#ifndef _ISPACKETS_H_ #define _ISPACKETS_H_ ///////////////////// // InSim System for Live for Speed : (Version : S2 ALPHA 0.5X) // InSim allows communication between an external program and LFS.exe. // UDP packets can be sent in either direction, LFS reporting various // things about its state, and the external program requesting info and // controlling LFS with special packets, text commands or keypresses. // NOTE : This text file was written with a TAB size equal to 4 spaces // INSIM VERSION NUMBER (updated for this 0.5X version) const int INSIM_VERSION = 4; // CHANGE LOG : // ============ // CHANGES W9 to W11 // ----------------- // The guaranteed delivery system has been removed. // Now you do not send an acknowledgment every time you receive a race tracking packet. // TCP packets are now available for most packets, while UDP is still supported. // The regular packets IS_NLP and IS_MCI are the only exceptionss - not sent via TCP. // To guarantee delivery over the internet, you must use the TCP method of connection. // UDP can be reliable on LAN and provides an easier upgrade path to the new system. // As TCP is a continuous stream rather than separate packets, every packet now starts // with a size byte, which you must compare with the read data stored in a buffer, to // know if you have a complete packet to process. // All packet headers (except NLP and MCI) have changed from the old four character // header, to a new style of header suitable for TCP. The first four bytes of all // packets now follow a common pattern. // Size - total packet size // Type - packet identification byte from the ISP_ enumeration - see below // ReqI - request id specified by an InSim program and returned in a requested packet // Xxxx - different in each case, often zero in the case of converted packets // All sizes are a multiple of 4 bytes. Two examples of smallest possible packets : // e.g. 1 : An IS_TINY packet equivalent to the old IS_REN (Race ENd) packet // Size : 4 // Type : 3 // from ISP_ enum : ISP_TINY (a general 4 byte packet) // ReqI : 0 // not a requested packet // SubT : 9 // from TINY_ enum : TINY_REN // e.g. 2 : The new IS_PLP packet // Size : 4 // Type : 21 // from ISP_ enum : ISP_PLP // ReqI : 0 // not a requested packet (this is sent when a player pits, not on request) // PLID : 8 // an example unique id (it would be the unique id of the player who pitted) // STEP BY STEP CHANGES for existing InSim software // ------------------------------------------------- // You may wish to upgrade your existing software in this order // UDP is still supported so it could be easier to change to the new packets in UDP // then finally switch over to TCP if you will be using your InSim program remotely // Guaranteed delivery system has been removed // VerifyID has been removed from all packets // Most "InSimPack" packets now use the new IS_TINY // Some "InSimPack" packets now use the new IS_SMALL // All packet headers have changed to the new style (Size, Type, ReqI, Xxxx) // Connections now have a unique identifier, called UCID, assigned in the IS_NCN packet // Any mention of "Conn" or "ConnNum" is removed - use UCID from now on // Player's unique identifier "UniqueId" is renamed to PLID // Any mention of "PlyNum" is removed - should already be using the unique id // MSS (message out split) packet has been removed - use MSO instead // MSO (message out) has new info added to take the place of MSS // NPL (new player) has been rearranged a bit // LAP packet has been reduced and rearranged // FIN and RES are now two separate packets // CHANGES W to W9 (search : NEW_W9) // --------------------------------- // changed packets (size not changed) : // IS_NPL : Handicap and passenger info added // IS_PEN : Penalty reason byte added // IS_FLG : Added unique id of obstructed player // Player flags : Added SHIFTER, AXIS_CLUTCH, CUSTOM_VIEW // new packets : // IS_CCH : sent when a player's selected camera changes // IS_III : info /i message sent by user to host's InSim // CHANGES V to W // -------------- // VERSION : InSim version increased to 3 // changed packets (size not changed) : // IS_RST - Added race flags (MUST_PIT, etc) // IS_NPL - CName now 4 chars + added skin name and tyre compounds // IS_LAP - CName now 4 chars + added number of laps / flags / penalty / stops // IS_RES - New FIN version of this is sent immediately on finishing race // new packets : // IS_PIT (pit stop) // IS_PSF (pit stop finished) // IS_PEN (penalty) // IS_TOC (take over car) // IS_FLG (yellow or blue flags) // IS_PFL (player help flags) // TYPES : (all multi-byte types are PC style - lowest byte first) // ===== // char 1-byte character // byte 1-byte unsigned integer // word 2-byte unsigned integer // short 2-byte signed integer // unsigned 4-byte unsigned integer // int 4-byte signed integerz // float 4-byte float // MSHT 4-byte minutes, seconds, hundredths, thousandths struct MSHT { byte M; // minutes byte S; // seconds byte H; // hundredths byte T; // thousandths }; // RaceLaps (rl) : (various meanings depending on range) // 0 : practice // 1-99 : number of laps... laps = rl // 100-190 : 100 to 1000 laps... laps = (rl - 100) * 10 + 100 // 191-238 : 1 to 48 hours... hours = rl - 190 // INITIALISING InSim // ================== // To initialise the InSim system, type into LFS : /insim xxxxx // where xxxxx is the UDP port you want LFS to open. // OR start LFS with the command line option : LFS /insim=xxxxx // This will make LFS listen for packets on that UDP port. // TO START COMMUNICATION : send this UDP packet to LFS // ====================== struct IS_ISI // InSim Init - packet to initialise the InSim system { byte Size; // 24 byte Type; // ISP_ISI byte ReqI; // 0 byte Zero; word Port; // Port for UDP replies from LFS (1...65535) byte Flags; // Bit flags for options (see below) byte NodeSecs; // Number of seconds between NLP or MCI (0 = none) char Admin [16]; // Admin password (if set in LFS) }; // If Port is zero, LFS will send replies back to the port of the incoming packet // Flags in InSimInit packet (set the relevant bits to turn on the option) : #define ISF_RACE_TRACKING 1 // bit 0 : turns on race tracking #define ISF_RESERVED_1 2 // bit 1 : spare #define ISF_RESERVED_2 4 // bit 2 : spare #define ISF_NO_WARNINGS 8 // bit 3 : turns off packet warnings #define ISF_KEEP_ALIVE 16 // bit 4 : send keep alive packets #define ISF_NLP_MCI 32 // bit 5 : send MCI instead of NLP // Now you can send packets to control LFS remotely, and LFS will send packets to you // ENUMERATIONS FOR PACKET TYPES // ============================= enum // the second byte in all packets is one of these { ISP_NONE, // 0 : not used ISP_ISI, // 1 - instruction : insim initialise ISP_VER, // 2 - info : version info ISP_TINY, // 3 - both ways : multi purpose ISP_SMALL, // 4 - both ways : multi purpose ISP_STA, // 5 - info : state info ISP_SCH, // 6 - instruction : single character ISP_SFP, // 7 - instruction : state flags pack ISP_SCC, // 8 - instruction : set car camera ISP_CPP, // 9 - both ways : cam pos pack ISP_ISM, // 10 - info : start multiplayer ISP_MSO, // 11 - info : message out ISP_III, // 12 - info : hidden /i message ISP_MST, // 13 - instruction : type message or /command ISP_MTC, // 14 - instruction : message to a connection ISP_MOD, // 15 - instruction : set screen mode ISP_VTN, // 16 - info : vote notification ISP_RST, // 17 - info : new connection ISP_NCN, // 18 - info : new connection ISP_CNL, // 19 - info : connection left ISP_CPR, // 20 - info : connection renamed ISP_NPL, // 21 - info : new player (joined race) ISP_PLP, // 22 - info : player pit (keeps slot in race) ISP_PLL, // 23 - info : player leave (spectate - loses slot) ISP_LAP, // 24 - info : lap time ISP_SPX, // 25 - info : split x time ISP_PIT, // 26 - info : pit stop start ISP_PSF, // 27 - info : pit stop finish ISP_PLA, // 28 - info : pit lane enter / leave ISP_CCH, // 29 - info : camera changed ISP_PEN, // 30 - info : penalty given or cleared ISP_TOC, // 31 - info : take over car ISP_FLG, // 32 - info : flag (yellow or blue) ISP_PFL, // 33 - info : player flags (help flags) ISP_FIN, // 34 - info : finished race ISP_RES, // 35 - info : result confirmed ISP_REO, // 36 - info : result confirmed ISP_NLP, // 36 - info : node and lap packet ISP_MCI, // 36 - info : multi car info }; enum // the fourth byte of IS_TINY packets is one of these { TINY_NONE, // 0 : used in ISF_KEEP_ALIVE TINY_VER, // 1 - info request : get version TINY_CLOSE, // 2 - instruction : close insim TINY_PING, // 3 - ping request : external progam requesting a reply TINY_REPLY, // 4 - ping reply : reply to a ping request TINY_VTC, // 5 - info : vote cancelled TINY_SCP, // 6 - info request : send camera pos TINY_SST, // 7 - info request : send state info TINY_GTH, // 8 - info request : get time in hundredths (i.e. SMALL_RTP) TINY_MPE, // 9 - info : multi player end TINY_ISM, // 10 - info request : get multiplayer info (i.e. ISP_ISM) TINY_REN, // 11 - info : race end (return to game setup screen) TINY_CLR, // 12 - info : all players cleared from race TINY_NCN, // 13 - info : get all connections TINY_NPL, // 14 - info : get all players TINY_RES, // 15 - info : get all results TINY_NLP, // 16 - info request : send an NLP packet TINY_MCI, // 17 - info request : send an MCI packet }; enum // the fourth byte of IS_SMALL packets is one of these { SMALL_NONE, // 0 : not used SMALL_SSP, // 1 - instruction : start sending positions SMALL_SSG, // 2 - instruction : start sending gauges SMALL_VTA, // 3 - report : vote action SMALL_TMS, // 4 - instruction : time stop SMALL_STP, // 5 - instruction : time step SMALL_RTP, // 6 - info : race time packet (reply to GTH) SMALL_NLI, // 7 - instruction : set node lap interval }; // General purpose packets IS_TINY (4 bytes) and IS_SMALL (8 bytes) // To avoid defining several packet structures that are exactly the same, and to avoid // wasting the ISP_ enumeration, IS_TINY is used at various times when no additional data // other than SubT is required. IS_SMALL is used when an additional integer is needed. // IS_TINY - used for various requests, replies and reports struct IS_TINY // General purpose 4 byte packet { byte Size; // always 4 byte Type; // always ISP_TINY byte ReqI; // 0 unless it is an info request or a reply to an info request byte SubT; // subtype, from TINY_ enumeration (e.g. TINY_RACE_END) }; // IS_SMALL - used for various requests, replies and reports struct IS_SMALL // General purpose 8 byte packet { byte Size; // always 8 byte Type; // always ISP_SMALL byte ReqI; // 0 unless it is an info request or a reply to an info request byte SubT; // subtype, from SMALL_ enumeration (e.g. SMALL_SSP) unsigned UVal; // value (e.g. for SMALL_SSP this would be the OutSim packet rate) }; // VERSION REQUEST // =============== // It is advisable to request version information as soon as you have connected, to // avoid problems when connecting to a host with a later or earlier version. // This version packet can be sent on request : struct IS_VER // VERsion { byte Size; // 20 byte Type; // ISP_VERSION byte ReqI; // ReqI as received in the request packet byte Zero; char Version [8]; // LFS version, e.g. 0.3G char Product [6]; // Product : DEMO or S1 word InSimVer; // InSim Version : increased when InSim packets change }; // To request an InSimVersion packet, send this IS_TINY : // ReqI : non-zero (if using a relay, use the ReqI provided by the relay system) // SubT : TINY_VER // CLOSING InSim // ============= // You can send this IS_TINY to return InSim to waiting / initialised / listening : // ReqI : 0 // SubT : TINY_CLOSE // Another InSimInit packet is then required to start operating again. // You can shut down InSim completely and stop it listening at all by typing /insim=0 // into LFS (or send a MsgTypePack to do the same thing). // MAINTAINING the connection - IMPORTANT // ========================== // If InSim does not receive a packet for 2 minutes, it will close the connection and // return to its original waiting / initialised state. // To open it again you would need to send another InSimInit packet. // To avoid InSim closing in this way, you need to send a packet every 20 - 30 seconds. // If you haven't sent any other packets for a while, send this blank IS_TINY : // ReqI : 0 // SubT : TINY_NONE (has no effect other than resetting the timeout) // Note 1 : If you set the ISF_KEEP_ALIVE option in the InSimInit packet, then LFS will // send a blank IS_TINY packet whenever it has not sent anything for 20 seconds. // You can simply reply to this with a blank IS_TINY, to maintain the connection. // If you don't receive anything for 2 minutes you can assume that you have lost the // connection for some reason. // Note 2 : If you want to request a reply from LFS to check the connection // at any time, you can send this IS_TINY : // ReqI : non-zero (if using a relay, use the ReqI provided by the relay system) // SubT : TINY_PING (request a reply) // LFS will reply with this IS_TINY : // ReqI : non-zero (as received in the request packet) // SubT : SMALL_REPLY (reply to ping) // STATE REPORTING AND REQUESTS // ============================ // LFS will send a StatePack any time the info in the StatePack changes. struct IS_STA // STAte { byte Size; // 28 byte Type; // ISP_STA byte ReqI; // ReqI if replying to a request packet byte Zero; float ReplaySpeed; // 4-byte float - 1.0 is normal speed word Flags; // ISS state flags (see below) byte InGameCam; // Which type of camera is selected (see below) byte ViewPlayer; // Player index of viewed car byte NumPlayers; // Number of players in race byte NumConns; // Number of connections including host byte NumFinished; // Number finished or qualified byte RaceInProgress; // 0 - no / 1 - race / 2 - qualifying byte QualMins; byte RaceLaps; // see "RaceLaps" near the top of this document byte Spare2; byte Spare3; char Track [6]; // short name for track e.g. FE2R byte Weather; // 0,1,2... byte Wind; // 0=off 1=weak 2=strong }; // InGameCam is the in-game selected camera mode (which is // still selected even if LFS is actually in SHIFT+U mode). // For InGameCam's values, see "View identifiers" below. // ISS state flags #define ISS_GAME 1 // in game (or MPR) #define ISS_REPLAY 2 // in SPR #define ISS_PAUSED 4 // paused #define ISS_SHIFTU 8 // in SHIFT+U mode #define ISS_SHIFTU_HIGH 16 // HIGH view #define ISS_SHIFTU_FOLLOW 32 // following car #define ISS_SHIFTU_NO_OPT 64 // buttons are hidden #define ISS_SHOW_2D 128 // showing 2d display #define ISS_FRONT_END 256 // in front end screen #define ISS_MULTI 512 // multiplayer mode #define ISS_MPSPEEDUP 1024 // multiplayer speedup option #define ISS_WINDOWED 2048 // lfs is running in a window #define ISS_SOUND_MUTE 4096 // sound is switched off #define ISS_VIEW_OVERRIDE 8192 // override user view // To request a StatePack at any time, send this IS_TINY : // ReqI : non-zero (if using a relay, use the ReqI provided by the relay system) // SubT : TINY_SST (Send STate) // Setting states // These states can be set by a special packet : // ISS_SHIFTU_FOLLOW - following car // ISS_SHIFTU_NO_OPT - buttons are hidden // ISS_SHOW_2D - showing 2d display // ISS_MPSPEEDUP - multiplayer speedup option // ISS_SOUND_MUTE - sound is mute struct IS_SFP // State Flags Pack { byte Size; // 8 byte Type; // ISP_SFP byte ReqI; // 0 byte Zero; word Flag; // the state to set byte OffOn; // 0 = off / 1 = on byte Sp3; // spare }; // Other states must be set by using keypresses or messages (see below) // SCREEN MODE // =========== // You can send this packet to LFS to set the screen mode : struct IS_MOD // MODe : send to LFS to change screen mode { byte Size; // 20 byte Type; // ISP_MOD byte ReqI; // 0 byte Zero; int Bits16; // set to choose 16-bit int RR; // refresh rate - zero for default int Width; // 0 means go to window int Height; // 0 means go to window }; // The refresh rate actually selected by LFS will be the highest available rate // that is less than or equal to the specified refresh rate. Refresh rate can // be specified as zero in which case the default refresh rate will be used. // If Width and Height are both zero, LFS will switch to windowed mode. // TEXT MESSAGES AND KEY PRESSES // ============================== // You can send 64-byte text messages to LFS as if the user had typed them in. // Messages that appear on LFS screen (up to 128 bytes) are reported to the // external program. You can also send simulated keypresses to LFS. // MESSAGES OUT (FROM LFS) // ------------ struct IS_MSO // MSg Out : system messages and user messages { byte Size; // 136 byte Type; // ISP_MSO byte ReqI; // 0 byte Zero; byte UCID; // connection's unique id (0 = host) byte PLID; // player's unique id (if zero, use UCID) byte User; // set if typed by a user byte TextStart; // actual text starts here (after player name) char Msg [128]; }; struct IS_III // InsIm Info : 64 chars - /i message from user to host's InSim ... NEW_W9 { byte Size; // 72 byte Type; // ISP_MSO byte ReqI; // 0 byte Zero; byte UCID; // connection's unique id (0 = host) byte PLID; // player's unique id (if zero, use UCID) byte Sp2; byte Sp3; char Msg [64]; }; // Note : The /mso command - Typing "/mso MESSAGE" into LFS will send a MSO packet. // MESSAGES IN (TO LFS) // ----------- struct IS_MST // MSg Type : 64 chars - send to LFS to type message or command { byte Size; // 68 byte Type; // ISP_MST byte ReqI; // 0 byte Zero; char Msg [64]; }; struct IS_MTC // Message To Connection : 64 chars - send to a connection or a player { byte Size; // 72 byte Type; // ISP_MTC byte ReqI; // 0 byte Zero; byte UCID; // connection's unique id (0 = host) byte PLID; // player's unique id (if zero, use UCID) byte Sp2; byte Sp3; char Msg [64]; }; struct IS_SCH // Single CHaracter - send to simulate single character { byte Size; // 8 byte Type; // ISP_SCH byte ReqI; // 0 byte Zero; byte CharB; // key to press byte Flags; // bit 0 : SHIFT / bit 1 : CTRL byte Spare2; byte Spare3; }; // MULTIPLAYER NOTIFICATION // ======================== // LFS will send this packet when a host is started or joined : struct IS_ISM // InSim Multi { byte Size; // 8 byte Type; // ISP_ISM byte ReqI; // usually 0 / or if a reply : ReqI as received in the TINY_ISM byte Zero; byte Host; // 0 = guest / 1 = host byte Sp1; byte Sp2; byte Sp3; char Name [32]; // the name of the host joined or started }; // On ending or leaving a host, LFS will send this IS_TINY : // ReqI : 0 // SubT : TINY_MPE (MultiPlayerEnd) // To request an IS_ISM packet at any time, send this IS_TINY : // ReqI : non-zero (if using a relay, use the ReqI provided by the relay system) // SubT : TINY_ISM // Note : If LFS is not in multiplayer mode, the host name in the ISM will be empty. // VOTE NOTIFY AND CANCEL // ====================== // LFS notifies the external program of any votes to restart or qualify // The Vote Actions are defined as : enum { VOTE_NONE, // 0 - no vote VOTE_END, // 1 - end race VOTE_RESTART, // 2 - restart VOTE_QUALIFY, // 3 - qualify VOTE_NUM }; struct IS_VTN // VoTe Notify { byte Size; // 8 byte Type; // ISP_VTN byte ReqI; // 0 byte Zero; byte UCID; // connection's unique id byte Action; // VOTE_X (Vote Action as defined above) byte Spare2; byte Spare3; }; // When a vote is cancelled, LFS sends this IS_TINY // ReqI : 0 // SubT : TINY_VTC (VoTe Cancelled) // When a vote is completed, LFS sends this IS_SMALL // ReqI : 0 // SubT : SMALL_VTA (VoTe Action) // UVal : action (VOTE_X - Vote Action as defined above) // You can instruct LFS host to cancel a vote using an IS_TINY // ReqI : 0 // SubT : TINY_VTC (VoTe Cancel) // RACE TRACKING // ============= // Packets sent if InSim was initialised with the ISF_RACE_TRACKING flag set // In LFS there are is a list of connections AND a list of players in the race // Some packets are related to connections, some players, some both // If you are making a multiplayer InSim program, you must maintain two lists // You should use the unique identifier UCID to identify the a connection // Each player has a unique identifier PLID from the moment he joins the race, until he // leaves. It's not possible for PLID and UCID to be the same thing, for two reasons : // 1) there may be more than one player per connection if AI drivers are used // 2) a player can swap between connections, in the case of a driver swap (IS_TOC) // When all players are cleared from race (e.g. /clear) LFS sends this IS_TINY // ReqI : 0 // SubT : TINY_CLR (CLear Race) // When a race ends (return to game setup screen) LFS sends this IS_TINY // ReqI : 0 // SubT : TINY_REN (Race ENd) // You can instruct LFS host to cancel a vote using an IS_TINY // ReqI : 0 // SubT : TINY_VTC (VoTe Cancel) struct IS_RST // Race STart { byte Size; // 20 byte Type; // ISP_RST byte ReqI; // 0 byte Zero; byte RaceLaps; // 0 if qualifying byte QualMins; // 0 if race byte NumInRace; byte Spare; char Track [6]; byte Weather; byte Wind; word Flags; byte Sp2; byte Sp3; }; struct IS_NCN // New ConN { byte Size; // 56 byte Type; // ISP_NCN byte ReqI; // 0 unless this is a reply to an info request byte UCID; // new connection's unique id (0 = host) char UName [24]; // username char PName [24]; // nickname byte Admin; // admin byte Total; // total now on host, including host byte Sp2; byte Sp3; }; struct IS_CNL // ConN Leave { byte Size; // 8 byte Type; // ISP_CNL byte ReqI; // 0 byte UCID; // unique id of the connection which left byte Sp0; // unique id of the connection which left byte Total; // total now on host, including host byte Sp2; byte Sp3; }; struct IS_CPR // Conn Player Rename { byte Size; // 36 byte Type; // ISP_CPR byte ReqI; // 0 byte UCID; // unique id of the connection char PName [24]; // new name char Plate [8]; // number plate - NO ZERO AT END! }; struct IS_NPL // New PLayer joining race (if PLID already exists, then leaving pits) { byte Size; // 76 byte Type; // ISP_NPL byte ReqI; // 0 unless this is a reply to an info request byte PLID; // player's newly assigned unique id byte UCID; // connection's unique id byte PType; // bit 0 - female / bit 1 - AI word Flags; // player flags char PName [24]; // nickname char Plate [8]; // number plate - NO ZERO AT END! char CName [4]; // car name char SName [16]; // skin name - MAX_CAR_TEX_NAME byte Tyres [4]; // compounds byte H_Mass; // added mass (kg) ... NEW_W9 byte H_TRes; // intake restriction ... NEW_W9 byte SpB; byte Passengers; // passengers byte ... NEW_W9 int Spare; byte Sp0; byte Total; // number in race (same when leaving pits, 1 more if new) byte Sp2; byte Sp3; }; struct IS_PLP // PLayer Pits (go to settings - stays in player list) { byte Size; // 4 byte Type; // ISP_PLP byte ReqI; // 0 byte PLID; // player's unique id }; struct IS_PLL // PLayer Leave race (spectate - removed from player list) { byte Size; // 4 byte Type; // ISP_PLL byte ReqI; // 0 byte PLID; // player's unique id }; struct IS_LAP // LAP time { byte Size; // 16 byte Type; // ISP_LAP byte ReqI; // 0 byte PLID; // player's unique id MSHT Time; // lap time word LapsDone; // laps completed word Flags; // player flags byte Sp0; byte Penalty; // current penalty value (see below) byte NumStops; // number of pit stops byte Sp3; }; struct IS_SPX // SPlit X time { byte Size; // 12 byte Type; // ISP_SPX byte ReqI; // 0 byte PLID; // player's unique id MSHT Time; // split time byte Split; // split number 1, 2, 3 byte Penalty; // current penalty value (see below) byte NumStops; // number of pit stops byte Sp3; }; struct IS_PIT // PIT stop (stop at pit garage) { byte Size; // 24 byte Type; // ISP_PIT byte ReqI; // 0 byte PLID; // player's unique id word LapsDone; // laps completed word Flags; // player flags byte Sp0; byte Penalty; // current penalty value (see below) byte NumStops; // number of pit stops byte Sp3; byte Tyres [4]; // tyres changed unsigned Work; // pit work unsigned Spare; }; struct IS_PSF // Pit Stop Finished { byte Size; // 12 byte Type; // ISP_PSF byte ReqI; // 0 byte PLID; // player's unique id MSHT Time; // stop time unsigned Spare; }; struct IS_PLA // Pit LAne { byte Size; // 8 byte Type; // ISP_PLA byte ReqI; // 0 byte PLID; // player's unique id byte Fact; // pit lane fact (see below) byte Sp1; byte Sp2; byte Sp3; }; // NOTE : To track cameras you need to consider 3 points // 1) The default camera : VIEW_DRIVER // 2) Player flags : CUSTOM_VIEW means VIEW_CUSTOM at start or pit exit // 3) IS_CCH : sent when an existing driver changes camera struct IS_CCH // Camera CHange ... NEW_W9 { byte Size; // 8 byte Type; // ISP_CCH byte ReqI; // 0 byte PLID; // player's unique id byte Camera; // view identifier (see below) byte Sp1; byte Sp2; byte Sp3; }; struct IS_PEN // PENalty (given or cleared) { byte Size; // 8 byte Type; // ISP_PEN byte ReqI; // 0 byte PLID; // player's unique id byte OldPen; // old penalty value (see below) byte NewPen; // new penalty value (see below) byte Reason; // penalty reason (see below) ... NEW_W9 byte Sp3; }; struct IS_TOC // Take Over Car { byte Size; // 8 byte Type; // ISP_TOC byte ReqI; // 0 byte PLID; // player's unique id byte OldUCID; // old connection's unique id byte NewUCID; // new connection's unique id byte Sp2; byte Sp3; }; struct IS_FLG // FLaG (yellow or blue flag changed) { byte Size; // 8 byte Type; // ISP_FLG byte ReqI; // 0 byte PLID; // player's unique id byte OffOn; // 0 = off / 1 = on byte Flag; // 1 = given blue / 2 = causing yellow byte CarBehind; // unique id of obstructed player byte Sp3; }; struct IS_PFL // Player FLags (help flags changed) { byte Size; // 8 byte Type; // ISP_PFL byte ReqI; // 0 byte PLID; // player's unique id word Flags; // player flags (see below) word Spare; }; struct IS_FIN // FINished race notification (not a final result - use IS_RES) { byte Size; // 20 byte Type; // ISP_FIN byte ReqI; // 0 byte PLID; // player's unique id (0 = player left before result was sent) MSHT TotalTime; // race time MSHT BestLap; // best lap byte Hours; // total hours (when TotalTime >= 1 hour) byte NumStops; // number of pit stops byte ConfirmFlags; // confirmation flags : disqualified etc - see below byte SpB; word LapsDone; // laps completed word Flags; // player flags : help settings etc - see below }; struct IS_RES // RESult (qualify or confirmed finish) { byte Size; // 84 byte Type; // ISP_PFL byte ReqI; // 0 byte PLID; // player's unique id (0 = player left before result was sent) char UName [24]; // username char PName [24]; // nickname char Plate [8]; // number plate - NO ZERO AT END! char CName [4]; // skin prefix MSHT TotalTime; // race time MSHT BestLap; // best lap byte Hours; // total hours (when TotalTime >= 1 hour) byte NumStops; // number of pit stops byte ConfirmFlags; // confirmation flags : disqualified etc - see below byte SpB; word LapsDone; // laps completed word Flags; // player flags : help settings etc - see below byte ResultNum; // finish or qualifying position (255 = not added to qualifying table) byte NumResults; // total number of results (qualify doesn't always add a new one) byte Sp2; byte Sp3; }; struct IS_REO // REOrder (when race restarts after qualifying) { byte Size; // 32 byte Type; // ISP_REO byte ReqI; // 0 byte NumPlayers; // number of players in race byte PLID [28]; // all PLIDs in new order }; // Pit Lane Facts enum { PITLANE_EXIT, // 0 - left pit lane PITLANE_ENTER, // 1 - entered pit lane PITLANE_NO_PURPOSE, // 2 - entered for no purpose PITLANE_DT, // 3 - entered for drive-through PITLANE_SG, // 4 - entered for stop-go PITLANE_NUM }; // Pit Work Flags enum { PSE_NOTHING, // bit 0 (1) PSE_STOP, // bit 1 (2) PSE_FR_DAM, // bit 2 (4) PSE_FR_WHL, // etc... PSE_LE_FR_DAM, PSE_LE_FR_WHL, PSE_RI_FR_DAM, PSE_RI_FR_WHL, PSE_RE_DAM, PSE_RE_WHL, PSE_LE_RE_DAM, PSE_LE_RE_WHL, PSE_RI_RE_DAM, PSE_RI_RE_WHL, PSE_BODY_MINOR, PSE_BODY_MAJOR, PSE_SETUP, PSE_REFUEL, }; // View identifiers enum { VIEW_FOLLOW, // 0 - arcade VIEW_HELI, // 1 - helicopter VIEW_CAM, // 2 - tv camera VIEW_DRIVER, // 3 - cockpit VIEW_CUSTOM, // 4 - custom VIEW_MAX }; const int VIEW_ANOTHER = 255; // viewing another car // Penalty values (VALID means the penalty can now be cleared) enum { PENALTY_NONE, // 0 PENALTY_DT, // 1 PENALTY_DT_VALID, // 2 PENALTY_SG, // 3 PENALTY_SG_VALID, // 4 PENALTY_30, // 5 PENALTY_45, // 6 PENALTY_NUM }; // Penalty reasons enum { PENR_UNKNOWN, // 0 - unknown or cleared penalty PENR_ADMIN, // 1 - penalty given by admin PENR_WRONG_WAY, // 2 - wrong way driving PENR_FALSE_START, // 3 - starting before green light PENR_SPEEDING, // 4 - speeding in pit lane PENR_STOP_SHORT, // 5 - stop-go pit stop too short PENR_STOP_LATE, // 6 - compulsory stop is too late PENR_NUM }; // Player flags ... NEW_W9 #define PIF_SWAPSIDE 1 #define PIF_GC_CUT 2 #define PIF_GC_BLIP 4 #define PIF_AUTOGEARS 8 #define PIF_SHIFTER 16 #define PIF_RESERVED 32 #define PIF_HELP_B 64 #define PIF_AXIS_CLUTCH 128 #define PIF_INPITS 256 #define PIF_AUTOCLUTCH 512 #define PIF_MOUSE 1024 #define PIF_KB_NO_HELP 2048 #define PIF_KB_STABILISED 4096 #define PIF_CUSTOM_VIEW 8192 // Tyre compounds (4 byte order : rear L, rear R, front L, front R) enum { TYRE_R1, // 0 TYRE_R2, // 1 TYRE_R3, // 2 TYRE_R4, // 3 TYRE_ROAD_SUPER, // 4 TYRE_ROAD_NORMAL, // 5 TYRE_HYBRID, // 6 TYRE_KNOBBLY, // 7 TYRE_NUM }; const int NOT_CHANGED = 255; // Confirmation flags #define CONF_MENTIONED 1 #define CONF_CONFIRMED 2 #define CONF_PENALTY_DT 4 #define CONF_PENALTY_SG 8 #define CONF_PENALTY_30 16 #define CONF_PENALTY_45 32 #define CONF_DID_NOT_PIT 64 #define CONF_DISQ (CONF_PENALTY_DT | CONF_PENALTY_SG | CONF_DID_NOT_PIT) #define CONF_TIME (CONF_PENALTY_30 | CONF_PENALTY_45) // Race flags // HOSTF_CAN_VOTE 1 // HOSTF_CAN_SELECT 2 // HOSTF_MID_RACE 32 // HOSTF_MUST_PIT 64 // HOSTF_CAN_RESET 128 // Passengers byte // bit 0 female // bit 1 front // bit 2 female // bit 3 rear left // bit 4 female // bit 5 rear middle // bit 6 female // bit 7 rear right // TRACKING PACKET REQUESTS // ======================== // To request player / connection / result / car tracking packets, you can send an IS_TINY // These requests work even if race tracking is not switched on // In each case, ReqI must be non-zero // If you are using a relay, use the ReqI provided by the relay system // SubT : TINT_NCN - request all connections // SubT : TINY_NPL - request all players // SubT : TINY_RES - request all results // SubT : TINY_NLP - request a single IS_NLP // SubT : TINY_MCI - request a set of IS_MCI // CAR TRACKING PACKETS - car position info sent at constant intervals // ==================== // IS_NLP - compact, all cars in one packet // IS_MCI - more detailed, 8 cars per packet // If NodeSecs was set in the InSimInit packet, LFS will send IS_NLP or IS_MCI packets at // the specified interval, depending on the InSimInit initialisation flag ISF_NLP_MCI. // Note : NODE/LAP - To allow laps up to 2047 to be reported, without increasing the size of // NLP and MCI packets, the next 3 high bits of the current lap are now placed in the highest // 3 bits of the Node_Lap_Hi3 member (of NodeLap and CompCar structures). // Example C code to extract the correct values from the packets : // int node = Node_Lap_Hi3 & 0x1fff; // int lap = Lap_Lo8 | ((Node_Lap_Hi3 & 0xe000) >> 5); // When ISF_NLP_MCI flag is NOT SET, this packet is sent... struct NodeLap // NOT A PACKET - Car info in 4 bytes - there is an array of these in the NLP (below) { word Node_Lap_Hi3; // current path node (and high 3 bits of Lap) byte Lap_Lo8; // current lap (low byte... see above : NODE/LAP) byte UniqueId; // player's unique id }; struct IS_NLP // Node and Lap Packet { byte Size; // 124 byte Type; // ISP_NLP byte ReqI; // 0 unless this is a reply to an TINY_NLP request byte Zero; word NumNodes; // total number of nodes in the path word FinishLine; // the node number of the finish line byte NumPlayers; // number of players in race byte Sp1; // spare byte Sp2; // spare byte Sp3; // spare NodeLap Info [28]; // node and lap of each player }; // When ISF_NLP_MCI flag is SET, this packet is sent... struct CompCar // NOT A PACKET - Car info in 24 bytes - there is an array of these in the MCI (below) { word Node_Lap_Hi3; // current path node (and high 3 bits of Lap) byte Lap_Lo8; // current lap (low byte... see above : NODE/LAP) byte UniqueId; // player's unique id int X; // X map (65536 = 1 metre) int Y; // Y map (65536 = 1 metre) int Z; // Z alt (65536 = 1 metre) word Speed; // speed (32768 = 100 m/s) word Direction; // direction of car's motion : 0 = world y direction, 32768 = 180 deg word Heading; // direction of forward axis : 0 = world y direction, 32768 = 180 deg short AngVel; // signed, rate of change of heading : (16384 = 360 deg/s) }; // Note 1 : 0 = world y axis direction, 32768 = 180 degrees, anticlockwise from above // Note 2 : 0 = no change in heading, 8192 = 180 degrees per second anticlockwise struct IS_MCI // MultiCarInfo - if more than 8 in race then more than one of these is sent { byte Size; // 204 byte Type; // ISP_MCI byte ReqI; // 0 unless this is a reply to an TINY_MCI request byte Zero; word NumNodes; // total number of nodes in the path word FinishLine; // the node number of the finish line byte NumPlayers; // number of players in race byte FirstPly; // first player in this packet byte Sp2; // spare byte Sp3; // spare CompCar Info [8]; // car info for each player }; // You can change the rate of NLP or MCI after initialisation by sending this IS_SMALL : // ReqI : 0 // SubT : SMALL_NLI (Node Lap Interval) // UVal : Interval (0 means stop, otherwise interval in milliseconds, minimum 100) // CAR POSITION PACKETS (Initialising OutSim from InSim - See "OutSim" below) // ==================== // To request Car Positions from the currently viewed car, send this IS_SMALL : // ReqI : 0 // SubT : SMALL_SSP - Start Sending Positions (sends UDP packets using OutSim system) // UVal : delay between updates (zero means stop sending) // The SSP packet makes LFS start sending UDP packets if in game, using the OutSim // system as documented near the end of this text file. // You do not need to set any OutSim values in LFS cfg.txt as OutSim is automatically // initialised by the SSP packet. // The OutSim packets will be sent to the UDP port specified in the InSimInit packet. // Note : OutSim packets don't have a 4-byte header like InSim packets. // - You can identify an OutSim packet by its size (64 bytes) and 4th byte : zero. // DASHBOARD PACKETS (Initialising OutGauge from InSim - See "OutGauge" below) // ================= // To request Dashboard Packets from the currently viewed car, send this IS_SMALL : // ReqI : 0 // SubT : SMALL_SSG - Start Sending Gauges (sends UDP packets using OutGauge system) // UVal : delay between updates (zero means stop sending) // The SSG packet makes LFS start sending UDP packets if in game, using the OutGauge // system as documented near the end of this text file. // You do not need to set any OutGauge values in LFS cfg.txt as OutSim is automatically // initialised by the SSG packet. // The OutGauge packets will be sent to the UDP port specified in the InSimInit packet. // Note : OutGauge packets don't have a 4-byte header like InSim packets. // - You can identify an OutGauge packet by its size (92 bytes) and 4th byte : zero. // CAMERA CONTROL // ============== // IN GAME camera control // ---------------------- // You can set the viewed car and selected camera directly with a special packet. // These are the states normally set in-game by using the TAB and V keys. struct IS_SCC // Set Car Camera - Simplified camera packet (not SHIFT+U mode) { byte Size; // 8 byte Type; // ISP_SCC byte ReqI; // 0 byte Zero; byte ViewPlayer; // Player Index of car to view (0 = pole...) byte InGameCam; // InGameCam (as reported in StatePack) byte UniqueId; // Overrides ViewPlayer if set byte Spare3; }; // Special case : set ViewPlayer or InGameCam to 255 to leave that option unchanged. // Note : if UniqueId is used, the ViewPlayer byte will be ignored // DIRECT camera control // --------------------- // A Camera Position Packet can be used for LFS to report a camera position and state, // and for the external program to set LFS camera position in game or SHIFT+U mode. // Type : "Vec" : 3 ints (X, Y, Z) - 65536 means 1 metre struct IS_CPP // Cam Pos Pack - Full camera packet (in car OR SHIFT+U mode) { byte Size; // 32 byte Type; // ISP_CPP byte ReqI; // instruction : 0 / or reply : ReqI as received in the TINY_SCP byte Zero; Vec Pos; // Position vector word Heading; // 0 points along Y axis word Pitch; // 0 means looking at horizon word Roll; // 0 means no roll byte ViewPlayer; // Player Index of car to view (0 = pole...) byte InGameCam; // InGameCam (as reported in StatePack) float FOV; // 4-byte float : FOV in radians word Time; // Time to get there (0 means instant + reset) word Flags; // ISS state flags (see below) }; // The ISS state flags that can be set are : // ISS_SHIFTU - in SHIFT+U mode // ISS_SHIFTU_HIGH - HIGH view // ISS_SHIFTU_FOLLOW - following car // ISS_VIEW_OVERRIDE - override user view // On receiving this packet, LFS will set up the camera to match the values in the packet, // including switching into or out of SHIFT+U mode depending on the ISS_SHIFTU flag. // If ISS_SHIFTU is not set, then ViewPlayer and InGameCam will be used. // If ISS_VIEW_OVERRIDE is set, the in-car view Heading Pitch and Roll will be taken // from the values in this packet. Otherwise normal in-game control will be used. // Position vector (Vec Pos) - ignored for in-game (not SHIFT+U) cameras. // For SHIFT+U cameras, Pos can be either relative or absolute. // If ISS_SHIFTU_FOLLOW is set, that means it's a following camera, so the position // is relative to the selected car. Otherwise, the position is an absolute camera // position, as used in normal SHIFT+U mode. // SMOOTH CAMERA POSITIONING // -------------------------- // The "Time" value in the packet is used for camera smoothing. A zero Time means instant // positioning. Any other value (milliseconds) will cause the camera to move smoothly to // the requested position in that time. This is most useful in SHIFT+U camera modes or // for smooth changes of internal view when using the ISS_VIEW_OVERRIDE flag. // Note : you can use frequently updated camera positions with a longer "Time" than your // updates. For example, sending a camera position every 100 ms, with a Time value of // 1000 ms. LFS will make a smooth motion from these "rough" inputs. // If the requested camera mode is different from the one LFS is already in, it cannot // move smoothly to the new position, so in this case the "Time" value is ignored. // GETTING A CAMERA PACKET // ----------------------- // To GET a CamPosPack from LFS, send this IS_TINY : // ReqI : non-zero (if using a relay, use the ReqI provided by the relay system) // SubT : TINY_SCP (Send Cam Pos) // LFS will reply with a CamPosPack as described above. You can store this packet // and later send back exactly the same packet to LFS and it will try to replicate // that camera position. // TIME CONTROL // ============ // You can Stop or Start Time in LFS and while it is stopped you can make LFS move // in time steps in multiples of 100th of a second. Warning : unlike pausing, this // is a "trick" to LFS and the program is unaware of time passing, so you must not // leave it stopped because LFS is unusable in that state. You must never use this // packet in multiplayer mode. // Request the current time at any point with this IS_TINY : // ReqI : non-zero (if using a relay, use the ReqI provided by the relay system) // SubT : TINY_GTH (Get Time in Hundredths) // The time will be sent back in this IS_SMALL : // ReqI : non-zero (as received in the request packet) // SubT : SMALL_RTP (Race Time Packet) // UVal : Time (hundredths of a second since start of race or replay) // Stop and Start with this IS_SMALL : // ReqI : 0 // SubT : SMALL_TMS (TiMe Stop) // UVal : stop (1 - stop / 0 - carry on) // When STOPPED, make time step updates with this IS_SMALL : // ReqI : 0 // SubT : SMALL_STP (STeP) // UVal : number (number of hundredths of a second to update) // OutSim - MOTION SIMULATOR SUPPORT // ====== // The user's car in multiplayer or the viewed car in single player or // single player replay can output information to a motion system while // viewed from an internal view. // This can be controlled by 5 lines in the cfg.txt file : // OutSim Mode 0 :0-off 1-driving 2-driving+replay // OutSim Delay 1 :minimum delay between packets (100ths of a sec) // OutSim IP 0.0.0.0 :IP address to send the UDP packet // OutSim Port 0 :IP port // OutSim ID 0 :if not zero, adds an identifier to the packet // Each update sends the following UDP packet : struct OutSimPack { unsigned Time; // time in milliseconds (to check order) Vector AngVel; // 3 floats, angular velocity vector float Heading; // anticlockwise from above (Z) float Pitch; // anticlockwise from right (X) float Roll; // anticlockwise from front (Y) Vector Accel; // 3 floats X, Y, Z Vector Vel; // 3 floats X, Y, Z Vec Pos; // 3 ints X, Y, Z (1m = 65536) int ID; // optional - only if GameID is specified }; // Note 1 : X and Y axes are on the ground, Z is up. // Note 2 : Motion simulators can be dangerous. The Live for Speed // developers do not support any motion systems in particular and cannot accept // responsibility for injuries or deaths connected with the use of such machinery. // OutGauge - EXTERNAL DASHBOARD SUPPORT // ======== // The user's car in multiplayer or the viewed car in single player or // single player replay can output information to a dashboard system // while viewed from an internal view. // This can be controlled by 5 lines in the cfg.txt file : // OutGauge Mode 0 :0-off 1-driving 2-driving+replay // OutGauge Delay 1 :minimum delay between packets (100ths of a sec) // OutGauge IP 0.0.0.0 :IP address to send the UDP packet // OutGauge Port 0 :IP port // OutGauge ID 0 :if not zero, adds an identifier to the packet // Each update sends the following UDP packet : struct OutGaugePack { unsigned Time; // time in milliseconds (to check order) char Car [4]; // Car name word Flags; // OG_FLAGS (see below) byte Gear; // Reverse:0, Neutral:1, First:2... byte SpareB; float Speed; // M/S float RPM; // RPM float Turbo; // BAR float EngTemp; // C float Fuel; // 0 to 1 float OilPress; // BAR float Spare1; float Spare2; float Spare3; float Throttle; // 0 to 1 float Brake; // 0 to 1 float Clutch; // 0 to 1 char Display1[16]; // Usually Fuel char Display2[16]; // Usually Settings int ID; // optional - only if GameID is specified }; #define OG_SHIFTLIGHT 1 #define OG_FULLBEAM 2 #define OG_HANDBRAKE 4 #define OG_PITSPEED 8 #define OG_TC 16 #define OG_HEADLIGHTS 32 #define OG_SIGNAL_L 64 #define OG_SIGNAL_R 128 #define OG_REDLINE 256 #define OG_OILWARN 512 #define OG_1 1024 #define OG_2 2048 #define OG_3 4096 #define OG_4 8192 #define OG_KM 16384 #define OG_BAR 32768 ////// #endif