Full Template for ticket #1

This commit is contained in:
DavidWyand-GG 2012-09-19 11:54:25 -04:00
parent 74f265b3b3
commit f439dc8dcd
2150 changed files with 286240 additions and 0 deletions

View file

@ -0,0 +1,42 @@
//-----------------------------------------------------------------------------
// 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 specific audio descriptions. Always declare SFXDescription's (the type of sound)
// before SFXProfile's (the sound itself) when creating new ones
singleton SFXDescription(BulletFireDesc : AudioEffect )
{
isLooping = false;
is3D = true;
ReferenceDistance = 10.0;
MaxDistance = 60.0;
};
singleton SFXDescription(BulletImpactDesc : AudioEffect )
{
isLooping = false;
is3D = true;
ReferenceDistance = 10.0;
MaxDistance = 30.0;
volume = 0.4;
pitch = 1.4;
};

View file

@ -0,0 +1,323 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Message Hud
//-----------------------------------------------------------------------------
// chat hud sizes in lines
$outerChatLenY[1] = 4;
$outerChatLenY[2] = 9;
$outerChatLenY[3] = 13;
// Only play sound files that are <= 5000ms in length.
$MaxMessageWavLength = 5000;
// Helper function to play a sound file if the message indicates.
// Returns starting position of wave file indicator.
function playMessageSound(%message, %voice, %pitch)
{
// Search for wav tag marker.
%wavStart = strstr(%message, "~w");
if (%wavStart == -1)
{
return -1;
}
%wav = getSubStr(%message, %wavStart + 2, 1000);
if (%voice !$= "")
{
%wavFile = "art/sound/voice/" @ %voice @ "/" @ %wav;
}
else
%wavFile = "art/sound/" @ %wav;
if (strstr(%wavFile, ".wav") != (strlen(%wavFile) - 4))
%wavFile = %wavFile @ ".wav";
// XXX This only expands to a single filepath, of course; it
// would be nice to support checking in each mod path if we
// have multiple mods active.
%wavFile = ExpandFilename(%wavFile);
%wavSource = sfxCreateSource(AudioMessage, %wavFile);
if (isObject(%wavSource))
{
%wavLengthMS = %wavSource.getDuration() * %pitch;
if (%wavLengthMS == 0)
error("** WAV file \"" @ %wavFile @ "\" is nonexistent or sound is zero-length **");
else if (%wavLengthMS <= $MaxMessageWavLength)
{
if (isObject($ClientChatHandle[%sender]))
$ClientChatHandle[%sender].delete();
$ClientChatHandle[%sender] = %wavSource;
if (%pitch != 1.0)
$ClientChatHandle[%sender].setPitch(%pitch);
$ClientChatHandle[%sender].play();
}
else
error("** WAV file \"" @ %wavFile @ "\" is too long **");
}
else
error("** Unable to load WAV file : \"" @ %wavFile @ "\" **");
return %wavStart;
}
// All messages are stored in this HudMessageVector, the actual
// MainChatHud only displays the contents of this vector.
new MessageVector(HudMessageVector);
$LastHudTarget = 0;
//-----------------------------------------------------------------------------
function onChatMessage(%message, %voice, %pitch)
{
// XXX Client objects on the server must have voiceTag and voicePitch
// fields for values to be passed in for %voice and %pitch... in
// this example mod, they don't have those fields.
// Clients are not allowed to trigger general game sounds with their
// chat messages... a voice directory MUST be specified.
if (%voice $= "") {
%voice = "default";
}
// See if there's a sound at the end of the message, and play it.
if ((%wavStart = playMessageSound(%message, %voice, %pitch)) != -1) {
// Remove the sound marker from the end of the message.
%message = getSubStr(%message, 0, %wavStart);
}
// Chat goes to the chat HUD.
if (getWordCount(%message)) {
ChatHud.addLine(%message);
}
}
function onServerMessage(%message)
{
// See if there's a sound at the end of the message, and play it.
if ((%wavStart = playMessageSound(%message)) != -1) {
// Remove the sound marker from the end of the message.
%message = getSubStr(%message, 0, %wavStart);
}
// Server messages go to the chat HUD too.
if (getWordCount(%message)) {
ChatHud.addLine(%message);
}
}
//-----------------------------------------------------------------------------
// MainChatHud methods
//-----------------------------------------------------------------------------
function MainChatHud::onWake( %this )
{
// set the chat hud to the users pref
%this.setChatHudLength( $Pref::ChatHudLength );
}
//------------------------------------------------------------------------------
function MainChatHud::setChatHudLength( %this, %length )
{
%textHeight = ChatHud.Profile.fontSize + ChatHud.lineSpacing;
if (%textHeight <= 0)
%textHeight = 12;
%lengthInPixels = $outerChatLenY[%length] * %textHeight;
%chatMargin = getWord(OuterChatHud.extent, 1) - getWord(ChatScrollHud.Extent, 1)
+ 2 * ChatScrollHud.profile.borderThickness;
OuterChatHud.setExtent(firstWord(OuterChatHud.extent), %lengthInPixels + %chatMargin);
ChatScrollHud.scrollToBottom();
ChatPageDown.setVisible(false);
}
//------------------------------------------------------------------------------
function MainChatHud::nextChatHudLen( %this )
{
%len = $pref::ChatHudLength++;
if ($pref::ChatHudLength == 4)
$pref::ChatHudLength = 1;
%this.setChatHudLength($pref::ChatHudLength);
}
//-----------------------------------------------------------------------------
// ChatHud methods
// This is the actual message vector/text control which is part of
// the MainChatHud dialog
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
function ChatHud::addLine(%this,%text)
{
//first, see if we're "scrolled up"...
%textHeight = %this.profile.fontSize + %this.lineSpacing;
if (%textHeight <= 0)
%textHeight = 12;
%scrollBox = %this.getGroup();
%chatScrollHeight = getWord(%scrollBox.extent, 1) - 2 * %scrollBox.profile.borderThickness;
%chatPosition = getWord(%this.extent, 1) - %chatScrollHeight + getWord(%this.position, 1) - %scrollBox.profile.borderThickness;
%linesToScroll = mFloor((%chatPosition / %textHeight) + 0.5);
if (%linesToScroll > 0)
%origPosition = %this.position;
//remove old messages from the top only if scrolled down all the way
while( !chatPageDown.isVisible() && HudMessageVector.getNumLines() && (HudMessageVector.getNumLines() >= $pref::HudMessageLogSize))
{
%tag = HudMessageVector.getLineTag(0);
if(%tag != 0)
%tag.delete();
HudMessageVector.popFrontLine();
}
//add the message...
HudMessageVector.pushBackLine(%text, $LastHudTarget);
$LastHudTarget = 0;
//now that we've added the message, see if we need to reset the position
if (%linesToScroll > 0)
{
chatPageDown.setVisible(true);
%this.position = %origPosition;
}
else
chatPageDown.setVisible(false);
}
//-----------------------------------------------------------------------------
function ChatHud::pageUp(%this)
{
// Find out the text line height
%textHeight = %this.profile.fontSize + %this.lineSpacing;
if (%textHeight <= 0)
%textHeight = 12;
%scrollBox = %this.getGroup();
// Find out how many lines per page are visible
%chatScrollHeight = getWord(%scrollBox.extent, 1) - 2 * %scrollBox.profile.borderThickness;
if (%chatScrollHeight <= 0)
return;
%pageLines = mFloor(%chatScrollHeight / %textHeight) - 1; // have a 1 line overlap on pages
if (%pageLines <= 0)
%pageLines = 1;
// See how many lines we actually can scroll up:
%chatPosition = -1 * (getWord(%this.position, 1) - %scrollBox.profile.borderThickness);
%linesToScroll = mFloor((%chatPosition / %textHeight) + 0.5);
if (%linesToScroll <= 0)
return;
if (%linesToScroll > %pageLines)
%scrollLines = %pageLines;
else
%scrollLines = %linesToScroll;
// Now set the position
%this.position = firstWord(%this.position) SPC (getWord(%this.position, 1) + (%scrollLines * %textHeight));
// Display the pageup icon
chatPageDown.setVisible(true);
}
//-----------------------------------------------------------------------------
function ChatHud::pageDown(%this)
{
// Find out the text line height
%textHeight = %this.profile.fontSize + %this.lineSpacing;
if (%textHeight <= 0)
%textHeight = 12;
%scrollBox = %this.getGroup();
// Find out how many lines per page are visible
%chatScrollHeight = getWord(%scrollBox.extent, 1) - 2 * %scrollBox.profile.borderThickness;
if (%chatScrollHeight <= 0)
return;
%pageLines = mFloor(%chatScrollHeight / %textHeight) - 1;
if (%pageLines <= 0)
%pageLines = 1;
// See how many lines we actually can scroll down:
%chatPosition = getWord(%this.extent, 1) - %chatScrollHeight + getWord(%this.position, 1) - %scrollBox.profile.borderThickness;
%linesToScroll = mFloor((%chatPosition / %textHeight) + 0.5);
if (%linesToScroll <= 0)
return;
if (%linesToScroll > %pageLines)
%scrollLines = %pageLines;
else
%scrollLines = %linesToScroll;
// Now set the position
%this.position = firstWord(%this.position) SPC (getWord(%this.position, 1) - (%scrollLines * %textHeight));
// See if we have should (still) display the pagedown icon
if (%scrollLines < %linesToScroll)
chatPageDown.setVisible(true);
else
chatPageDown.setVisible(false);
}
//-----------------------------------------------------------------------------
// Support functions
//-----------------------------------------------------------------------------
function pageUpMessageHud()
{
ChatHud.pageUp();
}
function pageDownMessageHud()
{
ChatHud.pageDown();
}
function cycleMessageHudSize()
{
MainChatHud.nextChatHudLen();
}

View file

@ -0,0 +1,199 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Server Admin Commands
//-----------------------------------------------------------------------------
function SAD(%password)
{
if (%password !$= "")
commandToServer('SAD', %password);
}
function SADSetPassword(%password)
{
commandToServer('SADSetPassword', %password);
}
//----------------------------------------------------------------------------
// Misc server commands
//----------------------------------------------------------------------------
function clientCmdSyncClock(%time)
{
// Time update from the server, this is only sent at the start of a mission
// or when a client joins a game in progress.
}
//-----------------------------------------------------------------------------
// Numerical Health Counter
//-----------------------------------------------------------------------------
function clientCmdSetNumericalHealthHUD(%curHealth)
{
// Skip if the hud is missing.
if (!isObject(numericalHealthHUD))
return;
// The server has sent us our current health, display it on the HUD
numericalHealthHUD.setValue(%curHealth);
// Ensure the HUD is set to visible while we have health / are alive
if (%curHealth)
HealthHUD.setVisible(true);
else
HealthHUD.setVisible(false);
}
//-----------------------------------------------------------------------------
// Damage Direction Indicator
//-----------------------------------------------------------------------------
function clientCmdSetDamageDirection(%direction)
{
eval("%ctrl = DamageHUD-->damage_" @ %direction @ ";");
if (isObject(%ctrl))
{
// Show the indicator, and schedule an event to hide it again
cancelAll(%ctrl);
%ctrl.setVisible(true);
%ctrl.schedule(500, setVisible, false);
}
}
//-----------------------------------------------------------------------------
// Teleporter visual effect
//-----------------------------------------------------------------------------
function clientCmdPlayTeleportEffect(%position, %effectDataBlock)
{
if (isObject(%effectDataBlock))
{
new Explosion()
{
position = %position;
dataBlock = %effectDataBlock;
};
}
}
// ----------------------------------------------------------------------------
// WeaponHUD
// ----------------------------------------------------------------------------
// Update the Ammo Counter with current ammo, if not any then hide the counter.
function clientCmdSetAmmoAmountHud(%amount, %amountInClips)
{
if (!%amount)
AmmoAmount.setVisible(false);
else
{
AmmoAmount.setVisible(true);
AmmoAmount.setText("Ammo: " @ %amount @ "/" @ %amountInClips);
}
}
// Here we update the Weapon Preview image & reticle for each weapon. We also
// update the Ammo Counter (just so we don't have to call it separately).
// Passing an empty parameter ("") hides the HUD component.
function clientCmdRefreshWeaponHUD(%amount, %preview, %ret, %zoomRet, %amountInClips)
{
if (!%amount)
AmmoAmount.setVisible(false);
else
{
AmmoAmount.setVisible(true);
AmmoAmount.setText("Ammo: " @ %amount @ "/" @ %amountInClips);
}
if (%preview $= "")
WeaponHUD.setVisible(false);//PreviewImage.setVisible(false);
else
{
WeaponHUD.setVisible(true);//PreviewImage.setVisible(true);
PreviewImage.setbitmap("art/gui/weaponHud/"@ detag(%preview));
}
if (%ret $= "")
Reticle.setVisible(false);
else
{
Reticle.setVisible(true);
Reticle.setbitmap("art/gui/weaponHud/"@ detag(%ret));
}
if (isObject(ZoomReticle))
{
if (%zoomRet $= "")
{
ZoomReticle.setBitmap("");
}
else
{
ZoomReticle.setBitmap("art/gui/weaponHud/"@ detag(%zoomRet));
}
}
}
// ----------------------------------------------------------------------------
// Vehicle Support
// ----------------------------------------------------------------------------
function clientCmdtoggleVehicleMap(%toggle)
{
if(%toggle)
{
moveMap.pop();
vehicleMap.push();
}
else
{
vehicleMap.pop();
moveMap.push();
}
}
// ----------------------------------------------------------------------------
// Turret Support
// ----------------------------------------------------------------------------
// Call by the Turret class when a player mounts or unmounts it.
// %turret = The turret that was mounted
// %player = The player doing the mounting
// %mounted = True if the turret was mounted, false if it was unmounted
function turretMountCallback(%turret, %player, %mounted)
{
//echo ( "\c4turretMountCallback -> " @ %mounted );
if (%mounted)
{
// Push the action map
turretMap.push();
}
else
{
// Pop the action map
turretMap.pop();
}
}

View file

@ -0,0 +1,809 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
if ( isObject( moveMap ) )
moveMap.delete();
new ActionMap(moveMap);
//------------------------------------------------------------------------------
// Non-remapable binds
//------------------------------------------------------------------------------
function escapeFromGame()
{
if ( $Server::ServerType $= "SinglePlayer" )
MessageBoxYesNo( "Exit", "Exit from this Mission?", "disconnect();", "");
else
MessageBoxYesNo( "Disconnect", "Disconnect from the server?", "disconnect();", "");
}
moveMap.bindCmd(keyboard, "escape", "", "handleEscape();");
function showPlayerList(%val)
{
if (%val)
PlayerListGui.toggle();
}
moveMap.bind( keyboard, F2, showPlayerList );
function showControlsHelp(%val)
{
if (%val)
ControlsHelpDlg.toggle();
}
moveMap.bind(keyboard, h, showControlsHelp);
function hideHUDs(%val)
{
if (%val)
HudlessPlayGui.toggle();
}
moveMap.bind(keyboard, "ctrl h", hideHUDs);
function doScreenShotHudless(%val)
{
if(%val)
{
canvas.setContent(HudlessPlayGui);
//doScreenshot(%val);
schedule(10, 0, "doScreenShot", %val);
}
else
canvas.setContent(PlayGui);
}
moveMap.bind(keyboard, "alt p", doScreenShotHudless);
//------------------------------------------------------------------------------
// Movement Keys
//------------------------------------------------------------------------------
$movementSpeed = 1; // m/s
function setSpeed(%speed)
{
if(%speed)
$movementSpeed = %speed;
}
function moveleft(%val)
{
$mvLeftAction = %val * $movementSpeed;
}
function moveright(%val)
{
$mvRightAction = %val * $movementSpeed;
}
function moveforward(%val)
{
$mvForwardAction = %val * $movementSpeed;
}
function movebackward(%val)
{
$mvBackwardAction = %val * $movementSpeed;
}
function moveup(%val)
{
%object = ServerConnection.getControlObject();
if(%object.isInNamespaceHierarchy("Camera"))
$mvUpAction = %val * $movementSpeed;
}
function movedown(%val)
{
%object = ServerConnection.getControlObject();
if(%object.isInNamespaceHierarchy("Camera"))
$mvDownAction = %val * $movementSpeed;
}
function turnLeft( %val )
{
$mvYawRightSpeed = %val ? $Pref::Input::KeyboardTurnSpeed : 0;
}
function turnRight( %val )
{
$mvYawLeftSpeed = %val ? $Pref::Input::KeyboardTurnSpeed : 0;
}
function panUp( %val )
{
$mvPitchDownSpeed = %val ? $Pref::Input::KeyboardTurnSpeed : 0;
}
function panDown( %val )
{
$mvPitchUpSpeed = %val ? $Pref::Input::KeyboardTurnSpeed : 0;
}
function getMouseAdjustAmount(%val)
{
// based on a default camera FOV of 90'
return(%val * ($cameraFov / 90) * 0.01) * $pref::Input::LinkMouseSensitivity;
}
function getGamepadAdjustAmount(%val)
{
// based on a default camera FOV of 90'
return(%val * ($cameraFov / 90) * 0.01) * 10.0;
}
function yaw(%val)
{
%yawAdj = getMouseAdjustAmount(%val);
if(ServerConnection.isControlObjectRotDampedCamera())
{
// Clamp and scale
%yawAdj = mClamp(%yawAdj, -m2Pi()+0.01, m2Pi()-0.01);
%yawAdj *= 0.5;
}
$mvYaw += %yawAdj;
}
function pitch(%val)
{
%pitchAdj = getMouseAdjustAmount(%val);
if(ServerConnection.isControlObjectRotDampedCamera())
{
// Clamp and scale
%pitchAdj = mClamp(%pitchAdj, -m2Pi()+0.01, m2Pi()-0.01);
%pitchAdj *= 0.5;
}
$mvPitch += %pitchAdj;
}
function jump(%val)
{
$mvTriggerCount2++;
}
function gamePadMoveX( %val )
{
if(%val > 0)
{
$mvRightAction = %val * $movementSpeed;
$mvLeftAction = 0;
}
else
{
$mvRightAction = 0;
$mvLeftAction = -%val * $movementSpeed;
}
}
function gamePadMoveY( %val )
{
if(%val > 0)
{
$mvForwardAction = %val * $movementSpeed;
$mvBackwardAction = 0;
}
else
{
$mvForwardAction = 0;
$mvBackwardAction = -%val * $movementSpeed;
}
}
function gamepadYaw(%val)
{
%yawAdj = getGamepadAdjustAmount(%val);
if(ServerConnection.isControlObjectRotDampedCamera())
{
// Clamp and scale
%yawAdj = mClamp(%yawAdj, -m2Pi()+0.01, m2Pi()-0.01);
%yawAdj *= 0.5;
}
if(%yawAdj > 0)
{
$mvYawLeftSpeed = %yawAdj;
$mvYawRightSpeed = 0;
}
else
{
$mvYawLeftSpeed = 0;
$mvYawRightSpeed = -%yawAdj;
}
}
function gamepadPitch(%val)
{
%pitchAdj = getGamepadAdjustAmount(%val);
if(ServerConnection.isControlObjectRotDampedCamera())
{
// Clamp and scale
%pitchAdj = mClamp(%pitchAdj, -m2Pi()+0.01, m2Pi()-0.01);
%pitchAdj *= 0.5;
}
if(%pitchAdj > 0)
{
$mvPitchDownSpeed = %pitchAdj;
$mvPitchUpSpeed = 0;
}
else
{
$mvPitchDownSpeed = 0;
$mvPitchUpSpeed = -%pitchAdj;
}
}
moveMap.bind( keyboard, a, moveleft );
moveMap.bind( keyboard, d, moveright );
moveMap.bind( keyboard, left, moveleft );
moveMap.bind( keyboard, right, moveright );
moveMap.bind( keyboard, w, moveforward );
moveMap.bind( keyboard, s, movebackward );
moveMap.bind( keyboard, up, moveforward );
moveMap.bind( keyboard, down, movebackward );
moveMap.bind( keyboard, e, moveup );
moveMap.bind( keyboard, c, movedown );
moveMap.bind( keyboard, space, jump );
moveMap.bind( mouse, xaxis, yaw );
moveMap.bind( mouse, yaxis, pitch );
moveMap.bind( gamepad, thumbrx, "D", "-0.23 0.23", gamepadYaw );
moveMap.bind( gamepad, thumbry, "D", "-0.23 0.23", gamepadPitch );
moveMap.bind( gamepad, thumblx, "D", "-0.23 0.23", gamePadMoveX );
moveMap.bind( gamepad, thumbly, "D", "-0.23 0.23", gamePadMoveY );
moveMap.bind( gamepad, btn_a, jump );
moveMap.bindCmd( gamepad, btn_back, "disconnect();", "" );
moveMap.bindCmd(gamepad, dpadl, "toggleLightColorViz();", "");
moveMap.bindCmd(gamepad, dpadu, "toggleDepthViz();", "");
moveMap.bindCmd(gamepad, dpadd, "toggleNormalsViz();", "");
moveMap.bindCmd(gamepad, dpadr, "toggleLightSpecularViz();", "");
// ----------------------------------------------------------------------------
// Stance/pose
// ----------------------------------------------------------------------------
function doCrouch(%val)
{
$mvTriggerCount3++;
}
moveMap.bind(keyboard, lcontrol, doCrouch);
moveMap.bind(gamepad, btn_b, doCrouch);
function doSprint(%val)
{
$mvTriggerCount5++;
}
moveMap.bind(keyboard, lshift, doSprint);
//------------------------------------------------------------------------------
// Mouse Trigger
//------------------------------------------------------------------------------
function mouseFire(%val)
{
$mvTriggerCount0++;
}
//function altTrigger(%val)
//{
//$mvTriggerCount1++;
//}
moveMap.bind( mouse, button0, mouseFire );
//moveMap.bind( mouse, button1, altTrigger );
//------------------------------------------------------------------------------
// Gamepad Trigger
//------------------------------------------------------------------------------
function gamepadFire(%val)
{
if(%val > 0.1 && !$gamepadFireTriggered)
{
$gamepadFireTriggered = true;
$mvTriggerCount0++;
}
else if(%val <= 0.1 && $gamepadFireTriggered)
{
$gamepadFireTriggered = false;
$mvTriggerCount0++;
}
}
function gamepadAltTrigger(%val)
{
if(%val > 0.1 && !$gamepadAltTriggerTriggered)
{
$gamepadAltTriggerTriggered = true;
$mvTriggerCount1++;
}
else if(%val <= 0.1 && $gamepadAltTriggerTriggered)
{
$gamepadAltTriggerTriggered = false;
$mvTriggerCount1++;
}
}
moveMap.bind(gamepad, triggerr, gamepadFire);
moveMap.bind(gamepad, triggerl, gamepadAltTrigger);
//------------------------------------------------------------------------------
// Zoom and FOV functions
//------------------------------------------------------------------------------
if($Player::CurrentFOV $= "")
$Player::CurrentFOV = $pref::Player::DefaultFOV / 2;
// toggleZoomFOV() works by dividing the CurrentFOV by 2. Each time that this
// toggle is hit it simply divides the CurrentFOV by 2 once again. If the
// FOV is reduced below a certain threshold then it resets to equal half of the
// DefaultFOV value. This gives us 4 zoom levels to cycle through.
function toggleZoomFOV()
{
$Player::CurrentFOV = $Player::CurrentFOV / 2;
if($Player::CurrentFOV < 5)
resetCurrentFOV();
if(ServerConnection.zoomed)
setFOV($Player::CurrentFOV);
else
{
setFov(ServerConnection.getControlCameraDefaultFov());
}
}
function resetCurrentFOV()
{
$Player::CurrentFOV = ServerConnection.getControlCameraDefaultFov() / 2;
}
function turnOffZoom()
{
ServerConnection.zoomed = false;
setFov(ServerConnection.getControlCameraDefaultFov());
Reticle.setVisible(true);
zoomReticle.setVisible(false);
// Rather than just disable the DOF effect, we want to set it to the level's
// preset values.
//DOFPostEffect.disable();
ppOptionsUpdateDOFSettings();
}
function setZoomFOV(%val)
{
if(%val)
toggleZoomFOV();
}
function toggleZoom(%val)
{
if (%val)
{
ServerConnection.zoomed = true;
setFov($Player::CurrentFOV);
Reticle.setVisible(false);
zoomReticle.setVisible(true);
DOFPostEffect.setAutoFocus( true );
DOFPostEffect.setFocusParams( 0.5, 0.5, 50, 500, -5, 5 );
DOFPostEffect.enable();
}
else
{
turnOffZoom();
}
}
function mouseButtonZoom(%val)
{
toggleZoom(%val);
}
moveMap.bind(keyboard, f, setZoomFOV); // f for field of view
moveMap.bind(keyboard, z, toggleZoom); // z for zoom
moveMap.bind( mouse, button1, mouseButtonZoom );
//------------------------------------------------------------------------------
// Camera & View functions
//------------------------------------------------------------------------------
function toggleFreeLook( %val )
{
if ( %val )
$mvFreeLook = true;
else
$mvFreeLook = false;
}
function toggleFirstPerson(%val)
{
if (%val)
{
ServerConnection.setFirstPerson(!ServerConnection.isFirstPerson());
}
}
function toggleCamera(%val)
{
if (%val)
commandToServer('ToggleCamera');
}
moveMap.bind( keyboard, v, toggleFreeLook ); // v for vanity
moveMap.bind(keyboard, tab, toggleFirstPerson );
moveMap.bind(keyboard, "alt c", toggleCamera);
moveMap.bind( gamepad, btn_start, toggleCamera );
moveMap.bind( gamepad, btn_x, toggleFirstPerson );
// ----------------------------------------------------------------------------
// Misc. Player stuff
// ----------------------------------------------------------------------------
// Gideon does not have these animations, so the player does not need access to
// them. Commenting instead of removing so as to retain an example for those
// who will want to use a player model that has these animations and wishes to
// use them.
//moveMap.bindCmd(keyboard, "ctrl w", "commandToServer('playCel',\"wave\");", "");
//moveMap.bindCmd(keyboard, "ctrl s", "commandToServer('playCel',\"salute\");", "");
moveMap.bindCmd(keyboard, "ctrl k", "commandToServer('suicide');", "");
//------------------------------------------------------------------------------
// Item manipulation
//------------------------------------------------------------------------------
moveMap.bindCmd(keyboard, "1", "commandToServer('use',\"Ryder\");", "");
moveMap.bindCmd(keyboard, "2", "commandToServer('use',\"Lurker\");", "");
moveMap.bindCmd(keyboard, "3", "commandToServer('use',\"LurkerGrenadeLauncher\");", "");
moveMap.bindCmd(keyboard, "4", "commandToServer('use',\"ProxMine\");", "");
moveMap.bindCmd(keyboard, "5", "commandToServer('use',\"DeployableTurret\");", "");
moveMap.bindCmd(keyboard, "r", "commandToServer('reloadWeapon');", "");
function unmountWeapon(%val)
{
if (%val)
commandToServer('unmountWeapon');
}
moveMap.bind(keyboard, 0, unmountWeapon);
function throwWeapon(%val)
{
if (%val)
commandToServer('Throw', "Weapon");
}
function tossAmmo(%val)
{
if (%val)
commandToServer('Throw', "Ammo");
}
moveMap.bind(keyboard, "alt w", throwWeapon);
moveMap.bind(keyboard, "alt a", tossAmmo);
function nextWeapon(%val)
{
if (%val)
commandToServer('cycleWeapon', "next");
}
function prevWeapon(%val)
{
if (%val)
commandToServer('cycleWeapon', "prev");
}
function mouseWheelWeaponCycle(%val)
{
if (%val < 0)
commandToServer('cycleWeapon', "next");
else if (%val > 0)
commandToServer('cycleWeapon', "prev");
}
moveMap.bind(keyboard, q, nextWeapon);
moveMap.bind(keyboard, "ctrl q", prevWeapon);
moveMap.bind(mouse, "zaxis", mouseWheelWeaponCycle);
//------------------------------------------------------------------------------
// Message HUD functions
//------------------------------------------------------------------------------
function pageMessageHudUp( %val )
{
if ( %val )
pageUpMessageHud();
}
function pageMessageHudDown( %val )
{
if ( %val )
pageDownMessageHud();
}
function resizeMessageHud( %val )
{
if ( %val )
cycleMessageHudSize();
}
moveMap.bind(keyboard, u, toggleMessageHud );
//moveMap.bind(keyboard, y, teamMessageHud );
moveMap.bind(keyboard, "pageUp", pageMessageHudUp );
moveMap.bind(keyboard, "pageDown", pageMessageHudDown );
moveMap.bind(keyboard, "p", resizeMessageHud );
//------------------------------------------------------------------------------
// Demo recording functions
//------------------------------------------------------------------------------
function startRecordingDemo( %val )
{
if ( %val )
startDemoRecord();
}
function stopRecordingDemo( %val )
{
if ( %val )
stopDemoRecord();
}
moveMap.bind( keyboard, F3, startRecordingDemo );
moveMap.bind( keyboard, F4, stopRecordingDemo );
//------------------------------------------------------------------------------
// Helper Functions
//------------------------------------------------------------------------------
function dropCameraAtPlayer(%val)
{
if (%val)
commandToServer('dropCameraAtPlayer');
}
function dropPlayerAtCamera(%val)
{
if (%val)
commandToServer('DropPlayerAtCamera');
}
moveMap.bind(keyboard, "F8", dropCameraAtPlayer);
moveMap.bind(keyboard, "F7", dropPlayerAtCamera);
function bringUpOptions(%val)
{
if (%val)
Canvas.pushDialog(OptionsDlg);
}
GlobalActionMap.bind(keyboard, "ctrl o", bringUpOptions);
//------------------------------------------------------------------------------
// Debugging Functions
//------------------------------------------------------------------------------
$MFDebugRenderMode = 0;
function cycleDebugRenderMode(%val)
{
if (!%val)
return;
$MFDebugRenderMode++;
if ($MFDebugRenderMode > 16)
$MFDebugRenderMode = 0;
if ($MFDebugRenderMode == 15)
$MFDebugRenderMode = 16;
setInteriorRenderMode($MFDebugRenderMode);
if (isObject(ChatHud))
{
%message = "Setting Interior debug render mode to ";
%debugMode = "Unknown";
switch($MFDebugRenderMode)
{
case 0:
%debugMode = "NormalRender";
case 1:
%debugMode = "NormalRenderLines";
case 2:
%debugMode = "ShowDetail";
case 3:
%debugMode = "ShowAmbiguous";
case 4:
%debugMode = "ShowOrphan";
case 5:
%debugMode = "ShowLightmaps";
case 6:
%debugMode = "ShowTexturesOnly";
case 7:
%debugMode = "ShowPortalZones";
case 8:
%debugMode = "ShowOutsideVisible";
case 9:
%debugMode = "ShowCollisionFans";
case 10:
%debugMode = "ShowStrips";
case 11:
%debugMode = "ShowNullSurfaces";
case 12:
%debugMode = "ShowLargeTextures";
case 13:
%debugMode = "ShowHullSurfaces";
case 14:
%debugMode = "ShowVehicleHullSurfaces";
// Depreciated
//case 15:
// %debugMode = "ShowVertexColors";
case 16:
%debugMode = "ShowDetailLevel";
}
ChatHud.addLine(%message @ %debugMode);
}
}
GlobalActionMap.bind(keyboard, "F9", cycleDebugRenderMode);
//------------------------------------------------------------------------------
//
// Start profiler by pressing ctrl f3
// ctrl f3 - starts profile that will dump to console and file
//
function doProfile(%val)
{
if (%val)
{
// key down -- start profile
echo("Starting profile session...");
profilerReset();
profilerEnable(true);
}
else
{
// key up -- finish off profile
echo("Ending profile session...");
profilerDumpToFile("profilerDumpToFile" @ getSimTime() @ ".txt");
profilerEnable(false);
}
}
GlobalActionMap.bind(keyboard, "ctrl F3", doProfile);
//------------------------------------------------------------------------------
// Misc.
//------------------------------------------------------------------------------
GlobalActionMap.bind(keyboard, "tilde", toggleConsole);
GlobalActionMap.bindCmd(keyboard, "alt k", "cls();","");
GlobalActionMap.bindCmd(keyboard, "alt enter", "", "Canvas.attemptFullscreenToggle();");
GlobalActionMap.bindCmd(keyboard, "F1", "", "contextHelp();");
moveMap.bindCmd(keyboard, "n", "toggleNetGraph();", "");
// ----------------------------------------------------------------------------
// Useful vehicle stuff
// ----------------------------------------------------------------------------
// Trace a line along the direction the crosshair is pointing
// If you find a car with a player in it...eject them
function carjack()
{
%player = LocalClientConnection.getControlObject();
if (%player.getClassName() $= "Player")
{
%eyeVec = %player.getEyeVector();
%startPos = %player.getEyePoint();
%endPos = VectorAdd(%startPos, VectorScale(%eyeVec, 1000));
%target = ContainerRayCast(%startPos, %endPos, $TypeMasks::VehicleObjectType);
if (%target)
{
// See if anyone is mounted in the car's driver seat
%mount = %target.getMountNodeObject(0);
// Can only carjack bots
// remove '&& %mount.getClassName() $= "AIPlayer"' to allow you
// to carjack anyone/anything
if (%mount && %mount.getClassName() $= "AIPlayer")
{
commandToServer('carUnmountObj', %mount);
}
}
}
}
// Bind the keys to the carjack command
moveMap.bindCmd(keyboard, "ctrl z", "carjack();", "");
// Starting vehicle action map code
if ( isObject( vehicleMap ) )
vehicleMap.delete();
new ActionMap(vehicleMap);
// The key command for flipping the car
vehicleMap.bindCmd(keyboard, "ctrl x", "commandToServer(\'flipCar\');", "");
function getOut()
{
vehicleMap.pop();
moveMap.push();
commandToServer('dismountVehicle');
}
function brakeLights()
{
// Turn on/off the Cheetah's head lights.
commandToServer('toggleBrakeLights');
}
function brake(%val)
{
commandToServer('toggleBrakeLights');
$mvTriggerCount2++;
}
vehicleMap.bind( keyboard, w, moveforward );
vehicleMap.bind( keyboard, s, movebackward );
vehicleMap.bind( keyboard, up, moveforward );
vehicleMap.bind( keyboard, down, movebackward );
vehicleMap.bind( mouse, xaxis, yaw );
vehicleMap.bind( mouse, yaxis, pitch );
vehicleMap.bind( mouse, button0, mouseFire );
vehicleMap.bind( mouse, button1, altTrigger );
vehicleMap.bindCmd(keyboard, "ctrl f","getout();","");
vehicleMap.bind(keyboard, space, brake);
vehicleMap.bindCmd(keyboard, "l", "brakeLights();", "");
vehicleMap.bindCmd(keyboard, "escape", "", "handleEscape();");
vehicleMap.bind(keyboard, h, showControlsHelp);
vehicleMap.bind( keyboard, v, toggleFreeLook ); // v for vanity
//vehicleMap.bind(keyboard, tab, toggleFirstPerson );
vehicleMap.bind(keyboard, "alt c", toggleCamera);

View 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/client/defaults.cs" );
// Now add your own game specific client preferences as
// well as any overloaded core defaults here.
$PhysXLogWarnings = false;
// 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 client prefs.cs on Xbox360" );
}

View file

@ -0,0 +1,54 @@
//-----------------------------------------------------------------------------
// 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 start / end events sent from the server
//----------------------------------------------------------------------------
function clientCmdGameStart(%seq)
{
PlayerListGui.zeroScores();
ControlsHelpDlg.toggle();
}
function clientCmdGameEnd(%seq)
{
// Stop local activity... the game will be destroyed on the server
sfxStopAll();
if ((!EditorIsActive() && !GuiEditorIsActive()))
{
// Copy the current scores from the player list into the
// end game gui (bit of a hack for now).
EndGameGuiList.clear();
for (%i = 0; %i < PlayerListGuiList.rowCount(); %i++)
{
%text = PlayerListGuiList.getRowText(%i);
%id = PlayerListGuiList.getRowId(%i);
EndGameGuiList.addRow(%id, %text);
}
EndGameGuiList.sortNumerical(1, false);
// Display the end-game screen
Canvas.setContent(EndGameGui);
}
}

View file

@ -0,0 +1,194 @@
//-----------------------------------------------------------------------------
// 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 client scripts & code. The ones marked with (c)
// are accessed from code. Variables preceeded by Pref:: are client
// preferences and stored automatically in the ~/client/prefs.cs file
// in between sessions.
//
// (c) Client::MissionFile Mission file name
// ( ) Client::Password Password for server join
// (?) Pref::Player::CurrentFOV
// (?) Pref::Player::DefaultFov
// ( ) Pref::Input::KeyboardTurnSpeed
// (c) pref::Master[n] List of master servers
// (c) pref::Net::RegionMask
// (c) pref::Client::ServerFavoriteCount
// (c) pref::Client::ServerFavorite[FavoriteCount]
// .. Many more prefs... need to finish this off
// Moves, not finished with this either...
// (c) firstPerson
// $mv*Action...
//-----------------------------------------------------------------------------
// These are variables used to control the shell scripts and
// can be overriden by mods:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
function initClient()
{
echo("\n--------- Initializing " @ $appName @ ": Client Scripts ---------");
// Make sure this variable reflects the correct state.
$Server::Dedicated = false;
// Game information used to query the master server
$Client::GameTypeQuery = $appName;
$Client::MissionTypeQuery = "Any";
exec("art/gui/customProfiles.cs"); // override the base profiles if necessary
// The common module provides basic client functionality
initBaseClient();
// Use our prefs to configure our Canvas/Window
configureCanvas();
// Load up the Game GUIs
exec("art/gui/defaultGameProfiles.cs");
exec("art/gui/PlayGui.gui");
exec("art/gui/ChatHud.gui");
exec("art/gui/playerList.gui");
exec("art/gui/hudlessGui.gui");
exec("art/gui/controlsHelpDlg.gui");
// Load up the shell GUIs
if($platform !$= "xenon") // Use the unified shell instead
exec("art/gui/mainMenuGui.gui");
exec("art/gui/joinServerDlg.gui");
exec("art/gui/endGameGui.gui");
exec("art/gui/StartupGui.gui");
// Gui scripts
exec("./playerList.cs");
exec("./chatHud.cs");
exec("./messageHud.cs");
exec("scripts/gui/playGui.cs");
exec("scripts/gui/startupGui.cs");
// Client scripts
exec("./client.cs");
exec("./game.cs");
exec("./missionDownload.cs");
exec("./serverConnection.cs");
// Load useful Materials
exec("./shaders.cs");
// Default player key bindings
exec("./default.bind.cs");
if (isFile("./config.cs"))
exec("./config.cs");
loadMaterials();
// Really shouldn't be starting the networking unless we are
// going to connect to a remote server, or host a multi-player
// game.
setNetPort(0);
// Copy saved script prefs into C++ code.
setDefaultFov( $pref::Player::defaultFov );
setZoomSpeed( $pref::Player::zoomSpeed );
if( isFile( "./audioData.cs" ) )
exec( "./audioData.cs" );
// Start up the main menu... this is separated out into a
// method for easier mod override.
if ($startWorldEditor || $startGUIEditor) {
// Editor GUI's will start up in the primary main.cs once
// engine is initialized.
return;
}
// Connect to server if requested.
if ($JoinGameAddress !$= "") {
// If we are instantly connecting to an address, load the
// loading GUI then attempt the connect.
loadLoadingGui();
connect($JoinGameAddress, "", $Pref::Player::Name);
}
else {
// Otherwise go to the splash screen.
Canvas.setCursor("DefaultCursor");
loadStartup();
}
}
//-----------------------------------------------------------------------------
function loadMainMenu()
{
// Startup the client with the Main menu...
if (isObject( MainMenuGui ))
Canvas.setContent( MainMenuGui );
else if (isObject( UnifiedMainMenuGui ))
Canvas.setContent( UnifiedMainMenuGui );
Canvas.setCursor("DefaultCursor");
// first check if we have a level file to load
if ($levelToLoad !$= "")
{
%levelFile = "levels/";
%ext = getSubStr($levelToLoad, strlen($levelToLoad) - 3, 3);
if(%ext !$= "mis")
%levelFile = %levelFile @ $levelToLoad @ ".mis";
else
%levelFile = %levelFile @ $levelToLoad;
// Clear out the $levelToLoad so we don't attempt to load the level again
// later on.
$levelToLoad = "";
// let's make sure the file exists
%file = findFirstFile(%levelFile);
if(%file !$= "")
createAndConnectToLocalServer( "SinglePlayer", %file );
}
}
function loadLoadingGui(%displayText)
{
Canvas.setContent("LoadingGui");
LoadingProgress.setValue(1);
if (%displayText !$= "")
{
LoadingProgressTxt.setValue(%displayText);
}
else
{
LoadingProgressTxt.setValue("WAITING FOR SERVER");
}
Canvas.repaint();
}

View 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.
//-----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Enter Chat Message Hud
//----------------------------------------------------------------------------
//------------------------------------------------------------------------------
function MessageHud::open(%this)
{
%offset = 6;
if(%this.isVisible())
return;
if(%this.isTeamMsg)
%text = "TEAM:";
else
%text = "GLOBAL:";
MessageHud_Text.setValue(%text);
%windowPos = "0 " @ ( getWord( outerChatHud.position, 1 ) + getWord( outerChatHud.extent, 1 ) + 1 );
%windowExt = getWord( OuterChatHud.extent, 0 ) @ " " @ getWord( MessageHud_Frame.extent, 1 );
%textExtent = getWord(MessageHud_Text.extent, 0) + 14;
%ctrlExtent = getWord(MessageHud_Frame.extent, 0);
Canvas.pushDialog(%this);
messageHud_Frame.position = %windowPos;
messageHud_Frame.extent = %windowExt;
MessageHud_Edit.position = setWord(MessageHud_Edit.position, 0, %textExtent + %offset);
MessageHud_Edit.extent = setWord(MessageHud_Edit.extent, 0, %ctrlExtent - %textExtent - (2 * %offset));
%this.setVisible(true);
deactivateKeyboard();
MessageHud_Edit.makeFirstResponder(true);
}
//------------------------------------------------------------------------------
function MessageHud::close(%this)
{
if(!%this.isVisible())
return;
Canvas.popDialog(%this);
%this.setVisible(false);
if ( $enableDirectInput )
activateKeyboard();
MessageHud_Edit.setValue("");
}
//------------------------------------------------------------------------------
function MessageHud::toggleState(%this)
{
if(%this.isVisible())
%this.close();
else
%this.open();
}
//------------------------------------------------------------------------------
function MessageHud_Edit::onEscape(%this)
{
MessageHud.close();
}
//------------------------------------------------------------------------------
function MessageHud_Edit::eval(%this)
{
%text = collapseEscape(trim(%this.getValue()));
if(%text !$= "")
{
if(MessageHud.isTeamMsg)
commandToServer('teamMessageSent', %text);
else
commandToServer('messageSent', %text);
}
MessageHud.close();
}
//----------------------------------------------------------------------------
// MessageHud key handlers
function toggleMessageHud(%make)
{
if(%make)
{
MessageHud.isTeamMsg = false;
MessageHud.toggleState();
}
}
function teamMessageHud(%make)
{
if(%make)
{
MessageHud.isTeamMsg = true;
MessageHud.toggleState();
}
}

View file

@ -0,0 +1,221 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Mission Loading & Mission Info
// The mission loading server handshaking is handled by the
// core/scripts/client/missingLoading.cs. This portion handles the interface
// with the game GUI.
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Loading Phases:
// Phase 1: Download Datablocks
// Phase 2: Download Ghost Objects
// Phase 3: Scene Lighting
//----------------------------------------------------------------------------
// Phase 1
//----------------------------------------------------------------------------
function onMissionDownloadPhase1(%missionName, %musicTrack)
{
// Load the post effect presets for this mission.
%path = "levels/" @ fileBase( %missionName ) @ $PostFXManager::fileExtension;
if ( isScriptFile( %path ) )
postFXManager::loadPresetHandler( %path );
else
PostFXManager::settingsApplyDefaultPreset();
// Close and clear the message hud (in case it's open)
if ( isObject( MessageHud ) )
MessageHud.close();
// Reset the loading progress controls:
if ( !isObject( LoadingProgress ) )
return;
LoadingProgress.setValue(0);
LoadingProgressTxt.setValue("LOADING DATABLOCKS");
Canvas.repaint();
}
function onPhase1Progress(%progress)
{
if ( !isObject( LoadingProgress ) )
return;
LoadingProgress.setValue(%progress);
Canvas.repaint(33);
}
function onPhase1Complete()
{
if ( !isObject( LoadingProgress ) )
return;
LoadingProgress.setValue( 1 );
Canvas.repaint();
}
//----------------------------------------------------------------------------
// Phase 2
//----------------------------------------------------------------------------
function onMissionDownloadPhase2()
{
if ( !isObject( LoadingProgress ) )
return;
LoadingProgress.setValue(0);
LoadingProgressTxt.setValue("LOADING OBJECTS");
Canvas.repaint();
}
function onPhase2Progress(%progress)
{
if ( !isObject( LoadingProgress ) )
return;
LoadingProgress.setValue(%progress);
Canvas.repaint(33);
}
function onPhase2Complete()
{
if ( !isObject( LoadingProgress ) )
return;
LoadingProgress.setValue( 1 );
Canvas.repaint();
}
function onFileChunkReceived(%fileName, %ofs, %size)
{
if ( !isObject( LoadingProgress ) )
return;
LoadingProgress.setValue(%ofs / %size);
LoadingProgressTxt.setValue("Downloading " @ %fileName @ "...");
}
//----------------------------------------------------------------------------
// Phase 3
//----------------------------------------------------------------------------
function onMissionDownloadPhase3()
{
if ( !isObject( LoadingProgress ) )
return;
LoadingProgress.setValue(0);
LoadingProgressTxt.setValue("LIGHTING MISSION");
Canvas.repaint();
}
function onPhase3Progress(%progress)
{
if ( !isObject( LoadingProgress ) )
return;
LoadingProgress.setValue(%progress);
Canvas.repaint(33);
}
function onPhase3Complete()
{
$lightingMission = false;
if ( !isObject( LoadingProgress ) )
return;
LoadingProgressTxt.setValue("STARTING MISSION");
LoadingProgress.setValue( 1 );
Canvas.repaint();
}
//----------------------------------------------------------------------------
// Mission loading done!
//----------------------------------------------------------------------------
function onMissionDownloadComplete()
{
// Client will shortly be dropped into the game, so this is
// good place for any last minute gui cleanup.
}
//------------------------------------------------------------------------------
// Before downloading a mission, the server transmits the mission
// information through these messages.
//------------------------------------------------------------------------------
addMessageCallback( 'MsgLoadInfo', handleLoadInfoMessage );
addMessageCallback( 'MsgLoadDescripition', handleLoadDescriptionMessage );
addMessageCallback( 'MsgLoadInfoDone', handleLoadInfoDoneMessage );
addMessageCallback( 'MsgLoadFailed', handleLoadFailedMessage );
//------------------------------------------------------------------------------
function handleLoadInfoMessage( %msgType, %msgString, %mapName )
{
// Make sure the LoadingGUI is displayed
if (Canvas.getContent() != LoadingGui.getId())
{
loadLoadingGui("LOADING MISSION FILE");
}
// Clear all of the loading info lines:
for( %line = 0; %line < LoadingGui.qLineCount; %line++ )
LoadingGui.qLine[%line] = "";
LoadingGui.qLineCount = 0;
}
//------------------------------------------------------------------------------
function handleLoadDescriptionMessage( %msgType, %msgString, %line )
{
LoadingGui.qLine[LoadingGui.qLineCount] = %line;
LoadingGui.qLineCount++;
// Gather up all the previous lines, append the current one
// and stuff it into the control
%text = "<spush><font:Arial:16>";
for( %line = 0; %line < LoadingGui.qLineCount - 1; %line++ )
%text = %text @ LoadingGui.qLine[%line] @ " ";
%text = %text @ LoadingGui.qLine[%line] @ "<spop>";
}
//------------------------------------------------------------------------------
function handleLoadInfoDoneMessage( %msgType, %msgString )
{
// This will get called after the last description line is sent.
}
//------------------------------------------------------------------------------
function handleLoadFailedMessage( %msgType, %msgString )
{
MessageBoxOK( "Mission Load Failed", %msgString NL "Press OK to return to the Main Menu", "disconnect();" );
}

View file

@ -0,0 +1,116 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Hook into the client update messages to maintain our player list and scores.
//-----------------------------------------------------------------------------
addMessageCallback('MsgClientJoin', handleClientJoin);
addMessageCallback('MsgClientDrop', handleClientDrop);
addMessageCallback('MsgClientScoreChanged', handleClientScoreChanged);
function handleClientJoin(%msgType, %msgString, %clientName, %clientId, %guid,
%score, %kills, %deaths, %isAI, %isAdmin, %isSuperAdmin)
{
PlayerListGui.update(%clientId, detag(%clientName), %isSuperAdmin, %isAdmin,
%isAI, %score, %kills, %deaths);
}
function handleClientDrop(%msgType, %msgString, %clientName, %clientId)
{
PlayerListGui.remove(%clientId);
}
function handleClientScoreChanged(%msgType, %msgString, %score, %kills, %deaths, %clientId)
{
PlayerListGui.updateScore(%clientId, %score, %kills, %deaths);
echo(" score:"@%score@" kills:"@%kills@" deaths:"@%deaths);
}
// ----------------------------------------------------------------------------
// GUI methods
// ----------------------------------------------------------------------------
function PlayerListGui::update(%this, %clientId, %name, %isSuperAdmin, %isAdmin, %isAI, %score, %kills, %deaths)
{
// Build the row to display. The name can have ML control tags, including
// color and font. Since we're not using an ML control here, we need to
// strip them off.
%tag = %isSuperAdmin ? "[Super]" :
(%isAdmin ? "[Admin]" :
(%isAI ? "[Bot]" :
""));
%text = StripMLControlChars(%name) SPC %tag TAB %score TAB %kills TAB %deaths;
// Update or add the player to the control
if (PlayerListGuiList.getRowNumById(%clientId) == -1)
PlayerListGuiList.addRow(%clientId, %text);
else
PlayerListGuiList.setRowById(%clientId, %text);
// Sorts by score
PlayerListGuiList.sortNumerical(1, false);
PlayerListGuiList.clearSelection();
}
function PlayerListGui::updateScore(%this, %clientId, %score, %kills, %deaths)
{
%text = PlayerListGuiList.getRowTextById(%clientId);
%text = setField(%text, 1, %score);
%text = setField(%text, 2, %kills);
%text = setField(%text, 3, %deaths);
PlayerListGuiList.setRowById(%clientId, %text);
PlayerListGuiList.sortNumerical(1, false);
PlayerListGuiList.clearSelection();
}
function PlayerListGui::remove(%this, %clientId)
{
PlayerListGuiList.removeRowById(%clientId);
}
function PlayerListGui::toggle(%this)
{
if (%this.isAwake())
Canvas.popDialog(%this);
else
Canvas.pushDialog(%this);
}
function PlayerListGui::clear(%this)
{
// Override to clear the list.
PlayerListGuiList.clear();
}
function PlayerListGui::zeroScores(%this)
{
for (%i = 0; %i < PlayerListGuiList.rowCount(); %i++)
{
%text = PlayerListGuiList.getRowText(%i);
%text = setField(%text, 1, "0");
%text = setField(%text, 2, "0");
%text = setField(%text, 3, "0");
PlayerListGuiList.setRowById(PlayerListGuiList.getRowId(%i), %text);
}
PlayerListGuiList.clearSelection();
}

View file

@ -0,0 +1,228 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
// Functions dealing with connecting to a server
//-----------------------------------------------------------------------------
// Server connection error
//-----------------------------------------------------------------------------
addMessageCallback( 'MsgConnectionError', handleConnectionErrorMessage );
function handleConnectionErrorMessage(%msgType, %msgString, %msgError)
{
// On connect the server transmits a message to display if there
// are any problems with the connection. Most connection errors
// are game version differences, so hopefully the server message
// will tell us where to get the latest version of the game.
$ServerConnectionErrorMessage = %msgError;
}
//----------------------------------------------------------------------------
// GameConnection client callbacks
//----------------------------------------------------------------------------
function GameConnection::initialControlSet(%this)
{
echo ("*** Initial Control Object");
// The first control object has been set by the server
// and we are now ready to go.
// first check if the editor is active
if (!isToolBuild() || !Editor::checkActiveLoadDone())
{
if (Canvas.getContent() != PlayGui.getId())
{
Canvas.setContent(PlayGui);
ControlsHelpDlg.toggle();
}
}
}
function GameConnection::onControlObjectChange(%this)
{
echo ("*** Control Object Changed");
// Reset the current FOV to match the new object
// and turn off any current zoom.
resetCurrentFOV();
turnOffZoom();
}
function GameConnection::setLagIcon(%this, %state)
{
if (%this.getAddress() $= "local")
return;
LagIcon.setVisible(%state $= "true");
}
function GameConnection::onFlash(%this, %state)
{
if (isObject(FlashFx))
{
if (%state)
{
FlashFx.enable();
}
else
{
FlashFx.disable();
}
}
}
// Called on the new connection object after connect() succeeds.
function GameConnection::onConnectionAccepted(%this)
{
// Called on the new connection object after connect() succeeds.
LagIcon.setVisible(false);
// Startup the physics world on the client before any
// datablocks and objects are ghosted over.
physicsInitWorld( "client" );
}
function GameConnection::onConnectionTimedOut(%this)
{
// Called when an established connection times out
disconnectedCleanup();
MessageBoxOK( "TIMED OUT", "The server connection has timed out.");
}
function GameConnection::onConnectionDropped(%this, %msg)
{
// Established connection was dropped by the server
disconnectedCleanup();
MessageBoxOK( "DISCONNECT", "The server has dropped the connection: " @ %msg);
}
function GameConnection::onConnectionError(%this, %msg)
{
// General connection error, usually raised by ghosted objects
// initialization problems, such as missing files. We'll display
// the server's connection error message.
disconnectedCleanup();
MessageBoxOK( "DISCONNECT", $ServerConnectionErrorMessage @ " (" @ %msg @ ")" );
}
//----------------------------------------------------------------------------
// Connection Failed Events
//----------------------------------------------------------------------------
function GameConnection::onConnectRequestRejected( %this, %msg )
{
switch$(%msg)
{
case "CR_INVALID_PROTOCOL_VERSION":
%error = "Incompatible protocol version: Your game version is not compatible with this server.";
case "CR_INVALID_CONNECT_PACKET":
%error = "Internal Error: badly formed network packet";
case "CR_YOUAREBANNED":
%error = "You are not allowed to play on this server.";
case "CR_SERVERFULL":
%error = "This server is full.";
case "CHR_PASSWORD":
// XXX Should put up a password-entry dialog.
if ($Client::Password $= "")
MessageBoxOK( "REJECTED", "That server requires a password.");
else {
$Client::Password = "";
MessageBoxOK( "REJECTED", "That password is incorrect.");
}
return;
case "CHR_PROTOCOL":
%error = "Incompatible protocol version: Your game version is not compatible with this server.";
case "CHR_CLASSCRC":
%error = "Incompatible game classes: Your game version is not compatible with this server.";
case "CHR_INVALID_CHALLENGE_PACKET":
%error = "Internal Error: Invalid server response packet";
default:
%error = "Connection error. Please try another server. Error code: (" @ %msg @ ")";
}
disconnectedCleanup();
MessageBoxOK( "REJECTED", %error);
}
function GameConnection::onConnectRequestTimedOut(%this)
{
disconnectedCleanup();
MessageBoxOK( "TIMED OUT", "Your connection to the server timed out." );
}
//-----------------------------------------------------------------------------
// Disconnect
//-----------------------------------------------------------------------------
function disconnect()
{
// We need to stop the client side simulation
// else physics resources will not cleanup properly.
physicsStopSimulation( "client" );
// Delete the connection if it's still there.
if (isObject(ServerConnection))
ServerConnection.delete();
disconnectedCleanup();
// Call destroyServer in case we're hosting
destroyServer();
}
function disconnectedCleanup()
{
// End mission, if it's running.
if( $Client::missionRunning )
clientEndMission();
// Disable mission lighting if it's going, this is here
// in case we're disconnected while the mission is loading.
$lightingMission = false;
$sceneLighting::terminateLighting = true;
// Clear misc script stuff
HudMessageVector.clear();
//
LagIcon.setVisible(false);
PlayerListGui.clear();
// Clear all print messages
clientCmdclearBottomPrint();
clientCmdClearCenterPrint();
// Back to the launch screen
if (isObject( MainMenuGui ))
Canvas.setContent( MainMenuGui );
else if (isObject( UnifiedMainMenuGui ))
Canvas.setContent( UnifiedMainMenuGui );
// We can now delete the client physics simulation.
physicsDestroyWorld( "client" );
}

View file

@ -0,0 +1,25 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
//*****************************************************************************
// Shaders ( For Custom Materials )
//*****************************************************************************

View file

@ -0,0 +1,80 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// PlayGui is the main TSControl through which the game is viewed.
// The PlayGui also contains the hud controls.
//-----------------------------------------------------------------------------
function PlayGui::onWake(%this)
{
// Turn off any shell sounds...
// sfxStop( ... );
$enableDirectInput = "1";
activateDirectInput();
// Message hud dialog
if ( isObject( MainChatHud ) )
{
Canvas.pushDialog( MainChatHud );
chatHud.attach(HudMessageVector);
}
// just update the action map here
moveMap.push();
// hack city - these controls are floating around and need to be clamped
if ( isFunction( "refreshCenterTextCtrl" ) )
schedule(0, 0, "refreshCenterTextCtrl");
if ( isFunction( "refreshBottomTextCtrl" ) )
schedule(0, 0, "refreshBottomTextCtrl");
}
function PlayGui::onSleep(%this)
{
if ( isObject( MainChatHud ) )
Canvas.popDialog( MainChatHud );
// pop the keymaps
moveMap.pop();
}
function PlayGui::clearHud( %this )
{
Canvas.popDialog( MainChatHud );
while ( %this.getCount() > 0 )
%this.getObject( 0 ).delete();
}
//-----------------------------------------------------------------------------
function refreshBottomTextCtrl()
{
BottomPrintText.position = "0 0";
}
function refreshCenterTextCtrl()
{
CenterPrintText.position = "0 0";
}

View file

@ -0,0 +1,149 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// StartupGui is the splash screen that initially shows when the game is loaded
//-----------------------------------------------------------------------------
function loadStartup()
{
// The index of the current splash screen
$StartupIdx = 0;
// A list of the splash screens and logos
// to cycle through. Note that they have to
// be in consecutive numerical order
StartupGui.bitmap0 = "art/gui/background";
StartupGui.logo0 = "art/gui/Torque-3D-logo";
StartupGui.logoPos0 = "178 251";
StartupGui.logoExtent0 = "443 139";
// Call the next() function to set our firt
// splash screen
StartupGui.next();
// Play our startup sound
//SFXPlayOnce(AudioGui, "art/sound/gui/startup");//SFXPlay(startsnd);
}
function StartupGui::click(%this)
{
%this.done = true;
%this.onDone();
}
function StartupGui::next(%this)
{
// Set us to a blank screen while we load the next one
Canvas.setContent(BlankGui);
// Set our bitmap and reset the done variable
%this.setBitmap(getVariable(%this @ ".bitmap" @ $StartupIdx));
%this.done = false;
// If we have a logo then set it
if (isObject(%this->StartupLogo))
{
if (getVariable(%this @ ".logo" @ $StartupIdx) !$= "")
{
%this->StartupLogo.setBitmap(getVariable(%this @ ".logo" @ $StartupIdx));
if (getVariable(%this @ ".logoPos" @ $StartupIdx) !$= "")
{
%logoPosX = getWord(getVariable(%this @ ".logoPos" @ $StartupIdx), 0);
%logoPosY = getWord(getVariable(%this @ ".logoPos" @ $StartupIdx), 1);
%this->StartupLogo.setPosition(%logoPosX, %logoPosY);
}
if (getVariable(%this @ ".logoExtent" @ $StartupIdx) !$= "")
%this->StartupLogo.setExtent(getVariable(%this @ ".logoExtent" @ $StartupIdx));
%this->StartupLogo.setVisible(true);
}
else
%this->StartupLogo.setVisible(false);
}
// If we have a secondary logo then set it
if (isObject(%this->StartupLogoSecondary))
{
if (getVariable(%this @ ".seclogo" @ $StartupIdx) !$= "")
{
%this->StartupLogoSecondary.setBitmap(getVariable(%this @ ".seclogo" @ $StartupIdx));
if (getVariable(%this @ ".seclogoPos" @ $StartupIdx) !$= "")
{
%logoPosX = getWord(getVariable(%this @ ".seclogoPos" @ $StartupIdx), 0);
%logoPosY = getWord(getVariable(%this @ ".seclogoPos" @ $StartupIdx), 1);
%this->StartupLogoSecondary.setPosition(%logoPosX, %logoPosY);
}
if (getVariable(%this @ ".seclogoExtent" @ $StartupIdx) !$= "")
%this->StartupLogoSecondary.setExtent(getVariable(%this @ ".seclogoExtent" @ $StartupIdx));
%this->StartupLogoSecondary.setVisible(true);
}
else
%this->StartupLogoSecondary.setVisible(false);
}
// Increment our screen index for the next screen
$StartupIdx++;
// Set the Canvas to our newly updated GuiFadeinBitmapCtrl
Canvas.setContent(%this);
}
function StartupGui::onDone(%this)
{
// If we have been tagged as done decide if we need
// to end or cycle to the next one
if (%this.done)
{
// See if we have a valid bitmap for the next screen
if (getVariable(%this @ ".bitmap" @ $StartupIdx) $= "")
{
// Clear our data and load the main menu
%this.done = true;
// NOTE: Don't ever ever delete yourself during a callback from C++.
//
// Deleting the whole gui itself seems a bit excessive, what if we want
// to return to the startup gui at a later time? Any bitmaps set on
// the controls should be unloaded automatically if the control is not
// awake, if this is not the case then that's what needs to be fixed.
//%this.delete();
//BlankGui.delete();
//flushTextureCache();
loadMainMenu();
}
else
{
// We do have a bitmap so cycle to it
%this.next();
}
}
}

View file

@ -0,0 +1,142 @@
//-----------------------------------------------------------------------------
// 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 core script base
loadDir("core"); // Should be loaded at a higher level, but for now leave -- SRZ 11/29/07
//-----------------------------------------------------------------------------
// Package overrides to initialize the mod.
package fps {
function displayHelp() {
Parent::displayHelp();
error(
"Fps Mod options:\n"@
" -dedicated Start as dedicated server\n"@
" -connect <address> For non-dedicated: Connect to a game at <address>\n" @
" -mission <filename> For dedicated: Load the mission\n"
);
}
function parseArgs()
{
// Call the parent
Parent::parseArgs();
// Arguments, which override everything else.
for (%i = 1; %i < $Game::argc ; %i++)
{
%arg = $Game::argv[%i];
%nextArg = $Game::argv[%i+1];
%hasNextArg = $Game::argc - %i > 1;
switch$ (%arg)
{
//--------------------
case "-dedicated":
$Server::Dedicated = true;
enableWinConsole(true);
$argUsed[%i]++;
//--------------------
case "-mission":
$argUsed[%i]++;
if (%hasNextArg) {
$missionArg = %nextArg;
$argUsed[%i+1]++;
%i++;
}
else
error("Error: Missing Command Line argument. Usage: -mission <filename>");
//--------------------
case "-connect":
$argUsed[%i]++;
if (%hasNextArg) {
$JoinGameAddress = %nextArg;
$argUsed[%i+1]++;
%i++;
}
else
error("Error: Missing Command Line argument. Usage: -connect <ip_address>");
}
}
}
function onStart()
{
// The core does initialization which requires some of
// the preferences to loaded... so do that first.
exec( "./client/defaults.cs" );
exec( "./server/defaults.cs" );
Parent::onStart();
echo("\n--------- Initializing Directory: scripts ---------");
// Load the scripts that start it all...
exec("./client/init.cs");
exec("./server/init.cs");
// Init the physics plugin.
physicsInit();
// Start up the audio system.
sfxStartup();
// Server gets loaded for all sessions, since clients
// can host in-game servers.
initServer();
// Start up in either client, or dedicated server mode
if ($Server::Dedicated)
initDedicated();
else
initClient();
}
function onExit()
{
// Ensure that we are disconnected and/or the server is destroyed.
// This prevents crashes due to the SceneGraph being deleted before
// the objects it contains.
if ($Server::Dedicated)
destroyServer();
else
disconnect();
// Destroy the physics plugin.
physicsDestroy();
echo("Exporting client prefs");
export("$pref::*", "./client/prefs.cs", False);
echo("Exporting server prefs");
export("$Pref::Server::*", "./server/prefs.cs", False);
BanList::Export("./server/banlist.cs");
Parent::onExit();
}
}; // package fps
// Activate the game package.
activatePackage(fps);

View 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;
}

View 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;
}

View 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);
}

View 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);
}

View 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" );
}

View 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);
}

File diff suppressed because it is too large Load diff

View 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);
}

View 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);
*/
}

View 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;
}

View 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)");
}

View 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.
}

View 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;
}

View 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);
}

View 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);
}

View 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 );
}

View 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);
}
}
}

View 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;
}

View 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.

View 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.
}

View 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!");
}

View 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);
}

View 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);
}

View 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);
}

View 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;
}

View 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);
}

View 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]);
}
}