mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-25 15:14:46 +00:00
313 lines
9.5 KiB
C#
313 lines
9.5 KiB
C#
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// 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.
|
|
}
|