10 Commits
5 changed files with 126 additions and 28 deletions
-2
View File
@@ -117,7 +117,6 @@ try {
Write-Host 'Start Sons of the Forest, then:'
Write-Host ' 1. Check that MODS appears on the main menu and lists RifleScope'
Write-Host ' 2. Load into a game, equip the rifle and aim down the scope'
Write-Host ' 3. Press F1 and type scopezoom to see or change the zoom'
Write-Host ''
}
catch {
@@ -129,4 +128,3 @@ catch {
Write-Host ''
}
Read-Host 'Press Enter to close' | Out-Null
+15 -3
View File
@@ -1,9 +1,15 @@
# Rifle Scope
[![Downloads](https://img.shields.io/github/downloads/JustinOros/sotf-riflescope/total?label=downloads)](https://github.com/JustinOros/sotf-riflescope/releases) [![Latest](https://img.shields.io/github/v/release/JustinOros/sotf-riflescope?label=latest)](https://github.com/JustinOros/sotf-riflescope/releases/latest)
A stronger rifle scope for Sons of the Forest. Aiming down the rifle scope zooms
5x further than the vanilla scope and shows a full screen scope view with a
crosshair reticle, mil dots and a rangefinder instead of the red dot.
Want a suppressed rifle too? Install
[RifleSuppressor](https://github.com/JustinOros/sotf-riflesuppressor). It used to
be part of this mod and is now its own mod, so you can use either one or both.
## Multiplayer
Client side only. Nothing gets installed on a dedicated server, and other players
@@ -67,15 +73,21 @@ Press F1 to open the console, then use these commands:
| Command | Action |
| --- | --- |
| `scope` | Show whether the scope is on or off |
| `scope off` | Go back to the vanilla scope |
| `scope on` | Turn the scope back on |
| `scopezoom` | Show the current zoom |
| `scopezoom 5` | Set the zoom as a multiple of the vanilla scope, 1 to 50. The default is 5 |
| `scopetrim` | Show the current vertical trim |
| `scopetrim 50` | Set the vertical trim, -200 to 200. Positive moves hits down, negative moves hits up. The default is 50 |
| `scopetrim 60` | Set the vertical trim, -200 to 200. Positive moves hits down, negative moves hits up. The default is 60 |
| `scopewind` | Show the current windage |
| `scopewind 20` | Set the windage, -200 to 200. Positive moves hits right, negative moves hits left. The default is 0 |
| `scopedebug` | Toggle a debug readout above the range |
The zoom, trim and windage are saved to `UserData\RifleScope.txt` in your game
Trim and windage are angle adjustments, so a setting that is right at one range
stays right at every range.
The on or off setting, zoom, trim and windage are saved to `UserData\RifleScope.txt` in your game
folder. Setting the zoom to 1 keeps vanilla zoom and the normal scope view,
without the red dot.
@@ -94,4 +106,4 @@ the game is not found automatically.
## Troubleshooting
Check `_RedLoader\Latest.log` in your game folder. RifleScope logs a line when it
loads.
loads.
+107 -19
View File
@@ -2,9 +2,15 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using RedLoader;
using RedLoader.Utils;
using Sons.FieldOfView;
using Sons.Items.Core;
using Sons.Weapon;
using SonsSdk;
using SonsSdk.Attributes;
@@ -20,9 +26,10 @@ public class RifleScope : SonsMod
private const float DefaultZoom = 5f;
private const float MinZoom = 1f;
private const float MaxZoom = 50f;
private const float DefaultTrimCm = 50f;
private const float DefaultTrimCm = 60f;
private const float MaxTrimCm = 200f;
private const float MaxWindCm = 200f;
private const float TrimReferenceRange = 50f;
private const int MilDotCount = 10;
private const float MilDotSize = 0.4f;
private const float MinDotPx = 7f;
@@ -42,10 +49,12 @@ public class RifleScope : SonsMod
private static float _trimCm = DefaultTrimCm;
private static float _windCm;
private static bool _debug;
private static bool _enabled = true;
private static readonly List<(Renderer Renderer, int Slot, Material Original)> RedDotSlots = new();
private static string _configPath;
private static RifleAnimatorController _rifle;
private static float _nextSearch;
private static RifleAnimatorController _pendingRifle;
private static float _hipFov;
private static float _vanillaAimFov = 35f;
private static float _targetAimFov;
@@ -73,6 +82,7 @@ public class RifleScope : SonsMod
public RifleScope()
{
OnUpdateCallback = OnUpdate;
HarmonyPatchAll = true;
}
protected override void OnSdkInitialized()
@@ -100,15 +110,22 @@ public class RifleScope : SonsMod
{
if (!_rifle || !_rifle.gameObject.activeInHierarchy)
{
_rifle = null;
SetZoomed(false, null);
if (Time.unscaledTime < _nextSearch)
return;
_nextSearch = Time.unscaledTime + 0.5f;
if (!FindRifle())
if (_rifle || _hiddenCam)
{
_rifle = null;
SetZoomed(false, null);
}
var pending = _pendingRifle;
_pendingRifle = null;
if (!pending || !pending.gameObject.activeInHierarchy)
return;
AdoptRifle(pending);
}
if (!_enabled)
return;
var manager = _rifle._cameraFovManager;
if (!manager)
{
@@ -123,20 +140,25 @@ public class RifleScope : SonsMod
SetZoomed(zoomed, cam);
}
private static bool FindRifle()
internal static void OnWeaponTick(RangedWeaponController controller)
{
foreach (var rifle in UnityEngine.Object.FindObjectsOfType<RifleAnimatorController>())
if (!controller || (_rifle && _rifle.Pointer == controller.Pointer))
return;
var rifle = controller.TryCast<RifleAnimatorController>();
if (rifle && rifle.IsLocalPlayer())
_pendingRifle = rifle;
}
private static void AdoptRifle(RifleAnimatorController rifle)
{
_rifle = rifle;
_projectile = FindProjectileTransform(rifle);
if (_enabled)
{
if (!rifle || !rifle.gameObject.activeInHierarchy || !rifle.IsLocalPlayer())
continue;
_rifle = rifle;
_projectile = FindProjectileTransform(rifle);
if (!_overlay)
CreateOverlay();
HideRedDot(rifle);
return true;
}
return false;
}
private static Transform FindProjectileTransform(RangedWeaponController rifle)
@@ -196,8 +218,9 @@ public class RifleScope : SonsMod
}
CenterPoint(cam, out var point);
point -= cam.transform.up * (_trimCm * 0.01f);
point += cam.transform.right * (_windCm * 0.01f);
var scale = Vector3.Distance(cam.transform.position, point) / TrimReferenceRange;
point -= cam.transform.up * (_trimCm * 0.01f * scale);
point += cam.transform.right * (_windCm * 0.01f * scale);
var dir = point - _projectile.position;
if (dir.sqrMagnitude < 0.0001f)
return;
@@ -267,6 +290,7 @@ public class RifleScope : SonsMod
var mat = mats[i];
if (!mat || HiddenIds.Contains(mat.GetInstanceID()) || !mat.shader || mat.shader.name != RedDotShader)
continue;
RedDotSlots.Add((renderer, i, mat));
mats[i] = HiddenFor(mat);
changed = true;
}
@@ -275,6 +299,33 @@ public class RifleScope : SonsMod
}
}
private static void RestoreRedDot()
{
foreach (var (renderer, slot, original) in RedDotSlots)
{
if (!renderer || !original)
continue;
var mats = renderer.sharedMaterials;
if (slot >= mats.Length || !mats[slot] || !HiddenIds.Contains(mats[slot].GetInstanceID()))
continue;
mats[slot] = original;
renderer.sharedMaterials = mats;
}
RedDotSlots.Clear();
}
private static void Disable()
{
SetZoomed(false, null);
if (_rifle)
{
var settings = _rifle._fovChangeSettings;
if (settings != null && OriginalOffsets.TryGetValue(settings.Pointer, out var original))
settings._FieldOfViewTargetOffset_k__BackingField = original;
}
RestoreRedDot();
}
private static Material HiddenFor(Material original)
{
var id = original.GetInstanceID();
@@ -632,6 +683,26 @@ public class RifleScope : SonsMod
return tex;
}
[DebugCommand("scope")]
private static void ScopeCommand(string args)
{
args = (args ?? string.Empty).Trim().ToLowerInvariant();
if (args == "on" || args == "off")
{
_enabled = args == "on";
Save();
if (_enabled)
_rifle = null;
else
Disable();
Say($"RifleScope {(_enabled ? "on" : "off")}");
return;
}
Say($"RifleScope is {(_enabled ? "on" : "off")}. Usage: scope on or scope off");
}
[DebugCommand("scopezoom")]
private static void ScopeZoomCommand(string args)
{
@@ -732,6 +803,8 @@ public class RifleScope : SonsMod
_trimCm = trim;
if (parts.Length > 2 && float.TryParse(parts[2], NumberStyles.Float, Inv, out var wind) && wind >= -MaxWindCm && wind <= MaxWindCm)
_windCm = wind;
if (parts.Length > 3)
_enabled = parts[3] != "0";
}
catch (Exception e)
{
@@ -743,7 +816,7 @@ public class RifleScope : SonsMod
{
try
{
File.WriteAllText(_configPath, $"{_zoom.ToString(Inv)} {_trimCm.ToString(Inv)} {_windCm.ToString(Inv)}");
File.WriteAllText(_configPath, $"{_zoom.ToString(Inv)} {_trimCm.ToString(Inv)} {_windCm.ToString(Inv)} {(_enabled ? "1" : "0")}");
}
catch (Exception e)
{
@@ -751,3 +824,18 @@ public class RifleScope : SonsMod
}
}
}
[HarmonyPatch(typeof(RangedWeaponController), nameof(RangedWeaponController.CheckFireInput))]
internal static class CheckFireInputPatch
{
private static void Postfix(RangedWeaponController __instance)
{
try
{
global::RifleScope.RifleScope.OnWeaponTick(__instance);
}
catch
{
}
}
}
+2 -2
View File
@@ -6,7 +6,7 @@
<LangVersion>latest</LangVersion>
<AssemblyName>RifleScope</AssemblyName>
<RootNamespace>RifleScope</RootNamespace>
<Version>1.0.0</Version>
<Version>1.2.0</Version>
<NoWarn>CS0436;CS1701;CS1702;MSB3277;MSB3106</NoWarn>
</PropertyGroup>
@@ -34,4 +34,4 @@
<EmbeddedResource Include="manifest.json" />
</ItemGroup>
</Project>
</Project>
+2 -2
View File
@@ -3,9 +3,9 @@
"id": "RifleScope",
"name": "RifleScope",
"author": "JustinOros",
"version": "1.0.0",
"version": "1.2.0",
"description": "Stronger rifle scope magnification and a crosshair reticle",
"gameVersion": "1.0.0",
"platform": "Client",
"type": "Mod"
}
}