├── .editorconfig ├── .gitattributes ├── olmod ├── stdafx.cpp ├── olmodserver.bat ├── olmod.h ├── olmodserverinet.bat ├── olmod.ico ├── olmod.rc ├── small.ico ├── targetver.h ├── resource.h ├── stdafx.h └── olmod.vcxproj.filters ├── PoorMansProfiler ├── .gitignore ├── pmp_heat.sh ├── Makefile └── pmp-filters.txt ├── linux ├── olmodserver.sh ├── olmodserverinet.sh ├── makefile ├── olmod.sh └── mono_build.sh ├── GameMod ├── 0Harmony.dll ├── Resources │ └── meshes ├── Directory.Build.targets ├── olmodsettings.json ├── MPHUDMessage.cs ├── AmbientUnload.cs ├── MPUnlockAll.cs ├── MPTriggers.cs ├── ServerPort.cs ├── MPCeiling.cs ├── MPIPLogging.cs ├── Boss2B.cs ├── MPSuperCheck.cs ├── MPLongPwd.cs ├── MPDeathRollSync.cs ├── MPMatchTimeLimits.cs ├── MPPwdPaste.cs ├── ExitCutscene.cs ├── MPTeamsEnemyArrow.cs ├── MPPickupCheck.cs ├── MPSpawnInitialization.cs ├── VRScale.cs ├── GSyncFix.cs ├── MPItemSpawns.cs ├── PrevWeaponFix.cs ├── DisableProfanityFilter.cs ├── MPNoNewWeaponSound.cs ├── MPSpawnInvuln.cs ├── MPReduceJoinTimeout.cs ├── CrusherTrails.cs ├── Properties │ └── AssemblyInfo.cs ├── MPNoDupes.cs ├── HUDVelocity.cs ├── CustomDoorAutomap.cs ├── MPNegativeKills.cs ├── MPMonoDNSFix.cs ├── MPOpponentCockpits.cs ├── MPDoors.cs ├── MPAlwaysCloaked.cs ├── UIMeshColliderNoRender.cs ├── AxisCountFix.cs ├── MPAnticheat.cs ├── MouseSlidingFix.cs ├── SPThunderboltShakeFix.cs ├── ServerTrackerPost.cs ├── MPDamageEffects.cs ├── Config.cs ├── DisableTimeCheat.cs ├── VSync.cs ├── FixWidescreenDeathBars.cs ├── Shaders.cs ├── MessageTypes.cs ├── LevelError.cs ├── MusicCustom.cs ├── MPCloak.cs ├── MatcenHp.cs ├── MPContinue.cs ├── AddOnLevelSort.cs ├── CustomLevelResources.cs ├── ReversePatches.cs ├── MoreAudio.cs ├── VersionHandling │ ├── OlmodVersion.cs │ └── PatchVersionInfo.cs ├── MPThunderboltPassthrough.cs ├── FrameTime.cs ├── MPSmash.cs ├── ServerPing.cs ├── MPSpew.cs ├── MPAutomap.cs ├── MPLavaTrack.cs ├── FastLoad.cs ├── MPProjInit.cs ├── MPDirectionalWarning.cs ├── ServerCleanup.cs ├── MPShips.cs ├── RearView.cs ├── MPSkipClientResimulation.cs ├── MPFixGhostProjectiles.cs ├── MPDeathExplosion.cs ├── MPColliderSwap.cs ├── MPValidatePlayerNames.cs ├── MPCustomModeFile.cs └── MatchmakerLog.cs ├── .gitignore ├── OLModUnitTest ├── packages.config ├── Properties │ └── AssemblyInfo.cs └── HelperClasses │ └── FakeGameList.cs ├── LICENSE ├── olgetdata ├── Properties │ └── AssemblyInfo.cs └── olgetdata.csproj └── olmod.sln /.editorconfig: -------------------------------------------------------------------------------- 1 | end_of_line = lf 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sh text eol=lf 2 | -------------------------------------------------------------------------------- /olmod/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | -------------------------------------------------------------------------------- /PoorMansProfiler/.gitignore: -------------------------------------------------------------------------------- 1 | pmp_heat 2 | 3 | -------------------------------------------------------------------------------- /olmod/olmodserver.bat: -------------------------------------------------------------------------------- 1 | "olmod" -nographics -batchmode 2 | -------------------------------------------------------------------------------- /olmod/olmod.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | -------------------------------------------------------------------------------- /olmod/olmodserverinet.bat: -------------------------------------------------------------------------------- 1 | "olmod" -nographics -batchmode -internet 2 | -------------------------------------------------------------------------------- /linux/olmodserver.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec `dirname $0`/olmod.sh -nographics -batchmode "$@" 3 | -------------------------------------------------------------------------------- /olmod/olmod.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overload-development-community/olmod/HEAD/olmod/olmod.ico -------------------------------------------------------------------------------- /olmod/olmod.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overload-development-community/olmod/HEAD/olmod/olmod.rc -------------------------------------------------------------------------------- /olmod/small.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overload-development-community/olmod/HEAD/olmod/small.ico -------------------------------------------------------------------------------- /linux/olmodserverinet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec `dirname $0`/olmod.sh -nographics -batchmode -internet "$@" 3 | -------------------------------------------------------------------------------- /GameMod/0Harmony.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overload-development-community/olmod/HEAD/GameMod/0Harmony.dll -------------------------------------------------------------------------------- /GameMod/Resources/meshes: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/overload-development-community/olmod/HEAD/GameMod/Resources/meshes -------------------------------------------------------------------------------- /GameMod/Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | C:\Program Files (x86)\Steam\steamapps\common\Overload 4 | 5 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | x64/ 2 | Debug/ 3 | bin/ 4 | obj/ 5 | Release/ 6 | *.dll 7 | *.exe 8 | *.pdb 9 | UnityEngine*.xml 10 | .vs/ 11 | *~ 12 | !0Harmony.dll 13 | *.aps 14 | *.o 15 | *.so 16 | *.user 17 | packages/ 18 | -------------------------------------------------------------------------------- /GameMod/olmodsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "isServer": false, 3 | "trackerBaseUrl": "https://tracker.otl.gg", 4 | "keepListed": false, 5 | "serverName": "My Overload Server", 6 | "notes": "Change these notes to give information about your server, such as geographical location, hardware, bandwidth, etc." 7 | } -------------------------------------------------------------------------------- /olmod/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /GameMod/MPHUDMessage.cs: -------------------------------------------------------------------------------- 1 | using Overload; 2 | 3 | namespace GameMod 4 | { 5 | class MPHUDMessage 6 | { 7 | public static void SendToAll(string message, int id = -1, bool priority = false) 8 | { 9 | foreach (Player player in Overload.NetworkManager.m_Players) 10 | player.CallTargetAddHUDMessage(player.connectionToClient, message, id, priority); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /linux/makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-Wall -O2 -g -fPIC 2 | 3 | all: olmod.so 4 | 5 | mac: olmod.dylib 6 | 7 | olmod.so: olmod.o 8 | $(CC) $(CFLAGS) -shared -o $@ $^ -ldl 9 | 10 | olmod.dylib: olmod.o 11 | $(CC) -dynamiclib -o $@ $^ 12 | 13 | GameMod.dll: ../GameMod/*.cs ../GameMod/*/*.cs 14 | ./mono_build.sh 15 | 16 | clean: 17 | rm -f olmod.so 18 | 19 | dist: olmod.so 20 | cp -p olmod.so olmod.sh olmodserver.sh ../x64/Release 21 | -------------------------------------------------------------------------------- /GameMod/AmbientUnload.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using UnityEngine; 3 | 4 | namespace GameMod 5 | { 6 | // Fix reloading custom ambient sounds by unloading them after the level ends 7 | [HarmonyPatch(typeof(UnityAudio), "KillAllSounds")] 8 | class AmbientUnload 9 | { 10 | static void Postfix(UnityAudio __instance) { 11 | foreach (AudioSource src in __instance.m_ambient_sources) 12 | src.clip.UnloadAudioData(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /PoorMansProfiler/pmp_heat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # HARDCODED FOR MY SYSTEM 4 | DATADIR="${HOME}/.config/unity3d/Revival/Overload" 5 | OUTDIR="${HOME}/tmp/DONTBACKUP/olmod-experiments/pmp/$(date '+%Y-%m-%d')" 6 | OLMODSRC="${HOME}/development/olmod" 7 | 8 | 9 | mkdir -p "${OUTDIR}" 10 | cd "${OUTDIR}" 11 | 12 | for file in "${DATADIR}/olmod_pmp"*.csv; do 13 | SNAME="$(basename -- ${file})" 14 | mv "$file" . 15 | echo "$SNAME" 16 | "${OLMODSRC}/PoorMansProfiler/pmp_heat" "$@" "$SNAME" > "$SNAME.pmplog" 17 | done 18 | 19 | 20 | -------------------------------------------------------------------------------- /GameMod/MPUnlockAll.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | 7 | // contributed by terminal 8 | namespace GameMod 9 | { 10 | // Tricks the modifiers menu into checking if user's XP is greater than 0 11 | [HarmonyPatch(typeof(Player), "GetModifierMinXP")] 12 | class MPUnlockAllModifiers 13 | { 14 | static void Postfix(ref int __result) 15 | { 16 | __result = 0; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /GameMod/MPTriggers.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using UnityEngine; 4 | 5 | namespace GameMod 6 | { 7 | //Prevent RobotManager from removing triggers in multiplayer 8 | [HarmonyPatch(typeof(RobotManager), "TriggerInRelevantSegment")] 9 | internal class MPTriggerVisible 10 | { 11 | private static void Postfix(ref bool __result) 12 | { 13 | if (GameplayManager.IsMultiplayerActive) 14 | { 15 | __result = true; 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /olmod/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by olmod.rc 4 | // 5 | #define IDI_SMALL 103 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NO_MFC 1 12 | #define _APS_NEXT_RESOURCE_VALUE 129 13 | #define _APS_NEXT_COMMAND_VALUE 32771 14 | #define _APS_NEXT_CONTROL_VALUE 1000 15 | #define _APS_NEXT_SYMED_VALUE 110 16 | #endif 17 | #endif 18 | -------------------------------------------------------------------------------- /OLModUnitTest/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /GameMod/ServerPort.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | 4 | namespace GameMod 5 | { 6 | [HarmonyPatch(typeof(Server), "Listen")] 7 | class ServerPort 8 | { 9 | static int PortArg = 0; 10 | 11 | private static bool Prepare(){ 12 | if (!Core.GameMod.FindArgVal("-port", out string arg) || !int.TryParse(arg, out int val)) 13 | return false; 14 | PortArg = val; 15 | return true; 16 | } 17 | 18 | private static void Prefix(ref int port) 19 | { 20 | if (port == 0) 21 | port = PortArg; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /olmod/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | // Windows Header Files 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | // C RunTime Header Files 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | // reference additional headers your program requires here 26 | -------------------------------------------------------------------------------- /GameMod/MPCeiling.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using UnityEngine; 3 | 4 | // by terminal 5 | namespace GameMod 6 | { 7 | // Prevent items from escaping through invisible ceilings on non-monsterball maps. 8 | [HarmonyPatch(typeof(NetworkMatch), "StartPlaying")] 9 | internal class MPItemCollideWithLayer31 10 | { 11 | private static void Postfix() 12 | { 13 | var isMonsterball = NetworkMatch.GetMode() == MatchMode.MONSTERBALL; 14 | Physics.IgnoreLayerCollision(31, (int)Overload.UnityObjectLayers.ITEMS, isMonsterball); 15 | Physics.IgnoreLayerCollision(31, (int)Overload.UnityObjectLayers.ITEM_LEVEL, isMonsterball); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /GameMod/MPIPLogging.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using UnityEngine; 4 | using UnityEngine.Networking; 5 | 6 | namespace GameMod { 7 | 8 | [HarmonyPatch(typeof(Server), "OnAddPlayerMessage")] 9 | class MPIPLogging_NetworkManager_AddPlayer { 10 | static void Postfix(NetworkMessage msg) { 11 | if (Overload.NetworkManager.IsServer()) { 12 | if (NetworkMatch.m_players.ContainsKey(msg.conn.connectionId)) { 13 | var player = NetworkMatch.m_players[msg.conn.connectionId]; 14 | Debug.Log($"Player connected: {player.m_name} from {msg.conn.address}"); 15 | } 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /GameMod/Boss2B.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection.Emit; 6 | using System.Text; 7 | using UnityEngine; 8 | 9 | namespace GameMod 10 | { 11 | // Allow boss2b (unused boss) to trigger exit sequence when destroyed during a boss lockdown. 12 | [HarmonyPatch(typeof(Robot), "ExplodeNow")] 13 | public class Robot_ExplodeNow_Boss2B 14 | { 15 | static void Postfix(Robot __instance) 16 | { 17 | if(__instance.m_is_boss && __instance.robot_type == Overload.EnemyType.BOSS2B) 18 | { 19 | Overload.GameplayManager.LockdownBossDestroyed(); 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /GameMod/MPSuperCheck.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System.Linq; 4 | 5 | // only start super spawn timer if super spawn actually exists in the level 6 | namespace GameMod 7 | { 8 | [HarmonyPatch(typeof(NetworkMatch), "SetSpawnSuperTimer")] 9 | class MPSuperCheck 10 | { 11 | static bool Prefix(ref float ___m_spawn_super_timer) 12 | { 13 | if (GameManager.m_level_data.m_item_spawn_points.Any(x => x.multiplayer_team_association_mask == 1) && // 1 -> is super 14 | RobotManager.m_multiplayer_spawnable_supers.Count != 0) 15 | return true; 16 | ___m_spawn_super_timer = -1f; 17 | return false; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /GameMod/MPLongPwd.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System.Collections.Generic; 4 | using System.Reflection.Emit; 5 | 6 | // by Tobias 7 | namespace GameMod 8 | { 9 | [HarmonyPatch(typeof(MenuManager), "ProcessInputField")] 10 | class MPLongPwdProcessInputField 11 | { 12 | private static IEnumerable Transpiler(IEnumerable codes) 13 | { 14 | foreach (var code in codes) 15 | { 16 | if (code.opcode == OpCodes.Ldc_I4_S && (sbyte)code.operand == 16) 17 | { 18 | code.operand = 127; 19 | } 20 | yield return code; 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /OLModUnitTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("OLModUnitTest")] 6 | [assembly: AssemblyDescription("")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("OLModUnitTest")] 10 | [assembly: AssemblyCopyright("Copyright © 2021")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | 14 | [assembly: ComVisible(false)] 15 | 16 | [assembly: Guid("a3a1afa7-6214-4624-80f6-b17b60b36916")] 17 | 18 | // [assembly: AssemblyVersion("1.0.*")] 19 | [assembly: AssemblyVersion("1.0.0.0")] 20 | [assembly: AssemblyFileVersion("1.0.0.0")] 21 | -------------------------------------------------------------------------------- /GameMod/MPDeathRollSync.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | 4 | namespace GameMod 5 | { 6 | [HarmonyPatch(typeof(PlayerShip), "FixedUpdatePreDying")] 7 | class MPDeathRollSync_PlayerShip_FixedUpdatePreDying 8 | { 9 | static void Prefix(PlayerShip __instance) 10 | { 11 | if (GameplayManager.IsMultiplayerActive && __instance.c_mesh_collider_trans != null && __instance.c_transform != null) 12 | { 13 | __instance.c_mesh_collider_trans.localPosition = __instance.c_transform.localPosition; 14 | __instance.c_mesh_collider_trans.localRotation = __instance.c_transform.localRotation; // this matters somewhat with mesh colliders 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /GameMod/MPMatchTimeLimits.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | 4 | namespace GameMod 5 | { 6 | class MPMatchTimeLimits 7 | { 8 | public static int MatchTimeLimit = 600; 9 | } 10 | 11 | [HarmonyPatch(typeof(MenuManager), "GetMMSTimeLimit")] 12 | class MPMatchTimeLimits_MenuManager_GetMMSTimeLimit 13 | { 14 | static bool Prefix(ref string __result) 15 | { 16 | if (Menus.mms_match_time_limit == 0) 17 | { 18 | __result = "NONE"; 19 | } 20 | else 21 | { 22 | __result = (Menus.mms_match_time_limit / 60).ToString() + " MINUTE" + ((Menus.mms_match_time_limit > 60) ? "S" : ""); 23 | } 24 | return false; 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /GameMod/MPPwdPaste.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using UnityEngine; 8 | 9 | namespace GameMod 10 | { 11 | [HarmonyPatch(typeof(MenuManager), "MpMatchSetup")] 12 | class MPPwdPaste 13 | { 14 | static bool Prepare() 15 | { 16 | return !Core.GameMod.HasInternetMatch(); 17 | } 18 | 19 | static void Prefix() 20 | { 21 | if ((MenuManager.m_menu_micro_state == 1 || MenuManager.m_menu_micro_state == 4) && UIManager.m_menu_selection == 11 && 22 | ((Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) && Input.GetKeyDown(KeyCode.V))) 23 | MPInternet.MenuPassword = GUIUtility.systemCopyBuffer; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /GameMod/ExitCutscene.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection.Emit; 6 | using System.Text; 7 | using UnityEngine; 8 | 9 | namespace GameMod 10 | { 11 | // If a cloaking device expires during the exit cutscene, 12 | // cockpit visibility (which is also used to show the ship in cutscenes) 13 | // reverts to the profile setting even though we want it forced on. 14 | [HarmonyPatch(typeof(Overload.PlayerShip), "get_IsCockpitVisible")] 15 | public class PlayerShip_IsCockpitVisible_DuringExit 16 | { 17 | static bool Prefix(ref bool __result) 18 | { 19 | if (Overload.GameplayManager.m_gameplay_state == Overload.GameplayState.EXIT) 20 | { 21 | __result = true; 22 | return false; 23 | } 24 | return true; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /GameMod/MPTeamsEnemyArrow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using HarmonyLib; 3 | using Overload; 4 | using UnityEngine; 5 | 6 | namespace GameMod 7 | { 8 | [HarmonyPatch(typeof(UIManager), "DrawMpPlayerArrow")] 9 | internal partial class MPTeamsEnemyArrow 10 | { 11 | //In team games, display a red arrow below enemy names. 12 | private static void Postfix(Player player, Vector2 offset) 13 | { 14 | float a = (player.m_mp_team != GameManager.m_local_player.m_mp_team) ? (1f * player.m_mp_data.vis_fade) : 1f; 15 | float rotation = 4.712389f; 16 | 17 | if (player.m_mp_team != GameManager.m_local_player.m_mp_team) 18 | { 19 | Vector2 redOffset = new Vector2(0f, -0.8f); 20 | offset += redOffset; 21 | UIManager.DrawSpriteUIRotated(offset, 0.015f, 0.015f, rotation, Color.red, a, 81); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /GameMod/MPPickupCheck.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using HarmonyLib; 3 | using Overload; 4 | using UnityEngine; 5 | 6 | namespace GameMod 7 | { 8 | class MPPickupCheck 9 | { 10 | public static bool PickupCheck = true; 11 | } 12 | 13 | // Allow picking up items in MP when item is adjacent to an inverted segment. Items also no longer get stuck inside grates. by Terminal 14 | [HarmonyPatch(typeof(Item), "ItemIsReachable")] 15 | internal class MPItemInvertedSegment 16 | { 17 | private static bool Prefix(ref bool __result) 18 | { 19 | //Debug.Log("ItemIsReachable " + (Overload.NetworkManager.IsServer() ? "server" : "conn " + NetworkMatch.m_my_lobby_id) + " PickupCheck=" + MPPickupCheck.PickupCheck); 20 | if (GameplayManager.IsMultiplayerActive && !MPPickupCheck.PickupCheck) 21 | { 22 | __result = true; 23 | return false; 24 | } 25 | return true; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /GameMod/MPSpawnInitialization.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using HarmonyLib; 3 | using Overload; 4 | 5 | namespace GameMod 6 | { 7 | /// 8 | /// Does a better job of initializing playership state at spawn, resetting the flak/cyclone fire counter, the thunderbolt power level, and clearing the boost overheat. 9 | /// 10 | [HarmonyPatch(typeof(Player), "RestorePlayerShipDataAfterRespawn")] 11 | class MPSpawnInitialization 12 | { 13 | private static FieldInfo _PlayerShip_flak_fire_count_Field = typeof(PlayerShip).GetField("flak_fire_count", BindingFlags.NonPublic | BindingFlags.Instance); 14 | 15 | static void Prefix(Player __instance) { 16 | _PlayerShip_flak_fire_count_Field.SetValue(__instance.c_player_ship, 0); 17 | __instance.c_player_ship.m_thunder_power = 0; 18 | __instance.c_player_ship.m_boost_heat = 0; 19 | __instance.c_player_ship.m_boost_overheat_timer = 0f; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /GameMod/VRScale.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using UnityEngine; 4 | 5 | namespace GameMod { 6 | /// 7 | /// This mod is intended to set the camera scale for VR to make spaces feel bigger/smaller in VR. It's based on https://github.com/Raicuparta/unity-scale-adjuster. 8 | /// 9 | public class VRScale { 10 | private static float _VR_Scale = 1f; 11 | public static float VR_Scale { 12 | get { 13 | return _VR_Scale; 14 | } 15 | set { 16 | GameManager.m_player_ship.c_camera_transform.localScale = Vector3.one * value; 17 | 18 | _VR_Scale = value; 19 | } 20 | } 21 | } 22 | 23 | [HarmonyPatch(typeof(PlayerShip), "Awake")] 24 | public class VRScale_PlayerShip_Update { 25 | private static void Postfix(PlayerShip __instance) { 26 | __instance.c_camera_transform.localScale = Vector3.one * VRScale.VR_Scale; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /PoorMansProfiler/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for unix systems 2 | # this requires GNU make 3 | 4 | APPNAME=pmp_heat 5 | 6 | # enable all warnings in general 7 | WARNFLAGS= -Wall -Wextra -Wno-unused-parameter 8 | 9 | # optimize flags, only used for RELEASE=1 builds 10 | OPTIMIZEFLAGS = -mtune=native -march=native -flto -O4 -DNDEBUG 11 | 12 | ifeq ($(RELEASE), 1) 13 | CFLAGS = $(BASECFLAGS) $(WARNFLAGS) $(OPTIMIZEFLAGS) -s 14 | else 15 | CFLAGS = $(BASECFLAGS) $(WARNFLAGS) -Werror -g 16 | endif 17 | 18 | # all needed libraries 19 | LINK = -lm 20 | 21 | # Files 22 | 23 | # "shared" files are all files needed both for the uebung and the project 24 | CFILES=$(wildcard *.c) 25 | INCFILES=$(wildcard *.h) 26 | PRJFILES=Makefile $(wildcard *.sln) 27 | 28 | # build rules 29 | .PHONY: all 30 | all: $(APPNAME) 31 | 32 | # rules to build applications 33 | $(APPNAME): $(CFILES) $(INCFILES) 34 | $(CC) $(CFLAGS) $(CFILES) $(LDFLAGS) $(LINK) -o$(APPNAME) 35 | 36 | # remove all unneeded files 37 | .PHONY: clean 38 | clean: 39 | @echo removing binaries: $(APPNAME) 40 | @rm -f $(APPNAME) 41 | 42 | -------------------------------------------------------------------------------- /GameMod/GSyncFix.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using UnityEngine; 4 | 5 | namespace GameMod { 6 | // GSync fix 7 | [HarmonyPatch(typeof(GameManager), "UpdateTargetFramerate")] 8 | class GSyncFix_UpdateTargetFramerate { 9 | static bool Prefix() { 10 | if (GameplayManager.IsDedicatedServer()) { 11 | Application.targetFrameRate = 120; 12 | } else { 13 | if(FramerateLimiter.target_framerate != 0) 14 | { 15 | Application.targetFrameRate = FramerateLimiter.target_framerate; 16 | } 17 | else 18 | { 19 | if (GameManager.m_game_state == GameManager.GameState.GAMEPLAY) 20 | { 21 | Application.targetFrameRate = -1; 22 | } 23 | else 24 | { 25 | Application.targetFrameRate = 120; 26 | } 27 | } 28 | 29 | } 30 | return false; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /GameMod/MPItemSpawns.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using UnityEngine; 4 | 5 | namespace GameMod 6 | { 7 | 8 | /// 9 | /// Issue 200 10 | /// In multiplayer, non-CM item spawns cause unexpected behavior due to being unsync'd (e.g. Ascent health orbs). Destroy these items and respawn as single-use sync'd spew. 11 | /// 12 | [HarmonyPatch(typeof(UpdateDynamicManager), "AddItem")] 13 | public class UpdateDynamicManager_AddItem 14 | { 15 | static bool Prefix(Item item) 16 | { 17 | if (GameplayManager.IsMultiplayerActive) 18 | { 19 | if (item.netId.Value <= 0) 20 | { 21 | UnityEngine.Object.Destroy(item.c_go); 22 | if (GameplayManager.IsDedicatedServer()) 23 | { 24 | Item.Spew(item.c_go, item.c_transform.position, default(Vector3), -1, item.m_super); 25 | } 26 | return false; 27 | } 28 | } 29 | 30 | return true; 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Arne de Bruijn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PoorMansProfiler/pmp-filters.txt: -------------------------------------------------------------------------------- 1 | # method filter list for omlod -poor-mans-profiler 2 | # the first matching entry is applied 3 | # format is optionstypemethod 4 | # IGNORE THESE 5 | -R ^System\..* 6 | -R ^Rewired\..* 7 | # add stuff we're particularly interested in 8 | +R ^GameMod.MPSoundOcclusion_UnityAudio_PlaySound$ ^Void Postfix\( 9 | +R ^GameMod.MPClientExtrapolation_FixedUpdateAll$ ^Void Postfix\( 10 | +R ^Overload.PlayerShip$ ^Void FixedUpdatePre\( 11 | # add functions which look like Update() methods, but ignore some as patching leads to a crash 12 | -= Overload.SFXCueManager Void Update() 13 | -= UnityEngine.UI.CanvasScaler Void Update() 14 | += Void Update() 15 | += Void FixedUpdate() 16 | += Void FixedUpdateAll() 17 | += Void LateUpdate() 18 | # add interesting physics funtcions 19 | +=R ^UnityEngine.Physics$ ^[^()]* Linecast\( 20 | +=R ^UnityEngine.Physics$ ^[^()]* SphereCast\( 21 | +=R ^UnityEngine.Physics$ ^[^()]* Ray[Cc]ast\( 22 | # add functions which look like Message Handlers 23 | +R ^Void On.*\(UnityEngine.Networking.NetworkMessage\) 24 | # add all previously patched functions (the tabs here are important) 25 | +*p 26 | -------------------------------------------------------------------------------- /GameMod/PrevWeaponFix.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | using UnityEngine; 7 | 8 | namespace GameMod 9 | { 10 | 11 | /// 12 | /// Author: Tobias/luponix (adaptation of luponix' identified fix) 13 | /// Created: 2019-08-21 14 | /// 15 | [HarmonyPatch(typeof(PlayerShip), "UpdateReadImmediateControls")] 16 | class PrevWeaponFix 17 | { 18 | static IEnumerable Transpiler(IEnumerable codes) 19 | { 20 | foreach (var code in codes) 21 | { 22 | // Before if (Controls.IsPressed(CCInput.SWITCH_MISSILE)) 23 | if (code.opcode == OpCodes.Ldc_I4_S && (sbyte)code.operand == 17) 24 | { 25 | yield return new CodeInstruction(OpCodes.Ldarg_0); 26 | yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PrevWeaponFix), "PrevWeaponUpdate")); 27 | } 28 | 29 | yield return code; 30 | } 31 | } 32 | 33 | static void PrevWeaponUpdate(PlayerShip player) 34 | { 35 | player.c_player.CallCmdSetCurrentWeapon(player.c_player.m_weapon_type); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /GameMod/DisableProfanityFilter.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using UnityEngine; 4 | 5 | namespace GameMod 6 | { 7 | class DisableProfanityFilter 8 | { 9 | /// 10 | /// Author: luponix 11 | /// Created: 2022-03-07 12 | /// Removes the effects of the Profanity filter by returning the string immediatly 13 | /// and shifts the responsibility to the clients 14 | /// 15 | 16 | public static bool profanity_filter = false; 17 | 18 | [HarmonyPatch(typeof(StringParse), "ProfanityFilter")] 19 | class DisableProfanityFilter_StringParse_ProfanityFilter 20 | { 21 | static bool Prefix(string s, ref string __result) 22 | { 23 | if (GameplayManager.IsDedicatedServer() | !profanity_filter) 24 | { 25 | __result = s; 26 | return false; 27 | } 28 | return true; 29 | } 30 | } 31 | 32 | [HarmonyPatch(typeof(NetworkMessageManager), "AddFullChatMessage")] 33 | class DisableProfanityFilter_NetworkMessageManager_AddFullChatMessage 34 | { 35 | static void Prefix(ref string msg) 36 | { 37 | msg = StringParse.ProfanityFilter(msg); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /GameMod/MPNoNewWeaponSound.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System.Collections.Generic; 4 | using System.Reflection.Emit; 5 | 6 | namespace GameMod 7 | { 8 | [HarmonyPatch(typeof(Player), "UnlockWeaponClient")] 9 | class MPNoNewWeaponSound 10 | { 11 | private static IEnumerable Transpiler(ILGenerator ilGen, IEnumerable codes) 12 | { 13 | Label lbl = ilGen.DefineLabel(); 14 | int state = 0; 15 | foreach (var code in codes) 16 | { 17 | if (code.opcode == OpCodes.Ldc_I4 && (int)code.operand == (int)SoundEffect.hud_notify_message1) 18 | { 19 | var c = new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(GameplayManager), "IsMultiplayerActive")); 20 | c.labels.AddRange(code.labels); 21 | code.labels.Clear(); 22 | yield return c; 23 | yield return new CodeInstruction(OpCodes.Brtrue, lbl); 24 | state = 1; 25 | } 26 | else if (state == 1 && code.opcode == OpCodes.Call) 27 | { 28 | state = 2; 29 | } 30 | else if (state == 2) 31 | { 32 | code.labels.Add(lbl); 33 | state = 3; 34 | } 35 | yield return code; 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /GameMod/MPSpawnInvuln.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System.Collections.Generic; 4 | using System.Reflection.Emit; 5 | 6 | namespace GameMod 7 | { 8 | 9 | // Skip the portion in Player.UpdateInvul() where ship movement reduces your invuln time 10 | [HarmonyPatch(typeof(Player), "UpdateInvul")] 11 | internal class MPSpawnInvuln_Player_UpdateInvul 12 | { 13 | static IEnumerable Transpiler(IEnumerable codes) 14 | { 15 | int state = 0; 16 | foreach (var code in codes) 17 | { 18 | if (code.opcode == OpCodes.Stloc_1) 19 | { 20 | state++; 21 | if (state == 2) 22 | code.opcode = OpCodes.Pop; 23 | } 24 | 25 | yield return code; 26 | } 27 | } 28 | } 29 | 30 | // Cancels spawn invuln if a player starts charging Thunderbolt 31 | [HarmonyPatch(typeof(PlayerShip), "ThunderCharge")] 32 | internal class MPSpawnInvuln_PlayerShip_ThunderCharge 33 | { 34 | static void Postfix(Player ___c_player) 35 | { 36 | if (GameplayManager.IsMultiplayerActive && ___c_player.m_spawn_invul_active) 37 | { 38 | ___c_player.m_timer_invuln = (float)___c_player.m_timer_invuln - (float)NetworkMatch.m_respawn_shield_seconds; 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /GameMod/MPReduceJoinTimeout.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | using UnityEngine; 7 | using UnityEngine.Networking; 8 | using UnityEngine.Networking.NetworkSystem; 9 | 10 | 11 | namespace GameMod 12 | { 13 | // change the 60 second "Player Joining" timeout to 5 seconds 14 | [HarmonyPatch] 15 | class MPReduceJoinTimeout 16 | { 17 | private static MethodBase TargetMethod() 18 | { 19 | return typeof(NetworkMatch).GetNestedType("HostPlayerMatchmakerInfo", AccessTools.all).GetMethod("GetStatus"); 20 | } 21 | 22 | static IEnumerable Transpiler(IEnumerable codes) 23 | { 24 | int state = 0; 25 | foreach (var code in codes) 26 | { 27 | if (state == 0) { 28 | if (code.opcode == OpCodes.Ldc_R8 && (double)code.operand == 60) { 29 | state = 1; 30 | yield return new CodeInstruction(OpCodes.Ldc_R8, 5.0); 31 | } else { 32 | yield return code; 33 | } 34 | } else { 35 | yield return code; 36 | } 37 | } 38 | if (state != 1) { 39 | Debug.LogFormat("MPReduceJoinTimeout: transpiler failed at state {0}",state); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /GameMod/CrusherTrails.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Reflection.Emit; 3 | using HarmonyLib; 4 | using Overload; 5 | 6 | namespace GameMod { 7 | [HarmonyPatch(typeof(Projectile), "Fire")] 8 | class CrusherTrails_Projectile_Fire { 9 | 10 | private static void ModifyCrusherTrail(Projectile proj) { 11 | if (!GameplayManager.IsMultiplayer) { 12 | proj.m_trail_renderer = FXTrailRenderer.trail_renderer_crusher + Projectile.CrusherNextTrailIndex; 13 | Projectile.CrusherNextTrailIndex = (Projectile.CrusherNextTrailIndex + 1) % 3; 14 | } 15 | } 16 | 17 | private static IEnumerable Transpiler(IEnumerable codes) { 18 | int state = 0; 19 | foreach (var code in codes) { 20 | if (code.opcode == OpCodes.Ldc_I4_6) 21 | state++; 22 | 23 | if (state == 1) { 24 | if (code.opcode == OpCodes.Stsfld && code.operand == AccessTools.Field(typeof(Projectile), "CrusherNextTrailIndex")) { 25 | state++; 26 | yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(CrusherTrails_Projectile_Fire), "ModifyCrusherTrail")); 27 | continue; 28 | } else { 29 | continue; 30 | } 31 | } 32 | yield return code; 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /olgetdata/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("olgetdata")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("olgetdata")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5f11c292-d523-4c7f-88fa-3414f62a001a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /GameMod/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("GameMod")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("GameMod")] 13 | [assembly: AssemblyCopyright("Copyright © Overload Community 2019-2025")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("fb32eb50-de78-4ffb-8de8-c3c8a82e8b62")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("0.5.14.0")] 36 | [assembly: AssemblyFileVersion("0.5.14.0")] 37 | -------------------------------------------------------------------------------- /GameMod/MPNoDupes.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | using HarmonyLib; 5 | using Overload; 6 | 7 | namespace GameMod { 8 | /// 9 | /// Prevents stock items from being picked up by multiple pilots in the same frame. 10 | /// 11 | [HarmonyPatch(typeof(Item), "OnTriggerEnter")] 12 | class MPNoDupes_OnTriggerEnter { 13 | public static bool Prefix(Item __instance) { 14 | return __instance.m_type != ItemType.NONE; 15 | } 16 | 17 | public static void SetItemTypeToNoneAndDestroy(Item item) { 18 | item.m_type = ItemType.NONE; 19 | UnityEngine.Object.Destroy(item.c_go); 20 | } 21 | 22 | public static IEnumerable Transpiler(IEnumerable codes) { 23 | var ldfldCount = 0; 24 | 25 | foreach (var code in codes) { 26 | if (code.opcode == OpCodes.Ldfld) { 27 | ldfldCount++; 28 | 29 | if (ldfldCount == 39) { 30 | continue; 31 | } 32 | } 33 | 34 | if (code.opcode == OpCodes.Call && ((MethodInfo)code.operand).Name == "Destroy") { 35 | yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(MPNoDupes_OnTriggerEnter), "SetItemTypeToNoneAndDestroy")); 36 | continue; 37 | } 38 | 39 | yield return code; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /GameMod/HUDVelocity.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using UnityEngine; 4 | 5 | namespace GameMod 6 | { 7 | class HUDVelocity 8 | { 9 | public static bool MenuManagerEnabled = false; 10 | } 11 | 12 | [HarmonyPatch(typeof(UIElement), "DrawHUD")] 13 | class HUDVelocity_UIElement_DrawHud 14 | { 15 | static Max max = new Max { vel = 0f, time = 0f }; 16 | static float historyDuration = 5f; 17 | 18 | class Max 19 | { 20 | public float vel; 21 | public float time; 22 | } 23 | 24 | static void Postfix(UIElement __instance) 25 | { 26 | if (!HUDVelocity.MenuManagerEnabled || GameManager.m_local_player.m_spectator || (GameplayManager.IsMultiplayerActive && NetworkMatch.m_match_state != MatchState.PLAYING)) 27 | return; 28 | 29 | Vector2 pos = default(Vector2); 30 | pos.x = 0f; 31 | pos.y = UIManager.UI_TOP - 210f; 32 | var vel = GameManager.m_player_ship.c_rigidbody.velocity; 33 | if (vel.magnitude > max.vel || max.time < GameplayManager.m_total_time - historyDuration) 34 | max = new Max { vel = vel.magnitude, time = GameplayManager.m_total_time }; 35 | 36 | __instance.DrawStringSmall($"Vel: {vel.magnitude.ToString("n2")}", pos, 0.5f, StringOffset.CENTER, UIManager.m_col_ui4, 1f); 37 | pos.y -= 24f; 38 | __instance.DrawStringSmall($"Max: {max.vel.ToString("n2")}", pos, 0.5f, StringOffset.CENTER, UIManager.m_col_ui4, 1f); 39 | 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /GameMod/CustomDoorAutomap.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using UnityEngine; 4 | using System; 5 | 6 | namespace GameMod 7 | { 8 | // Ensure doors have a built-in automap material, needed for custom doors 9 | [HarmonyPatch(typeof(DoorAnimating), "Start")] 10 | class CustomDoorAutomap 11 | { 12 | private static void Postfix(DoorAnimating __instance, bool ___m_security_door) 13 | { 14 | if (!__instance.m_door_automap) 15 | return; 16 | Renderer component = __instance.m_door_automap.GetComponent(); 17 | if (!component || component.material == null) 18 | return; 19 | Material newMat = 20 | __instance.m_is_secret ? 21 | GameplayManager.m_automap.m_map_camera.m_map_solid_material : 22 | ___m_security_door ? 23 | GameManager.m_local_player.m_unlock_level < __instance.LockType ? 24 | GameplayManager.m_automap.m_map_camera.m_map_door_security_material : 25 | GameplayManager.m_automap.m_map_camera.m_map_door_unlocked_material : 26 | GameplayManager.m_automap.m_map_camera.m_map_door_default_material; 27 | string curName = component.material.name; 28 | int i = curName.IndexOf(' '); 29 | if (i >= 0) 30 | curName = curName.Substring(0, i); 31 | if (component.material != newMat && 32 | curName.Equals(newMat.name, StringComparison.OrdinalIgnoreCase)) 33 | component.material = newMat; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /GameMod/MPNegativeKills.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using UnityEngine; 4 | 5 | namespace GameMod 6 | { 7 | // Allow #kills < 0 when suiciding 8 | [HarmonyPatch(typeof(Player), "RpcAddKill")] 9 | class MPNegativeKills 10 | { 11 | private static void Prefix(Player __instance, int killer_connection_id, int killed_connection_id) 12 | { 13 | if (killer_connection_id == killed_connection_id && __instance.m_kills <= 0) // original code won't decrement in this case 14 | __instance.m_kills--; 15 | } 16 | } 17 | 18 | [HarmonyPatch(typeof(UIElement), "DrawDigitsVariable")] 19 | class DrawDigitsNeg 20 | { 21 | private static bool Prefix(UIElement __instance, ref Vector2 pos, ref int value, float scl, ref StringOffset offset, Color c, float a) 22 | { 23 | if (value >= 0) 24 | return true; 25 | value = -value; 26 | int len = (int)Mathf.Floor(Mathf.Log10(value) + 1f) + 1; 27 | switch (offset) 28 | { 29 | case StringOffset.CENTER: 30 | pos.x -= 22f * scl * 0.5f * (len - 1); 31 | break; 32 | case StringOffset.RIGHT: 33 | pos.x -= 22f * scl * (len - 1); 34 | break; 35 | } 36 | float width = 0.25f * scl; 37 | UIManager.DrawSpriteUI(pos, width, width, c, a, (int)AtlasIndex0.LINE_THICK1); // LINE_THICK1 has same width as digits 38 | pos.x += 22f * scl; 39 | offset = StringOffset.LEFT; 40 | return true; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /GameMod/MPMonoDNSFix.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | 7 | namespace GameMod 8 | { 9 | // do not call GetIPv4Properties on Windows, it crashes with >2 DNS servers 10 | // it's only used for LoopbackInterfaceIndex which is a stub on Windows 11 | // https://github.com/Unity-Technologies/mono/blob/unity-2017.4/mcs/class/System/System.Net.NetworkInformation/NetworkInterface.cs#L101 12 | [HarmonyPatch(typeof(BroadcastState), "EnumerateNetworkInterfaces")] 13 | class MPMonoDNSFix 14 | { 15 | // only patch on Windows 16 | private static bool Prepare() { 17 | // https://github.com/Unity-Technologies/mono/blob/unity-2017.4/mcs/class/corlib/System/Environment.cs#L742 18 | var runningOnWindows = ((int) System.Environment.OSVersion.Platform < 4); 19 | return runningOnWindows; 20 | } 21 | 22 | private static System.Net.NetworkInformation.IPv4InterfaceProperties GetIPv4Properties(object ipProperties) { 23 | return null; 24 | } 25 | 26 | private static IEnumerable Transpiler(IEnumerable codes) 27 | { 28 | int n = 0; 29 | foreach (var code in codes) 30 | { 31 | if (code.opcode == OpCodes.Callvirt && ((MethodInfo)code.operand).Name == "GetIPv4Properties") { 32 | code.operand = typeof(MPMonoDNSFix).GetMethod("GetIPv4Properties", BindingFlags.NonPublic | BindingFlags.Static); 33 | n++; 34 | } 35 | yield return code; 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /GameMod/MPOpponentCockpits.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using HarmonyLib; 4 | using Overload; 5 | using UnityEngine; 6 | 7 | namespace GameMod { 8 | public class MPOpponentCockpits { 9 | public static void SetOpponentCockpitVisibility(Player p, bool enabled) { 10 | if (p != null && p.c_player_ship != null && !p.isLocalPlayer && !p.m_spectator) { 11 | //Debug.LogFormat("Setting cockpit visibility for player ship {0} to {1}",p.m_mp_name, enabled); 12 | MeshRenderer[] componentsInChildren = p.c_player_ship.GetComponentsInChildren(includeInactive: true); 13 | foreach (MeshRenderer meshRenderer in componentsInChildren) 14 | { 15 | if (meshRenderer.enabled != enabled) { 16 | if (string.CompareOrdinal(meshRenderer.name, 0, "cp_", 0, 3) == 0) { 17 | meshRenderer.enabled = enabled; 18 | meshRenderer.shadowCastingMode = 0; 19 | } 20 | } 21 | } 22 | } 23 | } 24 | 25 | [HarmonyPatch(typeof(Overload.PlayerShip), "SetCockpitVisibility")] 26 | class MPOpponentCockpits_Disable1 { 27 | static void Postfix(PlayerShip __instance) { 28 | SetOpponentCockpitVisibility(__instance.c_player, false); 29 | } 30 | } 31 | 32 | [HarmonyPatch(typeof(Overload.Player), "RestorePlayerShipDataAfterRespawn")] 33 | class MPOpponentCockpits_Disable2 { 34 | static void Postfix(Player __instance) { 35 | SetOpponentCockpitVisibility(__instance, false); 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /GameMod/MPDoors.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using UnityEngine; 4 | 5 | // by terminal 6 | namespace GameMod 7 | { 8 | [HarmonyPatch(typeof(RUtility), "CanObjectOpenDoor")] 9 | internal class MPShootDoors 10 | { 11 | // In Multiplayer, players now open doors by shooting them or touching them. 12 | private static void Postfix(GameObject go, ref bool __result) 13 | { 14 | if (go != null && (go.layer == 13 || go.layer == 9 || go.layer == 31) && GameplayManager.IsMultiplayerActive) 15 | __result = true; 16 | } 17 | } 18 | 19 | [HarmonyPatch(typeof(DoorAnimating), "Start")] 20 | internal class MPTouchDoors 21 | { 22 | //Removes the proximity sensor which is replaced by a collision in MPShootDoors 23 | private static void Postfix(GameObject __instance, GameObject ___m_player_trigger) 24 | { 25 | if (GameplayManager.IsMultiplayerActive && __instance != null && ___m_player_trigger.GetComponentInChildren() != null && 26 | NetworkMatch.m_client_server_location != "OLMOD 0.2.5") // keep old behaviour on current server for now 27 | { 28 | ___m_player_trigger.GetComponentInChildren().size = default(Vector3); 29 | } 30 | } 31 | } 32 | 33 | //Prevent RobotManager from removing doors in multiplayer 34 | [HarmonyPatch(typeof(RobotManager), "DoorInRelevantSegment")] 35 | internal class MPDoorVisible 36 | { 37 | private static void Postfix(DoorBase door, ref bool __result) 38 | { 39 | if (GameplayManager.IsMultiplayerActive) 40 | { 41 | __result = true; 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /GameMod/MPAlwaysCloaked.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | 4 | namespace GameMod { 5 | public class MPAlwaysCloaked { 6 | public static bool Enabled { get; set; } = false; 7 | } 8 | 9 | /// 10 | /// Make ships cloaked on spawn when mod enabled. 11 | /// 12 | [HarmonyPatch(typeof(Player), "Update")] 13 | class MPAlwaysCloaked_Update { 14 | private static void Postfix(Player __instance) { 15 | if (GameplayManager.IsMultiplayer && NetworkManager.IsServer() && NetworkMatch.m_match_state == MatchState.PLAYING && MPAlwaysCloaked.Enabled && __instance != null && !__instance.Networkm_cloaked) { 16 | __instance.Networkm_cloaked = true; 17 | __instance.CallRpcActivateCloak(float.MaxValue); 18 | __instance.CallTargetAddHUDMessage(__instance.connectionToClient, Loc.LSN("EVERYONE IS ALWAYS CLOAKED!"), -1, true); 19 | } 20 | } 21 | } 22 | 23 | /// 24 | /// Disallow cloak from spawning when mod enabled. 25 | /// 26 | [HarmonyPatch(typeof(NetworkMatch), "RandomAllowedSuperSpawn")] 27 | class MPAlwaysCloaked_RandomAllowedSuperSpawn { 28 | private static void Prefix() { 29 | if (MPAlwaysCloaked.Enabled) { 30 | for (int index = 0; index < RobotManager.m_multiplayer_spawnable_supers.Count; index++) { 31 | var super = RobotManager.m_multiplayer_spawnable_supers[index]; 32 | if (super.type == (int)SuperType.CLOAK) { 33 | super.percent = 0; 34 | RobotManager.m_multiplayer_spawnable_supers[index] = super; 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /GameMod/UIMeshColliderNoRender.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using HarmonyLib; 4 | using Overload; 5 | using UnityEngine; 6 | 7 | namespace GameMod { 8 | 9 | [HarmonyPatch(typeof(UIManager), "GenerateUICollisionMesh")] 10 | class UIMeshColliderNoRender_GenerateUICollisionMesh { 11 | private static void Postfix() { 12 | // url[4] seems to be the ui collision layer, it is never _meant_ 13 | // to be rendered at all, but only (mis?-)used by the game as a 14 | // a helper to dynamically generate a Mesh for a MeshCollider 15 | // which is later used for (CPU side) raycasting in 16 | // UIManager.FindMousePosition(). 17 | // However, since this mesh is created in a render layer, it is 18 | // actually rendered _every frame_ for no reason at all. 19 | // 20 | // NOTE: "UnityRenderLayer" is not an Unity concept, but something 21 | // Luke Schneider came up with for his earlier games, see 22 | // https://www.gamasutra.com/blogs/LukeSchneider/20120911/177488/XNAtoUnity_Part_1__The_Setup.php 23 | // https://www.gamasutra.com/blogs/LukeSchneider/20120919/177963/XNAtoUnity_Part_2_Rendering.php 24 | // It seems this stuff got re-used in Overload... 25 | UnityRenderLayer renderLayer = Overload.UIManager.url[4]; 26 | 27 | // access the protected field "c_renderer" of the UnityRenderLayer 28 | Type renderLayerType = renderLayer.GetType(); 29 | BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic; 30 | FieldInfo fieldInfo = renderLayerType.GetField("c_renderer", bindingFlags); 31 | Renderer r = (Renderer)fieldInfo.GetValue(renderLayer); 32 | r.enabled = false; // turn it off 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /GameMod/AxisCountFix.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | 7 | namespace GameMod 8 | { 9 | // fixes that when swapping to a different controller overload's menu code doesnt check, 10 | // wether the currently selected axis is out of bounds for the new controller which would otherwise result in a freeze 11 | class AxisCountFix 12 | { 13 | [HarmonyPatch(typeof(MenuManager), "ControlsOptionsUpdate")] 14 | internal class AxisCountFix_MenuManager_ControlsOptionsUpdate 15 | { 16 | public static void MaybeAdjustAxisSelection(int controller) 17 | { 18 | if (Controls.m_controllers[controller].m_joystick.axisCount <= MenuManager.m_calibration_current_axis) 19 | MenuManager.m_calibration_current_axis = 0; 20 | } 21 | 22 | private static IEnumerable Transpiler(IEnumerable codes) 23 | { 24 | int state = 0; 25 | foreach (var code in codes) 26 | { 27 | yield return code; 28 | if (state == 0 && code.opcode == OpCodes.Call && ((MethodInfo)code.operand).Name == "GetPrevControllerWithAxes") 29 | state = 1; 30 | if (state == 5) 31 | { 32 | yield return new CodeInstruction(OpCodes.Ldloc_S, 9); 33 | yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(AxisCountFix_MenuManager_ControlsOptionsUpdate), "MaybeAdjustAxisSelection")); 34 | state++; 35 | continue; 36 | } 37 | if (state > 0) 38 | state++; 39 | 40 | } 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /linux/olmod.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | args=() 3 | gamedir="$(cd "$(dirname "$0")"; pwd)" 4 | olmoddir="$(cd "$(dirname "$0")"; pwd)" 5 | while [[ $# -gt 0 ]] 6 | do 7 | key="$1" 8 | case $key in 9 | -gamedir) 10 | gamedir="$2" 11 | shift 12 | shift 13 | ;; 14 | *) 15 | args+=("$1") 16 | shift 17 | ;; 18 | esac 19 | done 20 | olargs=${args[@]} 21 | 22 | if [[ -z "$OSTYPE" || "$OSTYPE" != "darwin"* ]]; 23 | then 24 | olmodso="${olmoddir}/olmod.so" 25 | overload="${gamedir}/Overload.x86_64" 26 | if [[ -f "${olmodso}" ]]; 27 | then 28 | if [[ -f "${overload}" ]]; 29 | then 30 | cd "${olmoddir}" 31 | OLMODDIR="${olmoddir}" LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}./olmod.so" "${overload}" ${olargs} 32 | else 33 | echo "Error: Overload.x86_64 not found." >&2 34 | echo "Looked in ${gamedir}" >&2 35 | echo "Use the -gamedir switch to specify the path that Overload.x86_64 resides in." >&2 36 | exit 1 37 | fi 38 | else 39 | echo "Error: olmod.so not found." >&2 40 | echo "Looked in ${olmoddir}" >&2 41 | echo "You must run olmod.sh while it's in the same directory as olmod.so." >&2 42 | exit 1 43 | fi 44 | else 45 | olmoddylib="${olmoddir}/olmod.dylib" 46 | overload="${gamedir}/Overload.app/Contents/MacOS/Overload" 47 | if [[ -f "${olmoddylib}" ]]; 48 | then 49 | if [[ -f "${overload}" ]]; 50 | then 51 | cd "${olmoddir}" 52 | OLMODDIR="${olmoddir}" DYLD_INSERT_LIBRARIES="${DYLD_INSERT_LIBRARIES:+$DYLD_INSERT_LIBRARIES:}./olmod.dylib" "${overload}" ${olargs} 53 | else 54 | echo "Error: Overload.app not found." >&2 55 | echo "Looked in ${gamedir}" >&2 56 | echo "Use the -gamedir switch to specify the path that Overload.app resides in." >&2 57 | exit 1 58 | fi 59 | else 60 | echo "Error: olmod.dylib not found." >&2 61 | echo "Looked in ${olmoddir}" >&2 62 | echo "You must run olmod.sh while it's in the same directory as olmod.dylib." >&2 63 | exit 1 64 | fi 65 | fi 66 | -------------------------------------------------------------------------------- /GameMod/MPAnticheat.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using UnityEngine; 4 | 5 | namespace GameMod 6 | { 7 | [HarmonyPatch(typeof(PlayerShip), "ProcessFiringControls")] 8 | internal class ProcessFiringControls 9 | { 10 | private static bool CanFire(PlayerShip __instance) 11 | { 12 | return !__instance.m_boosting && __instance.m_wheel_select_state == WheelSelectState.NONE; 13 | } 14 | 15 | private static void Prefix(PlayerShip __instance) 16 | { 17 | if (!GameplayManager.IsMultiplayer) 18 | { 19 | return; 20 | } 21 | 22 | if (!(__instance.c_player.JustPressed(CCInput.FIRE_WEAPON) && CanFire(__instance))) 23 | { 24 | return; 25 | } 26 | 27 | if (__instance.c_player.m_overdrive) 28 | { 29 | return; 30 | } 31 | 32 | if (__instance.c_player.m_weapon_type != WeaponType.CRUSHER && __instance.c_player.m_weapon_type != WeaponType.LANCER) { 33 | return; 34 | } 35 | 36 | if (__instance.m_refire_time > 0) 37 | { 38 | __instance.m_refire_time = Mathf.Max(__instance.m_refire_time, 1f / 20f); 39 | } 40 | return; 41 | } 42 | } 43 | 44 | [HarmonyPatch(typeof(Controls), "ReadControlData")] 45 | internal class ReadControlData 46 | { 47 | private static void Postfix() 48 | { 49 | for (var x = 0; x <= 1; x++) 50 | { 51 | for (var y = 14; y <= 15; y++) 52 | { 53 | if (Controls.m_input_kc[x, y] == KeyCode.Joystick8Button10 || Controls.m_input_kc[x, y] == KeyCode.Joystick8Button11) 54 | { 55 | Controls.m_input_kc[x, y] = KeyCode.None; 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /GameMod/MouseSlidingFix.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Overload; 3 | using UnityEngine; 4 | using HarmonyLib; 5 | using System.Reflection.Emit; 6 | 7 | 8 | namespace GameMod 9 | { 10 | [HarmonyPatch(typeof(PlayerShip), "FixedUpdateProcessControlsInternal")] 11 | public static class MouseSlidingFix_PlayerShip_FixedUpdateProcessControlsInternal 12 | { 13 | /* 14 | * 15 | zero.x *= (float)c_player.m_player_control_options.opt_mouse_sens_x * 0.01f; 16 | zero.y *= (float)c_player.m_player_control_options.opt_mouse_sens_y * 0.01f; 17 | zero.z *= (float)c_player.m_player_control_options.opt_mouse_sens_y * 0.01f; 18 | ... 19 | num4 += zero.x; -- becomes --> num4 = Mathf.Clamp(num4 + zero.x, -1f, 1f); 20 | num3 += zero.y; -- becomes --> num4 = Mathf.Clamp(num3 + zero.y, -1f, 1f); 21 | num5 += zero.z; -- becomes --> num4 = Mathf.Clamp(num5 + zero.z, -1f, 1f); 22 | * 23 | */ 24 | 25 | public static IEnumerable Transpiler(IEnumerable codes) 26 | { 27 | int count = 0; 28 | foreach (var code in codes) 29 | { 30 | if (code.opcode == OpCodes.Stloc_2 || code.opcode == OpCodes.Stloc_3 || (code.opcode == OpCodes.Stloc_S && ((LocalBuilder)code.operand).LocalIndex == 4)) 31 | { 32 | count++; 33 | 34 | if (count > 3 && count < 7) 35 | { 36 | yield return new CodeInstruction(OpCodes.Ldc_R4, -1f); 37 | yield return new CodeInstruction(OpCodes.Ldc_R4, 1f); 38 | yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Mathf), "Clamp", new System.Type[] { typeof(float), typeof(float), typeof(float) })); 39 | } 40 | } 41 | yield return code; 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /GameMod/SPThunderboltShakeFix.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Reflection.Emit; 8 | using System.Runtime.Remoting.Messaging; 9 | using System.Text; 10 | using UnityEngine; 11 | 12 | namespace GameMod 13 | { 14 | internal class SPThunderboltShakeFix 15 | { 16 | // In the singleplayer while charging the thunderbolt. torque towards a random direction gets applied on the ship. 17 | // To bad that the amount of torque is simply charge / frametime 18 | // So with the charge always being in the same range the ships get thrown more and more violently the lower 19 | // the frametime gets (and also more frequently since the method is built as sth that 20 | // should only get called at a fixed rate but ends up getting called every frame) 21 | // 22 | // https://www.youtube.com/watch?v=tfDDnJwi9LY 23 | 24 | [HarmonyPatch(typeof(PlayerShip), "ThunderCharge")] 25 | class FixThunderboltShake 26 | { 27 | private static IEnumerable Transpiler(IEnumerable codes) 28 | { 29 | int state = 0; 30 | foreach (var code in codes) 31 | { 32 | // ldloc_0 is not unique, so only look for it after passing the PlayCameraShake call 33 | if (state == 0 && code.opcode == OpCodes.Callvirt && ((MethodInfo)code.operand).Name == "PlayCameraShake") 34 | state = 1; 35 | 36 | if (state == 1 && code.opcode == OpCodes.Ldloc_0) 37 | { 38 | yield return new CodeInstruction(OpCodes.Ldc_R4, 0.0166667f); 39 | state = 2; 40 | continue; 41 | } 42 | yield return code; 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /olmod/olmod.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | 40 | 41 | Resource Files 42 | 43 | 44 | 45 | 46 | Resource Files 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /GameMod/ServerTrackerPost.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Newtonsoft.Json.Linq; 3 | using Overload; 4 | using System.Collections; 5 | using UnityEngine; 6 | 7 | namespace GameMod 8 | { 9 | [HarmonyPatch(typeof(NetworkMatch), "StartLobby")] 10 | class ServerTrackerPost 11 | { 12 | private static bool started = false; 13 | private static string url; 14 | 15 | public static void Postfix() 16 | { 17 | if (!Config.Settings.Value("isServer") || 18 | string.IsNullOrEmpty(url = Config.Settings.Value("trackerBaseUrl"))) 19 | return; 20 | 21 | if (!started && NetworkManager.IsHeadless()) 22 | { 23 | started = true; 24 | GameManager.m_gm.StartCoroutine(PingRoutine()); 25 | } 26 | } 27 | 28 | public static IEnumerator PingRoutine() 29 | { 30 | for (;;) { 31 | ServerStatLog.TrackerPost("/api/ping", JObject.FromObject(new 32 | { 33 | keepListed = Config.Settings.Value("keepListed"), 34 | name = Config.Settings.Value("serverName"), 35 | notes = Config.Settings.Value("notes"), 36 | version = VersionHandling.OlmodVersion.FullVersionString 37 | })); 38 | yield return new WaitForSecondsRealtime(5 * 60); 39 | } 40 | } 41 | } 42 | 43 | [HarmonyPatch(typeof(Server), "SendPlayersInLobbyToAllClients")] 44 | class ServerLobbyStatus 45 | { 46 | public static void SendToTracker() 47 | { 48 | MatchState state = NetworkMatch.GetMatchState(); 49 | if (state != MatchState.LOBBY && state != MatchState.LOBBY_LOADING_SCENE && state != MatchState.LOBBY_LOAD_COUNTDOWN) 50 | return; 51 | 52 | var obj = ServerStatLog.GetGameData(); 53 | obj["name"] = "Stats"; 54 | obj["type"] = "LobbyStatus"; 55 | 56 | ServerStatLog.TrackerPostStats(obj); 57 | } 58 | 59 | public static void Postfix() 60 | { 61 | SendToTracker(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /GameMod/MPDamageEffects.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Reflection.Emit; 6 | using UnityEngine; 7 | 8 | namespace GameMod 9 | { 10 | // Original orange color overlay deemed too intense in most MP situations, allow for reducing the alpha 11 | [HarmonyPatch(typeof(UIManager), "DrawFullScreenEffects")] 12 | class MPDamageEffects_UIManager_DrawFullScreenEffects 13 | { 14 | static void AdjustAlpha(ref float a) 15 | { 16 | PlayerShip player_ship = GameManager.m_player_ship; 17 | 18 | // Original alpha 19 | a = UIManager.menu_flash_fade * Mathf.Min(0.1f, player_ship.m_damage_flash_slow * 0.1f) + Mathf.Min(0.2f, player_ship.m_damage_flash_fast * 0.2f) * (GameplayManager.IsMultiplayerActive ? ((float)Menus.mms_damageeffect_alpha_mult) / 100f : 1f); 20 | } 21 | 22 | // Change damage color 23 | static IEnumerable Transpiler(IEnumerable codes) 24 | { 25 | int state = 0; 26 | foreach (var code in codes) 27 | { 28 | if (state == 0 && code.opcode == OpCodes.Stloc_2) 29 | { 30 | yield return code; 31 | yield return new CodeInstruction(OpCodes.Ldloca, 2); 32 | yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(MPDamageEffects_UIManager_DrawFullScreenEffects), "AdjustAlpha")); 33 | state = 1; 34 | continue; 35 | } 36 | 37 | yield return code; 38 | } 39 | } 40 | } 41 | 42 | // Original drunk blur effect on damage deemed too intense in many MP situations, allow adjustment 43 | [HarmonyPatch(typeof(Viewer), "UpdateCameraBlurs")] 44 | class MPDamageEffects_Viewer_UpdateCameraBlurs 45 | { 46 | static void Postfix(DrunkBlur ___m_drunk_blur) 47 | { 48 | if (___m_drunk_blur != null) 49 | { 50 | ___m_drunk_blur.strength *= GameplayManager.IsMultiplayerActive ? ((float)Menus.mms_damageeffect_drunk_blur_mult) / 100f : 1f; 51 | } 52 | 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /olgetdata/olgetdata.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {5F11C292-D523-4C7F-88FA-3414F62A001A} 8 | Exe 9 | olgetdata 10 | olgetdata 11 | v3.5 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | ..\x64\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | ..\x64\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /GameMod/Config.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using Newtonsoft.Json.Linq; 5 | using UnityEngine; 6 | 7 | namespace GameMod { 8 | static class Config 9 | { 10 | public static string OLModDir; 11 | public static bool NoDownload; 12 | public static JObject Settings; 13 | 14 | private static void LoadSettings() 15 | { 16 | if (string.IsNullOrEmpty(OLModDir)) 17 | { 18 | Debug.Log("olmod directory unknown " + Environment.GetEnvironmentVariable("OLMODDIR") + " path " + Environment.GetEnvironmentVariable("PATH")); 19 | return; 20 | } 21 | string settingsFilename = "olmodsettings.json"; 22 | if (Core.GameMod.FindArgVal("-config", out string configArg)) 23 | settingsFilename = configArg; 24 | if (!settingsFilename.Contains(Path.DirectorySeparatorChar) && !settingsFilename.Contains(Path.AltDirectorySeparatorChar)) 25 | settingsFilename = Path.Combine(OLModDir, settingsFilename); 26 | try 27 | { 28 | Settings = JObject.Parse(File.ReadAllText(settingsFilename)); 29 | Debug.Log("olmod settings loaded from " + settingsFilename); 30 | } 31 | catch (Exception ex) 32 | { 33 | Debug.Log("olmod settings loading failed " + ex.Message + " " + settingsFilename); 34 | } 35 | } 36 | 37 | public static void Init() 38 | { 39 | OLModDir = Environment.GetEnvironmentVariable("OLMODDIR"); 40 | if (OLModDir == null || OLModDir == "") { 41 | OLModDir = Path.GetDirectoryName(typeof(Core.GameMod).Assembly.Location); 42 | //if (OLModDir != null && OLModDir.EndsWith(Path.DirectorySeparatorChar + "Overload_Data" + Path.DirectorySeparatorChar + "Managed", StringComparison.InvariantCultureIgnoreCase)) 43 | // OLModDir = Path.GetDirectoryName(Path.GetDirectoryName(OLModDir)); 44 | } 45 | Debug.Log("olmod directory " + OLModDir); 46 | NoDownload = Core.GameMod.FindArg("-nodownload"); 47 | Settings = new JObject(); 48 | LoadSettings(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /GameMod/DisableTimeCheat.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | using System.Reflection.Emit; 7 | 8 | namespace GameMod 9 | { 10 | [HarmonyPatch(typeof(GameManager), "FixCurrentDateFormat")] 11 | class DisableTimeCheat 12 | { 13 | static void Prefix() 14 | { 15 | GameManager.m_gm.DisableTimeCheatingDetector(); 16 | GameManager.m_cheating_type = "olmod"; 17 | } 18 | } 19 | 20 | [HarmonyPatch(typeof(PilotManager), "Save")] 21 | class PilotSave 22 | { 23 | public static bool OtherDetected() 24 | { 25 | return GameManager.m_cheating_detected && GameManager.m_cheating_type != "olmod"; 26 | } 27 | 28 | static IEnumerable Transpiler(IEnumerable cs) 29 | { 30 | foreach (var c in cs) 31 | { 32 | if (c.opcode == OpCodes.Ldsfld && ((FieldInfo)c.operand).Name == "m_cheating_detected") 33 | { 34 | yield return new CodeInstruction(OpCodes.Call, 35 | typeof(PilotSave).GetMethod("OtherDetected", BindingFlags.Public | BindingFlags.Static)); 36 | continue; 37 | } 38 | yield return c; 39 | } 40 | } 41 | } 42 | 43 | [HarmonyPatch(typeof(GameplayManager), "DoneLevel")] 44 | internal class DisableTimeCheat_GameplayManager_DoneLevel 45 | { 46 | private static void Postfix() 47 | { 48 | 49 | if (!PilotSave.OtherDetected() && (GameplayManager.IsChallengeMode && GameplayManager.m_level_info.Mission.FileName != "_EDITOR" && ChallengeManager.ChallengeRobotsDestroyed > 0)) 50 | { 51 | try { 52 | Scores.UpdateChallengeScore(GameplayManager.m_level_info.LevelNum, GameplayManager.DifficultyLevel, ChallengeManager.CountdownMode, PilotManager.PilotName, ChallengeManager.ChallengeScore, ChallengeManager.ChallengeRobotsDestroyed, GameplayManager.MostDamagingWeapon(), GameplayManager.AliveTime); 53 | } 54 | catch (Exception ex) { 55 | uConsole.Log(ex.Message); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /GameMod/VSync.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System.Collections.Generic; 4 | using System.Reflection.Emit; 5 | 6 | namespace GameMod 7 | { 8 | 9 | // Stock game shows 60/30hz for what is actually "full/half" sync rates in Unity, simply change labels 10 | [HarmonyPatch(typeof(MenuManager), "GetVSyncSetting")] 11 | class VSync_MenuManager_GetVSyncSetting 12 | { 13 | static IEnumerable Transpiler(IEnumerable codes) 14 | { 15 | foreach (var code in codes) 16 | { 17 | if (code.opcode == OpCodes.Ldstr && (string)code.operand == "60 HZ") 18 | code.operand = "100% MONITOR RATE"; 19 | 20 | if (code.opcode == OpCodes.Ldstr && (string)code.operand == "30 HZ") 21 | code.operand = "50% MONITOR RATE"; 22 | 23 | yield return code; 24 | } 25 | } 26 | } 27 | 28 | // Stock game did not actually implement reverse arrow on vsync option 29 | [HarmonyPatch(typeof(MenuManager), "GraphicsOptionsUpdate")] 30 | class VSync_MenuManager_GraphicsOptionsUpdate 31 | { 32 | static IEnumerable Transpiler(IEnumerable codes) 33 | { 34 | int state = 0; 35 | foreach (var code in codes) 36 | { 37 | 38 | if (state == 0 && code.opcode == OpCodes.Ldsfld && code.operand == AccessTools.Field(typeof(MenuManager), "gfx_vsync")) 39 | state = 1; 40 | 41 | if (state == 1 && code.opcode == OpCodes.Ldc_I4_3) 42 | { 43 | // Original: MenuManager.gfx_vsync = (MenuManager.gfx_vsync + 3 - 1) % 3 44 | // New: MenuManager.gfx_vsync = (MenuManager.gfx_vsync + 3 + 1 - 1 + UIManager.m_select_dir) % 3 45 | yield return new CodeInstruction(OpCodes.Ldc_I4_1); 46 | yield return new CodeInstruction(OpCodes.Add); 47 | yield return new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(UIManager), "m_select_dir")); 48 | yield return new CodeInstruction(OpCodes.Add); 49 | state = 2; 50 | } 51 | 52 | yield return code; 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /GameMod/FixWidescreenDeathBars.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System.Collections.Generic; 4 | using System.Reflection.Emit; 5 | using UnityEngine; 6 | 7 | 8 | //////////////////////////////////////////////////////////////////////////////////////////////////// 9 | /// Author: luponix /// 10 | /// Issue: When dead the hud displays two black bars at the top and bottom. /// 11 | /// These bars have a fixed width of 1000 which is to little at very high aspect ratios. /// 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | namespace GameMod 16 | { 17 | class FixWidescreenDeathBars 18 | { 19 | 20 | [HarmonyPatch(typeof(UIManager), "DrawOverlay")] 21 | class FixWidescreenDeathBars_UIManager_DrawOverlay 22 | { 23 | static IEnumerable Transpiler(ILGenerator ilGen, IEnumerable instructions) 24 | { 25 | int state = 0; 26 | var codes = new List(instructions); 27 | for( int i = 0; i < codes.Count; i++) 28 | { 29 | // look for -460 30 | if( state == 0 && codes[i].opcode == OpCodes.Ldc_R4 && (float)codes[i].operand == -460f) 31 | { 32 | state = 1; 33 | } 34 | 35 | // and change the 1000 after it 36 | if( state == 1 && codes[i].opcode == OpCodes.Ldc_R4 && (float)codes[i].operand == 1000f) 37 | { 38 | codes[i].operand = 3000f; 39 | state = 2; 40 | } 41 | 42 | // look for 460 43 | if( state == 2 && codes[i].opcode == OpCodes.Ldc_R4 && (float)codes[i].operand == 460f) 44 | { 45 | state = 3; 46 | } 47 | 48 | // and change the 1000 after it 49 | if( state == 3 && codes[i].opcode == OpCodes.Ldc_R4 && (float)codes[i].operand == 1000f) 50 | { 51 | codes[i].operand = 3000f; 52 | state = 4; 53 | } 54 | yield return codes[i]; 55 | 56 | } 57 | } 58 | 59 | } 60 | 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /GameMod/Shaders.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using HarmonyLib; 3 | using UnityEngine; 4 | 5 | namespace GameMod { 6 | [HarmonyPatch(typeof(ProFlareBatch), "CreateMat")] 7 | class Shaders_CreateMat { 8 | public static bool Prefix(ProFlareBatch __instance) { 9 | if (!Core.GameMod.VREnabled) { 10 | return true; 11 | } 12 | 13 | __instance.mat = new Material(Shader.Find("Standard")); 14 | __instance.meshRender.material = __instance.mat; 15 | if (__instance._atlas && __instance._atlas.texture) { 16 | __instance.mat.mainTexture = __instance._atlas.texture; 17 | } 18 | 19 | return false; 20 | } 21 | } 22 | 23 | [HarmonyPatch(typeof(ProFlareBatch), "Reset")] 24 | class Shaders_Reset { 25 | private static MethodInfo _ProFlareBatch_CreateHelperTransform_Method = AccessTools.Method(typeof(ProFlareBatch), "CreateHelperTransform"); 26 | private static MethodInfo _ProFlareBatch_SetupMeshes_Method = AccessTools.Method(typeof(ProFlareBatch), "SetupMeshes"); 27 | public static bool Prefix(ProFlareBatch __instance) { 28 | if (!Core.GameMod.VREnabled) { 29 | return true; 30 | } 31 | 32 | if (__instance.helperTransform == null) { 33 | _ProFlareBatch_CreateHelperTransform_Method.Invoke(__instance, null); 34 | } 35 | __instance.mat = new Material((Shader)null); 36 | if (__instance.meshFilter == null) { 37 | __instance.meshFilter = __instance.GetComponent(); 38 | } 39 | if (__instance.meshFilter == null) { 40 | __instance.meshFilter = __instance.gameObject.AddComponent(); 41 | } 42 | __instance.meshRender = __instance.gameObject.GetComponent(); 43 | if (__instance.meshRender == null) { 44 | __instance.meshRender = __instance.gameObject.AddComponent(); 45 | } 46 | if (__instance.FlareCamera == null) { 47 | __instance.FlareCamera = __instance.transform.root.GetComponentInChildren(); 48 | } 49 | __instance.meshRender.material = __instance.mat; 50 | _ProFlareBatch_SetupMeshes_Method.Invoke(__instance, null); 51 | __instance.dirty = true; 52 | 53 | return false; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /GameMod/MessageTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace GameMod 7 | { 8 | public class MessageTypes 9 | { 10 | public const short MsgSetMatchState = 101; 11 | public const short MsgAddMpStatus = 102; 12 | public const short MsgModPrivateData = 103; 13 | public const short MsgJIPJustJoined = 104; 14 | 15 | public const short MsgClientCapabilities = 119; 16 | public const short MsgMPTweaksSet = 120; 17 | public const short MsgCTFPickup = 121; 18 | public const short MsgCTFLose = 122; 19 | public const short MsgCTFNotifyOld = 123; 20 | public const short MsgCTFFlagUpdate = 124; 21 | public const short MsgCTFNotify = 125; 22 | public const short MsgLapCompleted = 126; 23 | public const short MsgSetFullMatchState = 127; 24 | public const short MsgCTFJoinUpdate = 128; 25 | 26 | public const short MsgCreeperSync = 130; 27 | public const short MsgExplode = 131; 28 | // public const short MsgSetAlternatingMissleFire = 132; // No longer used. 29 | public const short MsgSniperPacket = 133; 30 | public const short MsgPlayerWeaponSynchronization = 134; 31 | public const short MsgPlayerAddResource = 135; 32 | public const short MsgPlayerSyncResource = 136; 33 | public const short MsgPlayerSyncAllMissiles = 137; 34 | public const short MsgDetonate = 138; 35 | public const short MsgSetDisconnectedMatchState = 139; 36 | public const short MsgNewPlayerSnapshotToClient = 140; 37 | public const short MsgCTFPlayerStats = 141; 38 | public const short MsgMonsterballPlayerStats = 142; 39 | public const short MsgDeathReview = 143; 40 | 41 | public const short MsgSetTurnRampMode = 145; 42 | public const short MsgChangeTeam = 146; 43 | public const short MsgCustomLoadouts = 147; 44 | public const short MsgSetCustomLoadout = 148; 45 | 46 | public const short MsgSendDamage = 149; 47 | 48 | public const short MsgShareAudioTauntIdentifiers = 150; 49 | public const short MsgRequestAudioTaunt = 151; 50 | public const short MsgPlayAudioTaunt = 152; 51 | public const short MsgAudioTauntPacket = 153; 52 | 53 | public const short MsgEnhancedFirePacket = 154; 54 | public const short MsgPlayerPhysics = 155; 55 | 56 | // Do not use 400, it is in use by Mod-Projdata.dll. 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /linux/mono_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then 4 | echo "Usage: $0 [-c|--copy]" 5 | echo " -c|--copy Copies the generated GameMod.dll to your Overload directory" 6 | exit 7 | fi 8 | 9 | if ! command -v mcs &> /dev/null; then 10 | echo "ERROR: You need the mono 'mcs' compiler (e.g. package 'mono-dev' on Ubuntu)." 11 | exit 1 12 | fi 13 | 14 | if test -z "${OLPATH}"; then 15 | echo "ERROR: Please specify your Overload installation directory in your environment.\n" 16 | echo 17 | echo "Examples:" 18 | echo " Steam: export OLPATH=~/.steam/steam/steamapps/common/Overload" 19 | echo " Steam alt.: export OLPATH=~/.local/share/Steam/steamapps/common/Overload" 20 | echo " GOG: export OLPATH=~/GOG\\ Games/Overload/game" 21 | exit 1 22 | fi 23 | 24 | echo "$OLPATH/Overload_Data" 25 | if ! test -d "${OLPATH}/Overload_Data"; then 26 | echo "ERROR: Could not locate your Overload_Data directory under the given path." 27 | exit 1 28 | fi 29 | 30 | echo ../GameMod/*.cs 31 | 32 | mcs \ 33 | -r:"${OLPATH}"/Overload_Data/Managed/Assembly-CSharp.dll \ 34 | -r:"${OLPATH}"/Overload_Data/Managed/Assembly-CSharp-firstpass.dll \ 35 | -r:"${OLPATH}"/Overload_Data/Managed/DotNetZip.dll \ 36 | -r:"${OLPATH}"/Overload_Data/Managed/Newtonsoft.Json.dll \ 37 | -r:"${OLPATH}"/Overload_Data/Managed/Rewired_Core.dll \ 38 | -r:"${OLPATH}"/Overload_Data/Managed/UnityEngine.AudioModule.dll \ 39 | -r:"${OLPATH}"/Overload_Data/Managed/UnityEngine.CoreModule.dll \ 40 | -r:"${OLPATH}"/Overload_Data/Managed/UnityEngine.dll \ 41 | -r:"${OLPATH}"/Overload_Data/Managed/UnityEngine.IMGUIModule.dll \ 42 | -r:"${OLPATH}"/Overload_Data/Managed/UnityEngine.Networking.dll \ 43 | -r:"${OLPATH}"/Overload_Data/Managed/UnityEngine.ParticleSystemModule.dll \ 44 | -r:"${OLPATH}"/Overload_Data/Managed/UnityEngine.PhysicsModule.dll \ 45 | -r:"${OLPATH}"/Overload_Data/Managed/UnityEngine.UnityWebRequestModule.dll \ 46 | -r:"${OLPATH}"/Overload_Data/Managed/UnityEngine.UnityWebRequestWWWModule.dll \ 47 | -r:"${OLPATH}"/Overload_Data/Managed/UnityEngine.UNETModule.dll \ 48 | -r:../GameMod/0Harmony.dll \ 49 | -target:library \ 50 | -sdk:2 \ 51 | -resource:../GameMod/Resources/meshes,GameMod.Resources.meshes \ 52 | -out:GameMod.dll \ 53 | ../GameMod/*.cs \ 54 | ../GameMod/*/*.cs 55 | 56 | if [ $? -ne 0 ]; then 57 | exit 1 58 | fi 59 | 60 | if [ "$1" = '-c' ] || [ "$1" = '--copy' ]; then 61 | cp -v GameMod.dll ${OLPATH} 62 | fi 63 | -------------------------------------------------------------------------------- /GameMod/LevelError.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Reflection.Emit; 6 | using UnityEngine; 7 | using UnityEngine.SceneManagement; 8 | 9 | namespace GameMod 10 | { 11 | [HarmonyPatch(typeof(UserLevelLoader), "Awake")] 12 | class LevelError_UserLevelLoader_Awake 13 | { 14 | public static bool loadError = false; 15 | 16 | static void UserLevelError() 17 | { 18 | if (Server.IsActive()) 19 | loadError = true; 20 | } 21 | 22 | // Hook call to UserLevelError() after the call to UnityEngine.Debug.LogErrorFormat("USERLEVEL ERROR: {0}", new object[] { ex.Message }) 23 | static IEnumerable Transpiler(IEnumerable codes) 24 | { 25 | int state = 0; 26 | foreach (var code in codes) 27 | { 28 | if (code.opcode == OpCodes.Ldstr && (string)code.operand == "USERLEVEL ERROR: {0}") 29 | state = 1; 30 | 31 | if (state == 1 && code.opcode == OpCodes.Ldarg_0) 32 | { 33 | state = 2; 34 | yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(LevelError_UserLevelLoader_Awake), "UserLevelError")); 35 | } 36 | 37 | yield return code; 38 | } 39 | } 40 | } 41 | 42 | [HarmonyPatch(typeof(GameplayManager), "OnSceneLoaded")] 43 | class LevelError_GameplayManager_OnSceneLoaded 44 | { 45 | static bool Prefix() 46 | { 47 | if (Server.IsActive() && LevelError_UserLevelLoader_Awake.loadError) 48 | { 49 | // End match, disconnect clients and do minor server cleanup 50 | LevelError_UserLevelLoader_Awake.loadError = false; 51 | Debug.Log("Server error loading map, killing match"); 52 | AccessTools.Method(typeof(NetworkMatch), "NetSystemNotifyMatchOver").Invoke(null, null); 53 | NetworkMatch.ExitMatchToMainMenu(); 54 | GameManager.m_player_ship = PlayerShip.Instantiate(); 55 | GameManager.m_local_player = GameManager.m_player_ship.c_player; 56 | AccessTools.Field(typeof(GameplayManager), "m_level_is_loaded").SetValue(null, true); 57 | AccessTools.Field(typeof(GameplayManager), "m_async_operation").SetValue(null, SceneManager.LoadSceneAsync(String.Empty)); 58 | return false; 59 | } 60 | 61 | return true; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /GameMod/MusicCustom.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using UnityEngine; 3 | using Overload; 4 | using System.IO; 5 | 6 | namespace GameMod 7 | { 8 | [HarmonyPatch(typeof(UnityAudio), "PlayCurrentTrack")] 9 | class MusicCustom 10 | { 11 | private static AudioClip LoadLevelAudioClip(LevelInfo level, string name) 12 | { 13 | if (!level.IsAddOn || level.FilePath == null) 14 | return null; 15 | string tmpFilename = null; 16 | string clipFilename = null; 17 | string ext = null; 18 | AudioClip clip = null; 19 | if (level.ZipPath != null) 20 | { 21 | byte[] data = Mission.LoadAddonData(level.ZipPath, Path.Combine(Path.GetDirectoryName(level.FilePath), name), ref ext, 22 | new [] { ".wav", ".ogg" }); 23 | if (data != null) 24 | { 25 | tmpFilename = Path.GetTempFileName() + ext; 26 | File.WriteAllBytes(tmpFilename, data); 27 | clipFilename = tmpFilename; 28 | } 29 | } 30 | else 31 | { 32 | clipFilename = Mission.FindAddonFile(Path.Combine(Path.GetDirectoryName(level.FilePath), name), ref ext, 33 | new[] { ".wav", ".ogg" }); 34 | } 35 | if (clipFilename != null) 36 | { 37 | WWW www = new WWW("file:///" + clipFilename); 38 | while (!www.isDone) 39 | { 40 | } 41 | if (string.IsNullOrEmpty(www.error)) 42 | clip = www.GetAudioClip(true, false); 43 | if (tmpFilename != null) 44 | File.Delete(tmpFilename); 45 | } 46 | return clip; 47 | } 48 | 49 | private static void Postfix(string ___m_current_track, AudioSource ___m_music_source, float ___m_volume_music) 50 | { 51 | if (___m_music_source.clip == null && ___m_current_track != null) // couldn't load built in, try custom 52 | { 53 | Debug.Log("Trying loading custom music " + ___m_current_track); 54 | ___m_music_source.clip = 55 | GameplayManager.Level.Mission.Type == MissionType.ADD_ON ? 56 | GameplayManager.Level.Mission.LoadAudioClip(___m_current_track) : 57 | LoadLevelAudioClip(GameplayManager.Level, ___m_current_track); 58 | if (___m_volume_music > 0f) 59 | ___m_music_source.Play(); 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /GameMod/MPCloak.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System.Collections.Generic; 4 | using System.Reflection.Emit; 5 | 6 | namespace GameMod 7 | { 8 | /// 9 | /// Issue #23 - Reduced Shader cloaked enemies are far too easy to see 10 | /// https://github.com/overload-development-community/olmod/issues/23 11 | /// 12 | [HarmonyPatch(typeof(PlayerShip), "DrawEffectMesh")] 13 | class MPCloak_PlayerShip_DrawEffectMesh 14 | { 15 | public static float adjustedReducedShaderCloakOpacity 16 | { 17 | get 18 | { 19 | return GameplayManager.IsMultiplayerActive ? 0.3f : 1f; 20 | } 21 | } 22 | 23 | private static IEnumerable Transpiler(IEnumerable codes) 24 | { 25 | int state = 0; 26 | foreach (var code in codes) 27 | { 28 | if (code.opcode == OpCodes.Ldsfld && code.operand == AccessTools.Field(typeof(Robot), "matid_opacity")) 29 | state = 1; 30 | 31 | if (state == 1 && code.opcode == OpCodes.Ldc_R4 && (float)code.operand == 1f) 32 | { 33 | state = 2; 34 | code.opcode = OpCodes.Call; 35 | code.operand = AccessTools.Property(typeof(MPCloak_PlayerShip_DrawEffectMesh), "adjustedReducedShaderCloakOpacity").GetGetMethod(); 36 | } 37 | 38 | yield return code; 39 | } 40 | } 41 | } 42 | 43 | 44 | /// 45 | /// Old: UIElement.HUD_ALPHA = Mathf.Max(0.2f, UIElement.HUD_ALPHA - RUtility.FRAMETIME_GAME * 3f); 46 | /// New: UIElement.HUD_ALPHA = Mathf.Max(0.6f, UIElement.HUD_ALPHA - RUtility.FRAMETIME_GAME * 3f); 47 | /// 48 | [HarmonyPatch(typeof(PlayerShip), "Update")] 49 | class MPCloak_PlayerShip_Update 50 | { 51 | private static IEnumerable Transpiler(IEnumerable codes) 52 | { 53 | int state = 0; 54 | foreach (var code in codes) 55 | { 56 | if (state == 0 && code.opcode == OpCodes.Ldfld && code.operand == AccessTools.Field(typeof(Player), "m_cloaked")) 57 | state = 1; 58 | 59 | if (state == 1 && code.opcode == OpCodes.Ldc_R4 && (float)code.operand == 0.2f) 60 | { 61 | state++; 62 | yield return new CodeInstruction(OpCodes.Ldc_R4, 0.6f); 63 | continue; 64 | } 65 | 66 | yield return code; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /GameMod/MatcenHp.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Reflection.Emit; 7 | using System.Text; 8 | 9 | namespace GameMod 10 | { 11 | /// 12 | /// Matcens get extra HP on later levels in a single player campaign. 13 | /// This patch disables this effect if a certain property is set. A corresponding editor change will setup said property appropriately. 14 | /// 15 | [HarmonyPatch(typeof(RobotMatcen), "Start")] 16 | public class Matcen_Start_FixedHp 17 | { 18 | static IEnumerable Transpiler(IEnumerable code) 19 | { 20 | // replace instances of 21 | // stloc.0 (i.e. setting a certain flag) 22 | // with 23 | // ldarg.0 24 | // ldfld m_destroyable 25 | // +-brnull 26 | // | ldarg.0 27 | // | ldfld m_destroyable 28 | // | ldfld m_special_index 29 | // | ldc.i4 2 30 | // | ceq 31 | // | or 32 | // +>stloc.0 33 | // 34 | // In C#: 35 | // flag = this.m_destroyable == null ? flag : (flag | this.m_destroyable.m_special_index == 2); 36 | 37 | foreach (var i in code) 38 | { 39 | if (i.opcode == OpCodes.Stloc_0) 40 | { 41 | var skipLabel = new Label(); 42 | 43 | yield return new CodeInstruction(OpCodes.Ldarg_0); 44 | yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(RobotMatcen), "m_destroyable")); 45 | yield return new CodeInstruction(OpCodes.Brfalse, skipLabel); 46 | { // (if not null) 47 | yield return new CodeInstruction(OpCodes.Ldarg_0); 48 | yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(RobotMatcen), "m_destroyable")); 49 | yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(Destroyable), "m_special_index")); 50 | yield return new CodeInstruction(OpCodes.Ldc_I4_2); 51 | yield return new CodeInstruction(OpCodes.Ceq); 52 | yield return new CodeInstruction(OpCodes.Or); 53 | } 54 | var end = new CodeInstruction(OpCodes.Stloc_0); 55 | end.labels.Add(skipLabel); 56 | yield return end; 57 | } 58 | else 59 | { 60 | yield return i; 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /GameMod/MPContinue.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using HarmonyLib; 3 | using Overload; 4 | using UnityEngine; 5 | 6 | namespace GameMod { 7 | [HarmonyPatch(typeof(UIElement), "DrawMpMatchEndedScoreboard")] 8 | class MPContinueDrawPostMatch 9 | { 10 | private static MethodInfo _UIElement_DrawMpScoreboardRaw_Method = typeof(UIElement).GetMethod("DrawMpScoreboardRaw", BindingFlags.NonPublic | BindingFlags.Instance); 11 | 12 | static bool Prefix(UIElement __instance) 13 | { 14 | if (!MenuManager.m_mp_lan_match) 15 | return true; 16 | var uie = __instance; 17 | uie.DrawMenuBG(); 18 | Vector2 position = uie.m_position; 19 | position.y = UIManager.UI_TOP + 75f; 20 | uie.DrawHeaderLarge(position, Loc.LS("SCOREBOARD")); 21 | position.y += 42f; 22 | MatchMode mode = NetworkMatch.GetMode(); 23 | string s = NetworkMatch.GetModeString(mode) + " - " + GameplayManager.Level.DisplayName; 24 | uie.DrawSubHeader(s, position); 25 | position.y += 20f; 26 | uie.DrawMenuSeparator(position); 27 | position.y += 20f; 28 | position.x = 0f; 29 | position.y += 10f; 30 | _UIElement_DrawMpScoreboardRaw_Method.Invoke(uie, new object[] { position }); 31 | position.y = UIManager.UI_BOTTOM - 30f; 32 | uie.SelectAndDrawItem(Loc.LS("MULTIPLAYER MENU"), position, 100, false); 33 | position.y -= 62f; 34 | uie.SelectAndDrawItem(Loc.LS(NetworkMatch.m_match_req_password == "" ? "CREATE AGAIN" : "JOIN AGAIN"), position, 2, false); 35 | return false; 36 | } 37 | } 38 | 39 | [HarmonyPatch(typeof(MenuManager), "MpMatchOverScoreboardUpdate")] 40 | class MPContinueUpdatePostMatch 41 | { 42 | static void Postfix() 43 | { 44 | if (MenuManager.m_menu_sub_state != MenuSubState.ACTIVE || NetworkManager.IsHeadless() || !UIManager.PushedSelect(100) || 45 | UIManager.m_menu_selection != 2) 46 | return; 47 | MenuManager.PlaySelectSound(); 48 | UIManager.DestroyAll(); 49 | 50 | NetworkMatch.SetNetworkGameClientMode(NetworkMatch.NetworkGameClientMode.Invalid); 51 | NetworkMatch.SetNetworkGameClientMode(NetworkMatch.NetworkGameClientMode.LocalLAN); 52 | MenuManager.ClearMpStatus(); 53 | 54 | if (NetworkMatch.m_match_req_password == "") 55 | { 56 | MenuManager.ChangeMenuState(MenuState.MP_LOCAL_MATCH); 57 | } 58 | else 59 | { 60 | MenuManager.m_mp_status = Loc.LS("JOINING " + MPInternet.ClientModeName()); 61 | NetworkMatch.JoinPrivateLobby(MPInternet.MenuPassword); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /GameMod/AddOnLevelSort.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection; 8 | using UnityEngine; 9 | 10 | namespace GameMod 11 | { 12 | 13 | /// 14 | /// Author: Tobias 15 | /// Created: 2019-05-30 16 | /// Email: tobiasksu@gmail.com 17 | /// Sort addon levels by DisplayName instead of arbitrary load 18 | /// 19 | [HarmonyPatch(typeof(GameManager), "InitializeMissionList")] 20 | class AddOnLevelSort 21 | { 22 | private static FieldInfo _GameManager_m_mission_list_Field = typeof(GameManager).GetField("m_mission_list", BindingFlags.NonPublic | BindingFlags.Static); 23 | private static MethodInfo _GameManager_ScanForLevels_Method = typeof(GameManager).GetMethod("ScanForLevels", BindingFlags.NonPublic | BindingFlags.Instance); 24 | private static FieldInfo _Mission_Levels_Field = typeof(Mission).GetField("Levels", BindingFlags.NonPublic | BindingFlags.Instance); 25 | private static PropertyInfo _LevelInfo_LevelNum_Property = typeof(LevelInfo).GetProperty("LevelNum"); 26 | static void Postfix(GameManager __instance) 27 | { 28 | try 29 | { 30 | // Scan for levels in -missionpath directory 31 | if (Core.GameMod.FindArgVal("-missionpath", out var path) && Directory.Exists(path)) { 32 | var lastMission = ((List)_GameManager_m_mission_list_Field.GetValue(null)).LastOrDefault(); 33 | 34 | int index = 0; 35 | 36 | if (lastMission != null) { 37 | index = lastMission.MissionIndex + 1; 38 | } 39 | 40 | var args = new object[] { path, index }; 41 | _GameManager_ScanForLevels_Method.Invoke(__instance, args); 42 | } 43 | 44 | // Sort addon levels by DisplayName instead of arbitrary load 45 | object __obj = _Mission_Levels_Field.GetValue(GameManager.MultiplayerMission); 46 | List __m_mission_list = (List)__obj; 47 | 48 | __m_mission_list.Sort((a, b) => a.IsAddOn && b.IsAddOn ? a.DisplayName.CompareTo(b.DisplayName) : a.LevelNum-b.LevelNum); 49 | for (var i = 0; i < __m_mission_list.Count; i++) 50 | { 51 | _LevelInfo_LevelNum_Property.DeclaringType.GetProperty("LevelNum"); 52 | _LevelInfo_LevelNum_Property.SetValue(__m_mission_list[i], i, BindingFlags.NonPublic | BindingFlags.Instance, null, null, null); 53 | } 54 | _Mission_Levels_Field.SetValue(GameManager.MultiplayerMission, __m_mission_list); 55 | } catch (Exception ex) 56 | { 57 | Debug.Log("InitializeMissionList() patch failed - " + ex.Message); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /GameMod/CustomLevelResources.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | 6 | namespace GameMod 7 | { 8 | [HarmonyPatch()] 9 | class CustomLevelMaterials 10 | { 11 | static Dictionary extra_materials = new Dictionary(StringComparer.InvariantCultureIgnoreCase) { 12 | { "alien_cave_crystals_02a", "alien_cave_crystals_02a/alien_cave_crystals_02a" }, 13 | { "alien_decals_01a_dark", "alien_decals_01a/alien_decals_01a_dark" }, 14 | { "alien_decals_02a_dark", "alien_decals_02a/alien_decals_02a_dark" }, 15 | { "alien_decals_02b_dark", "alien_decals_02b/alien_decals_02b_dark" }, 16 | { "alien_decals_03g_dark", "alien_decals_03g/alien_decals_03g_dark" }, 17 | { "om_signs_ambient_02b", "om_signs_ambient_02b/om_signs_ambient_02b" } 18 | }; 19 | 20 | static MethodInfo TargetMethod() 21 | { 22 | return typeof(UserLevelLoader).Assembly.GetType("ResourceDatabase").GetMethod("LookupMaterial", BindingFlags.Static | BindingFlags.Public); 23 | } 24 | 25 | static void Postfix(string name, ref string __result) 26 | { 27 | if (__result != null) 28 | return; 29 | if (extra_materials.TryGetValue(name, out string value)) 30 | __result = value; 31 | } 32 | } 33 | 34 | [HarmonyPatch()] 35 | class CustomLevelPrefabs 36 | { 37 | static Dictionary extra_prefabs = new Dictionary(StringComparer.InvariantCultureIgnoreCase) { 38 | { "entity_prop_alien_socket", "entity_prop_alien_socket" }, 39 | { "entity_prop_monitor_secret1", "entity_prop_monitor_secret1" }, 40 | { "entity_prop_monitor_secret2", "entity_prop_monitor_secret2" }, 41 | { "entity_prop_monitor_tn1", "entity_prop_monitor_tn1" }, 42 | { "entity_prop_monitor_tn2", "entity_prop_monitor_tn2" }, 43 | { "entity_prop_monitor_tn3", "entity_prop_monitor_tn3" }, 44 | { "entity_prop_fan_tn3", "entity_prop_fan_tn3" }, 45 | { "entity_prop_fan_tn4", "entity_prop_fan_tn4" }, 46 | { "entity_prop_fan_tn_corner", "entity_prop_fan_tn_corner" }, 47 | { "entity_prop_reactor_om16", "entity_prop_reactor_om16" }, 48 | { "entity_trigger_box_lava_alien", "entity_trigger_box_lava_alien" }, 49 | { "entity_trigger_box_lava_normal", "entity_trigger_box_lava_normal" } 50 | }; 51 | 52 | static MethodInfo TargetMethod() 53 | { 54 | return typeof(UserLevelLoader).Assembly.GetType("ResourceDatabase").GetMethod("LookupPrefab", BindingFlags.Static | BindingFlags.Public); 55 | } 56 | 57 | static void Postfix(string name, ref string __result) 58 | { 59 | if (__result != null) 60 | return; 61 | if (extra_prefabs.TryGetValue(name, out string value)) 62 | __result = value; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /GameMod/ReversePatches.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using UnityEngine; 6 | using UnityEngine.Networking; 7 | using Overload; 8 | using HarmonyLib; 9 | 10 | namespace GameMod 11 | { 12 | /* 13 | * Any private methods that would normally need a Reflection invocation can be added 14 | * here for common reference UNLESS they have also been patched. 15 | * 16 | * -- naming ex. "Server.PrivateMethod()" is now "OL_Server.PrivateMethod()". 17 | */ 18 | 19 | /// Overload.Client - private method reverse patches 20 | // ==================== 21 | // Overload.Client 22 | // ==================== 23 | [HarmonyPatch] 24 | public static class OL_Client 25 | { 26 | [HarmonyReversePatch] 27 | [HarmonyPatch(typeof(Client), "GetPlayerFromNetId")] 28 | public static Player GetPlayerFromNetId(NetworkInstanceId net_id) 29 | { 30 | throw new NotImplementedException("GetPlayerFromNetId stub"); 31 | } 32 | } 33 | 34 | /// Overload.Server - private method reverse patches 35 | // ==================== 36 | // Overload.Server 37 | // ==================== 38 | [HarmonyPatch] 39 | public static class OL_Server 40 | { 41 | [HarmonyReversePatch] 42 | [HarmonyPatch(typeof(Server), "QueueNewInputsForProcessingOnServer")] 43 | public static void QueueNewInputsForProcessingOnServer(Player player, PlayerInputMessage msg) 44 | { 45 | throw new NotImplementedException("QueueNewInputsForProcessingOnServer stub"); 46 | } 47 | 48 | [HarmonyReversePatch] 49 | [HarmonyPatch(typeof(Server), "SendJustPressedOrJustReleasedMessage")] 50 | public static void SendJustPressedOrJustReleasedMessage(Player player, CCInput button) 51 | { 52 | throw new NotImplementedException("SendJustPressedOrJustReleasedMessage stub"); 53 | } 54 | } 55 | 56 | /* 57 | /// Overload.UIElement - private method reverse patches 58 | // ==================== 59 | // Overload.UIElement 60 | // ==================== 61 | [HarmonyPatch] 62 | public static class OL_UIElement 63 | { 64 | [HarmonyReversePatch] 65 | [HarmonyPatch(typeof(UIElement), "DrawScoreHeader")] 66 | public static void DrawScoreHeader(UIElement instance, Vector2 pos, float col1, float col2, float col3, float col4, float col5, bool score = false) 67 | { 68 | { 69 | throw new NotImplementedException("DrawScoreHeader stub"); 70 | } 71 | } 72 | 73 | [HarmonyReversePatch] 74 | [HarmonyPatch(typeof(UIElement), "DrawScoresForTeam")] 75 | public static int DrawScoresForTeam(UIElement instance, MpTeam team, Vector2 pos, float col1, float col2, float col3, float col4, float col5) 76 | { 77 | { 78 | throw new NotImplementedException("DrawScoresForTeam stub"); 79 | } 80 | } 81 | } 82 | */ 83 | } 84 | -------------------------------------------------------------------------------- /OLModUnitTest/HelperClasses/FakeGameList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using GameMod; 5 | 6 | namespace OLModUnitTest.HelperClasses { 7 | internal class FakeGameList 8 | { 9 | private readonly List _levels = new List(); 10 | private readonly FakeFileSystem _fileSystem; 11 | 12 | public FakeGameList(FakeFileSystem fileSystem) 13 | { 14 | _fileSystem = fileSystem; 15 | } 16 | 17 | internal IEnumerable GetMPLevels() 18 | { 19 | return _levels; 20 | } 21 | 22 | internal void AddMPLevel(string filename) 23 | { 24 | if (filename.EndsWith(".mp", StringComparison.InvariantCultureIgnoreCase)) 25 | { 26 | string filenameInternal = Path.GetFileNameWithoutExtension(filename); 27 | string displayName = filenameInternal.Replace('_', ' ').ToUpper(); 28 | var levelInfo = new LevelDownloadInfo(filenameInternal, displayName, null, filename, null); 29 | _levels.Add(levelInfo); 30 | } 31 | else if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) 32 | { 33 | FakeFileSystem.FakeFile zip; 34 | try 35 | { 36 | zip = _fileSystem.GetFile(filename); 37 | } 38 | catch (Exception) 39 | { 40 | return; 41 | } 42 | foreach (var level in zip.Levels) 43 | { 44 | string filenameInternal = Path.GetFileNameWithoutExtension(level.Key); 45 | string displayName = filenameInternal.Replace('_', ' ').ToUpper(); 46 | string levelIdHash = string.Format("{0}:{1:X8}", level.Key.ToUpper(), level.Value); 47 | var levelInfo = new LevelDownloadInfo(filenameInternal, displayName, filename, null, levelIdHash); 48 | _levels.Add(levelInfo); 49 | } 50 | } 51 | } 52 | 53 | internal void RemoveMPLevel(int index) 54 | { 55 | _levels.RemoveAt(index); 56 | } 57 | 58 | internal int GetAddOnLevelIndex(string levelIdHash) 59 | { 60 | return _levels.FindIndex(levelInfo => levelInfo.IdStringHash == levelIdHash); 61 | } 62 | 63 | private class LevelDownloadInfo : ILevelDownloadInfo 64 | { 65 | public LevelDownloadInfo(string fileName, string displayName, string zipPath, string filePath, 66 | string idStringHash) 67 | { 68 | FileName = fileName; 69 | DisplayName = displayName; 70 | ZipPath = zipPath; 71 | FilePath = filePath; 72 | IdStringHash = idStringHash; 73 | } 74 | 75 | public string FileName { get; } 76 | 77 | public string DisplayName { get; } 78 | 79 | public string ZipPath { get; } 80 | 81 | public string FilePath { get; } 82 | 83 | public string IdStringHash { get; } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /GameMod/MoreAudio.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | 6 | namespace mod_moreaudio 7 | { 8 | static class MoreAudio 9 | { 10 | public static IEnumerable ChangeMaxSources(IEnumerable cs) { 11 | //int n = 0; 12 | foreach (var c in cs) 13 | { 14 | if (c.opcode == OpCodes.Ldc_I4 && (int)c.operand == 128) 15 | { 16 | c.operand = 512; 17 | //n++; 18 | } 19 | yield return c; 20 | } 21 | //Debug.Log(n); 22 | } 23 | } 24 | 25 | [HarmonyPatch] 26 | class MoreAudioIterator 27 | { 28 | static MethodBase TargetMethod() 29 | { 30 | foreach (var x in typeof(UnityAudio).GetNestedTypes(BindingFlags.NonPublic)) 31 | if (x.Name.Contains("LoadSoundEffects")) 32 | { 33 | //UnityEngine.Debug.Log("Found LoadSoundEffects iterator " + x.Name); 34 | return x.GetMethod("MoveNext"); 35 | } 36 | return null; 37 | } 38 | 39 | static IEnumerable Transpiler(IEnumerable cs) { return MoreAudio.ChangeMaxSources(cs); } 40 | } 41 | 42 | [HarmonyPatch(typeof(UnityAudio), "InitializeForNewLevel")] 43 | class MoreAudio2 { static IEnumerable Transpiler(IEnumerable cs) { return MoreAudio.ChangeMaxSources(cs); } } 44 | 45 | [HarmonyPatch(typeof(UnityAudio), "AdjustSFXPitch")] 46 | class MoreAudio3 { static IEnumerable Transpiler(IEnumerable cs) { return MoreAudio.ChangeMaxSources(cs); } } 47 | 48 | [HarmonyPatch(typeof(UnityAudio), "UpdateAudio")] 49 | class MoreAudio4 { static IEnumerable Transpiler(IEnumerable cs) { return MoreAudio.ChangeMaxSources(cs); } } 50 | 51 | [HarmonyPatch(typeof(UnityAudio), "PauseAllSounds")] 52 | class MoreAudio5 { static IEnumerable Transpiler(IEnumerable cs) { return MoreAudio.ChangeMaxSources(cs); } } 53 | 54 | [HarmonyPatch(typeof(UnityAudio), "RestartSoundsFromLoadGame")] 55 | class MoreAudio6 { static IEnumerable Transpiler(IEnumerable cs) { return MoreAudio.ChangeMaxSources(cs); } } 56 | 57 | [HarmonyPatch(typeof(UnityAudio), "Serialize")] 58 | class MoreAudio7 { static IEnumerable Transpiler(IEnumerable cs) { return MoreAudio.ChangeMaxSources(cs); } } 59 | 60 | [HarmonyPatch(typeof(UnityAudio), "Deserialize")] 61 | class MoreAudio8 { static IEnumerable Transpiler(IEnumerable cs) { return MoreAudio.ChangeMaxSources(cs); } } 62 | 63 | [HarmonyPatch(typeof(UnityAudio), MethodType.Constructor)] 64 | class MoreAudio9 { static IEnumerable Transpiler(IEnumerable cs) { return MoreAudio.ChangeMaxSources(cs); } } 65 | 66 | [HarmonyPatch(typeof(UnityAudio), "FindNextOpenAudioSlot")] 67 | class MoreAudio10 { static IEnumerable Transpiler(IEnumerable cs) { return MoreAudio.ChangeMaxSources(cs); } } 68 | } 69 | -------------------------------------------------------------------------------- /GameMod/VersionHandling/OlmodVersion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Linq; 4 | using System.Text.RegularExpressions; 5 | using Newtonsoft.Json.Linq; 6 | using Overload; 7 | using UnityEngine; 8 | using UnityEngine.Networking; 9 | using Version = System.Version; 10 | 11 | namespace GameMod.VersionHandling { 12 | 13 | public static class OlmodVersion 14 | { 15 | public static Version LatestKnownVersion { get; set; } 16 | public static Version RunningVersion { get; set; } 17 | 18 | public static bool Modded { get; set; } 19 | 20 | private static string _fullVersionString; 21 | 22 | public static string FullVersionString 23 | { 24 | get 25 | { 26 | if (_fullVersionString == null) 27 | { 28 | Setup(); 29 | 30 | // do not include revision unless explicitly set to non-zero in the assembly version 31 | string maybeRevision = RunningVersion.Revision > 0 ? $".{RunningVersion.Revision}" : ""; 32 | _fullVersionString = $"olmod {RunningVersion.ToString(3)}{maybeRevision}{(Modded ? " **MODDED**" : "")}"; 33 | } 34 | return _fullVersionString; 35 | } 36 | } 37 | 38 | public const string NewVersionReleasesUrl = "https://github.com/overload-development-community/olmod/releases"; 39 | 40 | private const string NewVersionCheckUrl = "https://api.github.com/repos/overload-development-community/olmod/releases"; 41 | 42 | public static void Setup() 43 | { 44 | RunningVersion = LatestKnownVersion = typeof(OlmodVersion).Assembly.GetName().Version; 45 | } 46 | 47 | public static void TryRefreshLatestKnownVersion() 48 | { 49 | if (_fullVersionString == null) { 50 | Setup(); 51 | } 52 | 53 | if (GameManager.m_gm != null) 54 | { 55 | GameManager.m_gm.StartCoroutine(VersionRequest()); 56 | } 57 | } 58 | 59 | static IEnumerator VersionRequest() 60 | { 61 | UnityWebRequest request = UnityWebRequest.Get(NewVersionCheckUrl); 62 | request.timeout = 10; 63 | yield return request.SendWebRequest(); 64 | 65 | if (request.isNetworkError || request.isHttpError) 66 | { 67 | Debug.Log(request.error); 68 | yield break; 69 | } 70 | else 71 | { 72 | JArray releases; 73 | try 74 | { 75 | releases = JArray.Parse(request.downloadHandler.text); 76 | 77 | if (releases == null) { 78 | yield break; 79 | } 80 | } 81 | catch (Exception e) 82 | { 83 | Debug.Log($"Unable to parse github releases response: {e}"); 84 | yield break; 85 | } 86 | 87 | Match versionMatch1 = Regex.Match(releases.First()["tag_name"].GetString(), @"\d+\.\d+\.\d+(\.\d+)?"); 88 | if (versionMatch1.Success) 89 | { 90 | // store the latest known versions so we can alert players on the main menu screen if the running version is outdated 91 | LatestKnownVersion = new Version(versionMatch1.Value); 92 | } 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /GameMod/VersionHandling/PatchVersionInfo.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Reflection.Emit; 6 | using UnityEngine; 7 | 8 | namespace GameMod.VersionHandling 9 | { 10 | 11 | [HarmonyPatch(typeof(GameplayManager), "Initialize")] 12 | class PCheckNewOlmodVersion 13 | { 14 | static void Postfix() 15 | { 16 | OlmodVersion.TryRefreshLatestKnownVersion(); 17 | } 18 | } 19 | 20 | // Display olmod related information on main menu 21 | [HarmonyPatch(typeof(UIElement), "DrawMainMenu")] 22 | class PVersionDisplay 23 | { 24 | static string GetVersion(string stockVersion) 25 | { 26 | return $"{stockVersion} {OlmodVersion.FullVersionString.ToUpperInvariant()}"; 27 | } 28 | 29 | // append olmod version to the regular version display on the main menu 30 | static IEnumerable Transpiler(IEnumerable codes) 31 | { 32 | var _string_Format_Method = AccessTools.Method(typeof(String), "Format", new Type[] { typeof(string), typeof(object), typeof(object), typeof(object) }); 33 | var _versionPatch_GetVersion_Method = AccessTools.Method(typeof(PVersionDisplay), "GetVersion"); 34 | 35 | int state = 0; 36 | 37 | foreach (var code in codes) 38 | { 39 | // this.DrawStringSmall(string.Format(Loc.LS("VERSION {0}.{1} BUILD {2}"), GameManager.Version.Major, GameManager.Version.Minor, GameManager.Version.Build), position, 0.5f, StringOffset.RIGHT, UIManager.m_col_ui1, 0.5f, -1f); 40 | if (state == 0 && code.opcode == OpCodes.Call && code.operand == _string_Format_Method) 41 | { 42 | state = 1; 43 | yield return code; 44 | yield return new CodeInstruction(OpCodes.Call, _versionPatch_GetVersion_Method); 45 | continue; 46 | } 47 | 48 | yield return code; 49 | } 50 | } 51 | 52 | 53 | // Draw olmod modified label and olmod update button, if applicable 54 | static void Postfix(UIElement __instance) 55 | { 56 | 57 | Vector2 pos = new Vector2(UIManager.UI_RIGHT - 10f, -155f - 60f + 50f + 40f); 58 | __instance.DrawStringSmall("UNOFFICIAL MODIFIED VERSION", pos, 59 | 0.35f, StringOffset.RIGHT, UIManager.m_col_ui1, 0.5f, -1f); 60 | 61 | // notify the player when a newer olmod verision is available 62 | if (OlmodVersion.RunningVersion < OlmodVersion.LatestKnownVersion) 63 | { 64 | pos = new Vector2(UIManager.UI_RIGHT - 10f, -155f - 60f + 50f + 60f); 65 | __instance.DrawStringSmall("OLMOD UPDATE AVAILABLE", pos, 66 | 0.35f, StringOffset.RIGHT, UIManager.m_col_ui1, 0.5f, -1f); 67 | 68 | __instance.SelectAndDrawHalfItem($"GET OLMOD {OlmodVersion.LatestKnownVersion}", new Vector2(UIManager.UI_RIGHT - 140f, 279f), 12, false); 69 | } 70 | } 71 | } 72 | 73 | // On select, get latest olmod version from main menu 74 | [HarmonyPatch(typeof(MenuManager), "MainMenuUpdate")] 75 | class PHandleOlmodUpdateSelect 76 | { 77 | private static void Postfix() 78 | { 79 | if (MenuManager.m_menu_sub_state == MenuSubState.ACTIVE && !NetworkManager.IsHeadless() && UIManager.PushedSelect(-1)) 80 | { 81 | if (UIManager.m_menu_selection == 12) 82 | { 83 | Application.OpenURL(OlmodVersion.NewVersionReleasesUrl); 84 | MenuManager.PlayCycleSound(1f, 1f); 85 | } 86 | } 87 | } 88 | } 89 | 90 | } -------------------------------------------------------------------------------- /GameMod/MPThunderboltPassthrough.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using Overload; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection.Emit; 7 | using System.Text; 8 | 9 | namespace GameMod 10 | { 11 | // Original Author: Tobias 12 | // Allows Thunderbolt projectiles to penetrate through ships 13 | class MPThunderboltPassthrough 14 | { 15 | 16 | public static bool isAllowed = false; 17 | 18 | [HarmonyPatch(typeof(Projectile), "OnTriggerEnter")] 19 | internal class MPWeaponBehavior_Projectile_OnTriggerEnter 20 | { 21 | private void MaybeExplode(bool damaged_something, Projectile proj) 22 | { 23 | bool enablePassthrough = proj.m_type == ProjPrefab.proj_thunderbolt && GameplayManager.IsMultiplayer && isAllowed; 24 | 25 | if (!enablePassthrough) 26 | proj.Explode(damaged_something); 27 | } 28 | 29 | private static IEnumerable Transpiler(IEnumerable codes) 30 | { 31 | foreach (var code in codes) 32 | { 33 | if (code.opcode == OpCodes.Call && code.operand == AccessTools.Method(typeof(Projectile), "Explode")) 34 | { 35 | yield return new CodeInstruction(OpCodes.Ldarg_0); 36 | yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(MPWeaponBehavior_Projectile_OnTriggerEnter), "MaybeExplode")); 37 | continue; 38 | } 39 | 40 | yield return code; 41 | } 42 | } 43 | } 44 | 45 | 46 | 47 | /* 48 | [HarmonyPatch(typeof(Projectile), "Explode")] 49 | internal class MPClassic_Projectile_Explode 50 | { 51 | private static bool Prefix(Projectile __instance) 52 | { 53 | return !(isAllowed && __instance.m_type == ProjPrefab.proj_thunderbolt && __instance.m_alive); 54 | } 55 | } 56 | 57 | [HarmonyPatch(typeof(Projectile), "ProcessCollision")] 58 | internal class MPWeaponBehavior_Projectile_ProcessCollision 59 | { 60 | private static void ThunderboltExplode(Projectile proj, int layer) 61 | { 62 | 63 | bool flag = layer == 11 || layer == 16; 64 | if (!(flag & isAllowed)) 65 | { 66 | proj.m_alive = false; 67 | proj.Explode(!flag); 68 | } 69 | } 70 | 71 | private static void FakeExplode(Projectile proj, int layer) 72 | { 73 | 74 | } 75 | 76 | private static IEnumerable Transpiler(IEnumerable codes) 77 | { 78 | var projectile_m_alive_Field = AccessTools.Field(typeof(Projectile), "m_alive"); 79 | 80 | int state = 0; 81 | foreach (CodeInstruction code in codes) 82 | { 83 | if (code.opcode == OpCodes.Ldc_I4_S && (sbyte)code.operand == 26) 84 | state = 1; 85 | 86 | if (state == 1 && code.opcode == OpCodes.Call && code.operand == AccessTools.Method(typeof(Projectile), "Explode", null, null)) 87 | { 88 | yield return new CodeInstruction(OpCodes.Ldarg_0); 89 | yield return new CodeInstruction(OpCodes.Ldc_I4_0); 90 | yield return new CodeInstruction(OpCodes.Stfld, projectile_m_alive_Field); 91 | state = 2; 92 | } 93 | 94 | if (code.opcode == OpCodes.Ldc_I4_S && (sbyte)code.operand == 16) 95 | state = 3; 96 | 97 | if (state == 3 && code.opcode == OpCodes.Call && code.operand == AccessTools.Method(typeof(Projectile), "Explode", null, null)) 98 | { 99 | List