Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f49dfbdb01 | ||
ac56754db2 | |||
![]() |
4839e050f8 | ||
![]() |
183c640ea3 | ||
![]() |
34e6c8fc06 | ||
027893c1d6 | |||
![]() |
28fd27d21d | ||
![]() |
796e7a6005 | ||
![]() |
88f39e76d3 | ||
![]() |
e28addc7ea | ||
![]() |
04b65cef3f | ||
![]() |
d96819d359 | ||
9801f92d69 | |||
![]() |
de74a09632 | ||
![]() |
0c90ab215a | ||
![]() |
944bb7d135 | ||
bd52f88452 | |||
7fba75b4f0 | |||
![]() |
b6092fee94 | ||
![]() |
d28425626d | ||
f565c3794d | |||
a4424ecd09 |
11
.gitignore
vendored
11
.gitignore
vendored
@ -1,3 +1,10 @@
|
|||||||
|
# Custom ignores
|
||||||
|
project/References/EFT_Managed/*
|
||||||
|
|
||||||
|
# Allow these files, despite the rules above
|
||||||
|
!project/References/EFT_Managed/.keep
|
||||||
|
!project/References/SPT/.keep
|
||||||
|
|
||||||
# ---> VisualStudio
|
# ---> VisualStudio
|
||||||
## Ignore Visual Studio temporary files, build results, and
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
## files generated by popular Visual Studio add-ons.
|
## files generated by popular Visual Studio add-ons.
|
||||||
@ -241,6 +248,10 @@ ClientBin/
|
|||||||
*.pfx
|
*.pfx
|
||||||
*.publishsettings
|
*.publishsettings
|
||||||
orleans.codegen.cs
|
orleans.codegen.cs
|
||||||
|
.idea
|
||||||
|
Freecam.sln.DotSettings.user
|
||||||
|
Project/.idea/
|
||||||
|
Project/Shared/*
|
||||||
|
|
||||||
# Including strong name files can present a security risk
|
# Including strong name files can present a security risk
|
||||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
28
README.md
28
README.md
@ -1,33 +1,33 @@
|
|||||||
# Freecam
|
# Freecam
|
||||||
|
|
||||||
An SPT-AKI module mod that allows you to detach the camera and fly around freely in Escape From Tarkov.
|
A BepInEx plugin for SPT-AKI that allows you to detach the camera and fly around freely in Escape From Tarkov.
|
||||||
|
|
||||||
### Controls
|
### Controls
|
||||||
|
|
||||||
For now, the keybinds are non-configurable (unless you change it in code and build from source).
|
The default controls are as follows:
|
||||||
- Keypad Plus - toggle free camera mode
|
- Keypad Plus - toggle free camera mode
|
||||||
- Keypad Enter - teleport player to camera position
|
- Keypad Enter - teleport player to camera position
|
||||||
- Keypad Multiply - toggle UI
|
- Keypad Multiply - toggle UI
|
||||||
|
|
||||||
|
If you need to change them, press F12 in-game and expand the `Freecam #.#.#` section and configure your keybinds there.
|
||||||
|
Alternatively, you can find the `com.terkoiz.freecam.cfg` file in your `BepInEx/config/` folder after you've started up the game at least once with Freecam installed, and change the keybinds there.
|
||||||
|
|
||||||
|
|
||||||
### How to install
|
### How to install
|
||||||
|
|
||||||
1. Download the latest release here: [link](https://dev.sp-tarkov.com/Terkoiz/Freecam/releases) -OR- build from source (instructions below)
|
1. Download the latest release here: [link](https://dev.sp-tarkov.com/Terkoiz/Freecam/releases) -OR- build from source (instructions below)
|
||||||
2. Simply drop the folder `Terkoiz-Freecam` into your SPT-AKI `user/mods/` directory.
|
2. Simply extract the zip file contents into your root SPT-AKI folder (where EscapeFromTarkov.exe is).
|
||||||
|
3. Your `BepInEx/plugins` folder should now contain a `Terkoiz.Freecam.dll` file inside.
|
||||||
|
|
||||||
### Known issues
|
### Known issues
|
||||||
|
|
||||||
1. Your weapon doesn't turn invisible when you enter freecam mode
|
1. When teleporting to camera position, the camera rotation gets copied exactly, potentially causing the player model to tilt
|
||||||
2. When teleporting to camera position, the camera rotation gets copied exactly, potentially causing the player model to tilt
|
2. Game version UI element is not hidden when toggling UI
|
||||||
3. Game version UI element is not hidden when toggling UI
|
3. When flying to distant parts of the map in freecam mode, LODs are not triggered (these seem to follow the player)
|
||||||
4. None of the camera settings (speed, senstivity, etc.) are user-configurable
|
|
||||||
5. When flying to distant parts of the map in freecam mode, LODs are not triggered (these seem to follow the player)
|
|
||||||
|
|
||||||
### How to build from source
|
### How to build from source
|
||||||
|
|
||||||
1. Download/clone this repository
|
1. Download/clone this repository
|
||||||
2. Download/clone the `SPT-AKI/Modules` repository: [link](https://dev.sp-tarkov.com/SPT-AKI/Modules)
|
2. Open your current SPT directory and copy all files from `\EscapeFromTarkov_Data\Managed` into this solution's `\References\EFT_Managed` folder.
|
||||||
3. Move the contents of the `project` folder over to the SPT-AKI Modules `project` folder
|
3. Rebuild the project in the Release configuration.
|
||||||
4. Add the `Terkoiz.Freecam` project to the SPT-AKI Modules solution
|
4. Grab the `Terkoiz.Freecam.dll` file from the `bin/Release` folder and use it wherever. Refer to the "How to install" section if you need help here.
|
||||||
5. Build modules - `Terkoiz.Freecam.dll` should appear under `Build/EscapeFromTarkov_Data/Managed` in the SPT-AKI Modules directory
|
|
||||||
6. Copy the .dll into the `mod/Terkoiz-Freecam` folder and rename to `module.dll`
|
|
||||||
7. That's it, you have a working release of this mod! Follow the `How to install` instructions on how to get the mod into your game
|
|
@ -1,31 +0,0 @@
|
|||||||
Copyright (c) 2021 Martynas Gestautas. All rights reserved.
|
|
||||||
|
|
||||||
Developed by: SPT-Aki
|
|
||||||
Martynas Gestautas
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
|
||||||
obtaining a copy of this software and associated documentation files
|
|
||||||
(the "Software"), to deal with the Software without restriction,
|
|
||||||
including without limitation the rights to use, copy, modify, merge,
|
|
||||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
|
||||||
and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimers.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimers in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the names of Martynas Gestautas, SPT-Aki nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this Software without specific prior written permission.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
|
|
||||||
THE SOFTWARE.
|
|
Binary file not shown.
Binary file not shown.
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Freecam",
|
|
||||||
"author": "Terkoiz",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"license": "NCSA Open Source",
|
|
||||||
"dependencies": {}
|
|
||||||
}
|
|
14
project/NuGet.Config
Normal file
14
project/NuGet.Config
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<packageRestore>
|
||||||
|
<add key="enabled" value="True" />
|
||||||
|
<add key="automatic" value="True" />
|
||||||
|
</packageRestore>
|
||||||
|
<activePackageSource>
|
||||||
|
<add key="All" value="(Aggregate source)" />
|
||||||
|
</activePackageSource>
|
||||||
|
<packageSources>
|
||||||
|
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||||
|
<add key="BepInEx" value="https://nuget.bepinex.dev/v3/index.json" protocolVersion="3" />
|
||||||
|
</packageSources>
|
||||||
|
</configuration>
|
0
project/References/EFT_Managed/.keep
Normal file
0
project/References/EFT_Managed/.keep
Normal file
0
project/References/SPT/.keep
Normal file
0
project/References/SPT/.keep
Normal file
25
project/Terkoiz.Freecam.sln
Normal file
25
project/Terkoiz.Freecam.sln
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.2.32616.157
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Terkoiz.Freecam", "Terkoiz.Freecam\Terkoiz.Freecam.csproj", "{9C38A2B1-5F09-49FE-AC57-9FBEF7717582}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{9C38A2B1-5F09-49FE-AC57-9FBEF7717582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9C38A2B1-5F09-49FE-AC57-9FBEF7717582}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9C38A2B1-5F09-49FE-AC57-9FBEF7717582}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9C38A2B1-5F09-49FE-AC57-9FBEF7717582}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {26F91A8D-3767-457A-821C-F66AFD620885}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
44
project/Terkoiz.Freecam/FallDamagePatch.cs
Normal file
44
project/Terkoiz.Freecam/FallDamagePatch.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using SPT.Reflection.Patching;
|
||||||
|
using EFT.HealthSystem;
|
||||||
|
using HarmonyLib;
|
||||||
|
|
||||||
|
namespace Terkoiz.Freecam
|
||||||
|
{
|
||||||
|
public class FallDamagePatch : ModulePatch
|
||||||
|
{
|
||||||
|
internal static bool HasTeleported;
|
||||||
|
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.Method(typeof(ActiveHealthController), nameof(ActiveHealthController.HandleFall));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPrefix]
|
||||||
|
public static bool PatchPrefix(ActiveHealthController __instance, float height)
|
||||||
|
{
|
||||||
|
// WARNING: The 'HandleFall' method gets called every frame for every player and AI in a raid. Be very careful with logging or expensive operations in this prefix patch!
|
||||||
|
|
||||||
|
// Check if it's our own player, or if a Player property even exists
|
||||||
|
if (__instance.Player?.IsAI ?? true)
|
||||||
|
{
|
||||||
|
return true; // Run original method
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global fall damage flag overrides everything
|
||||||
|
if (FreecamPlugin.GlobalDisableFallDamage.Value)
|
||||||
|
{
|
||||||
|
return false; // Prevent original method from running
|
||||||
|
}
|
||||||
|
|
||||||
|
// If smart fall damage flag is enabled, check if we've recently teleported and if the fall height value was positive
|
||||||
|
if (FreecamPlugin.SmartDisableFallDamage.Value && HasTeleported && height > 0)
|
||||||
|
{
|
||||||
|
HasTeleported = false;
|
||||||
|
return false; // Prevent original method from running
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // Run original method
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,103 +1,92 @@
|
|||||||
using UnityEngine;
|
using JetBrains.Annotations;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Terkoiz.Freecam
|
namespace Terkoiz.Freecam
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A simple free camera to be added to a Unity game object.
|
/// A simple free camera to be added to a Unity game object.
|
||||||
///
|
///
|
||||||
/// Full credit to Ashley Davis on GitHub for the inital code:
|
/// Full credit to Ashley Davis on GitHub for the initial code:
|
||||||
/// https://gist.github.com/ashleydavis/f025c03a9221bc840a2b
|
/// https://gist.github.com/ashleydavis/f025c03a9221bc840a2b
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Freecam : MonoBehaviour
|
public class Freecam : MonoBehaviour
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Normal speed of camera movement.
|
|
||||||
/// </summary>
|
|
||||||
public float MovementSpeed = 10f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Speed of camera movement when shift is held down.
|
|
||||||
/// </summary>
|
|
||||||
public float FastMovementSpeed = 100f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sensitivity for free look.
|
|
||||||
/// </summary>
|
|
||||||
public float FreeLookSensitivity = 3f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Amount to zoom the camera when using the mouse wheel.
|
|
||||||
/// </summary>
|
|
||||||
public float ZoomSensitivity = 10f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Amount to zoom the camera when using the mouse wheel (fast mode).
|
|
||||||
/// </summary>
|
|
||||||
public float FastZoomSensitivity = 50f;
|
|
||||||
|
|
||||||
public bool IsActive = false;
|
public bool IsActive = false;
|
||||||
|
|
||||||
void Update()
|
[UsedImplicitly]
|
||||||
|
public void Update()
|
||||||
{
|
{
|
||||||
if (!IsActive)
|
if (!IsActive)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fastMode = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
|
var fastMode = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
|
||||||
var movementSpeed = fastMode ? FastMovementSpeed : MovementSpeed;
|
var movementSpeed = fastMode ? FreecamPlugin.CameraFastMoveSpeed.Value : FreecamPlugin.CameraMoveSpeed.Value;
|
||||||
|
|
||||||
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
|
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
|
||||||
{
|
{
|
||||||
transform.position += (-transform.right * movementSpeed * Time.deltaTime);
|
transform.position += (-transform.right * (movementSpeed * Time.deltaTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
|
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
|
||||||
{
|
{
|
||||||
transform.position += (transform.right * movementSpeed * Time.deltaTime);
|
transform.position += (transform.right * (movementSpeed * Time.deltaTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
|
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
|
||||||
{
|
{
|
||||||
transform.position += (transform.forward * movementSpeed * Time.deltaTime);
|
transform.position += (transform.forward * (movementSpeed * Time.deltaTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
|
if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
|
||||||
{
|
{
|
||||||
transform.position += (-transform.forward * movementSpeed * Time.deltaTime);
|
transform.position += (-transform.forward * (movementSpeed * Time.deltaTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Input.GetKey(KeyCode.Q))
|
if (FreecamPlugin.CameraHeightMovement.Value)
|
||||||
{
|
{
|
||||||
transform.position += (transform.up * movementSpeed * Time.deltaTime);
|
if (Input.GetKey(KeyCode.Q))
|
||||||
|
{
|
||||||
|
transform.position += (transform.up * (movementSpeed * Time.deltaTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input.GetKey(KeyCode.E))
|
||||||
|
{
|
||||||
|
transform.position += (-transform.up * (movementSpeed * Time.deltaTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input.GetKey(KeyCode.R) || Input.GetKey(KeyCode.PageUp))
|
||||||
|
{
|
||||||
|
transform.position += (Vector3.up * (movementSpeed * Time.deltaTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input.GetKey(KeyCode.F) || Input.GetKey(KeyCode.PageDown))
|
||||||
|
{
|
||||||
|
transform.position += (-Vector3.up * (movementSpeed * Time.deltaTime));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Input.GetKey(KeyCode.E))
|
float newRotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * FreecamPlugin.CameraLookSensitivity.Value;
|
||||||
{
|
float newRotationY = transform.localEulerAngles.x - Input.GetAxis("Mouse Y") * FreecamPlugin.CameraLookSensitivity.Value;
|
||||||
transform.position += (-transform.up * movementSpeed * Time.deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Input.GetKey(KeyCode.R) || Input.GetKey(KeyCode.PageUp))
|
|
||||||
{
|
|
||||||
transform.position += (Vector3.up * movementSpeed * Time.deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Input.GetKey(KeyCode.F) || Input.GetKey(KeyCode.PageDown))
|
|
||||||
{
|
|
||||||
transform.position += (-Vector3.up * movementSpeed * Time.deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
float newRotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * FreeLookSensitivity;
|
|
||||||
float newRotationY = transform.localEulerAngles.x - Input.GetAxis("Mouse Y") * FreeLookSensitivity;
|
|
||||||
transform.localEulerAngles = new Vector3(newRotationY, newRotationX, 0f);
|
transform.localEulerAngles = new Vector3(newRotationY, newRotationX, 0f);
|
||||||
|
|
||||||
float axis = Input.GetAxis("Mouse ScrollWheel");
|
if (FreecamPlugin.CameraMousewheelZoom.Value)
|
||||||
if (axis != 0)
|
|
||||||
{
|
{
|
||||||
var zoomSensitivity = fastMode ? FastZoomSensitivity : ZoomSensitivity;
|
float axis = Input.GetAxis("Mouse ScrollWheel");
|
||||||
transform.position += transform.forward * axis * zoomSensitivity;
|
if (axis != 0)
|
||||||
|
{
|
||||||
|
var zoomSensitivity = fastMode ? FreecamPlugin.CameraFastZoomSpeed.Value : FreecamPlugin.CameraZoomSpeed.Value;
|
||||||
|
transform.position += transform.forward * (axis * zoomSensitivity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
Destroy(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,42 +1,79 @@
|
|||||||
using Comfort.Common;
|
using Comfort.Common;
|
||||||
using EFT;
|
using EFT;
|
||||||
|
using EFT.CameraControl;
|
||||||
using EFT.UI;
|
using EFT.UI;
|
||||||
|
using HarmonyLib;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Terkoiz.Freecam
|
namespace Terkoiz.Freecam
|
||||||
{
|
{
|
||||||
public class FreecamController : MonoBehaviour
|
public class FreecamController : MonoBehaviour
|
||||||
{
|
{
|
||||||
private GameObject mainCamera;
|
private GameObject _mainCamera;
|
||||||
private Freecam freeCamScript;
|
private Freecam _freeCamScript;
|
||||||
|
|
||||||
private BattleUIScreen playerUi;
|
private EftBattleUIScreen _playerUi;
|
||||||
private bool uiHidden;
|
private bool _uiHidden;
|
||||||
|
|
||||||
// TODO:
|
private GamePlayerOwner _gamePlayerOwner;
|
||||||
// Menu for adjusting settings
|
|
||||||
// Config file for default settings
|
|
||||||
// Configurable keybinds
|
|
||||||
|
|
||||||
// TODO MAYBE:
|
private Vector3? _lastPosition;
|
||||||
// Hide player weapon
|
private Quaternion? _lastRotation;
|
||||||
// Hide version number UI element
|
|
||||||
// FreeCam controller support (camera could be smoother with an analog stick, apparently)
|
|
||||||
// Adjusting speed/sensitivity without a menu (Ctrl+ScrollWheel for example)
|
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
// Get Main Camera
|
||||||
|
_mainCamera = GetLocalPlayerFromWorld().GetComponent<PlayerCameraController>().Camera.gameObject;
|
||||||
|
if (_mainCamera == null)
|
||||||
|
{
|
||||||
|
FreecamPlugin.Logger.LogError("Failed to locate main camera");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Player UI
|
||||||
|
_playerUi = Singleton<CommonUI>.Instance.EftBattleUIScreen;
|
||||||
|
if (_playerUi == null)
|
||||||
|
{
|
||||||
|
FreecamPlugin.Logger.LogError("Failed to locate player UI");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add Freecam script to main camera in scene
|
||||||
|
_freeCamScript = _mainCamera.AddComponent<Freecam>();
|
||||||
|
if (_freeCamScript == null)
|
||||||
|
{
|
||||||
|
FreecamPlugin.Logger.LogError("Failed to add Freecam script to Camera");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get GamePlayerOwner component
|
||||||
|
_gamePlayerOwner = GetLocalPlayerFromWorld().GetComponentInChildren<GamePlayerOwner>();
|
||||||
|
if (_gamePlayerOwner == null)
|
||||||
|
{
|
||||||
|
FreecamPlugin.Logger.LogError("Failed to locate GamePlayerOwner");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
if (Input.GetKeyDown(KeyCode.KeypadMultiply))
|
if (FreecamPlugin.ToggleUi.Value.IsDown())
|
||||||
{
|
{
|
||||||
ToggleUi();
|
ToggleUi();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Input.GetKeyDown(KeyCode.KeypadPlus))
|
if (FreecamPlugin.ToggleFreecamMode.Value.IsDown())
|
||||||
{
|
{
|
||||||
ToggleCamera();
|
ToggleCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Input.GetKeyDown(KeyCode.KeypadEnter))
|
if (FreecamPlugin.ToggleFreecamControls.Value.IsDown())
|
||||||
|
{
|
||||||
|
ToggleCameraControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FreecamPlugin.TeleportToCamera.Value.IsDown())
|
||||||
{
|
{
|
||||||
MovePlayerToCamera();
|
MovePlayerToCamera();
|
||||||
}
|
}
|
||||||
@ -50,41 +87,15 @@ namespace Terkoiz.Freecam
|
|||||||
// Get our own Player instance. Null means we're not in a raid
|
// Get our own Player instance. Null means we're not in a raid
|
||||||
var localPlayer = GetLocalPlayerFromWorld();
|
var localPlayer = GetLocalPlayerFromWorld();
|
||||||
if (localPlayer == null)
|
if (localPlayer == null)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// If we don't have the main camera object cached, go look for it in the scene
|
if (!_freeCamScript.IsActive)
|
||||||
if (mainCamera == null)
|
|
||||||
{
|
{
|
||||||
// Finding a GameObject by name directly is apparantly better than searching for objects of a type.
|
SetPlayerToFreecamMode(localPlayer);
|
||||||
// 'FPS Camera' is our main camera instance - so we just grab that
|
|
||||||
mainCamera = GameObject.Find("FPS Camera");
|
|
||||||
if (mainCamera == null)
|
|
||||||
{
|
|
||||||
Debug.LogError("Terkoiz.Freecam: ERROR: Failed to locate main camera");
|
|
||||||
PreloaderUI.Instance.Console.AddLog("ERROR: Failed to locate main camera", "FreeCam");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the Freecam script and attach it to the main camera
|
|
||||||
if (freeCamScript == null)
|
|
||||||
{
|
|
||||||
freeCamScript = mainCamera.AddComponent<Freecam>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// We disable the player's GameObject, which prevents the player from moving and interacting with the world while we're in Freecam mode
|
|
||||||
// Also, since the camera position keeps getting updated to where the player is, disabling the player's GameObject also stops this behaviour
|
|
||||||
if (!freeCamScript.IsActive)
|
|
||||||
{
|
|
||||||
localPlayer.gameObject.SetActive(false);
|
|
||||||
freeCamScript.IsActive = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
freeCamScript.IsActive = false;
|
SetPlayerToFirstPersonMode(localPlayer);
|
||||||
localPlayer.gameObject.SetActive(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,24 +106,20 @@ namespace Terkoiz.Freecam
|
|||||||
{
|
{
|
||||||
var localPlayer = GetLocalPlayerFromWorld();
|
var localPlayer = GetLocalPlayerFromWorld();
|
||||||
if (localPlayer == null)
|
if (localPlayer == null)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// If we don't have the main camera cached, it means we have yet to enter Freecam mode and there is nowhere to teleport to
|
// Move the player to the camera's current position and switch to First Person mode
|
||||||
if (mainCamera == null)
|
if (_freeCamScript.IsActive)
|
||||||
{
|
{
|
||||||
return;
|
// Tell the fall damage patch that we just teleported. Used for the "smart" fall damage prevention feature
|
||||||
}
|
FallDamagePatch.HasTeleported = true;
|
||||||
|
|
||||||
// We basically do what ToggleCamera() does, but with extra code inbetween
|
|
||||||
if (freeCamScript.IsActive)
|
|
||||||
{
|
|
||||||
freeCamScript.IsActive = false;
|
|
||||||
// We grab the camera's position, but we subtract a bit off the Y axis, because the players coordinate origin is at the feet
|
// We grab the camera's position, but we subtract a bit off the Y axis, because the players coordinate origin is at the feet
|
||||||
var position = new Vector3(mainCamera.transform.position.x, mainCamera.transform.position.y - 1.8f, mainCamera.transform.position.z);
|
var position = new Vector3(_mainCamera.transform.position.x, _mainCamera.transform.position.y - 1.8f, _mainCamera.transform.position.z);
|
||||||
localPlayer.gameObject.transform.SetPositionAndRotation(position, mainCamera.transform.rotation);
|
localPlayer.gameObject.transform.SetPositionAndRotation(position, Quaternion.Euler(0, _mainCamera.transform.rotation.y, 0));
|
||||||
localPlayer.gameObject.SetActive(true);
|
|
||||||
|
// localPlayer.gameObject.transform.SetPositionAndRotation(position, _mainCamera.transform.rotation);
|
||||||
|
SetPlayerToFirstPersonMode(localPlayer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,41 +130,112 @@ namespace Terkoiz.Freecam
|
|||||||
{
|
{
|
||||||
// Check if we're currently in a raid
|
// Check if we're currently in a raid
|
||||||
if (GetLocalPlayerFromWorld() == null)
|
if (GetLocalPlayerFromWorld() == null)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// If we don't have the UI Component cached, go look for it in the scene
|
_playerUi.gameObject.SetActive(_uiHidden);
|
||||||
if (playerUi == null)
|
_uiHidden = !_uiHidden;
|
||||||
{
|
|
||||||
playerUi = GameObject.Find("BattleUIScreen").GetComponent<BattleUIScreen>();
|
|
||||||
|
|
||||||
if (playerUi == null)
|
|
||||||
{
|
|
||||||
PreloaderUI.Instance.Console.AddLog("ERROR: Failed to locate player UI", "FreeCam");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
playerUi.gameObject.SetActive(uiHidden);
|
|
||||||
uiHidden = !uiHidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A helper method to set the Player into Freecam mode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localPlayer"></param>
|
||||||
|
private void SetPlayerToFreecamMode(Player localPlayer)
|
||||||
|
{
|
||||||
|
// We set the player to third person mode, but then we want set the camera to freecam mode
|
||||||
|
// This means our character will be fully visible, while letting the camera move freely
|
||||||
|
// Setting the player point of view directly to Freecam seems to hide the head and arms of the character, which is not desirable
|
||||||
|
|
||||||
|
localPlayer.PointOfView = EPointOfView.ThirdPerson;
|
||||||
|
|
||||||
|
// Get the PlayerBody reference. It's a protected field, so we have to use traverse to fetch it
|
||||||
|
var playerBody = Traverse.Create(localPlayer).Field<PlayerBody>("_playerBody").Value;
|
||||||
|
if (playerBody != null)
|
||||||
|
{
|
||||||
|
// We tell the PlayerBody class that it's in FreeCamera mode, and force an update of the Camera Controller view mode
|
||||||
|
// Setting the PointOfView.Value directly skips all the code that would usually change how the player body is rendered
|
||||||
|
playerBody.PointOfView.Value = EPointOfView.FreeCamera;
|
||||||
|
localPlayer.GetComponent<PlayerCameraController>().UpdatePointOfView();
|
||||||
|
|
||||||
|
// All we really needed to do, was trigger the UpdatePointOfView method and have it update to the FreeCam state
|
||||||
|
// There's no easy way of doing this without patching the method, and even then it might be a bloated solution
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FreecamPlugin.Logger.LogError("Failed to get the PlayerBody field");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instead of Detouring, just turn off _gamePlayerOwner which takes the input
|
||||||
|
_gamePlayerOwner.enabled = false;
|
||||||
|
|
||||||
|
if (FreecamPlugin.CameraRememberLastPosition.Value && _lastPosition != null && _lastRotation != null)
|
||||||
|
{
|
||||||
|
_mainCamera.transform.position = _lastPosition.Value;
|
||||||
|
_mainCamera.transform.rotation = _lastRotation.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
_freeCamScript.IsActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A helper method to reset the player view back to First Person
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localPlayer"></param>
|
||||||
|
private void SetPlayerToFirstPersonMode(Player localPlayer)
|
||||||
|
{
|
||||||
|
_freeCamScript.IsActive = false;
|
||||||
|
|
||||||
|
if (FreecamPlugin.CameraRememberLastPosition.Value)
|
||||||
|
{
|
||||||
|
_lastPosition = _mainCamera.transform.position;
|
||||||
|
_lastRotation = _mainCamera.transform.rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// re-enable _gamePlayerOwner
|
||||||
|
_gamePlayerOwner.enabled = true;
|
||||||
|
|
||||||
|
localPlayer.PointOfView = EPointOfView.FirstPerson;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A helper method to toggle the Freecam Camera Controls
|
||||||
|
/// </summary>
|
||||||
|
private void ToggleCameraControls()
|
||||||
|
{
|
||||||
|
if (_freeCamScript.IsActive)
|
||||||
|
{
|
||||||
|
_freeCamScript.IsActive = false;
|
||||||
|
_gamePlayerOwner.enabled = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_freeCamScript.IsActive = true;
|
||||||
|
_gamePlayerOwner.enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the current <see cref="Player"/> instance if it's available
|
/// Gets the current <see cref="Player"/> instance if it's available
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Local <see cref="Player"/> instance; returns null if the game is not in raid</returns>
|
/// <returns>Local <see cref="Player"/> instance; returns null if the game is not in raid</returns>
|
||||||
private static Player GetLocalPlayerFromWorld()
|
private Player GetLocalPlayerFromWorld()
|
||||||
{
|
{
|
||||||
// If the GameWorld instance is null or has no RegisteredPlayers, it most likely means we're not in a raid
|
// If the GameWorld instance is null or has no RegisteredPlayers, it most likely means we're not in a raid
|
||||||
var gameWorld = Singleton<GameWorld>.Instance;
|
var gameWorld = Singleton<GameWorld>.Instance;
|
||||||
if (gameWorld == null || gameWorld.RegisteredPlayers == null)
|
if (gameWorld == null || gameWorld.MainPlayer == null)
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
// One of the RegisterdPlayers will have the IsYourPlayer flag set, which will be our own Player instance
|
// One of the RegisteredPlayers will have the IsYourPlayer flag set, which will be our own Player instance
|
||||||
return gameWorld.RegisteredPlayers.Find(p => p.IsYourPlayer);
|
return gameWorld.MainPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
public void OnDestroy()
|
||||||
|
{
|
||||||
|
// Destroy FreeCamScript before FreeCamController if exists
|
||||||
|
Destroy(_freeCamScript);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
28
project/Terkoiz.Freecam/FreecamPatch.cs
Normal file
28
project/Terkoiz.Freecam/FreecamPatch.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using SPT.Reflection.Patching;
|
||||||
|
using Comfort.Common;
|
||||||
|
using EFT;
|
||||||
|
using HarmonyLib;
|
||||||
|
|
||||||
|
namespace Terkoiz.Freecam
|
||||||
|
{
|
||||||
|
public class FreecamPatch : ModulePatch
|
||||||
|
{
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.Method(typeof(GameWorld), nameof(GameWorld.OnGameStarted));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PatchPostfix]
|
||||||
|
public static void PatchPostFix()
|
||||||
|
{
|
||||||
|
var gameWorld = Singleton<GameWorld>.Instance;
|
||||||
|
|
||||||
|
if (gameWorld == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Add FreecamController to GameWorld GameObject
|
||||||
|
gameWorld.gameObject.AddComponent<FreecamController>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
149
project/Terkoiz.Freecam/FreecamPlugin.cs
Normal file
149
project/Terkoiz.Freecam/FreecamPlugin.cs
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
using BepInEx;
|
||||||
|
using BepInEx.Configuration;
|
||||||
|
using BepInEx.Logging;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using UnityEngine;
|
||||||
|
using KeyboardShortcut = BepInEx.Configuration.KeyboardShortcut;
|
||||||
|
|
||||||
|
namespace Terkoiz.Freecam
|
||||||
|
{
|
||||||
|
[BepInPlugin("com.terkoiz.freecam", "Terkoiz.Freecam", "1.4.4")]
|
||||||
|
public class FreecamPlugin : BaseUnityPlugin
|
||||||
|
{
|
||||||
|
internal new static ManualLogSource Logger { get; private set; }
|
||||||
|
|
||||||
|
// Fall damage config entries
|
||||||
|
private const string FallDamageSectionName = "Fall Damage";
|
||||||
|
internal static ConfigEntry<bool> GlobalDisableFallDamage;
|
||||||
|
internal static ConfigEntry<bool> SmartDisableFallDamage;
|
||||||
|
|
||||||
|
// Keyboard shortcut config entries
|
||||||
|
private const string KeybindSectionName = "Keybinds";
|
||||||
|
internal static ConfigEntry<KeyboardShortcut> ToggleFreecamMode;
|
||||||
|
internal static ConfigEntry<KeyboardShortcut> ToggleFreecamControls;
|
||||||
|
internal static ConfigEntry<KeyboardShortcut> TeleportToCamera;
|
||||||
|
internal static ConfigEntry<KeyboardShortcut> ToggleUi;
|
||||||
|
|
||||||
|
// Camera settings config entries
|
||||||
|
private const string CameraSettingsSectionName = "Camera Settings";
|
||||||
|
internal static ConfigEntry<float> CameraMoveSpeed;
|
||||||
|
internal static ConfigEntry<float> CameraFastMoveSpeed;
|
||||||
|
internal static ConfigEntry<float> CameraLookSensitivity;
|
||||||
|
internal static ConfigEntry<float> CameraZoomSpeed;
|
||||||
|
internal static ConfigEntry<float> CameraFastZoomSpeed;
|
||||||
|
|
||||||
|
// General toggles
|
||||||
|
private const string TogglesSectionName = "Toggles";
|
||||||
|
internal static ConfigEntry<bool> CameraHeightMovement;
|
||||||
|
internal static ConfigEntry<bool> CameraMousewheelZoom;
|
||||||
|
internal static ConfigEntry<bool> CameraRememberLastPosition;
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
internal void Start()
|
||||||
|
{
|
||||||
|
Logger = base.Logger;
|
||||||
|
InitConfiguration();
|
||||||
|
|
||||||
|
new FreecamPatch().Enable();
|
||||||
|
new FallDamagePatch().Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitConfiguration()
|
||||||
|
{
|
||||||
|
GlobalDisableFallDamage = Config.Bind(
|
||||||
|
FallDamageSectionName,
|
||||||
|
"Globally Disable Fall Damage",
|
||||||
|
false,
|
||||||
|
"Completely disables fall damage. This is the safest option for using freecam. Will fully override the 'Smart Fall Damage Prevention' setting.");
|
||||||
|
|
||||||
|
SmartDisableFallDamage = Config.Bind(
|
||||||
|
FallDamageSectionName,
|
||||||
|
"Smart Fall Damage Prevention",
|
||||||
|
true,
|
||||||
|
"Fall damage will only be disabled after using teleport, until your player lands. Less cheat-y way to save yourself from fall damage, but might sometimes be unreliable.");
|
||||||
|
|
||||||
|
ToggleFreecamMode = Config.Bind(
|
||||||
|
KeybindSectionName,
|
||||||
|
"Toggle Freecam",
|
||||||
|
new KeyboardShortcut(KeyCode.KeypadPlus),
|
||||||
|
"The keyboard shortcut that toggles Freecam");
|
||||||
|
|
||||||
|
ToggleFreecamControls = Config.Bind(
|
||||||
|
KeybindSectionName,
|
||||||
|
"Toggle Freecam Controls",
|
||||||
|
new KeyboardShortcut(KeyCode.KeypadPeriod),
|
||||||
|
"The keyboard shortcut that toggles Freecam Controls");
|
||||||
|
|
||||||
|
TeleportToCamera = Config.Bind(
|
||||||
|
KeybindSectionName,
|
||||||
|
"Teleport To Camera",
|
||||||
|
new KeyboardShortcut(KeyCode.KeypadEnter),
|
||||||
|
"The keyboard shortcut that teleports the player to camera position");
|
||||||
|
|
||||||
|
ToggleUi = Config.Bind(
|
||||||
|
KeybindSectionName,
|
||||||
|
"Toggle UI",
|
||||||
|
new KeyboardShortcut(KeyCode.KeypadMultiply),
|
||||||
|
"The keyboard shortcut that toggles the game UI");
|
||||||
|
|
||||||
|
CameraMoveSpeed = Config.Bind(
|
||||||
|
CameraSettingsSectionName,
|
||||||
|
"Camera Speed",
|
||||||
|
10f,
|
||||||
|
new ConfigDescription(
|
||||||
|
"The speed at which the camera will move normally",
|
||||||
|
new AcceptableValueRange<float>(0.01f, 100f)));
|
||||||
|
|
||||||
|
CameraFastMoveSpeed = Config.Bind(
|
||||||
|
CameraSettingsSectionName,
|
||||||
|
"Camera Sprint Speed",
|
||||||
|
100f,
|
||||||
|
new ConfigDescription(
|
||||||
|
"The speed at which the camera will move when the Shift key is held down",
|
||||||
|
new AcceptableValueRange<float>(0.01f, 1000f)));
|
||||||
|
|
||||||
|
CameraLookSensitivity = Config.Bind(
|
||||||
|
CameraSettingsSectionName,
|
||||||
|
"Camera Mouse Sensitivity",
|
||||||
|
3f,
|
||||||
|
new ConfigDescription(
|
||||||
|
"Camera free look mouse sensitivity",
|
||||||
|
new AcceptableValueRange<float>(0.1f, 10f)));
|
||||||
|
|
||||||
|
CameraZoomSpeed = Config.Bind(
|
||||||
|
CameraSettingsSectionName,
|
||||||
|
"Camera Zoom Speed",
|
||||||
|
10f,
|
||||||
|
new ConfigDescription(
|
||||||
|
"Amount to zoom the camera when using the mouse wheel",
|
||||||
|
new AcceptableValueRange<float>(0.01f, 100f)));
|
||||||
|
|
||||||
|
CameraFastZoomSpeed = Config.Bind(
|
||||||
|
CameraSettingsSectionName,
|
||||||
|
"Camera Zoom Sprint Speed",
|
||||||
|
50f,
|
||||||
|
new ConfigDescription(
|
||||||
|
"Amount to zoom the camera when using the mouse wheel while holding Shift",
|
||||||
|
new AcceptableValueRange<float>(0.01f, 1000f)));
|
||||||
|
|
||||||
|
CameraHeightMovement = Config.Bind(
|
||||||
|
TogglesSectionName,
|
||||||
|
"Camera Height Movement Keys",
|
||||||
|
true,
|
||||||
|
"Enables or disables the camera height movement keys, which default to Q, E, R, F." +
|
||||||
|
" \nUseful to disable if you want to let your character lean in Freecam mode");
|
||||||
|
|
||||||
|
CameraMousewheelZoom = Config.Bind(
|
||||||
|
TogglesSectionName,
|
||||||
|
"Camera Mousewheel Zoom",
|
||||||
|
true,
|
||||||
|
"Enables or disables camera movement on mousewheel scroll. Just in case you find it annoying and want that disabled.");
|
||||||
|
|
||||||
|
CameraRememberLastPosition = Config.Bind(
|
||||||
|
TogglesSectionName,
|
||||||
|
"Remember Last Camera Position",
|
||||||
|
false,
|
||||||
|
"If enabled, returning to Freecam mode will put the camera to it's last position which is saved when exiting Freecam mode.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Terkoiz.Freecam
|
|
||||||
{
|
|
||||||
public class Program
|
|
||||||
{
|
|
||||||
private static GameObject HookObject;
|
|
||||||
|
|
||||||
static void Main(string[] args)
|
|
||||||
{
|
|
||||||
Debug.LogError("Terkoiz.Freecam: Loading...");
|
|
||||||
HookObject = new GameObject();
|
|
||||||
HookObject.AddComponent<FreecamController>();
|
|
||||||
Object.DontDestroyOnLoad(HookObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
[assembly: AssemblyTitle("Terkoiz.Freecam")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Terkoiz.Freecam")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © 2021")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
|
||||||
// to COM components. If you need to access a type in this assembly from
|
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|
||||||
[assembly: Guid("be2de623-48ff-4807-9696-167a17787718")]
|
|
||||||
|
|
||||||
// Version information for an assembly consists of the following four values:
|
|
||||||
//
|
|
||||||
// Major Version
|
|
||||||
// Minor Version
|
|
||||||
// Build Number
|
|
||||||
// Revision
|
|
||||||
//
|
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
|
||||||
// by using the '*' as shown below:
|
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -1,93 +1,48 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<TargetFramework>net471</TargetFramework>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Version>1.4.4</Version>
|
||||||
<ProjectGuid>{BE2DE623-48FF-4807-9696-167A17787718}</ProjectGuid>
|
<Authors>Terkoiz, Kobrakon, CWX</Authors>
|
||||||
<OutputType>Library</OutputType>
|
<RepositoryUrl>https://dev.sp-tarkov.com/Terkoiz/Freecam</RepositoryUrl>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<PackageLicenseExpression>NCSA</PackageLicenseExpression>
|
||||||
<RootNamespace>Terkoiz.Freecam</RootNamespace>
|
|
||||||
<AssemblyName>Terkoiz.Freecam</AssemblyName>
|
|
||||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<Deterministic>true</Deterministic>
|
|
||||||
<TargetFrameworkProfile />
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<SignAssembly>true</SignAssembly>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="0Harmony">
|
<PackageReference Include="BepInEx.Core" Version="5.4.21">
|
||||||
<HintPath>..\Shared\References\0Harmony.dll</HintPath>
|
<ExcludeAssets>runtime</ExcludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Aki.Reflection">
|
||||||
|
<HintPath>..\References\SPT\spt-reflection.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Assembly-CSharp">
|
<Reference Include="Assembly-CSharp">
|
||||||
<HintPath>..\Shared\References\Assembly-CSharp.dll</HintPath>
|
<HintPath>..\References\EFT_Managed\Assembly-CSharp.dll</HintPath>
|
||||||
<Private>False</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="ItemComponent.Types">
|
|
||||||
<HintPath>..\Shared\References\ItemComponent.Types.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Comfort">
|
<Reference Include="Comfort">
|
||||||
<HintPath>..\Shared\References\Comfort.dll</HintPath>
|
<HintPath>..\References\EFT_Managed\Comfort.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Comfort.Unity">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<HintPath>..\References\EFT_Managed\Comfort.Unity.dll</HintPath>
|
||||||
<HintPath>..\Shared\References\Newtonsoft.Json.dll</HintPath>
|
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="UnityEngine">
|
<Reference Include="UnityEngine">
|
||||||
<HintPath>..\Shared\References\UnityEngine.dll</HintPath>
|
<HintPath>..\References\EFT_Managed\UnityEngine.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="UnityEngine.CoreModule">
|
<Reference Include="UnityEngine.CoreModule">
|
||||||
<HintPath>..\Shared\References\UnityEngine.CoreModule.dll</HintPath>
|
<HintPath>..\References\EFT_Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="UnityEngine.PhysicsModule">
|
<Reference Include="UnityEngine.InputLegacyModule">
|
||||||
<HintPath>..\Shared\References\UnityEngine.PhysicsModule.dll</HintPath>
|
<HintPath>..\References\EFT_Managed\UnityEngine.InputLegacyModule.dll</HintPath>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="Freecam.cs" />
|
</Project>
|
||||||
<Compile Include="FreecamController.cs" />
|
|
||||||
<Compile Include="Program.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Aki.Common\Aki.Common.csproj">
|
|
||||||
<Project>{7584f43a-5937-417e-abf4-c5f680f300fb}</Project>
|
|
||||||
<Name>Aki.Common</Name>
|
|
||||||
<Private>False</Private>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="key.snk" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
</Project>
|
|
||||||
|
Reference in New Issue
Block a user