mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-12 15:14:35 +00:00
Full Template for ticket #1
This commit is contained in:
parent
74f265b3b3
commit
f439dc8dcd
2150 changed files with 286240 additions and 0 deletions
328
Templates/Full/game/scripts/server/aiPlayer.cs
Normal file
328
Templates/Full/game/scripts/server/aiPlayer.cs
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// AIPlayer callbacks
|
||||
// The AIPlayer class implements the following callbacks:
|
||||
//
|
||||
// PlayerData::onStop(%this,%obj)
|
||||
// PlayerData::onMove(%this,%obj)
|
||||
// PlayerData::onReachDestination(%this,%obj)
|
||||
// PlayerData::onMoveStuck(%this,%obj)
|
||||
// PlayerData::onTargetEnterLOS(%this,%obj)
|
||||
// PlayerData::onTargetExitLOS(%this,%obj)
|
||||
// PlayerData::onAdd(%this,%obj)
|
||||
//
|
||||
// Since the AIPlayer doesn't implement it's own datablock, these callbacks
|
||||
// all take place in the PlayerData namespace.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Demo Pathed AIPlayer.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function DemoPlayer::onReachDestination(%this,%obj)
|
||||
{
|
||||
//echo( %obj @ " onReachDestination" );
|
||||
|
||||
// Moves to the next node on the path.
|
||||
// Override for all player. Normally we'd override this for only
|
||||
// a specific player datablock or class of players.
|
||||
if (%obj.path !$= "")
|
||||
{
|
||||
if (%obj.currentNode == %obj.targetNode)
|
||||
%this.onEndOfPath(%obj,%obj.path);
|
||||
else
|
||||
%obj.moveToNextNode();
|
||||
}
|
||||
}
|
||||
|
||||
function DemoPlayer::onMoveStuck(%this,%obj)
|
||||
{
|
||||
//echo( %obj @ " onMoveStuck" );
|
||||
}
|
||||
|
||||
function DemoPlayer::onTargetExitLOS(%this,%obj)
|
||||
{
|
||||
//echo( %obj @ " onTargetExitLOS" );
|
||||
}
|
||||
|
||||
function DemoPlayer::onTargetEnterLOS(%this,%obj)
|
||||
{
|
||||
//echo( %obj @ " onTargetEnterLOS" );
|
||||
}
|
||||
|
||||
function DemoPlayer::onEndOfPath(%this,%obj,%path)
|
||||
{
|
||||
%obj.nextTask();
|
||||
}
|
||||
|
||||
function DemoPlayer::onEndSequence(%this,%obj,%slot)
|
||||
{
|
||||
echo("Sequence Done!");
|
||||
%obj.stopThread(%slot);
|
||||
%obj.nextTask();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// AIPlayer static functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function AIPlayer::spawn(%name,%spawnPoint)
|
||||
{
|
||||
// Create the demo player object
|
||||
%player = new AiPlayer()
|
||||
{
|
||||
dataBlock = DemoPlayer;
|
||||
path = "";
|
||||
};
|
||||
MissionCleanup.add(%player);
|
||||
%player.setShapeName(%name);
|
||||
%player.setTransform(%spawnPoint);
|
||||
return %player;
|
||||
}
|
||||
|
||||
function AIPlayer::spawnOnPath(%name,%path)
|
||||
{
|
||||
// Spawn a player and place him on the first node of the path
|
||||
if (!isObject(%path))
|
||||
return 0;
|
||||
%node = %path.getObject(0);
|
||||
%player = AIPlayer::spawn(%name, %node.getTransform());
|
||||
return %player;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// AIPlayer methods
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function AIPlayer::followPath(%this,%path,%node)
|
||||
{
|
||||
// Start the player following a path
|
||||
%this.stopThread(0);
|
||||
if (!isObject(%path))
|
||||
{
|
||||
%this.path = "";
|
||||
return;
|
||||
}
|
||||
|
||||
if (%node > %path.getCount() - 1)
|
||||
%this.targetNode = %path.getCount() - 1;
|
||||
else
|
||||
%this.targetNode = %node;
|
||||
|
||||
if (%this.path $= %path)
|
||||
%this.moveToNode(%this.currentNode);
|
||||
else
|
||||
{
|
||||
%this.path = %path;
|
||||
%this.moveToNode(0);
|
||||
}
|
||||
}
|
||||
|
||||
function AIPlayer::moveToNextNode(%this)
|
||||
{
|
||||
if (%this.targetNode < 0 || %this.currentNode < %this.targetNode)
|
||||
{
|
||||
if (%this.currentNode < %this.path.getCount() - 1)
|
||||
%this.moveToNode(%this.currentNode + 1);
|
||||
else
|
||||
%this.moveToNode(0);
|
||||
}
|
||||
else
|
||||
if (%this.currentNode == 0)
|
||||
%this.moveToNode(%this.path.getCount() - 1);
|
||||
else
|
||||
%this.moveToNode(%this.currentNode - 1);
|
||||
}
|
||||
|
||||
function AIPlayer::moveToNode(%this,%index)
|
||||
{
|
||||
// Move to the given path node index
|
||||
%this.currentNode = %index;
|
||||
%node = %this.path.getObject(%index);
|
||||
%this.setMoveDestination(%node.getTransform(), %index == %this.targetNode);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function AIPlayer::pushTask(%this,%method)
|
||||
{
|
||||
if (%this.taskIndex $= "")
|
||||
{
|
||||
%this.taskIndex = 0;
|
||||
%this.taskCurrent = -1;
|
||||
}
|
||||
%this.task[%this.taskIndex] = %method;
|
||||
%this.taskIndex++;
|
||||
if (%this.taskCurrent == -1)
|
||||
%this.executeTask(%this.taskIndex - 1);
|
||||
}
|
||||
|
||||
function AIPlayer::clearTasks(%this)
|
||||
{
|
||||
%this.taskIndex = 0;
|
||||
%this.taskCurrent = -1;
|
||||
}
|
||||
|
||||
function AIPlayer::nextTask(%this)
|
||||
{
|
||||
if (%this.taskCurrent != -1)
|
||||
if (%this.taskCurrent < %this.taskIndex - 1)
|
||||
%this.executeTask(%this.taskCurrent++);
|
||||
else
|
||||
%this.taskCurrent = -1;
|
||||
}
|
||||
|
||||
function AIPlayer::executeTask(%this,%index)
|
||||
{
|
||||
%this.taskCurrent = %index;
|
||||
eval(%this.getId() @"."@ %this.task[%index] @";");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function AIPlayer::singleShot(%this)
|
||||
{
|
||||
// The shooting delay is used to pulse the trigger
|
||||
%this.setImageTrigger(0, true);
|
||||
%this.setImageTrigger(0, false);
|
||||
%this.trigger = %this.schedule(%this.shootingDelay, singleShot);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function AIPlayer::wait(%this, %time)
|
||||
{
|
||||
%this.schedule(%time * 1000, "nextTask");
|
||||
}
|
||||
|
||||
function AIPlayer::done(%this,%time)
|
||||
{
|
||||
%this.schedule(0, "delete");
|
||||
}
|
||||
|
||||
function AIPlayer::fire(%this,%bool)
|
||||
{
|
||||
if (%bool)
|
||||
{
|
||||
cancel(%this.trigger);
|
||||
%this.singleShot();
|
||||
}
|
||||
else
|
||||
cancel(%this.trigger);
|
||||
%this.nextTask();
|
||||
}
|
||||
|
||||
function AIPlayer::aimAt(%this,%object)
|
||||
{
|
||||
echo("Aim: "@ %object);
|
||||
%this.setAimObject(%object);
|
||||
%this.nextTask();
|
||||
}
|
||||
|
||||
function AIPlayer::animate(%this,%seq)
|
||||
{
|
||||
//%this.stopThread(0);
|
||||
//%this.playThread(0,%seq);
|
||||
%this.setActionThread(%seq);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Some handy getDistance/nearestTarget functions for the AI to use
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function AIPlayer::getTargetDistance(%this, %target)
|
||||
{
|
||||
echo("\c4AIPlayer::getTargetDistance("@ %this @", "@ %target @")");
|
||||
$tgt = %target;
|
||||
%tgtPos = %target.getPosition();
|
||||
%eyePoint = %this.getWorldBoxCenter();
|
||||
%distance = VectorDist(%tgtPos, %eyePoint);
|
||||
echo("Distance to target = "@ %distance);
|
||||
return %distance;
|
||||
}
|
||||
|
||||
function AIPlayer::getNearestPlayerTarget(%this)
|
||||
{
|
||||
echo("\c4AIPlayer::getNearestPlayerTarget("@ %this @")");
|
||||
|
||||
%index = -1;
|
||||
%botPos = %this.getPosition();
|
||||
%count = ClientGroup.getCount();
|
||||
for(%i = 0; %i < %count; %i++)
|
||||
{
|
||||
%client = ClientGroup.getObject(%i);
|
||||
if (%client.player $= "" || %client.player == 0)
|
||||
return -1;
|
||||
%playerPos = %client.player.getPosition();
|
||||
|
||||
%tempDist = VectorDist(%playerPos, %botPos);
|
||||
if (%i == 0)
|
||||
{
|
||||
%dist = %tempDist;
|
||||
%index = %i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (%dist > %tempDist)
|
||||
{
|
||||
%dist = %tempDist;
|
||||
%index = %i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return %index;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function AIManager::think(%this)
|
||||
{
|
||||
// We could hook into the player's onDestroyed state instead of having to
|
||||
// "think", but thinking allows us to consider other things...
|
||||
if (!isObject(%this.player))
|
||||
%this.player = %this.spawn();
|
||||
%this.schedule(500, think);
|
||||
}
|
||||
|
||||
function AIManager::spawn(%this)
|
||||
{
|
||||
%player = AIPlayer::spawnOnPath("Shootme", "MissionGroup/Paths/Path1");
|
||||
|
||||
if (isObject(%player))
|
||||
{
|
||||
%player.followPath("MissionGroup/Paths/Path1", -1);
|
||||
|
||||
// slow this sucker down, I'm tired of chasing him!
|
||||
%player.setMoveSpeed(0.5);
|
||||
|
||||
//%player.mountImage(xxxImage, 0);
|
||||
//%player.setInventory(xxxAmmo, 1000);
|
||||
|
||||
return %player;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
75
Templates/Full/game/scripts/server/camera.cs
Normal file
75
Templates/Full/game/scripts/server/camera.cs
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Global movement speed that affects all cameras. This should be moved
|
||||
// into the camera datablock.
|
||||
$Camera::movementSpeed = 40;
|
||||
|
||||
function Observer::onTrigger(%this,%obj,%trigger,%state)
|
||||
{
|
||||
// state = 0 means that a trigger key was released
|
||||
if (%state == 0)
|
||||
return;
|
||||
|
||||
// Default player triggers: 0=fire 1=altFire 2=jump
|
||||
%client = %obj.getControllingClient();
|
||||
switch$ (%obj.mode)
|
||||
{
|
||||
case "Observer":
|
||||
// Do something interesting.
|
||||
|
||||
case "Corpse":
|
||||
// Fade out the corpse
|
||||
if (isObject(%obj.orbitObj))
|
||||
{
|
||||
cancelAll(%obj.orbitObj);
|
||||
%obj.orbitObj.schedule(0, "startFade", 1000, 0, true);
|
||||
%obj.orbitObj.schedule(1000, "delete");
|
||||
}
|
||||
|
||||
// Viewing dead corpse, so we probably want to respawn.
|
||||
game.preparePlayer(%client);
|
||||
|
||||
// Set the camera back into observer mode, since in
|
||||
// debug mode we like to switch to it.
|
||||
%this.setMode(%obj,"Observer");
|
||||
}
|
||||
}
|
||||
|
||||
function Observer::setMode(%this,%obj,%mode,%arg1,%arg2,%arg3)
|
||||
{
|
||||
switch$ (%mode)
|
||||
{
|
||||
case "Observer":
|
||||
// Let the player fly around
|
||||
%obj.setFlyMode();
|
||||
|
||||
case "Corpse":
|
||||
// Lock the camera down in orbit around the corpse,
|
||||
// which should be arg1
|
||||
%transform = %arg1.getTransform();
|
||||
%obj.setOrbitMode(%arg1, %transform, 0.5, 4.5, 4.5);
|
||||
%obj.orbitObj = %arg1;
|
||||
|
||||
}
|
||||
%obj.mode = %mode;
|
||||
}
|
||||
162
Templates/Full/game/scripts/server/cheetah.cs
Normal file
162
Templates/Full/game/scripts/server/cheetah.cs
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function CheetahCar::onAdd(%this, %obj)
|
||||
{
|
||||
Parent::onAdd(%this, %obj);
|
||||
|
||||
%obj.setWheelTire(0,CheetahCarTire);
|
||||
%obj.setWheelTire(1,CheetahCarTire);
|
||||
%obj.setWheelTire(2,CheetahCarTireRear);
|
||||
%obj.setWheelTire(3,CheetahCarTireRear);
|
||||
|
||||
// Setup the car with some tires & springs
|
||||
for (%i = %obj.getWheelCount() - 1; %i >= 0; %i--)
|
||||
{
|
||||
%obj.setWheelPowered(%i, true);
|
||||
%obj.setWheelSpring(%i, CheetahCarSpring);
|
||||
}
|
||||
|
||||
// Steer with the front tires
|
||||
%obj.setWheelSteering(0, 1);
|
||||
%obj.setWheelSteering(1, 1);
|
||||
|
||||
// Add tail lights
|
||||
%obj.rightBrakeLight = new PointLight()
|
||||
{
|
||||
radius = "1";
|
||||
isEnabled = "0";
|
||||
color = "1 0 0.141176 1";
|
||||
brightness = "2";
|
||||
castShadows = "1";
|
||||
priority = "1";
|
||||
animate = "0";
|
||||
animationPeriod = "1";
|
||||
animationPhase = "1";
|
||||
flareScale = "1";
|
||||
attenuationRatio = "0 1 1";
|
||||
shadowType = "DualParaboloidSinglePass";
|
||||
texSize = "512";
|
||||
overDarkFactor = "2000 1000 500 100";
|
||||
shadowDistance = "400";
|
||||
shadowSoftness = "0.15";
|
||||
numSplits = "1";
|
||||
logWeight = "0.91";
|
||||
fadeStartDistance = "0";
|
||||
lastSplitTerrainOnly = "0";
|
||||
representedInLightmap = "0";
|
||||
shadowDarkenColor = "0 0 0 -1";
|
||||
includeLightmappedGeometryInShadow = "0";
|
||||
rotation = "1 0 0 0";
|
||||
canSave = "1";
|
||||
canSaveDynamicFields = "1";
|
||||
splitFadeDistances = "10 20 30 40";
|
||||
};
|
||||
%obj.leftBrakeLight = new PointLight()
|
||||
{
|
||||
radius = "1";
|
||||
isEnabled = "0";
|
||||
color = "1 0 0.141176 1";
|
||||
brightness = "2";
|
||||
castShadows = "1";
|
||||
priority = "1";
|
||||
animate = "0";
|
||||
animationPeriod = "1";
|
||||
animationPhase = "1";
|
||||
flareScale = "1";
|
||||
attenuationRatio = "0 1 1";
|
||||
shadowType = "DualParaboloidSinglePass";
|
||||
texSize = "512";
|
||||
overDarkFactor = "2000 1000 500 100";
|
||||
shadowDistance = "400";
|
||||
shadowSoftness = "0.15";
|
||||
numSplits = "1";
|
||||
logWeight = "0.91";
|
||||
fadeStartDistance = "0";
|
||||
lastSplitTerrainOnly = "0";
|
||||
representedInLightmap = "0";
|
||||
shadowDarkenColor = "0 0 0 -1";
|
||||
includeLightmappedGeometryInShadow = "0";
|
||||
rotation = "1 0 0 0";
|
||||
canSave = "1";
|
||||
canSaveDynamicFields = "1";
|
||||
splitFadeDistances = "10 20 30 40";
|
||||
};
|
||||
|
||||
// Mount a ShapeBaseImageData
|
||||
%didMount = %obj.mountImage(TurretImage, %this.turretSlot);
|
||||
|
||||
// Mount the brake lights
|
||||
%obj.mountObject(%obj.rightBrakeLight, %this.rightBrakeSlot);
|
||||
%obj.mountObject(%obj.leftBrakeLight, %this.leftBrakeSlot);
|
||||
}
|
||||
|
||||
function CheetahCar::onRemove(%this, %obj)
|
||||
{
|
||||
Parent::onRemove(%this, %obj);
|
||||
|
||||
if(isObject(%obj.rightBrakeLight))
|
||||
%obj.rightBrakeLight.delete();
|
||||
|
||||
if(isObject(%obj.leftBrakeLight))
|
||||
%obj.leftBrakeLight.delete();
|
||||
|
||||
if(isObject(%obj.turret))
|
||||
%obj.turret.delete();
|
||||
}
|
||||
|
||||
function serverCmdtoggleBrakeLights(%client)
|
||||
{
|
||||
%car = %client.player.getControlObject();
|
||||
|
||||
if (%car.getClassName() $= "WheeledVehicle")
|
||||
{
|
||||
if(%car.rightBrakeLight.isEnabled)
|
||||
{
|
||||
%car.rightBrakeLight.setLightEnabled(0);
|
||||
%car.leftBrakeLight.setLightEnabled(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
%car.rightBrakeLight.setLightEnabled(1);
|
||||
%car.leftBrakeLight.setLightEnabled(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Callback invoked when an input move trigger state changes when the CheetahCar
|
||||
// is the control object
|
||||
function CheetahCar::onTrigger(%this, %obj, %index, %state)
|
||||
{
|
||||
// Pass trigger states on to TurretImage (to fire weapon)
|
||||
switch ( %index )
|
||||
{
|
||||
case 0: %obj.setImageTrigger( %this.turretSlot, %state );
|
||||
case 1: %obj.setImageAltTrigger( %this.turretSlot, %state );
|
||||
}
|
||||
}
|
||||
|
||||
function TurretImage::onMount(%this, %obj, %slot)
|
||||
{
|
||||
// Load the gun
|
||||
%obj.setImageAmmo(%slot, true);
|
||||
}
|
||||
123
Templates/Full/game/scripts/server/commands.cs
Normal file
123
Templates/Full/game/scripts/server/commands.cs
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Misc server commands avialable to clients
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function serverCmdSuicide(%client)
|
||||
{
|
||||
if (isObject(%client.player))
|
||||
%client.player.kill("Suicide");
|
||||
}
|
||||
|
||||
function serverCmdPlayCel(%client,%anim)
|
||||
{
|
||||
if (isObject(%client.player))
|
||||
%client.player.playCelAnimation(%anim);
|
||||
}
|
||||
|
||||
function serverCmdTestAnimation(%client, %anim)
|
||||
{
|
||||
if (isObject(%client.player))
|
||||
%client.player.playTestAnimation(%anim);
|
||||
}
|
||||
|
||||
function serverCmdPlayDeath(%client)
|
||||
{
|
||||
if (isObject(%client.player))
|
||||
%client.player.playDeathAnimation();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Throw/Toss
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function serverCmdThrow(%client, %data)
|
||||
{
|
||||
%player = %client.player;
|
||||
if(!isObject(%player) || %player.getState() $= "Dead" || !$Game::Running)
|
||||
return;
|
||||
switch$ (%data)
|
||||
{
|
||||
case "Weapon":
|
||||
%item = (%player.getMountedImage($WeaponSlot) == 0) ? "" : %player.getMountedImage($WeaponSlot).item;
|
||||
if (%item !$="")
|
||||
%player.throw(%item);
|
||||
case "Ammo":
|
||||
%weapon = (%player.getMountedImage($WeaponSlot) == 0) ? "" : %player.getMountedImage($WeaponSlot);
|
||||
if (%weapon !$= "")
|
||||
{
|
||||
if(%weapon.ammo !$= "")
|
||||
%player.throw(%weapon.ammo);
|
||||
}
|
||||
default:
|
||||
if(%player.hasInventory(%data.getName()))
|
||||
%player.throw(%data);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Force game end and cycle
|
||||
// Probably don't want this in a final game without some checks. Anyone could
|
||||
// restart a game.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function serverCmdFinishGame()
|
||||
{
|
||||
cycleGame();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Cycle weapons
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function serverCmdCycleWeapon(%client, %direction)
|
||||
{
|
||||
%client.getControlObject().cycleWeapon(%direction);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Unmount current weapon
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function serverCmdUnmountWeapon(%client)
|
||||
{
|
||||
%client.getControlObject().unmountImage($WeaponSlot);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Weapon reloading
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function serverCmdReloadWeapon(%client)
|
||||
{
|
||||
%player = %client.getControlObject();
|
||||
%image = %player.getMountedImage($WeaponSlot);
|
||||
|
||||
// Don't reload if the weapon's full.
|
||||
if (%player.getInventory(%image.ammo) == %image.ammo.maxInventory)
|
||||
return;
|
||||
|
||||
if (%image > 0)
|
||||
%image.clearAmmoClip(%player, $WeaponSlot);
|
||||
}
|
||||
43
Templates/Full/game/scripts/server/defaults.cs
Normal file
43
Templates/Full/game/scripts/server/defaults.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// First we execute the core default preferences.
|
||||
exec( "core/scripts/server/defaults.cs" );
|
||||
|
||||
|
||||
// Now add your own game specific server preferences as
|
||||
// well as any overloaded core defaults here.
|
||||
|
||||
|
||||
|
||||
|
||||
// Finally load the preferences saved from the last
|
||||
// game execution if they exist.
|
||||
if ( $platform !$= "xenon" )
|
||||
{
|
||||
if ( isFile( "./prefs.cs" ) )
|
||||
exec( "./prefs.cs" );
|
||||
}
|
||||
else
|
||||
{
|
||||
echo( "Not loading server prefs.cs on Xbox360" );
|
||||
}
|
||||
190
Templates/Full/game/scripts/server/game.cs
Normal file
190
Templates/Full/game/scripts/server/game.cs
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Game duration in secs, no limit if the duration is set to 0
|
||||
$Game::Duration = 20 * 60;
|
||||
|
||||
// When a client score reaches this value, the game is ended.
|
||||
$Game::EndGameScore = 30;
|
||||
|
||||
// Pause while looking over the end game screen (in secs)
|
||||
$Game::EndGamePause = 10;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function onServerCreated()
|
||||
{
|
||||
// Server::GameType is sent to the master server.
|
||||
// This variable should uniquely identify your game and/or mod.
|
||||
$Server::GameType = $appName;
|
||||
|
||||
// Server::MissionType sent to the master server. Clients can
|
||||
// filter servers based on mission type.
|
||||
$Server::MissionType = "Deathmatch";
|
||||
|
||||
// GameStartTime is the sim time the game started. Used to calculated
|
||||
// game elapsed time.
|
||||
$Game::StartTime = 0;
|
||||
|
||||
// Create the server physics world.
|
||||
physicsInitWorld( "server" );
|
||||
|
||||
// Load up any objects or datablocks saved to the editor managed scripts
|
||||
%datablockFiles = new ArrayObject();
|
||||
%datablockFiles.add( "art/shapes/particles/managedParticleData.cs" );
|
||||
%datablockFiles.add( "art/shapes/particles/managedParticleEmitterData.cs" );
|
||||
%datablockFiles.add( "art/decals/managedDecalData.cs" );
|
||||
%datablockFiles.add( "art/datablocks/managedDatablocks.cs" );
|
||||
%datablockFiles.add( "art/forest/managedItemData.cs" );
|
||||
%datablockFiles.add( "art/datablocks/datablockExec.cs" );
|
||||
loadDatablockFiles( %datablockFiles, true );
|
||||
|
||||
// Run the other gameplay scripts in this folder
|
||||
exec("./scriptExec.cs");
|
||||
|
||||
// Keep track of when the game started
|
||||
$Game::StartTime = $Sim::Time;
|
||||
}
|
||||
|
||||
function onServerDestroyed()
|
||||
{
|
||||
// This function is called as part of a server shutdown.
|
||||
|
||||
physicsDestroyWorld( "server" );
|
||||
|
||||
// Clean up the GameCore package here as it persists over the
|
||||
// life of the server.
|
||||
if (isPackage(GameCore))
|
||||
{
|
||||
deactivatePackage(GameCore);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function onGameDurationEnd()
|
||||
{
|
||||
// This "redirect" is here so that we can abort the game cycle if
|
||||
// the $Game::Duration variable has been cleared, without having
|
||||
// to have a function to cancel the schedule.
|
||||
|
||||
if ($Game::Duration && !(EditorIsActive() && GuiEditorIsActive()))
|
||||
Game.onGameDurationEnd();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function cycleGame()
|
||||
{
|
||||
// This is setup as a schedule so that this function can be called
|
||||
// directly from object callbacks. Object callbacks have to be
|
||||
// carefull about invoking server functions that could cause
|
||||
// their object to be deleted.
|
||||
|
||||
if (!$Game::Cycling)
|
||||
{
|
||||
$Game::Cycling = true;
|
||||
$Game::Schedule = schedule(0, 0, "onCycleExec");
|
||||
}
|
||||
}
|
||||
|
||||
function onCycleExec()
|
||||
{
|
||||
// End the current game and start another one, we'll pause for a little
|
||||
// so the end game victory screen can be examined by the clients.
|
||||
|
||||
//endGame();
|
||||
endMission();
|
||||
$Game::Schedule = schedule($Game::EndGamePause * 1000, 0, "onCyclePauseEnd");
|
||||
}
|
||||
|
||||
function onCyclePauseEnd()
|
||||
{
|
||||
$Game::Cycling = false;
|
||||
|
||||
// Just cycle through the missions for now.
|
||||
|
||||
%search = $Server::MissionFileSpec;
|
||||
%oldMissionFile = makeRelativePath( $Server::MissionFile );
|
||||
|
||||
for( %file = findFirstFile( %search ); %file !$= ""; %file = findNextFile( %search ) )
|
||||
{
|
||||
if( %file $= %oldMissionFile )
|
||||
{
|
||||
// Get the next one, back to the first if there is no next.
|
||||
%file = findNextFile( %search );
|
||||
if( %file $= "" )
|
||||
%file = findFirstFile(%search);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( %file $= "" )
|
||||
%file = findFirstFile( %search );
|
||||
|
||||
loadMission(%file);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GameConnection Methods
|
||||
// These methods are extensions to the GameConnection class. Extending
|
||||
// GameConnection makes it easier to deal with some of this functionality,
|
||||
// but these could also be implemented as stand-alone functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function GameConnection::onLeaveMissionArea(%this)
|
||||
{
|
||||
// The control objects invoke this method when they
|
||||
// move out of the mission area.
|
||||
|
||||
messageClient(%this, 'MsgClientJoin', '\c2Now leaving the mission area!');
|
||||
}
|
||||
|
||||
function GameConnection::onEnterMissionArea(%this)
|
||||
{
|
||||
// The control objects invoke this method when they
|
||||
// move back into the mission area.
|
||||
|
||||
messageClient(%this, 'MsgClientJoin', '\c2Now entering the mission area.');
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function GameConnection::onDeath(%this, %sourceObject, %sourceClient, %damageType, %damLoc)
|
||||
{
|
||||
game.onDeath(%this, %sourceObject, %sourceClient, %damageType, %damLoc);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// weapon HUD
|
||||
// ----------------------------------------------------------------------------
|
||||
function GameConnection::setAmmoAmountHud(%client, %amount, %amountInClips )
|
||||
{
|
||||
commandToClient(%client, 'SetAmmoAmountHud', %amount, %amountInClips);
|
||||
}
|
||||
|
||||
function GameConnection::RefreshWeaponHud(%client, %amount, %preview, %ret, %zoomRet, %amountInClips)
|
||||
{
|
||||
commandToClient(%client, 'RefreshWeaponHud', %amount, %preview, %ret, %zoomRet, %amountInClips);
|
||||
}
|
||||
1061
Templates/Full/game/scripts/server/gameCore.cs
Normal file
1061
Templates/Full/game/scripts/server/gameCore.cs
Normal file
File diff suppressed because it is too large
Load diff
112
Templates/Full/game/scripts/server/gameDM.cs
Normal file
112
Templates/Full/game/scripts/server/gameDM.cs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// DeathmatchGame
|
||||
// ----------------------------------------------------------------------------
|
||||
// Depends on methods found in gameCore.cs. Those added here are specific to
|
||||
// this game type and/or over-ride the "default" game functionaliy.
|
||||
//
|
||||
// The desired Game Type must be added to each mission's LevelInfo object.
|
||||
// - gameType = "Deathmatch";
|
||||
// If this information is missing then the GameCore will default to Deathmatch.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function DeathMatchGame::onMissionLoaded(%game)
|
||||
{
|
||||
//echo (%game @"\c4 -> "@ %game.class @" -> DeathMatchGame::onMissionLoaded");
|
||||
|
||||
$Server::MissionType = "DeathMatch";
|
||||
parent::onMissionLoaded(%game);
|
||||
}
|
||||
|
||||
function DeathMatchGame::initGameVars(%game)
|
||||
{
|
||||
//echo (%game @"\c4 -> "@ %game.class @" -> DeathMatchGame::initGameVars");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// What kind of "player" is spawned is either controlled directly by the
|
||||
// SpawnSphere or it defaults back to the values set here. This also controls
|
||||
// which SimGroups to attempt to select the spawn sphere's from by walking down
|
||||
// the list of SpawnGroups till it finds a valid spawn object.
|
||||
// These override the values set in core/scripts/server/spawn.cs
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Leave $Game::defaultPlayerClass and $Game::defaultPlayerDataBlock as empty strings ("")
|
||||
// to spawn a the $Game::defaultCameraClass as the control object.
|
||||
$Game::defaultPlayerClass = "Player";
|
||||
$Game::defaultPlayerDataBlock = "DefaultPlayerData";
|
||||
$Game::defaultPlayerSpawnGroups = "PlayerSpawnPoints PlayerDropPoints";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// What kind of "camera" is spawned is either controlled directly by the
|
||||
// SpawnSphere or it defaults back to the values set here. This also controls
|
||||
// which SimGroups to attempt to select the spawn sphere's from by walking down
|
||||
// the list of SpawnGroups till it finds a valid spawn object.
|
||||
// These override the values set in core/scripts/server/spawn.cs
|
||||
//-----------------------------------------------------------------------------
|
||||
$Game::defaultCameraClass = "Camera";
|
||||
$Game::defaultCameraDataBlock = "Observer";
|
||||
$Game::defaultCameraSpawnGroups = "CameraSpawnPoints PlayerSpawnPoints PlayerDropPoints";
|
||||
|
||||
// Set the gameplay parameters
|
||||
%game.duration = 30 * 60;
|
||||
%game.endgameScore = 20;
|
||||
%game.endgamePause = 10;
|
||||
%game.allowCycling = false; // Is mission cycling allowed?
|
||||
}
|
||||
|
||||
function DeathMatchGame::startGame(%game)
|
||||
{
|
||||
//echo (%game @"\c4 -> "@ %game.class @" -> DeathMatchGame::startGame");
|
||||
|
||||
parent::startGame(%game);
|
||||
}
|
||||
|
||||
function DeathMatchGame::endGame(%game)
|
||||
{
|
||||
//echo (%game @"\c4 -> "@ %game.class @" -> DeathMatchGame::endGame");
|
||||
|
||||
parent::endGame(%game);
|
||||
}
|
||||
|
||||
function DeathMatchGame::onGameDurationEnd(%game)
|
||||
{
|
||||
//echo (%game @"\c4 -> "@ %game.class @" -> DeathMatchGame::onGameDurationEnd");
|
||||
|
||||
parent::onGameDurationEnd(%game);
|
||||
}
|
||||
|
||||
function DeathMatchGame::onClientEnterGame(%game, %client)
|
||||
{
|
||||
//echo (%game @"\c4 -> "@ %game.class @" -> DeathMatchGame::onClientEnterGame");
|
||||
|
||||
parent::onClientEnterGame(%game, %client);
|
||||
}
|
||||
|
||||
function DeathMatchGame::onClientLeaveGame(%game, %client)
|
||||
{
|
||||
//echo (%game @"\c4 -> "@ %game.class @" -> DeathMatchGame::onClientLeaveGame");
|
||||
|
||||
parent::onClientLeaveGame(%game, %client);
|
||||
|
||||
}
|
||||
117
Templates/Full/game/scripts/server/grenadeLauncher.cs
Normal file
117
Templates/Full/game/scripts/server/grenadeLauncher.cs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function enableManualDetonation(%obj)
|
||||
{
|
||||
%obj.detonadeEnabled = true;
|
||||
}
|
||||
|
||||
function doManualDetonation(%obj)
|
||||
{
|
||||
%nade = new Item()
|
||||
{
|
||||
dataBlock = Detonade;
|
||||
};
|
||||
MissionCleanup.add(%nade);
|
||||
|
||||
%nade.setTransform(%obj.getTransform());
|
||||
%nade.sourceObject = %obj.sourceObject;
|
||||
%nade.schedule(50, "setDamageState", "Destroyed"); // Why must we schedule?!
|
||||
//%nade.setDamageState(Destroyed);
|
||||
|
||||
%obj.delete();
|
||||
}
|
||||
|
||||
function Detonade::onDestroyed(%this, %object, %lastState)
|
||||
{
|
||||
radiusDamage(%object, %object.getPosition(), 10, 25, "DetonadeDamage", 2000);
|
||||
}
|
||||
|
||||
function GrenadeLauncherImage::onMount(%this, %obj, %slot)
|
||||
{
|
||||
// Make it ready
|
||||
%obj.detonadeEnabled = true;
|
||||
Parent::onMount(%this, %obj, %slot);
|
||||
}
|
||||
|
||||
function GrenadeLauncherImage::onAltFire(%this, %obj, %slot)
|
||||
{
|
||||
/*
|
||||
//echo("\c4GrenadeLauncherImage::onFire("@ %this.getName() @", "@ %obj.client.nameBase @", "@ %slot@")");
|
||||
|
||||
// It's not ready yet
|
||||
if(!%obj.detonadeEnabled)
|
||||
return;
|
||||
|
||||
// If we already have one of these... blow it up!!!
|
||||
if(isObject(%obj.lastProj))
|
||||
{
|
||||
doManualDetonation(%obj.lastProj);
|
||||
if(%obj.lastNade)
|
||||
{
|
||||
// We remove the ammo of the last projectile fired only after it has
|
||||
// been triggered, otherwise we wouldn't be able to set it off.
|
||||
%obj.lastNade = "";
|
||||
%obj.decInventory(%this.ammo, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// We fire our weapon using the straight ahead aiming point of the gun.
|
||||
%muzzleVector = %obj.getMuzzleVector(%slot);
|
||||
|
||||
// Get the player's velocity, we'll then add it to that of the projectile
|
||||
%objectVelocity = %obj.getVelocity();
|
||||
%muzzleVelocity = VectorAdd(
|
||||
VectorScale(%muzzleVector, %this.projectile.muzzleVelocity),
|
||||
VectorScale(%objectVelocity, %this.projectile.velInheritFactor));
|
||||
|
||||
%p = new (%this.projectileType)()
|
||||
{
|
||||
dataBlock = %this.projectile;
|
||||
initialVelocity = %muzzleVelocity;
|
||||
initialPosition = %obj.getMuzzlePoint(%slot);
|
||||
sourceObject = %obj;
|
||||
sourceSlot = %slot;
|
||||
client = %obj.client;
|
||||
};
|
||||
|
||||
%obj.lastProj = %p;
|
||||
MissionCleanup.add(%p);
|
||||
|
||||
// Decrement inventory ammo.
|
||||
//%obj.decInventory(%this.ammo, 1);
|
||||
|
||||
// Must do some trickiness with reducing the ammo count to account for the
|
||||
// very last shot. If we don't you wouldn't be able to trigger it.
|
||||
%currentAmmo = %obj.getInventory(%this.ammo);
|
||||
if(%currentAmmo == 1)
|
||||
%obj.lastNade = 1;
|
||||
else
|
||||
%obj.decInventory(%this.ammo, 1);
|
||||
|
||||
// We don't want to detonate it in our face now do we? Give it a little time.
|
||||
%obj.detonadeEnabled = false;
|
||||
schedule(250, 0, "enableManualDetonation", %obj);
|
||||
|
||||
*/
|
||||
}
|
||||
99
Templates/Full/game/scripts/server/health.cs
Normal file
99
Templates/Full/game/scripts/server/health.cs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Inventory items. These objects rely on the item & inventory support
|
||||
// system defined in item.cs and inventory.cs
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Health Patches cannot be picked up and are not meant to be added to inventory.
|
||||
// Health is applied automatically when an objects collides with a patch.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function HealthPatch::onCollision(%this, %obj, %col)
|
||||
{
|
||||
// Apply health to colliding object if it needs it.
|
||||
// Works for all shapebase objects.
|
||||
if (%col.getDamageLevel() != 0 && %col.getState() !$= "Dead")
|
||||
{
|
||||
%col.applyRepair(%this.repairAmount);
|
||||
|
||||
// Update the Health GUI while repairing
|
||||
%this.doHealthUpdate(%col);
|
||||
|
||||
%obj.respawn();
|
||||
if (%col.client)
|
||||
messageClient(%col.client, 'MsgHealthPatchUsed', '\c2Health Patch Applied');
|
||||
serverPlay3D(HealthUseSound, %obj.getTransform());
|
||||
}
|
||||
}
|
||||
|
||||
function HealthPatch::doHealthUpdate(%this, %obj)
|
||||
{
|
||||
// Would be better to add a onRepair() callback to shapeBase.cpp in order to
|
||||
// prevent any excess/unneccesary schedules from this. But for the time
|
||||
// being....
|
||||
|
||||
// This is just a rough timer to update the Health HUD every 250 ms. From
|
||||
// my tests a large health pack will fully heal a player from 10 health in
|
||||
// 36 iterations (ie. 9 seconds). If either the scheduling time, the repair
|
||||
// amount, or the repair rate is changed then the healthTimer counter should
|
||||
// be changed also.
|
||||
|
||||
if (%obj.healthTimer < 40) // 40 = 10 seconds at 1 iteration per 250 ms.
|
||||
{
|
||||
%obj.UpdateHealth();
|
||||
%this.schedule(250, doHealthUpdate, %obj);
|
||||
%obj.healthTimer++;
|
||||
}
|
||||
else
|
||||
%obj.healthTimer = 0;
|
||||
}
|
||||
|
||||
function ShapeBase::tossPatch(%this)
|
||||
{
|
||||
//error("ShapeBase::tossPatch(" SPC %this.client.nameBase SPC ")");
|
||||
if(!isObject(%this))
|
||||
return;
|
||||
|
||||
%item = ItemData::createItem(HealthKitPatch);
|
||||
%item.sourceObject = %this;
|
||||
%item.static = false;
|
||||
MissionCleanup.add(%item);
|
||||
|
||||
%vec = (-1.0 + getRandom() * 2.0) SPC (-1.0 + getRandom() * 2.0) SPC getRandom();
|
||||
%vec = vectorScale(%vec, 10);
|
||||
%eye = %this.getEyeVector();
|
||||
%dot = vectorDot("0 0 1", %eye);
|
||||
if (%dot < 0)
|
||||
%dot = -%dot;
|
||||
%vec = vectorAdd(%vec, vectorScale("0 0 8", 1 - %dot));
|
||||
%vec = vectorAdd(%vec, %this.getVelocity());
|
||||
%pos = getBoxCenter(%this.getWorldBox());
|
||||
|
||||
%item.setTransform(%pos);
|
||||
%item.applyImpulse(%pos, %vec);
|
||||
%item.setCollisionTimeout(%this);
|
||||
//serverPlay3D(%item.getDataBlock().throwSound, %item.getTransform());
|
||||
%item.schedulePop();
|
||||
|
||||
return %item;
|
||||
}
|
||||
96
Templates/Full/game/scripts/server/init.cs
Normal file
96
Templates/Full/game/scripts/server/init.cs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Variables used by server scripts & code. The ones marked with (c)
|
||||
// are accessed from code. Variables preceeded by Pref:: are server
|
||||
// preferences and stored automatically in the ServerPrefs.cs file
|
||||
// in between server sessions.
|
||||
//
|
||||
// (c) Server::ServerType {SinglePlayer, MultiPlayer}
|
||||
// (c) Server::GameType Unique game name
|
||||
// (c) Server::Dedicated Bool
|
||||
// ( ) Server::MissionFile Mission .mis file name
|
||||
// (c) Server::MissionName DisplayName from .mis file
|
||||
// (c) Server::MissionType Not used
|
||||
// (c) Server::PlayerCount Current player count
|
||||
// (c) Server::GuidList Player GUID (record list?)
|
||||
// (c) Server::Status Current server status
|
||||
//
|
||||
// (c) Pref::Server::Name Server Name
|
||||
// (c) Pref::Server::Password Password for client connections
|
||||
// ( ) Pref::Server::AdminPassword Password for client admins
|
||||
// (c) Pref::Server::Info Server description
|
||||
// (c) Pref::Server::MaxPlayers Max allowed players
|
||||
// (c) Pref::Server::RegionMask Registers this mask with master server
|
||||
// ( ) Pref::Server::BanTime Duration of a player ban
|
||||
// ( ) Pref::Server::KickBanTime Duration of a player kick & ban
|
||||
// ( ) Pref::Server::MaxChatLen Max chat message len
|
||||
// ( ) Pref::Server::FloodProtectionEnabled Bool
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function initServer()
|
||||
{
|
||||
echo("\n--------- Initializing " @ $appName @ ": Server Scripts ---------");
|
||||
|
||||
// Server::Status is returned in the Game Info Query and represents the
|
||||
// current status of the server. This string sould be very short.
|
||||
$Server::Status = "Unknown";
|
||||
|
||||
// Turn on testing/debug script functions
|
||||
$Server::TestCheats = false;
|
||||
|
||||
// Specify where the mission files are.
|
||||
$Server::MissionFileSpec = "levels/*.mis";
|
||||
|
||||
// The common module provides the basic server functionality
|
||||
initBaseServer();
|
||||
|
||||
// Load up game server support scripts
|
||||
exec("./commands.cs");
|
||||
exec("./game.cs");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function initDedicated()
|
||||
{
|
||||
enableWinConsole(true);
|
||||
echo("\n--------- Starting Dedicated Server ---------");
|
||||
|
||||
// Make sure this variable reflects the correct state.
|
||||
$Server::Dedicated = true;
|
||||
|
||||
// The server isn't started unless a mission has been specified.
|
||||
if ($missionArg !$= "") {
|
||||
createServer("MultiPlayer", $missionArg);
|
||||
}
|
||||
else
|
||||
echo("No mission specified (use -mission filename)");
|
||||
}
|
||||
|
||||
312
Templates/Full/game/scripts/server/inventory.cs
Normal file
312
Templates/Full/game/scripts/server/inventory.cs
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// This inventory system is totally scripted, no C++ code involved.
|
||||
// It uses object datablock names to track inventory and is generally
|
||||
// object type, or class, agnostic. In other words, it will inventory
|
||||
// any kind of ShapeBase object, though the throw method does assume
|
||||
// that the objects are small enough to throw :)
|
||||
//
|
||||
// For a ShapeBase object to support inventory, it must have an array
|
||||
// of inventory max values:
|
||||
// %this.maxInv[GunAmmo] = 100;
|
||||
// %this.maxInv[SpeedGun] = 1;
|
||||
// where the names "SpeedGun" and "GunAmmo" are datablocks.
|
||||
//
|
||||
// For objects to be inventoriable, they must provide a set of inventory
|
||||
// callback methods, mainly:
|
||||
// onUse
|
||||
// onThrow
|
||||
// onPickup
|
||||
//
|
||||
// Example methods are given further down. The item.cs file also contains
|
||||
// example inventory items.
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Inventory server commands
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function serverCmdUse(%client, %data)
|
||||
{
|
||||
%client.getControlObject().use(%data);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ShapeBase inventory support
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function ShapeBase::use(%this, %data)
|
||||
{
|
||||
// Use an object in the inventory.
|
||||
|
||||
// Need to prevent weapon changing when zooming, but only shapes
|
||||
// that have a connection.
|
||||
%conn = %this.getControllingClient();
|
||||
if (%conn)
|
||||
{
|
||||
%defaultFov = %conn.getControlCameraDefaultFov();
|
||||
%fov = %conn.getControlCameraFov();
|
||||
if (%fov != %defaultFov)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (%this.getInventory(%data) > 0)
|
||||
return %data.onUse(%this);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function ShapeBase::throw(%this, %data, %amount)
|
||||
{
|
||||
// Throw objects from inventory. The onThrow method is
|
||||
// responsible for decrementing the inventory.
|
||||
|
||||
if (%this.getInventory(%data) > 0)
|
||||
{
|
||||
%obj = %data.onThrow(%this, %amount);
|
||||
if (%obj)
|
||||
{
|
||||
%this.throwObject(%obj);
|
||||
serverPlay3D(ThrowSnd, %this.getTransform());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function ShapeBase::pickup(%this, %obj, %amount)
|
||||
{
|
||||
// This method is called to pickup an object and add it to the inventory.
|
||||
// The datablock onPickup method is actually responsible for doing all the
|
||||
// work, including incrementing the inventory.
|
||||
|
||||
%data = %obj.getDatablock();
|
||||
|
||||
// Try and pickup the max if no value was specified
|
||||
if (%amount $= "")
|
||||
%amount = %this.maxInventory(%data) - %this.getInventory(%data);
|
||||
|
||||
// The datablock does the work...
|
||||
if (%amount < 0)
|
||||
%amount = 0;
|
||||
if (%amount)
|
||||
return %data.onPickup(%obj, %this, %amount);
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function ShapeBase::hasInventory(%this, %data)
|
||||
{
|
||||
return (%this.inv[%data] > 0);
|
||||
}
|
||||
|
||||
function ShapeBase::hasAmmo(%this, %weapon)
|
||||
{
|
||||
if (%weapon.image.ammo $= "")
|
||||
return(true);
|
||||
else
|
||||
return(%this.getInventory(%weapon.image.ammo) > 0);
|
||||
}
|
||||
|
||||
function ShapeBase::maxInventory(%this, %data)
|
||||
{
|
||||
if (%data.isField("clip"))
|
||||
{
|
||||
// Use the clip system which uses the maxInventory
|
||||
// field on the ammo itself.
|
||||
return %data.maxInventory;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the ammo pool system which uses the maxInv[]
|
||||
// array on the object's datablock.
|
||||
// If there is no limit defined, we assume 0
|
||||
return %this.getDatablock().maxInv[%data.getName()];
|
||||
}
|
||||
}
|
||||
|
||||
function ShapeBase::incInventory(%this, %data, %amount)
|
||||
{
|
||||
// Increment the inventory by the given amount. The return value
|
||||
// is the amount actually added, which may be less than the
|
||||
// requested amount due to inventory restrictions.
|
||||
|
||||
%max = %this.maxInventory(%data);
|
||||
%total = %this.inv[%data.getName()];
|
||||
if (%total < %max)
|
||||
{
|
||||
if (%total + %amount > %max)
|
||||
%amount = %max - %total;
|
||||
%this.setInventory(%data, %total + %amount);
|
||||
return %amount;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function ShapeBase::decInventory(%this, %data, %amount)
|
||||
{
|
||||
// Decrement the inventory by the given amount. The return value
|
||||
// is the amount actually removed.
|
||||
|
||||
%total = %this.inv[%data.getName()];
|
||||
if (%total > 0)
|
||||
{
|
||||
if (%total < %amount)
|
||||
%amount = %total;
|
||||
%this.setInventory(%data, %total - %amount);
|
||||
return %amount;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function ShapeBase::getInventory(%this, %data)
|
||||
{
|
||||
// Return the current inventory amount
|
||||
return %this.inv[%data.getName()];
|
||||
}
|
||||
|
||||
function ShapeBase::setInventory(%this, %data, %value)
|
||||
{
|
||||
// Set the inventory amount for this datablock and invoke inventory
|
||||
// callbacks. All changes to inventory go through this single method.
|
||||
|
||||
// Impose inventory limits
|
||||
if (%value < 0)
|
||||
%value = 0;
|
||||
else
|
||||
{
|
||||
%max = %this.maxInventory(%data);
|
||||
if (%value > %max)
|
||||
%value = %max;
|
||||
}
|
||||
|
||||
// Set the value and invoke object callbacks
|
||||
%name = %data.getName();
|
||||
if (%this.inv[%name] != %value)
|
||||
{
|
||||
%this.inv[%name] = %value;
|
||||
%data.onInventory(%this, %value);
|
||||
%this.getDataBlock().onInventory(%data, %value);
|
||||
}
|
||||
return %value;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function ShapeBase::clearInventory(%this)
|
||||
{
|
||||
// To be filled in...
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function ShapeBase::throwObject(%this, %obj)
|
||||
{
|
||||
// Throw the given object in the direction the shape is looking.
|
||||
// The force value is hardcoded according to the current default
|
||||
// object mass and mission gravity (20m/s^2).
|
||||
|
||||
%throwForce = %this.getDataBlock().throwForce;
|
||||
if (!%throwForce)
|
||||
%throwForce = 20;
|
||||
|
||||
// Start with the shape's eye vector...
|
||||
%eye = %this.getEyeVector();
|
||||
%vec = vectorScale(%eye, %throwForce);
|
||||
|
||||
// Add a vertical component to give the object a better arc
|
||||
%verticalForce = %throwForce / 2;
|
||||
%dot = vectorDot("0 0 1", %eye);
|
||||
if (%dot < 0)
|
||||
%dot = -%dot;
|
||||
%vec = vectorAdd(%vec, vectorScale("0 0 "@%verticalForce, 1 - %dot));
|
||||
|
||||
// Add the shape's velocity
|
||||
%vec = vectorAdd(%vec, %this.getVelocity());
|
||||
|
||||
// Set the object's position and initial velocity
|
||||
%pos = getBoxCenter(%this.getWorldBox());
|
||||
%obj.setTransform(%pos);
|
||||
%obj.applyImpulse(%pos, %vec);
|
||||
|
||||
// Since the object is thrown from the center of the shape,
|
||||
// the object needs to avoid colliding with it's thrower.
|
||||
%obj.setCollisionTimeout(%this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Callback hooks invoked by the inventory system
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ShapeBase object callbacks invoked by the inventory system
|
||||
|
||||
function ShapeBase::onInventory(%this, %data, %value)
|
||||
{
|
||||
// Invoked on ShapeBase objects whenever their inventory changes
|
||||
// for the given datablock.
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ShapeBase datablock callback invoked by the inventory system.
|
||||
|
||||
function ShapeBaseData::onUse(%this, %user)
|
||||
{
|
||||
// Invoked when the object uses this datablock, should return
|
||||
// true if the item was used.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function ShapeBaseData::onThrow(%this, %user, %amount)
|
||||
{
|
||||
// Invoked when the object is thrown. This method should
|
||||
// construct and return the actual mission object to be
|
||||
// physically thrown. This method is also responsible for
|
||||
// decrementing the user's inventory.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function ShapeBaseData::onPickup(%this, %obj, %user, %amount)
|
||||
{
|
||||
// Invoked when the user attempts to pickup this datablock object.
|
||||
// The %amount argument is the space in the user's inventory for
|
||||
// this type of datablock. This method is responsible for
|
||||
// incrementing the user's inventory is something is addded.
|
||||
// Should return true if something was added to the inventory.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function ShapeBaseData::onInventory(%this, %user, %value)
|
||||
{
|
||||
// Invoked whenever an user's inventory total changes for
|
||||
// this datablock.
|
||||
}
|
||||
151
Templates/Full/game/scripts/server/item.cs
Normal file
151
Templates/Full/game/scripts/server/item.cs
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// These scripts make use of dynamic attribute values on Item datablocks,
|
||||
// these are as follows:
|
||||
//
|
||||
// maxInventory Max inventory per object (100 bullets per box, etc.)
|
||||
// pickupName Name to display when client pickups item
|
||||
//
|
||||
// Item objects can have:
|
||||
//
|
||||
// count The # of inventory items in the object. This
|
||||
// defaults to maxInventory if not set.
|
||||
|
||||
// Respawntime is the amount of time it takes for a static "auto-respawn"
|
||||
// object, such as an ammo box or weapon, to re-appear after it's been
|
||||
// picked up. Any item marked as "static" is automaticlly respawned.
|
||||
$Item::RespawnTime = 30 * 1000;
|
||||
|
||||
// Poptime represents how long dynamic items (those that are thrown or
|
||||
// dropped) will last in the world before being deleted.
|
||||
$Item::PopTime = 30 * 1000;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ItemData base class methods used by all items
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function Item::respawn(%this)
|
||||
{
|
||||
// This method is used to respawn static ammo and weapon items
|
||||
// and is usually called when the item is picked up.
|
||||
// Instant fade...
|
||||
%this.startFade(0, 0, true);
|
||||
%this.setHidden(true);
|
||||
|
||||
// Shedule a reapearance
|
||||
%this.schedule($Item::RespawnTime, "setHidden", false);
|
||||
%this.schedule($Item::RespawnTime + 100, "startFade", 1000, 0, false);
|
||||
}
|
||||
|
||||
function Item::schedulePop(%this)
|
||||
{
|
||||
// This method deletes the object after a default duration. Dynamic
|
||||
// items such as thrown or drop weapons are usually popped to avoid
|
||||
// world clutter.
|
||||
%this.schedule($Item::PopTime - 1000, "startFade", 1000, 0, true);
|
||||
%this.schedule($Item::PopTime, "delete");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Callbacks to hook items into the inventory system
|
||||
|
||||
function ItemData::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 object is given a random z rotation.
|
||||
%obj = new Item()
|
||||
{
|
||||
datablock = %this;
|
||||
rotation = "0 0 1 "@ (getRandom() * 360);
|
||||
count = %amount;
|
||||
};
|
||||
MissionGroup.add(%obj);
|
||||
%obj.schedulePop();
|
||||
return %obj;
|
||||
}
|
||||
|
||||
function ItemData::onPickup(%this, %obj, %user, %amount)
|
||||
{
|
||||
// Add it to the inventory, this currently ignores the request
|
||||
// amount, you get what you get. If the object doesn't have
|
||||
// a count or the datablock doesn't have maxIventory set, the
|
||||
// object cannot be picked up.
|
||||
|
||||
// See if the object has a count
|
||||
%count = %obj.count;
|
||||
if (%count $= "")
|
||||
{
|
||||
// No, so check the datablock
|
||||
%count = %this.count;
|
||||
if (%count $= "")
|
||||
{
|
||||
// No, so attempt to provide the maximum amount
|
||||
if (%this.maxInventory !$= "")
|
||||
{
|
||||
if (!(%count = %this.maxInventory))
|
||||
return;
|
||||
}
|
||||
else
|
||||
%count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
%user.incInventory(%this, %count);
|
||||
|
||||
// Inform the client what they got.
|
||||
if (%user.client)
|
||||
messageClient(%user.client, 'MsgItemPickup', '\c0You picked up %1', %this.pickupName);
|
||||
|
||||
// If the item is a static respawn item, then go ahead and
|
||||
// respawn it, otherwise remove it from the world.
|
||||
// Anything not taken up by inventory is lost.
|
||||
if (%obj.isStatic())
|
||||
%obj.respawn();
|
||||
else
|
||||
%obj.delete();
|
||||
return true;
|
||||
}
|
||||
|
||||
function ItemData::createItem(%data)
|
||||
{
|
||||
%obj = new Item()
|
||||
{
|
||||
dataBlock = %data;
|
||||
static = true;
|
||||
rotate = true;
|
||||
};
|
||||
return %obj;
|
||||
}
|
||||
508
Templates/Full/game/scripts/server/player.cs
Normal file
508
Templates/Full/game/scripts/server/player.cs
Normal file
|
|
@ -0,0 +1,508 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Timeouts for corpse deletion.
|
||||
$CorpseTimeoutValue = 45 * 1000;
|
||||
|
||||
// // Damage Rate for entering Liquid
|
||||
// $DamageLava = 0.01;
|
||||
// $DamageHotLava = 0.01;
|
||||
// $DamageCrustyLava = 0.01;
|
||||
|
||||
// Death Animations
|
||||
$PlayerDeathAnim::TorsoFrontFallForward = 1;
|
||||
$PlayerDeathAnim::TorsoFrontFallBack = 2;
|
||||
$PlayerDeathAnim::TorsoBackFallForward = 3;
|
||||
$PlayerDeathAnim::TorsoLeftSpinDeath = 4;
|
||||
$PlayerDeathAnim::TorsoRightSpinDeath = 5;
|
||||
$PlayerDeathAnim::LegsLeftGimp = 6;
|
||||
$PlayerDeathAnim::LegsRightGimp = 7;
|
||||
$PlayerDeathAnim::TorsoBackFallForward = 8;
|
||||
$PlayerDeathAnim::HeadFrontDirect = 9;
|
||||
$PlayerDeathAnim::HeadBackFallForward = 10;
|
||||
$PlayerDeathAnim::ExplosionBlowBack = 11;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Armor Datablock methods
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
function Armor::onAdd(%this, %obj)
|
||||
{
|
||||
// Vehicle timeout
|
||||
%obj.mountVehicle = true;
|
||||
|
||||
// Default dynamic armor stats
|
||||
%obj.setRechargeRate(%this.rechargeRate);
|
||||
%obj.setRepairRate(0);
|
||||
|
||||
// Set the numerical Health HUD
|
||||
//%obj.updateHealth();
|
||||
|
||||
// Calling updateHealth() must be delayed now... for some reason
|
||||
%obj.schedule(50, "updateHealth");
|
||||
}
|
||||
|
||||
function Armor::onRemove(%this, %obj)
|
||||
{
|
||||
if (%obj.client.player == %obj)
|
||||
%obj.client.player = 0;
|
||||
}
|
||||
|
||||
function Armor::onNewDataBlock(%this, %obj)
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
function Armor::onMount(%this, %obj, %vehicle, %node)
|
||||
{
|
||||
// Node 0 is the pilot's position, we need to dismount his weapon.
|
||||
if (%node == 0)
|
||||
{
|
||||
%obj.setTransform("0 0 0 0 0 1 0");
|
||||
%obj.setActionThread(%vehicle.getDatablock().mountPose[%node], true, true);
|
||||
|
||||
%obj.lastWeapon = %obj.getMountedImage($WeaponSlot);
|
||||
%obj.unmountImage($WeaponSlot);
|
||||
|
||||
%obj.setControlObject(%vehicle);
|
||||
|
||||
if(%obj.getClassName() $= "Player")
|
||||
commandToClient(%obj.client, 'toggleVehicleMap', true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (%vehicle.getDataBlock().mountPose[%node] !$= "")
|
||||
%obj.setActionThread(%vehicle.getDatablock().mountPose[%node]);
|
||||
else
|
||||
%obj.setActionThread("root", true);
|
||||
}
|
||||
}
|
||||
|
||||
function Armor::onUnmount(%this, %obj, %vehicle, %node)
|
||||
{
|
||||
if (%node == 0)
|
||||
{
|
||||
%obj.mountImage(%obj.lastWeapon, $WeaponSlot);
|
||||
%obj.setControlObject("");
|
||||
}
|
||||
}
|
||||
|
||||
function Armor::doDismount(%this, %obj, %forced)
|
||||
{
|
||||
//echo("\c4Armor::doDismount(" @ %this @", "@ %obj.client.nameBase @", "@ %forced @")");
|
||||
|
||||
// This function is called by player.cc when the jump trigger
|
||||
// is true while mounted
|
||||
%vehicle = %obj.mVehicle;
|
||||
if (!%obj.isMounted() || !isObject(%vehicle))
|
||||
return;
|
||||
|
||||
// Vehicle must be at rest!
|
||||
if ((VectorLen(%vehicle.getVelocity()) <= %vehicle.getDataBlock().maxDismountSpeed ) || %forced)
|
||||
{
|
||||
// Position above dismount point
|
||||
%pos = getWords(%obj.getTransform(), 0, 2);
|
||||
%rot = getWords(%obj.getTransform(), 3, 6);
|
||||
%oldPos = %pos;
|
||||
%vec[0] = " -1 0 0";
|
||||
%vec[1] = " 0 0 1";
|
||||
%vec[2] = " 0 0 -1";
|
||||
%vec[3] = " 1 0 0";
|
||||
%vec[4] = "0 -1 0";
|
||||
%impulseVec = "0 0 0";
|
||||
%vec[0] = MatrixMulVector(%obj.getTransform(), %vec[0]);
|
||||
|
||||
// Make sure the point is valid
|
||||
%pos = "0 0 0";
|
||||
%numAttempts = 5;
|
||||
%success = -1;
|
||||
for (%i = 0; %i < %numAttempts; %i++)
|
||||
{
|
||||
%pos = VectorAdd(%oldPos, VectorScale(%vec[%i], 3));
|
||||
if (%obj.checkDismountPoint(%oldPos, %pos))
|
||||
{
|
||||
%success = %i;
|
||||
%impulseVec = %vec[%i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (%forced && %success == -1)
|
||||
%pos = %oldPos;
|
||||
|
||||
%obj.mountVehicle = false;
|
||||
%obj.schedule(4000, "mountVehicles", true);
|
||||
|
||||
// Position above dismount point
|
||||
%obj.unmount();
|
||||
%obj.setTransform(%pos SPC %rot);//%obj.setTransform(%pos);
|
||||
//%obj.playAudio(0, UnmountVehicleSound);
|
||||
%obj.applyImpulse(%pos, VectorScale(%impulseVec, %obj.getDataBlock().mass));
|
||||
|
||||
// Set player velocity when ejecting
|
||||
%vel = %obj.getVelocity();
|
||||
%vec = vectorDot( %vel, vectorNormalize(%vel));
|
||||
if(%vec > 50)
|
||||
{
|
||||
%scale = 50 / %vec;
|
||||
%obj.setVelocity(VectorScale(%vel, %scale));
|
||||
}
|
||||
|
||||
//%obj.vehicleTurret = "";
|
||||
}
|
||||
else
|
||||
messageClient(%obj.client, 'msgUnmount', '\c2Cannot exit %1 while moving.', %vehicle.getDataBlock().nameTag);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
function Armor::onCollision(%this, %obj, %col)
|
||||
{
|
||||
if (!isObject(%col) || %obj.getState() $= "Dead")
|
||||
return;
|
||||
|
||||
// Try and pickup all items
|
||||
if (%col.getClassName() $= "Item")
|
||||
{
|
||||
%obj.pickup(%col);
|
||||
return;
|
||||
}
|
||||
|
||||
// Mount vehicles
|
||||
if (%col.getType() & $TypeMasks::GameBaseObjectType)
|
||||
{
|
||||
%db = %col.getDataBlock();
|
||||
if ((%db.getClassName() $= "WheeledVehicleData" ) && %obj.mountVehicle && %obj.getState() $= "Move" && %col.mountable)
|
||||
{
|
||||
// Only mount drivers for now.
|
||||
ServerConnection.setFirstPerson(0);
|
||||
|
||||
// For this specific example, only one person can fit
|
||||
// into a vehicle
|
||||
%mount = %col.getMountNodeObject(0);
|
||||
if(%mount)
|
||||
return;
|
||||
|
||||
// For this specific FPS Example, always mount the player
|
||||
// to node 0
|
||||
%node = 0;
|
||||
%col.mountObject(%obj, %node);
|
||||
%obj.mVehicle = %col;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Armor::onImpact(%this, %obj, %collidedObject, %vec, %vecLen)
|
||||
{
|
||||
%obj.damage(0, VectorAdd(%obj.getPosition(), %vec), %vecLen * %this.speedDamageScale, "Impact");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
function Armor::damage(%this, %obj, %sourceObject, %position, %damage, %damageType)
|
||||
{
|
||||
if (!isObject(%obj) || %obj.getState() $= "Dead" || !%damage)
|
||||
return;
|
||||
|
||||
%obj.applyDamage(%damage);
|
||||
|
||||
%location = "Body";
|
||||
|
||||
// Update the numerical Health HUD
|
||||
%obj.updateHealth();
|
||||
|
||||
// Deal with client callbacks here because we don't have this
|
||||
// information in the onDamage or onDisable methods
|
||||
%client = %obj.client;
|
||||
%sourceClient = %sourceObject ? %sourceObject.client : 0;
|
||||
|
||||
if (isObject(%client))
|
||||
{
|
||||
// Determine damage direction
|
||||
if (%damageType !$= "Suicide")
|
||||
%obj.setDamageDirection(%sourceObject, %position);
|
||||
|
||||
if (%obj.getState() $= "Dead")
|
||||
%client.onDeath(%sourceObject, %sourceClient, %damageType, %location);
|
||||
}
|
||||
}
|
||||
|
||||
function Armor::onDamage(%this, %obj, %delta)
|
||||
{
|
||||
// This method is invoked by the ShapeBase code whenever the
|
||||
// object's damage level changes.
|
||||
if (%delta > 0 && %obj.getState() !$= "Dead")
|
||||
{
|
||||
// Apply a damage flash
|
||||
%obj.setDamageFlash(1);
|
||||
|
||||
// If the pain is excessive, let's hear about it.
|
||||
if (%delta > 10)
|
||||
%obj.playPain();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// The player object sets the "disabled" state when damage exceeds it's
|
||||
// maxDamage value. This is method is invoked by ShapeBase state mangement code.
|
||||
|
||||
// If we want to deal with the damage information that actually caused this
|
||||
// death, then we would have to move this code into the script "damage" method.
|
||||
|
||||
function Armor::onDisabled(%this, %obj, %state)
|
||||
{
|
||||
// Release the main weapon trigger
|
||||
%obj.setImageTrigger(0, false);
|
||||
|
||||
// Toss current mounted weapon and ammo if any
|
||||
%item = %obj.getMountedImage($WeaponSlot).item;
|
||||
if (isObject(%item))
|
||||
{
|
||||
%amount = %obj.getInventory(%item.image.ammo);
|
||||
|
||||
if (!%item.image.clip)
|
||||
warn("No clip exists to throw for item ", %item);
|
||||
if(%amount)
|
||||
%obj.throw(%item.image.clip, 1);
|
||||
}
|
||||
|
||||
// Toss out a health patch
|
||||
%obj.tossPatch();
|
||||
|
||||
%obj.playDeathCry();
|
||||
%obj.playDeathAnimation();
|
||||
//%obj.setDamageFlash(0.75);
|
||||
|
||||
// Disable any vehicle map
|
||||
commandToClient(%obj.client, 'toggleVehicleMap', false);
|
||||
|
||||
// Schedule corpse removal. Just keeping the place clean.
|
||||
%obj.schedule($CorpseTimeoutValue - 1000, "startFade", 1000, 0, true);
|
||||
%obj.schedule($CorpseTimeoutValue, "delete");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function Armor::onLeaveMissionArea(%this, %obj)
|
||||
{
|
||||
//echo("\c4Leaving Mission Area at POS:"@ %obj.getPosition());
|
||||
|
||||
// Inform the client
|
||||
%obj.client.onLeaveMissionArea();
|
||||
|
||||
// Damage over time and kill the coward!
|
||||
//%obj.setDamageDt(0.2, "MissionAreaDamage");
|
||||
}
|
||||
|
||||
function Armor::onEnterMissionArea(%this, %obj)
|
||||
{
|
||||
//echo("\c4Entering Mission Area at POS:"@ %obj.getPosition());
|
||||
|
||||
// Inform the client
|
||||
%obj.client.onEnterMissionArea();
|
||||
|
||||
// Stop the punishment
|
||||
//%obj.clearDamageDt();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function Armor::onEnterLiquid(%this, %obj, %coverage, %type)
|
||||
{
|
||||
//echo("\c4this:"@ %this @" object:"@ %obj @" just entered water of type:"@ %type @" for "@ %coverage @"coverage");
|
||||
}
|
||||
|
||||
function Armor::onLeaveLiquid(%this, %obj, %type)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function Armor::onTrigger(%this, %obj, %triggerNum, %val)
|
||||
{
|
||||
// This method is invoked when the player receives a trigger move event.
|
||||
// The player automatically triggers slot 0 and slot one off of triggers #
|
||||
// 0 & 1. Trigger # 2 is also used as the jump key.
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function Armor::onPoseChange(%this, %obj, %oldPose, %newPose)
|
||||
{
|
||||
// Set the script anim prefix to be that of the current pose
|
||||
%obj.setImageScriptAnimPrefix( $WeaponSlot, addTaggedString(%newPose) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function Armor::onStartSprintMotion(%this, %obj)
|
||||
{
|
||||
%obj.setImageGenericTrigger($WeaponSlot, 0, true);
|
||||
}
|
||||
|
||||
function Armor::onStopSprintMotion(%this, %obj)
|
||||
{
|
||||
%obj.setImageGenericTrigger($WeaponSlot, 0, false);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Player methods
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
function Player::kill(%this, %damageType)
|
||||
{
|
||||
%this.damage(0, %this.getPosition(), 10000, %damageType);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
function Player::mountVehicles(%this, %bool)
|
||||
{
|
||||
// If set to false, this variable disables vehicle mounting.
|
||||
%this.mountVehicle = %bool;
|
||||
}
|
||||
|
||||
function Player::isPilot(%this)
|
||||
{
|
||||
%vehicle = %this.getObjectMount();
|
||||
// There are two "if" statements to avoid a script warning.
|
||||
if (%vehicle)
|
||||
if (%vehicle.getMountNodeObject(0) == %this)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
function Player::playDeathAnimation(%this)
|
||||
{
|
||||
%numDeathAnimations = %this.getNumDeathAnimations();
|
||||
if ( %numDeathAnimations > 0 )
|
||||
{
|
||||
if (isObject(%this.client))
|
||||
{
|
||||
if (%this.client.deathIdx++ > %numDeathAnimations)
|
||||
%this.client.deathIdx = 1;
|
||||
%this.setActionThread("Death" @ %this.client.deathIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
%rand = getRandom(1, %numDeathAnimations);
|
||||
%this.setActionThread("Death" @ %rand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Player::playCelAnimation(%this, %anim)
|
||||
{
|
||||
if (%this.getState() !$= "Dead")
|
||||
%this.setActionThread("cel"@%anim);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
function Player::playDeathCry(%this)
|
||||
{
|
||||
%this.playAudio(0, DeathCrySound);
|
||||
}
|
||||
|
||||
function Player::playPain(%this)
|
||||
{
|
||||
%this.playAudio(0, PainCrySound);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Numerical Health Counter
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function Player::updateHealth(%player)
|
||||
{
|
||||
//echo("\c4Player::updateHealth() -> Player Health changed, updating HUD!");
|
||||
|
||||
// Calcualte player health
|
||||
%maxDamage = %player.getDatablock().maxDamage;
|
||||
%damageLevel = %player.getDamageLevel();
|
||||
%curHealth = %maxDamage - %damageLevel;
|
||||
%curHealth = mceil(%curHealth);
|
||||
|
||||
// Send the player object's current health level to the client, where it
|
||||
// will Update the numericalHealth HUD.
|
||||
commandToClient(%player.client, 'setNumericalHealthHUD', %curHealth);
|
||||
}
|
||||
|
||||
function Player::setDamageDirection(%player, %sourceObject, %damagePos)
|
||||
{
|
||||
if (isObject(%sourceObject))
|
||||
{
|
||||
if (%sourceObject.isField(initialPosition))
|
||||
{
|
||||
// Projectiles have this field set to the muzzle point of
|
||||
// the firing weapon at the time the projectile was created.
|
||||
// This gives a damage direction towards the firing player,
|
||||
// turret, vehicle, etc. Bullets and weapon fired grenades
|
||||
// are examples of projectiles.
|
||||
%damagePos = %sourceObject.initialPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Other objects that cause damage, such as mines, use their own
|
||||
// location as the damage position. This gives a damage direction
|
||||
// towards the explosive origin rather than the person that lay the
|
||||
// explosives.
|
||||
%damagePos = %sourceObject.getPosition();
|
||||
}
|
||||
}
|
||||
|
||||
// Rotate damage vector into object space
|
||||
%damageVec = VectorSub(%damagePos, %player.getWorldBoxCenter());
|
||||
%damageVec = VectorNormalize(%damageVec);
|
||||
%damageVec = MatrixMulVector(%player.client.getCameraObject().getInverseTransform(), %damageVec);
|
||||
|
||||
// Determine largest component of damage vector to get direction
|
||||
%vecComponents = -%damageVec.x SPC %damageVec.x SPC -%damageVec.y SPC %damageVec.y SPC -%damageVec.z SPC %damageVec.z;
|
||||
%vecDirections = "Left" SPC "Right" SPC "Bottom" SPC "Front" SPC "Bottom" SPC "Top";
|
||||
|
||||
%max = -1;
|
||||
for (%i = 0; %i < 6; %i++)
|
||||
{
|
||||
%value = getWord(%vecComponents, %i);
|
||||
if (%value > %max)
|
||||
{
|
||||
%max = %value;
|
||||
%damageDir = getWord(%vecDirections, %i);
|
||||
}
|
||||
}
|
||||
commandToClient(%player.client, 'setDamageDirection', %damageDir);
|
||||
}
|
||||
|
||||
function Player::use(%player, %data)
|
||||
{
|
||||
// No mounting/using weapons when you're driving!
|
||||
if (%player.isPilot())
|
||||
return(false);
|
||||
|
||||
Parent::use(%player, %data);
|
||||
}
|
||||
46
Templates/Full/game/scripts/server/projectile.cs
Normal file
46
Templates/Full/game/scripts/server/projectile.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// "Universal" script methods for projectile damage handling. You can easily
|
||||
// override these support functions with an equivalent namespace method if your
|
||||
// weapon needs a unique solution for applying damage.
|
||||
|
||||
function ProjectileData::onCollision(%data, %proj, %col, %fade, %pos, %normal)
|
||||
{
|
||||
//echo("ProjectileData::onCollision("@%data.getName()@", "@%proj@", "@%col.getClassName()@", "@%fade@", "@%pos@", "@%normal@")");
|
||||
|
||||
// Apply damage to the object all shape base objects
|
||||
if (%data.directDamage > 0)
|
||||
{
|
||||
if (%col.getType() & ($TypeMasks::ShapeBaseObjectType))
|
||||
%col.damage(%proj, %pos, %data.directDamage, %data.damageType);
|
||||
}
|
||||
}
|
||||
|
||||
function ProjectileData::onExplode(%data, %proj, %position, %mod)
|
||||
{
|
||||
//echo("ProjectileData::onExplode("@%data.getName()@", "@%proj@", "@%position@", "@%mod@")");
|
||||
|
||||
// Damage objects within the projectiles damage radius
|
||||
if (%data.damageRadius > 0)
|
||||
radiusDamage(%proj, %position, %data.damageRadius, %data.radiusDamage, %data.damageType, %data.areaImpulse);
|
||||
}
|
||||
118
Templates/Full/game/scripts/server/proximityMine.cs
Normal file
118
Templates/Full/game/scripts/server/proximityMine.cs
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function ProximityMineData::onThrow( %this, %user, %amount )
|
||||
{
|
||||
// Remove the object from the inventory
|
||||
%user.decInventory( %this, 1 );
|
||||
|
||||
// Construct the actual object in the world, and add it to
|
||||
// the mission group so its cleaned up when the mission is
|
||||
// done. The object is given a random z rotation.
|
||||
%obj = new ProximityMine()
|
||||
{
|
||||
datablock = %this;
|
||||
sourceObject = %user;
|
||||
rotation = "0 0 1 "@ (getRandom() * 360);
|
||||
static = false;
|
||||
client = %user.client;
|
||||
};
|
||||
MissionCleanup.add(%obj);
|
||||
return %obj;
|
||||
}
|
||||
|
||||
|
||||
function ProximityMineData::onTriggered( %this, %obj, %target )
|
||||
{
|
||||
//echo(%this.name SPC "triggered by " @ %target.getClassName());
|
||||
}
|
||||
|
||||
function ProximityMineData::onExplode( %this, %obj, %position )
|
||||
{
|
||||
// Damage objects within the mine's damage radius
|
||||
if ( %this.damageRadius > 0 )
|
||||
radiusDamage( %obj, %position, %this.damageRadius, %this.radiusDamage, %this.damageType, %this.areaImpulse );
|
||||
}
|
||||
|
||||
function ProximityMineData::damage( %this, %obj, %position, %source, %amount, %damageType )
|
||||
{
|
||||
// Explode if any damage is applied to the mine
|
||||
%obj.schedule(50 + getRandom(50), explode);
|
||||
}
|
||||
|
||||
// Customized kill message for deaths caused by proximity mines
|
||||
function sendMsgClientKilled_MineDamage( %msgType, %client, %sourceClient, %damLoc )
|
||||
{
|
||||
if ( %sourceClient $= "" ) // editor placed mine
|
||||
messageAll( %msgType, '%1 was blown up!', %client.playerName );
|
||||
else if ( %sourceClient == %client ) // own mine
|
||||
messageAll( %msgType, '%1 stepped on his own mine!', %client.playerName );
|
||||
else // enemy placed mine
|
||||
messageAll( %msgType, '%1 was blown up by %2!', %client.playerName, %sourceClient.playerName );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Player deployable proximity mine
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Cannot use the Weapon class for ProximityMineData datablocks as it is already tied
|
||||
// to ItemData.
|
||||
|
||||
function ProxMine::onUse(%this, %obj)
|
||||
{
|
||||
// Act like a weapon on use
|
||||
Weapon::onUse( %this, %obj );
|
||||
}
|
||||
|
||||
function ProxMine::onPickup( %this, %obj, %shape, %amount )
|
||||
{
|
||||
// Act like a weapon on pickup
|
||||
Weapon::onPickup( %this, %obj, %shape, %amount );
|
||||
}
|
||||
|
||||
function ProxMine::onInventory( %this, %obj, %amount )
|
||||
{
|
||||
%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 ProxMineImage::onMount( %this, %obj, %slot )
|
||||
{
|
||||
// The mine doesn't use ammo from a player's perspective.
|
||||
%obj.setImageAmmo( %slot, true );
|
||||
%numMines = %obj.getInventory(%this.item);
|
||||
%obj.client.RefreshWeaponHud( 1, %this.item.previewImage, %this.item.reticle, %this.item.zoomReticle, %numMines );
|
||||
}
|
||||
|
||||
function ProxMineImage::onUnmount( %this, %obj, %slot )
|
||||
{
|
||||
%obj.client.RefreshWeaponHud( 0, "", "" );
|
||||
}
|
||||
|
||||
function ProxMineImage::onFire( %this, %obj, %slot )
|
||||
{
|
||||
// To fire a deployable mine is to throw it
|
||||
%obj.throw( %this.item );
|
||||
}
|
||||
72
Templates/Full/game/scripts/server/radiusDamage.cs
Normal file
72
Templates/Full/game/scripts/server/radiusDamage.cs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Support function which applies damage to objects within the radius of
|
||||
// some effect, usually an explosion. This function will also optionally
|
||||
// apply an impulse to each object.
|
||||
|
||||
function radiusDamage(%sourceObject, %position, %radius, %damage, %damageType, %impulse)
|
||||
{
|
||||
// Use the container system to iterate through all the objects
|
||||
// within our explosion radius. We'll apply damage to all ShapeBase
|
||||
// objects.
|
||||
InitContainerRadiusSearch(%position, %radius, $TypeMasks::ShapeBaseObjectType);
|
||||
|
||||
%halfRadius = %radius / 2;
|
||||
while ((%targetObject = containerSearchNext()) != 0)
|
||||
{
|
||||
// Calculate how much exposure the current object has to
|
||||
// the explosive force. The object types listed are objects
|
||||
// that will block an explosion. If the object is totally blocked,
|
||||
// then no damage is applied.
|
||||
%coverage = calcExplosionCoverage(%position, %targetObject,
|
||||
$TypeMasks::InteriorObjectType |
|
||||
$TypeMasks::TerrainObjectType |
|
||||
$TypeMasks::ForceFieldObjectType |
|
||||
$TypeMasks::StaticShapeObjectType |
|
||||
$TypeMasks::VehicleObjectType);
|
||||
if (%coverage == 0)
|
||||
continue;
|
||||
|
||||
// Radius distance subtracts out the length of smallest bounding
|
||||
// box axis to return an appriximate distance to the edge of the
|
||||
// object's bounds, as opposed to the distance to it's center.
|
||||
%dist = containerSearchCurrRadiusDist();
|
||||
|
||||
// Calculate a distance scale for the damage and the impulse.
|
||||
// Full damage is applied to anything less than half the radius away,
|
||||
// linear scale from there.
|
||||
%distScale = (%dist < %halfRadius)? 1.0 : 1.0 - ((%dist - %halfRadius) / %halfRadius);
|
||||
|
||||
// Apply the damage
|
||||
%targetObject.damage(%sourceObject, %position, %damage * %coverage * %distScale, %damageType);
|
||||
|
||||
// Apply the impulse
|
||||
if (%impulse)
|
||||
{
|
||||
%impulseVec = VectorSub(%targetObject.getWorldBoxCenter(), %position);
|
||||
%impulseVec = VectorNormalize(%impulseVec);
|
||||
%impulseVec = VectorScale(%impulseVec, %impulse * %distScale);
|
||||
%targetObject.applyImpulse(%position, %impulseVec);
|
||||
}
|
||||
}
|
||||
}
|
||||
99
Templates/Full/game/scripts/server/rocketLauncher.cs
Normal file
99
Templates/Full/game/scripts/server/rocketLauncher.cs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Support methods used to track our number of ready shells for a charged shot.
|
||||
// ----------------------------------------------------------------------------
|
||||
function RocketLauncherImage::readyLoad(%this)
|
||||
{
|
||||
//echo("\c4RocketLauncherImage::readyLoad("@ %this.getName()@")");
|
||||
%this.loadCount = 1;
|
||||
//echo("\c4 loadCount = "@ %this.loadCount);
|
||||
}
|
||||
|
||||
function RocketLauncherImage::incLoad(%this)
|
||||
{
|
||||
//echo("\c4RocketLauncherImage::incLoad("@ %this.getName()@")");
|
||||
%this.loadCount++;
|
||||
//echo("\c4 loadCount = "@ %this.loadCount);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// The fire method that does all of the work
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function RocketLauncherImage::onAltFire(%this, %obj, %slot)
|
||||
{
|
||||
//echo("\c4RocketLauncherImage::onFire("@ %this.getName() @", "@ %obj.client.nameBase @", "@ %slot@")");
|
||||
|
||||
//echo("\c4 #in the pipe = "@ %this.loadCount);
|
||||
//echo("");
|
||||
|
||||
// Let's check amount of ammo, if it's less than the loadCount then only
|
||||
// fire the number of shots equal to the ammount of remaining ammo.
|
||||
%currentAmmo = %obj.getInventory(%this.ammo);
|
||||
if(%currentAmmo < %this.loadCount)
|
||||
%this.loadCount = %currentAmmo;
|
||||
|
||||
for(%shotCount = 0; %shotCount < %this.loadCount; %shotCount++)
|
||||
{
|
||||
// Decrement inventory ammo. The image's ammo state is updated
|
||||
// automatically by the ammo inventory hooks.
|
||||
%obj.decInventory(%this.ammo, 1);
|
||||
|
||||
// We fire our weapon using the straight ahead aiming point of the gun
|
||||
//%muzzleVector = %obj.getMuzzleVector(%slot);
|
||||
|
||||
// We'll need to "skew" the projectile a little bit. We start by getting
|
||||
// the straight ahead aiming point of the gun
|
||||
%vec = %obj.getMuzzleVector(%slot);
|
||||
|
||||
// Then we'll create a spread matrix by randomly generating x, y, and z
|
||||
// points in a circle
|
||||
%matrix = "";
|
||||
for(%i = 0; %i < 3; %i++)
|
||||
%matrix = %matrix @ (getRandom() - 0.5) * 2 * 3.1415926 * 0.008 @ " ";
|
||||
%mat = MatrixCreateFromEuler(%matrix);
|
||||
|
||||
// Which we'll use to alter the projectile's initial vector with
|
||||
%muzzleVector = MatrixMulVector(%mat, %vec);
|
||||
|
||||
// Get the player's velocity, we'll then add it to that of the projectile
|
||||
%objectVelocity = %obj.getVelocity();
|
||||
%muzzleVelocity = VectorAdd(
|
||||
VectorScale(%muzzleVector, %this.projectile.muzzleVelocity),
|
||||
VectorScale(%objectVelocity, %this.projectile.velInheritFactor));
|
||||
|
||||
// Create the projectile object
|
||||
%p = new (%this.projectileType)()
|
||||
{
|
||||
dataBlock = %this.projectile;
|
||||
initialVelocity = %muzzleVelocity;
|
||||
initialPosition = %obj.getMuzzlePoint(%slot);
|
||||
sourceObject = %obj;
|
||||
sourceSlot = %slot;
|
||||
client = %obj.client;
|
||||
};
|
||||
MissionCleanup.add(%p);
|
||||
}
|
||||
return %p;
|
||||
}
|
||||
61
Templates/Full/game/scripts/server/scriptExec.cs
Normal file
61
Templates/Full/game/scripts/server/scriptExec.cs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Load up all scripts. This function is called when
|
||||
// a server is constructed.
|
||||
exec("./camera.cs");
|
||||
exec("./triggers.cs");
|
||||
exec("./inventory.cs");
|
||||
exec("./shapeBase.cs");
|
||||
exec("./item.cs");
|
||||
exec("./health.cs");
|
||||
exec("./projectile.cs");
|
||||
exec("./radiusDamage.cs");
|
||||
exec("./teleporter.cs");
|
||||
|
||||
// Load our supporting weapon script, it contains methods used by all weapons.
|
||||
exec("./weapon.cs");
|
||||
|
||||
// Load our weapon scripts
|
||||
// We only need weapon scripts for those weapons that work differently from the
|
||||
// "generic" methods defined in weapon.cs
|
||||
exec("./rocketLauncher.cs");
|
||||
exec("./soldierGun.cs");
|
||||
exec("./grenadeLauncher.cs");
|
||||
exec("./proximityMine.cs");
|
||||
|
||||
// Load our default player script
|
||||
exec("./player.cs");
|
||||
|
||||
// Load our player scripts
|
||||
exec("./aiPlayer.cs");
|
||||
|
||||
exec("./vehicle.cs");
|
||||
exec("./vehicleWheeled.cs");
|
||||
exec("./cheetah.cs");
|
||||
|
||||
// Load turret support scripts
|
||||
exec("./turret.cs");
|
||||
|
||||
// Load our gametypes
|
||||
exec("./gameCore.cs"); // This is the 'core' of the gametype functionality.
|
||||
exec("./gameDM.cs"); // Overrides GameCore with DeathMatch functionality.
|
||||
108
Templates/Full/game/scripts/server/shapeBase.cs
Normal file
108
Templates/Full/game/scripts/server/shapeBase.cs
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// This file contains ShapeBase methods used by all the derived classes
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ShapeBase object
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// A raycast helper function to keep from having to duplicate code everytime
|
||||
// that a raycast is needed.
|
||||
// %this = the object doing the cast, usually a player
|
||||
// %range = range to search
|
||||
// %mask = what to look for
|
||||
|
||||
function ShapeBase::doRaycast(%this, %range, %mask)
|
||||
{
|
||||
// get the eye vector and eye transform of the player
|
||||
%eyeVec = %this.getEyeVector();
|
||||
%eyeTrans = %this.getEyeTransform();
|
||||
|
||||
// extract the position of the player's camera from the eye transform (first 3 words)
|
||||
%eyePos = getWord(%eyeTrans, 0) SPC getWord(%eyeTrans, 1) SPC getWord(%eyeTrans, 2);
|
||||
|
||||
// normalize the eye vector
|
||||
%nEyeVec = VectorNormalize(%eyeVec);
|
||||
|
||||
// scale (lengthen) the normalized eye vector according to the search range
|
||||
%scEyeVec = VectorScale(%nEyeVec, %range);
|
||||
|
||||
// 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, %this);
|
||||
|
||||
return %searchResult;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function ShapeBase::damage(%this, %sourceObject, %position, %damage, %damageType)
|
||||
{
|
||||
// All damage applied by one object to another should go through this method.
|
||||
// This function is provided to allow objects some chance of overriding or
|
||||
// processing damage values and types. As opposed to having weapons call
|
||||
// ShapeBase::applyDamage directly. Damage is redirected to the datablock,
|
||||
// this is standard procedure for many built in callbacks.
|
||||
|
||||
if (isObject(%this))
|
||||
%this.getDataBlock().damage(%this, %sourceObject, %position, %damage, %damageType);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function ShapeBase::setDamageDt(%this, %damageAmount, %damageType)
|
||||
{
|
||||
// This function is used to apply damage over time. The damage is applied
|
||||
// at a fixed rate (50 ms). Damage could be applied over time using the
|
||||
// built in ShapBase C++ repair functions (using a neg. repair), but this
|
||||
// has the advantage of going through the normal script channels.
|
||||
|
||||
if (%this.getState() !$= "Dead")
|
||||
{
|
||||
%this.damage(0, "0 0 0", %damageAmount, %damageType);
|
||||
%this.damageSchedule = %this.schedule(50, "setDamageDt", %damageAmount, %damageType);
|
||||
}
|
||||
else
|
||||
%this.damageSchedule = "";
|
||||
}
|
||||
|
||||
function ShapeBase::clearDamageDt(%this)
|
||||
{
|
||||
if (%this.damageSchedule !$= "")
|
||||
{
|
||||
cancel(%this.damageSchedule);
|
||||
%this.damageSchedule = "";
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ShapeBase datablock
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function ShapeBaseData::damage(%this, %obj, %position, %source, %amount, %damageType)
|
||||
{
|
||||
// Ignore damage by default. This empty method is here to
|
||||
// avoid console warnings.
|
||||
}
|
||||
32
Templates/Full/game/scripts/server/soldierGun.cs
Normal file
32
Templates/Full/game/scripts/server/soldierGun.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function Soldier_gunImage::onMount(%this, %obj, %slot)
|
||||
{
|
||||
// Make it ready
|
||||
Parent::onMount(%this, %obj, %slot);
|
||||
}
|
||||
|
||||
function Soldier_gunImage::onAltFire(%this, %obj, %slot)
|
||||
{
|
||||
echo("Fire Grenade!");
|
||||
}
|
||||
251
Templates/Full/game/scripts/server/teleporter.cs
Normal file
251
Templates/Full/game/scripts/server/teleporter.cs
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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);
|
||||
}
|
||||
48
Templates/Full/game/scripts/server/triggers.cs
Normal file
48
Templates/Full/game/scripts/server/triggers.cs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DefaultTrigger is used by the mission editor. This is also an example
|
||||
// of trigger methods and callbacks.
|
||||
|
||||
function DefaultTrigger::onEnterTrigger(%this,%trigger,%obj)
|
||||
{
|
||||
// This method is called whenever an object enters the %trigger
|
||||
// area, the object is passed as %obj.
|
||||
}
|
||||
|
||||
function DefaultTrigger::onLeaveTrigger(%this,%trigger,%obj)
|
||||
{
|
||||
// This method is called whenever an object leaves the %trigger
|
||||
// area, the object is passed as %obj.
|
||||
}
|
||||
|
||||
function DefaultTrigger::onTickTrigger(%this,%trigger)
|
||||
{
|
||||
// This method is called every tickPerioMS, as long as any
|
||||
// objects intersect the trigger.
|
||||
|
||||
// You can iterate through the objects in the list by using these
|
||||
// methods:
|
||||
// %trigger.getNumObjects();
|
||||
// %trigger.getObject(n);
|
||||
}
|
||||
492
Templates/Full/game/scripts/server/turret.cs
Normal file
492
Templates/Full/game/scripts/server/turret.cs
Normal file
|
|
@ -0,0 +1,492 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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);
|
||||
}
|
||||
130
Templates/Full/game/scripts/server/vehicle.cs
Normal file
130
Templates/Full/game/scripts/server/vehicle.cs
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Parenting is in place for WheeledVehicleData to VehicleData. This should
|
||||
// make it easier for people to simply drop in new (generic) vehicles. All that
|
||||
// the user needs to create is a set of datablocks for the new wheeled vehicle
|
||||
// to use. This means that no (or little) scripting should be necessary.
|
||||
|
||||
// Special, or unique vehicles however will still require some scripting. They
|
||||
// may need to override the onAdd() function in order to mount weapons,
|
||||
// differing tires/springs, etc., almost everything else is taken care of in the
|
||||
// WheeledVehicleData and VehicleData methods. This helps us by not having to
|
||||
// duplicate the same code for every new vehicle.
|
||||
|
||||
// In theory this would work for HoverVehicles and FlyingVehicles also, but
|
||||
// hasn't been tested or fully implemented for those classes -- yet.
|
||||
|
||||
function VehicleData::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);
|
||||
}
|
||||
|
||||
function VehicleData::onRemove(%this, %obj)
|
||||
{
|
||||
//echo("\c4VehicleData::onRemove("@ %this.getName() @", "@ %obj.getClassName() @")");
|
||||
|
||||
// if there are passengers/driver, kick them out
|
||||
for(%i = 0; %i < %obj.getDatablock().numMountPoints; %i++)
|
||||
{
|
||||
if (%obj.getMountNodeObject(%i))
|
||||
{
|
||||
%passenger = %obj.getMountNodeObject(%i);
|
||||
%passenger.getDataBlock().doDismount(%passenger, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Vehicle player mounting and dismounting
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function VehicleData::isMountable(%this, %obj, %val)
|
||||
{
|
||||
%obj.mountable = %val;
|
||||
}
|
||||
|
||||
function VehicleData::mountPlayer(%this, %vehicle, %player)
|
||||
{
|
||||
//echo("\c4VehicleData::mountPlayer("@ %this.getName() @", "@ %vehicle @", "@ %player.client.nameBase @")");
|
||||
|
||||
if (isObject(%vehicle) && %vehicle.getDamageState() !$= "Destroyed")
|
||||
{
|
||||
%player.startFade(1000, 0, true);
|
||||
%this.schedule(1000, "setMountVehicle", %vehicle, %player);
|
||||
%player.schedule(1500, "startFade", 1000, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
function VehicleData::setMountVehicle(%this, %vehicle, %player)
|
||||
{
|
||||
//echo("\c4VehicleData::setMountVehicle("@ %this.getName() @", "@ %vehicle @", "@ %player.client.nameBase @")");
|
||||
|
||||
if (isObject(%vehicle) && %vehicle.getDamageState() !$= "Destroyed")
|
||||
{
|
||||
%node = %this.findEmptySeat(%vehicle, %player);
|
||||
if (%node >= 0)
|
||||
{
|
||||
//echo("\c4Mount Node: "@ %node);
|
||||
%vehicle.mountObject(%player, %node);
|
||||
//%player.playAudio(0, MountVehicleSound);
|
||||
%player.mVehicle = %vehicle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function VehicleData::findEmptySeat(%this, %vehicle, %player)
|
||||
{
|
||||
//echo("\c4This vehicle has "@ %this.numMountPoints @" mount points.");
|
||||
|
||||
for (%i = 0; %i < %this.numMountPoints; %i++)
|
||||
{
|
||||
%node = %vehicle.getMountNodeObject(%i);
|
||||
if (%node == 0)
|
||||
return %i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function VehicleData::switchSeats(%this, %vehicle, %player)
|
||||
{
|
||||
for (%i = 0; %i < %this.numMountPoints; %i++)
|
||||
{
|
||||
%node = %vehicle.getMountNodeObject(%i);
|
||||
if (%node == %player || %node > 0)
|
||||
continue;
|
||||
|
||||
if (%node == 0)
|
||||
return %i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
102
Templates/Full/game/scripts/server/vehicleWheeled.cs
Normal file
102
Templates/Full/game/scripts/server/vehicleWheeled.cs
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// This file contains script methods unique to the WheeledVehicle class. All
|
||||
// other necessary methods are contained in "../server/scripts/vehicle.cs" in
|
||||
// which the "generic" Vehicle class methods that are shared by all vehicles,
|
||||
// (flying, hover, and wheeled) can be found.
|
||||
|
||||
// Parenting is in place for WheeledVehicleData to VehicleData. This should
|
||||
// make it easier for people to simply drop in new (generic) vehicles. All that
|
||||
// the user needs to create is a set of datablocks for the new wheeled vehicle
|
||||
// to use. This means that no (or little) scripting should be necessary.
|
||||
|
||||
function WheeledVehicleData::onAdd(%this, %obj)
|
||||
{
|
||||
Parent::onAdd(%this, %obj);
|
||||
|
||||
// Setup the car with some tires & springs
|
||||
for (%i = %obj.getWheelCount() - 1; %i >= 0; %i--)
|
||||
{
|
||||
%obj.setWheelTire(%i, DefaultCarTire);
|
||||
%obj.setWheelSpring(%i, DefaultCarSpring);
|
||||
%obj.setWheelPowered(%i, false);
|
||||
}
|
||||
|
||||
// Steer with the front tires
|
||||
%obj.setWheelSteering(0, 1);
|
||||
%obj.setWheelSteering(1, 1);
|
||||
|
||||
// Only power the two rear wheels... assuming there are only 4 wheels.
|
||||
%obj.setWheelPowered(2, true);
|
||||
%obj.setWheelPowered(3, true);
|
||||
}
|
||||
|
||||
function WheeledVehicleData::onCollision(%this, %obj, %col, %vec, %speed)
|
||||
{
|
||||
// Collision with other objects, including items
|
||||
}
|
||||
|
||||
// Used to kick the players out of the car that your crosshair is over
|
||||
function serverCmdcarUnmountObj(%client, %obj)
|
||||
{
|
||||
%obj.unmount();
|
||||
%obj.setControlObject(%obj);
|
||||
|
||||
%ejectpos = %obj.getPosition();
|
||||
%ejectpos = VectorAdd(%ejectpos, "0 0 5");
|
||||
%obj.setTransform(%ejectpos);
|
||||
|
||||
%ejectvel = %obj.mVehicle.getVelocity();
|
||||
%ejectvel = VectorAdd(%ejectvel, "0 0 10");
|
||||
%ejectvel = VectorScale(%ejectvel, %obj.getDataBlock().mass);
|
||||
%obj.applyImpulse(%ejectpos, %ejectvel);
|
||||
}
|
||||
|
||||
// Used to flip the car over if it manages to get stuck upside down
|
||||
function serverCmdflipCar(%client)
|
||||
{
|
||||
%car = %client.player.getControlObject();
|
||||
|
||||
if (%car.getClassName() $= "WheeledVehicle")
|
||||
{
|
||||
%carPos = %car.getPosition();
|
||||
%carPos = VectorAdd(%carPos, "0 0 3");
|
||||
|
||||
%car.setTransform(%carPos SPC "0 0 1 0");
|
||||
}
|
||||
}
|
||||
|
||||
function serverCmdsetPlayerControl(%client)
|
||||
{
|
||||
%client.setControlObject(%client.player);
|
||||
}
|
||||
|
||||
function serverCmddismountVehicle(%client)
|
||||
{
|
||||
%car = %client.player.getControlObject();
|
||||
|
||||
%passenger = %car.getMountNodeObject(0);
|
||||
%passenger.getDataBlock().doDismount(%passenger, true);
|
||||
|
||||
%client.setControlObject(%client.player);
|
||||
}
|
||||
643
Templates/Full/game/scripts/server/weapon.cs
Normal file
643
Templates/Full/game/scripts/server/weapon.cs
Normal file
|
|
@ -0,0 +1,643 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// This file contains Weapon and Ammo Class/"namespace" helper methods as well
|
||||
// as hooks into the inventory system. These functions are not attached to a
|
||||
// specific C++ class or datablock, but define a set of methods which are part
|
||||
// of dynamic namespaces "class". The Items include these namespaces into their
|
||||
// scope using the ItemData and ItemImageData "className" variable.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// All ShapeBase images are mounted into one of 8 slots on a shape. This weapon
|
||||
// system assumes all primary weapons are mounted into this specified slot:
|
||||
$WeaponSlot = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Weapon Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function Weapon::onUse(%data, %obj)
|
||||
{
|
||||
// Default behavior for all weapons is to mount it into the object's weapon
|
||||
// slot, which is currently assumed to be slot 0
|
||||
if (%obj.getMountedImage($WeaponSlot) != %data.image.getId())
|
||||
{
|
||||
serverPlay3D(WeaponUseSound, %obj.getTransform());
|
||||
|
||||
%obj.mountImage(%data.image, $WeaponSlot);
|
||||
if (%obj.client)
|
||||
{
|
||||
if (%data.description !$= "")
|
||||
messageClient(%obj.client, 'MsgWeaponUsed', '\c0%1 selected.', %data.description);
|
||||
else
|
||||
messageClient(%obj.client, 'MsgWeaponUsed', '\c0Weapon selected');
|
||||
}
|
||||
|
||||
// If this is a Player class object then allow the weapon to modify allowed poses
|
||||
if (%obj.isInNamespaceHierarchy("Player"))
|
||||
{
|
||||
// Start by allowing everything
|
||||
%obj.allowAllPoses();
|
||||
|
||||
// Now see what isn't allowed by the weapon
|
||||
|
||||
%image = %data.image;
|
||||
|
||||
if (%image.jumpingDisallowed)
|
||||
%obj.allowJumping(false);
|
||||
|
||||
if (%image.jetJumpingDisallowed)
|
||||
%obj.allowJetJumping(false);
|
||||
|
||||
if (%image.sprintDisallowed)
|
||||
%obj.allowSprinting(false);
|
||||
|
||||
if (%image.crouchDisallowed)
|
||||
%obj.allowCrouching(false);
|
||||
|
||||
if (%image.proneDisallowed)
|
||||
%obj.allowProne(false);
|
||||
|
||||
if (%image.swimmingDisallowed)
|
||||
%obj.allowSwimming(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Weapon::onPickup(%this, %obj, %shape, %amount)
|
||||
{
|
||||
// The parent Item method performs the actual pickup.
|
||||
// For player's we automatically use the weapon if the
|
||||
// player does not already have one in hand.
|
||||
if (Parent::onPickup(%this, %obj, %shape, %amount))
|
||||
{
|
||||
serverPlay3D(WeaponPickupSound, %shape.getTransform());
|
||||
if (%shape.getClassName() $= "Player" && %shape.getMountedImage($WeaponSlot) == 0)
|
||||
%shape.use(%this);
|
||||
}
|
||||
}
|
||||
|
||||
function Weapon::onInventory(%this, %obj, %amount)
|
||||
{
|
||||
// Weapon inventory has changed, make sure there are no weapons
|
||||
// of this type mounted if there are none left in inventory.
|
||||
if (!%amount && (%slot = %obj.getMountSlot(%this.image)) != -1)
|
||||
%obj.unmountImage(%slot);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Weapon Image Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function WeaponImage::onMount(%this, %obj, %slot)
|
||||
{
|
||||
// Images assume a false ammo state on load. We need to
|
||||
// set the state according to the current inventory.
|
||||
if(%this.isField("clip"))
|
||||
{
|
||||
// Use the clip system for this weapon. Check if the player already has
|
||||
// some ammo in a clip.
|
||||
if (%obj.getInventory(%this.ammo))
|
||||
{
|
||||
%obj.setImageAmmo(%slot, true);
|
||||
%currentAmmo = %obj.getInventory(%this.ammo);
|
||||
}
|
||||
else if(%obj.getInventory(%this.clip) > 0)
|
||||
{
|
||||
// Fill the weapon up from the first clip
|
||||
%obj.setInventory(%this.ammo, %this.ammo.maxInventory);
|
||||
%obj.setImageAmmo(%slot, true);
|
||||
|
||||
// Add any spare ammo that may be "in the player's pocket"
|
||||
%currentAmmo = %this.ammo.maxInventory;
|
||||
%amountInClips += %obj.getFieldValue( "remaining" @ %this.ammo.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
%currentAmmo = 0 + %obj.getFieldValue( "remaining" @ %this.ammo.getName());
|
||||
}
|
||||
|
||||
%amountInClips = %obj.getInventory(%this.clip);
|
||||
%amountInClips *= %this.ammo.maxInventory;
|
||||
|
||||
if (%obj.client !$= "" && !%obj.isAiControlled)
|
||||
%obj.client.RefreshWeaponHud(%currentAmmo, %this.item.previewImage, %this.item.reticle, %this.item.zoomReticle, %amountInClips);
|
||||
}
|
||||
else if(%this.ammo !$= "")
|
||||
{
|
||||
// Use the ammo pool system for this weapon
|
||||
if (%obj.getInventory(%this.ammo))
|
||||
{
|
||||
%obj.setImageAmmo(%slot, true);
|
||||
%currentAmmo = %obj.getInventory(%this.ammo);
|
||||
}
|
||||
else
|
||||
%currentAmmo = 0;
|
||||
|
||||
if (%obj.client !$= "" && !%obj.isAiControlled)
|
||||
%obj.client.RefreshWeaponHud( 1, %this.item.previewImage, %this.item.reticle, %this.item.zoomReticle, %currentAmmo );
|
||||
}
|
||||
}
|
||||
|
||||
function WeaponImage::onUnmount(%this, %obj, %slot)
|
||||
{
|
||||
if (%obj.client !$= "" && !%obj.isAiControlled)
|
||||
%obj.client.RefreshWeaponHud(0, "", "");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// A "generic" weaponimage onFire handler for most weapons. Can be overridden
|
||||
// with an appropriate namespace method for any weapon that requires a custom
|
||||
// firing solution.
|
||||
|
||||
// projectileSpread is a dynamic property declared in the weaponImage datablock
|
||||
// for those weapons in which bullet skew is desired. Must be greater than 0,
|
||||
// otherwise the projectile goes straight ahead as normal. lower values give
|
||||
// greater accuracy, higher values increase the spread pattern.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function WeaponImage::onFire(%this, %obj, %slot)
|
||||
{
|
||||
//echo("\c4WeaponImage::onFire( "@%this.getName()@", "@%obj.client.nameBase@", "@%slot@" )");
|
||||
|
||||
// Make sure we have valid data
|
||||
if (!isObject(%this.projectile))
|
||||
{
|
||||
error("WeaponImage::onFire() - Invalid projectile datablock");
|
||||
return;
|
||||
}
|
||||
|
||||
// Decrement inventory ammo. The image's ammo state is updated
|
||||
// automatically by the ammo inventory hooks.
|
||||
if ( !%this.infiniteAmmo )
|
||||
%obj.decInventory(%this.ammo, 1);
|
||||
|
||||
// Get the player's velocity, we'll then add it to that of the projectile
|
||||
%objectVelocity = %obj.getVelocity();
|
||||
|
||||
%numProjectiles = %this.projectileNum;
|
||||
if (%numProjectiles == 0)
|
||||
%numProjectiles = 1;
|
||||
|
||||
for (%i = 0; %i < %numProjectiles; %i++)
|
||||
{
|
||||
if (%this.projectileSpread)
|
||||
{
|
||||
// We'll need to "skew" this projectile a little bit. We start by
|
||||
// getting the straight ahead aiming point of the gun
|
||||
%vec = %obj.getMuzzleVector(%slot);
|
||||
|
||||
// Then we'll create a spread matrix by randomly generating x, y, and z
|
||||
// points in a circle
|
||||
%matrix = "";
|
||||
for(%j = 0; %j < 3; %j++)
|
||||
%matrix = %matrix @ (getRandom() - 0.5) * 2 * 3.1415926 * %this.projectileSpread @ " ";
|
||||
%mat = MatrixCreateFromEuler(%matrix);
|
||||
|
||||
// Which we'll use to alter the projectile's initial vector with
|
||||
%muzzleVector = MatrixMulVector(%mat, %vec);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Weapon projectile doesn't have a spread factor so we fire it using
|
||||
// the straight ahead aiming point of the gun
|
||||
%muzzleVector = %obj.getMuzzleVector(%slot);
|
||||
}
|
||||
|
||||
// Add player's velocity
|
||||
%muzzleVelocity = VectorAdd(
|
||||
VectorScale(%muzzleVector, %this.projectile.muzzleVelocity),
|
||||
VectorScale(%objectVelocity, %this.projectile.velInheritFactor));
|
||||
|
||||
// Create the projectile object
|
||||
%p = new (%this.projectileType)()
|
||||
{
|
||||
dataBlock = %this.projectile;
|
||||
initialVelocity = %muzzleVelocity;
|
||||
initialPosition = %obj.getMuzzlePoint(%slot);
|
||||
sourceObject = %obj;
|
||||
sourceSlot = %slot;
|
||||
client = %obj.client;
|
||||
sourceClass = %obj.getClassName();
|
||||
};
|
||||
MissionCleanup.add(%p);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// A "generic" weaponimage onAltFire handler for most weapons. Can be
|
||||
// overridden with an appropriate namespace method for any weapon that requires
|
||||
// a custom firing solution.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function WeaponImage::onAltFire(%this, %obj, %slot)
|
||||
{
|
||||
//echo("\c4WeaponImage::onAltFire("@%this.getName()@", "@%obj.client.nameBase@", "@%slot@")");
|
||||
|
||||
// Decrement inventory ammo. The image's ammo state is updated
|
||||
// automatically by the ammo inventory hooks.
|
||||
%obj.decInventory(%this.ammo, 1);
|
||||
|
||||
// Get the player's velocity, we'll then add it to that of the projectile
|
||||
%objectVelocity = %obj.getVelocity();
|
||||
|
||||
%numProjectiles = %this.altProjectileNum;
|
||||
if (%numProjectiles == 0)
|
||||
%numProjectiles = 1;
|
||||
|
||||
for (%i = 0; %i < %numProjectiles; %i++)
|
||||
{
|
||||
if (%this.altProjectileSpread)
|
||||
{
|
||||
// We'll need to "skew" this projectile a little bit. We start by
|
||||
// getting the straight ahead aiming point of the gun
|
||||
%vec = %obj.getMuzzleVector(%slot);
|
||||
|
||||
// Then we'll create a spread matrix by randomly generating x, y, and z
|
||||
// points in a circle
|
||||
%matrix = "";
|
||||
for(%i = 0; %i < 3; %i++)
|
||||
%matrix = %matrix @ (getRandom() - 0.5) * 2 * 3.1415926 * %this.altProjectileSpread @ " ";
|
||||
%mat = MatrixCreateFromEuler(%matrix);
|
||||
|
||||
// Which we'll use to alter the projectile's initial vector with
|
||||
%muzzleVector = MatrixMulVector(%mat, %vec);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Weapon projectile doesn't have a spread factor so we fire it using
|
||||
// the straight ahead aiming point of the gun.
|
||||
%muzzleVector = %obj.getMuzzleVector(%slot);
|
||||
}
|
||||
|
||||
// Add player's velocity
|
||||
%muzzleVelocity = VectorAdd(
|
||||
VectorScale(%muzzleVector, %this.altProjectile.muzzleVelocity),
|
||||
VectorScale(%objectVelocity, %this.altProjectile.velInheritFactor));
|
||||
|
||||
// Create the projectile object
|
||||
%p = new (%this.projectileType)()
|
||||
{
|
||||
dataBlock = %this.altProjectile;
|
||||
initialVelocity = %muzzleVelocity;
|
||||
initialPosition = %obj.getMuzzlePoint(%slot);
|
||||
sourceObject = %obj;
|
||||
sourceSlot = %slot;
|
||||
client = %obj.client;
|
||||
};
|
||||
MissionCleanup.add(%p);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// A "generic" weaponimage onWetFire handler for most weapons. Can be
|
||||
// overridden with an appropriate namespace method for any weapon that requires
|
||||
// a custom firing solution.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function WeaponImage::onWetFire(%this, %obj, %slot)
|
||||
{
|
||||
//echo("\c4WeaponImage::onWetFire("@%this.getName()@", "@%obj.client.nameBase@", "@%slot@")");
|
||||
|
||||
// Decrement inventory ammo. The image's ammo state is updated
|
||||
// automatically by the ammo inventory hooks.
|
||||
%obj.decInventory(%this.ammo, 1);
|
||||
|
||||
// Get the player's velocity, we'll then add it to that of the projectile
|
||||
%objectVelocity = %obj.getVelocity();
|
||||
|
||||
%numProjectiles = %this.projectileNum;
|
||||
if (%numProjectiles == 0)
|
||||
%numProjectiles = 1;
|
||||
|
||||
for (%i = 0; %i < %numProjectiles; %i++)
|
||||
{
|
||||
if (%this.wetProjectileSpread)
|
||||
{
|
||||
// We'll need to "skew" this projectile a little bit. We start by
|
||||
// getting the straight ahead aiming point of the gun
|
||||
%vec = %obj.getMuzzleVector(%slot);
|
||||
|
||||
// Then we'll create a spread matrix by randomly generating x, y, and z
|
||||
// points in a circle
|
||||
%matrix = "";
|
||||
for(%j = 0; %j < 3; %j++)
|
||||
%matrix = %matrix @ (getRandom() - 0.5) * 2 * 3.1415926 * %this.wetProjectileSpread @ " ";
|
||||
%mat = MatrixCreateFromEuler(%matrix);
|
||||
|
||||
// Which we'll use to alter the projectile's initial vector with
|
||||
%muzzleVector = MatrixMulVector(%mat, %vec);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Weapon projectile doesn't have a spread factor so we fire it using
|
||||
// the straight ahead aiming point of the gun.
|
||||
%muzzleVector = %obj.getMuzzleVector(%slot);
|
||||
}
|
||||
|
||||
// Add player's velocity
|
||||
%muzzleVelocity = VectorAdd(
|
||||
VectorScale(%muzzleVector, %this.wetProjectile.muzzleVelocity),
|
||||
VectorScale(%objectVelocity, %this.wetProjectile.velInheritFactor));
|
||||
|
||||
// Create the projectile object
|
||||
%p = new (%this.projectileType)()
|
||||
{
|
||||
dataBlock = %this.wetProjectile;
|
||||
initialVelocity = %muzzleVelocity;
|
||||
initialPosition = %obj.getMuzzlePoint(%slot);
|
||||
sourceObject = %obj;
|
||||
sourceSlot = %slot;
|
||||
client = %obj.client;
|
||||
};
|
||||
MissionCleanup.add(%p);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Clip Management
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function WeaponImage::onClipEmpty(%this, %obj, %slot)
|
||||
{
|
||||
//echo("WeaponImage::onClipEmpty: " SPC %this SPC %obj SPC %slot);
|
||||
|
||||
// Attempt to automatically reload. Schedule this so it occurs
|
||||
// outside of the current state that called this method
|
||||
%this.schedule(0, "reloadAmmoClip", %obj, %slot);
|
||||
}
|
||||
|
||||
function WeaponImage::reloadAmmoClip(%this, %obj, %slot)
|
||||
{
|
||||
//echo("WeaponImage::reloadAmmoClip: " SPC %this SPC %obj SPC %slot);
|
||||
|
||||
// Make sure we're indeed the currect image on the given slot
|
||||
if (%this != %obj.getMountedImage(%slot))
|
||||
return;
|
||||
|
||||
if ( %this.isField("clip") )
|
||||
{
|
||||
if (%obj.getInventory(%this.clip) > 0)
|
||||
{
|
||||
%obj.decInventory(%this.clip, 1);
|
||||
%obj.setInventory(%this.ammo, %this.ammo.maxInventory);
|
||||
%obj.setImageAmmo(%slot, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
%amountInPocket = %obj.getFieldValue( "remaining" @ %this.ammo.getName());
|
||||
if ( %amountInPocket )
|
||||
{
|
||||
%obj.setFieldValue( "remaining" @ %this.ammo.getName(), 0);
|
||||
%obj.setInventory( %this.ammo, %amountInPocket );
|
||||
%obj.setImageAmmo( %slot, true );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function WeaponImage::clearAmmoClip( %this, %obj, %slot )
|
||||
{
|
||||
//echo("WeaponImage::clearAmmoClip: " SPC %this SPC %obj SPC %slot);
|
||||
|
||||
// if we're not empty put the remaining bullets from the current clip
|
||||
// in to the player's "pocket".
|
||||
|
||||
if ( %this.isField( "clip" ) )
|
||||
{
|
||||
// Commenting out this line will use a "hard clip" system, where
|
||||
// A player will lose any ammo currently in the gun when reloading.
|
||||
%pocketAmount = %this.stashSpareAmmo( %obj );
|
||||
|
||||
if ( %obj.getInventory( %this.clip ) > 0 || %pocketAmount != 0 )
|
||||
%obj.setImageAmmo(%slot, false);
|
||||
}
|
||||
}
|
||||
function WeaponImage::stashSpareAmmo( %this, %player )
|
||||
{
|
||||
// If the amount in our pocket plus what we are about to add from the clip
|
||||
// Is over a clip, add a clip to inventory and keep the remainder
|
||||
// on the player
|
||||
if (%player.getInventory( %this.ammo ) < %this.ammo.maxInventory )
|
||||
{
|
||||
%nameOfAmmoField = "remaining" @ %this.ammo.getName();
|
||||
|
||||
%amountInPocket = %player.getFieldValue( %nameOfAmmoField );
|
||||
|
||||
%amountInGun = %player.getInventory( %this.ammo );
|
||||
|
||||
%combinedAmmo = %amountInGun + %amountInPocket;
|
||||
|
||||
// Give the player another clip if the amount in our pocket + the
|
||||
// Amount in our gun is over the size of a clip.
|
||||
if ( %combinedAmmo >= %this.ammo.maxInventory )
|
||||
{
|
||||
%player.setFieldValue( %nameOfAmmoField, %combinedAmmo - %this.ammo.maxInventory );
|
||||
%player.incInventory( %this.clip, 1 );
|
||||
}
|
||||
else if ( %player.getInventory(%this.clip) > 0 )// Only put it back in our pocket if we have clips.
|
||||
%player.setFieldValue( %nameOfAmmoField, %combinedAmmo );
|
||||
|
||||
return %player.getFieldValue( %nameOfAmmoField );
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Clip Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function AmmoClip::onPickup(%this, %obj, %shape, %amount)
|
||||
{
|
||||
// The parent Item method performs the actual pickup.
|
||||
if (Parent::onPickup(%this, %obj, %shape, %amount))
|
||||
serverPlay3D(AmmoPickupSound, %shape.getTransform());
|
||||
|
||||
// The clip inventory state has changed, we need to update the
|
||||
// current mounted image using this clip to reflect the new state.
|
||||
if ((%image = %shape.getMountedImage($WeaponSlot)) > 0)
|
||||
{
|
||||
// Check if this weapon uses the clip we just picked up and if
|
||||
// there is no ammo.
|
||||
if (%image.isField("clip") && %image.clip.getId() == %this.getId())
|
||||
{
|
||||
%outOfAmmo = !%shape.getImageAmmo($WeaponSlot);
|
||||
|
||||
%currentAmmo = %shape.getInventory(%image.ammo);
|
||||
|
||||
if ( isObject( %image.clip ) )
|
||||
%amountInClips = %shape.getInventory(%image.clip);
|
||||
|
||||
%amountInClips *= %image.ammo.maxInventory;
|
||||
%amountInClips += %obj.getFieldValue( "remaining" @ %this.ammo.getName() );
|
||||
|
||||
%shape.client.setAmmoAmountHud(%currentAmmo, %amountInClips );
|
||||
|
||||
if (%outOfAmmo)
|
||||
{
|
||||
%image.onClipEmpty(%shape, $WeaponSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Ammmo Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function Ammo::onPickup(%this, %obj, %shape, %amount)
|
||||
{
|
||||
// The parent Item method performs the actual pickup.
|
||||
if (Parent::onPickup(%this, %obj, %shape, %amount))
|
||||
serverPlay3D(AmmoPickupSound, %shape.getTransform());
|
||||
}
|
||||
|
||||
function Ammo::onInventory(%this, %obj, %amount)
|
||||
{
|
||||
// The ammo inventory state has changed, we need to update any
|
||||
// mounted images using this ammo to reflect the new state.
|
||||
for (%i = 0; %i < 8; %i++)
|
||||
{
|
||||
if ((%image = %obj.getMountedImage(%i)) > 0)
|
||||
if (isObject(%image.ammo) && %image.ammo.getId() == %this.getId())
|
||||
{
|
||||
%obj.setImageAmmo(%i, %amount != 0);
|
||||
%currentAmmo = %obj.getInventory(%this);
|
||||
|
||||
if (%obj.getClassname() $= "Player")
|
||||
{
|
||||
if ( isObject( %this.clip ) )
|
||||
{
|
||||
%amountInClips = %obj.getInventory(%this.clip);
|
||||
%amountInClips *= %this.maxInventory;
|
||||
%amountInClips += %obj.getFieldValue( "remaining" @ %this.getName() );
|
||||
}
|
||||
else //Is a single fire weapon, like the grenade launcher.
|
||||
{
|
||||
%amountInClips = %currentAmmo;
|
||||
%currentAmmo = 1;
|
||||
}
|
||||
|
||||
if (%obj.client !$= "" && !%obj.isAiControlled)
|
||||
%obj.client.setAmmoAmountHud(%currentAmmo, %amountInClips);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Weapon cycling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function ShapeBase::clearWeaponCycle(%this)
|
||||
{
|
||||
%this.totalCycledWeapons = 0;
|
||||
}
|
||||
|
||||
function ShapeBase::addToWeaponCycle(%this, %weapon)
|
||||
{
|
||||
%this.cycleWeapon[%this.totalCycledWeapons++ - 1] = %weapon;
|
||||
}
|
||||
|
||||
function ShapeBase::cycleWeapon(%this, %direction)
|
||||
{
|
||||
// Can't cycle what we don't have
|
||||
if (%this.totalCycledWeapons == 0)
|
||||
return;
|
||||
|
||||
// Find out the index of the current weapon, if any (not all
|
||||
// available weapons may be part of the cycle)
|
||||
%currentIndex = -1;
|
||||
if (%this.getMountedImage($WeaponSlot) != 0)
|
||||
{
|
||||
%curWeapon = %this.getMountedImage($WeaponSlot).item.getName();
|
||||
for (%i=0; %i<%this.totalCycledWeapons; %i++)
|
||||
{
|
||||
if (%this.cycleWeapon[%i] $= %curWeapon)
|
||||
{
|
||||
%currentIndex = %i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the next weapon index
|
||||
%nextIndex = 0;
|
||||
%dir = 1;
|
||||
if (%currentIndex != -1)
|
||||
{
|
||||
if (%direction $= "prev")
|
||||
{
|
||||
%dir = -1;
|
||||
%nextIndex = %currentIndex - 1;
|
||||
if (%nextIndex < 0)
|
||||
{
|
||||
// Wrap around to the end
|
||||
%nextIndex = %this.totalCycledWeapons - 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
%nextIndex = %currentIndex + 1;
|
||||
if (%nextIndex >= %this.totalCycledWeapons)
|
||||
{
|
||||
// Wrap back to the beginning
|
||||
%nextIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We now need to check if the next index is a valid weapon. If not,
|
||||
// then continue to cycle to the next weapon, in the appropriate direction,
|
||||
// until one is found. If nothing is found, then do nothing.
|
||||
%found = false;
|
||||
for (%i=0; %i<%this.totalCycledWeapons; %i++)
|
||||
{
|
||||
%weapon = %this.cycleWeapon[%nextIndex];
|
||||
if (%weapon !$= "" && %this.hasInventory(%weapon) && %this.hasAmmo(%weapon))
|
||||
{
|
||||
// We've found out weapon
|
||||
%found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
%nextIndex = %nextIndex + %dir;
|
||||
if (%nextIndex < 0)
|
||||
{
|
||||
%nextIndex = %this.totalCycledWeapons - 1;
|
||||
}
|
||||
else if (%nextIndex >= %this.totalCycledWeapons)
|
||||
{
|
||||
%nextIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (%found)
|
||||
{
|
||||
%this.use(%this.cycleWeapon[%nextIndex]);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue