603 lines
16 KiB
C++
603 lines
16 KiB
C++
|
|
#include "../../idlib/precompiled.h"
|
|
#pragma hdrstop
|
|
|
|
#include "../Game_local.h"
|
|
#include "../vehicle/Vehicle.h"
|
|
|
|
//
|
|
class rvMonsterConvoyGround : public idAI {
|
|
public:
|
|
|
|
CLASS_PROTOTYPE( rvMonsterConvoyGround );
|
|
|
|
rvMonsterConvoyGround ( void );
|
|
|
|
void Spawn ( void );
|
|
void InitSpawnArgsVariables ( void );
|
|
void Save ( idSaveGame *savefile ) const;
|
|
void Restore ( idRestoreGame *savefile );
|
|
|
|
virtual void Postthink ( void );
|
|
virtual bool Pain ( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location );
|
|
virtual bool CheckPainActions ( void );
|
|
|
|
virtual bool CanTurn ( void ) const;
|
|
virtual bool CanMove ( void ) const;
|
|
virtual void Damage ( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location );
|
|
virtual void AdjustHealthByDamage ( int inDamage );
|
|
|
|
virtual void GetDebugInfo ( debugInfoProc_t proc, void* userData );
|
|
|
|
protected:
|
|
|
|
int shots;
|
|
int minShots;
|
|
int maxShots;
|
|
bool isOpen;
|
|
bool vehicleCollision;
|
|
float moveCurrentAnimRate;
|
|
float moveAnimRateMin;
|
|
float moveAnimRateRange;
|
|
float moveAccelRate;
|
|
bool onGround;
|
|
idVec3 oldOrigin;
|
|
idVec3 lastPainDir;
|
|
|
|
rvAIAction actionBlasterAttack;
|
|
|
|
virtual bool CheckActions ( void );
|
|
virtual int FilterTactical ( int availableTactical );
|
|
|
|
virtual const char* GetIdleAnimName ( void );
|
|
|
|
virtual void OnDeath ( void );
|
|
|
|
private:
|
|
|
|
// General states
|
|
stateResult_t State_Fall ( const stateParms_t& parms );
|
|
|
|
// Legs States
|
|
stateResult_t State_Legs_Move ( const stateParms_t& parms );
|
|
|
|
// Torso States
|
|
stateResult_t State_Torso_BlasterAttack ( const stateParms_t& parms );
|
|
stateResult_t State_Torso_Open ( const stateParms_t& parms );
|
|
stateResult_t State_Torso_Close ( const stateParms_t& parms );
|
|
stateResult_t State_Torso_Pain ( const stateParms_t& parms );
|
|
|
|
CLASS_STATES_PROTOTYPE ( rvMonsterConvoyGround );
|
|
};
|
|
|
|
CLASS_DECLARATION( idAI, rvMonsterConvoyGround )
|
|
END_CLASS
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::rvMonsterConvoyGround
|
|
================
|
|
*/
|
|
rvMonsterConvoyGround::rvMonsterConvoyGround ( ) {
|
|
shots = 0;
|
|
isOpen = false;
|
|
vehicleCollision = false;
|
|
moveCurrentAnimRate = 1.0f;
|
|
}
|
|
|
|
void rvMonsterConvoyGround::InitSpawnArgsVariables ( void )
|
|
{
|
|
minShots = spawnArgs.GetInt ( "minShots" );
|
|
maxShots = spawnArgs.GetInt ( "maxShots" );
|
|
moveAccelRate = spawnArgs.GetFloat ( "moveAccelRate", ".1" );
|
|
moveAnimRateMin = spawnArgs.GetFloat ( "moveMinAnimRate", "1" );
|
|
moveAnimRateRange = spawnArgs.GetFloat ( "moveMaxAnimRate", "10" ) - moveAnimRateMin;
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::Spawn
|
|
================
|
|
*/
|
|
void rvMonsterConvoyGround::Spawn ( void ) {
|
|
actionBlasterAttack.Init ( spawnArgs, "action_blasterAttack", "Torso_BlasterAttack", AIACTIONF_ATTACK );
|
|
|
|
InitSpawnArgsVariables();
|
|
|
|
aifl.disableLook = true;
|
|
|
|
onGround = true;
|
|
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::Prethink
|
|
================
|
|
*/
|
|
void rvMonsterConvoyGround::Postthink ( void ) {
|
|
/* FIXME
|
|
if ( onGround && !physicsObj.HasGroundContacts ( ) ) {
|
|
onGround = false;
|
|
InterruptState ( "State_Fall" );
|
|
}
|
|
*/
|
|
|
|
idAI::Postthink ( );
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::Save
|
|
================
|
|
*/
|
|
bool rvMonsterConvoyGround::Pain ( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
|
|
lastPainDir = dir;
|
|
return idAI::Pain ( inflictor, attacker, damage, dir, location );
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::Save
|
|
================
|
|
*/
|
|
void rvMonsterConvoyGround::Save ( idSaveGame *savefile ) const {
|
|
savefile->WriteInt ( shots );
|
|
//minShots and maxShots are set in the Restore
|
|
savefile->WriteBool ( isOpen );
|
|
savefile->WriteBool ( vehicleCollision );
|
|
savefile->WriteBool ( onGround );
|
|
|
|
savefile->WriteFloat ( moveCurrentAnimRate );
|
|
savefile->WriteVec3 ( oldOrigin );
|
|
savefile->WriteVec3 ( lastPainDir );
|
|
|
|
actionBlasterAttack.Save ( savefile );
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::Restore
|
|
================
|
|
*/
|
|
void rvMonsterConvoyGround::Restore ( idRestoreGame *savefile ) {
|
|
savefile->ReadInt ( shots );
|
|
savefile->ReadBool ( isOpen );
|
|
savefile->ReadBool ( vehicleCollision );
|
|
savefile->ReadBool ( onGround );
|
|
|
|
savefile->ReadFloat ( moveCurrentAnimRate );
|
|
savefile->ReadVec3 ( oldOrigin );
|
|
savefile->ReadVec3 ( lastPainDir );
|
|
|
|
actionBlasterAttack.Restore ( savefile );
|
|
|
|
InitSpawnArgsVariables();
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::CanMove
|
|
================
|
|
*/
|
|
bool rvMonsterConvoyGround::CanMove ( void ) const {
|
|
if ( isOpen ) {
|
|
return false;
|
|
}
|
|
return idAI::CanMove ( );
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::CanTurn
|
|
================
|
|
*/
|
|
bool rvMonsterConvoyGround::CanTurn ( void ) const {
|
|
if ( isOpen ) {
|
|
return false;
|
|
}
|
|
return idAI::CanTurn ( );
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::OnDeath
|
|
================
|
|
*/
|
|
void rvMonsterConvoyGround::OnDeath ( void ) {
|
|
idVec3 fxOrg;
|
|
idVec3 up;
|
|
idMat3 fxAxis;
|
|
|
|
//center it
|
|
fxOrg = GetPhysics()->GetCenterMass();
|
|
|
|
//point it up
|
|
up.Set( 0, 0, 1 );
|
|
fxAxis = up.ToMat3();
|
|
|
|
//if we can play it at the joint, do that
|
|
jointHandle_t axisJoint = animator.GetJointHandle ( "axis" );
|
|
if ( axisJoint != INVALID_JOINT ) {
|
|
idMat3 junk;
|
|
animator.GetJointLocalTransform( axisJoint, gameLocal.GetTime(), fxOrg, junk );
|
|
fxOrg = renderEntity.origin + (fxOrg*renderEntity.axis);
|
|
}
|
|
|
|
gameLocal.PlayEffect ( spawnArgs, "fx_death", fxOrg, fxAxis );
|
|
idAI::OnDeath ( );
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::AdjustHealthByDamage
|
|
================
|
|
*/
|
|
void rvMonsterConvoyGround::AdjustHealthByDamage ( int damage ) {
|
|
if ( isOpen || vehicleCollision ) {
|
|
idAI::AdjustHealthByDamage ( damage );
|
|
} else {
|
|
PlayEffect ( "fx_shieldHit", animator.GetJointHandle ( "axis" ) );
|
|
}
|
|
}
|
|
|
|
void rvMonsterConvoyGround::Damage ( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location )
|
|
{
|
|
vehicleCollision = false;
|
|
const idDict *damageDef = gameLocal.FindEntityDefDict( damageDefName, false );
|
|
if ( damageDef && damageDef->GetBool( "vehicle_collision" ) ) {
|
|
vehicleCollision = true;
|
|
}
|
|
|
|
idAI::Damage( inflictor, attacker, dir, damageDefName, damageScale, location );
|
|
}
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::Spawn
|
|
================
|
|
*/
|
|
bool rvMonsterConvoyGround::CheckActions ( void ) {
|
|
if ( isOpen ) {
|
|
if ( move.fl.moving ) {
|
|
/*
|
|
|| !CheckAction_RangedAttack( &actionBlasterAttack, -1 )
|
|
|| enemy.range > actionBlasterAttack.maxRange
|
|
|| enemy.range < actionBlasterAttack.minRange
|
|
|| (!move.fl.moving && (gameLocal.GetTime()-move.startTime) > 3000 ) ) {
|
|
*/
|
|
StartSound( "snd_prepare", SND_CHANNEL_ANY, 0, 0, 0 );
|
|
PerformAction ( "Torso_Close", 4, true );
|
|
return true;
|
|
}
|
|
|
|
if ( PerformAction ( &actionBlasterAttack, (checkAction_t)&idAI::CheckAction_RangedAttack, &actionTimerRangedAttack ) ) {
|
|
return true;
|
|
}
|
|
} else {
|
|
// Open up if we have stopped and have an enemy
|
|
if ( !move.fl.moving && physicsObj.HasGroundContacts ( ) && enemy.ent && legsAnim.IsIdle ( ) && CheckTactical ( AITACTICAL_RANGED ) ) {
|
|
StartSound( "snd_prepare", SND_CHANNEL_ANY, 0, 0, 0 );
|
|
PerformAction ( "Torso_Open", 4, true );
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return idAI::CheckActions ( );
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::CheckPainActions
|
|
================
|
|
*/
|
|
bool rvMonsterConvoyGround::CheckPainActions ( void ) {
|
|
if ( isOpen ) {
|
|
return false;
|
|
}
|
|
|
|
return idAI::CheckPainActions ( );
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::GetIdleAnimName
|
|
================
|
|
*/
|
|
const char* rvMonsterConvoyGround::GetIdleAnimName ( void ) {
|
|
// Start idle animation
|
|
if ( isOpen ) {
|
|
return "idle_open";
|
|
}
|
|
return "idle";
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::FilterTactical
|
|
================
|
|
*/
|
|
int rvMonsterConvoyGround::FilterTactical ( int availableTactical ) {
|
|
return idAI::FilterTactical ( availableTactical );
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
rvMonsterConvoyGround::GetDebugInfo
|
|
=====================
|
|
*/
|
|
void rvMonsterConvoyGround::GetDebugInfo ( debugInfoProc_t proc, void* userData ) {
|
|
// Base class first
|
|
idAI::GetDebugInfo ( proc, userData );
|
|
|
|
proc ( "idAI", "action_blasterAttack", aiActionStatusString[actionBlasterAttack.status], userData );
|
|
|
|
proc ( "rvMonsterConvoyGround", "moveAnimRate", va("%g", moveCurrentAnimRate ), userData );
|
|
proc ( "rvMonsterConvoyGround", "isOpen", isOpen ? "true" : "false", userData );
|
|
}
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
States
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
CLASS_STATES_DECLARATION ( rvMonsterConvoyGround )
|
|
STATE ( "State_Fall", rvMonsterConvoyGround::State_Fall )
|
|
STATE ( "Torso_Open", rvMonsterConvoyGround::State_Torso_Open )
|
|
STATE ( "Torso_Close", rvMonsterConvoyGround::State_Torso_Close )
|
|
STATE ( "Torso_BlasterAttack", rvMonsterConvoyGround::State_Torso_BlasterAttack )
|
|
STATE ( "Torso_Pain", rvMonsterConvoyGround::State_Torso_Pain )
|
|
|
|
STATE ( "Legs_Move", rvMonsterConvoyGround::State_Legs_Move )
|
|
END_CLASS_STATES
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::State_Fall
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterConvoyGround::State_Fall ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT, // Initialize fall stage
|
|
STAGE_WAITIMPACT, // Wait for the drop turret to hit the ground
|
|
STAGE_IMPACT, // Handle drop turret impact, switch to combat state
|
|
STAGE_WAITDONE,
|
|
STAGE_DONE
|
|
};
|
|
switch ( parms.stage ) {
|
|
case STAGE_INIT:
|
|
StopMove ( MOVE_STATUS_DONE );
|
|
StopAnimState ( ANIMCHANNEL_LEGS );
|
|
StopAnimState ( ANIMCHANNEL_TORSO );
|
|
StartSound ( "snd_falling", SND_CHANNEL_VOICE, 0, false, NULL );
|
|
PlayEffect ( "fx_droptrail", animator.GetJointHandle ( "origin" ), true );
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
PlayCycle ( ANIMCHANNEL_TORSO, "idle", 0 );
|
|
oldOrigin = physicsObj.GetOrigin ( );
|
|
return SRESULT_STAGE(STAGE_WAITIMPACT);
|
|
|
|
case STAGE_WAITIMPACT:
|
|
if ( physicsObj.HasGroundContacts ( ) ) {
|
|
return SRESULT_STAGE(STAGE_IMPACT);
|
|
}
|
|
return SRESULT_WAIT;
|
|
|
|
case STAGE_IMPACT:
|
|
StopSound ( SND_CHANNEL_VOICE, false );
|
|
StopEffect ( "fx_droptrail" );
|
|
PlayEffect ( "fx_landing", GetPhysics()->GetOrigin(), (-GetPhysics()->GetGravityNormal()).ToMat3() );
|
|
|
|
if ( (physicsObj.GetOrigin ( ) - oldOrigin).LengthSqr() > Square(128.0f) ) {
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "land", 0 );
|
|
return SRESULT_STAGE ( STAGE_WAITDONE );
|
|
}
|
|
return SRESULT_STAGE ( STAGE_DONE );
|
|
|
|
case STAGE_WAITDONE:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 4 ) ) {
|
|
return SRESULT_STAGE ( STAGE_DONE );
|
|
}
|
|
return SRESULT_WAIT;
|
|
|
|
case STAGE_DONE:
|
|
onGround = true;
|
|
SetAnimState ( ANIMCHANNEL_LEGS, "Legs_Idle" );
|
|
SetAnimState ( ANIMCHANNEL_TORSO, "Torso_Idle" );
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_ERROR;
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::State_Torso_BlasterAttack
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterConvoyGround::State_Torso_BlasterAttack ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_ATTACK,
|
|
STAGE_WAIT
|
|
};
|
|
switch ( parms.stage ) {
|
|
case STAGE_INIT:
|
|
shots = (gameLocal.random.RandomInt ( maxShots - minShots ) + minShots) * combat.aggressiveScale;
|
|
return SRESULT_STAGE ( STAGE_ATTACK );
|
|
|
|
case STAGE_ATTACK:
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "range_attack", parms.blendFrames );
|
|
shots--;
|
|
return SRESULT_STAGE ( STAGE_WAIT );
|
|
|
|
case STAGE_WAIT:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 0 ) ) {
|
|
if ( --shots <= 0 || (IsEnemyVisible() && !enemy.fl.inFov) ) {
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_STAGE ( STAGE_ATTACK );
|
|
}
|
|
return SRESULT_WAIT;
|
|
}
|
|
return SRESULT_ERROR;
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::State_Torso_Open
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterConvoyGround::State_Torso_Open ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_WAIT,
|
|
};
|
|
|
|
switch ( parms.stage ) {
|
|
case STAGE_INIT:
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "extend_legs", parms.blendFrames );
|
|
isOpen = true;
|
|
aifl.disableLook = false;
|
|
return SRESULT_STAGE ( STAGE_WAIT );
|
|
|
|
case STAGE_WAIT:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, parms.blendFrames ) ) {
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
}
|
|
return SRESULT_ERROR;
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::State_Torso_Close
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterConvoyGround::State_Torso_Close ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_WAIT,
|
|
};
|
|
|
|
switch ( parms.stage ) {
|
|
case STAGE_INIT:
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, "retract_legs", parms.blendFrames );
|
|
return SRESULT_STAGE ( STAGE_WAIT );
|
|
|
|
case STAGE_WAIT:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, 0 ) ) {
|
|
isOpen = false;
|
|
aifl.disableLook = true;
|
|
ForceTacticalUpdate();
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
|
|
}
|
|
return SRESULT_ERROR;
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::State_Torso_Pain
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterConvoyGround::State_Torso_Pain ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_START,
|
|
STAGE_END
|
|
};
|
|
|
|
switch ( parms.stage ) {
|
|
case STAGE_START:
|
|
// Force the orientation to the direction we got hit from so the animation looks correct
|
|
OverrideFlag ( AIFLAGOVERRIDE_NOTURN, true );
|
|
TurnToward ( physicsObj.GetOrigin() - lastPainDir * 128.0f );
|
|
move.current_yaw = move.ideal_yaw;
|
|
|
|
// Just in case the pain anim wasnt set before we got here.
|
|
if ( !painAnim.Length ( ) ) {
|
|
painAnim = "pain";
|
|
}
|
|
|
|
DisableAnimState ( ANIMCHANNEL_LEGS );
|
|
PlayAnim ( ANIMCHANNEL_TORSO, painAnim, parms.blendFrames );
|
|
return SRESULT_STAGE ( STAGE_END );
|
|
|
|
case STAGE_END:
|
|
if ( AnimDone ( ANIMCHANNEL_TORSO, parms.blendFrames ) ) {
|
|
return SRESULT_DONE;
|
|
}
|
|
return SRESULT_WAIT;
|
|
}
|
|
return SRESULT_ERROR;
|
|
}
|
|
|
|
/*
|
|
================
|
|
rvMonsterConvoyGround::State_Legs_Move
|
|
================
|
|
*/
|
|
stateResult_t rvMonsterConvoyGround::State_Legs_Move ( const stateParms_t& parms ) {
|
|
enum {
|
|
STAGE_INIT,
|
|
STAGE_MOVE
|
|
};
|
|
switch ( parms.stage ) {
|
|
case STAGE_INIT:
|
|
move.fl.allowAnimMove = true;
|
|
move.fl.allowPrevAnimMove = false;
|
|
move.fl.running = true;
|
|
move.currentDirection = MOVEDIR_FORWARD;
|
|
// TODO: Looks like current anim rate never gets reset, so they do not correctly accelerate from a stop
|
|
// unfortunately, adding this change (with a decent acceleration factor) caused them to do lots of
|
|
// not-so-good looking short moves.
|
|
// moveCurrentAnimRate = 0;
|
|
|
|
oldOrigin = physicsObj.GetOrigin ( );
|
|
PlayCycle ( ANIMCHANNEL_LEGS, "run", 0 );
|
|
StartSound( "snd_move", SND_CHANNEL_BODY3, 0, false, NULL );
|
|
|
|
return SRESULT_STAGE ( STAGE_MOVE );
|
|
|
|
case STAGE_MOVE:
|
|
|
|
// If not moving forward just go back to idle
|
|
if ( !move.fl.moving || !CanMove() ) {
|
|
StopSound( SND_CHANNEL_BODY3, 0 );
|
|
PostAnimState ( ANIMCHANNEL_LEGS, "Legs_Idle", 0 );
|
|
return SRESULT_DONE;
|
|
}
|
|
|
|
// If on the ground update the animation rate based on the normal of the ground plane
|
|
if ( !ai_debugHelpers.GetBool ( ) && physicsObj.HasGroundContacts ( ) ) {
|
|
float rate;
|
|
idVec3 dir;
|
|
|
|
dir = (physicsObj.GetOrigin ( ) - oldOrigin);
|
|
|
|
if ( DistanceTo ( move.moveDest ) < move.walkRange ) {
|
|
rate = moveAnimRateMin;
|
|
} else if ( dir.Normalize ( ) > 0.0f ) {
|
|
rate = idMath::ClampFloat ( -0.7f, 0.7f, physicsObj.GetGravityNormal ( ) * dir ) / 0.7f;
|
|
rate = moveAnimRateMin + moveAnimRateRange * (1.0f + rate) / 2.0f;
|
|
} else {
|
|
rate = moveAnimRateMin + moveAnimRateRange * 0.5f;
|
|
}
|
|
moveCurrentAnimRate += ((rate - moveCurrentAnimRate) * moveAccelRate);
|
|
|
|
animator.CurrentAnim ( ANIMCHANNEL_LEGS )->SetPlaybackRate ( gameLocal.time, moveCurrentAnimRate );
|
|
}
|
|
|
|
oldOrigin = physicsObj.GetOrigin ( );
|
|
|
|
return SRESULT_WAIT;
|
|
}
|
|
|
|
return SRESULT_ERROR;
|
|
}
|
|
|