I have a scenario where I am using loose tags to manage ability activation, but those loose tags are known only at runtime, and only on the client. The problem is that I do not know how to trigger the application of the tag on the server , from the client.
Example representative scenario
1. A laser that can lock on to objects in the world
2. Depending on the object the laser is locked on to, its color will be different - this is can only be known at runtime
3. The laser has 3 abilities:
- Turn on & lockon - can only do when the laser is off
- Turn off - can only do when the laser in on
- Pulse - can only do when the laser is green
Implementation
1. Laser is a `UActorComponent`, on a pawn that has an ASC component as well.
2. When the laser is locked on, the color & state of laser is tracked by loose Gameplay tag set on the ASC.:
- Laser_Green
- Laser_Red
- Laser_LockedOn
these tags are currently applied on client only via UAbilitySystemBlueprintLibrary::AddLooseGameplayTags() via the Laser component
3. Each ability is a UGameplayAbility
- GA_Laser_LockOn- blocked by `Laser_LockedOn` (set via ActivationBlocked Tags)
- GA_Laser_Off - requires `Laser_LockedOn` (set via ActivationRequired Tags)
- GA_Laser_Pulse - requires `Laser_Green` (set via ActivationRequired Tags)
4. The abilities call in to the laser component class , and it determines the state tags to apply
5. The laser component is not replicated (intentional, would like it to be this way), and thus the server does not have enough information to deduce the tag to apply on ability activation. This means I cannot apply the tag both on the server & the client separately.
My issue is that in a Server/Client setup, when I fire `GA_Laser_On` on the client, I cannot then fire `GA_Laser_Off`, because the server rejects the activation as `GA_Laser_Off` requires `Laser_LockedOn`, and that tag was never applied on the ASC on the server.
I have tried the following:
1. Use a gameplay effect to apply the tags via ApplyGameplayEffectSpecToSelf . This does not replicate the tags to the server
2. Use a server RPC on the laser component to add replicated tags on the server - a race condition will exist:
- client activates GA_Laser_LockOn
- RPC to add Laser_LockedOn tag goes out to server
- Server adds replicated Laser_LockedOn tag
- client receives addition of replicated Laser_LockedOn tag
- client activates GA_Laser_Off
- RPC to remove Laser_LockedOn tag goes out to server
- client instantly fires GA_Laser_LockOn
- client gets blocked because locally it still has the Laser_LockedOn tag
- client receives removal of replicated Laser_LockedOn
3. Lyra method of blocking GA_Weapon_Fire with Ability.Weapon.NoFiring, added on both server & client. Does not work because the tag is dynamic and not known on server.
Given this context, what is the best way that I can trigger the application of a tag from the client to the server, when the server cannot independently deduce which tag to add?