t2-mapper/docs/base/@vl2/TR2final105-server.vl2/scripts/TR2Packages.cs
2025-11-26 00:00:11 -08:00

1031 lines
33 KiB
C#

package TR2Game {
function Player::scriptKill(%player, %damageType)
{
if (%damageType == $DamageType::suicide ||
%damageType == $DamageType::RespawnAfterScoring ||
%damageType == 0)
{
%player.client.forceRespawn = true;
%player.client.inSpawnBuilding = true;
%player.knockedDown = false;
}
Parent::scriptKill(%player, %damageType);
}
function Player::isAboveSomething(%player, %searchrange)
{
// Borrow some deployment code to determine whether the player is
// above something.
%mask = $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType;
%eyeVec = "0 0 -1";//%player.getEyeVector();
%eyeTrans = %player.getEyeTransform();
// extract the position of the player's camera from the eye transform (first 3 words)
%eyePos = posFromTransform(%eyeTrans);
// normalize the eye vector
%nEyeVec = VectorNormalize(%eyeVec);
// scale (lengthen) the normalized eye vector according to the search range
%scEyeVec = VectorScale(%nEyeVec, %searchRange);
// add the scaled & normalized eye vector to the position of the camera
%eyeEnd = VectorAdd(%eyePos, %scEyeVec);
// see if anything gets hit
return containerRayCast(%eyePos, %eyeEnd, %mask, 0);
}
function ShapeBase::hasAmmo( %this, %weapon )
{
switch$ ( %weapon )
{
// TR2
case TR2Disc:
return( %this.getInventory( TR2DiscAmmo ) > 0 );
case TR2GrenadeLauncher:
return( %this.getInventory( TR2GrenadeLauncherAmmo ) > 0 );
case TR2Chaingun:
return( %this.getInventory( TR2ChaingunAmmo ) > 0);
case TR2Mortar:
return( %this.getInventory( TR2MortarAmmo ) > 0 );
case TR2Shocklance:
return( true );
case TR2GoldTargetingLaser:
return( false );
case TR2SilverTargetingLaser:
return( false );
default:
return Parent::hasAmmo(%this, %weapon);
}
}
function ShapeBase::clearInventory(%this)
{
// TR2
%this.setInventory(TR2Disc,0);
%this.setInventory(TR2GrenadeLauncher,0);
%this.setInventory(TR2Chaingun,0);
%this.setInventory(TR2Mortar,0);
%this.setInventory(TR2Shocklance,0);
%this.setInventory(TR2GoldTargetingLaser,0);
%this.setInventory(TR2SilverTargetingLaser,0);
%this.setInventory(TR2DiscAmmo,0);
%this.setInventory(TR2GrenadeLauncherAmmo,0);
%this.setInventory(TR2MortarAmmo, 0);
%this.setInventory(TR2ChaingunAmmo,0);
%this.setInventory(TR2Grenade,0);
Parent::clearInventory(%this);
}
function serverCmdUse(%client,%data)
{
if( %data $= Disc )
%client.getControlObject().use(TR2Disc);
else if( %data $= GrenadeLauncher )
%client.getControlObject().use(TR2GrenadeLauncher);
else if( %data $= Chaingun )
%client.getControlObject().use(TR2Chaingun);
else if( %data $= Shocklance )
%client.getControlObject().use(TR2Shocklance);
else if( %data $= Grenade )
%client.getControlObject().use(TR2Grenade);
else if( %data $= Mortar )
%client.getControlObject().use(TR2Mortar);
else if( %data $= TargetingLaser )
%client.getControlObject().use((%client.team == 1) ? TR2GoldTargetingLaser : TR2SilverTargetingLaser);
// etc...
else
%client.getControlObject().use(%data);
}
function serverCmdStartNewVote(%client, %typeName, %arg1, %arg2, %arg3, %arg4, %playerVote)
{
parent::serverCmdStartNewVote(%client, %typeName, %arg1, %arg2, %arg3, %arg4, %playerVote);
//if( %typeName $= "ToggleDisableDeath" && %client.isAdmin )
// ToggleDisableDeath(%client);
if ( %typeName $= "TogglePracticeMode" && %client.isAdmin )
TogglePracticeMode(%client);
if( %typeName $= "ToggleRoles" && %client.isAdmin )
TogglePlayerRoles(%client);
if( %typeName $= "ToggleCrowd" && %client.isAdmin )
ToggleCrowd(%client);
if( %typeName $= "getQueuePos" )
{
messageQueueClient(%client);
}
if( %typeName $= "toggleSpecLock" && %client.isAdmin )
{
toggleSpectatorLock(%client);
}
if( %typeName $= "toggleSpecOnly" )
toggleSpecOnly(%client);
if( %typeName $= "toggleSpecMode" )
toggleSpectatorMode(%client);
if( %typeName $= "tr2JoinGame" )
{
reindexQueue();
if( !$TR2::SpecLock && %client.queueSlot !$= "" && %client.queueSlot <= ((6 * 2) - getActiveCount()) )
{
Game.assignClientTeam(%client);
Game.spawnPlayer(%client, $MatchStarted);
}
}
if( %typeName $= "tr2ForceFlagReturn" )
{
if( %client.isAdmin && $TheFlag.carrier $= "" && (getSimTime() - $TheFlag.dropTime) >= 30000 )
{
messageAll('MsgAdminForce', '\c0%1 forced the flag to return to the stand.', %client.name);
Game.flagReturn($TheFlag, 0);
}
}
}
function toggleSpectatorMode(%client)
{
if( %client.team <= 0 )
{
%client.tr2SpecMode = !%client.tr2SpecMode;
if( %client.tr2SpecMode )
{
%target = $TheFlag.carrier $= "" ? $TheFlag : $TheFlag.carrier.client;
%type = $TheFlag.carrier $= "" ? 2 : 1;
Game.observeObject(%client, %target, %type);
}
else
{
if( %client.camera.mode !$= "observerFly" )
%client.camera.getDataBlock().setMode(%client.camera, "observerFly");
}
}
}
function toggleSpectatorLock(%client)
{
$TR2::SpecLock = !$TR2::SpecLock;
%status = $TR2::SpecLock ? "locked spectators in observer mode." : "enabled the spectator queue.";
messageAll('MsgAdminForce', '\c0%1 %2.', %client.name, %status);
}
function toggleSpecOnly(%client)
{
%time = getSimTime() - %client.specOnlyTime;
if( %time > 10000 )
{
%client.specOnly = !%client.specOnly;
%status = %client.specOnly ? "You have locked yourself as a spectator." : "You have entered the queue.";
messageClient(%client, 'MsgAdminForce', '\c2%1', %status);
reindexQueue();
messageQueueClient(%client);
%client.specOnlyTime = getSimTime();
%vacant = ((6 * 2) - getActiveCount());
if( !%client.specOnly && %vacant > 0 && %client.queueSlot <= %vacant )
{
Game.assignClientTeam(%client, 0);
Game.spawnPlayer(%client, 0);
}
}
else
messageClient(%client, 'MsgTR2Wait', '\c0You must wait %1 seconds before using this option again!~wfx/powered/station_denied.wav', mFloor((10000 - %time)/1000) );
}
function TogglePlayerRoles(%client)
{
$TR2::EnableRoles = !$TR2::EnableRoles;
%status = $TR2::EnableRoles ? "enabled player roles." : "disabled player roles.";
messageAll('MsgAdminForce', '\c2%1 %2', %client.name, %status);
}
function ToggleCrowd(%client)
{
if ($TR2::EnableCrowd)
Game.stopCrowd();
$TR2::EnableCrowd = !$TR2::EnableCrowd;
%status = $TR2::EnableCrowd ? "enabled the crowd." : "disabled the crowd";
messageAll('MsgAdminForce', '\c2%1 %2', %client.name, %status);
}
function ToggleDisableDeath(%client)
{
$TR2::DisableDeath = !$TR2::DisableDeath;
%status = $TR2::DisableDeath ? "disabled Death." : "enabled Death.";
messageAll('MsgAdminForce', '\c2%1 %2', %client.name, %status);
// Reset all players' knockdown status
for(%i = 0; %i < ClientGroup.getCount(); %i ++)
{
%cl = ClientGroup.getObject(%i);
%cl.knockedDown = false;
cancel(%cl.knockdownThread);
}
}
function TogglePracticeMode(%client)
{
$TR2::PracticeMode = !$TR2::PracticeMode;
%status = $TR2::PracticeMode ? "enabled Practice Mode." : "disabled Practice Mode.";
messageAll('MsgAdminForce', '\c2%1 %2', %client.name, %status);
}
function Flag::shouldApplyImpulse(%data, %obj)
{
// TR2: Get rid of flag discing
return false;
}
function TR2ShockLanceImage::onFire(%this, %obj, %slot)
{
if( %obj.isCloaked() )
{
if( %obj.respawnCloakThread !$= "" )
{
Cancel(%obj.respawnCloakThread);
%obj.setCloaked( false );
}
else
{
if( %obj.getEnergyLevel() > 20 )
{
%obj.setCloaked( false );
%obj.reCloak = %obj.schedule( 500, "setCloaked", true );
}
}
}
%muzzlePos = %obj.getMuzzlePoint(%slot);
%muzzleVec = %obj.getMuzzleVector(%slot);
%endPos = VectorAdd(%muzzlePos, VectorScale(%muzzleVec, %this.projectile.extension));
%damageMasks = $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType |
$TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType |
$TypeMasks::SensorObjectType | $TypeMasks::TurretObjectType;
%everythingElseMask = $TypeMasks::TerrainObjectType |
$TypeMasks::InteriorObjectType |
$TypeMasks::ForceFieldObjectType |
$TypeMasks::StaticObjectType |
$TypeMasks::MoveableObjectType |
$TypeMasks::DamagableItemObjectType;
// did I miss anything? players, vehicles, stations, gens, sensors, turrets
%hit = ContainerRayCast(%muzzlePos, %endPos, %damageMasks | %everythingElseMask, %obj);
%noDisplay = true;
if (%hit !$= "0")
{
%obj.setEnergyLevel(%obj.getEnergyLevel() - %this.hitEnergy);
%hitobj = getWord(%hit, 0);
%hitpos = getWord(%hit, 1) @ " " @ getWord(%hit, 2) @ " " @ getWord(%hit, 3);
if ( %hitObj.getType() & %damageMasks )
{
// TR2: Don't allow friendly lances
if (%obj.team == %hitobj.team)
return;
%hitobj.applyImpulse(%hitpos, VectorScale(%muzzleVec, %this.projectile.impulse));
%obj.playAudio(0, ShockLanceHitSound);
// This is truly lame, but we need the sourceobject property present...
%p = new ShockLanceProjectile() {
dataBlock = %this.projectile;
initialDirection = %obj.getMuzzleVector(%slot);
initialPosition = %obj.getMuzzlePoint(%slot);
sourceObject = %obj;
sourceSlot = %slot;
targetId = %hit;
};
MissionCleanup.add(%p);
%damageMultiplier = 1.0;
if(%hitObj.getDataBlock().getClassName() $= "PlayerData")
{
// Now we see if we hit from behind...
%forwardVec = %hitobj.getForwardVector();
%objDir2D = getWord(%forwardVec, 0) @ " " @ getWord(%forwardVec,1) @ " " @ "0.0";
%objPos = %hitObj.getPosition();
%dif = VectorSub(%objPos, %muzzlePos);
%dif = getWord(%dif, 0) @ " " @ getWord(%dif, 1) @ " 0";
%dif = VectorNormalize(%dif);
%dot = VectorDot(%dif, %objDir2D);
// 120 Deg angle test...
// 1.05 == 60 degrees in radians
if (%dot >= mCos(1.05)) {
// Rear hit
%damageMultiplier = 3.0;
}
}
%totalDamage = %this.Projectile.DirectDamage * %damageMultiplier;
%hitObj.getDataBlock().damageObject(%hitobj, %p.sourceObject, %hitpos, %totalDamage, $DamageType::ShockLance);
%noDisplay = false;
}
}
if( %noDisplay )
{
// Miss
%obj.setEnergyLevel(%obj.getEnergyLevel() - %this.missEnergy);
%obj.playAudio(0, ShockLanceMissSound);
%p = new ShockLanceProjectile() {
dataBlock = %this.projectile;
initialDirection = %obj.getMuzzleVector(%slot);
initialPosition = %obj.getMuzzlePoint(%slot);
sourceObject = %obj;
sourceSlot = %slot;
};
MissionCleanup.add(%p);
}
}
function Armor::onCollision(%this,%obj,%col,%forceVehicleNode)
{
// Don't allow corpse looting
%dataBlock = %col.getDataBlock();
%className = %dataBlock.className;
if (%className $= "Armor")
if (%col.getState() $= "Dead")
return;
Parent::onCollision(%this, %obj, %col, %forceVehicleNode);
if (%obj.getState() $= "Dead")
return;
%obj.delayRoleChangeTime = getSimTime();
%dataBlock = %col.getDataBlock();
%className = %dataBlock.className;
%client = %obj.client;
if (%className $= "Armor")
{
if (%col.getState() $= "Dead" || %obj.invincible)
return;
CollisionBonus.evaluate(%obj, %col);
}
}
function Armor::onDisabled(%this, %obj, %state)
{
Game.assignOutermostRole(%obj.client);
if (!$TR2::DisableDeath || %obj.client.forceRespawn)
Parent::onDisabled(%this, %obj, %state);
}
function Armor::damageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType, %momVec, %mineSC)
{
//echo("Armor::damageObject() (targetClient = " @ getTaggedString(%targetObject.client.name) @ ")");
//echo("Armor::damageObject() (sourceClient = " @ getTaggedString(%sourceObject.client.name) @ ")");
//echo("Armor::damageObject() (sourceObj = " @ %sourceObject @ ")");
if (Game.goalJustScored)
return;
//if (%sourceObject == 0)
//{
//%targetObject.schedule(2, "setDataBlock", TR2HeavyMaleHumanArmor);
%targetObject.delayRoleChangeTime = getSimTime();
//}
return Parent::DamageObject(%data, %targetObject, %sourceObject, %position, %amount, %damageType, %momVec, %mineSC);
}
function ShapeBase::getHeight(%this)
{
%z = getWord(%this.getPosition(), 2);
return (%z - getTerrainHeight(%this.getPosition()));
}
function ShapeBase::getSpeed(%this)
{
return (VectorLen(%this.getVelocity()));
}
function ShapeBase::isOutOfBounds(%this)
{
%shapePos = %this.getPosition();
%shapex = firstWord(%shapePos);
%shapey = getWord(%shapePos, 1);
%bounds = MissionArea.area;
%boundsWest = firstWord(%bounds);
%boundsNorth = getWord(%bounds, 1);
%boundsEast = %boundsWest + getWord(%bounds, 2);
%boundsSouth = %boundsNorth + getWord(%bounds, 3);
return (%shapex < %boundsWest || %shapex > %boundsEast ||
%shapey < %boundsNorth || %shapey > %boundsSouth);
}
function ShapeBase::bounceOffGrid(%this, %bounceForce)
{
if (%bounceForce $= "")
%bounceForce = 85;
%oldVel = %this.getVelocity();
%this.setVelocity("0 0 0");
%vecx = firstWord(%oldVel);
%vecy = getWord(%oldVel, 1);
%vecz = getWord(%oldVel, 2);
%shapePos = %this.getPosition();
%shapex = firstWord(%shapePos);
%shapey = getWord(%shapePos, 1);
%bounds = MissionArea.area;
%boundsWest = firstWord(%bounds);
%boundsNorth = getWord(%bounds, 1);
%boundsEast = %boundsWest + getWord(%bounds, 2);
%boundsSouth = %boundsNorth + getWord(%bounds, 3);
// Two cases: 1) object is at E or W side; 2) object is at N or S side
if((%shapex <= %boundsWest) || (%shapex >= %boundsEast))
%vecx = -%vecx;
else
%vecy = -%vecy;
%vec = %vecx SPC %vecy SPC %vecz;
// normalize the vector, scale it
//%vecNorm = VectorNormalize(%vec);
//%vec = VectorScale(%vecNorm, 100 * %bounceForce);
// If the object's speed was pretty slow, give it a boost
%oldSpeed = VectorLen(%oldVel);
if (%oldSpeed < $TR2_MinimumGridBoost)
{
%vec = VectorNormalize(%vec);
%vec = VectorScale(%vec, $TR2_MinimumGridBoost);
}
else
%vec = VectorScale(%vec, $TR2_GridVelocityScale);
// apply the impulse to the flag object
//%this.applyImpulse(%this.getWorldBoxCenter(), %vec);
%this.setVelocity(%vec);
}
function Observer::setMode(%data, %obj, %mode, %targetObj)
{
if(%mode $= "")
return;
%client = %obj.getControllingClient();
%obsVector = $TR2_playerObserveParameters;
if (%client > 0 && %client.obsZoomLevel !$= "")
%zoomLevel = %client.obsZoomLevel;
else
%zoomLevel = 0;
%obsVector = VectorScale(%obsVector, $TR2::ObsZoomScale[%zoomLevel]);
%obsx = getWord(%obsVector, 0);
%obsy = getWord(%obsVector, 1);
%obsz = getWord(%obsVector, 2);
switch$ (%mode) {
case "justJoined":
commandToClient(%client, 'setHudMode', 'Observer');
%markerObj = Game.pickObserverSpawn(%client, true);
%transform = %markerObj.getTransform();
%obj.setTransform(%transform);
%obj.setFlyMode();
case "followFlag":
// Follow the dropped flag (hopefully)
%position = %targetObj.getPosition();
%newTransform = %position SPC %client.lastObsRot;
%obj.setOrbitMode(%targetObj, %newTransform, %obsx, %obsy, %obsz);
//%obj.setOrbitMode(%targetObj, %targetObj.getTransform(), %obsx, %obsy, %obsz);
%obj.mode = %mode;
case "pre-game":
commandToClient(%client, 'setHudMode', 'Observer');
%obj.setOrbitMode( %targetObj, %targetObj.getTransform(), %obsx, %obsy, %obsz);
case "observerFollow":
// Observer attached to a moving object (assume player for now...)
%position = %targetObj.getPosition();
%transform = %position SPC %client.lastObsRot;
//%obj.setOrbitMode(%targetObj, %newTransform, %obsx, %obsy, %obsz);
//%transform = %targetObj.getTransform();
if( !%targetObj.isMounted() )
%obj.setOrbitMode(%targetObj, %transform, %obsx, %obsy, %obsz);
else
{
%mount = %targetObj.getObjectMount();
if( %mount.getDataBlock().observeParameters $= "" )
%params = %transform;
else
%params = %mount.getDataBlock().observeParameters;
%obj.setOrbitMode(%mount, %mount.getTransform(), getWord( %params, 0 ), getWord( %params, 1 ), getWord( %params, 2 ));
}
case "observerFly":
// Free-flying observer camera
commandToClient(%client, 'setHudMode', 'Observer');
%markerObj = Game.pickObserverSpawn(%client, true);
%transform = %markerObj.getTransform();
%obj.setTransform(%transform);
%obj.setFlyMode();
case "observerStatic" or "observerStaticNoNext":
// Non-moving observer camera
%markerObj = Game.pickObserverSpawn(%client, true);
%transform = %markerObj.getTransform();
%obj.setTransform(%transform);
case "observerTimeout":
commandToClient(%client, 'setHudMode', 'Observer');
%markerObj = Game.pickObserverSpawn(%client, true);
%transform = %markerObj.getTransform();
%obj.setTransform(%transform);
%obj.setFlyMode();
}
%obj.mode = %mode;
}
function ShapeBaseImageData::onFire(%data, %obj, %slot)
{
//if (Game.goalJustScored)
// return;
%data.lightStart = getSimTime();
// TR2: No need for cloak logic
//if( %obj.station $= "" && %obj.isCloaked() )
//{
// if( %obj.respawnCloakThread !$= "" )
// {
// Cancel(%obj.respawnCloakThread);
// %obj.setCloaked( false );
// %obj.respawnCloakThread = "";
// }
// else
// {
// if( %obj.getEnergyLevel() > 20 )
// {
// %obj.setCloaked( false );
// %obj.reCloak = %obj.schedule( 500, "setCloaked", true );
// }
// }
//}
// TR2: Delay the disabling of invincibility to allow one free disc jump
if( %obj.client > 0 )
{
%obj.setInvincibleMode(0 ,0.00);
%obj.schedule(200, "setInvincible", false ); // fire your weapon and your invincibility goes away.
}
%vehicle = 0;
if(%data.usesEnergy)
{
if(%data.useMountEnergy)
{
%useEnergyObj = %obj.getObjectMount();
if(!%useEnergyObj)
%useEnergyObj = %obj;
%energy = %useEnergyObj.getEnergyLevel();
%vehicle = %useEnergyObj;
}
else
%energy = %obj.getEnergyLevel();
if(%data.useCapacitor && %data.usesEnergy)
{
if( %useEnergyObj.turretObject.getCapacitorLevel() < %data.minEnergy )
{
return;
}
}
else if(%energy < %data.minEnergy)
return;
}
if(%data.projectileSpread)
{
%vector = %obj.getMuzzleVector(%slot);
%x = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread;
%y = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread;
%z = (getRandom() - 0.5) * 2 * 3.1415926 * %data.projectileSpread;
%mat = MatrixCreateFromEuler(%x @ " " @ %y @ " " @ %z);
%vector = MatrixMulVector(%mat, %vector);
%p = new (%data.projectileType)() {
dataBlock = %data.projectile;
initialDirection = %vector;
initialPosition = %obj.getMuzzlePoint(%slot);
sourceObject = %obj;
sourceSlot = %slot;
vehicleObject = %vehicle;
};
}
else
{
%p = new (%data.projectileType)() {
dataBlock = %data.projectile;
initialDirection = %obj.getMuzzleVector(%slot);
initialPosition = %obj.getMuzzlePoint(%slot);
sourceObject = %obj;
sourceSlot = %slot;
vehicleObject = %vehicle;
};
// echo("blah");
}
if (isObject(%obj.lastProjectile) && %obj.deleteLastProjectile)
%obj.lastProjectile.delete();
%obj.lastProjectile = %p;
%obj.deleteLastProjectile = %data.deleteLastProjectile;
MissionCleanup.add(%p);
// AI hook
if(%obj.client)
%obj.client.projectile = %p;
if(%data.usesEnergy)
{
if(%data.useMountEnergy)
{
if( %data.useCapacitor )
{
%vehicle.turretObject.setCapacitorLevel( %vehicle.turretObject.getCapacitorLevel() - %data.fireEnergy );
}
else
%useEnergyObj.setEnergyLevel(%energy - %data.fireEnergy);
}
else
%obj.setEnergyLevel(%energy - %data.fireEnergy);
}
else
%obj.decInventory(%data.ammo,1);
return %p;
}
function updateScores()
{
if ( !isObject( Game ) )
return;
%numTeams = Game.numTeams;
// Initialize the team counts:
for ( %teamIndex = 0; %teamIndex <= %numTeams; %teamIndex++ )
Game.teamCount[%teamIndex] = 0;
%count = ClientGroup.getCount();
for ( %clientIndex = 0; %clientIndex < %count; %clientIndex++ )
{
%cl = ClientGroup.getObject( %clientIndex );
%team = %cl.getSensorGroup();
if ( %numTeams == 1 && %team != 0 )
%team = 1;
Game.teamScores[%team, Game.teamCount[%team], 0] = %cl.name;
if ( %cl.score $= "" )
Game.teamScores[%team, Game.teamCount[%team], 1] = 0;
else
Game.teamScores[%team, Game.teamCount[%team], 1] = %cl.passingScore + %cl.receivingScore;
Game.teamCount[%team]++;
}
}
// Ugly, non-gametype specific code to deal with tourney mode :/
function serverCmdClientPickedTeam( %client, %option )
{
if( Game.class $= "TR2Game" && %client.lastTeam <= 0 )
{
Game.forceObserver( %client, "playerChoose" );
return;
}
switch(%option)
{
case 1:
if ( isObject(%client.player) )
{
%client.player.scriptKill(0);
Game.clientChangeTeam(%client, %option, 0);
}
else
Game.clientJoinTeam( %client, %option, false );
case 2:
if ( isObject(%client.player) )
{
%client.player.scriptKill(0);
Game.clientChangeTeam(%client, %option, 0);
}
else
Game.clientJoinTeam( %client, %option, false );
case 3:
if( !isObject(%client.player) )
{
Game.assignClientTeam( %client, $MatchStarted );
Game.spawnPlayer( %client, false );
}
default:
if( isObject(%client.player) )
{
%client.player.scriptKill(0);
ClearBottomPrint(%client);
}
Game.forceObserver( %client, "playerChoose" );
%client.observerMode = "observer";
%client.notReady = false;
return;
}
// End z0dd - ZOD
// ------------------------------------------------------------------------------------
ClearBottomPrint(%client);
%client.observerMode = "pregame";
%client.notReady = true;
%client.camera.getDataBlock().setMode( %client.camera, "pre-game", %client.player );
commandToClient(%client, 'setHudMode', 'Observer');
%client.setControlObject( %client.camera );
centerprint( %client, "\nPress FIRE when ready.", 0, 3 );
}
function playerPickTeam( %client )
{
if( Game.class $= "TR2Game" )
{
if( %client.lastTeam > 0 )
schedule( 0, 0, "commandToClient", %client, 'pickTeamMenu', Game.getTeamName(1), Game.getTeamName(2));
}
else
{
%numTeams = Game.numTeams;
if(%numTeams > 1)
{
%client.camera.mode = "PickingTeam";
schedule( 0, 0, "commandToClient", %client, 'pickTeamMenu', Game.getTeamName(1), Game.getTeamName(2));
}
else
{
Game.clientJoinTeam(%client, 0, 0);
%client.observerMode = "pregame";
%client.notReady = true;
%client.camera.getDataBlock().setMode( %client.camera, "pre-game", %client.player );
centerprint( %client, "\nPress FIRE when ready.", 0, 3 );
%client.setControlObject( %client.camera );
}
}
}
function Beacon::onUse(%data, %obj)
{
// look for 3 meters along player's viewpoint for interior or terrain
// TR2: increased
//%searchRange = 3.0;
%searchRange = 5.2;
%mask = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType;
// get the eye vector and eye transform of the player
%eyeVec = %obj.getEyeVector();
%eyeTrans = %obj.getEyeTransform();
// extract the position of the player's camera from the eye transform (first 3 words)
%eyePos = posFromTransform(%eyeTrans);
// normalize the eye vector
%nEyeVec = VectorNormalize(%eyeVec);
// scale (lengthen) the normalized eye vector according to the search range
%scEyeVec = VectorScale(%nEyeVec, %searchRange);
// add the scaled & normalized eye vector to the position of the camera
%eyeEnd = VectorAdd(%eyePos, %scEyeVec);
// see if anything gets hit
%searchResult = containerRayCast(%eyePos, %eyeEnd, %mask, 0);
if(!%searchResult )
{
// no terrain/interior collision within search range
if(%obj.inv[%data.getName()] > 0)
messageClient(%obj.client, 'MsgBeaconNoSurface', '\c2Cannot place beacon. Too far from surface.');
return 0;
}
else
{
%searchObj = GetWord(%searchResult, 0);
if(%searchObj.getType() & ($TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType) )
{
// if there's already a beacon where player is aiming, switch its type
// otherwise, player can't deploy a beacon there
if(%searchObj.getDataBlock().getName() $= TR2DeployedBeacon)
switchBeaconType(%searchObj);
else
messageClient(%obj.client, 'MsgBeaconNoSurface', '\c2Cannot place beacon. Not a valid surface.');
return 0;
}
else if(%obj.inv[%data.getName()] <= 0)
return 0;
}
// newly deployed beacons default to "target" type
//if($TeamDeployedCount[%obj.team, TargetBeacon] >= $TeamDeployableMax[TargetBeacon])
//{
// messageClient(%obj.client, 'MsgDeployFailed', '\c2Your team\'s control network has reached its capacity for this item.~wfx/misc/misc.error.wav');
// return 0;
//}
%terrPt = posFromRaycast(%searchResult);
%terrNrm = normalFromRaycast(%searchResult);
%intAngle = getTerrainAngle(%terrNrm); // getTerrainAngle() function found in staticShape.cs
%rotAxis = vectorNormalize(vectorCross(%terrNrm, "0 0 1"));
if (getWord(%terrNrm, 2) == 1 || getWord(%terrNrm, 2) == -1)
%rotAxis = vectorNormalize(vectorCross(%terrNrm, "0 1 0"));
%rotation = %rotAxis @ " " @ %intAngle;
// TR2: T1-style beacon stop
%playerSpeed = %obj.getSpeed();
if (%obj.isJetting)
%obj.setVelocity("0 0 " @ %playerSpeed * $TR2_beaconStopScale);
else
%obj.setVelocity("0 0 0");
if (%playerSpeed > 17)
serverPlay3D(CarScreechSound, %obj.getPosition());
%obj.decInventory(%data, 1);
%depBeac = new BeaconObject() {
dataBlock = "DeployedBeacon";
position = VectorAdd(%terrPt, VectorScale(%terrNrm, 0.05));
rotation = %rotation;
};
//$TeamDeployedCount[%obj.team, TargetBeacon]++;
// TR2: Auto-delete beacon
%depBeac.startFade(2 * 1000, 0, true);
%depBeac.schedule(3 * 1000, "delete");
%depBeac.playThread($AmbientThread, "ambient");
%depBeac.team = %obj.team;
%depBeac.sourceObject = %obj;
// give it a team target
%depBeac.setTarget(%depBeac.team);
MissionCleanup.add(%depBeac);
}
function ShapeBase::throwObject(%this,%obj)
{
//if the object is being thrown by a corpse, use a random vector
if (%this.getState() $= "Dead" && %obj.getDataBlock().getName() !$= "TR2Flag1" )
{
%vec = (-1.0 + getRandom() * 2.0) SPC (-1.0 + getRandom() * 2.0) SPC getRandom();
%vec = vectorScale(%vec, 10);
}
// else Initial vel based on the dir the player is looking
else
{
%eye = %this.getEyeVector();
%vec = vectorScale(%eye, 20);
}
// Add player's velocity
%vec = vectorAdd(%vec, %this.getVelocity());
%pos = getBoxCenter(%this.getWorldBox());
// Add a vertical component to give the item a better arc
%dot = vectorDot("0 0 1",%eye);
if (%dot < 0)
%dot = -%dot;
//since flags have a huge mass (so when you shoot them, they don't bounce too far)
//we need to up the %vec so that you can still throw them...
if (%obj.getDataBlock().getName() $= "TR2Flag1")
{
// Add the throw strength, which ranges from 0.2 - 1.2
// Make it range from 0 - 1
//%addedStrength = %this.flagThrowStrength/1.25 - 0.2;
%addedStrength = %this.flagThrowStrength - 0.2;
%addedStrength *= $TR2_FlagThrowScale;
%vec = vectorAdd(%vec,vectorScale("0 0 " @ $TR2_UpwardFlagThrust,1 - %dot));
%flagVel = %this.getVelocity();
%playerRot = %this.getEyeVector();
%testDirection = VectorDot(VectorNormalize(%playerVel), VectorNormalize(%playerRot));
//%flagVel = VectorScale(%flagVel, 50);
%playerVel = VectorNormalize(%this.getVelocity());
if (%obj.oneTimer)
{
%playerVel = VectorScale(%playerVel, $TR2_PlayerVelocityAddedToFlagThrust / 1.3);
%addedStrength *= 1.1;
//%obj.oneTimer = 0;
}
else
%playerVel = VectorScale(%playerVel, $TR2_PlayerVelocityAddedToFlagThrust);
%playerRot = VectorScale(%playerRot, $TR2_ForwardFlagThrust * %addedStrength);
//%pos = VectorAdd(VectorNormalize(%playerRot), %this.getPosition());
%vec = VectorAdd(%vec, %playerVel);
%vec = VectorAdd(%vec, %playerRot);
// Don't apply the velocity impulse if the player is facing one direction
// but travelling in the other
//if (%testDirection > -0.85)
%newVel = VectorAdd(%playerVel, %newVel);
// apply the impulse to the flag object
//%flag.applyImpulse(%flag.getPosition(), %newVel);
%vec = vectorScale(%vec, $TR2_GeneralFlagBoost);
//%vec = %newVel;
//echo("applying flag impulse: " @ %vec);
// Remember the throw velocity in case T2's flag re-catch bug rears
// its ugly head, and we need to re-boost it
//%obj.throwVelocity = %vec;
// Try adjust the flag to start further away from the player in order to
// bypass T2's re-catch bug
%extend = VectorScale(VectorNormalize(%this.getEyeVector()), 2);
%pos = VectorAdd(%extend, %pos);
%this.throwStrength = 0;
}
%obj.setTransform(%pos);
%obj.applyImpulse(%pos,%vec);
%obj.setCollisionTimeout(%this);
%data = %obj.getDatablock();
%data.onThrow(%obj,%this);
//call the AI hook
//AIThrowObject(%obj);
}
// classic hoses this up.
// using the grenade throw from 24834
function HandInventory::onUse(%data, %obj)
{
// %obj = player %data = datablock of what's being thrown
if(Game.handInvOnUse(%data, %obj))
{
//AI HOOK - If you change the %throwStren, tell Tinman!!!
//Or edit aiInventory.cs and search for: use(%grenadeType);
%tossTimeout = getSimTime() - %obj.lastThrowTime[%data];
if(%tossTimeout < $HandInvThrowTimeout)
return;
%throwStren = %obj.throwStrength;
%obj.decInventory(%data, 1);
%thrownItem = new Item()
{
dataBlock = %data.thrownItem;
sourceObject = %obj;
};
MissionCleanup.add(%thrownItem);
// throw it
%eye = %obj.getEyeVector();
%vec = vectorScale(%eye, (%throwStren * 20.0));
// add a vertical component to give it a better arc
%dot = vectorDot("0 0 1", %eye);
if(%dot < 0)
%dot = -%dot;
%vec = vectorAdd(%vec, vectorScale("0 0 4", 1 - %dot));
// add player's velocity
%vec = vectorAdd(%vec, vectorScale(%obj.getVelocity(), 0.4));
%pos = getBoxCenter(%obj.getWorldBox());
%thrownItem.sourceObject = %obj;
%thrownItem.team = %obj.team;
%thrownItem.setTransform(%pos);
%thrownItem.applyImpulse(%pos, %vec);
%thrownItem.setCollisionTimeout(%obj);
serverPlay3D(GrenadeThrowSound, %pos);
%obj.lastThrowTime[%data] = getSimTime();
%thrownItem.getDataBlock().onThrow(%thrownItem, %obj);
%obj.throwStrength = 0;
}
}
};