Skip to content

Commit c0d13a1

Browse files
authored
Friendly Fire Limits v1.2.0 - Mono support
- Adds mono support (dedicated servers) - CI integration
1 parent 7f3a716 commit c0d13a1

File tree

3 files changed

+75
-88
lines changed

3 files changed

+75
-88
lines changed

Si_FriendlyFireLimits/Si_FF.cs

Lines changed: 47 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -21,40 +21,24 @@ You should have received a copy of the GNU General Public License
2121
along with this program. If not, see <http://www.gnu.org/licenses/>.
2222
*/
2323

24-
using UnityEngine;
25-
using MelonLoader;
24+
#if NET6_0
2625
using Il2Cpp;
26+
#endif
27+
28+
using MelonLoader;
2729
using HarmonyLib;
2830
using Si_FriendlyFireLimits;
29-
using static MelonLoader.MelonLogger;
30-
using System.Diagnostics;
31+
using System;
32+
using SilicaAdminMod;
3133

32-
[assembly: MelonInfo(typeof(FriendlyFireLimits), "Friendly Fire Limits", "1.1.5", "databomb")]
34+
[assembly: MelonInfo(typeof(FriendlyFireLimits), "Friendly Fire Limits", "1.2.0", "databomb", "https://github.com/data-bomb/Silica")]
3335
[assembly: MelonGame("Bohemia Interactive", "Silica")]
36+
[assembly: MelonOptionalDependencies("Admin Mod")]
3437

3538
namespace Si_FriendlyFireLimits
3639
{
3740
public class FriendlyFireLimits : MelonMod
3841
{
39-
public static void PrintError(Exception exception, string? message = null)
40-
{
41-
if (message != null)
42-
{
43-
MelonLogger.Msg(message);
44-
}
45-
string error = exception.Message;
46-
error += "\n" + exception.TargetSite;
47-
error += "\n" + exception.StackTrace;
48-
Exception? inner = exception.InnerException;
49-
if (inner != null)
50-
{
51-
error += "\n" + inner.Message;
52-
error += "\n" + inner.TargetSite;
53-
error += "\n" + inner.StackTrace;
54-
}
55-
MelonLogger.Error(error);
56-
}
57-
5842
static MelonPreferences_Category _modCategory;
5943
static MelonPreferences_Entry<float> _UnitOnUnitNonExplosionDamageMultipler;
6044
static MelonPreferences_Entry<float> _UnitOnUnitExplosionDamageMultiplier;
@@ -73,37 +57,41 @@ public override void OnInitializeMelon()
7357
}
7458
if (_UnitOnUnitNonExplosionDamageMultipler == null)
7559
{
76-
_UnitOnUnitNonExplosionDamageMultipler = _modCategory.CreateEntry<float>("FriendlyFire_UnitAttacked_DamageMultiplier", 0.05f);
60+
_UnitOnUnitNonExplosionDamageMultipler = _modCategory.CreateEntry<float>("FriendlyFire_UnitAttacked_DamageMultiplier", 0.75f);
7761
}
7862
if (_UnitOnUnitExplosionDamageMultiplier == null)
7963
{
80-
_UnitOnUnitExplosionDamageMultiplier = _modCategory.CreateEntry<float>("FriendlyFire_UnitAttacked_DamageMultiplier_Exp", 0.8f);
64+
_UnitOnUnitExplosionDamageMultiplier = _modCategory.CreateEntry<float>("FriendlyFire_UnitAttacked_DamageMultiplier_Exp", 0.85f);
8165
}
8266
if (_UnitOnStructureExplosionDamageMultiplier == null)
8367
{
8468
_UnitOnStructureExplosionDamageMultiplier = _modCategory.CreateEntry<float>("FriendlyFire_StructureAttacked_DamageMultiplier_Exp", 0.65f);
8569
}
8670
if (_UnitOnStructureNonExplosionDamageMultiplier == null)
8771
{
88-
_UnitOnStructureNonExplosionDamageMultiplier = _modCategory.CreateEntry<float>("FriendlyFire_StructureAttacked_DamageMultiplier_NonExp", 0.15f);
72+
_UnitOnStructureNonExplosionDamageMultiplier = _modCategory.CreateEntry<float>("FriendlyFire_StructureAttacked_DamageMultiplier_NonExp", 0.0f);
8973
}
9074
if (_HarvesterPassthrough == null)
9175
{
9276
_HarvesterPassthrough = _modCategory.CreateEntry<bool>("FriendlyFire_Passthrough_Harvester_Damage", true);
9377
}
9478
}
9579

96-
[HarmonyPatch(typeof(Il2Cpp.GameByteStreamReader), nameof(Il2Cpp.GameByteStreamReader.GetGameByteStreamReader))]
80+
[HarmonyPatch(typeof(GameByteStreamReader), nameof(GameByteStreamReader.GetGameByteStreamReader))]
9781
static class GetGameByteStreamReaderPrePatch
9882
{
99-
public static void Prefix(Il2Cpp.GameByteStreamReader __result, Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStructArray<byte> __0, int __1, bool __2)
83+
#if NET6_0
84+
public static void Prefix(GameByteStreamReader __result, Il2CppInterop.Runtime.InteropTypes.Arrays.Il2CppStructArray<byte> __0, int __1, bool __2)
85+
#else
86+
public static void Prefix(GameByteStreamReader __result, byte[] __0, int __1, bool __2)
87+
#endif
10088
{
10189
try
10290
{
10391
// byte[0] = (2) Byte
10492
// byte[1] = ENetworkPacketType
105-
Il2Cpp.ENetworkPacketType packetType = (Il2Cpp.ENetworkPacketType)__0[1];
106-
if (packetType == Il2Cpp.ENetworkPacketType.ObjectReceiveDamage)
93+
ENetworkPacketType packetType = (ENetworkPacketType)__0[1];
94+
if (packetType == ENetworkPacketType.ObjectReceiveDamage)
10795
{
10896
// byte[2] = (8) PackedUInt32
10997
// byte[3:4] = NetID
@@ -117,7 +105,7 @@ public static void Prefix(Il2Cpp.GameByteStreamReader __result, Il2CppInterop.Ru
117105
victimNetID = __0[3];
118106
}
119107

120-
Il2Cpp.NetworkComponent victimNetComp = Il2Cpp.NetworkComponent.GetNetObject(victimNetID);
108+
NetworkComponent victimNetComp = NetworkComponent.GetNetObject(victimNetID);
121109

122110
uint attackerNetID;
123111
if (__0[21] >= 241)
@@ -129,7 +117,7 @@ public static void Prefix(Il2Cpp.GameByteStreamReader __result, Il2CppInterop.Ru
129117
attackerNetID = __0[21];
130118
}
131119

132-
Il2Cpp.NetworkComponent attackerNetComp = Il2Cpp.NetworkComponent.GetNetObject(attackerNetID);
120+
NetworkComponent attackerNetComp = NetworkComponent.GetNetObject(attackerNetID);
133121

134122
// byte[5] = (8) PackedUInt32
135123
// byte[6:7] = colliderIndex
@@ -145,40 +133,40 @@ public static void Prefix(Il2Cpp.GameByteStreamReader __result, Il2CppInterop.Ru
145133

146134
if (victimNetComp != null && attackerNetComp != null && colliderIndex >= 1)
147135
{
148-
Il2Cpp.BaseGameObject victimBase = victimNetComp.Owner;
149-
Il2Cpp.BaseGameObject attackerBase = attackerNetComp.Owner;
136+
BaseGameObject victimBase = victimNetComp.Owner;
137+
BaseGameObject attackerBase = attackerNetComp.Owner;
150138

151139
if (victimBase == null || attackerBase == null)
152140
{
153141
return;
154142
}
155143

156-
Il2Cpp.Team victimTeam = victimBase.Team;
157-
Il2Cpp.Team attackerTeam = attackerBase.Team;
144+
Team victimTeam = victimBase.Team;
145+
Team attackerTeam = attackerBase.Team;
158146

159147
// if they'rea on the same team but allow fall damage
160148
if (victimTeam == attackerTeam && victimBase != attackerBase)
161149
{
162150
// Victim Object Type
163-
Il2Cpp.ObjectInfoType victimType = victimBase.ObjectInfo.ObjectType;
151+
ObjectInfoType victimType = victimBase.ObjectInfo.ObjectType;
164152
// Attacker Object Type
165-
Il2Cpp.ObjectInfoType attackerType = attackerBase.ObjectInfo.ObjectType;
153+
ObjectInfoType attackerType = attackerBase.ObjectInfo.ObjectType;
166154

167-
Il2Cpp.EDamageType damagetype = (Il2Cpp.EDamageType)__0[13];
155+
EDamageType damagetype = (EDamageType)__0[13];
168156
float damage = BitConverter.ToSingle(__0, 8);
169157

170158
// block units attacking friendly units
171-
if (victimType == Il2Cpp.ObjectInfoType.Unit && attackerType == Il2Cpp.ObjectInfoType.Unit)
159+
if (victimType == ObjectInfoType.Unit && attackerType == ObjectInfoType.Unit)
172160
{
173161
// check if we should skip harvester damage
174-
if (_HarvesterPassthrough.Value && victimBase.ObjectInfo.UnitType == Il2Cpp.UnitType.Harvester)
162+
if (_HarvesterPassthrough.Value && victimBase.ObjectInfo.UnitType == UnitType.Harvester)
175163
{
176164
return;
177165
}
178166

179167
// AoE does more damage (by default)
180168
byte[] modifiedDamage;
181-
if (damagetype != Il2Cpp.EDamageType.Explosion)
169+
if (damagetype != EDamageType.Explosion)
182170
{
183171
modifiedDamage = BitConverter.GetBytes(damage * _UnitOnUnitExplosionDamageMultiplier.Value);
184172
}
@@ -196,11 +184,11 @@ public static void Prefix(Il2Cpp.GameByteStreamReader __result, Il2CppInterop.Ru
196184
}
197185

198186
// reduce damage of units attacking friendly structures
199-
if (victimType == Il2Cpp.ObjectInfoType.Structure && attackerType == Il2Cpp.ObjectInfoType.Unit)
187+
if (victimType == ObjectInfoType.Structure && attackerType == ObjectInfoType.Unit)
200188
{
201189
// AoE goes through with more damage (by default)
202190
byte[] modifiedDamage;
203-
if (damagetype == Il2Cpp.EDamageType.Explosion)
191+
if (damagetype == EDamageType.Explosion)
204192
{
205193
modifiedDamage = BitConverter.GetBytes(damage * _UnitOnStructureExplosionDamageMultiplier.Value);
206194
}
@@ -220,50 +208,50 @@ public static void Prefix(Il2Cpp.GameByteStreamReader __result, Il2CppInterop.Ru
220208
}
221209
catch (Exception error)
222210
{
223-
PrintError(error, "Failed to run GameByteStreamReader::GetGameByteStreamReader");
211+
HelperMethods.PrintError(error, "Failed to run GameByteStreamReader::GetGameByteStreamReader");
224212
}
225213
}
226214
}
227215

228216
// this applies to the host
229-
[HarmonyPatch(typeof(Il2Cpp.DamageManager), nameof(Il2Cpp.DamageManager.ApplyDamage))]
217+
[HarmonyPatch(typeof(DamageManager), nameof(DamageManager.ApplyDamage))]
230218
static class ApplyPatchApplyDamage
231219
{
232-
public static bool Prefix(Il2Cpp.DamageManager __instance, ref float __result, UnityEngine.Collider __0, float __1, Il2Cpp.EDamageType __2, UnityEngine.GameObject __3, UnityEngine.Vector3 __4)
220+
public static bool Prefix(DamageManager __instance, ref float __result, UnityEngine.Collider __0, float __1, EDamageType __2, UnityEngine.GameObject __3, UnityEngine.Vector3 __4)
233221
{
234222
try
235223
{
236224
// Victim Team
237-
Il2Cpp.BaseGameObject victimBase = __instance.Owner;
238-
Il2Cpp.Team victimTeam = __instance.Team;
225+
BaseGameObject victimBase = __instance.Owner;
226+
Team victimTeam = __instance.Team;
239227
// Attacker Team
240-
Il2Cpp.BaseGameObject attackerBase = Il2Cpp.GameFuncs.GetBaseGameObject(__3);
241-
Il2Cpp.Team attackerTeam = attackerBase.Team;
228+
BaseGameObject attackerBase = GameFuncs.GetBaseGameObject(__3);
229+
Team attackerTeam = attackerBase.Team;
242230

243231
// if they'rea on the same team but allow fall damage
244232
if (victimTeam == attackerTeam && victimBase != attackerBase)
245233
{
246234
// Victim Object Type
247-
Il2Cpp.ObjectInfoType victimType = victimBase.ObjectInfo.ObjectType;
235+
ObjectInfoType victimType = victimBase.ObjectInfo.ObjectType;
248236
// Attacker Object Type
249-
Il2Cpp.ObjectInfoType attackerType = attackerBase.ObjectInfo.ObjectType;
237+
ObjectInfoType attackerType = attackerBase.ObjectInfo.ObjectType;
250238

251239
// block units attacking friendly units
252-
if (victimType == Il2Cpp.ObjectInfoType.Unit && attackerType == Il2Cpp.ObjectInfoType.Unit)
240+
if (victimType == ObjectInfoType.Unit && attackerType == ObjectInfoType.Unit)
253241
{
254242
// but don't block AoE and don't block if victim is a harvester
255-
if (__2 != Il2Cpp.EDamageType.Explosion && victimBase.ObjectInfo.UnitType != Il2Cpp.UnitType.Harvester)
243+
if (__2 != EDamageType.Explosion && victimBase.ObjectInfo.UnitType != UnitType.Harvester)
256244
{
257245
__result = __1 * _UnitOnUnitNonExplosionDamageMultipler.Value;
258246
return false;
259247
}
260248
}
261249

262250
// reduce damage of units attacking friendly structures
263-
if (victimType == Il2Cpp.ObjectInfoType.Structure && attackerType == Il2Cpp.ObjectInfoType.Unit)
251+
if (victimType == ObjectInfoType.Structure && attackerType == ObjectInfoType.Unit)
264252
{
265253
// AoE goes through with more damage
266-
if (__2 == Il2Cpp.EDamageType.Explosion)
254+
if (__2 == EDamageType.Explosion)
267255
{
268256
__result = __1 * _UnitOnStructureExplosionDamageMultiplier.Value;
269257
}
@@ -278,7 +266,7 @@ public static bool Prefix(Il2Cpp.DamageManager __instance, ref float __result, U
278266
}
279267
catch (Exception error)
280268
{
281-
PrintError(error, "Failed to run DamageManager::ApplyDamage");
269+
HelperMethods.PrintError(error, "Failed to run DamageManager::ApplyDamage");
282270
}
283271

284272
return true;
Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,13 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
5-
<ImplicitUsings>enable</ImplicitUsings>
4+
<TargetFrameworks>net6.0;netstandard2.1</TargetFrameworks>
65
<Nullable>enable</Nullable>
76
</PropertyGroup>
87

98
<ItemGroup>
10-
<Reference Include="0Harmony">
11-
<HintPath>..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Silica\MelonLoader\net6\0Harmony.dll</HintPath>
12-
</Reference>
13-
<Reference Include="Assembly-CSharp">
14-
<HintPath>..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Silica\MelonLoader\Il2CppAssemblies\Assembly-CSharp.dll</HintPath>
15-
</Reference>
16-
<Reference Include="Il2CppInterop.Runtime">
17-
<HintPath>..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Silica\MelonLoader\net6\Il2CppInterop.Runtime.dll</HintPath>
18-
</Reference>
19-
<Reference Include="Il2Cppmscorlib">
20-
<HintPath>..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Silica\MelonLoader\Il2CppAssemblies\Il2Cppmscorlib.dll</HintPath>
21-
</Reference>
22-
<Reference Include="MelonLoader">
23-
<HintPath>..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Silica\MelonLoader\net6\MelonLoader.dll</HintPath>
24-
</Reference>
25-
<Reference Include="UnityEngine">
26-
<HintPath>..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Silica\MelonLoader\Il2CppAssemblies\UnityEngine.dll</HintPath>
27-
</Reference>
28-
<Reference Include="UnityEngine.CoreModule">
29-
<HintPath>..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Silica\MelonLoader\Il2CppAssemblies\UnityEngine.CoreModule.dll</HintPath>
30-
</Reference>
31-
<Reference Include="UnityEngine.InputLegacyModule">
32-
<HintPath>..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Silica\MelonLoader\Il2CppAssemblies\UnityEngine.InputLegacyModule.dll</HintPath>
33-
</Reference>
34-
<Reference Include="UnityEngine.PhysicsModule">
35-
<HintPath>..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Silica\MelonLoader\Il2CppAssemblies\UnityEngine.PhysicsModule.dll</HintPath>
36-
</Reference>
9+
<PackageReference Include="Silica-MelonLoader-AdminMod" Version="2.0.0" />
10+
<PackageReference Include="Silica-MelonLoader-Dependencies" Version="0.8.19" />
3711
</ItemGroup>
3812

3913
</Project>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.6.33723.286
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Si_FriendlyFireLimits", "Si_FriendlyFireLimits.csproj", "{E894FEBB-E0CC-4313-B3B0-8C07F1033DA5}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{E894FEBB-E0CC-4313-B3B0-8C07F1033DA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{E894FEBB-E0CC-4313-B3B0-8C07F1033DA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{E894FEBB-E0CC-4313-B3B0-8C07F1033DA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{E894FEBB-E0CC-4313-B3B0-8C07F1033DA5}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {3A87A634-87CC-425D-848D-FBA077B41442}
24+
EndGlobalSection
25+
EndGlobal

0 commit comments

Comments
 (0)