ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/Daodan/MSVC/Flatline.c
(Generate patch)

Comparing Daodan/MSVC/Flatline.c (file contents):
Revision 579 by gumby, Thu Jan 13 01:02:52 2011 UTC vs.
Revision 580 by gumby, Fri Jan 14 07:39:14 2011 UTC

# Line 8 | Line 8
8   uint32_t last1 = 0; uint32_t last2 = 0;
9   player_info Players[MAX_PLAYERS] = {{0}, {0}, {0}, {0}};
10   player_info * PlayerList[MAX_CONNECTIONS] = {0};
11 +
12 + unsigned int lastPingTime;
13 +
14   const char * Rejection_Messages[][255] = {
15          {"Server is full"},
16          {"-2"},
# Line 23 | Line 26 | void DoRareSync( short Player, sockaddr_
26          flatline_packet sync = {0};    
27  
28          if (Player > max_connections || !PlayerList[ Player ] ) return;
29 <        
30 <                        
31 < //      DDrConsole_PrintF( "Sending sync data for player %i, new index %u", Player, PlayerList[ Player ]->rare_sync_index);
29 >
30 >
31 >        //      DDrConsole_PrintF( "Sending sync data for player %i, new index %u", Player, PlayerList[ Player ]->rare_sync_index);
32          sender->sin_addr.S_un.S_addr = htonl(sender->sin_addr.S_un.S_addr);
33          sync.id = RARE_SYNC_DATA;
34          sprintf( sync.rare_sync_data.Class, TMrInstance_GetInstanceName( PlayerList[ Player ]->Chr->ONCC ) );
# Line 50 | Line 53 | bool FLrServer_PacketCallback(char* data
53          sender.sin_family = AF_INET;
54          sender.sin_port = htons(27777);
55          sender.sin_addr = *((struct in_addr*)(int*)&from);
56 <        
56 >
57  
58          //packet->data[datalen] = '\0';
59 <        
59 >
60          //DDrConsole_PrintF("Packet \r%d recieved from %i",  ++recieved, from);
61  
62 <        
63 <        
62 >
63 >
64          //if data[0] != CONNECT_SEND, search in playerlist for ip address
62        
65  
66  
67 <        
67 >
68 >
69          switch(packet->id) {
70                  flatline_packet connect_recv;
71                  player_info * playah;
72                  //rewrite this when we get TCP support.
73                  //rewrite this before we get TCP support*
74                  //the way of seeing if there is room for players sucks.
75 <                case CONNECT_SEND:
76 <                        ;
74 <                        
75 <                        connect_recv.id = CONNECT_REPLY;
76 <                
77 <                        //if(Players[i].ip == sender.sin_addr.S_un.S_addr) break; //needs to send an error message
78 <                        sender.sin_addr.S_un.S_addr = htonl(sender.sin_addr.S_un.S_addr);
79 <                        playah = FLrServer_AddPlayer(from,packet->connect_send.name, 0, 0);
80 <                        DDrConsole_PrintF("%s connected from %s", packet->connect_send.name, inet_ntoa(sender.sin_addr ) );
81 <                        if(!((int)playah > -5 && (int)playah <= 0)) {
82 <                                flatline_packet new_char = {0};
83 <                                CharacterObject* Char;
84 <                                connect_recv.connect_reply.goodtogo = 1;
85 <                                connect_recv.connect_reply.player_slot = playah->list_slot;
86 <                                DDrConsole_PrintF("Slot: %i", playah->list_slot);
87 <
88 <                                //sending this several times to make sure it gets through. Really need to make up some form of packet tracking.
89 <                                NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
90 <                                NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
91 <                                NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
92 <                                NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
93 <                                NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
94 <                                Sleep(100);
95 <
96 <                                new_char.id = NEW_PLAYER;
97 <                                Char = &new_char.new_player.Character;
98 <                                memset(Char, 0, sizeof(CharacterObject));
99 <                                Char->Header.Type = 'CHAR';
100 <                                Char->OSD.Options = chr_dontaim;
101 <                                for(j = 0; j < max_connections; j++) {
102 <                                        if(PlayerList[j] != 0) {
103 <                                                new_char.new_player.Playernumber = j;
104 <                                                sprintf(Char->OSD.Name,"%s",PlayerList[j]->name);
75 >        case CONNECT_SEND:
76 >                ;
77  
78 <                                                sprintf(Char->OSD.Class, "%s", TMrInstance_GetInstanceName(PlayerList[j]->Chr->ONCC));
107 <                                                DDrConsole_PrintF("Class %s", Char->OSD.Class );
78 >                connect_recv.id = CONNECT_REPLY;
79  
80 <                                                sprintf(Char->OSD.Class, "konoko_generic");
81 <                                                NetTCPServer_Send((sockaddr *) &sender, (char*)&new_char, sizeof(new_player) + FLATLINE_HEADER );
82 <                                        }
80 >                //if(Players[i].ip == sender.sin_addr.S_un.S_addr) break; //needs to send an error message
81 >                sender.sin_addr.S_un.S_addr = htonl(sender.sin_addr.S_un.S_addr);
82 >                playah = FLrServer_AddPlayer(from,packet->connect_send.name, 0, 0);
83 >                DDrConsole_PrintF("%s connected from %s", packet->connect_send.name, inet_ntoa(sender.sin_addr ) );
84 >                if(!((int)playah > -5 && (int)playah <= 0)) {
85 >                        flatline_packet new_char = {0};
86 >                        CharacterObject* Char;
87 >                        connect_recv.connect_reply.goodtogo = 1;
88 >                        connect_recv.connect_reply.player_slot = playah->list_slot;
89 >                        DDrConsole_PrintF("Slot: %i", playah->list_slot);
90 >
91 >                        //sending this several times to make sure it gets through. Really need to make up some form of packet tracking.
92 >                        NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
93 >                        NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
94 >                        NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
95 >                        NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
96 >                        NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(connect_reply) + FLATLINE_HEADER);
97 >                        Sleep(100);
98 >
99 >                        new_char.id = NEW_PLAYER;
100 >                        Char = &new_char.new_player.Character;
101 >                        memset(Char, 0, sizeof(CharacterObject));
102 >                        Char->Header.Type = 'CHAR';
103 >                        Char->OSD.Options = chr_dontaim;
104 >                        for(j = 0; j < max_connections; j++) {
105 >                                if(PlayerList[j] != 0) {
106 >                                        new_char.new_player.Playernumber = j;
107 >                                        sprintf(Char->OSD.Name,"%s",PlayerList[j]->name);
108  
109 +                                        sprintf(Char->OSD.Class, "%s", TMrInstance_GetInstanceName(PlayerList[j]->Chr->ONCC));
110 +                                        DDrConsole_PrintF("Class %s", Char->OSD.Class );
111 +
112 +                                        sprintf(Char->OSD.Class, "konoko_generic");
113 +                                        NetTCPServer_Send((sockaddr *) &sender, (char*)&new_char, sizeof(new_player) + FLATLINE_HEADER );
114                                  }
115 +
116                          }
117 <                        else {
118 <                                //fix the error messages...
119 <                                DDrConsole_PrintF("Server is full. :(");
120 <                                connect_recv.connect_reply.goodtogo = 0;
121 <                                sender.sin_addr.S_un.S_addr = htonl(sender.sin_addr.S_un.S_addr);
122 <                                memcpy(&connect_recv.connect_reply.message,"Server is full.", sizeof("Server is full."));
123 <                                NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(bool)*2 + FLATLINE_HEADER + sizeof("Server is full."));    
117 >                }
118 >                else {
119 >                        //fix the error messages...
120 >                        DDrConsole_PrintF("Server is full. :(");
121 >                        connect_recv.connect_reply.goodtogo = 0;
122 >                        sender.sin_addr.S_un.S_addr = htonl(sender.sin_addr.S_un.S_addr);
123 >                        memcpy(&connect_recv.connect_reply.message,"Server is full.", sizeof("Server is full."));
124 >                        NetTCPServer_Send((sockaddr *) &sender, (char*)&connect_recv, sizeof(bool)*2 + FLATLINE_HEADER + sizeof("Server is full."));    
125  
126 <                        }
126 >                }
127  
128  
129 +                break;
130 +        case CONNECT_REPLY:
131 +                break;  //do nothing...a server shouldn't recieve this type of packet.
132 +        case MESSAGE:
133 +                for(i = 0; i < MAX_PLAYERS; i++) {
134 +                        //DDrConsole_PrintF("%i : %i | %s : %s", from, Players[i].ip, inet_ntoa(*(struct in_addr*)&from), inet_ntoa(*(struct in_addr*)&(Players[i].ip)));
135 +                        if(Players[i].ip == sender.sin_addr.S_un.S_addr) {
136 +                                found_player = 1;
137 +                                break;
138 +                        }      
139 +                }
140 +                if(found_player == 0) return true;
141 +                else {
142 +                        char message_buffer[512] = {0};
143 +                        flatline_packet message;
144 +                        int message_size;
145 +                        data[datalen] = 0;
146 +
147 +                        DDrConsole_PrintF("%s: %s", Players[i].name, packet->data);
148 +                        sprintf(message_buffer, "%s: %s", Players[i].name, packet->data);
149 +
150 +                        message.id = MESSAGE;
151 +                        message_size = sprintf(message.data, "%s", message_buffer);
152 +                        COrMessage_Print(message_buffer, "chat", 0);
153 +                        UDPServer_SendToAll(&message, message_size + 1 + FLATLINE_HEADER);
154                          break;
155 <                case CONNECT_REPLY:
156 <                        break;  //do nothing...a server shouldn't recieve this type of packet.
157 <                case MESSAGE:
158 <                        for(i = 0; i < MAX_PLAYERS; i++) {
159 <                                //DDrConsole_PrintF("%i : %i | %s : %s", from, Players[i].ip, inet_ntoa(*(struct in_addr*)&from), inet_ntoa(*(struct in_addr*)&(Players[i].ip)));
160 <                                if(Players[i].ip == sender.sin_addr.S_un.S_addr) {
161 <                                        found_player = 1;
134 <                                        break;
135 <                                }      
136 <                        }
137 <                        if(found_player == 0) return true;
138 <                        else {
139 <                                char message_buffer[512] = {0};
140 <                                flatline_packet message;
141 <                                int message_size;
142 <                                data[datalen] = 0;
143 <
144 <                                DDrConsole_PrintF("%s: %s", Players[i].name, packet->data);
145 <                                sprintf(message_buffer, "%s: %s", Players[i].name, packet->data);
146 <                                
147 <                                message.id = MESSAGE;
148 <                                message_size = sprintf(message.data, "%s", message_buffer);
149 <                                COrMessage_Print(message_buffer, "chat", 0);
150 <                                UDPServer_SendToAll(&message, message_size + 1 + FLATLINE_HEADER);
155 >                }
156 >        case CHANGE_NAME:
157 >                ; //wtf, needed or i get an error.
158 >                DDrConsole_PrintF("Changing Name to: %s", packet->data);
159 >                for(i = 0; i < MAX_PLAYERS; i++) {
160 >                        if(Players[i].ip == sender.sin_addr.S_un.S_addr) {
161 >                                found_player = 1;
162                                  break;
163 <                        }
164 <                case CHANGE_NAME:
165 <                        ; //wtf, needed or i get an error.
166 <                        DDrConsole_PrintF("Changing Name to: %s", packet->data);
167 <                        for(i = 0; i < MAX_PLAYERS; i++) {
168 <                                if(Players[i].ip == sender.sin_addr.S_un.S_addr) {
169 <                                        found_player = 1;
163 >                        }      
164 >                }
165 >                if(found_player == 0) return true;
166 >                else {
167 >                        bool name_exists = 0;
168 >                        for(j = 0; j < MAX_PLAYERS; j++) {
169 >                                if(!strcmp(packet->data, Players[j].name)) {
170 >                                        name_exists = 1;
171                                          break;
160                                }      
161                        }
162                        if(found_player == 0) return true;
163                        else {
164                                bool name_exists = 0;
165                                for(j = 0; j < MAX_PLAYERS; j++) {
166                                        if(!strcmp(packet->data, Players[j].name)) {
167                                                name_exists = 1;
168                                                break;
169                                        }
170                                }
171                                if(!name_exists) {
172                                        char message_buffer[1024];
173                                        sprintf(message_buffer,"%s changed their name to %s", Players[i].name, packet->data);
174                                        COrMessage_Print(message_buffer, "name_change", 0);
175                                        memcpy(Players[i].name, packet->data, 256);
176
172                                  }
178                                break;
173                          }
174 <                case PLAYER_INPUT:
175 <                        
176 <                        for(i = 0; i < max_connections; i++) {
177 <                                if(PlayerList[i] != 0 && PlayerList[i]->ip == sender.sin_addr.S_un.S_addr) {
178 <                                        found_player = 1;
179 <                                        break;
186 <                                }      
174 >                        if(!name_exists) {
175 >                                char message_buffer[1024];
176 >                                sprintf(message_buffer,"%s changed their name to %s", Players[i].name, packet->data);
177 >                                COrMessage_Print(message_buffer, "name_change", 0);
178 >                                memcpy(Players[i].name, packet->data, 256);
179 >
180                          }
181 <                        
182 <                        if(found_player == 0) return true;
183 <                        else {
191 <                                input_struct * packet_input = &packet->input_struct;
181 >                        break;
182 >                }
183 >        case PLAYER_INPUT:
184  
185 +                for(i = 0; i < max_connections; i++) {
186 +                        if(PlayerList[i] != 0 && PlayerList[i]->ip == sender.sin_addr.S_un.S_addr) {
187 +                                found_player = 1;
188 +                                break;
189 +                        }      
190 +                }
191  
192 <                                PlayerList[i]->Actions1 = packet_input->Actions1;
193 <                                PlayerList[i]->Actions2 = packet_input->Actions2;
194 <                                PlayerList[i]->MouseDeltaX = packet_input->MouseDeltaX;
195 <                                PlayerList[i]->MouseDeltaY = packet_input->MouseDeltaY;
196 <                                PlayerList[i]->LastInputTime = packet_input->Time;
192 >                if(found_player == 0) return true;
193 >                else {
194 >                        input_struct * packet_input = &packet->input_struct;
195 >
196 >
197 >                        PlayerList[i]->Actions1 = packet_input->Actions1;
198 >                        PlayerList[i]->Actions2 = packet_input->Actions2;
199 >                        PlayerList[i]->MouseDeltaX = packet_input->MouseDeltaX;
200 >                        PlayerList[i]->MouseDeltaY = packet_input->MouseDeltaY;
201 >                        PlayerList[i]->LastInputTime = packet_input->Time;
202  
200                                break;
201                        }
202                case RARE_SYNC_DATA_REQUEST:
203                        DoRareSync( packet->sync_request , &sender);
204                        break;
205                default:
206                        DDrConsole_PrintF("Warning, recieved badly formed packet!");
203                          break;
204 +                }
205 +        case RARE_SYNC_DATA_REQUEST:
206 +                DoRareSync( packet->sync_request , &sender);
207 +                break;
208 +        case PK_PONG:
209 +                                for(i = 0; i < max_connections; i++) {
210 +                        if(PlayerList[i] != 0 && PlayerList[i]->ip == sender.sin_addr.S_un.S_addr) {
211 +                                found_player = 1;
212 +                                break;
213 +                        }      
214 +                }
215 +
216 +                if(found_player == 0) return true;
217 +                if(packet->ping != lastPingTime)
218 +                {
219 +                        PlayerList[i]->Ping = 999;
220 +                }
221 +                else
222 +                {
223 +                        PlayerList[i]->Ping = (ONgGameState->GameTime - packet->ping) * 1000 / 60;
224 +                }
225 +                break;
226 +        default:
227 +                DDrConsole_PrintF("Warning, recieved badly formed packet!");
228 +                break;
229          }
230          return true;
231   }
# Line 213 | Line 234 | bool FLrServer_Run()
234   {
235          // Get the local hostname
236          char szHostName[255];
237 <                struct hostent *host_entry;
237 >        struct hostent *host_entry;
238          gethostname(szHostName, 255);
239  
240          host_entry=gethostbyname(szHostName);
# Line 227 | Line 248 | short TRrAnimation_GetType(char* anim)
248   }
249  
250   void ONrCharacter_SetAnimationInternal(Character* Char, ActiveCharacter* AChar,
251 <                                                                           short inFromState, short inNextAnimType, const void *TRAM)
251 >        short inFromState, short inNextAnimType, const void *TRAM)
252   {
253          ONCC            *ONCC   = Char->ONCC;
254          void            *TRAC   = ONCC->TRAC;
# Line 235 | Line 256 | void ONrCharacter_SetAnimationInternal(C
256          short animType;
257  
258          if (TRAM == 0) return;
259 <        
259 >
260          animType = TRrAnimation_GetType(TRAM);
261 <        
261 >
262          AChar->Animation = TRAM;
263          AChar->Frame = 0;
264          AChar->AnimationFromState = inFromState;
265          AChar->AnimationType = animType;
266 <        
266 >
267          AChar->NextAnimationType= inNextAnimType;
268          AChar->AnimationToState = TRrAnimation_GetTo(TRAM);
269  
# Line 250 | Line 271 | void ONrCharacter_SetAnimationInternal(C
271   }
272  
273  
274 <        RGBA green = {0, 0xFF, 0, 0};
275 <        RGBA red = {0, 0, 0xFF, 0};
276 <        RGBA grey = {0x80,0x80,0x80,0x80};
277 <        
274 > RGBA green = {0, 0xFF, 0, 0};
275 > RGBA red = {0, 0, 0xFF, 0};
276 > RGBA grey = {0x80,0x80,0x80,0x80};
277 >
278   //FLrClient_Run
279   //Looping function that waits for packets from the server.
280  
# Line 266 | Line 287 | bool FLrClient_Run(flatline_packet* pack
287          int j;
288          int sent_bytes;
289          client_connected = 0;
290 <        
290 >
291  
292          //starts the connection
293          DDrConsole_PrintF("Connecting to server %s on socket %i",  inet_ntoa(address.sin_addr), client_sock);
# Line 288 | Line 309 | bool FLrClient_Run(flatline_packet* pack
309                                          PlayerList[client_slot]->Chr = ONgGameState->PlayerCharacter;
310  
311                                          DDrConsole_PrintColored("Connection successful!",0,green, grey);
312 <                                        
312 >
313                                          //disable local input.
314                                          DDrPatch_NOOP(0x004FA929, 5 + 6 + 5);
315 <                                        
315 >
316                                          //DDrConsole_PrintF("Slot %i",  ((connect_reply*)packet)->player_slot);
317                                          break;
318                                  }
# Line 315 | Line 336 | bool FLrClient_Run(flatline_packet* pack
336          {
337                  ActiveCharacter * Active;
338                  flatline_packet packet;
339 < //#define SPAM_INPUT
339 >                //#define SPAM_INPUT
340   #ifdef SPAM_INPUT
341                  struct timeval lasttime;
342                  struct timeval thistime;
# Line 324 | Line 345 | bool FLrClient_Run(flatline_packet* pack
345                  while(1) {
346   #ifdef SPAM_INPUT
347                          gettimeofday(&thistime, 0);
348 <                        
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 <                                }
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();
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) );
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 <                        if( !server_started && pd->rare_sync_index > PlayerList[i]->rare_sync_index )
413 <                        {
414 <                                        int sent_bytes;
415 <                                        flatline_packet sync_request = {0};
416 <                                        sync_request.id = RARE_SYNC_DATA_REQUEST;
417 <                                        sync_request.sync_request = i;
418 <                                        DDrConsole_PrintF( "Requesting sync data for player %i, old index %u", i, PlayerList[i]->rare_sync_index);
419 <                                        sent_bytes = NetUDPSocket_Send(client_sock,(sockaddr *) &address, (char*)&sync_request, FLATLINE_HEADER + sizeof(int) );
420 <                        }
443 >                                                PlayerList[i]->DataApplied = 0;
444  
445  
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 <        
479 <                        break;
480 <                        }
481 <                case RARE_SYNC_DATA:
482 <                        if(1) {
483 <                        sl_arg hax[2];
484 <                        int dontuse;
485 <                        uint16_t i = packet.rare_sync_data.PlayerNum;
432 <                                                
433 <                        if (i > max_connections) break;
434 <                        if( !PlayerList[i] ) break;
435 <
436 <                        //WEAPONS ARE DISABLED. Why? Pain in the arse to sync.
437 <                        packet.rare_sync_data.Inventory.Weapons[0] = NULL;
438 <                        packet.rare_sync_data.Inventory.Weapons[1] = NULL;
439 <                        packet.rare_sync_data.Inventory.Weapons[2] = NULL;
440 < //                      TMrInstance_GetDataPtr( 'ONCC', packet.rare_sync_data.Class, PlayerList[ i ]->Chr->ONCC );
441 <                        
442 <                        //add the target character
443 <                        hax[0].type = sl_int32;
444 <                        hax[0].value_int32 = PlayerList[ packet.rare_sync_data.PlayerNum ]->spawnnumber;
445 <
446 <                        //add the new class
447 <                        //fix this later so we cant buffer overflow :O
448 <                        hax[1].type = sl_str32;
449 <                        hax[1].value_str32 = packet.rare_sync_data.Class;
450 <                        
451 <                        //we are directly calling a bsl function instead of using the normal method for two reasons
452 <                        //1. it has all the checking built in
453 <                        iSetCharacterClass( 0, 2, hax, &dontuse, &dontuse, hax );
454 <                        //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);
455 <                        memcpy( &(PlayerList[ i ]->Chr->Inventory), &(packet.rare_sync_data.Inventory), sizeof(Inventory ));
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  
487 <                        PlayerList[i]->rare_sync_index = packet.rare_sync_data.index;
488 <                        }
489 <                        break;
490 <                case FLATLINE_EVENT:
491 <                        FLcEventHandler( packet.flatline_event.event_index, packet.flatline_event.intArray );
462 <                        break;
463 <                default:
464 <                        DDrConsole_PrintF("Warning, recieved badly formed packet!");
465 <                        break;
487 >                                        NetUDPSocket_Send(client_sock, (sockaddr *) &address, (char*)&packet, FLATLINE_HEADER + 4);            
488 >                                        break;
489 >                                default:
490 >                                        DDrConsole_PrintF("Warning, recieved badly formed packet!");
491 >                                        break;
492                                  }
493                          }
494                          else {
# Line 494 | Line 520 | uint16_t FLr_FindEmptyListSlot() {
520          }
521          return -1;
522   }
523 <        typedef struct
524 <        {
525 <                uint16_t x;
526 <                uint16_t y;
527 <                
528 <        } IMtPoint2D;
523 > typedef struct
524 > {
525 >        uint16_t x;
526 >        uint16_t y;
527 >
528 > } IMtPoint2D;
529   static flatline_packet cache_input = {0};
530   extern void* TSrTest;
531   void * ONICALL FLrInput_Update_Keys(void)
# Line 521 | Line 547 | void * ONICALL FLrInput_Update_Keys(void
547                  input_packet.input_struct.Actions2 = ((GameState*)(ONgGameState))->Input.Current.Actions2;
548                  input_packet.input_struct.MouseDeltaX = ((GameState*)(ONgGameState))->Input.MouseDeltaX;
549                  input_packet.input_struct.MouseDeltaY = ((GameState*)(ONgGameState))->Input.MouseDeltaY;
550 <                
550 >
551                  sent_bytes = NetUDPSocket_Send(client_sock,(sockaddr *) &address, (char*)&input_packet, sizeof(input_struct) + FLATLINE_HEADER);
552 <                
552 >
553                  //return ONgGameState;
554          }
555  
556  
557          if(!(server_started || client_connected)) return ONgGameState;
558  
559 +        if(server_started && ONgGameState->GameTime % 120 == 0)
560 +        {
561 +                FLsPingAll();
562 +        }
563 +
564          for(i = 0; i < max_connections; i++) {
565                  ActiveCharacter * Active_Player;
566                  Character* Player;
567                  GameInput * Active_Input;
568                  if(PlayerList[i] == 0) continue;
569 <                
570 <                
569 >
570 >
571                  Player = PlayerList[i]->Chr;
572                  if( Player->Health == 0)
573                  {
# Line 574 | Line 605 | void * ONICALL FLrInput_Update_Keys(void
605                                  FLrPlayerRespawn( i );
606                          }
607                          continue;
608 <                                
609 <                        
608 >
609 >
610                  }
611  
612                  Active_Player = ONrGetActiveCharacter( PlayerList[i]->Chr);
613 <                
613 >
614                  if(Active_Player == 0) continue;
615                  Active_Input = &(Active_Player->Input);
616                  if(server_started) {
617                          player_data * data;
618                          flatline_packet data_out = {0};
619  
620 <                        
620 >                        if(!strcmp(PlayerList[i]->player_data.Animation, TMrInstance_GetInstanceName(Active_Player->Animation)))
621 >                                continue;
622  
623                          data_out.id = PLAYER_DATA;
624                          data = (void*)&(data_out.data);
# Line 599 | Line 631 | void * ONICALL FLrInput_Update_Keys(void
631                          data->Position = Active_Player->PhyContext->Position;
632                          memcpy(data->Animation, TMrInstance_GetInstanceName(Active_Player->Animation), 31);
633                          data->Frame = Active_Player->Frame;
634 <                        
634 >
635                          if(Active_Player->targetThrow)
636                          {
637                                  data->throw_data.throwing = Players[Active_Player->throwing].list_slot;
638                                  memcpy(data->throw_data.throwName, TMrInstance_GetInstanceName(Active_Player->targetThrow), 31);
639                                  data->throw_data.throwFrame = ONrGetActiveCharacter(Active_Player->targetThrow)->Frame;
640                          }
641 <                        
642 <                        
641 >
642 >
643                          if( PlayerList[i]->OldClass != PlayerList[i]->Chr->ONCC || memcmp( &(PlayerList[i]->Inventory), &(PlayerList[i]->Chr->Inventory), sizeof(Inventory) ) )
644                          {
645                                  PlayerList[i]->OldClass = PlayerList[i]->Chr->ONCC;
# Line 615 | Line 647 | void * ONICALL FLrInput_Update_Keys(void
647                                  PlayerList[i]->rare_sync_index++;
648  
649                          }
650 <                        
650 >
651                          data->rare_sync_index = PlayerList[i]->rare_sync_index;
652 <                        
652 >
653  
654                          if(i == 0) {
655                                  data->Inputs.Actions1 = ((GameState*)(ONgGameState))->Input.Current.Actions1;
# Line 631 | Line 663 | void * ONICALL FLrInput_Update_Keys(void
663                                  data->Inputs.MouseDeltaX = PlayerList[i]->MouseDeltaX;
664                                  data->Inputs.MouseDeltaY = PlayerList[i]->MouseDeltaY;
665                          }
666 +                        data->Ping = PlayerList[i]->Ping;
667                          memcpy( &(PlayerList[i]->player_data), data, sizeof(player_data) );
668 <                        
668 >
669                          UDPServer_SendToAll(&data_out, sizeof(player_data) + FLATLINE_HEADER);
670                  }
671 <                
671 >
672                  if( (server_started && i !=0)  || (!server_started/* && i != client_slot*/) )
673                  {
674                          Active_Input->Stop.Actions1 = ~PlayerList[i]->Actions1 & Active_Input->Current.Actions1;
675                          Active_Input->Stop.Actions2 = ~PlayerList[i]->Actions2 & Active_Input->Current.Actions2;
676                          Active_Input->Start.Actions1 = ~Active_Input->Current.Actions1 & PlayerList[i]->Actions1;
677                          Active_Input->Start.Actions2 = ~Active_Input->Current.Actions2 & PlayerList[i]->Actions2;
678 <                        
678 >
679                          Active_Input->Current.Actions1 = PlayerList[i]->Actions1;
680                          Active_Input->Current.Actions2 = PlayerList[i]->Actions2;
681                          Active_Input->Stopped.Actions1 = ~Active_Input->Current.Actions1;
# Line 655 | Line 688 | void * ONICALL FLrInput_Update_Keys(void
688                                  void* OldAnimation;
689                                  void* Animation;
690                                  player_data* pd = &PlayerList[i]->player_data;
691 +
692 +                                if(PlayerList[i]->DataApplied) continue;
693 +
694                                  Player->Health = PlayerList[i]->player_data.Health;
695                                  PlayerList[i]->Chr->MaxHealth = PlayerList[i]->player_data.MaxHealth;
696  
# Line 667 | Line 703 | void * ONICALL FLrInput_Update_Keys(void
703                                  PlayerList[i]->MouseDeltaY = PlayerList[i]->player_data.Inputs.MouseDeltaY;
704                                  Active_Player->PhyContext->Position = PlayerList[i]->player_data.Position;
705                                  OldAnimation = Active_Player->Animation;
706 <                                
706 >
707                                  if (!(Player->Flags & ONcCharacterFlag_BeingThrown) &&
708                                          (pd->Animation != 0))
709                                  {
710                                          // get a pointer to the animation
711 <                                        
712 <                                                TMrInstance_GetDataPtr(
711 >
712 >                                        TMrInstance_GetDataPtr(
713                                                  'TRAM',
714                                                  pd->Animation,
715                                                  &Animation);
716 <                                                if (Animation != OldAnimation)
716 >                                        if (Animation != OldAnimation)
717                                          {
718                                                  short   num_frames;
719                                                  bool    updateAnimation = true;
720  
721                                                  // if the character is dead, make sure this animation is appropriate for death
722 <                                /*
722 >                                                /*
723                                                  if (Player->Flags & ONcCharacterFlag_Dead)
724                                                  {
725 <                                                        short   curToState = TRrAnimation_GetTo(Active_Player->Animation);
726 <                                                        short   newToState = TRrAnimation_GetTo(animation);
725 >                                                short   curToState = TRrAnimation_GetTo(Active_Player->Animation);
726 >                                                short   newToState = TRrAnimation_GetTo(animation);
727  
728 <                                                        // if we are currently heading towards fallen and the new animation would not
729 <                                                        // then this is a better animation to run when we are dead
730 <                                                        if ((ONrAnimState_IsFallen(curToState)) &&
731 <                                                                (!ONrAnimState_IsFallen(newToState)))
732 <                                                        {
733 <                                                                updateAnimation = false;
734 <                                                        }
728 >                                                // if we are currently heading towards fallen and the new animation would not
729 >                                                // then this is a better animation to run when we are dead
730 >                                                if ((ONrAnimState_IsFallen(curToState)) &&
731 >                                                (!ONrAnimState_IsFallen(newToState)))
732 >                                                {
733 >                                                updateAnimation = false;
734 >                                                }
735                                                  }
736                                                  */
737                                                  if ((updateAnimation) && (Active_Player->Animation == Animation))
# Line 712 | Line 748 | void * ONICALL FLrInput_Update_Keys(void
748                                                  if (updateAnimation)
749                                                  {
750                                                          // set the characters animation
751 <                                        /*      ONrCharacter_SetAnimationInternal(Player,
752 <                                                                Active_Player,
753 <                                                                Active_Player->AnimationToState,
754 <                                                                0,
755 <                                                                Animation);
756 <                                                ONrCharacter_NewAnimationHook(Player, Active_Player);*/
757 <                                                //Player->Flags |= 0x00000010;
751 >                                                        /*      ONrCharacter_SetAnimationInternal(Player,
752 >                                                        Active_Player,
753 >                                                        Active_Player->AnimationToState,
754 >                                                        0,
755 >                                                        Animation);
756 >                                                        ONrCharacter_NewAnimationHook(Player, Active_Player);*/
757 >                                                        //Player->Flags |= 0x00000010;
758                                                          ONrCharacter_SetAnimationExternal(Player, TRrAnimation_GetFrom(Animation), Animation, 0);
759                                                  }
760  
# Line 738 | Line 774 | void * ONICALL FLrInput_Update_Keys(void
774  
775                                  if (PlayerList[i]->player_data.throw_data.throwName[0] != 0)
776                                  {
777 <                                        pd->throw_data.throwing = PlayerList[pd->throw_data.throwing]->spawnnumber;
778 <                                        if ((pd->throw_data.throwing != Active_Player->throwing) &&
777 >                                        short throwTarget = PlayerList[pd->throw_data.throwing]->spawnnumber;
778 >                                        if ((throwTarget != Active_Player->throwing) &&
779                                                  (pd->throw_data.throwFrame < 10))
780                                          {
781                                                  void    *throw_animation;
# Line 753 | Line 789 | void * ONICALL FLrInput_Update_Keys(void
789                                                  //if (error) return;
790  
791                                                  // set the throw target
792 <                                                Active_Player->ThrowTargetCharacter = &ONgGameState->CharacterStorage[pd->throw_data.throwing];
792 >                                                Active_Player->ThrowTargetCharacter = &ONgGameState->CharacterStorage[throwTarget];
793                                                  Target = ONrGetActiveCharacter(Active_Player->ThrowTargetCharacter);
794                                                  if ((Target->Animation != throw_animation) &&
795                                                          (OldAnimation != Animation) &&
# Line 761 | Line 797 | void * ONICALL FLrInput_Update_Keys(void
797                                                  {
798                                                          // set the throw variables
799                                                          Active_Player->targetThrow      = throw_animation;
800 <                                                        Active_Player->throwing         = pd->throw_data.throwing;
800 >                                                        Active_Player->throwing         = throwTarget;
801  
802                                                          // run the throw
803                                                          ONrCharacter_NewAnimationHook(Player, Active_Player);
804 <                                                        
804 >
805                                                          if (Active_Player->ThrowTargetCharacter)
806                                                          {
807                                                                  Target->Frame += 2;
# Line 774 | Line 810 | void * ONICALL FLrInput_Update_Keys(void
810                                                  }
811                                          }
812                                  }
813 +                                PlayerList[i]->DataApplied = 1;
814  
815                          }
816                  }
# Line 790 | Line 827 | void FLrPlayerDisconnect( int Player )
827          }
828          //Kill off the character in another function, please
829          //ONrCharacter_SetHitPoints(  PlayerList[Player]->Chr, 0);
830 <        
830 >
831          memset(PlayerList[Player], 0, sizeof(player_info));
832          PlayerList[Player] = 0;
833 <        
833 >
834  
835  
836          return;
# Line 831 | Line 868 | void FLrRun_Scores()
868                          TSrContext_DrawText(ScoreboardInstance, "Name", 255, 0, &DrawLocation);
869                          DrawLocation.x += 150;
870                          TSrContext_DrawText(ScoreboardInstance, "Score", 255, 0, &DrawLocation);
871 +                        DrawLocation.x += 50;
872 +                        TSrContext_DrawText(ScoreboardInstance, "Ping", 255, 0, &DrawLocation);
873                          for(i = 0; i <MAX_PLAYERS; i++)
874                          {
875 <                                if(PlayerList[i] == 0) continue;
875 >                                if(PlayerList[i] == 0 || PlayerList[i]->Chr == 0) continue;
876  
877                                  DrawLocation.x = 20;
878                                  DrawLocation.y += LineHeight;
879 <                                
880 <                                if(PlayerList[i]->Chr->Health == 0)
879 >
880 >                                if(PlayerList[i]->Chr && PlayerList[i]->Chr->Health == 0)
881                                  {
882                                          TSrContext_SetShade(ScoreboardInstance, red);
883                                  }
# Line 851 | Line 890 | void FLrRun_Scores()
890                                  DrawLocation.x += 150;
891                                  sprintf(DrawString, "%i", PlayerList[i]->Chr->Damage);
892                                  TSrContext_DrawText(ScoreboardInstance, DrawString, 255, 0, &DrawLocation);
893 <
893 >                                DrawLocation.x += 50;
894 >                                sprintf(DrawString, "%i", PlayerList[i]->player_data.Ping);
895 >                                TSrContext_DrawText(ScoreboardInstance, DrawString, 255, 0, &DrawLocation);
896                          }
897                  }
898          }

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)