Torque3D Documentation / _generateds / proximityMine.cpp

proximityMine.cpp

Engine/source/T3D/proximityMine.cpp

More...

Public Functions

ConsoleDocClass(ProximityMine , "@brief A simple proximity <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mine.\n\n</a>" "Proximity mines can be deployed using the world editor or thrown by an " "in-game object. Once armed, any <a href="/coding/class/classplayer/">Player</a> or <a href="/coding/class/classvehicle/">Vehicle</a> object that moves within " "the mine 's trigger area will cause it <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">explode.\n\n</a>" " Internally, the <a href="/coding/class/classproximitymine/">ProximityMine</a> object transitions through the following <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">states:\n</a>" "< ol >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Thrown</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >:Mine has been thrown, but has not yet attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> surface</li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Deployed</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >:Mine has attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> surface but is not yet armed. Start " "playing the #armingSound and< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >armed</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > sequence.</li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Armed</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >:Mine is armed and will trigger <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classvehicle/">Vehicle</a> or <a href="/coding/class/classplayer/">Player</a> object moves " "within the trigger area.</li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Triggered</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >:Mine has been triggered and will explode soon. Invoke the " "onTriggered callback, and start playing the #triggerSound and< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >triggered</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > " "sequence.</li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Exploded</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >:Mine has exploded and will be deleted on the server shortly. " "Invoke the onExplode callback on the server and generate the explosion effects " "on the client.</li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "</ol >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" " @note Proximity mines with the #static field set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true will start in the " "< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Armed</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > state. Use this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> mines placed with the <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a81f4537631c9ab219ec74de554483adc">World</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editor.\n\n</a>" "The shape used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the mine may optionally define the following <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">sequences:\n</a>" "< dl >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< dt >armed</dt >< dd >Sequence <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> play when the mine is deployed, but before " "it becomes active and triggerable(#armingDelay should be set appropriately).</dd >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< dt >triggered</dt >< dd >Sequence <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> play when the mine is triggered)
ConsoleDocClass(ProximityMineData , "@brief Stores common properties <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ProximityMine.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ProximityMine\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">gameObjects\n</a>" )
DefineEngineMethod(ProximityMine , explode , void , () , "@brief Manually cause the mine <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">explode.\n\n</a>" )
IMPLEMENT_CALLBACK(ProximityMineData , onExplode , void , (ProximityMine *obj, Point3F pos) , (obj, pos) , "Callback invoked when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classproximitymine/">ProximityMine</a> is about <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">explode.\n\n</a>" "@param obj The <a href="/coding/class/classproximitymine/">ProximityMine</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object\n</a>" "@param pos The position of the mine <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">explosion\n</a>" "@note This callback is only invoked on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ProximityMine\n</a>" )
IMPLEMENT_CALLBACK(ProximityMineData , onTriggered , void , (ProximityMine *obj, SceneObject *target) , (obj, target) , "Callback invoked when an object triggers the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ProximityMine.\n\n</a>" "@param obj The <a href="/coding/class/classproximitymine/">ProximityMine</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object\n</a>" "@param target The object that triggered the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mine\n</a>" "@note This callback is only invoked on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ProximityMine\n</a>" )

Detailed Description

Public Variables

S32 gAutoDeleteTicks 
const U32 sTriggerCollisionMask 

Public Functions

ConsoleDocClass(ProximityMine , "@brief A simple proximity <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mine.\n\n</a>" "Proximity mines can be deployed using the world editor or thrown by an " "in-game object. Once armed, any <a href="/coding/class/classplayer/">Player</a> or <a href="/coding/class/classvehicle/">Vehicle</a> object that moves within " "the mine 's trigger area will cause it <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">explode.\n\n</a>" " Internally, the <a href="/coding/class/classproximitymine/">ProximityMine</a> object transitions through the following <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">states:\n</a>" "< ol >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Thrown</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >:Mine has been thrown, but has not yet attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> surface</li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Deployed</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >:Mine has attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> surface but is not yet armed. Start " "playing the #armingSound and< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >armed</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > sequence.</li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Armed</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >:Mine is armed and will trigger <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classvehicle/">Vehicle</a> or <a href="/coding/class/classplayer/">Player</a> object moves " "within the trigger area.</li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Triggered</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >:Mine has been triggered and will explode soon. Invoke the " "onTriggered callback, and start playing the #triggerSound and< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> >triggered</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1acb559820d9ca11295b4500f179ef6392">i</a> > " "sequence.</li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< li >< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Exploded</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >:Mine has exploded and will be deleted on the server shortly. " "Invoke the onExplode callback on the server and generate the explosion effects " "on the client.</li >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "</ol >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" " @note Proximity mines with the #static field set <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> true will start in the " "< <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> >Armed</<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a91b64995742fd30063314f12340b4b5a">b</a> > state. Use this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> mines placed with the <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a81f4537631c9ab219ec74de554483adc">World</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editor.\n\n</a>" "The shape used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the mine may optionally define the following <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">sequences:\n</a>" "< dl >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< dt >armed</dt >< dd >Sequence <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> play when the mine is deployed, but before " "it becomes active and triggerable(#armingDelay should be set appropriately).</dd >\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "< dt >triggered</dt >< dd >Sequence <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> play when the mine is triggered)

ConsoleDocClass(ProximityMineData , "@brief Stores common properties <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ProximityMine.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ProximityMine\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">gameObjects\n</a>" )

DefineEngineMethod(ProximityMine , explode , void , () , "@brief Manually cause the mine <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">explode.\n\n</a>" )

IMPLEMENT_CALLBACK(ProximityMineData , onExplode , void , (ProximityMine *obj, Point3F pos) , (obj, pos) , "Callback invoked when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classproximitymine/">ProximityMine</a> is about <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">explode.\n\n</a>" "@param obj The <a href="/coding/class/classproximitymine/">ProximityMine</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object\n</a>" "@param pos The position of the mine <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">explosion\n</a>" "@note This callback is only invoked on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ProximityMine\n</a>" )

IMPLEMENT_CALLBACK(ProximityMineData , onTriggered , void , (ProximityMine *obj, SceneObject *target) , (obj, target) , "Callback invoked when an object triggers the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ProximityMine.\n\n</a>" "@param obj The <a href="/coding/class/classproximitymine/">ProximityMine</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object\n</a>" "@param target The object that triggered the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mine\n</a>" "@note This callback is only invoked on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ProximityMine\n</a>" )

IMPLEMENT_CO_DATABLOCK_V1(ProximityMineData )

IMPLEMENT_CO_NETOBJECT_V1(ProximityMine )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25
 26#include "core/stream/bitStream.h"
 27#include "console/console.h"
 28#include "console/consoleTypes.h"
 29#include "console/engineAPI.h"
 30#include "sim/netConnection.h"
 31#include "math/mMath.h"
 32#include "math/mathIO.h"
 33#include "math/mathUtils.h"
 34#include "gfx/gfxTransformSaver.h"
 35#include "gfx/gfxDrawUtil.h"
 36#include "sfx/sfxTrack.h"
 37#include "sfx/sfxTypes.h"
 38#include "sfx/sfxSystem.h"
 39#include "ts/tsShapeInstance.h"
 40#include "T3D/fx/explosion.h"
 41#include "T3D/proximityMine.h"
 42#include "T3D/physics/physicsBody.h"
 43
 44const U32 sTriggerCollisionMask = ( VehicleObjectType | PlayerObjectType );
 45
 46static S32 gAutoDeleteTicks = 16;   // Provides about half a second for all clients to be updated
 47                                    // before a mine is deleted on the server.
 48
 49//----------------------------------------------------------------------------
 50
 51IMPLEMENT_CO_DATABLOCK_V1( ProximityMineData );
 52
 53ConsoleDocClass( ProximityMineData,
 54   "@brief Stores common properties for a ProximityMine.\n\n"
 55   "@see ProximityMine\n"
 56   "@ingroup gameObjects\n"
 57);
 58
 59IMPLEMENT_CALLBACK( ProximityMineData, onTriggered, void, ( ProximityMine* obj, SceneObject *target ),( obj, target ),
 60   "Callback invoked when an object triggers the ProximityMine.\n\n"
 61   "@param obj The ProximityMine object\n"
 62   "@param target The object that triggered the mine\n"
 63   "@note This callback is only invoked on the server.\n"
 64   "@see ProximityMine\n"
 65);
 66
 67IMPLEMENT_CALLBACK( ProximityMineData, onExplode, void, ( ProximityMine* obj, Point3F pos ),( obj, pos ),
 68   "Callback invoked when a ProximityMine is about to explode.\n\n"
 69   "@param obj The ProximityMine object\n"
 70   "@param pos The position of the mine explosion\n"
 71   "@note This callback is only invoked on the server.\n"
 72   "@see ProximityMine\n"
 73);
 74
 75ProximityMineData::ProximityMineData()
 76 : armingDelay( 0 ),
 77   armingSequence( -1 ),
 78   armingSound( NULL ),
 79   triggerRadius( 5.0f ),
 80   triggerSpeed( 1.0f ),
 81   autoTriggerDelay( 0 ),
 82   triggerOnOwner( false ),
 83   triggerDelay( 0 ),
 84   triggerSequence( -1 ),
 85   triggerSound( NULL ),
 86   explosionOffset( 0.05f )
 87{
 88}
 89
 90void ProximityMineData::initPersistFields()
 91{
 92   addGroup( "Arming" );
 93   addField( "armingDelay", TypeF32, Offset(armingDelay, ProximityMineData), 
 94      "Delay (in seconds) from when the mine is placed to when it becomes active." );
 95   addField( "armingSound", TypeSFXTrackName, Offset(armingSound, ProximityMineData),
 96      "Sound to play when the mine is armed (starts at the same time as "
 97      "the <i>armed</i> sequence if defined)." );
 98   endGroup( "Arming" );
 99
100   addGroup( "Triggering" );
101   addField( "autoTriggerDelay", TypeF32, Offset(autoTriggerDelay, ProximityMineData),
102      "@brief Delay (in seconds) from arming until the mine automatically "
103      "triggers and explodes, even if no object has entered the trigger area.\n\n"
104      "Set to 0 to disable." );
105   addField( "triggerOnOwner", TypeBool, Offset(triggerOnOwner, ProximityMineData),
106      "@brief Controls whether the mine can be triggered by the object that owns it.\n\n"
107      "For example, a player could deploy mines that are only dangerous to other "
108      "players and not himself." );
109   addField( "triggerRadius", TypeF32, Offset(triggerRadius, ProximityMineData),
110      "Distance at which an activated mine will detect other objects and explode." );
111   addField( "triggerSpeed", TypeF32, Offset(triggerSpeed, ProximityMineData),
112      "Speed above which moving objects within the trigger radius will trigger the mine" );
113   addField( "triggerDelay", TypeF32, Offset(triggerDelay, ProximityMineData),
114      "Delay (in seconds) from when the mine is triggered until it explodes." );
115   addField( "triggerSound", TypeSFXTrackName, Offset(triggerSound, ProximityMineData),
116      "Sound to play when the mine is triggered (starts at the same time as "
117      "the <i>triggered</i> sequence if defined)." );
118   endGroup( "Triggering" );
119
120   addGroup( "Explosion" );
121   addField( "explosionOffset", TypeF32, Offset(explosionOffset, ProximityMineData),
122      "@brief Offset from the mine's origin where the explosion emanates from."
123      "Sometimes a thrown mine may be slightly sunk into the ground.  This can be just "
124      "enough to cause the explosion to occur under the ground, especially on flat "
125      "ground, which can end up blocking the explosion.  This offset along the mine's "
126      "'up' normal allows you to raise the explosion origin to a better height.");
127   endGroup( "Explosion" );
128
129   Parent::initPersistFields();
130}
131
132bool ProximityMineData::preload( bool server, String& errorStr )
133{
134   if ( Parent::preload( server, errorStr ) == false )
135      return false;
136
137   if ( !server )
138   {
139      // Resolve sounds
140      String sfxErrorStr;
141      if( !sfxResolve( &armingSound, sfxErrorStr ) )
142         Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid packet: %s", sfxErrorStr.c_str() );
143      if( !sfxResolve( &triggerSound, sfxErrorStr ) )
144         Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid packet: %s", sfxErrorStr.c_str() );
145   }
146
147   if ( mShape )
148   {
149      // Lookup animation sequences
150      armingSequence = mShape->findSequence( "armed" );
151      triggerSequence = mShape->findSequence( "triggered" );
152   }
153
154   return true;
155}
156
157void ProximityMineData::packData( BitStream* stream )
158{
159   Parent::packData( stream );
160
161   stream->write( armingDelay );
162   sfxWrite( stream, armingSound );
163
164   stream->write( autoTriggerDelay );
165   stream->writeFlag( triggerOnOwner );
166   stream->write( triggerRadius );
167   stream->write( triggerSpeed );
168   stream->write( triggerDelay );
169   sfxWrite( stream, triggerSound );
170}
171
172void ProximityMineData::unpackData( BitStream* stream )
173{
174   Parent::unpackData(stream);
175
176   stream->read( &armingDelay );
177   sfxRead( stream, &armingSound );
178
179   stream->read( &autoTriggerDelay );
180   triggerOnOwner = stream->readFlag();
181   stream->read( &triggerRadius );
182   stream->read( &triggerSpeed );
183   stream->read( &triggerDelay );
184   sfxRead( stream, &triggerSound );
185}
186
187//----------------------------------------------------------------------------
188
189IMPLEMENT_CO_NETOBJECT_V1( ProximityMine );
190
191ConsoleDocClass( ProximityMine,
192   "@brief A simple proximity mine.\n\n"
193
194   "Proximity mines can be deployed using the world editor or thrown by an "
195   "in-game object. Once armed, any Player or Vehicle object that moves within "
196   "the mine's trigger area will cause it to explode.\n\n"
197
198   "Internally, the ProximityMine object transitions through the following states:\n"
199   "<ol>\n"
200   "  <li><b>Thrown</b>: Mine has been thrown, but has not yet attached to a surface</li>\n"
201   "  <li><b>Deployed</b>: Mine has attached to a surface but is not yet armed. Start "
202      "playing the #armingSound and <i>armed</i> sequence.</li>\n"
203   "  <li><b>Armed</b>: Mine is armed and will trigger if a Vehicle or Player object moves "
204      "within the trigger area.</li>\n"
205   "  <li><b>Triggered</b>: Mine has been triggered and will explode soon. Invoke the "
206      "onTriggered callback, and start playing the #triggerSound and <i>triggered</i> "
207      "sequence.</li>\n"
208   "  <li><b>Exploded</b>: Mine has exploded and will be deleted on the server shortly. "
209      "Invoke the onExplode callback on the server and generate the explosion effects "
210      "on the client.</li>\n"
211   "</ol>\n\n"
212
213   "@note Proximity mines with the #static field set to true will start in the "
214   "<b>Armed</b> state. Use this for mines placed with the World Editor.\n\n"
215
216   "The shape used for the mine may optionally define the following sequences:\n"
217   "<dl>\n"
218   "  <dt>armed</dt><dd>Sequence to play when the mine is deployed, but before "
219   "it becomes active and triggerable (#armingDelay should be set appropriately).</dd>\n"
220   "  <dt>triggered</dt><dd>Sequence to play when the mine is triggered, just "
221   "before it explodes (#triggerDelay should be set appropriately).<dd>\n"
222   "</dl>\n\n"
223
224   "@tsexample\n"
225   "datablock ProximityMineData( SimpleMine )\n"
226   "{\n"
227   "   // ShapeBaseData fields\n"
228   "   category = \"Weapon\";\n"
229   "   shapeFile = \"art/shapes/weapons/misc/proximityMine.dts\";\n\n"
230
231   "   // ItemData fields\n"
232   "   sticky = true;\n\n"
233
234   "   // ProximityMineData fields\n"
235   "   armingDelay = 0.5;\n"
236   "   armingSound = MineArmedSound;\n\n"
237
238   "   autoTriggerDelay = 0;\n"
239   "   triggerOnOwner = true;\n"
240   "   triggerRadius = 5.0;\n"
241   "   triggerSpeed = 1.0;\n"
242   "   triggerDelay = 0.5;\n"
243   "   triggerSound = MineTriggeredSound;\n"
244   "   explosion = RocketLauncherExplosion;\n\n"
245
246   "   // dynamic fields\n"
247   "   pickUpName = \"Proximity Mines\";\n"
248   "   maxInventory = 20;\n\n"
249
250   "   damageType = \"MineDamage\"; // type of damage applied to objects in radius\n"
251   "   radiusDamage = 30;           // amount of damage to apply to objects in radius\n"
252   "   damageRadius = 8;            // search radius to damage objects when exploding\n"
253   "   areaImpulse = 2000;          // magnitude of impulse to apply to objects in radius\n"
254   "};\n\n"
255
256   "function ProximityMineData::onTriggered( %this, %obj, %target )\n"
257   "{\n"
258   "   echo( %this.name SPC \"triggered by \" @ %target.getClassName() );\n"
259   "}\n\n"
260
261   "function ProximityMineData::onExplode( %this, %obj, %position )\n"
262   "{\n"
263   "   // Damage objects within the mine's damage radius\n"
264   "   if ( %this.damageRadius > 0 )\n"
265   "      radiusDamage( %obj.sourceObject, %position, %this.damageRadius, %this.radiusDamage, %this.damageType, %this.areaImpulse );\n"
266   "}\n\n"
267
268   "function ProximityMineData::damage( %this, %obj, %position, %source, %amount, %damageType )\n"
269   "{\n"
270   "   // Explode if any damage is applied to the mine\n"
271   "   %obj.schedule(50 + getRandom(50), explode);\n"
272   "}\n\n"
273
274   "%obj = new ProximityMine()\n"
275   "{\n"
276   "   dataBlock = SimpleMine;\n"
277   "};\n"
278   "@endtsexample\n\n"
279
280   "@see ProximityMineData\n"
281
282   "@ingroup gameObjects\n"
283);
284
285ProximityMine::ProximityMine()
286{
287   mTypeMask |= StaticShapeObjectType;
288   mDataBlock = 0;
289
290   mStickyCollisionPos.zero();
291
292   mOwner = NULL;
293
294   mState = Thrown;
295   mStateTimeout = 0;
296
297   mAnimThread = NULL;
298
299   // For the Item class
300   mSubclassItemHandlesScene = true;
301}
302
303ProximityMine::~ProximityMine()
304{
305}
306
307//----------------------------------------------------------------------------
308
309void ProximityMine::consoleInit()
310{
311   Parent::consoleInit();
312
313   Con::addVariable("$ProxMine::autoDeleteTicks", TypeS32, &gAutoDeleteTicks,
314      "@brief Number of ticks until an exploded mine is deleted on the server.\n\n"
315
316      "After a mine has exploded it remains in the server's scene graph for a time "
317      "to allow its exploded state to be passed along to each client.  This variable "
318      "controls how long a mine remains before it is deleted.  Any client that has not "
319      "received the exploded state by then (perhaps due to lag) will not see any "
320      "explosion produced by the mine.\n\n"
321
322      "@ingroup GameObjects");
323}
324
325//----------------------------------------------------------------------------
326
327bool ProximityMine::onAdd()
328{
329   if ( !Parent::onAdd() || !mDataBlock )
330      return false;
331
332   addToScene();
333
334   if (isServerObject())
335      scriptOnAdd();
336
337   if ( mStatic )
338   {
339      // static mines are armed immediately
340      mState = Deployed;
341      mStateTimeout = 0;
342   }
343
344   return true;
345}
346
347bool ProximityMine::onNewDataBlock( GameBaseData* dptr, bool reload )
348{
349   mDataBlock = dynamic_cast<ProximityMineData*>( dptr );
350   if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) )
351      return false;
352
353   scriptOnNewDataBlock();
354   return true;
355}
356
357void ProximityMine::onRemove()
358{
359   scriptOnRemove();
360   removeFromScene();
361
362   Parent::onRemove();
363}
364
365//----------------------------------------------------------------------------
366
367void ProximityMine::setTransform( const MatrixF& mat )
368{
369   ShapeBase::setTransform( mat );   // Skip Item::setTransform as it restricts rotation to the Z axis
370
371   if ( !mStatic )
372   {
373      mAtRest = false;
374      mAtRestCounter = 0;
375   }
376
377   if ( mPhysicsRep )
378      mPhysicsRep->setTransform( getTransform() );
379
380   setMaskBits( Item::RotationMask | Item::PositionMask | Item::NoWarpMask );
381}
382
383void ProximityMine::setDeployedPos( const Point3F& pos, const Point3F& normal )
384{
385   // Align to deployed surface normal
386   MatrixF mat( true );
387   MathUtils::getMatrixFromUpVector( normal, &mat );
388   mat.setPosition( pos + normal * mObjBox.minExtents.z );
389
390   mDelta.pos = pos;
391   mDelta.posVec.set(0, 0, 0);
392
393   ShapeBase::setTransform( mat );
394   if ( mPhysicsRep )
395      mPhysicsRep->setTransform( getTransform() );
396
397   setMaskBits( DeployedMask );
398}
399
400void ProximityMine::processTick( const Move* move )
401{
402   Parent::processTick( move );
403
404   // Process state machine
405   mStateTimeout -= TickSec;
406
407   State lastState = NumStates;;
408   while ( mState != lastState )
409   {
410      lastState = mState;
411      switch ( mState )
412      {
413         case Thrown:
414            if ( mAtRest )
415            {
416               mState = Deployed;
417               mStateTimeout = mDataBlock->armingDelay;
418
419               // Get deployed position if mine was not stuck to another surface
420               if ( mStickyCollisionPos.isZero() )
421               {
422                  mObjToWorld.getColumn( 2, &mStickyCollisionNormal );
423                  mObjToWorld.getColumn( 3, &mStickyCollisionPos );
424               }
425               setDeployedPos( mStickyCollisionPos, mStickyCollisionNormal );
426
427               if ( mDataBlock->armingSequence != -1 )
428               {
429                  mAnimThread = mShapeInstance->addThread();
430                  mShapeInstance->setSequence( mAnimThread, mDataBlock->armingSequence, 0.0f );
431               }
432               if ( mDataBlock->armingSound )
433                  SFX->playOnce( mDataBlock->armingSound, &getRenderTransform() );
434            }
435            break;
436
437         case Deployed:
438            // Timeout into Armed state
439            if ( mStateTimeout <= 0 )
440            {
441               mState = Armed;
442               mStateTimeout = mDataBlock->autoTriggerDelay ? mDataBlock->autoTriggerDelay : F32_MAX;
443            }
444            break;
445
446         case Armed:
447         {
448            // Check for objects within the trigger area
449            Box3F triggerBox( mDataBlock->triggerRadius * 2 );
450            triggerBox.setCenter( getTransform().getPosition() );
451
452            SimpleQueryList sql;
453            getContainer()->findObjects( triggerBox, sTriggerCollisionMask,
454               SimpleQueryList::insertionCallback, &sql );
455            for ( S32 i = 0; i < sql.mList.size(); i++ )
456            {
457               // Detect movement in the trigger area
458               if ( ( sql.mList[i] == mOwner && !mDataBlock->triggerOnOwner ) ||
459                    sql.mList[i]->getVelocity().len() < mDataBlock->triggerSpeed )
460                  continue;
461
462               // Mine has been triggered
463               mShapeInstance->destroyThread( mAnimThread );
464               mAnimThread = NULL;
465
466               mState = Triggered;
467               mStateTimeout = mDataBlock->triggerDelay;
468               if ( mDataBlock->triggerSequence != -1 )
469               {
470                  mAnimThread = mShapeInstance->addThread();
471                  mShapeInstance->setSequence( mAnimThread, mDataBlock->triggerSequence, 0.0f );
472               }
473               if ( mDataBlock->triggerSound )
474                  SFX->playOnce( mDataBlock->triggerSound, &getRenderTransform() );
475
476               if ( isServerObject() )
477                  mDataBlock->onTriggered_callback( this, sql.mList[0] );
478            }
479            break;
480         }
481
482         case Triggered:
483            // Timeout into exploded state
484            if ( mStateTimeout <= 0 )
485            {
486               explode();
487            }
488            break;
489
490         case Exploded:
491            // Mine's delete themselves on the server after exploding
492            if ( isServerObject() && ( mStateTimeout <= 0 ) )
493            {
494               deleteObject();
495               return;
496            }
497            break;
498      }
499   }
500}
501
502//----------------------------------------------------------------------------
503
504void ProximityMine::explode()
505{
506   // Make sure we don't explode twice
507   if ( mState == Exploded )
508   {
509      return;
510   }
511
512   mState = Exploded;
513   mStateTimeout = TickSec * gAutoDeleteTicks;  // auto-delete on server N ticks after exploding
514
515   // Move the explosion point slightly off the surface to avoid problems with radius damage
516   Point3F normal = getTransform().getUpVector();
517   Point3F explodePos = getTransform().getPosition() + normal * mDataBlock->explosionOffset;
518
519   if ( isServerObject() )
520   {
521      // Do what the server needs to do, damage the surrounding objects, etc.
522      mDataBlock->onExplode_callback( this, explodePos );
523      setMaskBits( ExplosionMask );
524
525      // Wait till the timeout to self delete. This gives the server object time
526      // to get ghosted to the client
527   } 
528   else 
529   {
530      // Client just plays the explosion effect at the right place
531      if ( mDataBlock->explosion )
532      {
533         Explosion *pExplosion = new Explosion;
534         pExplosion->onNewDataBlock( mDataBlock->explosion, false );
535
536         MatrixF xform( true );
537         xform.setPosition( explodePos );
538         pExplosion->setTransform( xform );
539         pExplosion->setInitialState( explodePos, normal );
540         pExplosion->setCollideType( sTriggerCollisionMask );
541         if ( pExplosion->registerObject() == false )
542         {
543            Con::errorf( ConsoleLogEntry::General, "ProximityMine(%s)::explode: couldn't register explosion",
544                         mDataBlock->getName() );
545            delete pExplosion;
546         }
547      }
548   }
549}
550
551void ProximityMine::advanceTime( F32 dt )
552{
553   Parent::advanceTime( dt );
554
555   if ( mAnimThread )
556      mShapeInstance->advancePos( dt, mAnimThread );
557}
558
559//----------------------------------------------------------------------------
560
561U32 ProximityMine::packUpdate( NetConnection* connection, U32 mask, BitStream* stream )
562{
563   // Handle rotation ourselves (so it is not locked to the Z axis like for Items)
564   U32 retMask = Parent::packUpdate( connection, mask & (~<a href="/coding/class/classitem/#classitem_1aaacac713d02fa2d54fcca2662866de3fa5f0360bea9b5df7a11abb6ab328e4a92">Item::RotationMask</a>), stream );
565
566   if ( stream->writeFlag( mask & Item::RotationMask ) )
567   {
568      QuatF rot( mObjToWorld );
569      mathWrite( *stream, rot );
570   }
571
572   if ( stream->writeFlag( !mStatic && ( mask & DeployedMask ) && ( mState > Thrown ) ) )
573   {
574      mathWrite( *stream, mStickyCollisionPos );
575      mathWrite( *stream, mStickyCollisionNormal );
576   }
577
578   stream->writeFlag( ( mask & ExplosionMask ) && ( mState == Exploded ) );
579
580   return retMask;
581}
582
583void ProximityMine::unpackUpdate( NetConnection* connection, BitStream* stream )
584{
585   Parent::unpackUpdate( connection, stream );
586
587   // Item::RotationMask
588   if ( stream->readFlag() )
589   {
590      QuatF rot;
591      mathRead( *stream, &rot );
592
593      Point3F pos = mObjToWorld.getPosition();
594      rot.setMatrix( &mObjToWorld );
595      mObjToWorld.setPosition( pos );
596   }
597
598   // !mStatic && ( mask & DeployedMask ) && ( mState > Thrown )
599   if ( stream->readFlag() )
600   {
601      mathRead( *stream, &mStickyCollisionPos );
602      mathRead( *stream, &mStickyCollisionNormal );
603
604      mAtRest = true;
605
606      setDeployedPos( mStickyCollisionPos, mStickyCollisionNormal );
607   }
608
609   // ( mask & ExplosionMask ) && ( mState == Exploded )
610   if ( stream->readFlag() )
611   {
612      // start the explosion visuals on the client
613      explode();
614   }
615
616   if ( mStatic && mState <= Deployed )
617   {
618      // static mines are armed immediately
619      mState = Deployed;
620      mStateTimeout = 0;
621   }
622}
623
624//----------------------------------------------------------------------------
625
626void ProximityMine::prepRenderImage( SceneRenderState* state )
627{
628   // Don't render the mine if exploded
629   if ( mState == Exploded )
630      return;
631
632   // Use ShapeBase to render the 3D shape
633   Parent::prepRenderImage( state );
634
635   // Add a custom render instance to draw the trigger area
636   if ( !state->isShadowPass() )
637   {
638      ObjectRenderInst* ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
639      ri->renderDelegate.bind( this, &ProximityMine::renderObject );
640      ri->type = RenderPassManager::RIT_ObjectTranslucent;
641      ri->translucentSort = true;
642      ri->defaultKey = 1;
643      state->getRenderPass()->addInst( ri );
644   }
645}
646
647void ProximityMine::renderObject( ObjectRenderInst* ri,
648                                  SceneRenderState* state,
649                                  BaseMatInstance* overrideMat )
650{
651   if ( overrideMat )
652      return;
653/*
654   // Render the trigger area
655   if ( mState == Armed || mState == Triggered )
656   {
657      const LinearColorF drawColor(1, 0, 0, 0.05f);
658      if ( drawColor.alpha > 0 )
659      {
660         GFXStateBlockDesc desc;
661         desc.setZReadWrite( true, false );
662         desc.setBlend( true );
663
664         GFXTransformSaver saver;
665
666         MatrixF mat = getRenderTransform();
667         mat.scale( getScale() );
668
669         GFX->getDrawUtil()->drawSphere(  desc, mDataBlock->triggerRadius, mat.getPosition(),
670                                          drawColor, true, false, &mat );
671      }
672   }
673*/
674}
675
676//----------------------------------------------------------------------------
677
678DefineEngineMethod( ProximityMine, explode, void, (),,
679   "@brief Manually cause the mine to explode.\n\n")
680{
681   object->explode();
682}
683