openmohaa/code/game/vehicleturret.cpp
2023-04-29 21:56:38 +02:00

735 lines
12 KiB
C++

/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// vehicleturret.cpp: Vehicle Turret.
//
#include "g_phys.h"
#include "vehicleturret.h"
#include "player.h"
#include "explosion.h"
#include "gibs.h"
#include "scriptexception.h"
Event EV_VehicleTurretGun_SetBaseEntity
(
"setbaseentity",
EV_DEFAULT,
"e",
"base_entity",
"Sets the base entity to take its orientation from."
);
Event EV_VehicleTurretGun_RemoveOnDeath
(
"removeondeath",
EV_DEFAULT,
"i",
"removeondeath",
"If set to a non-zero value, vehicles will not be removed when they die"
);
Event EV_VehicleTurretGun_SetCollisionEntity
(
"setcollisionentity",
EV_DEFAULT,
"e",
"entity",
"Sets the Collision Entity."
);
Event EV_VehicleTurretGun_Lock
(
"lock",
EV_DEFAULT,
NULL,
NULL,
"The Turret can not be used."
);
Event EV_VehicleTurretGun_Unlock
(
"unlock",
EV_DEFAULT,
NULL,
NULL,
"The Turret Can be used."
);
Event EV_VehicleTurretGun_SoundSet
(
"SoundSet",
EV_DEFAULT,
"s",
"soundset",
"Sets the Sound Set to use."
);
Event EV_VehicleTurretGun_CollisionEntitySetter
(
"collisionent",
EV_DEFAULT,
"s",
"entity",
"Sets the Collision Entity",
EV_SETTER
);
Event EV_VehicleTurretGun_CollisionEntityGetter
(
"collisionent",
EV_DEFAULT,
NULL,
NULL,
"Gets the Collision Entity",
EV_GETTER
);
CLASS_DECLARATION( TurretGun, VehicleTurretGun, NULL )
{
{ &EV_Item_DropToFloor, &VehicleTurretGun::PlaceTurret },
{ &EV_Item_Pickup, NULL },
{ &EV_Touch, NULL },
{ &EV_Use, &VehicleTurretGun::TurretUsed },
{ &EV_VehicleTurretGun_SetBaseEntity, &VehicleTurretGun::SetBaseEntity },
{ &EV_VehicleTurretGun_RemoveOnDeath, &VehicleTurretGun::EventRemoveOnDeath },
{ &EV_VehicleTurretGun_SetCollisionEntity, &VehicleTurretGun::EventSetCollisionModel },
{ &EV_Damage, &VehicleTurretGun::EventDamage },
{ &EV_Killed, &VehicleTurretGun::EventKilled },
{ &EV_Turret_TurnSpeed, &VehicleTurretGun::EventTurnSpeed },
{ &EV_VehicleTurretGun_Lock, &VehicleTurretGun::EventLock },
{ &EV_VehicleTurretGun_Unlock, &VehicleTurretGun::EventUnlock },
{ &EV_VehicleTurretGun_SoundSet, &VehicleTurretGun::SetSoundSet },
{ &EV_VehicleTurretGun_CollisionEntitySetter, &VehicleTurretGun::EventSetCollisionModel },
{ &EV_VehicleTurretGun_CollisionEntityGetter, &VehicleTurretGun::EventGetCollisionModel },
{ NULL, NULL }
};
// FIXME
VehicleTurretGun::VehicleTurretGun()
{
entflags |= EF_VEHICLETURRET;
if( LoadingSavegame )
{
return;
}
edict->s.eType = ET_MODELANIM;
setRespawn( false );
respondto = TRIGGER_PLAYERS | TRIGGER_MONSTERS;
edict->clipmask = MASK_VEHICLETURRET;
m_iIdleHitCount = 0;
m_bUsable = true;
m_bPlayerUsable = true;
m_bRestable = false;
m_fIdlePitchSpeed = 0;
takedamage = DAMAGE_NO;
health = 100.0f;
max_health = 100.0f;
setSize( Vector( -16, -16, 0 ), Vector( 16, 16, 32 ) );
m_fTurnSpeed = 1001.0f;
m_fPitchUpCap = -45.0f;
m_fPitchDownCap = 45.0f;
m_fMaxYawOffset = 180.0f;
m_fUserDistance = 64.0f;
m_vIdleCheckOffset = Vector( -56, 0, 0 );
m_bBOIsSet = false;
m_iFiring = 0;
m_fFireToggleTime = 0;
m_pBaseEntity = NULL;
m_vLastBaseAngles = vec_zero;
m_vBaseAngles = vec_zero;
m_vBarrelPos = origin;
m_vLastBarrelPos = origin;
m_bUseRemoteControl = false;
m_pVehicleOwner = NULL;
m_bRemoveOnDeath = true;
m_eSoundState = ST_OFF;
m_bLocked = true;
m_fNextSoundState = level.time;
m_sSoundSet = "";
}
VehicleTurretGun::~VehicleTurretGun()
{
Unregister( STRING_ONTARGET );
if( m_pCollisionEntity )
{
m_pCollisionEntity->PostEvent( EV_Remove, 0 );
}
entflags &= ~EF_VEHICLETURRET;
}
void VehicleTurretGun::Think
(
void
)
{
// FIXME: stub
}
void VehicleTurretGun::SetBaseOrientation
(
float( *borientation )[ 3 ],
float *bangles
)
{
m_bBOIsSet = true;
VectorCopy( borientation[ 0 ], m_mBaseOrientation[ 0 ] );
VectorCopy( borientation[ 1 ], m_mBaseOrientation[ 1 ] );
VectorCopy( borientation[ 2 ], m_mBaseOrientation[ 2 ] );
m_vLastBaseAngles = m_vBaseAngles;
if( bangles )
{
m_vBaseAngles = bangles;
}
else
{
MatrixToEulerAngles( borientation,m_vBaseAngles );
}
flags |= FL_THINK;
}
void VehicleTurretGun::SetBaseEntity
(
Entity *e
)
{
m_pBaseEntity = e;
m_vLastBaseAngles = m_vBaseAngles;
if( e )
{
m_vBaseAngles = e->angles;
}
else
{
m_vBaseAngles = vec_zero;
}
flags |= FL_THINK;
}
void VehicleTurretGun::SetVehicleOwner
(
Entity *e
)
{
m_pVehicleOwner = e;
}
void VehicleTurretGun::SetRemoteOwner
(
Sentient *e
)
{
m_bUseRemoteControl = true;
m_pRemoteOwner = e;
}
void VehicleTurretGun::RemoteControl
(
usercmd_t *ucmd,
Sentient *owner
)
{
}
void VehicleTurretGun::CollisionCorrect
(
trace_t *pTr
)
{
}
void VehicleTurretGun::UpdateOrientation
(
bool bCollisionCheck
)
{
}
void VehicleTurretGun::UpdateSound
(
void
)
{
if( level.time < m_fNextSoundState )
{
return;
}
float fDiff = AngleSubtract( m_vTargetAngles[ 1 ], m_vLocalAngles[ 1 ] );
switch( m_eSoundState )
{
case ST_OFF:
StopLoopSound();
m_fNextSoundState = level.time;
if( fabs( fDiff ) > 0.5f )
{
m_eSoundState = ST_OFF_TRANS_IDLE;
}
break;
case ST_OFF_TRANS_IDLE:
m_eSoundState = ST_IDLE_TRANS_OFF;
m_fNextSoundState = level.time;
LoopSound( m_sSoundSet + "snd_move" );
break;
case ST_IDLE_TRANS_OFF:
m_fNextSoundState = level.time;
if( fabs( fDiff ) < 0.5f )
{
m_eSoundState = ST_IDLE;
}
LoopSound( m_sSoundSet + "snd_move" );
break;
case ST_IDLE:
m_eSoundState = ST_OFF;
m_fNextSoundState = level.time;
LoopSound( m_sSoundSet + "snd_move" );
break;
default:
// FIXME: default sound?
break;
}
}
void VehicleTurretGun::UpdateOwner
(
Sentient *pOwner
)
{
// FIXME: stub
STUB();
}
void VehicleTurretGun::SetBaseEntity
(
Event *ev
)
{
SetBaseEntity( ev->GetEntity( 1 ) );
}
void VehicleTurretGun::PlaceTurret
(
Event *ev
)
{
setSolidType( SOLID_BBOX );
edict->r.contents = CONTENTS_UNKNOWN2;
setMoveType( MOVETYPE_NONE );
showModel();
groundentity = NULL;
m_fStartYaw = angles[ 1 ];
flags |= FL_THINK;
m_vLastBaseAngles = angles;
m_vBaseAngles = angles;
if( m_vBaseAngles.length() != 0.0f )
{
AnglesToAxis( m_vBaseAngles, m_mBaseOrientation );
m_bBOIsSet = true;
}
m_iPitchBone = gi.Tag_NumForName( edict->tiki, "pitch" );
SetControllerTag( 0, m_iPitchBone );
m_iBarrelTag = gi.Tag_NumForName( edict->tiki, "tag_barrel" );
m_iEyeBone = gi.Tag_NumForName( edict->tiki, "eyebone" );
if( m_pRemoteOwner || owner )
{
if( m_pRemoteOwner )
UpdateOwner( m_pRemoteOwner );
else
UpdateOwner( owner );
}
}
void VehicleTurretGun::TurretBeginUsed
(
Sentient *pEnt
)
{
if( m_pVehicleOwner )
{
Vehicle *pVehicle = ( Vehicle * )m_pVehicleOwner.Pointer();
int slot = pVehicle->FindTurretSlotByEntity( this );
pVehicle->UpdateTurretSlot( slot );
m_vBaseAngles = m_pVehicleOwner->angles;
}
owner = pEnt;
edict->r.ownerNum = pEnt->entnum;
m_bHadOwner = true;
Sound( sPickupSound );
owner->SetViewAngles( m_vBaseAngles );
m_vUserViewAng = m_vBaseAngles;
m_vUserViewAng[ 0 ] = AngleNormalize180( m_vUserViewAng[ 0 ] );
m_vUserLastCmdAng = vec_zero;
setAngles( m_vBaseAngles );
if( owner->IsSubclassOfPlayer() )
{
Player *player = ( Player * )owner.Pointer();
player->EnterTurret( this );
if( !m_pUserCamera ) {
m_pUserCamera = new Camera;
}
player->SetCamera( m_pUserCamera, 0.0f );
m_pUserCamera->setAngles( m_vBaseAngles );
}
UpdateOwner( owner );
flags &= ~FL_THINK;
current_attachToTag = "";
ForceIdle();
CreateViewModel();
}
void VehicleTurretGun::TurretEndUsed
(
void
)
{
if( owner->IsSubclassOfPlayer() )
{
Player *player = ( Player * )owner.Pointer();
if( m_pUserCamera )
{
player->SetCamera( NULL, 0 );
player->ZoomOff();
m_pUserCamera->PostEvent( EV_Remove, 0 );
m_pUserCamera = NULL;
}
player->ExitTurret();
DeleteViewModel();
}
owner = NULL;
edict->r.ownerNum = ENTITYNUM_NONE;
m_fIdlePitchSpeed = 0;
m_iIdleHitCount = 0;
m_iFiring = 0;
}
void VehicleTurretGun::TurretUsed
(
Sentient *pEnt
)
{
if( owner )
{
if( owner == pEnt )
{
TurretEndUsed();
m_iFiring = 0;
}
}
else
{
TurretBeginUsed( pEnt );
}
}
void VehicleTurretGun::TurretUsed
(
Event *ev
)
{
Sentient *pEnt = ( Sentient *)ev->GetEntity( 1 );
if( !pEnt || !pEnt->IsSubclassOfSentient() )
{
return;
}
if( !m_bUsable || m_bLocked )
{
return;
}
if( pEnt->IsSubclassOfPlayer() && !m_bPlayerUsable )
{
return;
}
TurretUsed( pEnt );
}
void VehicleTurretGun::EventKilled
(
Event *ev
)
{
Entity *ent;
Entity *attacker;
deadflag = DEAD_DEAD;
Unregister( STRING_DEATH );
if( !m_bRemoveOnDeath )
{
return;
}
takedamage = DAMAGE_NO;
setSolidType( SOLID_NOT );
hideModel();
attacker = ev->GetEntity( 1 );
if( flags & FL_DIE_EXPLODE )
{
CreateExplosion( origin, 150 * edict->s.scale, this, this, this );
}
if( flags & FL_DIE_GIBS )
{
setSolidType( SOLID_NOT );
hideModel();
CreateGibs( this, -150, edict->s.scale, 3 );
}
if( *killtarget )
{
ent = NULL;
while( ( ent = ( Entity * )G_FindTarget( ent, killtarget ) ) != NULL )
{
ent->PostEvent( EV_Remove, 0 );
}
}
if( *target )
{
ent = NULL;
while( ( ent = ( Entity * )G_FindTarget( ent, target ) ) != NULL )
{
ent->ProcessEvent( EV_Activate );
}
}
PostEvent( EV_Remove, 0 );
}
void VehicleTurretGun::EventDamage
(
Event *ev
)
{
Event *event = new Event( ev );
if( owner )
{
owner->ProcessEvent( event );
return;
}
if( m_pVehicleOwner )
{
m_pVehicleOwner->ProcessEvent( event );
return;
}
if( !m_bUseRemoteControl )
{
DamageEvent( event );
return;
}
if( m_pRemoteOwner && m_pRemoteOwner->IsSubclassOfPlayer() )
{
Player *player = ( Player * )m_pRemoteOwner.Pointer();
if( player->m_pVehicle )
{
player->m_pVehicle->ProcessEvent( event );
return;
}
}
}
void VehicleTurretGun::EventRemoveOnDeath
(
Event *ev
)
{
m_bRemoveOnDeath = ev->GetBoolean( 1 );
}
void VehicleTurretGun::EventSetCollisionModel
(
Event *ev
)
{
Entity *pColEnt = ev->GetEntity( 1 );
if( !pColEnt )
{
ScriptError( "Trying to set a collision model with a NULL entity." );
}
if( m_pCollisionEntity )
{
m_pCollisionEntity->PostEvent( EV_Remove, EV_VEHICLE );
}
m_pCollisionEntity = new VehicleCollisionEntity( this );
m_pCollisionEntity->setModel( pColEnt->model );
if( !m_pCollisionEntity->model.length() || *m_pCollisionEntity->model != '*' )
{
// Re-post the event with the correct time
m_pCollisionEntity->CancelEventsOfType( EV_Remove );
m_pCollisionEntity->PostEvent( EV_Remove, EV_VEHICLE );
m_pCollisionEntity = NULL;
ScriptError( "Model for Entity not of a valid type. Must be B-Model." );
}
m_pCollisionEntity->setOrigin( origin );
m_pCollisionEntity->setAngles( angles );
}
void VehicleTurretGun::EventGetCollisionModel
(
Event *ev
)
{
ev->AddEntity( m_pCollisionEntity );
}
void VehicleTurretGun::EventTurnSpeed
(
Event *ev
)
{
TurnSpeed( ev->GetFloat( 1 ) );
}
void VehicleTurretGun::EventLock
(
Event *ev
)
{
Lock();
}
void VehicleTurretGun::EventUnlock
(
Event *ev
)
{
UnLock();
}
void VehicleTurretGun::SetSoundSet
(
Event *ev
)
{
m_sSoundSet = ev->GetString( 1 );
}
bool VehicleTurretGun::isLocked
(
void
)
{
return m_bLocked;
}
void VehicleTurretGun::Lock
(
void
)
{
m_bLocked = true;
}
void VehicleTurretGun::UnLock
(
void
)
{
m_bLocked = false;
}
bool VehicleTurretGun::UseRemoteControl
(
void
)
{
return m_bUseRemoteControl;
}
Sentient* VehicleTurretGun::GetRemoteOwner
(
void
)
{
return m_pRemoteOwner;
}