mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-02 19:11:00 +00:00
493 lines
16 KiB
C#
493 lines
16 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.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Respawntime is the amount of time it takes for a static "auto-respawn"
|
|
// turret to re-appear after it's been picked up. Any turret marked as "static"
|
|
// is automaticlly respawned.
|
|
$TurretShape::RespawnTime = 30 * 1000;
|
|
|
|
// DestroyedFadeDelay is the how long a destroyed turret sticks around before it
|
|
// fades out and is deleted.
|
|
$TurretShape::DestroyedFadeDelay = 5 * 1000;
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// TurretShapeData
|
|
// ----------------------------------------------------------------------------
|
|
|
|
function TurretShapeData::onAdd(%this, %obj)
|
|
{
|
|
%obj.setRechargeRate(%this.rechargeRate);
|
|
%obj.setEnergyLevel(%this.MaxEnergy);
|
|
%obj.setRepairRate(0);
|
|
|
|
if (%obj.mountable || %obj.mountable $= "")
|
|
%this.isMountable(%obj, true);
|
|
else
|
|
%this.isMountable(%obj, false);
|
|
|
|
if (%this.nameTag !$= "")
|
|
%obj.setShapeName(%this.nameTag);
|
|
|
|
// Mount weapons
|
|
for(%i = 0; %i < %this.numWeaponMountPoints; %i++)
|
|
{
|
|
// Handle inventory
|
|
%obj.incInventory(%this.weapon[%i], 1);
|
|
%obj.incInventory(%this.weaponAmmo[%i], %this.weaponAmmoAmount[%i]);
|
|
|
|
// Mount the image
|
|
%obj.mountImage(%this.weapon[%i].image, %i, %this.startLoaded);
|
|
%obj.setImageGenericTrigger(%i, 0, false); // Used to indicate the turret is destroyed
|
|
}
|
|
|
|
if (%this.enterSequence !$= "")
|
|
{
|
|
%obj.entranceThread = 0;
|
|
%obj.playThread(%obj.entranceThread, %this.enterSequence);
|
|
%obj.pauseThread(%obj.entranceThread);
|
|
}
|
|
else
|
|
{
|
|
%obj.entranceThread = -1;
|
|
}
|
|
}
|
|
|
|
function TurretShapeData::onRemove(%this, %obj)
|
|
{
|
|
//echo("\c4TurretShapeData::onRemove("@ %this.getName() @", "@ %obj.getClassName() @")");
|
|
|
|
// if there are passengers/driver, kick them out
|
|
for(%i = 0; %i < %this.numMountPoints; %i++)
|
|
{
|
|
if (%obj.getMountNodeObject(%i))
|
|
{
|
|
%passenger = %obj.getMountNodeObject(%i);
|
|
%passenger.getDataBlock().doDismount(%passenger, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
// This is on MissionGroup so it doesn't happen when the mission has ended
|
|
function MissionGroup::respawnTurret(%this, %datablock, %className, %transform, %static, %respawn)
|
|
{
|
|
%turret = new (%className)()
|
|
{
|
|
datablock = %datablock;
|
|
static = %static;
|
|
respawn = %respawn;
|
|
};
|
|
|
|
%turret.setTransform(%transform);
|
|
MissionGroup.add(%turret);
|
|
return %turret;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// TurretShapeData damage state
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// This method is called by weapons fire
|
|
function TurretShapeData::damage(%this, %turret, %sourceObject, %position, %damage, %damageType)
|
|
{
|
|
//echo("\TurretShapeData::damage(" @ %turret @ ", "@ %sourceObject @ ", " @ %position @ ", "@ %damage @ ", "@ %damageType @ ")");
|
|
|
|
if (%turret.getState() $= "Dead")
|
|
return;
|
|
|
|
%turret.applyDamage(%damage);
|
|
|
|
// Update the numerical Health HUD
|
|
%mountedObject = %turret.getObjectMount();
|
|
if (%mountedObject)
|
|
%mountedObject.updateHealth();
|
|
|
|
// Kill any occupants
|
|
if (%turret.getState() $= "Dead")
|
|
{
|
|
for (%i = 0; %i < %this.numMountPoints; %i++)
|
|
{
|
|
%player = %turret.getMountNodeObject(%i);
|
|
if (%player != 0)
|
|
%player.killWithSource(%sourceObject, "InsideTurret");
|
|
}
|
|
}
|
|
}
|
|
|
|
function TurretShapeData::onDamage(%this, %obj, %delta)
|
|
{
|
|
// This method is invoked by the ShapeBase code whenever the
|
|
// object's damage level changes.
|
|
}
|
|
|
|
function TurretShapeData::onDestroyed(%this, %obj, %lastState)
|
|
{
|
|
// This method is invoked by the ShapeBase code whenever the
|
|
// object's damage state changes.
|
|
|
|
// Fade out the destroyed object. Then schedule a return.
|
|
%obj.startFade(1000, $TurretShape::DestroyedFadeDelay, true);
|
|
%obj.schedule($TurretShape::DestroyedFadeDelay + 1000, "delete");
|
|
|
|
if (%obj.doRespawn())
|
|
{
|
|
MissionGroup.schedule($TurretShape::RespawnTime, "respawnTurret", %this, %obj.getClassName(), %obj.getTransform(), true, true);
|
|
}
|
|
}
|
|
|
|
function TurretShapeData::onDisabled(%this, %obj, %lastState)
|
|
{
|
|
// This method is invoked by the ShapeBase code whenever the
|
|
// object's damage state changes.
|
|
}
|
|
|
|
function TurretShapeData::onEnabled(%this, %obj, %lastState)
|
|
{
|
|
// This method is invoked by the ShapeBase code whenever the
|
|
// object's damage state changes.
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// TurretShapeData player mounting and dismounting
|
|
// ----------------------------------------------------------------------------
|
|
|
|
function TurretShapeData::isMountable(%this, %obj, %val)
|
|
{
|
|
%obj.mountable = %val;
|
|
}
|
|
|
|
function TurretShapeData::onMountObject(%this, %turret, %player, %node)
|
|
{
|
|
if (%turret.entranceThread >= 0)
|
|
{
|
|
%turret.setThreadDir(%turret.entranceThread, true);
|
|
%turret.setThreadPosition(%turret.entranceThread, 0);
|
|
%turret.playThread(%turret.entranceThread, "");
|
|
}
|
|
}
|
|
|
|
function TurretShapeData::onUnmountObject(%this, %turret, %player)
|
|
{
|
|
if (%turret.entranceThread >= 0)
|
|
{
|
|
// Play the entrance thread backwards for an exit
|
|
%turret.setThreadDir(%turret.entranceThread, false);
|
|
%turret.setThreadPosition(%turret.entranceThread, 1);
|
|
%turret.playThread(%turret.entranceThread, "");
|
|
}
|
|
}
|
|
|
|
function TurretShapeData::mountPlayer(%this, %turret, %player)
|
|
{
|
|
//echo("\c4TurretShapeData::mountPlayer("@ %this.getName() @", "@ %turret @", "@ %player.client.nameBase @")");
|
|
|
|
if (isObject(%turret) && %turret.getDamageState() !$= "Destroyed")
|
|
{
|
|
//%player.startFade(1000, 0, true);
|
|
//%this.schedule(1000, "setMountTurret", %turret, %player);
|
|
//%player.schedule(1500, "startFade", 1000, 0, false);
|
|
%this.setMountTurret(%turret, %player);
|
|
}
|
|
}
|
|
|
|
function TurretShapeData::setMountTurret(%this, %turret, %player)
|
|
{
|
|
//echo("\c4TurretShapeData::setMountTurret("@ %this.getName() @", "@ %turret @", "@ %player.client.nameBase @")");
|
|
|
|
if (isObject(%turret) && %turret.getDamageState() !$= "Destroyed")
|
|
{
|
|
%node = %this.findEmptySeat(%turret, %player);
|
|
if (%node >= 0)
|
|
{
|
|
//echo("\c4Mount Node: "@ %node);
|
|
%turret.mountObject(%player, %node);
|
|
//%player.playAudio(0, MountVehicleSound);
|
|
%player.mVehicle = %turret;
|
|
}
|
|
}
|
|
}
|
|
|
|
function TurretShapeData::findEmptySeat(%this, %turret, %player)
|
|
{
|
|
//echo("\c4This turret has "@ %this.numMountPoints @" mount points.");
|
|
|
|
for (%i = 0; %i < %this.numMountPoints; %i++)
|
|
{
|
|
%node = %turret.getMountNodeObject(%i);
|
|
if (%node == 0)
|
|
return %i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
function TurretShapeData::switchSeats(%this, %turret, %player)
|
|
{
|
|
for (%i = 0; %i < %this.numMountPoints; %i++)
|
|
{
|
|
%node = %turret.getMountNodeObject(%i);
|
|
if (%node == %player || %node > 0)
|
|
continue;
|
|
|
|
if (%node == 0)
|
|
return %i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
function TurretShapeData::onMount(%this, %turret, %player, %node)
|
|
{
|
|
//echo("\c4TurretShapeData::onMount("@ %this.getName() @", "@ %turret @", "@ %player.client.nameBase @")");
|
|
|
|
%player.client.RefreshVehicleHud(%turret, %this.reticle, %this.zoomReticle);
|
|
//%player.client.UpdateVehicleHealth(%turret);
|
|
}
|
|
|
|
function TurretShapeData::onUnmount(%this, %turret, %player, %node)
|
|
{
|
|
//echo("\c4TurretShapeData::onUnmount(" @ %this.getName() @ ", " @ %turret @ ", " @ %player.client.nameBase @ ")");
|
|
|
|
%player.client.RefreshVehicleHud(0, "", "");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// TurretShape damage
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// This method is called by weapons fire
|
|
function TurretShape::damage(%this, %sourceObject, %position, %damage, %damageType)
|
|
{
|
|
//echo("\TurretShape::damage(" @ %this @ ", "@ %sourceObject @ ", " @ %position @ ", "@ %damage @ ", "@ %damageType @ ")");
|
|
|
|
%this.getDataBlock().damage(%this, %sourceObject, %position, %damage, %damageType);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// TurretDamage
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Customized kill message for deaths caused by turrets
|
|
function sendMsgClientKilled_TurretDamage( %msgType, %client, %sourceClient, %damLoc )
|
|
{
|
|
if ( %sourceClient $= "" ) // editor placed turret
|
|
messageAll( %msgType, '%1 was shot down by a turret!', %client.playerName );
|
|
else if ( %sourceClient == %client ) // own mine
|
|
messageAll( %msgType, '%1 kill by his own turret!', %client.playerName );
|
|
else // enemy placed mine
|
|
messageAll( %msgType, '%1 was killed by a turret of %2!', %client.playerName, %sourceClient.playerName );
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// AITurretShapeData
|
|
// ----------------------------------------------------------------------------
|
|
|
|
function AITurretShapeData::onAdd(%this, %obj)
|
|
{
|
|
Parent::onAdd(%this, %obj);
|
|
|
|
%obj.mountable = false;
|
|
}
|
|
|
|
// Player has thrown a deployable turret. This copies from ItemData::onThrow()
|
|
function AITurretShapeData::onThrow(%this, %user, %amount)
|
|
{
|
|
// Remove the object from the inventory
|
|
if (%amount $= "")
|
|
%amount = 1;
|
|
if (%this.maxInventory !$= "")
|
|
if (%amount > %this.maxInventory)
|
|
%amount = %this.maxInventory;
|
|
if (!%amount)
|
|
return 0;
|
|
%user.decInventory(%this,%amount);
|
|
|
|
// Construct the actual object in the world, and add it to
|
|
// the mission group so it's cleaned up when the mission is
|
|
// done. The turret's rotation matches the player's.
|
|
%rot = %user.getEulerRotation();
|
|
%obj = new AITurretShape()
|
|
{
|
|
datablock = %this;
|
|
rotation = "0 0 1 " @ getWord(%rot, 2);
|
|
count = 1;
|
|
sourceObject = %user;
|
|
client = %user.client;
|
|
isAiControlled = true;
|
|
};
|
|
MissionGroup.add(%obj);
|
|
|
|
// Let the turret know that we're a firend
|
|
%obj.addToIgnoreList(%user);
|
|
|
|
// We need to add this turret to a list on the client so that if we die,
|
|
// the turret will still ignore our player.
|
|
%client = %user.client;
|
|
if (%client)
|
|
{
|
|
if (!%client.ownedTurrets)
|
|
{
|
|
%client.ownedTurrets = new SimSet();
|
|
}
|
|
|
|
// Go through the client's owned turret list. Make sure we're
|
|
// a friend of every turret and every turret is a friend of ours.
|
|
// Commence hugging!
|
|
for (%i=0; %i<%client.ownedTurrets.getCount(); %i++)
|
|
{
|
|
%turret = %client.ownedTurrets.getObject(%i);
|
|
%turret.addToIgnoreList(%obj);
|
|
%obj.addToIgnoreList(%turret);
|
|
}
|
|
|
|
// Add ourselves to the client's owned list.
|
|
%client.ownedTurrets.add(%obj);
|
|
}
|
|
|
|
return %obj;
|
|
}
|
|
|
|
function AITurretShapeData::onDestroyed(%this, %turret, %lastState)
|
|
{
|
|
// This method is invoked by the ShapeBase code whenever the
|
|
// object's damage state changes.
|
|
|
|
%turret.playAudio(0, TurretDestroyed);
|
|
%turret.setAllGunsFiring(false);
|
|
%turret.resetTarget();
|
|
%turret.setTurretState( "Destroyed", true );
|
|
|
|
// Set the weapons to destoryed
|
|
for(%i = 0; %i < %this.numWeaponMountPoints; %i++)
|
|
{
|
|
%turret.setImageGenericTrigger(%i, 0, true);
|
|
}
|
|
|
|
Parent::onDestroyed(%this, %turret, %lastState);
|
|
}
|
|
|
|
function AITurretShapeData::OnScanning(%this, %turret)
|
|
{
|
|
//echo("AITurretShapeData::OnScanning: " SPC %this SPC %turret);
|
|
|
|
%turret.startScanForTargets();
|
|
%turret.playAudio(0, TurretScanningSound);
|
|
}
|
|
|
|
function AITurretShapeData::OnTarget(%this, %turret)
|
|
{
|
|
//echo("AITurretShapeData::OnTarget: " SPC %this SPC %turret);
|
|
|
|
%turret.startTrackingTarget();
|
|
%turret.playAudio(0, TargetAquiredSound);
|
|
}
|
|
|
|
function AITurretShapeData::OnNoTarget(%this, %turret)
|
|
{
|
|
//echo("AITurretShapeData::OnNoTarget: " SPC %this SPC %turret);
|
|
|
|
%turret.setAllGunsFiring(false);
|
|
%turret.recenterTurret();
|
|
%turret.playAudio(0, TargetLostSound);
|
|
}
|
|
|
|
function AITurretShapeData::OnFiring(%this, %turret)
|
|
{
|
|
//echo("AITurretShapeData::OnFiring: " SPC %this SPC %turret);
|
|
|
|
%turret.setAllGunsFiring(true);
|
|
}
|
|
|
|
function AITurretShapeData::OnThrown(%this, %turret)
|
|
{
|
|
//echo("AITurretShapeData::OnThrown: " SPC %this SPC %turret);
|
|
|
|
%turret.playAudio(0, TurretThrown);
|
|
}
|
|
|
|
function AITurretShapeData::OnDeploy(%this, %turret)
|
|
{
|
|
//echo("AITurretShapeData::OnDeploy: " SPC %this SPC %turret);
|
|
|
|
// Set the weapons to loaded
|
|
for(%i = 0; %i < %this.numWeaponMountPoints; %i++)
|
|
{
|
|
%turret.setImageLoaded(%i, true);
|
|
}
|
|
|
|
%turret.playAudio(0, TurretActivatedSound);
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Player deployable turret
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Cannot use the Weapon class for deployable turrets as it is already tied
|
|
// to ItemData.
|
|
|
|
function DeployableTurretWeapon::onUse(%this, %obj)
|
|
{
|
|
Weapon::onUse(%this, %obj);
|
|
}
|
|
|
|
function DeployableTurretWeapon::onPickup(%this, %obj, %shape, %amount)
|
|
{
|
|
Weapon::onPickup(%this, %obj, %shape, %amount);
|
|
}
|
|
|
|
function DeployableTurretWeapon::onInventory(%this, %obj, %amount)
|
|
{
|
|
if (%obj.client !$= "" && !%obj.isAiControlled)
|
|
{
|
|
%obj.client.setAmmoAmountHud( 1, %amount );
|
|
}
|
|
|
|
// Cycle weapons if we are out of ammo
|
|
if ( !%amount && ( %slot = %obj.getMountSlot( %this.image ) ) != -1 )
|
|
%obj.cycleWeapon( "prev" );
|
|
}
|
|
|
|
function DeployableTurretWeaponImage::onMount(%this, %obj, %slot)
|
|
{
|
|
// The turret doesn't use ammo from a player's perspective.
|
|
%obj.setImageAmmo(%slot, true);
|
|
%numTurrets = %obj.getInventory(%this.item);
|
|
|
|
if (%obj.client !$= "" && !%obj.isAiControlled)
|
|
%obj.client.RefreshWeaponHud( 1, %this.item.previewImage, %this.item.reticle, %this.item.zoomReticle, %numTurrets);
|
|
}
|
|
|
|
function DeployableTurretWeaponImage::onUnmount(%this, %obj, %slot)
|
|
{
|
|
if (%obj.client !$= "" && !%obj.isAiControlled)
|
|
%obj.client.RefreshWeaponHud(0, "", "");
|
|
}
|
|
|
|
function DeployableTurretWeaponImage::onFire(%this, %obj, %slot)
|
|
{
|
|
//echo("\DeployableTurretWeaponImage::onFire( "@%this.getName()@", "@%obj.client.nameBase@", "@%slot@" )");
|
|
|
|
// To fire a deployable turret is to throw it. Schedule the throw
|
|
// so that it doesn't happen during this ShapeBaseImageData's state machine.
|
|
// If we throw the last one then we end up unmounting while the state machine
|
|
// is still being processed.
|
|
%obj.schedule(0, "throw", %this.item);
|
|
}
|