Page 1 of 1

Detect player team change

Posted: Sat Oct 15, 2022 12:25 pm
by ShaiHulud
Just wanted to share something I observed recently while working on a Nexgen plugin. Nexgen (and other mutators that I've peered into) keeps track of player team changes by testing the playerReplicationInfo.team value against a stored team value in a timer event with a short fuse.

If these two numbers diverge, Nexgen issues a playerTeamChanged() call to plugins. In the vast majority of instances this works just fine. But for reasons that would be too long-winded to go into, I needed something that had a direct link back to the line that caused the team change to happen in the first place - in other words, I didn't want additional game ticks to take place before I had a chance to intercept and deal with them.

So poking around, and tracing through the class hierarchy, I eventually found the AddToTeam() function inside of TeamGamePlus (so, obviously, this will only be applicable to TeamGamePlus derived game types).

Near the end of the AddToTeam() function, a call to BroadcastLocalizedMessage() is issued, and this can be intercepted by a mutatorBroadcastLocalizedMessage() function in a mutator to watch for the relevant LocalMessage class, e.g.,

Code: Select all

function bool mutatorBroadcastLocalizedMessage(actor sender, pawn receiver, out class<LocalMessage> message, out optional int switch, out optional playerReplicationInfo relatedPRI_1, out optional playerReplicationInfo relatedPRI_2, out optional object optionalObject)
{
  local teamInfo TI;

  if (message == class'botpack.deathMatchMessage' && sender.isA('CTFGame') && switch == 3)
  {
    TI = teamInfo(optionalObject);
    // TI.teamIndex contains the new team number
    // relatedPRI_1 is the playerReplicationInfo for the player who changed teams
    if (TI != none)
      LOG(relatedPRI_1.playerName $ " SWITCHED TO TEAM " $ TI.teamIndex);
  }

  return true;
}

Re: Detect player team change

Posted: Sat Oct 15, 2022 10:09 pm
by EvilGrins
In my experience, when playing if anyone changes teams a message pops on the screen and states it.

How is this better than that?

Re: Detect player team change

Posted: Sat Oct 15, 2022 10:46 pm
by ShaiHulud
It isn't, it's not intended as a replacement of any kind, I just added the code snippet here for anyone who might be writing a mutator, and who wants a way to detect player team changes in their script.

Re: Detect player team change

Posted: Sun Oct 16, 2022 9:47 am
by Sp0ngeb0b
Thanks for sharing that hook Shai! Out of curiousity, how do other teamgame gametypes setup that message? Referring to the "sender.isA('CTFGame') && switch == 3" conditions - is above code snippet generally applicable?

Re: Detect player team change

Posted: Sun Oct 16, 2022 10:12 am
by Dennis
You can also just add the playerReplicationInfo.team check in a function Tick() to detect it just as fast?

Re: Detect player team change

Posted: Sun Oct 16, 2022 12:39 pm
by ShaiHulud
Sp0ngeb0b wrote: Sun Oct 16, 2022 9:47 am Thanks for sharing that hook Shai! Out of curiousity, how do other teamgame gametypes setup that message? Referring to the "sender.isA('CTFGame') && switch == 3" conditions - is above code snippet generally applicable?
Good question, Sponge, I was being totally single-minded about figuring out a solution for my situation, so I haven't investigated other scenarios so far!
Dennis wrote: Sun Oct 16, 2022 10:12 am You can also just add the playerReplicationInfo.team check in a function Tick() to detect it just as fast?
Very true, but as I mentioned, in this very particular case I didn't want additional game ticks to occur between the team change and my ability to respond to it, so this technique meant I was able to satisfy that requirement.

Re: Detect player team change

Posted: Mon Oct 17, 2022 5:46 pm
by Dennis
ShaiHulud wrote: Sun Oct 16, 2022 12:39 pm Very true, but as I mentioned, in this very particular case I didn't want additional game ticks to occur between the team change and my ability to respond to it, so this technique meant I was able to satisfy that requirement.
But if you hook a message then you will also be on next tick() as one tick() has to occur before input is processed into message? So we are on the same Tick() regardless what method is used correct?

Re: Detect player team change

Posted: Mon Oct 17, 2022 7:50 pm
by sektor2111
Sp0ngeb0b wrote: Sun Oct 16, 2022 9:47 am Referring to the "sender.isA('CTFGame') && switch == 3" conditions - is above code snippet generally applicable?
if Sender is Pawn then... I'm really scared...
I don't get if a Sender can be a game-type. Tell me that I'm wrong.

Resuming.
If I want to detect a team change, I think my methods are not really bad. Once again, assign an actor tracking players with vars "OldTeam" "CurrentTeam" working in a SLOW timer NOT TICK (not 80 times/second or such ticks) - we don't have to exhaust resources for something simple. When OldTeam != CurrentTeam this means that player has changed team - here you can increment something "Changes++". If a limit is set, do what is supposed to be done (eat his legs, arms, etc.)

Re: Detect player team change

Posted: Wed Dec 14, 2022 12:13 am
by snowguy
Thanks for writing about this Shai. Just had occasion to use it and was happy to not have to put additional checks in a tick or timer.

A couple things that might be worth mentioning that I learned when using it. It seems the function is called for each pawn (or is it playerpawn?) on the server so the log would be repeated multiple times depending on the number of players and spectators on the server. I changed the TI check to this to make it only log once:

Code: Select all

if (TI != none && receiver.PlayerReplicationInfo!= none && receiver.PlayerReplicationInfo == relatedPRI_1)
Also, I broke other mutators in the chain that used this function when using the code as is so I changed the 'return true' to the following:

Code: Select all

return Super.MutatorBroadcastLocalizedMessage( Sender, Receiver, Message, Switch, RelatedPRI_1, RelatedPRI_2, OptionalObject );
The mutator I was working with had already registered itself as a message mutator so I'm not sure if that is required for the use of this function or if it had any bearing on my findings listed above. If anyone has more info about this I would like to know. :)