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; /// /// 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. /// 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(); if (data.ActionToken == 0) data.ActionToken = NextToken(); return data.ActionToken; } private static int NextToken() { unchecked { nextToken++; if (nextToken == 0) nextToken++; } return nextToken; } }