1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 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 3 of the License, or
- (at your option) any later version.
- Doom 3 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- /*
- Various utility objects and functions.
- */
- #include "../idlib/precompiled.h"
- #pragma hdrstop
- #include "Game_local.h"
- /*
- ===============================================================================
- idSpawnableEntity
- A simple, spawnable entity with a model and no functionable ability of it's own.
- For example, it can be used as a placeholder during development, for marking
- locations on maps for script, or for simple placed models without any behavior
- that can be bound to other entities. Should not be subclassed.
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idSpawnableEntity )
- END_CLASS
- /*
- ======================
- idSpawnableEntity::Spawn
- ======================
- */
- void idSpawnableEntity::Spawn() {
- // this just holds dict information
- }
- /*
- ===============================================================================
- idPlayerStart
- ===============================================================================
- */
- const idEventDef EV_TeleportStage( "<TeleportStage>", "e" );
- CLASS_DECLARATION( idEntity, idPlayerStart )
- EVENT( EV_Activate, idPlayerStart::Event_TeleportPlayer )
- EVENT( EV_TeleportStage, idPlayerStart::Event_TeleportStage )
- END_CLASS
- /*
- ===============
- idPlayerStart::idPlayerStart
- ================
- */
- idPlayerStart::idPlayerStart( void ) {
- teleportStage = 0;
- }
- /*
- ===============
- idPlayerStart::Spawn
- ================
- */
- void idPlayerStart::Spawn( void ) {
- teleportStage = 0;
- }
- /*
- ================
- idPlayerStart::Save
- ================
- */
- void idPlayerStart::Save( idSaveGame *savefile ) const {
- savefile->WriteInt( teleportStage );
- }
- /*
- ================
- idPlayerStart::Restore
- ================
- */
- void idPlayerStart::Restore( idRestoreGame *savefile ) {
- savefile->ReadInt( teleportStage );
- }
- /*
- ================
- idPlayerStart::ClientReceiveEvent
- ================
- */
- bool idPlayerStart::ClientReceiveEvent( int event, int time, const idBitMsg &msg ) {
- int entityNumber;
- switch( event ) {
- case EVENT_TELEPORTPLAYER: {
- entityNumber = msg.ReadBits( GENTITYNUM_BITS );
- idPlayer *player = static_cast<idPlayer *>( gameLocal.entities[entityNumber] );
- if ( player != NULL && player->IsType( idPlayer::Type ) ) {
- Event_TeleportPlayer( player );
- }
- return true;
- }
- default: {
- return idEntity::ClientReceiveEvent( event, time, msg );
- }
- }
- return false;
- }
- /*
- ===============
- idPlayerStart::Event_TeleportStage
- FIXME: add functionality to fx system ( could be done with player scripting too )
- ================
- */
- void idPlayerStart::Event_TeleportStage( idEntity *_player ) {
- idPlayer *player;
- if ( !_player->IsType( idPlayer::Type ) ) {
- common->Warning( "idPlayerStart::Event_TeleportStage: entity is not an idPlayer\n" );
- return;
- }
- player = static_cast<idPlayer*>(_player);
- float teleportDelay = spawnArgs.GetFloat( "teleportDelay" );
- switch ( teleportStage ) {
- case 0:
- player->playerView.Flash( colorWhite, 125 );
- player->SetInfluenceLevel( INFLUENCE_LEVEL3 );
- player->SetInfluenceView( spawnArgs.GetString( "mtr_teleportFx" ), NULL, 0.0f, NULL );
- gameSoundWorld->FadeSoundClasses( 0, -20.0f, teleportDelay );
- player->StartSound( "snd_teleport_start", SND_CHANNEL_BODY2, 0, false, NULL );
- teleportStage++;
- PostEventSec( &EV_TeleportStage, teleportDelay, player );
- break;
- case 1:
- gameSoundWorld->FadeSoundClasses( 0, 0.0f, 0.25f );
- teleportStage++;
- PostEventSec( &EV_TeleportStage, 0.25f, player );
- break;
- case 2:
- player->SetInfluenceView( NULL, NULL, 0.0f, NULL );
- TeleportPlayer( player );
- player->StopSound( SND_CHANNEL_BODY2, false );
- player->SetInfluenceLevel( INFLUENCE_NONE );
- teleportStage = 0;
- break;
- default:
- break;
- }
- }
- /*
- ===============
- idPlayerStart::TeleportPlayer
- ================
- */
- void idPlayerStart::TeleportPlayer( idPlayer *player ) {
- float pushVel = spawnArgs.GetFloat( "push", "300" );
- float f = spawnArgs.GetFloat( "visualEffect", "0" );
- const char *viewName = spawnArgs.GetString( "visualView", "" );
- idEntity *ent = viewName ? gameLocal.FindEntity( viewName ) : NULL;
- #ifdef _D3XP
- SetTimeState ts( player->timeGroup );
- #endif
- if ( f && ent ) {
- // place in private camera view for some time
- // the entity needs to teleport to where the camera view is to have the PVS right
- player->Teleport( ent->GetPhysics()->GetOrigin(), ang_zero, this );
- player->StartSound( "snd_teleport_enter", SND_CHANNEL_ANY, 0, false, NULL );
- player->SetPrivateCameraView( static_cast<idCamera*>(ent) );
- // the player entity knows where to spawn from the previous Teleport call
- if ( !gameLocal.isClient ) {
- player->PostEventSec( &EV_Player_ExitTeleporter, f );
- }
- } else {
- // direct to exit, Teleport will take care of the killbox
- player->Teleport( GetPhysics()->GetOrigin(), GetPhysics()->GetAxis().ToAngles(), NULL );
- // multiplayer hijacked this entity, so only push the player in multiplayer
- if ( gameLocal.isMultiplayer ) {
- player->GetPhysics()->SetLinearVelocity( GetPhysics()->GetAxis()[0] * pushVel );
- }
- }
- }
- /*
- ===============
- idPlayerStart::Event_TeleportPlayer
- ================
- */
- void idPlayerStart::Event_TeleportPlayer( idEntity *activator ) {
- idPlayer *player;
- if ( activator->IsType( idPlayer::Type ) ) {
- player = static_cast<idPlayer*>( activator );
- } else {
- player = gameLocal.GetLocalPlayer();
- }
- if ( player ) {
- if ( spawnArgs.GetBool( "visualFx" ) ) {
- teleportStage = 0;
- Event_TeleportStage( player );
- } else {
- if ( gameLocal.isServer ) {
- idBitMsg msg;
- byte msgBuf[MAX_EVENT_PARAM_SIZE];
- msg.Init( msgBuf, sizeof( msgBuf ) );
- msg.BeginWriting();
- msg.WriteBits( player->entityNumber, GENTITYNUM_BITS );
- ServerSendEvent( EVENT_TELEPORTPLAYER, &msg, false, -1 );
- }
- TeleportPlayer( player );
- }
- }
- }
- /*
- ===============================================================================
- idActivator
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idActivator )
- EVENT( EV_Activate, idActivator::Event_Activate )
- END_CLASS
- /*
- ===============
- idActivator::Save
- ================
- */
- void idActivator::Save( idSaveGame *savefile ) const {
- savefile->WriteBool( stay_on );
- }
- /*
- ===============
- idActivator::Restore
- ================
- */
- void idActivator::Restore( idRestoreGame *savefile ) {
- savefile->ReadBool( stay_on );
- if ( stay_on ) {
- BecomeActive( TH_THINK );
- }
- }
- /*
- ===============
- idActivator::Spawn
- ================
- */
- void idActivator::Spawn( void ) {
- bool start_off;
- spawnArgs.GetBool( "stay_on", "0", stay_on );
- spawnArgs.GetBool( "start_off", "0", start_off );
- GetPhysics()->SetClipBox( idBounds( vec3_origin ).Expand( 4 ), 1.0f );
- GetPhysics()->SetContents( 0 );
- if ( !start_off ) {
- BecomeActive( TH_THINK );
- }
- }
- /*
- ===============
- idActivator::Think
- ================
- */
- void idActivator::Think( void ) {
- RunPhysics();
- if ( thinkFlags & TH_THINK ) {
- if ( TouchTriggers() ) {
- if ( !stay_on ) {
- BecomeInactive( TH_THINK );
- }
- }
- }
- Present();
- }
- /*
- ===============
- idActivator::Activate
- ================
- */
- void idActivator::Event_Activate( idEntity *activator ) {
- if ( thinkFlags & TH_THINK ) {
- BecomeInactive( TH_THINK );
- } else {
- BecomeActive( TH_THINK );
- }
- }
- /*
- ===============================================================================
- idPathCorner
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idPathCorner )
- EVENT( AI_RandomPath, idPathCorner::Event_RandomPath )
- END_CLASS
- /*
- =====================
- idPathCorner::Spawn
- =====================
- */
- void idPathCorner::Spawn( void ) {
- }
- /*
- =====================
- idPathCorner::DrawDebugInfo
- =====================
- */
- void idPathCorner::DrawDebugInfo( void ) {
- idEntity *ent;
- idBounds bnds( idVec3( -4.0, -4.0f, -8.0f ), idVec3( 4.0, 4.0f, 64.0f ) );
- for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
- if ( !ent->IsType( idPathCorner::Type ) ) {
- continue;
- }
- idVec3 org = ent->GetPhysics()->GetOrigin();
- gameRenderWorld->DebugBounds( colorRed, bnds, org, 0 );
- }
- }
- /*
- ============
- idPathCorner::RandomPath
- ============
- */
- idPathCorner *idPathCorner::RandomPath( const idEntity *source, const idEntity *ignore ) {
- int i;
- int num;
- int which;
- idEntity *ent;
- idPathCorner *path[ MAX_GENTITIES ];
- num = 0;
- for( i = 0; i < source->targets.Num(); i++ ) {
- ent = source->targets[ i ].GetEntity();
- if ( ent && ( ent != ignore ) && ent->IsType( idPathCorner::Type ) ) {
- path[ num++ ] = static_cast<idPathCorner *>( ent );
- if ( num >= MAX_GENTITIES ) {
- break;
- }
- }
- }
- if ( !num ) {
- return NULL;
- }
- which = gameLocal.random.RandomInt( num );
- return path[ which ];
- }
- /*
- =====================
- idPathCorner::Event_RandomPath
- =====================
- */
- void idPathCorner::Event_RandomPath( void ) {
- idPathCorner *path;
- path = RandomPath( this, NULL );
- idThread::ReturnEntity( path );
- }
- /*
- ===============================================================================
- idDamagable
-
- ===============================================================================
- */
- const idEventDef EV_RestoreDamagable( "<RestoreDamagable>" );
- CLASS_DECLARATION( idEntity, idDamagable )
- EVENT( EV_Activate, idDamagable::Event_BecomeBroken )
- EVENT( EV_RestoreDamagable, idDamagable::Event_RestoreDamagable )
- END_CLASS
- /*
- ================
- idDamagable::idDamagable
- ================
- */
- idDamagable::idDamagable( void ) {
- count = 0;
- nextTriggerTime = 0;
- }
- /*
- ================
- idDamagable::Save
- ================
- */
- void idDamagable::Save( idSaveGame *savefile ) const {
- savefile->WriteInt( count );
- savefile->WriteInt( nextTriggerTime );
- }
- /*
- ================
- idDamagable::Restore
- ================
- */
- void idDamagable::Restore( idRestoreGame *savefile ) {
- savefile->ReadInt( count );
- savefile->ReadInt( nextTriggerTime );
- }
- /*
- ================
- idDamagable::Spawn
- ================
- */
- void idDamagable::Spawn( void ) {
- idStr broken;
- health = spawnArgs.GetInt( "health", "5" );
- spawnArgs.GetInt( "count", "1", count );
- nextTriggerTime = 0;
-
- // make sure the model gets cached
- spawnArgs.GetString( "broken", "", broken );
- if ( broken.Length() && !renderModelManager->CheckModel( broken ) ) {
- gameLocal.Error( "idDamagable '%s' at (%s): cannot load broken model '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), broken.c_str() );
- }
- fl.takedamage = true;
- GetPhysics()->SetContents( CONTENTS_SOLID );
- }
- /*
- ================
- idDamagable::BecomeBroken
- ================
- */
- void idDamagable::BecomeBroken( idEntity *activator ) {
- float forceState;
- int numStates;
- int cycle;
- float wait;
-
- if ( gameLocal.time < nextTriggerTime ) {
- return;
- }
- spawnArgs.GetFloat( "wait", "0.1", wait );
- nextTriggerTime = gameLocal.time + SEC2MS( wait );
- if ( count > 0 ) {
- count--;
- if ( !count ) {
- fl.takedamage = false;
- } else {
- health = spawnArgs.GetInt( "health", "5" );
- }
- }
- idStr broken;
- spawnArgs.GetString( "broken", "", broken );
- if ( broken.Length() ) {
- SetModel( broken );
- }
- // offset the start time of the shader to sync it to the gameLocal time
- renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( gameLocal.time );
- spawnArgs.GetInt( "numstates", "1", numStates );
- spawnArgs.GetInt( "cycle", "0", cycle );
- spawnArgs.GetFloat( "forcestate", "0", forceState );
- // set the state parm
- if ( cycle ) {
- renderEntity.shaderParms[ SHADERPARM_MODE ]++;
- if ( renderEntity.shaderParms[ SHADERPARM_MODE ] > numStates ) {
- renderEntity.shaderParms[ SHADERPARM_MODE ] = 0;
- }
- } else if ( forceState ) {
- renderEntity.shaderParms[ SHADERPARM_MODE ] = forceState;
- } else {
- renderEntity.shaderParms[ SHADERPARM_MODE ] = gameLocal.random.RandomInt( numStates ) + 1;
- }
- renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( gameLocal.time );
- ActivateTargets( activator );
- if ( spawnArgs.GetBool( "hideWhenBroken" ) ) {
- Hide();
- PostEventMS( &EV_RestoreDamagable, nextTriggerTime - gameLocal.time );
- BecomeActive( TH_THINK );
- }
- }
- /*
- ================
- idDamagable::Killed
- ================
- */
- void idDamagable::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
- if ( gameLocal.time < nextTriggerTime ) {
- health += damage;
- return;
- }
- BecomeBroken( attacker );
- }
- #ifdef _D3XP
- /*
- ================
- idDamagable::Hide
- ================
- */
- void idDamagable::Hide( void ) {
- idEntity::Hide();
- GetPhysics()->SetContents( 0 );
- }
- /*
- ================
- idDamagable::Show
- ================
- */
- void idDamagable::Show( void ) {
- idEntity::Show();
- GetPhysics()->SetContents( CONTENTS_SOLID );
- }
- #endif
- /*
- ================
- idDamagable::Event_BecomeBroken
- ================
- */
- void idDamagable::Event_BecomeBroken( idEntity *activator ) {
- BecomeBroken( activator );
- }
- /*
- ================
- idDamagable::Event_RestoreDamagable
- ================
- */
- void idDamagable::Event_RestoreDamagable( void ) {
- health = spawnArgs.GetInt( "health", "5" );
- Show();
- }
- /*
- ===============================================================================
- idExplodable
-
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idExplodable )
- EVENT( EV_Activate, idExplodable::Event_Explode )
- END_CLASS
- /*
- ================
- idExplodable::Spawn
- ================
- */
- void idExplodable::Spawn( void ) {
- Hide();
- }
- /*
- ================
- idExplodable::Event_Explode
- ================
- */
- void idExplodable::Event_Explode( idEntity *activator ) {
- const char *temp;
- if ( spawnArgs.GetString( "def_damage", "damage_explosion", &temp ) ) {
- gameLocal.RadiusDamage( GetPhysics()->GetOrigin(), activator, activator, this, this, temp );
- }
- StartSound( "snd_explode", SND_CHANNEL_ANY, 0, false, NULL );
- // Show() calls UpdateVisuals, so we don't need to call it ourselves after setting the shaderParms
- renderEntity.shaderParms[SHADERPARM_RED] = 1.0f;
- renderEntity.shaderParms[SHADERPARM_GREEN] = 1.0f;
- renderEntity.shaderParms[SHADERPARM_BLUE] = 1.0f;
- renderEntity.shaderParms[SHADERPARM_ALPHA] = 1.0f;
- renderEntity.shaderParms[SHADERPARM_TIMEOFFSET] = -MS2SEC( gameLocal.time );
- renderEntity.shaderParms[SHADERPARM_DIVERSITY] = 0.0f;
- Show();
- PostEventMS( &EV_Remove, 2000 );
- ActivateTargets( activator );
- }
- /*
- ===============================================================================
- idSpring
-
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idSpring )
- EVENT( EV_PostSpawn, idSpring::Event_LinkSpring )
- END_CLASS
- /*
- ================
- idSpring::Think
- ================
- */
- void idSpring::Think( void ) {
- idVec3 start, end, origin;
- idMat3 axis;
- // run physics
- RunPhysics();
- if ( thinkFlags & TH_THINK ) {
- // evaluate force
- spring.Evaluate( gameLocal.time );
- start = p1;
- if ( ent1->GetPhysics() ) {
- axis = ent1->GetPhysics()->GetAxis();
- origin = ent1->GetPhysics()->GetOrigin();
- start = origin + start * axis;
- }
- end = p2;
- if ( ent2->GetPhysics() ) {
- axis = ent2->GetPhysics()->GetAxis();
- origin = ent2->GetPhysics()->GetOrigin();
- end = origin + p2 * axis;
- }
-
- gameRenderWorld->DebugLine( idVec4(1, 1, 0, 1), start, end, 0, true );
- }
- Present();
- }
- /*
- ================
- idSpring::Event_LinkSpring
- ================
- */
- void idSpring::Event_LinkSpring( void ) {
- idStr name1, name2;
- spawnArgs.GetString( "ent1", "", name1 );
- spawnArgs.GetString( "ent2", "", name2 );
- if ( name1.Length() ) {
- ent1 = gameLocal.FindEntity( name1 );
- if ( !ent1 ) {
- gameLocal.Error( "idSpring '%s' at (%s): cannot find first entity '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), name1.c_str() );
- }
- }
- else {
- ent1 = gameLocal.entities[ENTITYNUM_WORLD];
- }
- if ( name2.Length() ) {
- ent2 = gameLocal.FindEntity( name2 );
- if ( !ent2 ) {
- gameLocal.Error( "idSpring '%s' at (%s): cannot find second entity '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), name2.c_str() );
- }
- }
- else {
- ent2 = gameLocal.entities[ENTITYNUM_WORLD];
- }
- spring.SetPosition( ent1->GetPhysics(), id1, p1, ent2->GetPhysics(), id2, p2 );
- BecomeActive( TH_THINK );
- }
- /*
- ================
- idSpring::Spawn
- ================
- */
- void idSpring::Spawn( void ) {
- float Kstretch, damping, restLength;
- spawnArgs.GetInt( "id1", "0", id1 );
- spawnArgs.GetInt( "id2", "0", id2 );
- spawnArgs.GetVector( "point1", "0 0 0", p1 );
- spawnArgs.GetVector( "point2", "0 0 0", p2 );
- spawnArgs.GetFloat( "constant", "100.0f", Kstretch );
- spawnArgs.GetFloat( "damping", "10.0f", damping );
- spawnArgs.GetFloat( "restlength", "0.0f", restLength );
- spring.InitSpring( Kstretch, 0.0f, damping, restLength );
- ent1 = ent2 = NULL;
- PostEventMS( &EV_PostSpawn, 0 );
- }
- /*
- ===============================================================================
- idForceField
-
- ===============================================================================
- */
- const idEventDef EV_Toggle( "Toggle", NULL );
- CLASS_DECLARATION( idEntity, idForceField )
- EVENT( EV_Activate, idForceField::Event_Activate )
- EVENT( EV_Toggle, idForceField::Event_Toggle )
- EVENT( EV_FindTargets, idForceField::Event_FindTargets )
- END_CLASS
- /*
- ===============
- idForceField::Toggle
- ================
- */
- void idForceField::Toggle( void ) {
- if ( thinkFlags & TH_THINK ) {
- BecomeInactive( TH_THINK );
- } else {
- BecomeActive( TH_THINK );
- }
- }
- /*
- ================
- idForceField::Think
- ================
- */
- void idForceField::Think( void ) {
- if ( thinkFlags & TH_THINK ) {
- // evaluate force
- forceField.Evaluate( gameLocal.time );
- }
- Present();
- }
- /*
- ================
- idForceField::Save
- ================
- */
- void idForceField::Save( idSaveGame *savefile ) const {
- savefile->WriteStaticObject( forceField );
- }
- /*
- ================
- idForceField::Restore
- ================
- */
- void idForceField::Restore( idRestoreGame *savefile ) {
- savefile->ReadStaticObject( forceField );
- }
- /*
- ================
- idForceField::Spawn
- ================
- */
- void idForceField::Spawn( void ) {
- idVec3 uniform;
- float explosion, implosion, randomTorque;
- if ( spawnArgs.GetVector( "uniform", "0 0 0", uniform ) ) {
- forceField.Uniform( uniform );
- } else if ( spawnArgs.GetFloat( "explosion", "0", explosion ) ) {
- forceField.Explosion( explosion );
- } else if ( spawnArgs.GetFloat( "implosion", "0", implosion ) ) {
- forceField.Implosion( implosion );
- }
- if ( spawnArgs.GetFloat( "randomTorque", "0", randomTorque ) ) {
- forceField.RandomTorque( randomTorque );
- }
- if ( spawnArgs.GetBool( "applyForce", "0" ) ) {
- forceField.SetApplyType( FORCEFIELD_APPLY_FORCE );
- } else if ( spawnArgs.GetBool( "applyImpulse", "0" ) ) {
- forceField.SetApplyType( FORCEFIELD_APPLY_IMPULSE );
- } else {
- forceField.SetApplyType( FORCEFIELD_APPLY_VELOCITY );
- }
- forceField.SetPlayerOnly( spawnArgs.GetBool( "playerOnly", "0" ) );
- forceField.SetMonsterOnly( spawnArgs.GetBool( "monsterOnly", "0" ) );
- // set the collision model on the force field
- forceField.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ) );
- // remove the collision model from the physics object
- GetPhysics()->SetClipModel( NULL, 1.0f );
- if ( spawnArgs.GetBool( "start_on" ) ) {
- BecomeActive( TH_THINK );
- }
- }
- /*
- ===============
- idForceField::Event_Toggle
- ================
- */
- void idForceField::Event_Toggle( void ) {
- Toggle();
- }
- /*
- ================
- idForceField::Event_Activate
- ================
- */
- void idForceField::Event_Activate( idEntity *activator ) {
- float wait;
- Toggle();
- if ( spawnArgs.GetFloat( "wait", "0.01", wait ) ) {
- PostEventSec( &EV_Toggle, wait );
- }
- }
- /*
- ================
- idForceField::Event_FindTargets
- ================
- */
- void idForceField::Event_FindTargets( void ) {
- FindTargets();
- RemoveNullTargets();
- if ( targets.Num() ) {
- forceField.Uniform( targets[0].GetEntity()->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin() );
- }
- }
- /*
- ===============================================================================
- idAnimated
- ===============================================================================
- */
- const idEventDef EV_Animated_Start( "<start>" );
- const idEventDef EV_LaunchMissiles( "launchMissiles", "ssssdf" );
- const idEventDef EV_LaunchMissilesUpdate( "<launchMissiles>", "dddd" );
- const idEventDef EV_AnimDone( "<AnimDone>", "d" );
- const idEventDef EV_StartRagdoll( "startRagdoll" );
- #ifdef _D3XP
- const idEventDef EV_SetAnimation( "setAnimation", "s" );
- const idEventDef EV_GetAnimationLength( "getAnimationLength", NULL, 'f' );
- #endif
- CLASS_DECLARATION( idAFEntity_Gibbable, idAnimated )
- EVENT( EV_Activate, idAnimated::Event_Activate )
- EVENT( EV_Animated_Start, idAnimated::Event_Start )
- EVENT( EV_StartRagdoll, idAnimated::Event_StartRagdoll )
- EVENT( EV_AnimDone, idAnimated::Event_AnimDone )
- EVENT( EV_Footstep, idAnimated::Event_Footstep )
- EVENT( EV_FootstepLeft, idAnimated::Event_Footstep )
- EVENT( EV_FootstepRight, idAnimated::Event_Footstep )
- EVENT( EV_LaunchMissiles, idAnimated::Event_LaunchMissiles )
- EVENT( EV_LaunchMissilesUpdate, idAnimated::Event_LaunchMissilesUpdate )
- #ifdef _D3XP
- EVENT( EV_SetAnimation, idAnimated::Event_SetAnimation )
- EVENT( EV_GetAnimationLength, idAnimated::Event_GetAnimationLength )
- #endif
- END_CLASS
- /*
- ===============
- idAnimated::idAnimated
- ================
- */
- idAnimated::idAnimated() {
- anim = 0;
- blendFrames = 0;
- soundJoint = INVALID_JOINT;
- activated = false;
- combatModel = NULL;
- activator = NULL;
- current_anim_index = 0;
- num_anims = 0;
- }
- /*
- ===============
- idAnimated::idAnimated
- ================
- */
- idAnimated::~idAnimated() {
- delete combatModel;
- combatModel = NULL;
- }
- /*
- ===============
- idAnimated::Save
- ================
- */
- void idAnimated::Save( idSaveGame *savefile ) const {
- savefile->WriteInt( current_anim_index );
- savefile->WriteInt( num_anims );
- savefile->WriteInt( anim );
- savefile->WriteInt( blendFrames );
- savefile->WriteJoint( soundJoint );
- activator.Save( savefile );
- savefile->WriteBool( activated );
- }
- /*
- ===============
- idAnimated::Restore
- ================
- */
- void idAnimated::Restore( idRestoreGame *savefile ) {
- savefile->ReadInt( current_anim_index );
- savefile->ReadInt( num_anims );
- savefile->ReadInt( anim );
- savefile->ReadInt( blendFrames );
- savefile->ReadJoint( soundJoint );
- activator.Restore( savefile );
- savefile->ReadBool( activated );
- }
- /*
- ===============
- idAnimated::Spawn
- ================
- */
- void idAnimated::Spawn( void ) {
- idStr animname;
- int anim2;
- float wait;
- const char *joint;
- joint = spawnArgs.GetString( "sound_bone", "origin" );
- soundJoint = animator.GetJointHandle( joint );
- if ( soundJoint == INVALID_JOINT ) {
- gameLocal.Warning( "idAnimated '%s' at (%s): cannot find joint '%s' for sound playback", name.c_str(), GetPhysics()->GetOrigin().ToString(0), joint );
- }
- LoadAF();
- // allow bullets to collide with a combat model
- if ( spawnArgs.GetBool( "combatModel", "0" ) ) {
- combatModel = new idClipModel( modelDefHandle );
- }
- // allow the entity to take damage
- if ( spawnArgs.GetBool( "takeDamage", "0" ) ) {
- fl.takedamage = true;
- }
- blendFrames = 0;
- current_anim_index = 0;
- spawnArgs.GetInt( "num_anims", "0", num_anims );
- blendFrames = spawnArgs.GetInt( "blend_in" );
- animname = spawnArgs.GetString( num_anims ? "anim1" : "anim" );
- if ( !animname.Length() ) {
- anim = 0;
- } else {
- anim = animator.GetAnim( animname );
- if ( !anim ) {
- gameLocal.Error( "idAnimated '%s' at (%s): cannot find anim '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), animname.c_str() );
- }
- }
- if ( spawnArgs.GetBool( "hide" ) ) {
- Hide();
- if ( !num_anims ) {
- blendFrames = 0;
- }
- } else if ( spawnArgs.GetString( "start_anim", "", animname ) ) {
- anim2 = animator.GetAnim( animname );
- if ( !anim2 ) {
- gameLocal.Error( "idAnimated '%s' at (%s): cannot find anim '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), animname.c_str() );
- }
- animator.CycleAnim( ANIMCHANNEL_ALL, anim2, gameLocal.time, 0 );
- } else if ( anim ) {
- // init joints to the first frame of the animation
- animator.SetFrame( ANIMCHANNEL_ALL, anim, 1, gameLocal.time, 0 );
- if ( !num_anims ) {
- blendFrames = 0;
- }
- }
- spawnArgs.GetFloat( "wait", "-1", wait );
- if ( wait >= 0 ) {
- PostEventSec( &EV_Activate, wait, this );
- }
- }
- /*
- ===============
- idAnimated::LoadAF
- ===============
- */
- bool idAnimated::LoadAF( void ) {
- idStr fileName;
- if ( !spawnArgs.GetString( "ragdoll", "*unknown*", fileName ) ) {
- return false;
- }
- af.SetAnimator( GetAnimator() );
- return af.Load( this, fileName );
- }
- /*
- ===============
- idAnimated::GetPhysicsToSoundTransform
- ===============
- */
- bool idAnimated::GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis ) {
- animator.GetJointTransform( soundJoint, gameLocal.time, origin, axis );
- axis = renderEntity.axis;
- return true;
- }
- /*
- ================
- idAnimated::StartRagdoll
- ================
- */
- bool idAnimated::StartRagdoll( void ) {
- // if no AF loaded
- if ( !af.IsLoaded() ) {
- return false;
- }
- // if the AF is already active
- if ( af.IsActive() ) {
- return true;
- }
- // disable any collision model used
- GetPhysics()->DisableClip();
- // start using the AF
- af.StartFromCurrentPose( spawnArgs.GetInt( "velocityTime", "0" ) );
-
- return true;
- }
- /*
- =====================
- idAnimated::PlayNextAnim
- =====================
- */
- void idAnimated::PlayNextAnim( void ) {
- const char *animname;
- int len;
- int cycle;
- if ( current_anim_index >= num_anims ) {
- Hide();
- if ( spawnArgs.GetBool( "remove" ) ) {
- PostEventMS( &EV_Remove, 0 );
- } else {
- current_anim_index = 0;
- }
- return;
- }
- Show();
- current_anim_index++;
- spawnArgs.GetString( va( "anim%d", current_anim_index ), NULL, &animname );
- if ( !animname ) {
- anim = 0;
- animator.Clear( ANIMCHANNEL_ALL, gameLocal.time, FRAME2MS( blendFrames ) );
- return;
- }
- anim = animator.GetAnim( animname );
- if ( !anim ) {
- gameLocal.Warning( "missing anim '%s' on %s", animname, name.c_str() );
- return;
- }
- if ( g_debugCinematic.GetBool() ) {
- gameLocal.Printf( "%d: '%s' start anim '%s'\n", gameLocal.framenum, GetName(), animname );
- }
-
- spawnArgs.GetInt( "cycle", "1", cycle );
- if ( ( current_anim_index == num_anims ) && spawnArgs.GetBool( "loop_last_anim" ) ) {
- cycle = -1;
- }
- animator.CycleAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( blendFrames ) );
- animator.CurrentAnim( ANIMCHANNEL_ALL )->SetCycleCount( cycle );
- len = animator.CurrentAnim( ANIMCHANNEL_ALL )->PlayLength();
- if ( len >= 0 ) {
- PostEventMS( &EV_AnimDone, len, current_anim_index );
- }
- // offset the start time of the shader to sync it to the game time
- renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( gameLocal.time );
- animator.ForceUpdate();
- UpdateAnimation();
- UpdateVisuals();
- Present();
- }
- /*
- ===============
- idAnimated::Event_StartRagdoll
- ================
- */
- void idAnimated::Event_StartRagdoll( void ) {
- StartRagdoll();
- }
- /*
- ===============
- idAnimated::Event_AnimDone
- ================
- */
- void idAnimated::Event_AnimDone( int animindex ) {
- if ( g_debugCinematic.GetBool() ) {
- const idAnim *animPtr = animator.GetAnim( anim );
- gameLocal.Printf( "%d: '%s' end anim '%s'\n", gameLocal.framenum, GetName(), animPtr ? animPtr->Name() : "" );
- }
- if ( ( animindex >= num_anims ) && spawnArgs.GetBool( "remove" ) ) {
- Hide();
- PostEventMS( &EV_Remove, 0 );
- } else if ( spawnArgs.GetBool( "auto_advance" ) ) {
- PlayNextAnim();
- } else {
- activated = false;
- }
- ActivateTargets( activator.GetEntity() );
- }
- /*
- ===============
- idAnimated::Event_Activate
- ================
- */
- void idAnimated::Event_Activate( idEntity *_activator ) {
- if ( num_anims ) {
- PlayNextAnim();
- activator = _activator;
- return;
- }
- if ( activated ) {
- // already activated
- return;
- }
- activated = true;
- activator = _activator;
- ProcessEvent( &EV_Animated_Start );
- }
- /*
- ===============
- idAnimated::Event_Start
- ================
- */
- void idAnimated::Event_Start( void ) {
- int cycle;
- int len;
- Show();
- if ( num_anims ) {
- PlayNextAnim();
- return;
- }
- if ( anim ) {
- if ( g_debugCinematic.GetBool() ) {
- const idAnim *animPtr = animator.GetAnim( anim );
- gameLocal.Printf( "%d: '%s' start anim '%s'\n", gameLocal.framenum, GetName(), animPtr ? animPtr->Name() : "" );
- }
- spawnArgs.GetInt( "cycle", "1", cycle );
- animator.CycleAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( blendFrames ) );
- animator.CurrentAnim( ANIMCHANNEL_ALL )->SetCycleCount( cycle );
- len = animator.CurrentAnim( ANIMCHANNEL_ALL )->PlayLength();
- if ( len >= 0 ) {
- PostEventMS( &EV_AnimDone, len, 1 );
- }
- }
- // offset the start time of the shader to sync it to the game time
- renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( gameLocal.time );
- animator.ForceUpdate();
- UpdateAnimation();
- UpdateVisuals();
- Present();
- }
- /*
- ===============
- idAnimated::Event_Footstep
- ===============
- */
- void idAnimated::Event_Footstep( void ) {
- StartSound( "snd_footstep", SND_CHANNEL_BODY, 0, false, NULL );
- }
- /*
- =====================
- idAnimated::Event_LaunchMissilesUpdate
- =====================
- */
- void idAnimated::Event_LaunchMissilesUpdate( int launchjoint, int targetjoint, int numshots, int framedelay ) {
- idVec3 launchPos;
- idVec3 targetPos;
- idMat3 axis;
- idVec3 dir;
- idEntity * ent;
- idProjectile * projectile;
- const idDict * projectileDef;
- const char * projectilename;
- projectilename = spawnArgs.GetString( "projectilename" );
- projectileDef = gameLocal.FindEntityDefDict( projectilename, false );
- if ( !projectileDef ) {
- gameLocal.Warning( "idAnimated '%s' at (%s): 'launchMissiles' called with unknown projectile '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), projectilename );
- return;
- }
- StartSound( "snd_missile", SND_CHANNEL_WEAPON, 0, false, NULL );
- animator.GetJointTransform( ( jointHandle_t )launchjoint, gameLocal.time, launchPos, axis );
- launchPos = renderEntity.origin + launchPos * renderEntity.axis;
-
- animator.GetJointTransform( ( jointHandle_t )targetjoint, gameLocal.time, targetPos, axis );
- targetPos = renderEntity.origin + targetPos * renderEntity.axis;
- dir = targetPos - launchPos;
- dir.Normalize();
- gameLocal.SpawnEntityDef( *projectileDef, &ent, false );
- if ( !ent || !ent->IsType( idProjectile::Type ) ) {
- gameLocal.Error( "idAnimated '%s' at (%s): in 'launchMissiles' call '%s' is not an idProjectile", name.c_str(), GetPhysics()->GetOrigin().ToString(0), projectilename );
- }
- projectile = ( idProjectile * )ent;
- projectile->Create( this, launchPos, dir );
- projectile->Launch( launchPos, dir, vec3_origin );
- if ( numshots > 0 ) {
- PostEventMS( &EV_LaunchMissilesUpdate, FRAME2MS( framedelay ), launchjoint, targetjoint, numshots - 1, framedelay );
- }
- }
- /*
- =====================
- idAnimated::Event_LaunchMissiles
- =====================
- */
- void idAnimated::Event_LaunchMissiles( const char *projectilename, const char *sound, const char *launchjoint, const char *targetjoint, int numshots, int framedelay ) {
- const idDict * projectileDef;
- jointHandle_t launch;
- jointHandle_t target;
- projectileDef = gameLocal.FindEntityDefDict( projectilename, false );
- if ( !projectileDef ) {
- gameLocal.Warning( "idAnimated '%s' at (%s): unknown projectile '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), projectilename );
- return;
- }
- launch = animator.GetJointHandle( launchjoint );
- if ( launch == INVALID_JOINT ) {
- gameLocal.Warning( "idAnimated '%s' at (%s): unknown launch joint '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), launchjoint );
- gameLocal.Error( "Unknown joint '%s'", launchjoint );
- }
- target = animator.GetJointHandle( targetjoint );
- if ( target == INVALID_JOINT ) {
- gameLocal.Warning( "idAnimated '%s' at (%s): unknown target joint '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), targetjoint );
- }
- spawnArgs.Set( "projectilename", projectilename );
- spawnArgs.Set( "missilesound", sound );
- CancelEvents( &EV_LaunchMissilesUpdate );
- ProcessEvent( &EV_LaunchMissilesUpdate, launch, target, numshots - 1, framedelay );
- }
- #ifdef _D3XP
- /*
- =====================
- idAnimated::Event_SetAnimation
- =====================
- */
- void idAnimated::Event_SetAnimation( const char *animName ) {
- //BSM Nerve: Need to add some error checking so we don't change the animation
- //in the middle of the existing animation
- anim = animator.GetAnim( animName );
- if ( !anim ) {
- gameLocal.Error( "idAnimated '%s' at (%s): cannot find anim '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), animName );
- }
- }
- /*
- =====================
- idAnimated::Event_GetAnimationLength
- =====================
- */
- void idAnimated::Event_GetAnimationLength() {
- float length = 0;
- if(anim) {
- length = (float)(animator.AnimLength( anim )) / 1000.f;
- }
- idThread::ReturnFloat(length);
- }
- #endif
- /*
- ===============================================================================
- idStaticEntity
- Some static entities may be optimized into inline geometry by dmap
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idStaticEntity )
- EVENT( EV_Activate, idStaticEntity::Event_Activate )
- END_CLASS
- /*
- ===============
- idStaticEntity::idStaticEntity
- ===============
- */
- idStaticEntity::idStaticEntity( void ) {
- spawnTime = 0;
- active = false;
- fadeFrom.Set( 1, 1, 1, 1 );
- fadeTo.Set( 1, 1, 1, 1 );
- fadeStart = 0;
- fadeEnd = 0;
- runGui = false;
- }
- /*
- ===============
- idStaticEntity::Save
- ===============
- */
- void idStaticEntity::Save( idSaveGame *savefile ) const {
- savefile->WriteInt( spawnTime );
- savefile->WriteBool( active );
- savefile->WriteVec4( fadeFrom );
- savefile->WriteVec4( fadeTo );
- savefile->WriteInt( fadeStart );
- savefile->WriteInt( fadeEnd );
- savefile->WriteBool( runGui );
- }
- /*
- ===============
- idStaticEntity::Restore
- ===============
- */
- void idStaticEntity::Restore( idRestoreGame *savefile ) {
- savefile->ReadInt( spawnTime );
- savefile->ReadBool( active );
- savefile->ReadVec4( fadeFrom );
- savefile->ReadVec4( fadeTo );
- savefile->ReadInt( fadeStart );
- savefile->ReadInt( fadeEnd );
- savefile->ReadBool( runGui );
- }
- /*
- ===============
- idStaticEntity::Spawn
- ===============
- */
- void idStaticEntity::Spawn( void ) {
- bool solid;
- bool hidden;
- // an inline static model will not do anything at all
- if ( spawnArgs.GetBool( "inline" ) || gameLocal.world->spawnArgs.GetBool( "inlineAllStatics" ) ) {
- Hide();
- return;
- }
- solid = spawnArgs.GetBool( "solid" );
- hidden = spawnArgs.GetBool( "hide" );
- if ( solid && !hidden ) {
- GetPhysics()->SetContents( CONTENTS_SOLID );
- } else {
- GetPhysics()->SetContents( 0 );
- }
- spawnTime = gameLocal.time;
- active = false;
- idStr model = spawnArgs.GetString( "model" );
- if ( model.Find( ".prt" ) >= 0 ) {
- // we want the parametric particles out of sync with each other
- renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] = gameLocal.random.RandomInt( 32767 );
- }
- fadeFrom.Set( 1, 1, 1, 1 );
- fadeTo.Set( 1, 1, 1, 1 );
- fadeStart = 0;
- fadeEnd = 0;
- // NOTE: this should be used very rarely because it is expensive
- runGui = spawnArgs.GetBool( "runGui" );
- if ( runGui ) {
- BecomeActive( TH_THINK );
- }
- }
- /*
- ================
- idStaticEntity::ShowEditingDialog
- ================
- */
- void idStaticEntity::ShowEditingDialog( void ) {
- common->InitTool( EDITOR_PARTICLE, &spawnArgs );
- }
- /*
- ================
- idStaticEntity::Think
- ================
- */
- void idStaticEntity::Think( void ) {
- idEntity::Think();
- if ( thinkFlags & TH_THINK ) {
- if ( runGui && renderEntity.gui[0] ) {
- idPlayer *player = gameLocal.GetLocalPlayer();
- if ( player ) {
- if ( !player->objectiveSystemOpen ) {
- renderEntity.gui[0]->StateChanged( gameLocal.time, true );
- if ( renderEntity.gui[1] ) {
- renderEntity.gui[1]->StateChanged( gameLocal.time, true );
- }
- if ( renderEntity.gui[2] ) {
- renderEntity.gui[2]->StateChanged( gameLocal.time, true );
- }
- }
- }
- }
- if ( fadeEnd > 0 ) {
- idVec4 color;
- if ( gameLocal.time < fadeEnd ) {
- color.Lerp( fadeFrom, fadeTo, ( float )( gameLocal.time - fadeStart ) / ( float )( fadeEnd - fadeStart ) );
- } else {
- color = fadeTo;
- fadeEnd = 0;
- BecomeInactive( TH_THINK );
- }
- SetColor( color );
- }
- }
- }
- /*
- ================
- idStaticEntity::Fade
- ================
- */
- void idStaticEntity::Fade( const idVec4 &to, float fadeTime ) {
- GetColor( fadeFrom );
- fadeTo = to;
- fadeStart = gameLocal.time;
- fadeEnd = gameLocal.time + SEC2MS( fadeTime );
- BecomeActive( TH_THINK );
- }
- /*
- ================
- idStaticEntity::Hide
- ================
- */
- void idStaticEntity::Hide( void ) {
- idEntity::Hide();
- GetPhysics()->SetContents( 0 );
- }
- /*
- ================
- idStaticEntity::Show
- ================
- */
- void idStaticEntity::Show( void ) {
- idEntity::Show();
- if ( spawnArgs.GetBool( "solid" ) ) {
- GetPhysics()->SetContents( CONTENTS_SOLID );
- }
- }
- /*
- ================
- idStaticEntity::Event_Activate
- ================
- */
- void idStaticEntity::Event_Activate( idEntity *activator ) {
- idStr activateGui;
- spawnTime = gameLocal.time;
- active = !active;
- const idKeyValue *kv = spawnArgs.FindKey( "hide" );
- if ( kv ) {
- if ( IsHidden() ) {
- Show();
- } else {
- Hide();
- }
- }
- renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( spawnTime );
- renderEntity.shaderParms[5] = active;
- // this change should be a good thing, it will automatically turn on
- // lights etc.. when triggered so that does not have to be specifically done
- // with trigger parms.. it MIGHT break things so need to keep an eye on it
- renderEntity.shaderParms[ SHADERPARM_MODE ] = ( renderEntity.shaderParms[ SHADERPARM_MODE ] ) ? 0.0f : 1.0f;
- BecomeActive( TH_UPDATEVISUALS );
- }
- /*
- ================
- idStaticEntity::WriteToSnapshot
- ================
- */
- void idStaticEntity::WriteToSnapshot( idBitMsgDelta &msg ) const {
- GetPhysics()->WriteToSnapshot( msg );
- WriteBindToSnapshot( msg );
- WriteColorToSnapshot( msg );
- WriteGUIToSnapshot( msg );
- msg.WriteBits( IsHidden()?1:0, 1 );
- }
- /*
- ================
- idStaticEntity::ReadFromSnapshot
- ================
- */
- void idStaticEntity::ReadFromSnapshot( const idBitMsgDelta &msg ) {
- bool hidden;
- GetPhysics()->ReadFromSnapshot( msg );
- ReadBindFromSnapshot( msg );
- ReadColorFromSnapshot( msg );
- ReadGUIFromSnapshot( msg );
- hidden = msg.ReadBits( 1 ) == 1;
- if ( hidden != IsHidden() ) {
- if ( hidden ) {
- Hide();
- } else {
- Show();
- }
- }
- if ( msg.HasChanged() ) {
- UpdateVisuals();
- }
- }
- /*
- ===============================================================================
- idFuncEmitter
- ===============================================================================
- */
- CLASS_DECLARATION( idStaticEntity, idFuncEmitter )
- EVENT( EV_Activate, idFuncEmitter::Event_Activate )
- END_CLASS
- /*
- ===============
- idFuncEmitter::idFuncEmitter
- ===============
- */
- idFuncEmitter::idFuncEmitter( void ) {
- hidden = false;
- }
- /*
- ===============
- idFuncEmitter::Spawn
- ===============
- */
- void idFuncEmitter::Spawn( void ) {
- if ( spawnArgs.GetBool( "start_off" ) ) {
- hidden = true;
- renderEntity.shaderParms[SHADERPARM_PARTICLE_STOPTIME] = MS2SEC( 1 );
- UpdateVisuals();
- } else {
- hidden = false;
- }
- }
- /*
- ===============
- idFuncEmitter::Save
- ===============
- */
- void idFuncEmitter::Save( idSaveGame *savefile ) const {
- savefile->WriteBool( hidden );
- }
- /*
- ===============
- idFuncEmitter::Restore
- ===============
- */
- void idFuncEmitter::Restore( idRestoreGame *savefile ) {
- savefile->ReadBool( hidden );
- }
- /*
- ================
- idFuncEmitter::Event_Activate
- ================
- */
- void idFuncEmitter::Event_Activate( idEntity *activator ) {
- if ( hidden || spawnArgs.GetBool( "cycleTrigger" ) ) {
- renderEntity.shaderParms[SHADERPARM_PARTICLE_STOPTIME] = 0;
- renderEntity.shaderParms[SHADERPARM_TIMEOFFSET] = -MS2SEC( gameLocal.time );
- hidden = false;
- } else {
- renderEntity.shaderParms[SHADERPARM_PARTICLE_STOPTIME] = MS2SEC( gameLocal.time );
- hidden = true;
- }
- UpdateVisuals();
- }
- /*
- ================
- idFuncEmitter::WriteToSnapshot
- ================
- */
- void idFuncEmitter::WriteToSnapshot( idBitMsgDelta &msg ) const {
- msg.WriteBits( hidden ? 1 : 0, 1 );
- msg.WriteFloat( renderEntity.shaderParms[ SHADERPARM_PARTICLE_STOPTIME ] );
- msg.WriteFloat( renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] );
- }
- /*
- ================
- idFuncEmitter::ReadFromSnapshot
- ================
- */
- void idFuncEmitter::ReadFromSnapshot( const idBitMsgDelta &msg ) {
- hidden = msg.ReadBits( 1 ) != 0;
- renderEntity.shaderParms[ SHADERPARM_PARTICLE_STOPTIME ] = msg.ReadFloat();
- renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] = msg.ReadFloat();
- if ( msg.HasChanged() ) {
- UpdateVisuals();
- }
- }
- /*
- ===============================================================================
- idFuncSplat
- ===============================================================================
- */
- const idEventDef EV_Splat( "<Splat>" );
- CLASS_DECLARATION( idFuncEmitter, idFuncSplat )
- EVENT( EV_Activate, idFuncSplat::Event_Activate )
- EVENT( EV_Splat, idFuncSplat::Event_Splat )
- END_CLASS
- /*
- ===============
- idFuncSplat::idFuncSplat
- ===============
- */
- idFuncSplat::idFuncSplat( void ) {
- }
- /*
- ===============
- idFuncSplat::Spawn
- ===============
- */
- void idFuncSplat::Spawn( void ) {
- }
- /*
- ================
- idFuncSplat::Event_Splat
- ================
- */
- void idFuncSplat::Event_Splat( void ) {
- const char *splat = NULL;
- int count = spawnArgs.GetInt( "splatCount", "1" );
- for ( int i = 0; i < count; i++ ) {
- splat = spawnArgs.RandomPrefix( "mtr_splat", gameLocal.random );
- if ( splat && *splat ) {
- float size = spawnArgs.GetFloat( "splatSize", "128" );
- float dist = spawnArgs.GetFloat( "splatDistance", "128" );
- float angle = spawnArgs.GetFloat( "splatAngle", "0" );
- gameLocal.ProjectDecal( GetPhysics()->GetOrigin(), GetPhysics()->GetAxis()[2], dist, true, size, splat, angle );
- }
- }
- StartSound( "snd_splat", SND_CHANNEL_ANY, 0, false, NULL );
- }
- /*
- ================
- idFuncSplat::Event_Activate
- ================
- */
- void idFuncSplat::Event_Activate( idEntity *activator ) {
- idFuncEmitter::Event_Activate( activator );
- PostEventSec( &EV_Splat, spawnArgs.GetFloat( "splatDelay", "0.25" ) );
- StartSound( "snd_spurt", SND_CHANNEL_ANY, 0, false, NULL );
- }
- /*
- ===============================================================================
- idFuncSmoke
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idFuncSmoke )
- EVENT( EV_Activate, idFuncSmoke::Event_Activate )
- END_CLASS
- /*
- ===============
- idFuncSmoke::idFuncSmoke
- ===============
- */
- idFuncSmoke::idFuncSmoke() {
- smokeTime = 0;
- smoke = NULL;
- restart = false;
- }
- /*
- ===============
- idFuncSmoke::Save
- ===============
- */
- void idFuncSmoke::Save( idSaveGame *savefile ) const {
- savefile->WriteInt( smokeTime );
- savefile->WriteParticle( smoke );
- savefile->WriteBool( restart );
- }
- /*
- ===============
- idFuncSmoke::Restore
- ===============
- */
- void idFuncSmoke::Restore( idRestoreGame *savefile ) {
- savefile->ReadInt( smokeTime );
- savefile->ReadParticle( smoke );
- savefile->ReadBool( restart );
- }
- /*
- ===============
- idFuncSmoke::Spawn
- ===============
- */
- void idFuncSmoke::Spawn( void ) {
- const char *smokeName = spawnArgs.GetString( "smoke" );
- if ( *smokeName != '\0' ) {
- smoke = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, smokeName ) );
- } else {
- smoke = NULL;
- }
- if ( spawnArgs.GetBool( "start_off" ) ) {
- smokeTime = 0;
- restart = false;
- } else if ( smoke ) {
- smokeTime = gameLocal.time;
- BecomeActive( TH_UPDATEPARTICLES );
- restart = true;
- }
- GetPhysics()->SetContents( 0 );
- }
- /*
- ================
- idFuncSmoke::Event_Activate
- ================
- */
- void idFuncSmoke::Event_Activate( idEntity *activator ) {
- if ( thinkFlags & TH_UPDATEPARTICLES ) {
- restart = false;
- return;
- } else {
- BecomeActive( TH_UPDATEPARTICLES );
- restart = true;
- smokeTime = gameLocal.time;
- }
- }
- /*
- ===============
- idFuncSmoke::Think
- ================
- */
- void idFuncSmoke::Think( void ) {
- // if we are completely closed off from the player, don't do anything at all
- if ( CheckDormant() || smoke == NULL || smokeTime == -1 ) {
- return;
- }
- if ( ( thinkFlags & TH_UPDATEPARTICLES) && !IsHidden() ) {
- if ( !gameLocal.smokeParticles->EmitSmoke( smoke, smokeTime, gameLocal.random.CRandomFloat(), GetPhysics()->GetOrigin(), GetPhysics()->GetAxis(), timeGroup /*_D3XP*/ ) ) {
- if ( restart ) {
- smokeTime = gameLocal.time;
- } else {
- smokeTime = 0;
- BecomeInactive( TH_UPDATEPARTICLES );
- }
- }
- }
- }
- /*
- ===============================================================================
- idTextEntity
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idTextEntity )
- END_CLASS
- /*
- ================
- idTextEntity::Spawn
- ================
- */
- void idTextEntity::Spawn( void ) {
- // these are cached as the are used each frame
- text = spawnArgs.GetString( "text" );
- playerOriented = spawnArgs.GetBool( "playerOriented" );
- bool force = spawnArgs.GetBool( "force" );
- if ( developer.GetBool() || force ) {
- BecomeActive(TH_THINK);
- }
- }
- /*
- ================
- idTextEntity::Save
- ================
- */
- void idTextEntity::Save( idSaveGame *savefile ) const {
- savefile->WriteString( text );
- savefile->WriteBool( playerOriented );
- }
- /*
- ================
- idTextEntity::Restore
- ================
- */
- void idTextEntity::Restore( idRestoreGame *savefile ) {
- savefile->ReadString( text );
- savefile->ReadBool( playerOriented );
- }
- /*
- ================
- idTextEntity::Think
- ================
- */
- void idTextEntity::Think( void ) {
- if ( thinkFlags & TH_THINK ) {
- gameRenderWorld->DrawText( text, GetPhysics()->GetOrigin(), 0.25, colorWhite, playerOriented ? gameLocal.GetLocalPlayer()->viewAngles.ToMat3() : GetPhysics()->GetAxis().Transpose(), 1 );
- for ( int i = 0; i < targets.Num(); i++ ) {
- if ( targets[i].GetEntity() ) {
- gameRenderWorld->DebugArrow( colorBlue, GetPhysics()->GetOrigin(), targets[i].GetEntity()->GetPhysics()->GetOrigin(), 1 );
- }
- }
- } else {
- BecomeInactive( TH_ALL );
- }
- }
- /*
- ===============================================================================
- idVacuumSeperatorEntity
- Can be triggered to let vacuum through a portal (blown out window)
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idVacuumSeparatorEntity )
- EVENT( EV_Activate, idVacuumSeparatorEntity::Event_Activate )
- END_CLASS
- /*
- ================
- idVacuumSeparatorEntity::idVacuumSeparatorEntity
- ================
- */
- idVacuumSeparatorEntity::idVacuumSeparatorEntity( void ) {
- portal = 0;
- }
- /*
- ================
- idVacuumSeparatorEntity::Save
- ================
- */
- void idVacuumSeparatorEntity::Save( idSaveGame *savefile ) const {
- savefile->WriteInt( (int)portal );
- savefile->WriteInt( gameRenderWorld->GetPortalState( portal ) );
- }
- /*
- ================
- idVacuumSeparatorEntity::Restore
- ================
- */
- void idVacuumSeparatorEntity::Restore( idRestoreGame *savefile ) {
- int state;
- savefile->ReadInt( (int &)portal );
- savefile->ReadInt( state );
- gameLocal.SetPortalState( portal, state );
- }
- /*
- ================
- idVacuumSeparatorEntity::Spawn
- ================
- */
- void idVacuumSeparatorEntity::Spawn() {
- idBounds b;
- b = idBounds( spawnArgs.GetVector( "origin" ) ).Expand( 16 );
- portal = gameRenderWorld->FindPortal( b );
- if ( !portal ) {
- gameLocal.Warning( "VacuumSeparator '%s' didn't contact a portal", spawnArgs.GetString( "name" ) );
- return;
- }
- gameLocal.SetPortalState( portal, PS_BLOCK_AIR | PS_BLOCK_LOCATION );
- }
- /*
- ================
- idVacuumSeparatorEntity::Event_Activate
- ================
- */
- void idVacuumSeparatorEntity::Event_Activate( idEntity *activator ) {
- if ( !portal ) {
- return;
- }
- gameLocal.SetPortalState( portal, PS_BLOCK_NONE );
- }
- /*
- ===============================================================================
- idLocationSeparatorEntity
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idLocationSeparatorEntity )
- END_CLASS
- /*
- ================
- idLocationSeparatorEntity::Spawn
- ================
- */
- void idLocationSeparatorEntity::Spawn() {
- idBounds b;
- b = idBounds( spawnArgs.GetVector( "origin" ) ).Expand( 16 );
- qhandle_t portal = gameRenderWorld->FindPortal( b );
- if ( !portal ) {
- gameLocal.Warning( "LocationSeparator '%s' didn't contact a portal", spawnArgs.GetString( "name" ) );
- }
- gameLocal.SetPortalState( portal, PS_BLOCK_LOCATION );
- }
- /*
- ===============================================================================
- idVacuumEntity
- Levels should only have a single vacuum entity.
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idVacuumEntity )
- END_CLASS
- /*
- ================
- idVacuumEntity::Spawn
- ================
- */
- void idVacuumEntity::Spawn() {
- if ( gameLocal.vacuumAreaNum != -1 ) {
- gameLocal.Warning( "idVacuumEntity::Spawn: multiple idVacuumEntity in level" );
- return;
- }
- idVec3 org = spawnArgs.GetVector( "origin" );
- gameLocal.vacuumAreaNum = gameRenderWorld->PointInArea( org );
- }
- /*
- ===============================================================================
- idLocationEntity
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idLocationEntity )
- END_CLASS
- /*
- ======================
- idLocationEntity::Spawn
- ======================
- */
- void idLocationEntity::Spawn() {
- idStr realName;
- // this just holds dict information
- // if "location" not already set, use the entity name.
- if ( !spawnArgs.GetString( "location", "", realName ) ) {
- spawnArgs.Set( "location", name );
- }
- }
- /*
- ======================
- idLocationEntity::GetLocation
- ======================
- */
- const char *idLocationEntity::GetLocation( void ) const {
- return spawnArgs.GetString( "location" );
- }
- /*
- ===============================================================================
- idBeam
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idBeam )
- EVENT( EV_PostSpawn, idBeam::Event_MatchTarget )
- EVENT( EV_Activate, idBeam::Event_Activate )
- END_CLASS
- /*
- ===============
- idBeam::idBeam
- ===============
- */
- idBeam::idBeam() {
- target = NULL;
- master = NULL;
- }
- /*
- ===============
- idBeam::Save
- ===============
- */
- void idBeam::Save( idSaveGame *savefile ) const {
- target.Save( savefile );
- master.Save( savefile );
- }
- /*
- ===============
- idBeam::Restore
- ===============
- */
- void idBeam::Restore( idRestoreGame *savefile ) {
- target.Restore( savefile );
- master.Restore( savefile );
- }
- /*
- ===============
- idBeam::Spawn
- ===============
- */
- void idBeam::Spawn( void ) {
- float width;
- if ( spawnArgs.GetFloat( "width", "0", width ) ) {
- renderEntity.shaderParms[ SHADERPARM_BEAM_WIDTH ] = width;
- }
- SetModel( "_BEAM" );
- Hide();
- PostEventMS( &EV_PostSpawn, 0 );
- }
- /*
- ================
- idBeam::Think
- ================
- */
- void idBeam::Think( void ) {
- idBeam *masterEnt;
- if ( !IsHidden() && !target.GetEntity() ) {
- // hide if our target is removed
- Hide();
- }
- RunPhysics();
- masterEnt = master.GetEntity();
- if ( masterEnt ) {
- const idVec3 &origin = GetPhysics()->GetOrigin();
- masterEnt->SetBeamTarget( origin );
- }
- Present();
- }
- /*
- ================
- idBeam::SetMaster
- ================
- */
- void idBeam::SetMaster( idBeam *masterbeam ) {
- master = masterbeam;
- }
- /*
- ================
- idBeam::SetBeamTarget
- ================
- */
- void idBeam::SetBeamTarget( const idVec3 &origin ) {
- if ( ( renderEntity.shaderParms[ SHADERPARM_BEAM_END_X ] != origin.x ) || ( renderEntity.shaderParms[ SHADERPARM_BEAM_END_Y ] != origin.y ) || ( renderEntity.shaderParms[ SHADERPARM_BEAM_END_Z ] != origin.z ) ) {
- renderEntity.shaderParms[ SHADERPARM_BEAM_END_X ] = origin.x;
- renderEntity.shaderParms[ SHADERPARM_BEAM_END_Y ] = origin.y;
- renderEntity.shaderParms[ SHADERPARM_BEAM_END_Z ] = origin.z;
- UpdateVisuals();
- }
- }
- /*
- ================
- idBeam::Show
- ================
- */
- void idBeam::Show( void ) {
- idBeam *targetEnt;
- idEntity::Show();
- targetEnt = target.GetEntity();
- if ( targetEnt ) {
- const idVec3 &origin = targetEnt->GetPhysics()->GetOrigin();
- SetBeamTarget( origin );
- }
- }
- /*
- ================
- idBeam::Event_MatchTarget
- ================
- */
- void idBeam::Event_MatchTarget( void ) {
- int i;
- idEntity *targetEnt;
- idBeam *targetBeam;
- if ( !targets.Num() ) {
- return;
- }
- targetBeam = NULL;
- for( i = 0; i < targets.Num(); i++ ) {
- targetEnt = targets[ i ].GetEntity();
- if ( targetEnt && targetEnt->IsType( idBeam::Type ) ) {
- targetBeam = static_cast<idBeam *>( targetEnt );
- break;
- }
- }
- if ( !targetBeam ) {
- gameLocal.Error( "Could not find valid beam target for '%s'", name.c_str() );
- }
- target = targetBeam;
- targetBeam->SetMaster( this );
- if ( !spawnArgs.GetBool( "start_off" ) ) {
- Show();
- }
- }
- /*
- ================
- idBeam::Event_Activate
- ================
- */
- void idBeam::Event_Activate( idEntity *activator ) {
- if ( IsHidden() ) {
- Show();
- } else {
- Hide();
- }
- }
- /*
- ================
- idBeam::WriteToSnapshot
- ================
- */
- void idBeam::WriteToSnapshot( idBitMsgDelta &msg ) const {
- GetPhysics()->WriteToSnapshot( msg );
- WriteBindToSnapshot( msg );
- WriteColorToSnapshot( msg );
- msg.WriteFloat( renderEntity.shaderParms[SHADERPARM_BEAM_END_X] );
- msg.WriteFloat( renderEntity.shaderParms[SHADERPARM_BEAM_END_Y] );
- msg.WriteFloat( renderEntity.shaderParms[SHADERPARM_BEAM_END_Z] );
- }
- /*
- ================
- idBeam::ReadFromSnapshot
- ================
- */
- void idBeam::ReadFromSnapshot( const idBitMsgDelta &msg ) {
- GetPhysics()->ReadFromSnapshot( msg );
- ReadBindFromSnapshot( msg );
- ReadColorFromSnapshot( msg );
- renderEntity.shaderParms[SHADERPARM_BEAM_END_X] = msg.ReadFloat();
- renderEntity.shaderParms[SHADERPARM_BEAM_END_Y] = msg.ReadFloat();
- renderEntity.shaderParms[SHADERPARM_BEAM_END_Z] = msg.ReadFloat();
- if ( msg.HasChanged() ) {
- UpdateVisuals();
- }
- }
- /*
- ===============================================================================
- idLiquid
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idLiquid )
- EVENT( EV_Touch, idLiquid::Event_Touch )
- END_CLASS
- /*
- ================
- idLiquid::Save
- ================
- */
- void idLiquid::Save( idSaveGame *savefile ) const {
- // Nothing to save
- }
- /*
- ================
- idLiquid::Restore
- ================
- */
- void idLiquid::Restore( idRestoreGame *savefile ) {
- //FIXME: NO!
- Spawn();
- }
- /*
- ================
- idLiquid::Spawn
- ================
- */
- void idLiquid::Spawn() {
- /*
- model = dynamic_cast<idRenderModelLiquid *>( renderEntity.hModel );
- if ( !model ) {
- gameLocal.Error( "Entity '%s' must have liquid model", name.c_str() );
- }
- model->Reset();
- GetPhysics()->SetContents( CONTENTS_TRIGGER );
- */
- }
- /*
- ================
- idLiquid::Event_Touch
- ================
- */
- void idLiquid::Event_Touch( idEntity *other, trace_t *trace ) {
- // FIXME: for QuakeCon
- /*
- idVec3 pos;
- pos = other->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
- model->IntersectBounds( other->GetPhysics()->GetBounds().Translate( pos ), -10.0f );
- */
- }
- /*
- ===============================================================================
- idShaking
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idShaking )
- EVENT( EV_Activate, idShaking::Event_Activate )
- END_CLASS
- /*
- ===============
- idShaking::idShaking
- ===============
- */
- idShaking::idShaking() {
- active = false;
- }
- /*
- ===============
- idShaking::Save
- ===============
- */
- void idShaking::Save( idSaveGame *savefile ) const {
- savefile->WriteBool( active );
- savefile->WriteStaticObject( physicsObj );
- }
- /*
- ===============
- idShaking::Restore
- ===============
- */
- void idShaking::Restore( idRestoreGame *savefile ) {
- savefile->ReadBool( active );
- savefile->ReadStaticObject( physicsObj );
- RestorePhysics( &physicsObj );
- }
- /*
- ===============
- idShaking::Spawn
- ===============
- */
- void idShaking::Spawn( void ) {
- physicsObj.SetSelf( this );
- physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), 1.0f );
- physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
- physicsObj.SetAxis( GetPhysics()->GetAxis() );
- physicsObj.SetClipMask( MASK_SOLID );
- SetPhysics( &physicsObj );
-
- active = false;
- if ( !spawnArgs.GetBool( "start_off" ) ) {
- BeginShaking();
- }
- }
- /*
- ================
- idShaking::BeginShaking
- ================
- */
- void idShaking::BeginShaking( void ) {
- int phase;
- idAngles shake;
- int period;
- active = true;
- phase = gameLocal.random.RandomInt( 1000 );
- shake = spawnArgs.GetAngles( "shake", "0.5 0.5 0.5" );
- period = spawnArgs.GetFloat( "period", "0.05" ) * 1000;
- physicsObj.SetAngularExtrapolation( extrapolation_t(EXTRAPOLATION_DECELSINE|EXTRAPOLATION_NOSTOP), phase, period * 0.25f, GetPhysics()->GetAxis().ToAngles(), shake, ang_zero );
- }
- /*
- ================
- idShaking::Event_Activate
- ================
- */
- void idShaking::Event_Activate( idEntity *activator ) {
- if ( !active ) {
- BeginShaking();
- } else {
- active = false;
- physicsObj.SetAngularExtrapolation( EXTRAPOLATION_NONE, 0, 0, physicsObj.GetAxis().ToAngles(), ang_zero, ang_zero );
- }
- }
- /*
- ===============================================================================
- idEarthQuake
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idEarthQuake )
- EVENT( EV_Activate, idEarthQuake::Event_Activate )
- END_CLASS
- /*
- ===============
- idEarthQuake::idEarthQuake
- ===============
- */
- idEarthQuake::idEarthQuake() {
- wait = 0.0f;
- random = 0.0f;
- nextTriggerTime = 0;
- shakeStopTime = 0;
- triggered = false;
- playerOriented = false;
- disabled = false;
- shakeTime = 0.0f;
- }
- /*
- ===============
- idEarthQuake::Save
- ===============
- */
- void idEarthQuake::Save( idSaveGame *savefile ) const {
- savefile->WriteInt( nextTriggerTime );
- savefile->WriteInt( shakeStopTime );
- savefile->WriteFloat( wait );
- savefile->WriteFloat( random );
- savefile->WriteBool( triggered );
- savefile->WriteBool( playerOriented );
- savefile->WriteBool( disabled );
- savefile->WriteFloat( shakeTime );
- }
- /*
- ===============
- idEarthQuake::Restore
- ===============
- */
- void idEarthQuake::Restore( idRestoreGame *savefile ) {
- savefile->ReadInt( nextTriggerTime );
- savefile->ReadInt( shakeStopTime );
- savefile->ReadFloat( wait );
- savefile->ReadFloat( random );
- savefile->ReadBool( triggered );
- savefile->ReadBool( playerOriented );
- savefile->ReadBool( disabled );
- savefile->ReadFloat( shakeTime );
- if ( shakeStopTime > gameLocal.time ) {
- BecomeActive( TH_THINK );
- }
- }
- /*
- ===============
- idEarthQuake::Spawn
- ===============
- */
- void idEarthQuake::Spawn( void ) {
- nextTriggerTime = 0;
- shakeStopTime = 0;
- wait = spawnArgs.GetFloat( "wait", "15" );
- random = spawnArgs.GetFloat( "random", "5" );
- triggered = spawnArgs.GetBool( "triggered" );
- playerOriented = spawnArgs.GetBool( "playerOriented" );
- disabled = false;
- shakeTime = spawnArgs.GetFloat( "shakeTime", "0" );
- if ( !triggered ){
- PostEventSec( &EV_Activate, spawnArgs.GetFloat( "wait" ), this );
- }
- BecomeInactive( TH_THINK );
- }
- /*
- ================
- idEarthQuake::Event_Activate
- ================
- */
- void idEarthQuake::Event_Activate( idEntity *activator ) {
-
- if ( nextTriggerTime > gameLocal.time ) {
- return;
- }
- if ( disabled && activator == this ) {
- return;
- }
- idPlayer *player = gameLocal.GetLocalPlayer();
- if ( player == NULL ) {
- return;
- }
- nextTriggerTime = 0;
- if ( !triggered && activator != this ){
- // if we are not triggered ( i.e. random ), disable or enable
- disabled ^= 1;
- if (disabled) {
- return;
- } else {
- PostEventSec( &EV_Activate, wait + random * gameLocal.random.CRandomFloat(), this );
- }
- }
- ActivateTargets( activator );
- const idSoundShader *shader = declManager->FindSound( spawnArgs.GetString( "snd_quake" ) );
- if ( playerOriented ) {
- player->StartSoundShader( shader, SND_CHANNEL_ANY, SSF_GLOBAL, false, NULL );
- } else {
- StartSoundShader( shader, SND_CHANNEL_ANY, SSF_GLOBAL, false, NULL );
- }
- if ( shakeTime > 0.0f ) {
- shakeStopTime = gameLocal.time + SEC2MS( shakeTime );
- BecomeActive( TH_THINK );
- }
- if ( wait > 0.0f ) {
- if ( !triggered ) {
- PostEventSec( &EV_Activate, wait + random * gameLocal.random.CRandomFloat(), this );
- } else {
- nextTriggerTime = gameLocal.time + SEC2MS( wait + random * gameLocal.random.CRandomFloat() );
- }
- } else if ( shakeTime == 0.0f ) {
- PostEventMS( &EV_Remove, 0 );
- }
- }
- /*
- ===============
- idEarthQuake::Think
- ================
- */
- void idEarthQuake::Think( void ) {
- if ( thinkFlags & TH_THINK ) {
- if ( gameLocal.time > shakeStopTime ) {
- BecomeInactive( TH_THINK );
- if ( wait <= 0.0f ) {
- PostEventMS( &EV_Remove, 0 );
- }
- return;
- }
- float shakeVolume = gameSoundWorld->CurrentShakeAmplitudeForPosition( gameLocal.time, gameLocal.GetLocalPlayer()->firstPersonViewOrigin );
- gameLocal.RadiusPush( GetPhysics()->GetOrigin(), 256, 1500 * shakeVolume, this, this, 1.0f, true );
- }
- BecomeInactive( TH_UPDATEVISUALS );
- }
- /*
- ===============================================================================
- idFuncPortal
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idFuncPortal )
- EVENT( EV_Activate, idFuncPortal::Event_Activate )
- END_CLASS
- /*
- ===============
- idFuncPortal::idFuncPortal
- ===============
- */
- idFuncPortal::idFuncPortal() {
- portal = 0;
- state = false;
- }
- /*
- ===============
- idFuncPortal::Save
- ===============
- */
- void idFuncPortal::Save( idSaveGame *savefile ) const {
- savefile->WriteInt( (int)portal );
- savefile->WriteBool( state );
- }
- /*
- ===============
- idFuncPortal::Restore
- ===============
- */
- void idFuncPortal::Restore( idRestoreGame *savefile ) {
- savefile->ReadInt( (int &)portal );
- savefile->ReadBool( state );
- gameLocal.SetPortalState( portal, state ? PS_BLOCK_ALL : PS_BLOCK_NONE );
- }
- /*
- ===============
- idFuncPortal::Spawn
- ===============
- */
- void idFuncPortal::Spawn( void ) {
- portal = gameRenderWorld->FindPortal( GetPhysics()->GetAbsBounds().Expand( 32.0f ) );
- if ( portal > 0 ) {
- state = spawnArgs.GetBool( "start_on" );
- gameLocal.SetPortalState( portal, state ? PS_BLOCK_ALL : PS_BLOCK_NONE );
- }
- }
- /*
- ================
- idFuncPortal::Event_Activate
- ================
- */
- void idFuncPortal::Event_Activate( idEntity *activator ) {
- if ( portal > 0 ) {
- state = !state;
- gameLocal.SetPortalState( portal, state ? PS_BLOCK_ALL : PS_BLOCK_NONE );
- }
- }
- /*
- ===============================================================================
- idFuncAASPortal
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idFuncAASPortal )
- EVENT( EV_Activate, idFuncAASPortal::Event_Activate )
- END_CLASS
- /*
- ===============
- idFuncAASPortal::idFuncAASPortal
- ===============
- */
- idFuncAASPortal::idFuncAASPortal() {
- state = false;
- }
- /*
- ===============
- idFuncAASPortal::Save
- ===============
- */
- void idFuncAASPortal::Save( idSaveGame *savefile ) const {
- savefile->WriteBool( state );
- }
- /*
- ===============
- idFuncAASPortal::Restore
- ===============
- */
- void idFuncAASPortal::Restore( idRestoreGame *savefile ) {
- savefile->ReadBool( state );
- gameLocal.SetAASAreaState( GetPhysics()->GetAbsBounds(), AREACONTENTS_CLUSTERPORTAL, state );
- }
- /*
- ===============
- idFuncAASPortal::Spawn
- ===============
- */
- void idFuncAASPortal::Spawn( void ) {
- state = spawnArgs.GetBool( "start_on" );
- gameLocal.SetAASAreaState( GetPhysics()->GetAbsBounds(), AREACONTENTS_CLUSTERPORTAL, state );
- }
- /*
- ================
- idFuncAASPortal::Event_Activate
- ================
- */
- void idFuncAASPortal::Event_Activate( idEntity *activator ) {
- state ^= 1;
- gameLocal.SetAASAreaState( GetPhysics()->GetAbsBounds(), AREACONTENTS_CLUSTERPORTAL, state );
- }
- /*
- ===============================================================================
- idFuncAASObstacle
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idFuncAASObstacle )
- EVENT( EV_Activate, idFuncAASObstacle::Event_Activate )
- END_CLASS
- /*
- ===============
- idFuncAASObstacle::idFuncAASObstacle
- ===============
- */
- idFuncAASObstacle::idFuncAASObstacle() {
- state = false;
- }
- /*
- ===============
- idFuncAASObstacle::Save
- ===============
- */
- void idFuncAASObstacle::Save( idSaveGame *savefile ) const {
- savefile->WriteBool( state );
- }
- /*
- ===============
- idFuncAASObstacle::Restore
- ===============
- */
- void idFuncAASObstacle::Restore( idRestoreGame *savefile ) {
- savefile->ReadBool( state );
- gameLocal.SetAASAreaState( GetPhysics()->GetAbsBounds(), AREACONTENTS_OBSTACLE, state );
- }
- /*
- ===============
- idFuncAASObstacle::Spawn
- ===============
- */
- void idFuncAASObstacle::Spawn( void ) {
- state = spawnArgs.GetBool( "start_on" );
- gameLocal.SetAASAreaState( GetPhysics()->GetAbsBounds(), AREACONTENTS_OBSTACLE, state );
- }
- /*
- ================
- idFuncAASObstacle::Event_Activate
- ================
- */
- void idFuncAASObstacle::Event_Activate( idEntity *activator ) {
- state ^= 1;
- gameLocal.SetAASAreaState( GetPhysics()->GetAbsBounds(), AREACONTENTS_OBSTACLE, state );
- }
- /*
- ===============================================================================
- idFuncRadioChatter
- ===============================================================================
- */
- const idEventDef EV_ResetRadioHud( "<resetradiohud>", "e" );
- CLASS_DECLARATION( idEntity, idFuncRadioChatter )
- EVENT( EV_Activate, idFuncRadioChatter::Event_Activate )
- EVENT( EV_ResetRadioHud, idFuncRadioChatter::Event_ResetRadioHud )
- END_CLASS
- /*
- ===============
- idFuncRadioChatter::idFuncRadioChatter
- ===============
- */
- idFuncRadioChatter::idFuncRadioChatter() {
- time = 0.0;
- }
- /*
- ===============
- idFuncRadioChatter::Save
- ===============
- */
- void idFuncRadioChatter::Save( idSaveGame *savefile ) const {
- savefile->WriteFloat( time );
- }
- /*
- ===============
- idFuncRadioChatter::Restore
- ===============
- */
- void idFuncRadioChatter::Restore( idRestoreGame *savefile ) {
- savefile->ReadFloat( time );
- }
- /*
- ===============
- idFuncRadioChatter::Spawn
- ===============
- */
- void idFuncRadioChatter::Spawn( void ) {
- time = spawnArgs.GetFloat( "time", "5.0" );
- }
- /*
- ================
- idFuncRadioChatter::Event_Activate
- ================
- */
- void idFuncRadioChatter::Event_Activate( idEntity *activator ) {
- idPlayer *player;
- const char *sound;
- const idSoundShader *shader;
- int length;
-
- if ( activator->IsType( idPlayer::Type ) ) {
- player = static_cast<idPlayer *>( activator );
- } else {
- player = gameLocal.GetLocalPlayer();
- }
- player->hud->HandleNamedEvent( "radioChatterUp" );
- sound = spawnArgs.GetString( "snd_radiochatter", "" );
- if ( sound && *sound ) {
- shader = declManager->FindSound( sound );
- player->StartSoundShader( shader, SND_CHANNEL_RADIO, SSF_GLOBAL, false, &length );
- time = MS2SEC( length + 150 );
- }
- // we still put the hud up because this is used with no sound on
- // certain frame commands when the chatter is triggered
- PostEventSec( &EV_ResetRadioHud, time, player );
- }
- /*
- ================
- idFuncRadioChatter::Event_ResetRadioHud
- ================
- */
- void idFuncRadioChatter::Event_ResetRadioHud( idEntity *activator ) {
- idPlayer *player = ( activator->IsType( idPlayer::Type ) ) ? static_cast<idPlayer *>( activator ) : gameLocal.GetLocalPlayer();
- player->hud->HandleNamedEvent( "radioChatterDown" );
- ActivateTargets( activator );
- }
- /*
- ===============================================================================
- idPhantomObjects
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idPhantomObjects )
- EVENT( EV_Activate, idPhantomObjects::Event_Activate )
- END_CLASS
- /*
- ===============
- idPhantomObjects::idPhantomObjects
- ===============
- */
- idPhantomObjects::idPhantomObjects() {
- target = NULL;
- end_time = 0;
- throw_time = 0.0f;
- shake_time = 0.0f;
- shake_ang.Zero();
- speed = 0.0f;
- min_wait = 0;
- max_wait = 0;
- fl.neverDormant = false;
- }
- /*
- ===============
- idPhantomObjects::Save
- ===============
- */
- void idPhantomObjects::Save( idSaveGame *savefile ) const {
- int i;
- savefile->WriteInt( end_time );
- savefile->WriteFloat( throw_time );
- savefile->WriteFloat( shake_time );
- savefile->WriteVec3( shake_ang );
- savefile->WriteFloat( speed );
- savefile->WriteInt( min_wait );
- savefile->WriteInt( max_wait );
- target.Save( savefile );
- savefile->WriteInt( targetTime.Num() );
- for( i = 0; i < targetTime.Num(); i++ ) {
- savefile->WriteInt( targetTime[ i ] );
- }
- for( i = 0; i < lastTargetPos.Num(); i++ ) {
- savefile->WriteVec3( lastTargetPos[ i ] );
- }
- }
- /*
- ===============
- idPhantomObjects::Restore
- ===============
- */
- void idPhantomObjects::Restore( idRestoreGame *savefile ) {
- int num;
- int i;
- savefile->ReadInt( end_time );
- savefile->ReadFloat( throw_time );
- savefile->ReadFloat( shake_time );
- savefile->ReadVec3( shake_ang );
- savefile->ReadFloat( speed );
- savefile->ReadInt( min_wait );
- savefile->ReadInt( max_wait );
- target.Restore( savefile );
-
- savefile->ReadInt( num );
- targetTime.SetGranularity( 1 );
- targetTime.SetNum( num );
- lastTargetPos.SetGranularity( 1 );
- lastTargetPos.SetNum( num );
- for( i = 0; i < num; i++ ) {
- savefile->ReadInt( targetTime[ i ] );
- }
- for( i = 0; i < num; i++ ) {
- savefile->ReadVec3( lastTargetPos[ i ] );
- }
- }
- /*
- ===============
- idPhantomObjects::Spawn
- ===============
- */
- void idPhantomObjects::Spawn( void ) {
- throw_time = spawnArgs.GetFloat( "time", "5" );
- speed = spawnArgs.GetFloat( "speed", "1200" );
- shake_time = spawnArgs.GetFloat( "shake_time", "1" );
- throw_time -= shake_time;
- if ( throw_time < 0.0f ) {
- throw_time = 0.0f;
- }
- min_wait = SEC2MS( spawnArgs.GetFloat( "min_wait", "1" ) );
- max_wait = SEC2MS( spawnArgs.GetFloat( "max_wait", "3" ) );
- shake_ang = spawnArgs.GetVector( "shake_ang", "65 65 65" );
- Hide();
- GetPhysics()->SetContents( 0 );
- }
- /*
- ================
- idPhantomObjects::Event_Activate
- ================
- */
- void idPhantomObjects::Event_Activate( idEntity *activator ) {
- int i;
- float time;
- float frac;
- float scale;
- if ( thinkFlags & TH_THINK ) {
- BecomeInactive( TH_THINK );
- return;
- }
- RemoveNullTargets();
- if ( !targets.Num() ) {
- return;
- }
- if ( !activator || !activator->IsType( idActor::Type ) ) {
- target = gameLocal.GetLocalPlayer();
- } else {
- target = static_cast<idActor *>( activator );
- }
-
- end_time = gameLocal.time + SEC2MS( spawnArgs.GetFloat( "end_time", "0" ) );
- targetTime.SetNum( targets.Num() );
- lastTargetPos.SetNum( targets.Num() );
- const idVec3 &toPos = target.GetEntity()->GetEyePosition();
- // calculate the relative times of all the objects
- time = 0.0f;
- for( i = 0; i < targetTime.Num(); i++ ) {
- targetTime[ i ] = SEC2MS( time );
- lastTargetPos[ i ] = toPos;
- frac = 1.0f - ( float )i / ( float )targetTime.Num();
- time += ( gameLocal.random.RandomFloat() + 1.0f ) * 0.5f * frac + 0.1f;
- }
- // scale up the times to fit within throw_time
- scale = throw_time / time;
- for( i = 0; i < targetTime.Num(); i++ ) {
- targetTime[ i ] = gameLocal.time + SEC2MS( shake_time )+ targetTime[ i ] * scale;
- }
- BecomeActive( TH_THINK );
- }
- /*
- ===============
- idPhantomObjects::Think
- ================
- */
- void idPhantomObjects::Think( void ) {
- int i;
- int num;
- float time;
- idVec3 vel;
- idVec3 ang;
- idEntity *ent;
- idActor *targetEnt;
- idPhysics *entPhys;
- trace_t tr;
- // if we are completely closed off from the player, don't do anything at all
- if ( CheckDormant() ) {
- return;
- }
- if ( !( thinkFlags & TH_THINK ) ) {
- BecomeInactive( thinkFlags & ~TH_THINK );
- return;
- }
- targetEnt = target.GetEntity();
- if ( !targetEnt || ( targetEnt->health <= 0 ) || ( end_time && ( gameLocal.time > end_time ) ) || gameLocal.inCinematic ) {
- BecomeInactive( TH_THINK );
- }
- const idVec3 &toPos = targetEnt->GetEyePosition();
- num = 0;
- for ( i = 0; i < targets.Num(); i++ ) {
- ent = targets[ i ].GetEntity();
- if ( !ent ) {
- continue;
- }
-
- if ( ent->fl.hidden ) {
- // don't throw hidden objects
- continue;
- }
- if ( !targetTime[ i ] ) {
- // already threw this object
- continue;
- }
- num++;
- time = MS2SEC( targetTime[ i ] - gameLocal.time );
- if ( time > shake_time ) {
- continue;
- }
- entPhys = ent->GetPhysics();
- const idVec3 &entOrg = entPhys->GetOrigin();
- gameLocal.clip.TracePoint( tr, entOrg, toPos, MASK_OPAQUE, ent );
- if ( tr.fraction >= 1.0f || ( gameLocal.GetTraceEntity( tr ) == targetEnt ) ) {
- lastTargetPos[ i ] = toPos;
- }
- if ( time < 0.0f ) {
- idAI::PredictTrajectory( entPhys->GetOrigin(), lastTargetPos[ i ], speed, entPhys->GetGravity(),
- entPhys->GetClipModel(), entPhys->GetClipMask(), 256.0f, ent, targetEnt, ai_debugTrajectory.GetBool() ? 1 : 0, vel );
- vel *= speed;
- entPhys->SetLinearVelocity( vel );
- if ( !end_time ) {
- targetTime[ i ] = 0;
- } else {
- targetTime[ i ] = gameLocal.time + gameLocal.random.RandomInt( max_wait - min_wait ) + min_wait;
- }
- if ( ent->IsType( idMoveable::Type ) ) {
- idMoveable *ment = static_cast<idMoveable*>( ent );
- ment->EnableDamage( true, 2.5f );
- }
- } else {
- // this is not the right way to set the angular velocity, but the effect is nice, so I'm keeping it. :)
- ang.Set( gameLocal.random.CRandomFloat() * shake_ang.x, gameLocal.random.CRandomFloat() * shake_ang.y, gameLocal.random.CRandomFloat() * shake_ang.z );
- ang *= ( 1.0f - time / shake_time );
- entPhys->SetAngularVelocity( ang );
- }
- }
- if ( !num ) {
- BecomeInactive( TH_THINK );
- }
- }
- #ifdef _D3XP
- /*
- ===============================================================================
- idShockwave
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idShockwave )
- EVENT( EV_Activate, idShockwave::Event_Activate )
- END_CLASS
- /*
- ===============
- idShockwave::idShockwave
- ===============
- */
- idShockwave::idShockwave() {
- isActive = false;
- startTime = 0;
- duration = 0;
- startSize = 0.f;
- endSize = 0.f;
- currentSize = 0.f;
- magnitude = 0.f;
- height = 0.0f;
- playerDamaged = false;
- playerDamageSize = 0.0f;
- }
- /*
- ===============
- idShockwave::~idShockwave
- ===============
- */
- idShockwave::~idShockwave() {
- }
- /*
- ===============
- idShockwave::Save
- ===============
- */
- void idShockwave::Save( idSaveGame *savefile ) const {
- savefile->WriteBool( isActive );
- savefile->WriteInt( startTime );
- savefile->WriteInt( duration );
- savefile->WriteFloat( startSize );
- savefile->WriteFloat( endSize );
- savefile->WriteFloat( currentSize );
- savefile->WriteFloat( magnitude );
- savefile->WriteFloat( height );
- savefile->WriteBool( playerDamaged );
- savefile->WriteFloat( playerDamageSize );
- }
- /*
- ===============
- idShockwave::Restore
- ===============
- */
- void idShockwave::Restore( idRestoreGame *savefile ) {
- savefile->ReadBool( isActive );
- savefile->ReadInt( startTime );
- savefile->ReadInt( duration );
- savefile->ReadFloat( startSize );
- savefile->ReadFloat( endSize );
- savefile->ReadFloat( currentSize );
- savefile->ReadFloat( magnitude );
- savefile->ReadFloat( height );
- savefile->ReadBool( playerDamaged );
- savefile->ReadFloat( playerDamageSize );
-
- }
- /*
- ===============
- idShockwave::Spawn
- ===============
- */
- void idShockwave::Spawn() {
- spawnArgs.GetInt( "duration", "1000", duration );
- spawnArgs.GetFloat( "startsize", "8", startSize );
- spawnArgs.GetFloat( "endsize", "512", endSize );
- spawnArgs.GetFloat( "magnitude", "100", magnitude );
- spawnArgs.GetFloat( "height", "0", height);
- spawnArgs.GetFloat( "player_damage_size", "20", playerDamageSize);
- if ( spawnArgs.GetBool( "start_on" ) ) {
- ProcessEvent( &EV_Activate, this );
- }
- }
- /*
- ===============
- idShockwave::Think
- ===============
- */
- void idShockwave::Think() {
- int endTime;
- if ( !isActive ) {
- BecomeInactive( TH_THINK );
- return;
- }
- endTime = startTime + duration;
- if ( gameLocal.time < endTime ) {
- float u;
- float newSize;
- // Expand shockwave
- u = (float)(gameLocal.time - startTime) / (float)duration;
- newSize = startSize + u * (endSize - startSize);
- // Find all clipmodels between currentSize and newSize
- idVec3 pos, end;
- idClipModel *clipModelList[ MAX_GENTITIES ];
- idClipModel *clip;
- idEntity *ent;
- int i, listedClipModels;
- // Set bounds
- pos = GetPhysics()->GetOrigin();
- float zVal;
- if(!height) {
- zVal = newSize;
- } else {
- zVal = height/2.0f;
- }
-
- //Expand in a sphere
- end = pos + idVec3( newSize, newSize, zVal );
- idBounds bounds( end );
- end = pos + idVec3( -newSize, -newSize, -zVal );
- bounds.AddPoint( end );
-
- if(g_debugShockwave.GetBool()) {
- gameRenderWorld->DebugBounds(colorRed, bounds, vec3_origin);
- }
- listedClipModels = gameLocal.clip.ClipModelsTouchingBounds( bounds, -1, clipModelList, MAX_GENTITIES );
- for ( i = 0; i < listedClipModels; i++ ) {
- clip = clipModelList[ i ];
- ent = clip->GetEntity();
- if ( ent->IsHidden() ) {
- continue;
- }
- if ( !ent->IsType( idMoveable::Type ) && !ent->IsType( idAFEntity_Base::Type ) && !ent->IsType( idPlayer::Type )) {
- continue;
- }
- idVec3 point = ent->GetPhysics()->GetOrigin();
- idVec3 force = point - pos;
- float dist = force.Normalize();
- if(ent->IsType( idPlayer::Type )) {
- if(ent->GetPhysics()->GetAbsBounds().IntersectsBounds(bounds)) {
-
- //For player damage we check the current radius and a specified player damage ring size
- if ( dist <= newSize && dist > newSize-playerDamageSize ) {
- idStr damageDef = spawnArgs.GetString("def_player_damage", "");
- if(damageDef.Length() > 0 && !playerDamaged) {
- playerDamaged = true; //Only damage once per shockwave
- idPlayer* player = static_cast< idPlayer* >( ent );
- idVec3 dir = ent->GetPhysics()->GetOrigin() - pos;
- dir.NormalizeFast();
- player->Damage(NULL, NULL, dir, damageDef, 1.0f, INVALID_JOINT);
- }
- }
- }
- } else {
- // If the object is inside the current expansion...
- if ( dist <= newSize && dist > currentSize ) {
- force.z += 4.f;
- force.NormalizeFast();
- if ( ent->IsType( idAFEntity_Base::Type ) ) {
- force = force * (ent->GetPhysics()->GetMass() * magnitude * 0.01f);
- } else {
- force = force * ent->GetPhysics()->GetMass() * magnitude;
- }
- // Kick it up, move force point off object origin
- float rad = ent->GetPhysics()->GetBounds().GetRadius();
- point.x += gameLocal.random.CRandomFloat() * rad;
- point.y += gameLocal.random.CRandomFloat() * rad;
- int j;
- for( j=0; j < ent->GetPhysics()->GetNumClipModels(); j++ ) {
- ent->GetPhysics()->AddForce( j, point, force );
- }
- }
- }
- }
- // Update currentSize for next frame
- currentSize = newSize;
- } else {
- // turn off
- isActive = false;
- }
- }
- /*
- ===============
- idShockwave::Event_Activate
- ===============
- */
- void idShockwave::Event_Activate( idEntity *activator ) {
- isActive = true;
- startTime = gameLocal.time;
- playerDamaged = false;
- BecomeActive( TH_THINK );
- }
- /*
- ===============================================================================
- idFuncMountedObject
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idFuncMountedObject )
- EVENT( EV_Touch, idFuncMountedObject::Event_Touch )
- EVENT( EV_Activate, idFuncMountedObject::Event_Activate )
- END_CLASS
- /*
- ===============
- idFuncMountedObject::idFuncMountedObject
- ===============
- */
- idFuncMountedObject::idFuncMountedObject() {
- isMounted = false;
- scriptFunction = NULL;
- mountedPlayer = NULL;
- harc = 0;
- varc = 0;
- }
- /*
- ===============
- idFuncMountedObject::idFuncMountedObject
- ===============
- */
- idFuncMountedObject::~idFuncMountedObject() {
- }
- /*
- ===============
- idFuncMountedObject::Spawn
- ===============
- */
- void idFuncMountedObject::Spawn( void ) {
- // Get viewOffset
- spawnArgs.GetInt( "harc", "45", harc );
- spawnArgs.GetInt( "varc", "30", varc );
- // Get script function
- idStr funcName = spawnArgs.GetString( "call", "" );
- if ( funcName.Length() ) {
- scriptFunction = gameLocal.program.FindFunction( funcName );
- if ( scriptFunction == NULL ) {
- gameLocal.Warning( "idFuncMountedObject '%s' at (%s) calls unknown function '%s'\n", name.c_str(), GetPhysics()->GetOrigin().ToString(0), funcName.c_str() );
- }
- }
- BecomeActive( TH_THINK );
- }
- /*
- ================
- idFuncMountedObject::Think
- ================
- */
- void idFuncMountedObject::Think( void ) {
- idEntity::Think();
- }
- /*
- ================
- idFuncMountedObject::GetViewInfo
- ================
- */
- void idFuncMountedObject::GetAngleRestrictions( int &yaw_min, int &yaw_max, int &pitch ) {
- idMat3 axis;
- idAngles angs;
- axis = GetPhysics()->GetAxis();
- angs = axis.ToAngles();
- yaw_min = angs.yaw - harc;
- yaw_min = idMath::AngleNormalize180( yaw_min );
- yaw_max = angs.yaw + harc;
- yaw_max = idMath::AngleNormalize180( yaw_max );
- pitch = varc;
- }
- /*
- ================
- idFuncMountedObject::Event_Touch
- ================
- */
- void idFuncMountedObject::Event_Touch( idEntity *other, trace_t *trace ) {
- ProcessEvent( &EV_Activate, other );
- }
- /*
- ================
- idFuncMountedObject::Event_Activate
- ================
- */
- void idFuncMountedObject::Event_Activate( idEntity *activator ) {
- if ( !isMounted && activator->IsType( idPlayer::Type ) ) {
- idPlayer *client = (idPlayer *)activator;
- mountedPlayer = client;
- /*
- // Place player at path_corner targeted by mounted object
- int i;
- idPathCorner *spot;
- for ( i = 0; i < targets.Num(); i++ ) {
- if ( targets[i]->IsType( idPathCorner::Type ) ) {
- spot = (idPathCorner*)targets[i];
- break;
- }
- }
- mountedPlayer->GetPhysics()->SetOrigin( spot->GetPhysics()->GetOrigin() );
- mountedPlayer->GetPhysics()->SetAxis( spot->GetPhysics()->GetAxis() );
- */
- mountedPlayer->Bind( this, true );
- mountedPlayer->mountedObject = this;
- // Call a script function
- idThread *mountthread;
- if ( scriptFunction ) {
- mountthread = new idThread( scriptFunction );
- mountthread->DelayedStart( 0 );
- }
- isMounted = true;
- }
- }
- /*
- ===============================================================================
- idFuncMountedWeapon
- ===============================================================================
- */
- CLASS_DECLARATION( idFuncMountedObject, idFuncMountedWeapon )
- EVENT( EV_PostSpawn, idFuncMountedWeapon::Event_PostSpawn )
- END_CLASS
- idFuncMountedWeapon::idFuncMountedWeapon() {
- turret = NULL;
- weaponLastFireTime = 0;
- weaponFireDelay = 0;
- projectile = NULL;
- }
- idFuncMountedWeapon::~idFuncMountedWeapon() {
- }
- void idFuncMountedWeapon::Spawn( void ) {
- // Get projectile info
- projectile = gameLocal.FindEntityDefDict( spawnArgs.GetString( "def_projectile" ), false );
- if ( !projectile ) {
- gameLocal.Warning( "Invalid projectile on func_mountedweapon." );
- }
- float firerate;
- spawnArgs.GetFloat( "firerate", "3", firerate );
- weaponFireDelay = 1000.f / firerate;
- // Get the firing sound
- idStr fireSound;
- spawnArgs.GetString( "snd_fire", "", fireSound );
- soundFireWeapon = declManager->FindSound( fireSound );
- PostEventMS( &EV_PostSpawn, 0 );
- }
- void idFuncMountedWeapon::Think( void ) {
- if ( isMounted && turret ) {
- idVec3 vec = mountedPlayer->viewAngles.ToForward();
- idAngles ang = mountedPlayer->GetLocalVector( vec ).ToAngles();
- turret->GetPhysics()->SetAxis( ang.ToMat3() );
- turret->UpdateVisuals();
- // Check for firing
- if ( mountedPlayer->usercmd.buttons & BUTTON_ATTACK && ( gameLocal.time > weaponLastFireTime + weaponFireDelay ) ) {
- // FIRE!
- idEntity *ent;
- idProjectile *proj;
- idBounds projBounds;
- idVec3 dir;
- gameLocal.SpawnEntityDef( *projectile, &ent );
- if ( !ent || !ent->IsType( idProjectile::Type ) ) {
- const char *projectileName = spawnArgs.GetString( "def_projectile" );
- gameLocal.Error( "'%s' is not an idProjectile", projectileName );
- }
- mountedPlayer->GetViewPos( muzzleOrigin, muzzleAxis );
- muzzleOrigin += ( muzzleAxis[0] * 128 );
- muzzleOrigin -= ( muzzleAxis[2] * 20 );
- dir = muzzleAxis[0];
- proj = static_cast<idProjectile *>(ent);
- proj->Create( this, muzzleOrigin, dir );
- projBounds = proj->GetPhysics()->GetBounds().Rotate( proj->GetPhysics()->GetAxis() );
- proj->Launch( muzzleOrigin, dir, vec3_origin );
- StartSoundShader( soundFireWeapon, SND_CHANNEL_WEAPON, SSF_GLOBAL, false, NULL );
- weaponLastFireTime = gameLocal.time;
- }
- }
- idFuncMountedObject::Think();
- }
- void idFuncMountedWeapon::Event_PostSpawn( void ) {
- if ( targets.Num() >= 1 ) {
- for ( int i=0; i < targets.Num(); i++ ) {
- if ( targets[i].GetEntity()->IsType( idStaticEntity::Type ) ) {
- turret = targets[i].GetEntity();
- break;
- }
- }
- } else {
- gameLocal.Warning( "idFuncMountedWeapon::Spawn: Please target one model for a turret\n" );
- }
- }
- /*
- ===============================================================================
- idPortalSky
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idPortalSky )
- EVENT( EV_PostSpawn, idPortalSky::Event_PostSpawn )
- EVENT( EV_Activate, idPortalSky::Event_Activate )
- END_CLASS
- /*
- ===============
- idPortalSky::idPortalSky
- ===============
- */
- idPortalSky::idPortalSky( void ) {
- }
- /*
- ===============
- idPortalSky::~idPortalSky
- ===============
- */
- idPortalSky::~idPortalSky( void ) {
- }
- /*
- ===============
- idPortalSky::Spawn
- ===============
- */
- void idPortalSky::Spawn( void ) {
- if ( !spawnArgs.GetBool( "triggered" ) ) {
- PostEventMS( &EV_PostSpawn, 1 );
- }
- }
- /*
- ================
- idPortalSky::Event_PostSpawn
- ================
- */
- void idPortalSky::Event_PostSpawn() {
- gameLocal.SetPortalSkyEnt( this );
- }
- /*
- ================
- idPortalSky::Event_Activate
- ================
- */
- void idPortalSky::Event_Activate( idEntity *activator ) {
- gameLocal.SetPortalSkyEnt( this );
- }
- #endif /* _D3XP */
|