Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10,516 changes: 10,516 additions & 0 deletions addons/compass/Configs/ACE/EarthMagneticField.conf

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions addons/compass/Configs/ACE/EarthMagneticField.conf.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
MetaFileClass {
Name "{46B2C74B04BA64CE}Configs/ACE/EarthMagneticField.conf"
Configurations {
CONFResourceClass PC {
}
CONFResourceClass XBOX_ONE : PC {
}
CONFResourceClass XBOX_SERIES : PC {
}
CONFResourceClass PS4 : PC {
}
CONFResourceClass PS5 : PC {
}
CONFResourceClass HEADLESS : PC {
}
}
}
6 changes: 6 additions & 0 deletions addons/compass/Configs/ACE/Settings.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ACE_SettingsConfig {
m_aInitialModSettings {
ACE_Compass_Settings "{69981B8FA0318F93}" {
}
}
}
17 changes: 17 additions & 0 deletions addons/compass/Configs/ACE/Settings.conf.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
MetaFileClass {
Name "{A305FEB7400A2965}Configs/ACE/Settings.conf"
Configurations {
CONFResourceClass PC {
}
CONFResourceClass XBOX_ONE : PC {
}
CONFResourceClass XBOX_SERIES : PC {
}
CONFResourceClass PS4 : PC {
}
CONFResourceClass PS5 : PC {
}
CONFResourceClass HEADLESS : PC {
}
}
}
1 change: 1 addition & 0 deletions addons/compass/scripts/Game/65AD7CF69FAF1FDD.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#define ACE_COMPASS
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,40 @@
modded class SCR_CompassComponent : SCR_GadgetComponent
{
protected ACE_Compass_Display m_ACE_Compass_Display;
protected TimeAndWeatherManagerEntity m_TimaAndWeatherManager;

//------------------------------------------------------------------------------------------------
override void ActivateGadgetUpdate()
{
super.ActivateGadgetUpdate();

ChimeraWorld world = GetGame().GetWorld();
m_TimaAndWeatherManager = world.GetTimeAndWeatherManager();

if (m_CharacterOwner != SCR_PlayerController.GetLocalControlledEntity())
return;

// https://discord.com/channels/105462288051380224/976155351999201390/1138453903562768414
if (!m_ACE_Compass_Display)
m_ACE_Compass_Display = ACE_Compass_Display.Cast(SCR_HUDManagerComponent.GetHUDManager().FindInfoDisplay(ACE_Compass_Display));
}

//------------------------------------------------------------------------------------------------
//! Make needle point at magnetic north
override protected void UpdateNeedleDirection(float timeSlice)
{
super.UpdateNeedleDirection(timeSlice);

float effectiveAngle = SCR_Math.fmod(m_fNeedleAngle + m_TimaAndWeatherManager.ACE_GetMagneticDeclination(), 360);
if (effectiveAngle > 180)
effectiveAngle -= 360;

if (m_SignalManager)
m_SignalManager.SetSignalValue(m_PrefabData.m_iSignalNeedle, effectiveAngle);
}

//------------------------------------------------------------------------------------------------
//! Update displayed bearing
override void Update(float timeSlice)
{
super.Update(timeSlice);
Expand All @@ -41,7 +60,7 @@ modded class SCR_CompassComponent : SCR_GadgetComponent
m_ACE_Compass_Display.Show(true, UIConstants.FADE_RATE_SLOW);
}

m_ACE_Compass_Display.UpdateBearing(m_fNeedleAngle);
m_ACE_Compass_Display.UpdateBearing(m_SignalManager.GetSignalValue(m_PrefabData.m_iSignalNeedle));
}

//------------------------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//------------------------------------------------------------------------------------------------
[BaseContainerProps(configRoot: true)]
class ACE_EarthMagneticFieldConfig
{
// Data obtained from https://www.ngdc.noaa.gov/geomag-web/calculators/calculateIgrfgrid?lat1=-90&lat2=90&lon1=-180&lon2=179&latStepSize=2.5&lonStepSize=2.5&magneticComponent=d&key=REDACTED&resultFormat=csv
[Attribute("Declination values in degrees, ordered latitude-major from latitude 90 to -90 and longitude -180 to <180.")]
protected ref array<float> m_aDeclinations;

[Attribute(defvalue: "2.5", desc: "Grid step size in degrees for both latitude and longitude.")]
protected float m_fStepSize;

//------------------------------------------------------------------------------------------------
float ComputeDeclination(float latitude, float longitude)
{
int xCount = 360 / m_fStepSize;
int yCount = 180 / m_fStepSize + 1;

if (m_aDeclinations.Count() != xCount * yCount)
{
Debug.Error(string.Format("Bad length of m_aDeclinations. %1 instead of %2.", m_aDeclinations.Count(), xCount * yCount));
return 0;
}

float x = (180 + longitude) / m_fStepSize;
int x0 = (int)Math.Floor(x) % xCount;
int x1 = (x0 + 1) % xCount;
float tx = Math.Mod(x, 1);

float y = (90 - latitude) / m_fStepSize;
int y0 = Math.Floor(y);
int y1 = Math.Min(y0 + 1, yCount - 1);
float ty = Math.Mod(y, 1);

int i00 = GetGridIndex(x0, y0);
int i10 = GetGridIndex(x1, y0);
int i01 = GetGridIndex(x0, y1);
int i11 = GetGridIndex(x1, y1);

return ACE_Math.Bilerp(m_aDeclinations[i00], m_aDeclinations[i10], m_aDeclinations[i01], m_aDeclinations[i11], tx, ty);
}

//------------------------------------------------------------------------------------------------
protected int GetGridIndex(int x, int y)
{
return y * (360 / m_fStepSize) + x;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//------------------------------------------------------------------------------------------------
//! Add mod settings to mission header
[BaseContainerProps()]
modded class ACE_MissionHeaderSettings
{
[Attribute()]
protected ref ACE_Compass_Settings m_ACE_Compass;

//------------------------------------------------------------------------------------------------
//! Applies settings from mission header to config
override void ApplyToSettingsConfig(notnull ACE_SettingsConfig config)
{
super.ApplyToSettingsConfig(config);

if (m_ACE_Compass)
config.SetModSettings(m_ACE_Compass);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//------------------------------------------------------------------------------------------------
[BaseContainerProps()]
class ACE_Compass_Settings : ACE_ModSettings
{
[Attribute(defvalue: "true", desc: "Enables simulation of magnatic north and makes compass point to it.")]
bool m_bMagneticDeclinationEnabled;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//------------------------------------------------------------------------------------------------
modded class TimeAndWeatherManagerEntity : BaseTimeAndWeatherManagerEntity
{
[Attribute(defvalue: "{46B2C74B04BA64CE}Configs/ACE/EarthMagneticField.conf", desc: "Whether the magnetic declination should be overriden by the value specified in this manager.")]
protected ResourceName m_sACE_EarthMagneticFieldConfigName;

[RplProp()]
protected float m_fACE_MagneticDeclination = 0;

//------------------------------------------------------------------------------------------------
override protected void EOnInit(IEntity owner)
{
super.EOnInit(owner);

if (!GetGame().InPlayMode() || !Replication.IsServer())
return;

ACE_Compass_Settings settings = ACE_SettingsHelperT<ACE_Compass_Settings>.GetModSettings();
if (!settings)
return;

ACE_EarthMagneticFieldConfig earthMagneticFieldConfig = SCR_ConfigHelperT<ACE_EarthMagneticFieldConfig>.GetConfigObject(m_sACE_EarthMagneticFieldConfigName);
if (earthMagneticFieldConfig)
{
if (settings.m_bMagneticDeclinationEnabled)
m_fACE_MagneticDeclination = earthMagneticFieldConfig.ComputeDeclination(GetCurrentLatitude(), GetCurrentLongitude());
}

Replication.BumpMe();
}

//------------------------------------------------------------------------------------------------
//! Returns magnetic declination in degrees
float ACE_GetMagneticDeclination()
{
return m_fACE_MagneticDeclination;
}
}
14 changes: 14 additions & 0 deletions addons/core/scripts/Game/ACE_Core/Global/ACE_Math.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,18 @@ class ACE_Math
float scale = Math.Pow(10, precision);
return Math.Round(value * scale) / scale;
}

//------------------------------------------------------------------------------------------------
//! Does bilinear interpolation between `a`, `b`, `c` and `d` using `tx` and `ty`.
//! \param[in] a Value at (0, 0)
//! \param[in] b Value at (1, 0)
//! \param[in] c Value at (0, 1)
//! \param[in] d Value at (1, 1)
//! \return interpolated value
static float Bilerp(float a, float b, float c, float d, float tx, float ty)
{
float y0 = Math.Lerp(a, b, tx);
float y1 = Math.Lerp(c, d, tx);
return Math.Lerp(y0, y1, ty);
}
}
47 changes: 46 additions & 1 deletion docs/src/content/docs/components/compass.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,55 @@
title: Compass
---

Displays bearing and cardinal when a compass is focused.
**ACE Compass** has the following features:
- Simulates magnetic declination based on the terrain's latitude and longitude.
- Makes compass point to magnetic north when declination is enabled (see `m_bMagneticDeclinationEnabled` in [Settings](#settings)).
- Displays bearing and cardinal when a compass is focused.

## Usage

### Show Compass Bearing

- Put compass in hand and use `Aiming down sight (toggle)` keybind in `Equipment` category (Default: <kbd>LMB</kbd>)

## Settings

Summary of settings that can be modified in the server config:

| Field | Value | Description |
| ------------------------------------- | -------------------- | -------------------------------------------------- |
| `m_bMagneticDeclinationEnabled` | Type: `bool`<br />Default: `true` | Enables simulation of magnatic north and makes compass point to it. |

<br />

Template for the `missionHeader` in a server config:
```
"missionHeader": {
"m_ACE_Settings": {
"m_ACE_Compass": {
"m_bMagneticDeclinationEnabled": true
}
}
}
```

## Modded Compass Support

### Make Analog Compass Point to Magnetic North

- If the compass has a `SCR_CompassComponent` and the needle gets animated based on the signal `Needle`, it should already point to the magnetic north out of the box.
- For custom setups see below for how to obtain the magnetic north.

### Get Angle for Magnetic North for Digital Compass

- The declination in degrees is constant for a terrain and can be obtained with `TimeAndWeatherManagerEntity::ACE_GetMagneticDeclination`
- The direction of the magnetic north is the direction of the true north minus the declination. _e.g._ adjust `northDirection` with declination if **ACE Compass** is loaded:

```cs
#ifdef ACE_COMPASS
ChimeraWorld world = GetGame().GetWorld();
TimeAndWeatherManagerEntity timeAndWeatherManager = world.GetTimeAndWeatherManager();
if (timeAndWeatherManager)
northDirection -= timeAndWeatherManager.ACE_GetMagneticDeclination();
#endif
```
Loading