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