Skip to content

Commit

Permalink
Merge pull request #245 from RiddleTime/dev
Browse files Browse the repository at this point in the history
2.2.4.0
Assetto Corsa EVO Early Access
- Added initial support for a few basic HUDs, like shift bar, shift rpm, input trace, g-force trace, and wheel slip.
- DSX (DualSense Active Triggers): Added support for AC EVO.
  • Loading branch information
RiddleTime authored Jan 20, 2025
2 parents 161c5a2 + e882cc6 commit 34ffa74
Show file tree
Hide file tree
Showing 20 changed files with 1,158 additions and 80 deletions.
2 changes: 1 addition & 1 deletion Race Element.Core/Race Element.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@
<ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
<PackageReference Include="System.Drawing.Common" Version="9.0.0" />
<PackageReference Include="System.Drawing.Common" Version="9.0.1" />
</ItemGroup>
</Project>
8 changes: 8 additions & 0 deletions Race Element.Data/Common/SimDataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using RaceElement.Data.Common.SimulatorData.LocalCar;
using RaceElement.Data.Games.Automobilista2;
using RaceElement.Data.Games.EuroTruckSimulator2;
using RaceElement.Data.Games.AssettoCorsaEvo;

namespace RaceElement.Data.Common;

Expand Down Expand Up @@ -84,6 +85,13 @@ public static void Update(bool clear = false)
_localCarEventLoop.Run();
break;
}
case Game.AssettoCorsaEvo:
{
Instance ??= new AssettoCorsaEvoDataProvider();
Instance.Update(ref _localCarData, ref _session, ref _gameData);
_localCarEventLoop.Run();
break;
}
default: { break; }
}
}
Expand Down
5 changes: 3 additions & 2 deletions Race Element.Data/Common/SimulatorData/SessionData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public static SessionData Instance

public bool IsSetupMenuVisible { get; set; }
public double SessionTimeLeftSecs { get; set; }

public CurrentFlag CurrentFlag { get; set; }
}

Expand All @@ -96,7 +96,8 @@ public enum RaceSessionType
Hotlap = 11,
Hotstint = 12,
HotlapSuperpole = 13,
Replay = 14
Replay = 14,
Unknown = 255
};
public enum SessionPhase
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using RaceElement.Data.Common;
using RaceElement.Data.Common.SimulatorData;
using RaceElement.Data.Common.SimulatorData.LocalCar;
using RaceElement.Data.Games.AssettoCorsaEvo.DataMapper;
using RaceElement.Data.Games.AssettoCorsaEvo.SharedMemory;
using System.Drawing;

namespace RaceElement.Data.Games.AssettoCorsaEvo;

internal sealed class AssettoCorsaEvoDataProvider : AbstractSimDataProvider
{
static int lastPhysicsPacketId = -1;

// AC1 seems to have only one class. Or at least no race class info in the telemetry.
static string dummyCarClass = "Race";
List<string> classes = [dummyCarClass];

internal override int PollingRate() => 200;

private static string GameName => Game.AssettoCorsaEvo.ToShortName();

public sealed override void Update(ref LocalCarData localCar, ref SessionData sessionData, ref GameData gameData)
{
var physicsPage = AcEvoSharedMemory.Instance.ReadPhysicsPageFile();
if (lastPhysicsPacketId == physicsPage.PacketId) // no need to remap the physics page if packet is the same
{
SimDataProvider.GameData.IsGamePaused = true;
return;
}
else
{
SimDataProvider.GameData.IsGamePaused = false;
}

LocalCarMapper.AddPhysics(ref physicsPage, ref localCar, ref sessionData);

gameData.Name = GameName;


// For now only physics page works, so no need to map other pages.

//var graphicsPage = AcEvoSharedMemory.Instance.ReadGraphicsPageFile();
//var staticPage = AcEvoSharedMemory.Instance.ReadStaticPageFile();
//LocalCarMapper.AddGraphics(ref graphicsPage, ref localCar, ref sessionData);

//SessionData.Instance.PlayerCarIndex = graphicsPage.PlayerCarID;
//SimDataProvider.LocalCar.CarModel.CarClass = dummyCarClass;

}

public override List<string> GetCarClasses()
{
return classes;
}

public override bool HasTelemetry()
{
return lastPhysicsPacketId > 0;
}

internal override void Stop()
{
// No-op
}

public override bool IsSpectating(int playerCarIndex, int focusedIndex)
{
// TODO: Can we spectate other cars in the pits in AC1?
return false;
}

public override Color GetColorForCategory(string category)
{
return Color.White;
}

internal sealed override void Start()
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using RaceElement.Data.Common.SimulatorData;
using Riok.Mapperly.Abstractions;
using static RaceElement.Data.Games.AssettoCorsaEvo.SharedMemory.AcEvoSharedMemory;

namespace RaceElement.Data.Games.AssettoCorsaEvo.DataMapper;

[Mapper]
internal static partial class GameDataMapper
{
public static void WithStaticPage(SPageFileStatic pageStatic, GameData gameData)
{
gameData.Version = pageStatic.AssettoCorsaVersion;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using RaceElement.Data.Common.SimulatorData.LocalCar;
using Riok.Mapperly.Abstractions;
using System.Numerics;
using static RaceElement.Data.Games.AssettoCorsa.SharedMemory.AcSharedMemory;

namespace RaceElement.Data.Games.AssettoCorsaEvo.DataMapper.LocalCar;

[Mapper]
internal static partial class PhysicsDataMapper
{
internal static void InsertPhysicsPage(ref PageFilePhysics pagePhysics, PhysicsData commonData)
{
commonData.Velocity = pagePhysics.SpeedKmh;
commonData.Acceleration = new(pagePhysics.AccG[0], pagePhysics.AccG[2], pagePhysics.AccG[1]);
commonData.Rotation = Quaternion.CreateFromYawPitchRoll(pagePhysics.Heading, pagePhysics.Pitch, pagePhysics.Roll);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using RaceElement.Data.Common.SimulatorData.LocalCar;
using Riok.Mapperly.Abstractions;
using System.Numerics;
using RaceElement.Data.Common.SimulatorData;
using static RaceElement.Data.Games.AssettoCorsaEvo.SharedMemory.AcEvoSharedMemory;

namespace RaceElement.Data.Games.AssettoCorsaEvo.DataMapper;

[Mapper]
internal static partial class LocalCarMapper
{
internal static void AddPhysics(ref SPageFilePhysics pagePhysics, ref LocalCarData commonData, ref SessionData sessionData)
{
commonData.Physics.Acceleration = new(pagePhysics.AccG[0], pagePhysics.AccG[1], pagePhysics.AccG[2]);
commonData.Engine.IsPitLimiterOn = pagePhysics.PitLimiterOn;
commonData.Engine.MaxRpm = pagePhysics.CurrentMaxRpm;
commonData.Engine.Rpm = pagePhysics.Rpms;

commonData.Engine.IsRunning = commonData.Engine.Rpm > 0;

commonData.Inputs.Steering = pagePhysics.SteerAngle;
commonData.Inputs.Clutch = pagePhysics.Clutch;
commonData.Inputs.Throttle = pagePhysics.Gas;
commonData.Inputs.Brake = pagePhysics.Brake;
commonData.Inputs.Gear = pagePhysics.Gear;

commonData.Tyres.CoreTemperature = pagePhysics.TyreCoreTemperature;
commonData.Tyres.Pressure = pagePhysics.WheelPressure;
commonData.Tyres.SlipRatio = pagePhysics.WheelSlip;
commonData.Tyres.Velocity = pagePhysics.Velocity;

commonData.Brakes.DiscTemperature = pagePhysics.BrakeTemperature;
commonData.Brakes.Pressure = pagePhysics.brakePressure;

commonData.Electronics.TractionControlLevel = (int)pagePhysics.TC;
commonData.Electronics.AbsLevel = (int)pagePhysics.Abs;
commonData.Engine.FuelLiters = pagePhysics.Fuel;

///
sessionData.Weather.AirTemperature = pagePhysics.AirTemp;
}

internal static void AddGraphics(ref SPageFileGraphic pageGraphics, ref LocalCarData commonData, ref SessionData sessionData)
{
if (pageGraphics.CarCoordinates.Length >= pageGraphics.PlayerCarID)
{
var coords = pageGraphics.CarCoordinates[pageGraphics.PlayerCarID];
commonData.Physics.Location = new Vector3(coords.X * 10f, coords.Y, coords.Z);
}

switch (pageGraphics.SessionType)
{
case AcSessionType.AC_HOTLAPSUPERPOLE: sessionData.SessionType = RaceSessionType.HotlapSuperpole; break;
case AcSessionType.AC_QUALIFY: sessionData.SessionType = RaceSessionType.Qualifying; break;
case AcSessionType.AC_HOTSTINT: sessionData.SessionType = RaceSessionType.Hotstint; break;
case AcSessionType.AC_PRACTICE: sessionData.SessionType = RaceSessionType.Practice; break;
case AcSessionType.AC_HOTLAP: sessionData.SessionType = RaceSessionType.Hotlap; break;
case AcSessionType.AC_RACE: sessionData.SessionType = RaceSessionType.Race; break;
default: sessionData.SessionType = RaceSessionType.Unknown; break;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Riok.Mapperly.Abstractions;
using RaceElement.Data.Common.SimulatorData;
using static RaceElement.Data.Games.AssettoCorsaEvo.SharedMemory.AcEvoSharedMemory;

namespace RaceElement.Data.Games.AssettoCorsaEvo.DataMapper;

[Mapper]
internal static partial class SessionDataMapper
{
}
Loading

0 comments on commit 34ffa74

Please sign in to comment.