Download

Replicate Actor to specific PlayerControllers only? Problems with IsNetRelevantFor() being const

Hi,
I’m trying to implement some sort of Viewrange-/Spotting-Mechanics for a simple RTS game. The goal is to directly control, exactly which Player can see a Character or not.
(btw a PlayerController owns multiple Characters, but shouldn’t be relevant to the topic)
A Character of Player1 gets replicated to a Player2, if

  1. Player1 is on the same Team as Player2 -> replicate
  2. the Character is spotted/ is within the Viewrange of any enemy Character (Viewrange is an Int stored in Character, differs from Character to Character, e.g normal GI, Sniper…)

If a Character got spotted for a while, and then isn’t in Viewrange of any enemy Character anymore, it again should only be replicated to teammembers/allies.

>>>Therefore, I wanted to override the IsRelevantFor function inherited by the AActor class. As far as I understood, the RealViewer is the PlayerController/Player, to which “this” (Actor/Character) will be replicated to or not. The ViewTarget is the OTHER Actor/Character - we want to e.g. messure the distance between him and “this”, see if we are on same team etc… Still not sure what the SrcLocation mean (looked like its only a Vector, where “this”'s mouse is looking at??)
This is what I got til now:


bool ACProjectCharacter::IsNetRelevantFor(const AActor * RealViewer, const AActor * ViewTarget, const FVector & SrcLocation) const
{
	if (!(Super::IsNetRelevantFor(RealViewer, ViewTarget, SrcLocation))) {
		return false;
	}

	const ACProjectCharacter* target = Cast<ACProjectCharacter>(ViewTarget);

	if (target != nullptr) {
		if (this->TeamID == target->TeamID) {
			return true;
		}
		else {
			float dist;
			FVector fV;
			fV = this->GetActorLocation() - target->GetActorLocation();
			dist = fV.Size();

			if (this->GetSpotter() == nullptr) {
				if (dist <= target->Viewrange) {
					this->Spotter = target; // ERROR: can't assign value from const type to a non const type
					return true;
				} else {
					return false;
				}
			} else if (Spotter == target) {
				if (dist <= target->Viewrange) {
					return true;
				} else {
					this->Spotter = nullptr;
					return false;
				}
			}
		}
	}
}

The Code worked fine before - when I only checked the TeamID and the distance between this and the ViewTarget, but now as I brought the Spotter variable in, I run into some troubles. Pretty sure, c++ guys were smiling already while reading the code :slight_smile:
But why do I even need a Spotter?
My thoughts were: If I (this Character) get spotted by EnemyCharacter1, I’ll get replicated; but in the next moment IsRelevantNetFor() is executed for another Actor EnemyCharater2, and I am NOT in the Viewrange of him, so the function returns false, and I am not replicated anymore, ALTHOUGH I AM still spotted by EnemyCharacter1. Therefore I wanted to save who spotted me, so not every other EnemyCharacter can set my Replication to false.

>>>But back to the Problem, i am stuck in: It is of course: CONST
As far as the IsNetRelevant function is tagged as const, I can’t modify any variables (members?) in this Character object, neither I can call a function, that is not const/changes any variables. Is this correct like this?
Before I tagged Spotter as mutable, “this->Spotter = target” I got error like “can’t assign value to a non mutable member”. But now I get something like “can’t assign value from const type to a non const type”.

>>> So what would be a proper way to implement this/ how to handle stuff like this with IsNetRelevantfor?
I am sure I still need to override the IsNetRelevant function, or is there another way to replicate an actor to specific Players only? Or do I need to do the calculations somewhere else (e.g. in GameMode: get through all Characters in Team0, foreach Character in Team1 calculate distance, and then set a simple bIsSpotted and (in case) the SpotterVariable;
IsNetRelevantFor() only needs to check these Values then, and replicates accordingly?)

I am not too happy with this solution, GameMode seems to do and hold so much stuff/calculations in it. Would like to “outsource” as much as I can, but GameMode is best choice to hold things like Teams, PlayerControllerList/CharacterList, Calculations etc, isn’t it?

Thank you in advance for all your input/workflows,
Regards

PS: Sorry, this text got so long… Tried to make things clear and readable, also if others got troubles with this and come upon this thread.