mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-15 20:53:50 +00:00
251 lines
9.5 KiB
C#
251 lines
9.5 KiB
C#
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Trigger-derrived teleporter object. Teleports an object from it's entrance to
|
|
// it's exit if one is defined.
|
|
|
|
function TeleporterTrigger::onAdd( %this, %teleporter )
|
|
{
|
|
|
|
// Setup default parameters.
|
|
if ( %teleporter.exit $= "" )
|
|
%teleporter.exit = "NameOfTeleporterExit";
|
|
if ( %teleporter.teleporterCooldown $= "" )
|
|
%teleporter.teleporterCooldown = %this.teleporterCooldown;
|
|
if ( %teleporter.exitVelocityScale $= "" )
|
|
%teleporter.exitVelocityScale = %this.exitVelocityScale;
|
|
if ( %teleporter.reorientPlayer $= "" )
|
|
%teleporter.reorientPlayer = %this.reorientPlayer;
|
|
if ( %teleporter.oneSided $= "" )
|
|
%teleporter.oneSided = %this.oneSided;
|
|
if ( %teleporter.entranceEffect $= "" )
|
|
%teleporter.entranceEffect = %this.entranceEffect;
|
|
if ( %teleporter.exitEffect $= "" )
|
|
%teleporter.exitEffect = %this.exitEffect;
|
|
|
|
// We do not want to save this variable between levels,
|
|
// clear it out every time the teleporter is added
|
|
// to the scene.
|
|
%teleporter.timeOfLastTeleport = "";
|
|
}
|
|
|
|
function TeleporterTrigger::onLeaveTrigger(%this,%trigger,%obj)
|
|
{
|
|
// This is called after onEnterTrigger for BOTH
|
|
// The teleporter's entrance and exit
|
|
%obj.isTeleporting = false;
|
|
}
|
|
|
|
//ARGS:
|
|
// %this - The teleporter datablock.
|
|
// %entrance - The teleporter the player has entered (The one calling this function).
|
|
// %obj - The object that entered the teleporter.
|
|
function TeleporterTrigger::onEnterTrigger(%this, %entrance, %obj)
|
|
{
|
|
// Get the location of our target position
|
|
%exit = nameToID(%entrance.exit);
|
|
|
|
// Check if the the teleport is valid.
|
|
%valid = %this.verifyObject(%obj, %entrance, %exit);
|
|
|
|
// Bail out early if we cannot complete this teleportation
|
|
if (!%valid)
|
|
return;
|
|
|
|
// Kill any players in the exit teleporter.
|
|
%this.telefrag(%obj, %exit);
|
|
|
|
// Create our entrance effects on all clients.
|
|
if (isObject(%entrance.entranceEffect))
|
|
{
|
|
for(%idx = 0; %idx < ClientGroup.getCount(); %idx++)
|
|
commandToClient(ClientGroup.getObject(%idx), 'PlayTeleportEffect', %entrance.position, %entrance.entranceEffect.getId());
|
|
}
|
|
|
|
// Teleport the player to the exit teleporter.
|
|
%this.teleportPlayer(%obj, %exit);
|
|
|
|
// Create our exit effects on all clients.
|
|
if (isObject(%exit.exitEffect))
|
|
{
|
|
for(%idx = 0; %idx < ClientGroup.getCount(); %idx++)
|
|
commandToClient(ClientGroup.getObject(%idx), 'PlayTeleportEffect', %exit.position, %exit.exitEffect.getId());
|
|
}
|
|
|
|
// Record what time we last teleported so we can determine if enough
|
|
// time has elapsed to teleport again
|
|
%entrance.timeOfLastTeleport = getSimTime();
|
|
|
|
// If this is a bidirectional teleporter, log it's exit too.
|
|
if (%exit.exit $= %entrance.name)
|
|
%exit.timeOfLastTeleport = %entrance.timeOfLastTeleport;
|
|
|
|
// Tell the client to play the 2D sound for the player that teleported.
|
|
if (isObject(%this.teleportSound) && isObject(%obj.client))
|
|
%obj.client.play2D(%this.teleportSound);
|
|
}
|
|
|
|
// Here we verify that the teleport is valid.
|
|
// Tests go here like if the object is of a 'teleportable' type, if the
|
|
// given teleporter has an exit defined, etc.
|
|
function TeleporterTrigger::verifyObject(%this, %obj, %entrance, %exit)
|
|
{
|
|
|
|
// Bail out early if we couldn't find an exit for this teleporter.
|
|
if (!isObject(%exit))
|
|
{
|
|
logError("Cound not find an exit for " @ %entrance.name @ ".");
|
|
return false;
|
|
}
|
|
|
|
// If the entrance is once sided, make sure the object
|
|
// approached it from it's front.
|
|
if (%entrance.oneSided)
|
|
{
|
|
%dotProduct = VectorDot(%entrance.getForwardVector(), %obj.getVelocity());
|
|
|
|
if (%dotProduct > 0)
|
|
return false;
|
|
}
|
|
|
|
// If we are coming directly from another teleporter and it happens
|
|
// to be bidirectional, We need to avoid ending sending objects through
|
|
// an infinite loop.
|
|
if (%obj.isTeleporting)
|
|
return false;
|
|
|
|
// We only want to teleport players
|
|
// So bail out early if we have found any
|
|
// other object.
|
|
if (!%obj.isMemberOfClass("Player"))
|
|
return false;
|
|
|
|
if (%entrance.timeOfLastTeleport > 0 && %entrance.teleporterCooldown > 0)
|
|
{
|
|
// Get the current time, subtract it from the time it last teleported
|
|
// And compare the difference to see if enough time has elapsed to
|
|
// activate the teleporter again.
|
|
%currentTime = getSimTime();
|
|
%timeDifference = %currentTime - %entrance.timeOfLastTeleport;
|
|
%db = %entrance.getDatablock();
|
|
if (%timeDifference <= %db.teleporterCooldown)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Function to teleport object %player to teleporter %exit.
|
|
function TeleporterTrigger::teleportPlayer(%this, %player, %exit)
|
|
{
|
|
// Teleport our player to the exit teleporter.
|
|
if (%exit.reorientPlayer)
|
|
%targetPosition = %exit.getTransform();
|
|
else
|
|
{
|
|
%pos = %exit.getPosition();
|
|
%rot = getWords(%player.getTransform(), 3, 6);
|
|
%targetPosition = %pos SPC %rot;
|
|
}
|
|
|
|
%player.setTransform(%targetPosition);
|
|
|
|
// Adjust the player's velocity by the Exit location's scale.
|
|
%player.setVelocity(vectorScale(%player.getVelocity(), %exit.exitVelocityScale));
|
|
|
|
// Prevent the object from doing an immediate second teleport
|
|
// In the case of a bidirectional teleporter
|
|
%player.isTeleporting = true;
|
|
}
|
|
|
|
// Telefrag is a term used in multiplayer gaming when a player takes a teleporter
|
|
// while another player is occupying it's exit. The player at the exit location
|
|
// is killed, allowing the original player to arrive at the teleporter.
|
|
function TeleporterTrigger::teleFrag(%this, %player, %exit)
|
|
{
|
|
// When a telefrag happens, there are two cases we have to consider.
|
|
// The first case occurs when the player's bounding box is much larger than the exit location,
|
|
// it is possible to have players colide even though a player is not within the bounds
|
|
// of the trigger Because of this we first check a radius the size of a player's bounding
|
|
// box around the exit location.
|
|
|
|
// Get the bounding box of the player
|
|
%boundingBoxSize = %player.getDatablock().boundingBox;
|
|
%radius = getWord(%boundingBoxSize, 0);
|
|
%boxSizeY = getWord(%boundingBoxSize, 1);
|
|
%boxSizeZ = getWord(%boundingBoxSize, 2);
|
|
|
|
// Use the largest dimention as the radius to check
|
|
if (%boxSizeY > %radius)
|
|
%radius = %boxSizeY;
|
|
if (%boxSizeZ > %radius)
|
|
%radius = %boxSizeZ;
|
|
|
|
%position = %exit.getPosition();
|
|
%mask = $TypeMasks::PlayerObjectType;
|
|
|
|
// Check all objects within the found radius of the exit location, and telefrag
|
|
// any players that meet the conditions.
|
|
initContainerRadiusSearch( %position, %radius, %mask );
|
|
while ( (%objectNearExit = containerSearchNext()) != 0 )
|
|
{
|
|
if (!%objectNearExit.isMemberOfClass("Player"))
|
|
continue;
|
|
|
|
// Avoid killing the player that is teleporting in the case of two
|
|
// Teleporters near eachother.
|
|
if (%objectNearExit == %player)
|
|
continue;
|
|
|
|
%objectNearExit.damage(%player, %exit.getTransform(), 10000, "Telefrag");
|
|
}
|
|
|
|
// The second case occurs when the bounds of the trigger are much larger
|
|
// than the bounding box of the player. (So multiple players can exist within the
|
|
// same trigger). For this case we check all objects contained within the trigger
|
|
// and telefrag all players.
|
|
%objectsInExit = %exit.getNumObjects();
|
|
|
|
// Loop through all objects in the teleporter exit
|
|
// And kill any players
|
|
for(%i = 0; %i < %objectsInExit; %i++)
|
|
{
|
|
%objectInTeleporter = %exit.getObject(%i);
|
|
|
|
if (!%objectInTeleporter.isMemberOfClass("Player"))
|
|
continue;
|
|
|
|
// Avoid killing the player that is teleporting in the case of two
|
|
// Teleporters near eachother.
|
|
if (%objectInTeleporter == %player)
|
|
continue;
|
|
|
|
%objectInTeleporter.damage(%player, %exit.getTransform(), 10000, "Telefrag");
|
|
}
|
|
}
|
|
|
|
// Customized kill message for telefrag deaths
|
|
function sendMsgClientKilled_Telefrag(%msgType, %client, %sourceClient, %damLoc)
|
|
{
|
|
messageAll(%msgType, '%1 was telefragged by %2!', %client.playerName, %sourceClient.playerName);
|
|
}
|