Author Topic: Prevent players from respawning (set as spectators)  (Read 1420 times)

I need to call a function when there is only one player left alive in a minigame. To do this, I have a loop that looks for when one player remains and calls my function when this is true.

But, I think my function is not being called because there's a default function that executes instead - the default function that gives the chat message "%1 is the last man standing" when minigame respawntime is set to -1. I need to have respawntime set to -1 because players should not be able to respawn in my gamemode.

I think I have 2 options, neither of which I've figured out how to do:
  • Set respawntime to something other than -1, and prevent players from manually respawning.
  • Keep respawntime at -1, but somehow call my function before the default 'last man standing' function calls.




Solution:

This prevents the countdown until respawn centerprint from showing up:

Code: [Select]
function gameConnection::onDeath(%cl,%sourceObject,%sourceClient,%damageType,%damageArea)
{
parent::onDeath(%cl,%sourceObject,%sourceClient,%damageType,%damageArea);
messageClient(%cl,'MsgYourSpawn');
centerPrint(%cl,"",1);
}


This prevents people from respawning, but also messes with admin orb mode and some other stuff:

Code: [Select]
package noObserverRespawn
{
function Observer::onTrigger(%this,%cam,%btn,%state)
{
return;
parent::onTrigger(%this,%cam,%btn,%state);
}
};
ActivatePackage(noObserverRespawn);


This does the same as the above code but also allows dead players to watch other players that are still alive. You can click to cycle to different players. To make it work, change "findclientbyname(fara).minigame" to whatever your minigame is.

Code: [Select]
package noObserverRespawn
{
function Observer::onTrigger(%this,%cam,%btn,%state)
{
%client = %cam.getControllingClient();
%client.centerPrint("", 1);
if(%state == 1)
{

%c = findclientbyname(fara).minigame.numMembers;
%aliveCount = 0;
for(%i = 0; %i < %c; %i++)
{
%member = findclientbyname(fara).minigame.member[%i];

if(!isObject(%member.player)) continue;

%aliveCount += 1;
%livingList[%aliveCount] = %member;
}

talk("observingClient: " @ %client.observingClient);

if(%aliveCount >= 1)
{
//talk("aliveCount >= 1");
if(!%client.observingClient)
{
//talk("clicker has no predefined observer - set player 1");
%client.observingClient = 1;
%client.camera.setOrbitMode(%livingList[1].player, %livingList[1].player.getTransform(), 0.5, 10, 20, false);
%client.setControlObject(%client.camera);
}
else
{
%client.observingClient += 1;
if(%client.observingClient > %aliveCount)
{
//talk("clicker has a predefined observer >> but it was the last player - set player 1");
%client.observingClient = 1;
%client.camera.setOrbitMode(%livingList[1].player, %livingList[1].player.getTransform(), 0.5, 10, 20, false);
%client.setControlObject(%client.camera);
}
else
{
//talk("clicker has a predefined observer >> set to next player");
%client.camera.setOrbitMode(%livingList[%client.observingClient].player, %livingList[%client.observingClient].player.getTransform(), 0.5, 10, 20, false);
%client.setControlObject(%client.camera);
}
}
}
}

return;
parent::onTrigger(%this,%cam,%btn,%state);
}
};
ActivatePackage(noObserverRespawn)
« Last Edit: July 10, 2016, 06:10:06 PM by Farad »

Having a looping function that checks to see if everyone is dead is a terrible idea. Package player::onDeath or something and then check if there's only one person left alive. Or you could use trace and package the function that's called that announces that there's only one person left standing and then do your stuff before parenting it?

To just prevent respawning at all, try packaging Observer::onTrigger, and see if you can do what you want with that and with what jes said.

To just prevent respawning at all, try packaging Observer::onTrigger, and see if you can do what you want with that and with what jes said.
I added the script below to prevent respawning. But there's a few problems with it:
- it doesn't allow players to spectate others in observer mode (it fixes the camera to one location)
- there's a message in centerprint saying "Click to respawn" that needs to be hidden.

Is there a way to fix those issues?

Code: [Select]
package noObserverRespawn
{
function Observer::onTrigger(%this,%cam,%btn,%state)
{
return;
parent::onTrigger(%this,%cam,%btn,%state);
}
};
ActivatePackage(noObserverRespawn);

if i remember correctly you have to package ondeath to prevent clicktorespawn to appear. Run a trace and see what's being called; something along the lines of GameConnection::showRespawnMessage() or GC::respawnTimer() gets called after a player dies. It would be cleanest to package the function that calls both rather than each one individually.

Of course you can't spectate other players with a package like that. ::onTrigger is called for clicking, jumping, jetting, and crouching. You need to check if(%btn == 0) to see if they're clicking.

Of course you can't spectate other players with a package like that. ::onTrigger is called for clicking, jumping, jetting, and crouching. You need to check if(%btn == 0) to see if they're clicking.
Alright, I finished the spectator script. I don't think it matters what button they press since they're dead, but I had to make sure %state == 1 otherwise it would run twice - when the button is pressed down and again when lifted up. It seems to work.

Is there a way to keep the position of the observer's camera in the same place relative to the living player even when the observer switches to watch another living player? Right now, the observer's camera is always set directly behind the living player (0.5,10,20) when the observer switches to watch the next player.

Code: [Select]
package noObserverRespawn
{
function Observer::onTrigger(%this,%cam,%btn,%state)
{
%client = %cam.getControllingClient();
%client.centerPrint("", 1);
if(%state == 1)
{

%c = findclientbyname(fara).minigame.numMembers;
%aliveCount = 0;
for(%i = 0; %i < %c; %i++)
{
%member = findclientbyname(fara).minigame.member[%i];

if(!isObject(%member.player)) continue;

%aliveCount += 1;
%livingList[%aliveCount] = %member;
}

talk("observingClient: " @ %client.observingClient);

if(%aliveCount >= 1)
{
//talk("aliveCount >= 1");
if(!%client.observingClient)
{
//talk("clicker has no predefined observer - set player 1");
%client.observingClient = 1;
%client.camera.setOrbitMode(%livingList[1].player, %livingList[1].player.getTransform(), 0.5, 10, 20, false);
%client.setControlObject(%client.camera);
}
else
{
%client.observingClient += 1;
if(%client.observingClient > %aliveCount)
{
//talk("clicker has a predefined observer >> but it was the last player - set player 1");
%client.observingClient = 1;
%client.camera.setOrbitMode(%livingList[1].player, %livingList[1].player.getTransform(), 0.5, 10, 20, false);
%client.setControlObject(%client.camera);
}
else
{
//talk("clicker has a predefined observer >> set to next player");
%client.camera.setOrbitMode(%livingList[%client.observingClient].player, %livingList[%client.observingClient].player.getTransform(), 0.5, 10, 20, false);
%client.setControlObject(%client.camera);
}
}
}
}

return;
parent::onTrigger(%this,%cam,%btn,%state);
}
};
ActivatePackage(noObserverRespawn)
« Last Edit: July 04, 2016, 06:05:57 PM by Farad »

if i remember correctly you have to package ondeath to prevent clicktorespawn to appear. Run a trace and see what's being called; something along the lines of GameConnection::showRespawnMessage() or GC::respawnTimer() gets called after a player dies. It would be cleanest to package the function that calls both rather than each one individually.

The function that centerprints the countdown until spawning and "Click to respawn" is function respawnCountDownTick(%time).

Is the script below the correct way to prevent this function from doing anything?

Code: [Select]
package PreventDeathMessage
{
function respawnCountDownTick(%time)
{
                return;
}
};
activatePackage(PreventDeathMessage);

The function that centerprints the countdown until spawning and "Click to respawn" is function respawnCountDownTick(%time).

Is the script below the correct way to prevent this function from doing anything?

Code: [Select]
package PreventDeathMessage
{
function respawnCountDownTick(%time)
{
                return;
}
};
activatePackage(PreventDeathMessage);
no respawnCountDownTick() is a clientsided function

Code: [Select]
function gameConnection::onDeath(%cl,%sourceObject,%sourceClient,%damageType,%damageArea)
{
parent::onDeath(%cl,%sourceObject,%sourceClient,%damageType,%damageArea);
messageClient(%cl,'MsgYourSpawn');
centerPrint(%cl,"",1);
}
do something like this
and then sending the 'MsgYourSpawn' message to the client will cause their client to stop doing the count down because it think's theyve spawned as a new player
and then sends a center print to suppress the initial respawn message

this is the best way to do it short of rewriting the entire death function

Code: [Select]
package noObserverRespawn
{
function Observer::onTrigger(%this,%cam,%btn,%state)
{
if(%cam.getControllingClient().isSpectator)
return;
parent::onTrigger(%this,%cam,%btn,%state);
}
};
ActivatePackage(noObserverRespawn);
upon a client's death set isSpectator = 1
this way it only blocks observer trigger if they are considered a spectator

Code: [Select]
package noObserverRespawn
{
function Observer::onTrigger(%this,%cam,%btn,%state)
{
if(%cam.getControllingClient().isSpectator)
return;
parent::onTrigger(%this,%cam,%btn,%state);
}
};
ActivatePackage(noObserverRespawn);
upon a client's death set isSpectator = 1
this way it only blocks observer trigger if they are considered a spectator
Oh good idea. I should also set isSpectator = 0 when players spawn.

I see you doing things like: %member = findclientbyname(fara).minigame.member[%i];. It's ok I guess, but I'd avoid doing things like this in the future, or if you plan to release this code. Instead, you can get the minigame the observer's client is in and perform logic.

I see you doing things like: %member = findclientbyname(fara).minigame.member[%i];. It's ok I guess, but I'd avoid doing things like this in the future, or if you plan to release this code. Instead, you can get the minigame the observer's client is in and perform logic.
Only did that for testing. The actual code uses a global variable for the minigame.