The online racing simulator
Searching in All forums
(781 results)
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
...
loopingz
S3 licensed
Thanks for the report, very interesting.
The tunnel video is fabulous although it feels a bit fast.
Does the new ZBuffer will improve the ground markings and tire marks? I mean in 2D I don't notice it but in VR it feels very slightly floating like 5 or 10mm (maybe less even)...
Nucle@rRacer
S3 licensed
Quote from Bob Smith :I still used VHPA very regularly, although not with LFS. I'm intending at some...

Thank you for your anwser Bob. I don`t mind doing it manually even if it takes long. My problem is just that with some parameters I just do not know where to get them. I looked on and off the last days and managed to acquire the most parameters through LFS-Editor or the RAF-File but there are parameters I don´t no how to get them and with some of the parameters I am not sure if I did them correctly.

For example CoG.

In LFS-Editor there are CoG-local-Parameters for my car R=0.004, F=0.06 and U=0.251. I guess it is in meters and in VHPA I have to set the values in % depending on the length of the car. Car length is 4.317 m. So the values are R=49.07% and F=48.61 %. I don´t know if the U-Value can be taken directly as CoG height because there are two further CoG height values (height above ground and minimum height). The result was kind of wrong as you can see the weight destribution in LFS and it differ from VHPA, so I had to "cheat" to get to the same weight destribution. I think the values for rotating and unspung mass may be wrong. In the RAF-File one wheel weighs 16.215 kg, so the rotating mass for rear and front is each 32.43 kg. In LFS-Editor the suspension weighs 80kg, so the unspung mass for rear and front is each 72.43 kg. Or am I allready wrong here?

These parameters here I don´t know where to get from:

Quote :Wheels & Tyres
--------------
Wheel & tyre dimensions & inertia -> Rotating Mass
Wheel Movement & Alignment -> Inclination (is only front/rear) / Camber offset / Wheel:spring motion ratio / Wheel:ARB motion ratio
Wheel positions -> Ride height

Aerodynamics
--------------
Body -> Frontal area / cd / Cl
Aero Devices - > ALL

I get you Bob. I would´nt be also too hyped about supporting a tool that is not up to date with current state of LFS and was made a long time ago.
I hope someone who still uses VHPA now and then can help me out? It is a very powerful tool. I managed to do some setups. I tried to make them completely neutral. I matched nearly every bar to be green. The car behaves mostly neutral but something feels a bit off. So it needs more polishing and I guess the right/missing values.
I think there is not that much left to have a proper vehicle data and then to be able to make setups properly.

After I guess 12 years break from sim racing and especially LFS I started again because of ACE and remembered LFS and tried it ... and now I am all hooked again.
sinanju
S3 licensed
Video of me driving layout in RB4 ...



Another video, but slightly different configuration ...

10 Years of Scawen's very own racetrack (Event & Anniversary)
MicroSpecV
S3 licensed
⛳️ We go back exactly 10 years to the first ever race, made by and raced with our very own mr. Scawen :



... and with that, an event race is coming up at this long-standing Scawen's Racetrack; and everyone is invited!



>>> Race takes place THIS SATURDAY, 08 March at 1500 UTC. <<<
https://www.lfs.net/forum/thread/110186-Layout-Racing-League-2025%3A-Announcement-%26-Schedule


Layout Racing League makes a return visit to the well-loved Scawen's Racetrack, having last hosted in 2019, the mega race in Covid-hit 2020 and 2021, and last in 2022.
sinanju
S3 licensed
Further update ...

sinanju
S3 licensed
A few changes ...

lucienz
S3 licensed
Options - Vue:
Champ de vision, Décalage de la vue, Amplitude vision ... no Z offset
wojt9la
S3 licensed
can u share me that ...?
\
Bokujishin
S3 licensed
I worked on LOD2 since I was basically using the version you can see in my first few posts up until now, and now I'm actually done with LOD2 before LOD1 Big grin

I ended up with about 5.5k triangles, I hope this won't be considered to be "very high"... To be perfectly honest, I would really hate to lower the count down to even 2k, as it would completely destroy the visual fidelity of the car - with 5.5k, I basically cannot see the transition to LOD2, which is the second purpose of levels of detail, after optimization. Below 2k or even 1k triangles should, in my opinion, only be for a third visual LOD (not the one LFS uses for collisions).

Anyway, now I need to get back to modeling the interior (mainly missing air vents on the dashboard, then I can add some detail on the tunnel and the back), and iron out some details on the exterior (properly plug the gaps here and there, refine some rough shapes, especially on the front grilles, and those pesky tail lights).
sinanju
S3 licensed
Top times for reverse Perimeter layout ...

FGED GREDG RDFGDR GSFDG