using SoulHarvest.Common;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using Terraria;
using Terraria.DataStructures;
using Terraria.ID;
using Terraria.ModLoader;
namespace SoulHarvest.Projectiles;
/// <summary>
/// Assigns a server-local monotonic presentation action token to each Void slash.
/// A multi-cut special uses one strike projectile per visible cut, so each cut can
/// create its own impact rift without relying on reusable projectile identities.
/// </summary>
internal sealed class ReaperVoidHitActionTokenGlobalProjectile : GlobalProjectile
{
private static int nextToken;
public override bool InstancePerEntity => true;
// This token is presentation-only. Restrict the per-entity global to the two
// direct-hit projectile types so unrelated projectiles do not pay an
// allocation or spawn hook.
public override bool AppliesToEntity(Projectile entity, bool lateInstantiation)
=> lateInstantiation && entity.ModProjectile is SickleSwingProjectile
or ReaperStrikeProjectile;
internal int ActionToken { get; private set; }
public override void OnSpawn(Projectile projectile, IEntitySource source)
{
if (Main.netMode == NetmodeID.MultiplayerClient)
return;
ActionToken = NextToken();
}
internal static int Resolve(Projectile projectile, int fallback)
{
if (Main.netMode == NetmodeID.MultiplayerClient)
return fallback;
return GetOrAssign(projectile);
}
private static int GetOrAssign(Projectile projectile)
{
ReaperVoidHitActionTokenGlobalProjectile data =
projectile.GetGlobalProjectile<ReaperVoidHitActionTokenGlobalProjectile>();
if (data.ActionToken == 0)
data.ActionToken = NextToken();
return data.ActionToken;
}
private static int NextToken()
{
unchecked
{
nextToken++;
if (nextToken == 0)
nextToken++;
}
return nextToken;
}
}
using SoulHarvest.Common;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using Terraria;
using Terraria.DataStructures;
using Terraria.ID;
using Terraria.ModLoader;
namespace SoulHarvest.Projectiles;
/// <summary>
/// Assigns a server-local monotonic presentation action token to each Void slash.
/// A multi-cut special uses one strike projectile per visible cut, so each cut can
/// create its own impact rift without relying on reusable projectile identities.
/// </summary>
internal sealed class ReaperVoidHitActionTokenGlobalProjectile : GlobalProjectile
{
private static int nextToken;
public override bool InstancePerEntity => true;
// This token is presentation-only. Restrict the per-entity global to the two
// direct-hit projectile types so unrelated projectiles do not pay an
// allocation or spawn hook.
public override bool AppliesToEntity(Projectile entity, bool lateInstantiation)
=> lateInstantiation && entity.ModProjectile is SickleSwingProjectile
or ReaperStrikeProjectile;
internal int ActionToken { get; private set; }
public override void OnSpawn(Projectile projectile, IEntitySource source)
{
if (Main.netMode == NetmodeID.MultiplayerClient)
return;
ActionToken = NextToken();
}
internal static int Resolve(Projectile projectile, int fallback)
{
if (Main.netMode == NetmodeID.MultiplayerClient)
return fallback;
return GetOrAssign(projectile);
}
private static int GetOrAssign(Projectile projectile)
{
ReaperVoidHitActionTokenGlobalProjectile data =
projectile.GetGlobalProjectile<ReaperVoidHitActionTokenGlobalProjectile>();
if (data.ActionToken == 0)
data.ActionToken = NextToken();
return data.ActionToken;
}
private static int NextToken()
{
unchecked
{
nextToken++;
if (nextToken == 0)
nextToken++;
}
return nextToken;
}
}