The online racing simulator
Searching in All forums
(778 results)
Scawen
Developer
I understand the distortion is kind of strange, because it is linear. Although 'correct' in one sense it is sort of wrong in another, related to our perception.

Ideally there could be a distortion shader to make this affect more agreeable but this is not available in LFS.

There is a quite extreme setting you can use. It uses multiple renders to create the main scene.

In Options - View ... there is a setting "Multiple screen layout" and you can set up to 5 left screens and 5 right screens. This can approximate a cylindrical render, created from 11 vertical linear renders per frame.

I'd be interested to know if you get any improvement by using that.

You would adjust the view in that case by "Main screen FOV" and "Screen Angle" which should be a fairly small number.
cuni
S3 licensed
Nilex . . .

Quote from Nilex :'Twas a sad day when they patched up that fence. Those red/white barriers too, both such crowd-pleasers.

I still dream about creating a follow up video, showing practical application of the jump during a live race. Those were the times!

* * *

Anyway, my first LFS memory ...

Just so you know, I decided to revive this thread because its your last post on the forums, after a 3 year hiatus (2017)...

@admins - send email to Nilex on befalf of LFS community asking him to come back
pls?
he's probably just waiting for the update . . .
cuni
S3 licensed
Here I am again, beating on the dead horse due to an external reference :
"Microsoft is not on the business of making OS's, the OS is nothing but a data mining tool. I wonder how much money they make on the sale of user data vs total sales of Windows OS" ... "at this point you're paying to be spied on"


Guess " meat is back on the menu boys "
sinanju
S3 licensed
Top Times per vehicle ...


I've also included the 3 layouts I made for the circuit; Perimeter, Short and Long.
J_Valkonen
S3 licensed
Quote from Bass-Driver :Change $modinfo to $modinfo["class"]...

Made the changes.
I still need to exclude front-wheel drive cars. Is there a query for the drivetrain?
is it something like
$modinfo["drive"] = getmoddedcarinfo($userName);
... and then the same if-then logic can be applied in the same way.

## Allowed Drivetrains on the server
## Drivetrain: Rear Wheel Drive [RWD] or Four wheel drive AWD
## List of Drivetrains
## No_drive, //0: No_drive
## Rear_wheel_drive, //1: RWD
## Front_wheel_drive, //2: FWD
## Four_wheel_drive, //3: AWD


Code:
----
Event OnNewPlayerJoin( $userName )

## Allowed tyres on the server
## Tyre types: Super or Normal
## List of Tyre types
## Slick_R1, //0: R1
## Slick_R2, //1: R2
## Slick_R3, //2: R3
## Slick_R4, //3: R4
## Road_super, //4: Super
## Road_normal, //5: Normal
## Hybrid, //6: Hybrid
## Knobbly, //7: Knobbly

$OTFR = GetCurrentPlayerVar( "OldTyreFrontRight" ); # Vanha Rengas etu oikea
$OTRR = GetCurrentPlayerVar( "OldTyreRearRight" ); # Vanha Rengas taka oikea
$TFR = GetCurrentPlayerVar( "TyreFrontRight" ); # Rengas etu oikea
$TRR = GetCurrentPlayerVar( "TyreRearRight" ); # Rengas taka oikea
$FWAdj = GetCurrentPlayerVar( "FrontWheelsAdj" ); # Etu rengas säätö?
$RWAdj = GetCurrentPlayerVar( "RearWheelsAdj" ); # Taka rengas säätö?

IF (($OTRR != "TYRE_ROAD_SUPER" ) && ($OTFR != "TYRE_ROAD_SUPER" ) && ($TRR != "TYRE_ROAD_SUPER" ) && ($TFR != "TYRE_ROAD_SUPER" ) && ($OTRR != "TYRE_ROAD_NORMAL" ) && ($OTFR != "TYRE_ROAD_NORMAL" ) && ($TRR != "TYRE_ROAD_NORMAL" ) && ($TFR != "TYRE_ROAD_NORMAL" ))
THEN
cmdLFS( "/spec " . GetCurrentPlayerVar("UserName") );
openPrivButton( "tyrespec",50,35,100,15,5,15,32, "^7You have been moved to spectators because your ^1disallowed ^7tyres");
openPrivButton( "tyrechange",50,50,100,15,5,15,32, "^7Please change your tyres to ^3Normal ^7or ^3Super" );
# openPrivButton( "tyrechange",50,50,100,15,5,15,32, "^7Please change rear ^7and front ^7tyres to ^3Super" );
ENDIF

## Allowed cars on the server
## Vehicle class: saloon, touring car or GT
## List of correct names of vehicleclasses
## Object, //0: Object
## Touring_Car, //1: Touring car
## Saloon_Car, //2: Saloon car
## Buggy, //3: Buggy
## Formula, //4: Formula
## GT, //5: GT
## Kart, //6: Kart
## Bike, //7: Bike
## Van, //8: Van
## Truck, //9: Truck
## Formula_1, //10: Formula 1
## Formula_SAE //11: Formula SAE

$modinfo["class"] = getmoddedcarinfo($userName);
IF(($modinfo["class"] != "GT" ) && ($modinfo["class"] != "Saloon_Car") && ($modinfo["class"] != "Touring_Car"))
THEN
cmdLFS( "/spec " . GetCurrentPlayerVar("UserName") );
openPrivButton( "classspec",50,35,100,15,5,15,32, "^7You have been moved to spectators because your ^1car ^7does not meet the server ^1requirements.");
openPrivButton( "classchange",50,50,100,15,5,15,32, "^7Allowed vehicles ^7on the server are ^3Saloon, Touring Car, or GT" );
ENDIF
EndEvent
WestlY
S3 licensed
defender control online with cloud proces ... gpedit.msc and control
sinanju
S3 licensed
Made a video of my driving a grass cutter round the 'infields' layout ...

sinanju
S3 licensed
Couldn't resist fiddling ...

sinanju
S3 licensed
As per your suggestion, I've made 2 different versions of the 'Perimeter' layout that now have pit areas. One to the left just before Turn 1, and one to the right ...


If anyoune wants to modify the other 3 versions, then be my guest.

As each layout uses the maximum 3000 objects, you'll need to remove the bales round some of the bends to give you spare objects to use for pits.
LA1 Sinanju GoKart
sinanju
S3 licensed
Go-kart layout with 4 configurations ...



Heavily based on circuit layout on Saipan (co-ordinates: 15.266423936618589, 145.78913892726305).
WildGamerz
S3 licensed
Alright here the program.cs press S to show the buttons and h to hide them ofc and it not even that refined but it better than nothing Smile


using System;
using System.Collections.Generic;
using System.Linq;
using InSimDotNet;
using InSimDotNet.Packets;

namespace MultiLineButton
{
public class MultiLineButton
{
private readonly InSim _inSim;
private readonly byte _clickId;
private readonly byte _ucid;
private readonly byte _width;
private readonly byte _height;
private readonly byte _top;
private readonly byte _left;
private readonly byte _rowHeight;
private readonly byte _maxCharsPerRow;
private readonly string _text;
private readonly bool _showScrollbar;
private readonly ButtonStyles _style;
private readonly List<string> _lines;
private int _scrollPosition;
private readonly byte _scrollbarWidth;
private readonly Dictionary<byte, ButtonInfo> _buttonInfo;

private struct ButtonInfo
{
public ButtonType Type { get; set; }
public string Text { get; set; }
}

private enum ButtonType
{
Background,
TextLine,
ScrollUp,
ScrollTrack,
ScrollDown
}

public MultiLineButton(
InSim inSim,
byte clickId,
byte ucid,
byte width,
byte height,
byte top,
byte left,
byte rowHeight,
byte maxCharsPerRow,
string text,
ButtonStyles style = ButtonStyles.ISB_DARK)
{
_inSim = inSim;
_clickId = clickId;
_ucid = ucid;
_width = width;
_height = height;
_top = top;
_left = left;
_rowHeight = rowHeight;
_maxCharsPerRow = maxCharsPerRow;
_text = text;
_style = style;
_scrollPosition = 0;
_scrollbarWidth = (byte)Math.Max(4, Math.Round(rowHeight * 0.75));
_buttonInfo = new Dictionary<byte, ButtonInfo>();
_lines = SplitTextIntoLines(text, maxCharsPerRow);
_showScrollbar = _lines.Count * rowHeight > height;

// Setup event handlers
_inSim.Bind<IS_BTC>((inSim, packet) => HandleButtonClick(packet));
}

public void Show()
{
DrawButtons();
LogButtonInfo();
}

public void Hide()
{
ClearButtons();
}

private void DrawButtons()
{
ClearButtons();
var textAreaWidth = (byte)(_showScrollbar ? _width - _scrollbarWidth : _width);
var maxVisibleRows = _height / _rowHeight;

// Background button
SendButton(
_clickId,
_top,
_left,
_width,
_height,
"",
_style | ButtonStyles.ISB_DARK,
ButtonType.Background
);

// Draw scrollbar if needed
if (_showScrollbar)
{
var canScrollUp = _scrollPosition > 0;
var canScrollDown = _scrollPosition + maxVisibleRows < _lines.Count;
var scrollbarLeft = (byte)(_left + textAreaWidth);

// Up arrow
if (canScrollUp)
{
SendButton(
(byte)(_clickId + 1),
_top,
scrollbarLeft,
_scrollbarWidth,
_rowHeight,
"▲",
_style | ButtonStyles.ISB_CLICK | ButtonStyles.ISB_DARK,
ButtonType.ScrollUp
);
}

// Scrollbar track
if (maxVisibleRows > 2)
{
var scrollbarHeight = (byte)(_height - (2 * _rowHeight));
var scrollbarThumbHeight = (byte)(scrollbarHeight * maxVisibleRows / Math.Max(1, _lines.Count));
var scrollbarPosition = (byte)(_top + _rowHeight +
(_scrollPosition * (scrollbarHeight - scrollbarThumbHeight) /
Math.Max(1, _lines.Count - maxVisibleRows)));

SendButton(
(byte)(_clickId + 2),
scrollbarPosition,
scrollbarLeft,
_scrollbarWidth,
scrollbarThumbHeight,
"",
_style | ButtonStyles.ISB_DARK,
ButtonType.ScrollTrack
);
}

// Down arrow
if (canScrollDown)
{
SendButton(
(byte)(_clickId + 3),
(byte)(_top + _height - _rowHeight),
scrollbarLeft,
_scrollbarWidth,
_rowHeight,
"▼",
_style | ButtonStyles.ISB_CLICK | ButtonStyles.ISB_DARK,
ButtonType.ScrollDown
);
}
}

// Draw text lines
byte currentId = (byte)(_clickId + 4);
for (var i = 0; i < maxVisibleRows && i + _scrollPosition < _lines.Count; i++)
{
var text = _lines[i + _scrollPosition];
// Add ellipsis if there's more text below
if (i == maxVisibleRows - 1 && i + _scrollPosition < _lines.Count - 1)
{
text += "...";
}

SendButton(
currentId++,
(byte)(_top + i * _rowHeight),
_left,
textAreaWidth,
_rowHeight,
text,
_style | ButtonStyles.ISB_C4,
ButtonType.TextLine
);
}
}

private void SendButton(
byte clickId,
byte top,
byte left,
byte width,
byte height,
string text,
ButtonStyles style,
ButtonType type)
{
_buttonInfo[clickId] = new ButtonInfo { Type = type, Text = text };

var button = new IS_BTN
{
ReqI = 1,
ClickID = clickId,
UCID = _ucid,
T = top,
L = left,
W = width,
H = height,
Text = text,
BStyle = style
};

_inSim.Send(button);
}

private void HandleButtonClick(IS_BTC packet)
{
if (!_buttonInfo.ContainsKey(packet.ClickID))
return;

var buttonInfo = _buttonInfo[packet.ClickID];
var maxVisibleRows = _height / _rowHeight;

switch (buttonInfo.Type)
{
case ButtonType.ScrollUp when _scrollPosition > 0:
_scrollPosition--;
DrawButtons();
break;

case ButtonType.ScrollDown when _scrollPosition + maxVisibleRows < _lines.Count:
_scrollPosition++;
DrawButtons();
break;
}
}

private void LogButtonInfo()
{
Console.WriteLine("\nButton Information:");
foreach (KeyValuePair<byte, ButtonInfo> button in _buttonInfo)
{
Console.WriteLine($"ClickID {button.Key}: Type={button.Value.Type}, Text={button.Value.Text}");
}
Console.WriteLine($"Total Buttons: {_buttonInfo.Count}");
}

private void ClearButtons()
{
foreach (var clickId in _buttonInfo.Keys.ToList())
{
var button = new IS_BFN
{
ReqI = 1,
UCID = _ucid,
ClickID = clickId,
SubT = ButtonFunction.BFN_DEL_BTN
};
_inSim.Send(button);
}
_buttonInfo.Clear();
}

private static List<string> SplitTextIntoLines(string text, int maxCharsPerLine)
{
var words = text.Split(' ');
var lines = new List<string>();
var currentLine = "";

foreach (var word in words)
{
if (currentLine.Length + word.Length + 1 <= maxCharsPerLine)
{
if (currentLine.Length > 0)
currentLine += " ";
currentLine += word;
}
else
{
if (currentLine.Length > 0)
lines.Add(currentLine);
currentLine = word;
}
}

if (currentLine.Length > 0)
lines.Add(currentLine);

return lines;
}
}

// Example usage
class Program
{
static void Main(string[] args)
{
Console.WriteLine("=== InSim Multi-line Button Test ===\n");
Console.WriteLine("This test demonstrates the InSim packet flow for multi-line buttons.\n");

var inSim = new InSim();
MultiLineButton multiLineButton = null;

try
{
inSim.Initialize(new InSimSettings
{
Host = "127.0.0.1",
Port = 29999,
Admin = "",
Prefix = '/',
Interval = 100,
Flags = InSimFlags.ISF_LOCAL
});

var testText = @"^7InSim Packets Explained:

1. ^7IS_BTN (Button) Packet:
- ^7ReqI: Request ID (1)
- ^7UCID: Connection ID
- ^7ClickID: Unique button ID
- ^7Inst: 0
- ^7BStyle: Button style flags
- ^7TypeIn: Max chars (0-240)
- ^7L,T: Position
- ^7W,H: Size
- ^7Text: Button text

2. ^7IS_BTC (Button Click):
- ^7ReqI: Copy of button ReqI
- ^7UCID: Connection that clicked
- ^7ClickID: Clicked button ID
- ^7Inst: 0
- ^7CFlags: Click flags

3. ^7IS_BFN (Button Function):
- ^7ReqI: Request ID
- ^7SubT: Delete/clear/etc
- ^7UCID: Target connection
- ^7ClickID: Target button";

multiLineButton = new MultiLineButton(
inSim: inSim,
clickId: 1,
ucid: 0,
width: 40,
height: 30,
top: 20,
left: 20,
rowHeight: 5,
maxCharsPerRow: 20,
text: testText,
style: ButtonStyles.ISB_C1
);

multiLineButton.Show();

Console.WriteLine("\nProgram is running. Press 'H' to hide the button, 'S' to show it again, or 'Q' to quit.");

while (true)
{
var key = Console.ReadKey(true);
switch (char.ToUpper(key.KeyChar))
{
case 'H':
multiLineButton.Hide();
Console.WriteLine("Button hidden");
break;
case 'S':
multiLineButton.Show();
Console.WriteLine("Button shown");
break;
case 'Q':
Console.WriteLine("Exiting...");
return;
}
}
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
finally
{
if (multiLineButton != null)
{
multiLineButton.Hide();
}

if (inSim != null)
{
inSim.Disconnect();
inSim.Dispose();
}
}
}
}
}


sinanju
S3 licensed
Further update to top times per vehicle ...

sinanju
S3 licensed
The %nl% part means put next lot of text on a new line.

On my server, I have the following as part of a table to see the top time for each car ...



The code for this could look like this ...

<?php 
openPrivButton
( "tt_car_note",$tt_left,$tt_top+142,68,4,3,$tt_time-12,16,"^3This table has to be partially laid out by hand ^8and was last updated: ^019 May 2025"%nl%^1If a driver beats the existing fastest time for a vehicle shown above, then table order may be wrong%nl%^7If a driver sets a time for a vehicle that is *NOT* on this list,"%nl%^2then I will have to manually update the table");
?>
Because I don't want a huge long line of text in my script, my actual code looks like ...
<?php 
openPrivButton
( "tt_car_note",$tt_left,$tt_top+142,68,4,3,$tt_time-12,16,"^3This table has to be partially laid out by hand ^8and was last updated: ^019 May 2025"
. "%nl%^1If a driver beats the existing fastest time for a vehicle shown above, then table order may be wrong"
. "%nl%^7If a driver sets a time for a vehicle that is *NOT* on this list,"
. "%nl%^2then I will have to manually update the table");
?>
To make it more readable in the script, I've put the new lines on seperate lines, and started each line with

. "%nl%

The full stop and quotation mark (. ") tells lapper that the current line should be added to the previous line.
sebaalfa
S3 licensed
Buenas tardes a todos.
Los invito a reflexionar, ... Para que un usuario usaria varias cuentas, o cambiaria su IP, para entrar a un server?
-Porque se castigaria al servidor con recortes herramientas para detectar
dichos usuarios?
-Porque se protege tanto a dichos usuarios?
En respuesta al señor Scawen....
y cito:

Los desarrolladores no querrán asumir la responsabilidad de revelar las direcciones IP de los usuarios a los proveedores de alojamiento.

Que problemas legales conllevarian esa "responsabilidad"? (para LFS)

Los desarrolladores querrán proporcionar una ayuda más sólida a los proveedores de alojamiento para identificar a los jugadores problemáticos.

Eso lo tienes al alcance de un click, y no pasa por desviar el tema, ni se trata de una IP.


Good afternoon, everyone.
I invite you to reflect... Why would a user use multiple accounts, or change their IP, to access a server?
Why would the server be punished by cutting tools to detect such users?
Why are such users so protected?
In response to Mr. Scawen...
and I quote:

Developers won't want to take responsibility for revealing users' IP addresses to hosting providers.

What legal issues would such "responsibility" entail? (for LFS)

Developers will want to provide more robust support to hosting providers to identify problem players.

That's just a click away, and it's not about getting off topic, nor is it about an IP.
To Windows 11, or not to Windows 11, that is the question.
cuni
S3 licensed
It is known that the security updates will end 14th of October for win10.

I am not willing to casually transition to the new standard, maybe not so important on the reasons why, there is the LTSC version which will receive updates (security, not features) until 2032

Has anyone been this stubborn?
What can we expect from keeping up with an "old" version of win10? Just wait for OTA updates like now in "normal" win10 ?

Seamless transition where every new game/app/etc until 2032, that says supports win11, can we expect to work as well on LTSC? ("work as well" meaning if there aren't any major architecture or DirectX changes that causes incompatibilities. Not focusing on which will have the best performance)... Haven't seen many discussing this, what are your thoughts?
cuni
S3 licensed
Well I found this thread so, here it goes ...

Whilst browsing the mod list on the website, I was expecting the rating sort to work as a total reviews, but I believe I was wrong now thinking about it.

As you can see the rating sort is working as the biggest number closer to 5, as it should(1 review of 5 is better than 400 reviews of 4), but I believe it would be beneficial to have another sorting list with the amount of reviews (total number of users who clicked the button "OVERALL")


I specify the Overall because I noticed some cars I've reviewed were missing the others fields of the review(Technical, Graphical etc..)
sinanju
S3 licensed
Some more times ...

sinanju
S3 licensed
Some times on the board ...

sinanju
S3 licensed
After a lot of effort, managed to get a couple of fastest times back ...



This is the last of this track on my server - about to change to a newly made layout.

To those that set a time, or two, many thanks.
wktor213
S3 licensed
...
sinanju
S3 licensed
Took me a lot of laps over a couple of weeks to set the fastest times, and someone takes a couple of hours to beat every vehicle type he tried ...

sinanju
S3 licensed
Current Top times per car ...

Flotch
S3 licensed
as always, reading such things is a real pleasure Thumbs up , keep up the wonderful work guys LFS
NB : I like the mention of "At Fern Bay, the old version" ... agree, the 2.0 track will be the one to rule rule them all Smile
Rubbel_31
S3 licensed
...
FGED GREDG RDFGDR GSFDG