In Sim
In Sim
#define _ISPACKETS_H_
/////////////////////
// TCP or UDP packets can be sent in both directions, 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.
// CHANGES
// =======
// Version 0.7E
// ------------
// License byte added to IS_NCI packet (after Language byte)
// IS_PLH packet sets handicaps for individual players
// TINY_PLH - request IS_PLH listing player handicaps
// SMALL_LCL - full control of lights including fog and extra lights
// Version 0.6V
// ------------
// NLP / MCI minimum time interval reduced to 10 ms (was 40 ms)
// IS_CPP FOV can now be used in-car but not smoothed (0 = no change)
// IS_CPP Pos is now relative to "Centre view" not the user setting
// IS_RES TTime now indicates time since qualifying started
// IS_RES PLID is now zero if the player has left the race
// IS_NPL Config : setup configuration
// IS_NPL Fuel : initial fuel load
// IS_NPL RWAdj : tyre width reduction (rear)
// IS_NPL FWAdj : tyre width reduction (front)
// IS_PIT FuelAdd : fuel added
// IS_SPX Fuel200 : fuel remaining
// IS_LAP Fuel200 : fuel remaining
// Version 0.6N
// ------------
// Added ISS_DIALOG and ISS_TEXT_ENTRY to the ISS state flags
// New packet SMALL_LCS - set local car switches (lights, horn, siren)
// Version 0.6C
// ------------
// Small change to the in-game usage of IS_REO - only valid after SMALL_VTA
// Some more values (CPW / OOS / JOOS / HACK) added to the leave reasons
// 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
// InSim PACKETS
// =============
// INITIALISING InSim
// ==================
// TO START COMMUNICATION
// ======================
// TCP: Connect to LFS using a TCP connection, then send this packet:
// UDP: No connection required, just send this packet to LFS:
// zero : LFS sends all packets to the port of the incoming packet
// non-zero : LFS sends all packets to the specified UDPPort
// zero : LFS sends NLP / MCI packets using your TCP connection
// non-zero : LFS sends NLP / MCI packets to the specified UDPPort
// NOTE 3) Flags field (set the relevant bits to turn on the option):
// In most cases you should not set both ISF_NLP and ISF_MCI flags
// because all IS_NLP information is included in the IS_MCI packet.
// 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
// IS_SMALL
unsigned UVal; // value (e.g. for SMALL_SSP this would be the OutSim
packet rate)
};
// IS_TTC
// VERSION REQUEST
// ===============
// NOTE: LFS tries to match InSimVer with the version requested in your program's
IS_ISI
// packet if it is lower than the latest version known to LFS. If backward
compatibility
// is no longer possible then this version may be higher than your program
requested.
// In that case your program may not be able to read some packets sent to it by
LFS.
// If you connect to an older LFS version then InSimVer may be lower than
requested.
// CLOSING InSim
// =============
// You can send this IS_TINY to close the InSim connection to your program:
// ReqI: 0
// SubT: TINY_CLOSE (close this connection)
// 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).
// If InSim does not receive a packet for 70 seconds, it will close your
connection.
// To open it again you would need to send another InSimInit packet.
// LFS will send a blank IS_TINY packet like this every 30 seconds:
// ReqI: 0
// SubT: TINY_NONE (keep alive packet)
// NOTE: If you want to request a reply from LFS to check the connection
// at any time, you can send this IS_TINY:
byte QualMins;
byte RaceLaps; // see "RaceLaps" near the top of this document
byte Sp2;
byte ServerStatus; // 0 = unknown / 1 = success / > 1 = fail
// Setting states
// SCREEN MODE
// ===========
// You can send this packet to LFS to set the screen mode:
// If Width and Height are both zero, LFS will switch to windowed mode.
// 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.
struct IS_MSO // MSg Out - system messages and user messages - variable size
{
byte Size; // 12, 16, 20... 136 depending on Msg
byte Type; // ISP_MSO
byte ReqI; // 0
byte Zero;
enum
{
MSO_SYSTEM, // 0 - system message
MSO_USER, // 1 - normal visible user message
MSO_PREFIX, // 2 - hidden message starting with special prefix
(see ISI)
MSO_O, // 3 - hidden message typed on local pc with /o
command
MSO_NUM
};
// NOTE: Typing "/o MESSAGE" into LFS will send an IS_MSO with UserType = MSO_O
struct IS_III // InsIm Info - /i message from user to host's InSim - variable size
{
byte Size; // 12, 16, 20... 72 depending on Msg
byte Type; // ISP_III
byte ReqI; // 0
byte Zero;
struct IS_ACR // Admin Command Report - a user typed an admin command - variable
size
{
byte Size; // 12, 16, 20... 72 depending on Text
byte Type; // ISP_ACR
byte ReqI; // 0
byte Zero;
struct IS_MSX // MSg eXtended - like MST but longer (not for commands)
{
byte Size; // 100
byte Type; // ISP_MSX
byte ReqI; // 0
byte Zero;
enum
{
SND_SILENT,
SND_MESSAGE,
SND_SYSMESSAGE,
SND_INVALIDKEY,
SND_ERROR,
SND_NUM
};
// You can send individual key presses to LFS with the IS_SCH packet.
// For standard keys (e.g. V and H) you should send a capital letter.
// This does not work with some keys like F keys, arrows or CTRL keys.
// You can also use IS_MST with the /press /shift /ctrl /alt commands.
// CAR SWITCHES
// ============
// To operate the local car's flash, horn or siren you can send this IS_SMALL:
// NOTE: SIGNALS and HEADLIGHTS should now be set using SMALL_LCL (see CAR LIGHTS
below)
// LCS_SET_SIGNALS and LCS_SET_HEADLIGHTS have been left in SMALL_LCS for
compatibility
// ReqI: 0
// SubT: SMALL_LCS (Local Car Switches)
// UVal: Switches (see below)
// Switches bits
// Bits 0 to 7 are a set of flags specifying which values to set. You can set as
many
// as you like at a time. This allows you to set only the values you want to set
// while leaving the others to be controlled by the user.
// Depending on the above values, InSim will read some of the following values and
try
// to set them as required, if a real player is found on the local computer.
// bits 8-9 (Switches & 0x0300) - Signal (0 off / 1 left / 2 right / 3 hazard)
// bit 10 (Switches & 0x0400) - Flash
// bit 11 (Switches & 0x0800) - Headlights
// CAR LIGHTS
// ==========
// To operate the local car's lights you can send this IS_SMALL:
// ReqI: 0
// SubT: SMALL_LCL (Local Car Lights)
// UVal: Switches (see below)
// Switches bits
// Bits 0 to 7 are a set of flags specifying which values to set. You can set as
many
// as you like at a time. This allows you to set only the values you want to set
// while leaving the others to be controlled by the user.
// Depending on the above values, InSim will read some of the following values and
try
// to set them as required, if a real player is found on the local computer.
// MULTIPLAYER NOTIFICATION
// ========================
// LFS will send this packet when a host is started or joined:
// ReqI: 0
// SubT: TINY_MPE (MultiPlayerEnd)
// NOTE: If LFS is not in multiplayer mode, the host name in the ISM will be empty.
enum
{
VOTE_NONE, // 0 - no vote
VOTE_END, // 1 - end race
VOTE_RESTART, // 2 - restart
VOTE_QUALIFY, // 3 - qualify
VOTE_NUM
};
// ReqI: 0
// SubT: TINY_VTC (VoTe Cancelled)
// ReqI: 0
// SubT: SMALL_VTA (VoTe Action)
// UVal: action (VOTE_X - Vote Action as defined above)
// ReqI: 0
// SubT: TINY_VTC (VoTe Cancel)
// ALLOWED CARS
// ============
// To set the allowed cars on the host (like /cars command) you can send this
IS_SMALL:
// ReqI: 0
// SubT: SMALL_ALC (ALlowed Cars)
// UVal: Cars (see below)
// To find out the allowed cars at any time (on guest or host) send this IS_TINY:
// You can send a packet to limit the cars that can be used by a given connection
// The resulting set of selectable cars is a subset of the cars set to be available
// on the host (by the /cars command or SMALL_ALC)
// For example:
// Cars = 0 ... no cars can be selected on the specified connection
// Cars = 0xffffffff ... all the host's available cars can be selected
// XF GTI - 1
// XR GT - 2
// XR GT TURBO - 4
// RB4 GT - 8
// FXO TURBO - 0x10
// LX4 - 0x20
// LX6 - 0x40
// MRT5 - 0x80
// UF 1000 - 0x100
// RACEABOUT - 0x200
// FZ50 - 0x400
// FORMULA XR - 0x800
// XF GTR - 0x1000
// UF GTR - 0x2000
// FORMULA V8 - 0x4000
// FXO GTR - 0x8000
// XR GTR - 0x10000
// FZ50 GTR - 0x20000
// BMW SAUBER F1.06 - 0x40000
// FORMULA BMW FB02 - 0x80000
// HANDICAPS
// =========
// You can send a packet to add mass and restrict the intake on each car model
// The same restriction applies to all drivers using a particular car model
// This can be useful for creating multi class hosts
struct CarHCP // Car handicaps in 2 bytes - there is an array of these in the HCP
(below)
{
byte H_Mass; // 0 to 200 - added mass (kg)
byte H_TRes; // 0 to 50 - intake restriction
};
// Alternatively you can set handicaps per player. These handicaps will remain
until
// the player spectates or rejoins after returning from pits or garage (an IS_NPL
will
// be sent in that case).
// An output IS_PLH is sent to all InSim clients after an IS_PLH is received. The
output IS_PLH
// contains an entry for all valid players that had handicaps updated. An IS_PLH
is also output
// when a handicap is set by a text command /h_mass username X or /h_tres username
X
// NOTE: The 'silent' flag in bit 7 (0x80) avoids showing a message on player's
screen.
// RACE TRACKING
// =============
// If you are making a multiplayer InSim program, you must maintain two lists
// You should use the unique identifier UCID to identify 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 race setup screen) LFS sends this IS_TINY
// ReqI: 0
// SubT: TINY_REN (Race ENd)
// The following packets are sent when the relevant events take place:
word Flags; // race flags (must pit, can reset, etc - see below)
word NumNodes; // total number of nodes in the path
word Finish; // node index - finish line
word Split1; // node index - split 1
word Split2; // node index - split 2
word Split3; // node index - split 3
};
// bits 0 and 1 (Timing & 0x03): number of checkpoints if lap timing is enabled
struct IS_SLC // SeLected Car - sent when a connection selects a car (empty if no
car)
{
byte Size; // 8
byte Type; // ISP_SLC
byte ReqI; // 0 unless this is a reply to a TINY_SLC request
byte UCID; // connection's unique id (0 = host)
// NOTE: If a new guest joins and does have a car selected then an IS_SLC will be
sent
// Allowed Mods
// You can set a list of up to 120 mods that are allowed to be used on a host
// Send zero to clear the list and allow all mods to be used
// Mode identifiers
enum
{
CIM_NORMAL, // 0 - not in a special mode
CIM_OPTIONS, // 1
CIM_HOST_OPTIONS, // 2
CIM_GARAGE, // 3
CIM_CAR_SELECT, // 4
CIM_TRACK_SELECT, // 5
CIM_SHIFTU, // 6 - free view mode
CIM_NUM
};
enum
{
NRM_NORMAL,
NRM_WHEEL_TEMPS, // F9
NRM_WHEEL_DAMAGE, // F10
NRM_LIVE_SETTINGS, // F11
NRM_PIT_INSTRUCTIONS, // F12
NRM_NUM
};
enum
{
GRG_INFO,
GRG_COLOURS,
GRG_BRAKE_TC,
GRG_SUSP,
GRG_STEER,
GRG_DRIVE,
GRG_TYRES,
GRG_AERO,
GRG_PASS,
GRG_NUM
};
enum
{
FVM_PLAIN, // no buttons displayed
FVM_BUTTONS, // buttons displayed (not editing)
FVM_EDIT, // edit mode
FVM_NUM
};
//
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 TINY_NPL request
byte PLID; // player's newly assigned unique id
// NOTE: PType bit 0 (female) is not reported on dedicated host as humans are not
loaded
// You can use the driver model byte instead if required (and to force the use of
helmets)
#define SETF_SYMM_WHEELS 1
#define SETF_TC_ENABLE 2
#define SETF_ABS_ENABLE 4
// More...
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
};
byte Sp0;
byte Penalty; // current penalty value (see below)
byte NumStops; // number of pit stops
byte Fuel200; // /showfuel yes: double fuel percent / no: 255
};
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)
byte SpA;
byte NumStops; // number of pit stops
byte Confirm; // confirmation flags: disqualified etc - see below
byte SpB;
byte SpA;
byte NumStops; // number of pit stops
byte Confirm; // confirmation flags: disqualified etc - see below
byte SpB;
// LFS sends one at the start of every race or qualifying session, listing the
start order
// You can send one to LFS in two different ways, to specify the starting order:
// 1) In the race setup screen, to immediately rearrange the grid when the packet
arrives
// 2) In game, just before a restart or exit, to specify the order on the restart
or exit
// If you are sending an IS_REO in game, you should send it when you receive the
SMALL_VTA
// informing you that the Vote Action (VOTE_END / VOTE_RESTART / VOTE_QUALIFY) is
about
// to take place. Any IS_REO received before the SMALL_VTA is sent will be
ignored.
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
};
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,
PSE_NUM
};
// 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
};
// Languages
enum
{
LFS_ENGLISH, // 0
LFS_DEUTSCH, // 1
LFS_PORTUGUESE, // 2
LFS_FRENCH, // 3
LFS_SUOMI, // 4
LFS_NORSK, // 5
LFS_NEDERLANDS, // 6
LFS_CATALAN, // 7
LFS_TURKISH, // 8
LFS_CASTELLANO, // 9
LFS_ITALIANO, // 10
LFS_DANSK, // 11
LFS_CZECH, // 12
LFS_RUSSIAN, // 13
LFS_ESTONIAN, // 14
LFS_SERBIAN, // 15
LFS_GREEK, // 16
LFS_POLSKI, // 17
LFS_CROATIAN, // 18
LFS_HUNGARIAN, // 19
LFS_BRAZILIAN, // 20
LFS_SWEDISH, // 21
LFS_SLOVAK, // 22
LFS_GALEGO, // 23
LFS_SLOVENSKI, // 24
LFS_BELARUSSIAN, // 25
LFS_LATVIAN, // 26
LFS_LITHUANIAN, // 27
LFS_TRADITIONAL_CHINESE, // 28
LFS_SIMPLIFIED_CHINESE, // 29
LFS_JAPANESE, // 30
LFS_KOREAN, // 31
LFS_BULGARIAN, // 32
LFS_LATINO, // 33
LFS_UKRAINIAN, // 34
LFS_INDONESIAN, // 35
LFS_ROMANIAN, // 36
LFS_NUM_LANG // 37
};
// Leave reasons
enum
{
LEAVR_DISCO, // 0 - none
LEAVR_TIMEOUT, // 1 - timed out
LEAVR_LOSTCONN, // 2 - lost connection
LEAVR_KICKED, // 3 - kicked
LEAVR_BANNED, // 4 - banned
LEAVR_SECURITY, // 5 - security
LEAVR_CPW, // 6 - cheat protection wrong
LEAVR_OOS, // 7 - out of sync with host
LEAVR_JOOS, // 8 - join OOS (initial sync failed)
LEAVR_HACK, // 9 - invalid packet
LEAVR_NUM
};
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
#define PIF_LEFTSIDE 1
#define PIF_RESERVED_2 2
#define PIF_RESERVED_4 4
#define PIF_AUTOGEARS 8
#define PIF_SHIFTER 16
#define PIF_RESERVED_32 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
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
};
// 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
// HOSTF_FCV 256
// HOSTF_CRUISE 512
// Passengers byte
// In each case, ReqI must be non-zero, and will be returned in the reply packet
// OBJECT INFO - for autocross objects - used in some packets and the layout file
// ===========
struct ObjectInfo // Info about a single object - explained in the layout file
format
{
short X;
short Y;
byte Zbyte;
byte Flags;
byte Index;
byte Heading;
};
// In this case, PLID must be zero and JRRAction must be JRR_REJECT or JRR_SPAWN
// If you allow the join and it is successful you will then get a normal IS_NPL
with NumP set
// You can also specify the start position of the car using the StartPos structure
struct IS_JRR // Join Request Reply - send one of these back to LFS in response to
a join request
{
byte Size; // 16
byte Type; // ISP_JRR
byte ReqI; // 0
byte PLID; // ZERO when this is a reply to a join request - SET to
move a car
ObjectInfo StartPos; // 0: use default start point / Flags = 0x80: set start
point
};
// To use default start point, StartPos should be filled with zero values
// To specify a start point, StartPos X, Y, Zbyte and Heading should be filled like
an autocross
// start position, Flags should be 0x80 and Index should be zero
enum
{
JRR_REJECT,
JRR_SPAWN,
JRR_2,
JRR_3,
JRR_RESET,
JRR_RESET_NO_REPAIR,
JRR_6,
JRR_7,
};
// AUTOCROSS
// =========
// When all objects are cleared from a layout, LFS sends this IS_TINY:
// ReqI: 0
// SubT: TINY_AXC (AutoX Cleared)
// You can request information about the current layout with this IS_TINY:
// The information will be sent back in this packet (also sent when a layout is
loaded):
char LName[32]; // the name of the layout last loaded (if loaded locally)
};
// 1) Set the Interval field in the IS_ISI (InSimInit) packet (10, 20, 30... 8000
ms)
// 2) Set one of the flags ISF_NLP or ISF_MCI in the IS_ISI packet
struct NodeLap // Car info in 6 bytes - there is an array of these in the NLP
(below)
{
word Node; // current path node
word Lap; // current lap
byte PLID; // player's unique id
byte Position; // current race position: 0 = unknown, 1 = leader, etc...
};
struct CompCar // Car info in 28 bytes - there is an array of these in the MCI
(below)
{
word Node; // current path node
word Lap; // current lap
byte PLID; // player's unique id
byte Position; // current race position: 0 = unknown, 1 = leader, etc...
byte Info; // flags and other info - see below
byte Sp3;
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; // car's motion if Speed > 0: 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) Info byte - the bits in this byte have the following meanings:
struct IS_MCI // Multi Car Info - if more than MCI_MAX_CARS in race then more than
one is sent
{
byte Size; // 4 + NumC * 28
byte Type; // ISP_MCI
byte ReqI; // 0 unless this is a reply to an TINY_MCI request
byte NumC; // number of valid CompCar structs in this packet
// 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 time interval: 40, 50, 60... 8000
ms)
// CONTACT - reports contacts between two cars if the closing speed is above 0.25
m/s
// =======
// Set the ISF_CON flag in the IS_ISI to receive car contact reports
struct CarContact // 16 bytes: one car in a contact - two of these in the IS_CON
(below)
{
byte PLID;
byte Info; // like Info byte in CompCar (CCI_BLUE / CCI_YELLOW /
CCI_LAG)
byte Sp2; // spare
char Steer; // front wheel steer in degrees (right positive)
struct IS_CON // CONtact - between two cars (A and B are sorted by PLID)
{
byte Size; // 40
byte Type; // ISP_CON
byte ReqI; // 0
byte Zero;
word SpClose; // high 4 bits: reserved / low 12 bits: closing speed (10 =
1 m/s)
word Time; // looping time stamp (hundredths - time since reset - like
TINY_GTH)
CarContact A;
CarContact B;
};
// Set the ISF_OBH flag in the IS_ISI to receive object contact reports
struct IS_OBH // OBject Hit - car hit an autocross object or an unknown object
{
byte Size; // 24
byte Type; // ISP_OBH
byte ReqI; // 0
byte PLID; // player's unique id
word SpClose; // high 4 bits: reserved / low 12 bits: closing speed (10 =
1 m/s)
word Time; // looping time stamp (hundredths - time since reset - like
TINY_GTH)
CarContOBJ C;
short X; // as in ObjectInfo
short Y; // as in ObjectInfo
// OBHFlags byte
// Set the ISF_HLV flag in the IS_ISI to receive reports of incidents that would
violate HLVC
struct IS_HLV // Hot Lap Validity - off track / hit wall / speeding in pits / out
of bounds
{
byte Size; // 16
byte Type; // ISP_HLV
byte ReqI; // 0
byte PLID; // player's unique id
CarContOBJ C;
};
byte Sp0;
byte UCOAction;
byte Sp2;
byte Sp3;
CarContOBJ C;
// UCOAction byte
enum
{
UCO_CIRCLE_ENTER, // entered a circle
UCO_CIRCLE_LEAVE, // left a circle
UCO_CP_FWD, // crossed cp in forward direction
UCO_CP_REV, // crossed cp in reverse direction
};
// Index is 252. Checkpoint index (seen in the layout editor) is stored in Flags
bits 0 and 1
// 00 = finish line
// 01 = 1st checkpoint
// 10 = 2nd checkpoint
// 11 = 3rd checkpoint
// Note that the checkpoint index has no meaning in LFS and is provided only for
your convenience.
// If you use many InSim checkpoints you may need to identify them with the X and Y
values.
// Index is 253. The circle index (seen in the layout editor) is stored in the
Heading byte.
struct IS_CSC // Car State Changed - reports a change in a car's state (currently
start or stop)
{
byte Size; // 20
byte Type; // ISP_CSC
byte ReqI; // 0
byte PLID; // player's unique id
byte Sp0;
byte CSCAction;
byte Sp2;
byte Sp3;
CarContOBJ C;
};
// CSCAction byte
enum
{
CSC_STOP,
CSC_START,
};
enum
{
OCO_ZERO, // reserved
OCO_1, //
OCO_2, //
OCO_3, //
OCO_LIGHTS_RESET, // give up control of all lights
OCO_LIGHTS_SET, // use Data byte to set the bulbs
OCO_LIGHTS_UNSET, // give up control of the specified lights
OCO_NUM
};
// It refers to the temporary lights identifier (0 to 63) seen in the layout editor
// OCO_INDEX_MAIN AXO_START_LIGHTS
// Set the ISF_AXM_LOAD flag in the IS_ISI for info about objects when a layout is
loaded.
// Set the ISF_AXM_EDIT flag in the IS_ISI for info about objects edited by user or
InSim.
// You can also get (TTC_SEL) or set (PMO_SELECTION) the current editor selection.
enum
{
PMO_LOADING_FILE, // 0 - sent by the layout loading system only
PMO_ADD_OBJECTS, // 1 - adding objects (from InSim or editor)
PMO_DEL_OBJECTS, // 2 - delete objects (from InSim or editor)
PMO_CLEAR_ALL, // 3 - clear all objects (NumO must be zero)
PMO_TINY_AXM, // 4 - a reply to a TINY_AXM request
PMO_TTC_SEL, // 5 - a reply to a TTC_SEL request
PMO_SELECTION, // 6 - set a connection's layout editor selection
PMO_POSITION, // 7 - user pressed O without anything selected
PMO_GET_Z, // 8 - request Z values / reply with Z values
PMO_NUM
};
#define PMO_FILE_END 1
#define PMO_MOVE_MODIFY 2
#define PMO_SELECTION_REAL 4
#define PMO_AVOID_CHECK 8
// PMO_FILE_END
// Optimised in this case means that static vertex buffers will be created for all
// objects, to greatly improve the frame rate. The problem with this is that when
// there are many objects loaded, optimisation causes a significant glitch which
can
// be long enough to cause a driver who is cornering to lose control and crash.
// NOTE 1) LFS makes sure that all objects are optimised when the race restarts.
// NOTE 2) In the 'more' section of SHIFT+U there is info about optimised objects.
// If you are using InSim to send many packets of objects (for example loading an
// entire layout through InSim) then you must take care of the bandwidth and buffer
// overflows. You must not try to send all the objects at once. It's probably
good
// to use LFS's method of doing this: send the first packet of objects then wait
for
// the corresponding IS_AXM that will be output when the packet is processed. Then
// you can send the second packet and again wait for the IS_AXM and so on.
// PMO_MOVE_MODIFY
// When objects are moved or modified in the layout editor, two IS_AXM packets are
// sent. A PMO_DEL_OBJECTS followed by a PMO_ADD_OBJECTS. In this case the flag
// PMO_MOVE_MODIFY is set in the PMOFlags byte of both packets.
// PMO_SELECTION_REAL
// PMO_AVOID_CHECK
// If you send an IS_AXM with PMOAction of PMO_ADD_OBJECTS you may wish to set the
// UCID to one of the guest connections (for example if that user's action caused
the
// objects to be added). In this case some validity checks are done on the guest's
// computer which may report "invalid position" or "intersecting object" and delete
// the objects. This can be avoided by setting the PMO_AVOID_CHECK bit.
// To request IS_AXM packets for all layout objects and circles send this IS_TINY:
// LFS will send as many IS_AXM packets as needed to describe the whole layout.
// If there are no objects or circles, there will be one IS_AXM with zero NumO.
// The final IS_AXM packet will have the PMO_FILE_END flag set.
// An IS_AXM with PMO_POSITION is sent with a single object in the packet if a user
// presses O without any object type selected. Information only - no object is
added.
// The only valid values in Info are X, Y, Zbyte and Heading.
// PMO_GET_Z can be used to request the resulting Zbyte values for given X, Y,
Zbyte
// positions listed in the IS_AXM. A similar reply (information only) will be sent
// with adjusted Zbyte values. Index and Heading are ignored and set to zero in
the
// reply. Flags is set to 0x80 if Zbyte was successfully adjusted, zero if not.
// Suggested input values for Zbyte are either 240 to get the highest point at X, Y
// or you may use the approximate altitude (see layout file format).
// 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)
// UVal: interval (time between updates - zero means stop sending)
// If OutSim has not been setup in cfg.txt, the SSP packet makes LFS send 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 - OutSim is fully
// initialised by the SSP packet.
// The OutSim packets will be sent to the UDP port specified in the InSimInit
packet.
// NOTE: OutSim packets are not InSim packets and don't have a 4-byte header.
// To request Dashboard Packets from the currently viewed car, send this IS_SMALL:
// ReqI: 0
// SubT: SMALL_SSG (Start Sending Gauges)
// UVal: interval (time between updates - zero means stop sending)
// If OutGauge has not been setup in cfg.txt, the SSG packet makes LFS send 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 - OutGauge is fully
// initialised by the SSG packet.
// The OutGauge packets will be sent to the UDP port specified in the InSimInit
packet.
// NOTE: OutGauge packets are not InSim packets and don't have a 4-byte header.
// 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;
// A Camera Position Packet can be used for LFS to report a camera position and
state.
// An InSim program can also send one to set LFS camera position in game or SHIFT+U
mode.
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;
// If ISS_VIEW_OVERRIDE is set, the in-car view Heading, Pitch, Roll and FOV [not
smooth]
// can be set using this packet. Otherwise normal in game control will be used.
// Position vector (Vec Pos) - in SHIFT+U mode, Pos can be either relative or
absolute.
// 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 value
than
// the update frequency. For example, sending a camera position every 100 ms, with
a
// Time value of 1000 ms. LFS will make a smooth motion from the 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.
// 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 send packets
to move
// time in steps. Time steps are specified in hundredths 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.
// This packet is not available in live multiplayer mode.
// ReqI: 0
// SubT: SMALL_TMS (TiMe Stop)
// UVal: stop (1 - stop / 0 - carry on)
// ReqI: 0
// SubT: SMALL_STP (STeP)
// UVal: number (number of hundredths of a second to update)
// REPLAY CONTROL
// ==============
// You can load a replay or set the position in a replay with an IS_RIP packet.
// Replay positions and lengths are specified in hundredths of a second.
// LFS will reply with another IS_RIP packet when the request is completed.
// You can request an IS_RIP packet at any time with this IS_TINY:
enum
{
RIP_OK, // 0 - OK: completed instruction
RIP_ALREADY, // 1 - OK: already at the destination
RIP_DEDICATED, // 2 - can't run a replay - dedicated host
RIP_WRONG_MODE, // 3 - can't start a replay - not in a suitable mode
RIP_NOT_REPLAY, // 4 - RName is zero but no replay is currently
loaded
RIP_CORRUPTED, // 5 - IS_RIP corrupted (e.g. RName does not end
with zero)
RIP_NOT_FOUND, // 6 - the replay file was not found
RIP_UNLOADABLE, // 7 - obsolete / future / corrupted
RIP_DEST_OOB, // 8 - destination is beyond replay length
RIP_UNKNOWN, // 9 - unknown error found starting replay
RIP_USER, // 10 - replay search was terminated by user
RIP_OOS, // 11 - can't reach destination - SPR is out of sync
};
// NOTE: RIPOPT_FULL_PHYS makes MPR searching much slower so should not normally be
used.
// This flag was added to allow high accuracy MCI packets to be output when fast
forwarding.
// SCREENSHOTS
// ===========
// You can instuct LFS to save a screenshot in data\shots using the IS_SSH packet.
// It will be saved as bmp / jpg / png as set in Misc Options.
// Name can be a filename (excluding extension) or zero - LFS will create a name.
// LFS will reply with another IS_SSH when the request is completed.
byte Sp0; // 0
byte Sp1; // 0
byte Sp2; // 0
byte Sp3; // 0
enum
{
SSH_OK, // 0 - OK: completed instruction
SSH_DEDICATED, // 1 - can't save a screenshot - dedicated host
SSH_CORRUPTED, // 2 - IS_SSH corrupted (e.g. Name does not end with
zero)
SSH_NO_SAVE, // 3 - could not save the screenshot
};
// BUTTONS
// =======
// You can make up to 240 buttons appear on the host or guests (ID = 0 to 239).
// You should set the ISF_LOCAL flag (in IS_ISI) if your program is not a host
control
// system, to make sure your buttons do not conflict with any buttons sent by the
host.
#define IS_X_MIN 0
#define IS_X_MAX 110
#define IS_Y_MIN 30
#define IS_Y_MAX 170
// If you draw buttons in this area, the area will be kept clear to
// avoid overlapping LFS buttons with your InSim program's buttons.
// Buttons outside that area will not have a space kept clear.
// You can also make buttons visible in all screens - see below.
// To delete one button or a range of buttons or clear all buttons, send this
packet:
// NOTE: BFN_REQUEST allows the user to bring up buttons with SHIFT+B or SHIFT+I
// Host buttons and local buttons are stored separately, so there is no chance of a
conflict between
// a host control system and a local system (although the buttons could overlap on
screen).
// On clicking the button, a text entry dialog will be opened, allowing the
specified number of
// characters to be typed in. The caption on the text entry dialog is optionally
customisable using
// Text in the IS_BTN packet. If the first character of IS_BTN's Text field is
zero, LFS will read
// the caption up to the second zero. The visible button text then follows that
second zero.
// Inst byte: mainly used internally by InSim but also provides some extra user
flags
// NOTE: You should not use INST_ALWAYS_ON for most buttons. This is a special
flag for buttons
// that really must be on in all screens (including the garage and options
screens). You will
// probably need to confine these buttons to the top or bottom edge of the screen,
to avoid
// overwriting LFS buttons. Most buttons should be defined without this flag, and
positioned
// in the recommended area so LFS can keep a space clear in the main screens.
// NOTE: If width or height are zero, this would normally be an invalid button.
But in that case if
// there is an existing button with the same ClickID, all the packet contents are
ignored except the
// Text field. This can be useful for updating the text in a button without
knowing its position.
// For example, you might reply to an IS_BTT using an IS_BTN with zero W and H to
update the text.
// Replies: If the user clicks on a clickable button, this packet will be sent:
struct IS_BTC // BuTton Click - sent back when user clicks a button
{
byte Size; // 8
byte Type; // ISP_BTC
byte ReqI; // ReqI as received in the IS_BTN
byte UCID; // connection that clicked the button (zero if local)
// If the TypeIn byte is set in IS_BTN the user can type text into the button
// In that case no IS_BTC is sent - an IS_BTT is sent when the user presses ENTER
struct IS_BTT // BuTton Type - sent back when user types into a text entry button
{
byte Size; // 104
byte Type; // ISP_BTT
byte ReqI; // ReqI as received in the IS_BTN
byte UCID; // connection that typed into the button (zero if local)
// The user's car in multiplayer or the viewed car in single player or single
player
// replay can output data to an external program while in VIEW_DRIVER or
VIEW_CUSTOM.
// If OutSim Opts is zero, each update sends the following UDP packet:
struct OutSimPack
{
unsigned Time; // time in milliseconds (to check order)
// 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.
struct OutGaugePack
{
unsigned Time; // time in milliseconds (to check order)
enum
{
DL_SHIFT, // bit 0 - shift light
DL_FULLBEAM, // bit 1 - full beam
DL_HANDBRAKE, // bit 2 - handbrake
DL_PITSPEED, // bit 3 - pit speed limiter
DL_TC, // bit 4 - TC active or switched off
DL_SIGNAL_L, // bit 5 - left turn signal
DL_SIGNAL_R, // bit 6 - right turn signal
DL_SIGNAL_ANY, // bit 7 - shared turn signal
DL_OILWARN, // bit 8 - oil pressure warning
DL_BATTERY, // bit 9 - battery warning
DL_ABS, // bit 10 - ABS active or switched off
DL_ENGINE, // bit 11 - engine damage
DL_FOG_REAR, // bit 12
DL_FOG_FRONT, // bit 13
DL_DIPPED, // bit 14 - dipped headlight symbol
DL_FUELWARN, // bit 15 - low fuel warning light
DL_SIDELIGHTS, // bit 16 - sidelights symbol
DL_NEUTRAL, // bit 17 - neutral light
DL_18,
DL_19,
DL_20,
DL_21,
DL_22,
DL_23,
DL_NUM
};