Skip to content

Commit

Permalink
Fix Nosk glob projectiles
Browse files Browse the repository at this point in the history
  • Loading branch information
Extremelyd1 committed Jul 15, 2024
1 parent 7f32dca commit f27d3fa
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 1 deletion.
80 changes: 79 additions & 1 deletion HKMP/Game/Client/Entity/Action/EntityFsmActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,16 @@ private static void EmitRandomInterceptInstructions<TValue, TObject>(ILCursor c)
// Push the current instance of the class onto the stack
c.Emit(OpCodes.Ldarg_0);

// Emit a delegate that pops the current int off the stack (our random value) and
// Emit a delegate that pops the current random value off the stack and puts it back after some processing
c.EmitDelegate<Func<TValue, TObject, TValue>>((value, instance) => {
// We need to check whether the game object that is being spawned with this action is not an object
// managed by the system. Because if so, we do not store the random values because the action for it
// is not being networked. Only the game object spawn is networked with an EntitySpawn packet directly.
var gameObject = ReflectionHelper.GetField<TObject, GameObject>(instance, "gameObject");
if (gameObject != null && IsObjectInRegistry(gameObject)) {
return value;
}

if (!RandomActionValues.TryGetValue(instance, out var queue)) {
queue = new Queue<object>();
RandomActionValues[instance] = queue;
Expand All @@ -238,6 +246,32 @@ private static void FlingObjectsFromGlobalPoolOnEnter(ILContext il) {
EmitRandomInterceptInstructions<float, FlingObjectsFromGlobalPool>(c);
EmitRandomInterceptInstructions<float, FlingObjectsFromGlobalPool>(c);
EmitRandomInterceptInstructions<float, FlingObjectsFromGlobalPool>(c);

// Reset cursor
c = new ILCursor(il);

// Goto the next call instruction for ObjectPoolExtensions.Spawn
c.GotoNext(i => i.MatchCall(typeof(ObjectPoolExtensions), "Spawn"));

// Move the cursor after the call instruction
c.Index++;

// Push the current instance of the class onto the stack
c.Emit(OpCodes.Ldarg_0);

// Emit a delegate that pops the spawned game object off the stack and uses it, then puts it back again
c.EmitDelegate<Func<GameObject, FlingObjectsFromGlobalPool, GameObject>>((go, action) => {
Logger.Debug($"Delegate of FlingObjectsFromGlobalPool: {go.name}");
if (EntitySpawnEvent != null && EntitySpawnEvent.Invoke(new EntitySpawnDetails {
Type = EntitySpawnType.FsmAction,
Action = action,
GameObject = go
})) {
Logger.Debug("FlingObjectsFromGlobalPool IL spawned object is entity");
}

return go;
});
} catch (Exception e) {
Logger.Error($"Could not change FlingObjectsFromGlobalPool#OnEnter IL:\n{e}");
}
Expand All @@ -258,6 +292,32 @@ private static void FlingObjectsFromGlobalPoolVelOnEnter(ILContext il) {
EmitRandomInterceptInstructions<float, FlingObjectsFromGlobalPoolVel>(c);
EmitRandomInterceptInstructions<float, FlingObjectsFromGlobalPoolVel>(c);
EmitRandomInterceptInstructions<float, FlingObjectsFromGlobalPoolVel>(c);

// Reset cursor
c = new ILCursor(il);

// Goto the next call instruction for ObjectPoolExtensions.Spawn
c.GotoNext(i => i.MatchCall(typeof(ObjectPoolExtensions), "Spawn"));

// Move the cursor after the call instruction
c.Index++;

// Push the current instance of the class onto the stack
c.Emit(OpCodes.Ldarg_0);

// Emit a delegate that pops the spawned game object off the stack and uses it, then puts it back again
c.EmitDelegate<Func<GameObject, FlingObjectsFromGlobalPoolVel, GameObject>>((go, action) => {
Logger.Debug($"Delegate of FlingObjectsFromGlobalPoolVel: {go.name}");
if (EntitySpawnEvent != null && EntitySpawnEvent.Invoke(new EntitySpawnDetails {
Type = EntitySpawnType.FsmAction,
Action = action,
GameObject = go
})) {
Logger.Debug("FlingObjectsFromGlobalPoolVel IL spawned object is entity");
}

return go;
});
} catch (Exception e) {
Logger.Error($"Could not change FlingObjectsFromGlobalPoolVel#OnEnter IL:\n{e}");
}
Expand Down Expand Up @@ -408,6 +468,15 @@ private static void ApplyNetworkDataFromAction(EntityNetworkData data, SpawnObje
#region FlingObjectsFromGlobalPool

private static bool GetNetworkDataFromAction(EntityNetworkData data, FlingObjectsFromGlobalPool action) {
// We first check whether the game object belonging to the Rigidbody2D in the action is an object that is
// managed by the system. Because if so, it means that we have already caught its spawning in the IL hook
// for the action and sent an EntitySpawn packet instead. So we need not also network this action separately.
var rigidbody = ReflectionHelper.GetField<FlingObjectsFromGlobalPool, Rigidbody2D>(action, "rb2d");
if (rigidbody != null && rigidbody.gameObject != null && IsObjectInRegistry(rigidbody.gameObject)) {
Logger.Debug("Skipping getting network data for FlingObjectsFromGlobalPool, because spawned objects are managed by system");
return false;
}

var position = Vector3.zero;

var spawnPoint = action.spawnPoint.Value;
Expand Down Expand Up @@ -521,6 +590,15 @@ private static void ApplyNetworkDataFromAction(EntityNetworkData data, FlingObje
#region FlingObjectsFromGlobalPoolVel

private static bool GetNetworkDataFromAction(EntityNetworkData data, FlingObjectsFromGlobalPoolVel action) {
// We first check whether the game object belonging to the Rigidbody2D in the action is an object that is
// managed by the system. Because if so, it means that we have already caught its spawning in the IL hook
// for the action and sent an EntitySpawn packet instead. So we need not also network this action separately.
var rigidbody = ReflectionHelper.GetField<FlingObjectsFromGlobalPoolVel, Rigidbody2D>(action, "rb2d");
if (rigidbody != null && rigidbody.gameObject != null && IsObjectInRegistry(rigidbody.gameObject)) {
Logger.Debug("Skipping getting network data for FlingObjectsFromGlobalPool, because spawned objects are managed by system");
return false;
}

var position = Vector3.zero;

var spawnPoint = action.spawnPoint.Value;
Expand Down
55 changes: 55 additions & 0 deletions HKMP/Game/Client/Entity/EntitySpawner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,22 @@ List<PlayMakerFSM> clientFsms
return SpawnRadianceNailFromComb(clientFsms[0]);
}

if (spawningType == EntityType.WingedNosk) {
if (spawnedType == EntityType.InfectedBalloon) {
return SpawnInfectedBalloonWingedNoskObject(clientFsms[0]);
}

if (spawnedType == EntityType.NoskBlob) {
return SpawnWingedNoskBlobObject(clientFsms[0]);
}
}

if (spawningType == EntityType.WingedNoskGlobDropper && spawnedType == EntityType.NoskBlob) {
return SpawnWingedNoskGlobDropper(clientFsms[0]);
}

Logger.Warn($"No implementation for spawning entity game object: {spawningType}, {spawnedType}");

return null;
}

Expand Down Expand Up @@ -217,6 +233,24 @@ private static GameObject SpawnFromGlobalPool(SpawnObjectFromGlobalPool action,
return spawnedObject;
}

private static GameObject SpawnFromFlingGlobalPool(FlingObjectsFromGlobalPool action, GameObject gameObject) {
var position = Vector3.zero;
var zero = Vector3.zero;
if (action.spawnPoint.Value != null) {
position = action.spawnPoint.Value.transform.position;
if (!action.position.IsNone) {
position += action.position.Value;
}
} else {
if (!action.position.IsNone) {
position = action.position.Value;
}
}

var spawnedObject = gameObject.Spawn(position, Quaternion.Euler(zero));
return spawnedObject;
}

private static GameObject SpawnFromFlingGlobalPoolTime(
FlingObjectsFromGlobalPoolTime action,
GameObject gameObject
Expand Down Expand Up @@ -483,4 +517,25 @@ private static GameObject SpawnRadianceNailFromComb(PlayMakerFSM fsm) {

return SpawnFromGlobalPool(action, gameObject);
}

private static GameObject SpawnInfectedBalloonWingedNoskObject(PlayMakerFSM fsm) {
var action = fsm.GetFirstAction<SpawnObjectFromGlobalPool>("Summon");
var gameObject = action.gameObject.Value;

return SpawnFromGlobalPool(action, gameObject);
}

private static GameObject SpawnWingedNoskBlobObject(PlayMakerFSM fsm) {
var action = fsm.GetFirstAction<FlingObjectsFromGlobalPool>("Spit 1");
var gameObject = action.gameObject.Value;

return SpawnFromFlingGlobalPool(action, gameObject);
}

private static GameObject SpawnWingedNoskGlobDropper(PlayMakerFSM fsm) {
var action = fsm.GetFirstAction<FlingObjectsFromGlobalPool>("Drop");
var gameObject = action.gameObject.Value;

return SpawnFromFlingGlobalPool(action, gameObject);
}
}
1 change: 1 addition & 0 deletions HKMP/Game/Client/Entity/EntityType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ internal enum EntityType {
PureVessel,
PureVesselBlast,
WingedNosk,
WingedNoskGlobDropper,
TurretZoteling,
LankyZoteling,
HeadOfZote,
Expand Down
5 changes: 5 additions & 0 deletions HKMP/Resource/entity-registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,11 @@
"type": "WingedNosk",
"fsm_name": "Hornet Nosk"
},
{
"base_object_name": "Glob Dropper",
"type": "WingedNoskGlobDropper",
"fsm_name": "Dropper"
},
{
"base_object_name": "Zote Turret",
"type": "TurretZoteling",
Expand Down

0 comments on commit f27d3fa

Please sign in to comment.