Skip to content

Commit

Permalink
Combat balance changes and bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
starfi5h committed Sep 7, 2024
1 parent fd7c760 commit fcec714
Show file tree
Hide file tree
Showing 12 changed files with 308 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ protected override void ProcessPacket(CombatStatDamagePacket packet, NebulaConne
{
if (IsHost)
{
Multiplayer.Session.Server.SendPacketExclude(packet, conn);
if (packet.TargetAstroId > 1000000)
{
Multiplayer.Session.Server.SendPacketExclude(packet, conn);
}
}

SkillTarget target;
Expand Down Expand Up @@ -48,7 +51,11 @@ protected override void ProcessPacket(CombatStatDamagePacket packet, NebulaConne

using (Multiplayer.Session.Combat.IsIncomingRequest.On())
{
GameMain.spaceSector.skillSystem.DamageObject(packet.Damage, packet.Slice, ref target, ref caster);
var skillSystem = GameMain.spaceSector.skillSystem;
var tmp = skillSystem.playerAlive;
skillSystem.playerAlive = true;
skillSystem.DamageObject(packet.Damage, packet.Slice, ref target, ref caster);
skillSystem.playerAlive = tmp;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ public class MechaAliveEventProcessor : PacketProcessor<MechaAliveEventPacket>
{
protected override void ProcessPacket(MechaAliveEventPacket packet, NebulaConnection conn)
{
if (IsHost)
{
Multiplayer.Session.Server.SendPacketExclude(packet, conn);
}

using (Multiplayer.Session.World.GetRemotePlayersModels(out var remotePlayersModels))
{
if (!remotePlayersModels.TryGetValue(packet.PlayerId, out var playerModel)) return;
Expand Down
3 changes: 2 additions & 1 deletion NebulaPatcher/Patches/Dynamic/DFGBaseComponent_Patch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ public static bool UpdateHatred_Prefix(DFGBaseComponent __instance, long gameTic
for (var pid = 0; pid < players.Length; pid++)
{
if (players[pid].planetId != planetId) continue;
if (((Vector3)enemyPool[__instance.enemyId].pos - players[pid].position).sqrMagnitude < 8100.0)
// Balance: Increase base player alert range from 90 to 200
if (((Vector3)enemyPool[__instance.enemyId].pos - players[pid].position).sqrMagnitude < 40000.0)
{
__instance.UnderAttack(players[pid].position, 50f, 120);
}
Expand Down
25 changes: 25 additions & 0 deletions NebulaPatcher/Patches/Dynamic/EnemyDFGroundSystem_Patch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,31 @@ public static bool ExecuteDeferredUnitFormation_Prefix(EnemyDFGroundSystem __ins
return true;
}

[HarmonyPrefix]
[HarmonyPatch(nameof(EnemyDFGroundSystem.CanEraseBase))]
public static bool CanEraseBase_Prefix(DFGBaseComponent _base, ref bool __result)
{
if (!Multiplayer.IsActive) return true;

if (_base == null || _base.id == 0)
{
__result = true;
return false;
}
// Skip __instance.builders.buffer[_base.builderId].sp check as it may have different value
var pbuilders = _base.pbuilders;
for (var i = 2; i < pbuilders.Length; i++)
{
if (pbuilders[i].instId > 0)
{
__result = false;
return false;
}
}
__result = true;
return false;
}

[HarmonyPrefix]
[HarmonyPatch(nameof(EnemyDFGroundSystem.NotifyEnemyKilled))]
public static bool NotifyEnemyKilled_Prefix()
Expand Down
2 changes: 1 addition & 1 deletion NebulaPatcher/Patches/Dynamic/PlayerAction_Death_Patch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal class PlayerAction_Death_Patch
[HarmonyPatch(nameof(PlayerAction_Death.Respawn))]
public static void Respawn_Prefix(PlayerAction_Death __instance, int _respawnMode)
{
if (!Multiplayer.IsActive) return;
if (!Multiplayer.IsActive || __instance.player != GameMain.mainPlayer) return;

if (!__instance.player.isAlive && !__instance.respawning)
{
Expand Down
17 changes: 17 additions & 0 deletions NebulaPatcher/Patches/Dynamic/Player_Patch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ public static bool Kill_Prefix(Player __instance)
{
Multiplayer.Session.Network.SendPacket(new MechaAliveEventPacket(
Multiplayer.Session.LocalPlayer.Id, MechaAliveEventPacket.EStatus.Kill));
ThrowItemsInInventory(__instance);
}
return true;
}
Expand All @@ -179,5 +180,21 @@ public static bool PrepareRedeploy_Prefix(Player __instance)
return false;
}

private static void ThrowItemsInInventory(Player player)
{
// Balance: Drop half of item in inventory when player killed
const float DROP_RATE = 0.5f;
for (var i = 0; i < player.package.size; i++)
{
var itemId = 0;
var itemCount = (int)(player.package.grids[i].count * DROP_RATE);
player.package.TakeItemFromGrid(i, ref itemId, ref itemCount, out var itemInc);
if (itemId > 0 && itemCount > 0)
{
player.ThrowTrash(itemId, itemCount, itemInc, 0, 0);
}
}
}

#endregion
}
31 changes: 24 additions & 7 deletions NebulaPatcher/Patches/Dynamic/SkillSystem_Patch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ public static void CollectPlayerStates_Postfix(SkillSystem __instance)
// Set those flags to false so AddSpaceEnemyHatred can add threat correctly for client's skill in host
__instance.playerIsSailing = false;
__instance.playerIsWarping = false;
// Set this flag to true so AddSpaceEnemyHatred can add threat correctly from craft/skill of other players even if host is dead (dedicated server)
__instance.playerAlive = true;
}

[HarmonyPostfix]
Expand Down Expand Up @@ -91,14 +93,29 @@ public static bool MechaEnergyShieldResist_Prefix(SkillSystem __instance, ref bo
[HarmonyPatch(nameof(SkillSystem.DamageObject))]
public static void DamageObject_Prefix(int damage, int slice, ref SkillTarget target, ref SkillTarget caster)
{
if (caster.type != ETargetType.Craft || target.type != ETargetType.Enemy
|| target.astroId <= 1000000 // Only sync for space target
if (!(caster.type == ETargetType.Craft || caster.type == ETargetType.Player)
|| target.type != ETargetType.Enemy
|| !Multiplayer.IsActive || Multiplayer.Session.Combat.IsIncomingRequest.Value) return;

var packet = new CombatStatDamagePacket(damage, slice, in target, in caster);
// Change the caster to player as craft (space fleet) is not sync yet
packet.CasterType = (short)ETargetType.Player;
packet.CasterId = Multiplayer.Session.LocalPlayer.Id;
Multiplayer.Session.Network.SendPacket(packet);
if (target.astroId > 1000000) // Sync for space enemy
{
var packet = new CombatStatDamagePacket(damage, slice, in target, in caster)
{
// Change the caster to player as craft (space fleet) is not sync yet
CasterType = (short)ETargetType.Player,
CasterId = Multiplayer.Session.LocalPlayer.Id
};
Multiplayer.Session.Network.SendPacket(packet);
}
else if (target.astroId == GameMain.localPlanet?.id) // Sync for local planet
{
var packet = new CombatStatDamagePacket(damage, slice, in target, in caster)
{
// Change the caster to player as craft (space fleet) is not sync yet
CasterType = (short)ETargetType.Player,
CasterId = Multiplayer.Session.LocalPlayer.Id
};
Multiplayer.Session.Network.SendPacketToLocalPlanet(packet);
}
}
}
8 changes: 8 additions & 0 deletions NebulaPatcher/Patches/Misc/Dedicated_Server_Patches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,12 @@ public static bool RecalculatePhysicsShape_Prefix(PlanetATField __instance)

return false;
}

[HarmonyPostfix]
[HarmonyPatch(typeof(PlanetATField), nameof(PlanetATField.TestRelayCondition))]
public static void StopLanding(PlanetATField __instance, ref bool __result)
{
// Balance: Stop relay landing when there are 7 or more working shield generators
__result &= !(__instance.energy > 0 && __instance.generatorCount >= 7);
}
}
86 changes: 86 additions & 0 deletions NebulaPatcher/Patches/Transpilers/DFGBaseComponent_Transpiler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#region

using System.Collections.Generic;
using System.Reflection.Emit;
using HarmonyLib;
using NebulaModel.Logger;
using NebulaWorld;

#endregion

namespace NebulaPatcher.Patches.Transpilers;

[HarmonyPatch(typeof(DFGBaseComponent))]
internal class DFGBaseComponent_Transpiler
{
[HarmonyTranspiler]
[HarmonyPatch(nameof(DFGBaseComponent.UpdateFactoryThreat))]
public static IEnumerable<CodeInstruction> UpdateFactoryThreat_Transpiler(IEnumerable<CodeInstruction> instructions)
{
try
{
/* Launch assault for player who on remote planet and has no power buildings
from:
if (num24 == 0.0 && this.groundSystem.local_player_grounded_alive)
{
num24 = 10.0;
ref Vector3 ptr2 = ref this.groundSystem.local_player_pos;
vector = new Vector3(ptr2.x - num, ptr2.y - num2, ptr2.z - num3);
num18 = num16;
num19 = num17;
}
to:
>> if (num24 == 0.0 && LaunchCondition(this))
{
...
}
*/

var codeMatcher = new CodeMatcher(instructions)
.End()
.MatchBack(true,
new CodeMatch(OpCodes.Ldloc_S),
new CodeMatch(OpCodes.Ldc_R8),
new CodeMatch(OpCodes.Bne_Un),
new CodeMatch(OpCodes.Ldarg_0),
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(DFGBaseComponent), nameof(DFGBaseComponent.groundSystem))),
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(EnemyDFGroundSystem), nameof(EnemyDFGroundSystem.local_player_grounded_alive))),
new CodeMatch(OpCodes.Brfalse));

if (codeMatcher.IsInvalid)
{
Log.Warn("DFGBaseComponent.UpdateFactoryThreat: Can't find target");
return codeMatcher.InstructionEnumeration();
}
codeMatcher.Advance(-2)
.RemoveInstruction()
.SetAndAdvance(OpCodes.Call, AccessTools.Method(typeof(DFGBaseComponent_Transpiler), nameof(LaunchCondition)));

return codeMatcher.InstructionEnumeration();
}
catch (System.Exception e)
{
Log.Warn("Transpiler DFGBaseComponent.UpdateFactoryThreat failed.");
Log.Warn(e);
return instructions;
}
}

static bool LaunchCondition(DFGBaseComponent @this)
{
if (!Multiplayer.IsActive || @this.groundSystem.local_player_alive == true) return @this.groundSystem.local_player_alive;

var planetId = @this.groundSystem.planet.id;
var players = Multiplayer.Session.Combat.Players;
for (var i = 0; i < players.Length; i++)
{
if (players[i].isAlive && players[i].planetId == planetId)
{
@this.groundSystem.local_player_pos = players[i].position;
Log.Info($"Base attack LaunchCondition: player[{i}] planeId{planetId}");
return true;
}
}
return false;
}
}
100 changes: 100 additions & 0 deletions NebulaPatcher/Patches/Transpilers/EnemyDFHiveSystem_Transpiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using NebulaModel.Logger;
using NebulaModel.Packets.Combat.SpaceEnemy;
using NebulaWorld;
using UnityEngine;

#endregion

Expand Down Expand Up @@ -111,6 +112,105 @@ public static IEnumerable<CodeInstruction> KeyTickLogic_Transpiler(IEnumerable<C
}
}

[HarmonyTranspiler]
[HarmonyPatch(nameof(EnemyDFHiveSystem.AssaultingWavesDetermineAI))]
public static IEnumerable<CodeInstruction> AssaultingWavesDetermineAI_Transpiler(IEnumerable<CodeInstruction> instructions)
{
try
{
/* Launch assault for player who on remote planet and has no power buildings
from:
if (!flag2 && this.gameData.localPlanet != null && this.gameData.localPlanet.type != EPlanetType.Gas && this.gameData.localPlanet.star == this.starData)
{
flag2 = true;
num5 = this.gameData.localPlanet.astroId;
vector2 = (vector = this.sector.skillSystem.playerSkillTargetL);
}
if (flag2) {
...
this.LaunchLancerAssault(aggressiveLevel, vector, vector2, num5, num2, num15);
}
to:
if (!flag2 && this.gameData.localPlanet != null && this.gameData.localPlanet.type != EPlanetType.Gas && this.gameData.localPlanet.star == this.starData)
{
flag2 = true;
num5 = this.gameData.localPlanet.astroId;
vector2 = (vector = this.sector.skillSystem.playerSkillTargetL);
}
>> if (LaunchCondition(flag2, this, ref num5, ref vector, ref vector2))
{
...
this.LaunchLancerAssault(aggressiveLevel, vector, vector2, num5, num2, num15);
}
*/

var codeMatcher = new CodeMatcher(instructions)
.End()
.MatchBack(true,
new CodeMatch(OpCodes.Ldc_I4_1),
new CodeMatch(OpCodes.Stloc_S), // flag2 = true
new CodeMatch(OpCodes.Ldarg_0),
new CodeMatch(OpCodes.Ldfld),
new CodeMatch(OpCodes.Callvirt),
new CodeMatch(OpCodes.Callvirt),
new CodeMatch(OpCodes.Stloc_S), // num5 = this.gameData.localPlanet.astroId
new CodeMatch(OpCodes.Ldarg_0),
new CodeMatch(OpCodes.Ldfld),
new CodeMatch(OpCodes.Ldfld),
new CodeMatch(OpCodes.Ldfld),
new CodeMatch(OpCodes.Dup),
new CodeMatch(OpCodes.Stloc_S), // vector
new CodeMatch(OpCodes.Stloc_S), // vector2
new CodeMatch(OpCodes.Ldloc_S),
new CodeMatch(OpCodes.Brfalse));

if (codeMatcher.IsInvalid)
{
Log.Warn("EnemyDFHiveSystem.AssaultingWavesDetermineAI: Can't find target");
return codeMatcher.InstructionEnumeration();
}
var tarPos = codeMatcher.InstructionAt(-2).operand;
var maxHatredPos = codeMatcher.InstructionAt(-3).operand;
var targetAstroId = codeMatcher.InstructionAt(-9).operand;

codeMatcher.Insert(
new CodeInstruction(OpCodes.Ldarg_0),
new CodeInstruction(OpCodes.Ldloca_S, targetAstroId),
new CodeInstruction(OpCodes.Ldloca_S, tarPos),
new CodeInstruction(OpCodes.Ldloca_S, maxHatredPos),
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(EnemyDFHiveSystem_Transpiler), nameof(LaunchCondition))));

return codeMatcher.InstructionEnumeration();
}
catch (System.Exception e)
{
Log.Warn("Transpiler EnemyDFHiveSystem.AssaultingWavesDetermineAI failed.");
Log.Warn(e);
return instructions;
}
}

static bool LaunchCondition(bool originalFlag, EnemyDFHiveSystem @this, ref int targetAstroId, ref Vector3 tarPos, ref Vector3 maxHatredPos)
{
if (!Multiplayer.IsActive || originalFlag == true) return originalFlag;

var players = Multiplayer.Session.Combat.Players;
for (var i = 0; i < players.Length; i++)
{
if (players[i].isAlive && players[i].starId == @this.starData.id && players[i].planetId > 0)
{
var planet = GameMain.galaxy.PlanetById(players[i].planetId);
if (planet == null || planet.type == EPlanetType.Gas) continue;

targetAstroId = players[i].planetId;
tarPos = maxHatredPos = players[i].skillTargetL;
Log.Info($"Hive attack LaunchCondition: player[{i}] planeId{targetAstroId}");
return true;
}
}
return originalFlag;
}

static void RealizePlanetBase(DFRelayComponent dFRelayComponent, SpaceSector spaceSector)
{
if (!Multiplayer.IsActive || Multiplayer.Session.IsServer)
Expand Down
Loading

0 comments on commit fcec714

Please sign in to comment.