123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition 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 BFG Edition 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 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition 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 BFG Edition 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.
- ===========================================================================
- */
- #include "../idlib/precompiled.h"
- #pragma hdrstop
- #include "Game_local.h"
- /*
- ===============================================================================
- idItem
- ===============================================================================
- */
- const idEventDef EV_DropToFloor( "<dropToFloor>" );
- const idEventDef EV_RespawnItem( "respawn" );
- const idEventDef EV_RespawnFx( "<respawnFx>" );
- const idEventDef EV_GetPlayerPos( "<getplayerpos>" );
- const idEventDef EV_HideObjective( "<hideobjective>", "e" );
- CLASS_DECLARATION( idEntity, idItem )
- EVENT( EV_DropToFloor, idItem::Event_DropToFloor )
- EVENT( EV_Touch, idItem::Event_Touch )
- EVENT( EV_Activate, idItem::Event_Trigger )
- EVENT( EV_RespawnItem, idItem::Event_Respawn )
- EVENT( EV_RespawnFx, idItem::Event_RespawnFx )
- END_CLASS
- /*
- ================
- idItem::idItem
- ================
- */
- idItem::idItem() :
- clientPredictPickupMilliseconds( 0 ) {
- spin = false;
- inView = false;
- inViewTime = 0;
- lastCycle = 0;
- lastRenderViewTime = -1;
- itemShellHandle = -1;
- shellMaterial = NULL;
- orgOrigin.Zero();
- canPickUp = true;
- fl.networkSync = true;
- }
- /*
- ================
- idItem::~idItem
- ================
- */
- idItem::~idItem() {
- // remove the highlight shell
- if ( itemShellHandle != -1 ) {
- gameRenderWorld->FreeEntityDef( itemShellHandle );
- }
- }
- /*
- ================
- idItem::Save
- ================
- */
- void idItem::Save( idSaveGame *savefile ) const {
- savefile->WriteVec3( orgOrigin );
- savefile->WriteBool( spin );
- savefile->WriteBool( pulse );
- savefile->WriteBool( canPickUp );
- savefile->WriteMaterial( shellMaterial );
- savefile->WriteBool( inView );
- savefile->WriteInt( inViewTime );
- savefile->WriteInt( lastCycle );
- savefile->WriteInt( lastRenderViewTime );
- }
- /*
- ================
- idItem::Restore
- ================
- */
- void idItem::Restore( idRestoreGame *savefile ) {
- savefile->ReadVec3( orgOrigin );
- savefile->ReadBool( spin );
- savefile->ReadBool( pulse );
- savefile->ReadBool( canPickUp );
- savefile->ReadMaterial( shellMaterial );
- savefile->ReadBool( inView );
- savefile->ReadInt( inViewTime );
- savefile->ReadInt( lastCycle );
- savefile->ReadInt( lastRenderViewTime );
- itemShellHandle = -1;
- }
- /*
- ================
- idItem::UpdateRenderEntity
- ================
- */
- bool idItem::UpdateRenderEntity( renderEntity_s *renderEntity, const renderView_t *renderView ) const {
- if ( lastRenderViewTime == renderView->time[timeGroup] ) {
- return false;
- }
- lastRenderViewTime = renderView->time[timeGroup];
- // check for glow highlighting if near the center of the view
- idVec3 dir = renderEntity->origin - renderView->vieworg;
- dir.Normalize();
- float d = dir * renderView->viewaxis[0];
- // two second pulse cycle
- float cycle = ( renderView->time[timeGroup] - inViewTime ) / 2000.0f;
- if ( d > 0.94f ) {
- if ( !inView ) {
- inView = true;
- if ( cycle > lastCycle ) {
- // restart at the beginning
- inViewTime = renderView->time[timeGroup];
- cycle = 0.0f;
- }
- }
- } else {
- if ( inView ) {
- inView = false;
- lastCycle = ceil( cycle );
- }
- }
- // fade down after the last pulse finishes
- if ( !inView && cycle > lastCycle ) {
- renderEntity->shaderParms[4] = 0.0f;
- } else {
- // pulse up in 1/4 second
- cycle -= (int)cycle;
- if ( cycle < 0.1f ) {
- renderEntity->shaderParms[4] = cycle * 10.0f;
- } else if ( cycle < 0.2f ) {
- renderEntity->shaderParms[4] = 1.0f;
- } else if ( cycle < 0.3f ) {
- renderEntity->shaderParms[4] = 1.0f - ( cycle - 0.2f ) * 10.0f;
- } else {
- // stay off between pulses
- renderEntity->shaderParms[4] = 0.0f;
- }
- }
- // update every single time this is in view
- return true;
- }
- /*
- ================
- idItem::ModelCallback
- ================
- */
- bool idItem::ModelCallback( renderEntity_t *renderEntity, const renderView_t *renderView ) {
- const idItem *ent;
- // this may be triggered by a model trace or other non-view related source
- if ( !renderView ) {
- return false;
- }
- ent = static_cast<idItem *>(gameLocal.entities[ renderEntity->entityNum ]);
- if ( ent == NULL ) {
- gameLocal.Error( "idItem::ModelCallback: callback with NULL game entity" );
- return false;
- }
- return ent->UpdateRenderEntity( renderEntity, renderView );
- }
- /*
- ================
- idItem::Think
- ================
- */
- void idItem::Think() {
- if ( thinkFlags & TH_THINK ) {
- if ( spin ) {
- idAngles ang;
- idVec3 org;
- ang.pitch = ang.roll = 0.0f;
- ang.yaw = ( gameLocal.time & 4095 ) * 360.0f / -4096.0f;
- SetAngles( ang );
- float scale = 0.005f + entityNumber * 0.00001f;
-
- org = orgOrigin;
- org.z += 4.0f + cos( ( gameLocal.time + 2000 ) * scale ) * 4.0f;
- SetOrigin( org );
- }
- }
- Present();
- }
- /*
- ================
- idItem::Present
- ================
- */
- void idItem::Present() {
- idEntity::Present();
- if ( !fl.hidden && pulse ) {
- // also add a highlight shell model
- renderEntity_t shell;
- shell = renderEntity;
- // we will mess with shader parms when the item is in view
- // to give the "item pulse" effect
- shell.callback = idItem::ModelCallback;
- shell.entityNum = entityNumber;
- shell.customShader = shellMaterial;
- if ( itemShellHandle == -1 ) {
- itemShellHandle = gameRenderWorld->AddEntityDef( &shell );
- } else {
- gameRenderWorld->UpdateEntityDef( itemShellHandle, &shell );
- }
- }
- }
- /*
- ================
- idItem::Spawn
- ================
- */
- void idItem::Spawn() {
- idStr giveTo;
- idEntity * ent;
- float tsize;
- if ( spawnArgs.GetBool( "dropToFloor" ) ) {
- PostEventMS( &EV_DropToFloor, 0 );
- }
- if ( spawnArgs.GetFloat( "triggersize", "0", tsize ) ) {
- GetPhysics()->GetClipModel()->LoadModel( idTraceModel( idBounds( vec3_origin ).Expand( tsize ) ) );
- GetPhysics()->GetClipModel()->Link( gameLocal.clip );
- }
- if ( spawnArgs.GetBool( "start_off" ) ) {
- GetPhysics()->SetContents( 0 );
- Hide();
- } else {
- GetPhysics()->SetContents( CONTENTS_TRIGGER );
- }
- giveTo = spawnArgs.GetString( "owner" );
- if ( giveTo.Length() ) {
- ent = gameLocal.FindEntity( giveTo );
- if ( !ent ) {
- gameLocal.Error( "Item couldn't find owner '%s'", giveTo.c_str() );
- }
- PostEventMS( &EV_Touch, 0, ent, NULL );
- }
- // idItemTeam does not rotate and bob
- if ( spawnArgs.GetBool( "spin" ) || (common->IsMultiplayer() && !this->IsType( idItemTeam::Type ) ) ) {
- spin = true;
- BecomeActive( TH_THINK );
- }
- //pulse = !spawnArgs.GetBool( "nopulse" );
- //temp hack for tim
- pulse = false;
- orgOrigin = GetPhysics()->GetOrigin();
- canPickUp = !( spawnArgs.GetBool( "triggerFirst" ) || spawnArgs.GetBool( "no_touch" ) );
- inViewTime = -1000;
- lastCycle = -1;
- itemShellHandle = -1;
- shellMaterial = declManager->FindMaterial( "itemHighlightShell" );
- }
- /*
- ================
- idItem::GetAttributes
- ================
- */
- void idItem::GetAttributes( idDict &attributes ) const {
- int i;
- const idKeyValue *arg;
- for( i = 0; i < spawnArgs.GetNumKeyVals(); i++ ) {
- arg = spawnArgs.GetKeyVal( i );
- if ( arg->GetKey().Left( 4 ) == "inv_" ) {
- attributes.Set( arg->GetKey().Right( arg->GetKey().Length() - 4 ), arg->GetValue() );
- }
- }
- }
- /*
- ================
- idItem::GiveToPlayer
- ================
- */
- bool idItem::GiveToPlayer( idPlayer *player, unsigned int giveFlags ) {
- if ( player == NULL ) {
- return false;
- }
- if ( spawnArgs.GetBool( "inv_carry" ) ) {
- return player->GiveInventoryItem( &spawnArgs, giveFlags );
- }
-
- return player->GiveItem( this, giveFlags );
- }
- /*
- ================
- idItem::Pickup
- ================
- */
- bool idItem::Pickup( idPlayer *player ) {
-
- const bool didGiveSucceed = GiveToPlayer( player, ITEM_GIVE_FEEDBACK );
- if ( !didGiveSucceed ) {
- return false;
- }
- // Store the time so clients know when to stop predicting and let snapshots overwrite.
- if ( player->IsLocallyControlled() ) {
- clientPredictPickupMilliseconds = gameLocal.time;
- } else {
- clientPredictPickupMilliseconds = 0;
- }
-
- // play pickup sound
- StartSound( "snd_acquire", SND_CHANNEL_ITEM, 0, false, NULL );
- // clear our contents so the object isn't picked up twice
- GetPhysics()->SetContents( 0 );
- // hide the model
- Hide();
- // remove the highlight shell
- if ( itemShellHandle != -1 ) {
- gameRenderWorld->FreeEntityDef( itemShellHandle );
- itemShellHandle = -1;
- }
- // Clients need to bail out after some feedback, but
- // before actually changing any values. The values
- // will be updated in the next snapshot.
- if ( common->IsClient() ) {
- return didGiveSucceed;
- }
- if ( !GiveToPlayer( player, ITEM_GIVE_UPDATE_STATE ) ) {
- return false;
- }
- // trigger our targets
- ActivateTargets( player );
- float respawn = spawnArgs.GetFloat( "respawn" );
- bool dropped = spawnArgs.GetBool( "dropped" );
- bool no_respawn = spawnArgs.GetBool( "no_respawn" );
- if ( common->IsMultiplayer() && respawn == 0.0f ) {
- respawn = 20.0f;
- }
- if ( respawn && !dropped && !no_respawn ) {
- const char *sfx = spawnArgs.GetString( "fxRespawn" );
- if ( sfx != NULL && *sfx != NULL ) {
- PostEventSec( &EV_RespawnFx, respawn - 0.5f );
- }
- PostEventSec( &EV_RespawnItem, respawn );
- } else if ( !spawnArgs.GetBool( "inv_objective" ) && !no_respawn ) {
- // give some time for the pickup sound to play
- // FIXME: Play on the owner
- if ( !spawnArgs.GetBool( "inv_carry" ) ) {
- PostEventMS( &EV_Remove, 5000 );
- }
- }
- BecomeInactive( TH_THINK );
- return true;
- }
- /*
- ================
- idItem::ClientThink
- ================
- */
- void idItem::ClientThink( const int curTime, const float fraction, const bool predict ) {
-
- // only think forward because the state is not synced through snapshots
- if ( !gameLocal.isNewFrame ) {
- return;
- }
- Think();
- }
- /*
- ================
- idItem::ClientPredictionThink
- ================
- */
- void idItem::ClientPredictionThink() {
- // only think forward because the state is not synced through snapshots
- if ( !gameLocal.isNewFrame ) {
- return;
- }
- Think();
- }
- /*
- ================
- idItem::WriteFromSnapshot
- ================
- */
- void idItem::WriteToSnapshot( idBitMsg &msg ) const {
- msg.WriteBits( IsHidden(), 1 );
- }
- /*
- ================
- idItem::ReadFromSnapshot
- ================
- */
- void idItem::ReadFromSnapshot( const idBitMsg &msg ) {
- if ( msg.ReadBits( 1 ) ) {
- Hide();
- } else if ( clientPredictPickupMilliseconds != 0 ) {
- // Fix mispredictions
- if ( gameLocal.GetLastClientUsercmdMilliseconds( gameLocal.GetLocalClientNum() ) >= clientPredictPickupMilliseconds ) {
- if ( GetPhysics()->GetContents() == 0 ) {
- GetPhysics()->SetContents( CONTENTS_TRIGGER );
- }
- Show();
- }
- }
- }
- /*
- ================
- idItem::ClientReceiveEvent
- ================
- */
- bool idItem::ClientReceiveEvent( int event, int time, const idBitMsg &msg ) {
- switch( event ) {
- case EVENT_RESPAWN: {
- Event_Respawn();
- return true;
- }
- case EVENT_RESPAWNFX: {
- Event_RespawnFx();
- return true;
- }
- default: {
- return idEntity::ClientReceiveEvent( event, time, msg );
- }
- }
- }
- /*
- ================
- idItem::Event_DropToFloor
- ================
- */
- void idItem::Event_DropToFloor() {
- trace_t trace;
- // don't drop the floor if bound to another entity
- if ( GetBindMaster() != NULL && GetBindMaster() != this ) {
- return;
- }
- gameLocal.clip.TraceBounds( trace, renderEntity.origin, renderEntity.origin - idVec3( 0, 0, 64 ), renderEntity.bounds, MASK_SOLID | CONTENTS_CORPSE, this );
- SetOrigin( trace.endpos );
- }
- /*
- ================
- idItem::Event_Touch
- ================
- */
- void idItem::Event_Touch( idEntity *other, trace_t *trace ) {
- if ( !other->IsType( idPlayer::Type ) ) {
- return;
- }
- if ( !canPickUp ) {
- return;
- }
- Pickup( static_cast<idPlayer *>(other) );
- }
- /*
- ================
- idItem::Event_Trigger
- ================
- */
- void idItem::Event_Trigger( idEntity *activator ) {
- if ( !canPickUp && spawnArgs.GetBool( "triggerFirst" ) ) {
- canPickUp = true;
- return;
- }
- if ( activator && activator->IsType( idPlayer::Type ) ) {
- Pickup( static_cast<idPlayer *>( activator ) );
- }
- }
- /*
- ================
- idItem::Event_Respawn
- ================
- */
- void idItem::Event_Respawn() {
- if ( common->IsServer() ) {
- ServerSendEvent( EVENT_RESPAWN, NULL, false );
- }
- BecomeActive( TH_THINK );
- Show();
- inViewTime = -1000;
- lastCycle = -1;
- GetPhysics()->SetContents( CONTENTS_TRIGGER );
- SetOrigin( orgOrigin );
- StartSound( "snd_respawn", SND_CHANNEL_ITEM, 0, false, NULL );
- CancelEvents( &EV_RespawnItem ); // don't double respawn
- }
- /*
- ================
- idItem::Event_RespawnFx
- ================
- */
- void idItem::Event_RespawnFx() {
- if ( common->IsServer() ) {
- ServerSendEvent( EVENT_RESPAWNFX, NULL, false );
- }
- const char *sfx = spawnArgs.GetString( "fxRespawn" );
- if ( sfx != NULL && *sfx != NULL ) {
- idEntityFx::StartFx( sfx, NULL, NULL, this, true );
- }
- }
- /*
- ===============================================================================
- idItemPowerup
- ===============================================================================
- */
- /*
- ===============
- idItemPowerup
- ===============
- */
- CLASS_DECLARATION( idItem, idItemPowerup )
- END_CLASS
- /*
- ================
- idItemPowerup::idItemPowerup
- ================
- */
- idItemPowerup::idItemPowerup() {
- time = 0;
- type = 0;
- }
- /*
- ================
- idItemPowerup::Save
- ================
- */
- void idItemPowerup::Save( idSaveGame *savefile ) const {
- savefile->WriteInt( time );
- savefile->WriteInt( type );
- }
- /*
- ================
- idItemPowerup::Restore
- ================
- */
- void idItemPowerup::Restore( idRestoreGame *savefile ) {
- savefile->ReadInt( time );
- savefile->ReadInt( type );
- }
- /*
- ================
- idItemPowerup::Spawn
- ================
- */
- void idItemPowerup::Spawn() {
- time = spawnArgs.GetInt( "time", "30" );
- type = spawnArgs.GetInt( "type", "0" );
- }
- /*
- ================
- idItemPowerup::GiveToPlayer
- ================
- */
- bool idItemPowerup::GiveToPlayer( idPlayer *player, unsigned int giveFlags ) {
- if ( player->spectating ) {
- return false;
- }
- player->GivePowerUp( type, time * 1000, giveFlags );
- return true;
- }
- /*
- ===============================================================================
- idItemTeam
- Used for flags in Capture the Flag
- ===============================================================================
- */
- // temporarely removed these events
- const idEventDef EV_FlagReturn( "flagreturn", "e" );
- const idEventDef EV_TakeFlag( "takeflag", "e" );
- const idEventDef EV_DropFlag( "dropflag", "d" );
- const idEventDef EV_FlagCapture( "flagcapture" );
- CLASS_DECLARATION( idItem, idItemTeam )
- EVENT( EV_FlagReturn, idItemTeam::Event_FlagReturn )
- EVENT( EV_TakeFlag, idItemTeam::Event_TakeFlag )
- EVENT( EV_DropFlag, idItemTeam::Event_DropFlag )
- EVENT( EV_FlagCapture, idItemTeam::Event_FlagCapture )
- END_CLASS
- /*
- ===============
- idItemTeam::idItemTeam
- ===============
- */
- idItemTeam::idItemTeam() {
- team = -1;
- carried = false;
- dropped = false;
- lastDrop = 0;
- itemGlowHandle = -1;
- skinDefault = NULL;
- skinCarried = NULL;
- scriptTaken = NULL;
- scriptDropped = NULL;
- scriptReturned = NULL;
- scriptCaptured = NULL;
- lastNuggetDrop = 0;
- nuggetName = 0;
- }
- /*
- ===============
- idItemTeam::~idItemTeam
- ===============
- */
- idItemTeam::~idItemTeam() {
- FreeLightDef();
- }
- /*
- ===============
- idItemTeam::Spawn
- ===============
- */
- void idItemTeam::Spawn() {
- team = spawnArgs.GetInt( "team" );
- returnOrigin = GetPhysics()->GetOrigin() + idVec3( 0, 0, 20 );
- returnAxis = GetPhysics()->GetAxis();
- BecomeActive( TH_THINK );
- const char * skinName;
- skinName = spawnArgs.GetString( "skin", "" );
- if ( skinName[0] )
- skinDefault = declManager->FindSkin( skinName );
- skinName = spawnArgs.GetString( "skin_carried", "" );
- if ( skinName[0] )
- skinCarried = declManager->FindSkin( skinName );
- nuggetName = spawnArgs.GetString( "nugget_name", "" );
- if ( !nuggetName[0] ) {
- nuggetName = NULL;
- }
- scriptTaken = LoadScript( "script_taken" );
- scriptDropped = LoadScript( "script_dropped" );
- scriptReturned = LoadScript( "script_returned" );
- scriptCaptured = LoadScript( "script_captured" );
- /* Spawn attached dlight */
- /*
- idDict args;
- idVec3 lightOffset( 0.0f, 20.0f, 0.0f );
- // Set up the flag's dynamic light
- memset( &itemGlow, 0, sizeof( itemGlow ) );
- itemGlow.axis = mat3_identity;
- itemGlow.lightRadius.x = 128.0f;
- itemGlow.lightRadius.y = itemGlow.lightRadius.z = itemGlow.lightRadius.x;
- itemGlow.noShadows = true;
- itemGlow.pointLight = true;
- itemGlow.shaderParms[ SHADERPARM_RED ] = 0.0f;
- itemGlow.shaderParms[ SHADERPARM_GREEN ] = 0.0f;
- itemGlow.shaderParms[ SHADERPARM_BLUE ] = 0.0f;
- itemGlow.shaderParms[ SHADERPARM_ALPHA ] = 0.0f;
- // Select a shader based on the team
- if ( team == 0 )
- itemGlow.shader = declManager->FindMaterial( "lights/redflag" );
- else
- itemGlow.shader = declManager->FindMaterial( "lights/blueflag" );
- */
- idMoveableItem::Spawn();
- physicsObj.SetContents( 0 );
- physicsObj.SetClipMask( MASK_SOLID | CONTENTS_MOVEABLECLIP );
- physicsObj.SetGravity( idVec3( 0, 0, spawnArgs.GetInt("gravity", "-30" ) ) );
- }
- /*
- ===============
- idItemTeam::LoadScript
- ===============
- */
- function_t * idItemTeam::LoadScript( char * script ) {
- function_t * function = NULL;
- idStr funcname = spawnArgs.GetString( script, "" );
- if ( funcname.Length() ) {
- function = gameLocal.program.FindFunction( funcname );
- if ( function == NULL ) {
- #ifdef _DEBUG
- gameLocal.Warning( "idItemTeam '%s' at (%s) calls unknown function '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), funcname.c_str() );
- #endif
- }
- }
- return function;
- }
- /*
- ===============
- idItemTeam::Think
- ===============
- */
- void idItemTeam::Think() {
- idMoveableItem::Think();
- TouchTriggers();
- // TODO : only update on updatevisuals
- /*idVec3 offset( 0.0f, 0.0f, 20.0f );
- itemGlow.origin = GetPhysics()->GetOrigin() + offset;
- if ( itemGlowHandle == -1 ) {
- itemGlowHandle = gameRenderWorld->AddLightDef( &itemGlow );
- } else {
- gameRenderWorld->UpdateLightDef( itemGlowHandle, &itemGlow );
- }*/
- #if 1
- // should only the server do this?
- if ( common->IsServer() && nuggetName && carried && ( !lastNuggetDrop || (gameLocal.time - lastNuggetDrop) > spawnArgs.GetInt("nugget_frequency") ) ) {
- SpawnNugget( GetPhysics()->GetOrigin() );
- lastNuggetDrop = gameLocal.time;
- }
- #endif
- // return dropped flag after si_flagDropTimeLimit seconds
- if ( dropped && !carried && lastDrop != 0 && (gameLocal.time - lastDrop) > ( si_flagDropTimeLimit.GetInteger()*1000 ) ) {
- Return(); // return flag after 30 seconds on ground
- return;
- }
- }
- /*
- ===============
- idItemTeam::Pickup
- ===============
- */
- bool idItemTeam::Pickup( idPlayer *player ) {
- if ( !gameLocal.mpGame.IsGametypeFlagBased() ) /* CTF */
- return false;
- if ( gameLocal.mpGame.GetGameState() == idMultiplayerGame::WARMUP ||
- gameLocal.mpGame.GetGameState() == idMultiplayerGame::COUNTDOWN )
- return false;
- // wait 2 seconds after drop before beeing picked up again
- if ( lastDrop != 0 && (gameLocal.time - lastDrop) < spawnArgs.GetInt("pickupDelay", "500") )
- return false;
-
- if ( carried == false && player->team != this->team ) {
- PostEventMS( &EV_TakeFlag, 0, player );
- return true;
- } else if ( carried == false && dropped == true && player->team == this->team ) {
- gameLocal.mpGame.PlayerScoreCTF( player->entityNumber, 5 );
- // return flag
- PostEventMS( &EV_FlagReturn, 0, player );
- return false;
- }
- return false;
- }
- /*
- ===============
- idItemTeam::ClientReceiveEvent
- ===============
- */
- bool idItemTeam::ClientReceiveEvent( int event, int time, const idBitMsg &msg ) {
- gameLocal.DPrintf("ClientRecieveEvent: %i\n", event );
- switch ( event ) {
- case EVENT_TAKEFLAG: {
- idPlayer * player = static_cast<idPlayer *>(gameLocal.entities[ msg.ReadBits( GENTITYNUM_BITS ) ]);
- if ( player == NULL ) {
- gameLocal.Warning( "NULL player takes flag?\n" );
- return false;
- }
- Event_TakeFlag( player );
- }
- return true;
- case EVENT_DROPFLAG : {
- bool death = bool( msg.ReadBits( 1 ) == 1 );
- Event_DropFlag( death );
- }
- return true;
- case EVENT_FLAGRETURN : {
- Hide();
- FreeModelDef();
- FreeLightDef();
- Event_FlagReturn();
- }
- return true;
- case EVENT_FLAGCAPTURE : {
- Hide();
- FreeModelDef();
- FreeLightDef();
- Event_FlagCapture();
- }
- return true;
- };
- return false;
- }
- /*
- ================
- idItemTeam::Drop
- ================
- */
- void idItemTeam::Drop( bool death )
- {
- // PostEventMS( &EV_DropFlag, 0, int(death == true) );
- // had to remove the delayed drop because of drop flag on disconnect
- Event_DropFlag( death );
- }
- /*
- ================
- idItemTeam::Return
- ================
- */
- void idItemTeam::Return( idPlayer * player )
- {
- if ( team != 0 && team != 1 )
- return;
- // PostEventMS( &EV_FlagReturn, 0 );
- Event_FlagReturn();
- }
- /*
- ================
- idItemTeam::Capture
- ================
- */
- void idItemTeam::Capture()
- {
- if ( team != 0 && team != 1 )
- return;
- PostEventMS( &EV_FlagCapture, 0 );
- }
- /*
- ================
- idItemTeam::PrivateReturn
- ================
- */
- void idItemTeam::PrivateReturn()
- {
- Unbind();
- if ( common->IsServer() && carried && !dropped ) {
- int playerIdx = gameLocal.mpGame.GetFlagCarrier( 1-team );
- if ( playerIdx != -1 ) {
- idPlayer * player = static_cast<idPlayer*>( gameLocal.entities[ playerIdx ] );
- player->carryingFlag = false;
- } else {
- gameLocal.Warning( "BUG: carried flag has no carrier before return" );
- }
- }
- dropped = false;
- carried = false;
- SetOrigin( returnOrigin );
- SetAxis( returnAxis );
- trigger->Link( gameLocal.clip, this, 0, GetPhysics()->GetOrigin(), mat3_identity );
- SetSkin( skinDefault );
- // Turn off the light
- /*itemGlow.shaderParms[ SHADERPARM_RED ] = 0.0f;
- itemGlow.shaderParms[ SHADERPARM_GREEN ] = 0.0f;
- itemGlow.shaderParms[ SHADERPARM_BLUE ] = 0.0f;
- itemGlow.shaderParms[ SHADERPARM_ALPHA ] = 0.0f;
- if ( itemGlowHandle != -1 )
- gameRenderWorld->UpdateLightDef( itemGlowHandle, &itemGlow );*/
- GetPhysics()->SetLinearVelocity( idVec3(0, 0, 0) );
- GetPhysics()->SetAngularVelocity( idVec3(0, 0, 0) );
- }
- /*
- ================
- idItemTeam::Event_TakeFlag
- ================
- */
- void idItemTeam::Event_TakeFlag( idPlayer * player ) {
- gameLocal.DPrintf("Event_TakeFlag()!\n");
- assert( player != NULL );
- if ( player->carryingFlag ) {
- // Don't do anything if the player is already carrying the flag.
- // Prevents duplicate messages.
- return;
- }
- if ( common->IsServer() ) {
- idBitMsg msg;
- byte msgBuf[MAX_EVENT_PARAM_SIZE];
- // Send the event
- msg.InitWrite( msgBuf, sizeof( msgBuf ) );
- msg.BeginWriting();
- msg.WriteBits( player->entityNumber, GENTITYNUM_BITS );
- ServerSendEvent( EVENT_TAKEFLAG, &msg, false );
- gameLocal.mpGame.PlayTeamSound( player->team, SND_FLAG_TAKEN_THEIRS );
- gameLocal.mpGame.PlayTeamSound( team, SND_FLAG_TAKEN_YOURS );
- gameLocal.mpGame.PrintMessageEvent( idMultiplayerGame::MSG_FLAGTAKEN, team, player->entityNumber );
- // dont drop a nugget RIGHT away
- lastNuggetDrop = gameLocal.time - gameLocal.random.RandomInt( 1000 );
- }
- BindToJoint( player, g_flagAttachJoint.GetString(), true );
- idVec3 origin( g_flagAttachOffsetX.GetFloat(), g_flagAttachOffsetY.GetFloat(), g_flagAttachOffsetZ.GetFloat() );
- idAngles angle( g_flagAttachAngleX.GetFloat(), g_flagAttachAngleY.GetFloat(), g_flagAttachAngleZ.GetFloat() );
- SetAngles( angle );
- SetOrigin( origin );
- // Turn the light on
- /*itemGlow.shaderParms[ SHADERPARM_RED ] = 1.0f;
- itemGlow.shaderParms[ SHADERPARM_GREEN ] = 1.0f;
- itemGlow.shaderParms[ SHADERPARM_BLUE ] = 1.0f;
- itemGlow.shaderParms[ SHADERPARM_ALPHA ] = 1.0f;
- if ( itemGlowHandle != -1 )
- gameRenderWorld->UpdateLightDef( itemGlowHandle, &itemGlow );*/
- if ( scriptTaken ) {
- idThread *thread = new idThread();
- thread->CallFunction( scriptTaken, false );
- thread->DelayedStart( 0 );
- }
- dropped = false;
- carried = true;
- player->carryingFlag = true;
- SetSkin( skinCarried );
- UpdateVisuals();
- UpdateGuis();
- if ( common->IsServer() ) {
- if ( team == 0 )
- gameLocal.mpGame.player_red_flag = player->entityNumber;
- else
- gameLocal.mpGame.player_blue_flag = player->entityNumber;
- }
- }
- /*
- ================
- idItemTeam::Event_DropFlag
- ================
- */
- void idItemTeam::Event_DropFlag( bool death ) {
- gameLocal.DPrintf("Event_DropFlag()!\n");
- if ( common->IsServer() ) {
- idBitMsg msg;
- byte msgBuf[MAX_EVENT_PARAM_SIZE];
- // Send the event
- msg.InitWrite( msgBuf, sizeof( msgBuf ) );
- msg.BeginWriting();
- msg.WriteBits( death, 1 );
- ServerSendEvent( EVENT_DROPFLAG, &msg, false );
- if ( gameLocal.mpGame.IsFlagMsgOn() ) {
- gameLocal.mpGame.PlayTeamSound( 1-team, SND_FLAG_DROPPED_THEIRS );
- gameLocal.mpGame.PlayTeamSound( team, SND_FLAG_DROPPED_YOURS );
- gameLocal.mpGame.PrintMessageEvent( idMultiplayerGame::MSG_FLAGDROP, team );
- }
- }
- lastDrop = gameLocal.time;
- BecomeActive( TH_THINK );
- Show();
- if ( death )
- GetPhysics()->SetLinearVelocity( idVec3(0, 0, 0) );
- else
- GetPhysics()->SetLinearVelocity( idVec3(0, 0, 20) );
- GetPhysics()->SetAngularVelocity( idVec3(0, 0, 0) );
- // GetPhysics()->SetLinearVelocity( ( GetPhysics()->GetLinearVelocity() * GetBindMaster()->GetPhysics()->GetAxis() ) + GetBindMaster()->GetPhysics()->GetLinearVelocity() );
- if ( GetBindMaster() ) {
- const idBounds bounds = GetPhysics()->GetBounds();
- idVec3 origin = GetBindMaster()->GetPhysics()->GetOrigin() + idVec3(0, 0, ( bounds[1].z-bounds[0].z )*0.6f );
- Unbind();
- SetOrigin( origin );
- }
- idAngles angle = GetPhysics()->GetAxis().ToAngles();
- angle.roll = 0;
- angle.pitch = 0;
- SetAxis( angle.ToMat3() );
- dropped = true;
- carried = false;
- if ( scriptDropped ) {
- idThread *thread = new idThread();
- thread->CallFunction( scriptDropped, false );
- thread->DelayedStart( 0 );
- }
- SetSkin( skinDefault );
- UpdateVisuals();
- UpdateGuis();
- if ( common->IsServer() ) {
- if ( team == 0 )
- gameLocal.mpGame.player_red_flag = -1;
- else
- gameLocal.mpGame.player_blue_flag = -1;
-
- }
- }
- /*
- ================
- idItemTeam::Event_FlagReturn
- ================
- */
- void idItemTeam::Event_FlagReturn( idPlayer * player ) {
- gameLocal.DPrintf("Event_FlagReturn()!\n");
- if ( common->IsServer() ) {
- ServerSendEvent( EVENT_FLAGRETURN, NULL, false );
- if ( gameLocal.mpGame.IsFlagMsgOn() ) {
- gameLocal.mpGame.PlayTeamSound( 1-team, SND_FLAG_RETURN );
- gameLocal.mpGame.PlayTeamSound( team, SND_FLAG_RETURN );
- int entitynum = 255;
- if ( player ) {
- entitynum = player->entityNumber;
- }
- gameLocal.mpGame.PrintMessageEvent( idMultiplayerGame::MSG_FLAGRETURN, team, entitynum );
- }
- }
- BecomeActive( TH_THINK );
- Show();
- PrivateReturn();
- if ( scriptReturned ) {
- idThread *thread = new idThread();
- thread->CallFunction( scriptReturned, false );
- thread->DelayedStart( 0 );
- }
- UpdateVisuals();
- UpdateGuis();
- // Present();
- if ( common->IsServer() ) {
- if ( team == 0 )
- gameLocal.mpGame.player_red_flag = -1;
- else
- gameLocal.mpGame.player_blue_flag = -1;
- }
- }
- /*
- ================
- idItemTeam::Event_FlagCapture
- ================
- */
- void idItemTeam::Event_FlagCapture() {
- gameLocal.DPrintf("Event_FlagCapture()!\n");
- if ( common->IsServer() ) {
- int playerIdx = gameLocal.mpGame.GetFlagCarrier( 1-team );
- if ( playerIdx != -1 ) {
- ServerSendEvent( EVENT_FLAGCAPTURE, NULL, false );
- gameLocal.mpGame.PlayTeamSound( 1-team, SND_FLAG_CAPTURED_THEIRS );
- gameLocal.mpGame.PlayTeamSound( team, SND_FLAG_CAPTURED_YOURS );
- gameLocal.mpGame.TeamScoreCTF( 1-team, 1 );
- gameLocal.mpGame.PlayerScoreCTF( playerIdx, 10 );
- gameLocal.mpGame.PrintMessageEvent( idMultiplayerGame::MSG_FLAGCAPTURE, team, playerIdx );
- } else {
- playerIdx = 255;
- }
- }
- BecomeActive( TH_THINK );
- Show();
- PrivateReturn();
- if ( scriptCaptured ) {
- idThread *thread = new idThread();
- thread->CallFunction( scriptCaptured, false );
- thread->DelayedStart( 0 );
- }
- UpdateVisuals();
- UpdateGuis();
-
- if ( common->IsServer() ) {
- if ( team == 0 )
- gameLocal.mpGame.player_red_flag = -1;
- else
- gameLocal.mpGame.player_blue_flag = -1;
- }
-
- }
- /*
- ================
- idItemTeam::FreeLightDef
- ================
- */
- void idItemTeam::FreeLightDef() {
- if ( itemGlowHandle != -1 ) {
- gameRenderWorld->FreeLightDef( itemGlowHandle );
- itemGlowHandle = -1;
- }
- }
- /*
- ================
- idItemTeam::SpawnNugget
- ================
- */
- void idItemTeam::SpawnNugget( idVec3 pos ) {
- idAngles angle( gameLocal.random.RandomInt(spawnArgs.GetInt("nugget_pitch", "30")), gameLocal.random.RandomInt(spawnArgs.GetInt("nugget_yaw", "360" )), 0 );
- float velocity = float(gameLocal.random.RandomInt( 40 )+15);
- velocity *= spawnArgs.GetFloat("nugget_velocity", "1" );
- idEntity * ent = idMoveableItem::DropItem( nuggetName, pos, GetPhysics()->GetAxis(), angle.ToMat3()*idVec3(velocity, velocity, velocity), 0, spawnArgs.GetInt("nugget_removedelay") );
- idPhysics_RigidBody * physics = static_cast<idPhysics_RigidBody *>( ent->GetPhysics() );
- if ( physics != NULL && physics->IsType( idPhysics_RigidBody::Type ) ) {
- physics->DisableImpact();
- }
- }
- /*
- ================
- idItemTeam::Event_FlagCapture
- ================
- */
- void idItemTeam::WriteToSnapshot( idBitMsg &msg ) const {
- msg.WriteBits( carried, 1 );
- msg.WriteBits( dropped, 1 );
- WriteBindToSnapshot( msg );
- idMoveableItem::WriteToSnapshot( msg );
- }
- /*
- ================
- idItemTeam::ReadFromSnapshot
- ================
- */
- void idItemTeam::ReadFromSnapshot( const idBitMsg &msg ) {
- carried = msg.ReadBits( 1 ) == 1;
- dropped = msg.ReadBits( 1 ) == 1;
- ReadBindFromSnapshot( msg );
- if ( msg.HasChanged() )
- {
- UpdateGuis();
- if ( carried == true )
- SetSkin( skinCarried );
- else
- SetSkin( skinDefault );
- }
- idMoveableItem::ReadFromSnapshot( msg );
- }
- /*
- ================
- idItemTeam::UpdateGuis
- Update all client's huds wrt the flag status.
- ================
- */
- void idItemTeam::UpdateGuis() {
- idPlayer *player;
-
- for ( int i = 0; i < gameLocal.numClients; i++ ) {
- player = static_cast<idPlayer *>( gameLocal.entities[ i ] );
- if ( player && player->hud ) {
- player->hud->SetFlagState( 0, gameLocal.mpGame.GetFlagStatus( 0 ) );
- player->hud->SetFlagState( 1, gameLocal.mpGame.GetFlagStatus( 1 ) );
- player->hud->SetTeamScore( 0, gameLocal.mpGame.GetFlagPoints( 0 ) );
- player->hud->SetTeamScore( 1, gameLocal.mpGame.GetFlagPoints( 1 ) );
- }
- }
- }
- /*
- ================
- idItemTeam::Present
- ================
- */
- void idItemTeam::Present() {
- // hide the flag for localplayer if in first person
- if ( carried && GetBindMaster() ) {
- idPlayer * player = static_cast<idPlayer *>( GetBindMaster() );
- if ( player == gameLocal.GetLocalPlayer() && !pm_thirdPerson.GetBool() ) {
- FreeModelDef();
- BecomeActive( TH_UPDATEVISUALS );
- return;
- }
- }
- idEntity::Present();
- }
- /*
- ===============================================================================
- idObjective
- ===============================================================================
- */
- CLASS_DECLARATION( idItem, idObjective )
- EVENT( EV_Activate, idObjective::Event_Trigger )
- EVENT( EV_HideObjective, idObjective::Event_HideObjective )
- EVENT( EV_GetPlayerPos, idObjective::Event_GetPlayerPos )
- END_CLASS
- /*
- ================
- idObjective::idObjective
- ================
- */
- idObjective::idObjective() {
- playerPos.Zero();
- }
- /*
- ================
- idObjective::Save
- ================
- */
- void idObjective::Save( idSaveGame *savefile ) const {
- savefile->WriteVec3( playerPos );
- savefile->WriteMaterial( screenshot );
- }
- /*
- ================
- idObjective::Restore
- ================
- */
- void idObjective::Restore( idRestoreGame *savefile ) {
- savefile->ReadVec3( playerPos );
- savefile->ReadMaterial( screenshot );
- }
- /*
- ================
- idObjective::Spawn
- ================
- */
- void idObjective::Spawn() {
- Hide();
- idStr shotName;
- shotName = gameLocal.GetMapName();
- shotName.StripFileExtension();
- shotName += "/";
- shotName += spawnArgs.GetString( "screenshot" );
- shotName.SetFileExtension( ".tga" );
- screenshot = declManager->FindMaterial( shotName );
- }
- /*
- ================
- idObjective::Event_Trigger
- ================
- */
- void idObjective::Event_Trigger( idEntity *activator ) {
- idPlayer *player = gameLocal.GetLocalPlayer();
- if ( player ) {
- //Pickup( player );
- if ( spawnArgs.GetString( "inv_objective", NULL ) ) {
- if ( player ) {
- player->GiveObjective( spawnArgs.GetString( "objectivetitle" ), spawnArgs.GetString( "objectivetext" ), screenshot );
- // a tad slow but keeps from having to update all objectives in all maps with a name ptr
- for( int i = 0; i < gameLocal.num_entities; i++ ) {
- if ( gameLocal.entities[ i ] && gameLocal.entities[ i ]->IsType( idObjectiveComplete::Type ) ) {
- if ( idStr::Icmp( spawnArgs.GetString( "objectivetitle" ), gameLocal.entities[ i ]->spawnArgs.GetString( "objectivetitle" ) ) == 0 ){
- gameLocal.entities[ i ]->spawnArgs.SetBool( "objEnabled", true );
- break;
- }
- }
- }
- PostEventMS( &EV_GetPlayerPos, 2000 );
- }
- }
- }
- }
- /*
- ================
- idObjective::Event_GetPlayerPos
- ================
- */
- void idObjective::Event_GetPlayerPos() {
- idPlayer *player = gameLocal.GetLocalPlayer();
- if ( player ) {
- playerPos = player->GetPhysics()->GetOrigin();
- PostEventMS( &EV_HideObjective, 100, player );
- }
- }
- /*
- ================
- idObjective::Event_HideObjective
- ================
- */
- void idObjective::Event_HideObjective(idEntity *e) {
- idPlayer *player = gameLocal.GetLocalPlayer();
- if ( player ) {
- idVec3 v = player->GetPhysics()->GetOrigin() - playerPos;
- if ( v.Length() > 64.0f ) {
- player->HideObjective();
- PostEventMS( &EV_Remove, 0 );
- } else {
- PostEventMS( &EV_HideObjective, 100, player );
- }
- }
- }
- /*
- ===============================================================================
- idVideoCDItem
- ===============================================================================
- */
- CLASS_DECLARATION( idItem, idVideoCDItem )
- END_CLASS
- /*
- ================
- idVideoCDItem::GiveToPlayer
- ================
- */
- bool idVideoCDItem::GiveToPlayer( idPlayer * player, unsigned int giveFlags ) {
- if ( player == NULL ) {
- return false;
- }
- const idDeclVideo * video = static_cast<const idDeclVideo * >( declManager->FindType( DECL_VIDEO, spawnArgs.GetString( "video" ), false ) );
- if ( video == NULL ) {
- return false;
- }
- if ( giveFlags & ITEM_GIVE_UPDATE_STATE ) {
- player->GiveVideo( video, spawnArgs.GetString( "inv_name" ) );
- }
- return true;
- }
- /*
- ===============================================================================
- idPDAItem
- ===============================================================================
- */
- CLASS_DECLARATION( idItem, idPDAItem )
- END_CLASS
- /*
- ================
- idPDAItem::GiveToPlayer
- ================
- */
- bool idPDAItem::GiveToPlayer( idPlayer *player, unsigned int giveFlags ) {
- if ( player == NULL ) {
- return false;
- }
- const char * pdaName = spawnArgs.GetString( "pda_name" );
- const char * invName = spawnArgs.GetString( "inv_name" );
- const idDeclPDA * pda = NULL;
- if ( pdaName != NULL && pdaName[0] != 0 ) {
- // An empty PDA name is legitimate, it means the personal PDA
- // But if the PDA name is not empty, it should be valid
- pda = static_cast<const idDeclPDA *>( declManager->FindType( DECL_PDA, pdaName, false ) );
- if ( pda == NULL ) {
- idLib::Warning( "PDA Item '%s' references unknown PDA %s", GetName(), pdaName );
- return false;
- }
- }
- if ( giveFlags & ITEM_GIVE_UPDATE_STATE ) {
- player->GivePDA( pda, invName );
- }
- return true;
- }
- /*
- ===============================================================================
- idMoveableItem
-
- ===============================================================================
- */
- CLASS_DECLARATION( idItem, idMoveableItem )
- EVENT( EV_DropToFloor, idMoveableItem::Event_DropToFloor )
- EVENT( EV_Gib, idMoveableItem::Event_Gib )
- END_CLASS
- /*
- ================
- idMoveableItem::idMoveableItem
- ================
- */
- idMoveableItem::idMoveableItem() {
- trigger = NULL;
- smoke = NULL;
- smokeTime = 0;
- nextSoundTime = 0;
- repeatSmoke = false;
- }
- /*
- ================
- idMoveableItem::~idMoveableItem
- ================
- */
- idMoveableItem::~idMoveableItem() {
- if ( trigger ) {
- delete trigger;
- }
- }
- /*
- ================
- idMoveableItem::Save
- ================
- */
- void idMoveableItem::Save( idSaveGame *savefile ) const {
- savefile->WriteStaticObject( physicsObj );
- savefile->WriteClipModel( trigger );
- savefile->WriteParticle( smoke );
- savefile->WriteInt( smokeTime );
- savefile->WriteInt( nextSoundTime );
- }
- /*
- ================
- idMoveableItem::Restore
- ================
- */
- void idMoveableItem::Restore( idRestoreGame *savefile ) {
- savefile->ReadStaticObject( physicsObj );
- RestorePhysics( &physicsObj );
- savefile->ReadClipModel( trigger );
- savefile->ReadParticle( smoke );
- savefile->ReadInt( smokeTime );
- savefile->ReadInt( nextSoundTime );
- }
- /*
- ================
- idMoveableItem::Spawn
- ================
- */
- void idMoveableItem::Spawn() {
- idTraceModel trm;
- float density, friction, bouncyness, tsize;
- idStr clipModelName;
- idBounds bounds;
- SetTimeState ts( timeGroup );
- // create a trigger for item pickup
- spawnArgs.GetFloat( "triggersize", "16.0", tsize );
- trigger = new (TAG_PHYSICS_CLIP_ENTITY) idClipModel( idTraceModel( idBounds( vec3_origin ).Expand( tsize ) ) );
- trigger->Link( gameLocal.clip, this, 0, GetPhysics()->GetOrigin(), GetPhysics()->GetAxis() );
- trigger->SetContents( CONTENTS_TRIGGER );
- // check if a clip model is set
- spawnArgs.GetString( "clipmodel", "", clipModelName );
- if ( !clipModelName[0] ) {
- clipModelName = spawnArgs.GetString( "model" ); // use the visual model
- }
- // load the trace model
- if ( !collisionModelManager->TrmFromModel( clipModelName, trm ) ) {
- gameLocal.Error( "idMoveableItem '%s': cannot load collision model %s", name.c_str(), clipModelName.c_str() );
- return;
- }
- // if the model should be shrinked
- if ( spawnArgs.GetBool( "clipshrink" ) ) {
- trm.Shrink( CM_CLIP_EPSILON );
- }
- // get rigid body properties
- spawnArgs.GetFloat( "density", "0.5", density );
- density = idMath::ClampFloat( 0.001f, 1000.0f, density );
- spawnArgs.GetFloat( "friction", "0.05", friction );
- friction = idMath::ClampFloat( 0.0f, 1.0f, friction );
- spawnArgs.GetFloat( "bouncyness", "0.6", bouncyness );
- bouncyness = idMath::ClampFloat( 0.0f, 1.0f, bouncyness );
- // setup the physics
- physicsObj.SetSelf( this );
- physicsObj.SetClipModel( new (TAG_PHYSICS_CLIP_ENTITY) idClipModel( trm ), density );
- physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
- physicsObj.SetAxis( GetPhysics()->GetAxis() );
- physicsObj.SetBouncyness( bouncyness );
- physicsObj.SetFriction( 0.6f, 0.6f, friction );
- physicsObj.SetGravity( gameLocal.GetGravity() );
- physicsObj.SetContents( CONTENTS_RENDERMODEL );
- physicsObj.SetClipMask( MASK_SOLID | CONTENTS_MOVEABLECLIP );
- SetPhysics( &physicsObj );
- if ( spawnArgs.GetBool( "nodrop" ) ) {
- physicsObj.PutToRest();
- }
- smoke = NULL;
- smokeTime = 0;
- nextSoundTime = 0;
- const char *smokeName = spawnArgs.GetString( "smoke_trail" );
- if ( *smokeName != '\0' ) {
- smoke = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, smokeName ) );
- smokeTime = gameLocal.time;
- BecomeActive( TH_UPDATEPARTICLES );
- }
- repeatSmoke = spawnArgs.GetBool( "repeatSmoke", "0" );
- }
- /*
- ================
- idItem::ClientThink
- ================
- */
- void idMoveableItem::ClientThink( const int curTime, const float fraction, const bool predict ) {
- InterpolatePhysicsOnly( fraction );
- if ( thinkFlags & TH_PHYSICS ) {
- // update trigger position
- trigger->Link( gameLocal.clip, this, 0, GetPhysics()->GetOrigin(), mat3_identity );
- }
- Present();
- }
- /*
- ================
- idMoveableItem::Think
- ================
- */
- void idMoveableItem::Think() {
- RunPhysics();
- if ( thinkFlags & TH_PHYSICS ) {
- // update trigger position
- trigger->Link( gameLocal.clip, this, 0, GetPhysics()->GetOrigin(), mat3_identity );
- }
-
- if ( thinkFlags & TH_UPDATEPARTICLES ) {
- if ( !gameLocal.smokeParticles->EmitSmoke( smoke, smokeTime, gameLocal.random.CRandomFloat(), GetPhysics()->GetOrigin(), GetPhysics()->GetAxis(), timeGroup /*_D3XP*/ ) ) {
- if ( !repeatSmoke ) {
- smokeTime = 0;
- BecomeInactive( TH_UPDATEPARTICLES );
- } else {
- smokeTime = gameLocal.time;
- }
- }
- }
- Present();
- }
- /*
- =================
- idMoveableItem::Collide
- =================
- */
- bool idMoveableItem::Collide( const trace_t &collision, const idVec3 &velocity ) {
- float v, f;
- v = -( velocity * collision.c.normal );
- if ( v > 80 && gameLocal.time > nextSoundTime ) {
- f = v > 200 ? 1.0f : idMath::Sqrt( v - 80 ) * 0.091f;
- if ( StartSound( "snd_bounce", SND_CHANNEL_ANY, 0, false, NULL ) ) {
- // don't set the volume unless there is a bounce sound as it overrides the entire channel
- // which causes footsteps on ai's to not honor their shader parms
- SetSoundVolume( f );
- }
- nextSoundTime = gameLocal.time + 500;
- }
- return false;
- }
- /*
- ================
- idMoveableItem::Pickup
- ================
- */
- bool idMoveableItem::Pickup( idPlayer *player ) {
- bool ret = idItem::Pickup( player );
- if ( ret ) {
- trigger->SetContents( 0 );
- }
- return ret;
- }
- /*
- ================
- idMoveableItem::DropItem
- ================
- */
- idEntity *idMoveableItem::DropItem( const char *classname, const idVec3 &origin, const idMat3 &axis, const idVec3 &velocity, int activateDelay, int removeDelay ) {
- idDict args;
- idEntity *item;
- args.Set( "classname", classname );
- args.Set( "dropped", "1" );
- // we sometimes drop idMoveables here, so set 'nodrop' to 1 so that it doesn't get put on the floor
- args.Set( "nodrop", "1" );
- if ( activateDelay ) {
- args.SetBool( "triggerFirst", true );
- }
- gameLocal.SpawnEntityDef( args, &item );
- if ( item ) {
- // set item position
- item->GetPhysics()->SetOrigin( origin );
- item->GetPhysics()->SetAxis( axis );
- item->GetPhysics()->SetLinearVelocity( velocity );
- item->UpdateVisuals();
- if ( activateDelay ) {
- item->PostEventMS( &EV_Activate, activateDelay, item );
- }
- if ( !removeDelay ) {
- removeDelay = 5 * 60 * 1000;
- }
- // always remove a dropped item after 5 minutes in case it dropped to an unreachable location
- item->PostEventMS( &EV_Remove, removeDelay );
- }
- return item;
- }
- /*
- ================
- idMoveableItem::DropItems
- The entity should have the following key/value pairs set:
- "def_drop<type>Item" "item def"
- "drop<type>ItemJoint" "joint name"
- "drop<type>ItemRotation" "pitch yaw roll"
- "drop<type>ItemOffset" "x y z"
- "skin_drop<type>" "skin name"
- To drop multiple items the following key/value pairs can be used:
- "def_drop<type>Item<X>" "item def"
- "drop<type>Item<X>Joint" "joint name"
- "drop<type>Item<X>Rotation" "pitch yaw roll"
- "drop<type>Item<X>Offset" "x y z"
- where <X> is an aribtrary string.
- ================
- */
- void idMoveableItem::DropItems( idAnimatedEntity *ent, const char *type, idList<idEntity *> *list ) {
- const idKeyValue *kv;
- const char *skinName, *c, *jointName;
- idStr key, key2;
- idVec3 origin;
- idMat3 axis;
- idAngles angles;
- const idDeclSkin *skin;
- jointHandle_t joint;
- idEntity *item;
- // drop all items
- kv = ent->spawnArgs.MatchPrefix( va( "def_drop%sItem", type ), NULL );
- while ( kv ) {
- c = kv->GetKey().c_str() + kv->GetKey().Length();
- if ( idStr::Icmp( c - 5, "Joint" ) != 0 && idStr::Icmp( c - 8, "Rotation" ) != 0 ) {
- key = kv->GetKey().c_str() + 4;
- key2 = key;
- key += "Joint";
- key2 += "Offset";
- jointName = ent->spawnArgs.GetString( key );
- joint = ent->GetAnimator()->GetJointHandle( jointName );
- if ( !ent->GetJointWorldTransform( joint, gameLocal.time, origin, axis ) ) {
- gameLocal.Warning( "%s refers to invalid joint '%s' on entity '%s'\n", key.c_str(), jointName, ent->name.c_str() );
- origin = ent->GetPhysics()->GetOrigin();
- axis = ent->GetPhysics()->GetAxis();
- }
- if ( g_dropItemRotation.GetString()[0] ) {
- angles.Zero();
- sscanf( g_dropItemRotation.GetString(), "%f %f %f", &angles.pitch, &angles.yaw, &angles.roll );
- } else {
- key = kv->GetKey().c_str() + 4;
- key += "Rotation";
- ent->spawnArgs.GetAngles( key, "0 0 0", angles );
- }
- axis = angles.ToMat3() * axis;
- origin += ent->spawnArgs.GetVector( key2, "0 0 0" );
- item = DropItem( kv->GetValue(), origin, axis, vec3_origin, 0, 0 );
- if ( list && item ) {
- list->Append( item );
- }
- }
- kv = ent->spawnArgs.MatchPrefix( va( "def_drop%sItem", type ), kv );
- }
- // change the skin to hide all items
- skinName = ent->spawnArgs.GetString( va( "skin_drop%s", type ) );
- if ( skinName[0] ) {
- skin = declManager->FindSkin( skinName );
- ent->SetSkin( skin );
- }
- }
- /*
- ======================
- idMoveableItem::WriteToSnapshot
- ======================
- */
- void idMoveableItem::WriteToSnapshot( idBitMsg &msg ) const {
- physicsObj.WriteToSnapshot( msg );
- msg.WriteBool( IsHidden() );
- }
- /*
- ======================
- idMoveableItem::ReadFromSnapshot
- ======================
- */
- void idMoveableItem::ReadFromSnapshot( const idBitMsg &msg ) {
- physicsObj.ReadFromSnapshot( msg );
- const bool snapshotHidden = msg.ReadBool();
- if ( snapshotHidden ) {
- Hide();
- } else if ( GetPredictPickupMilliseconds() != 0 ) {
- if ( gameLocal.GetLastClientUsercmdMilliseconds( gameLocal.GetLocalClientNum() ) >= GetPredictPickupMilliseconds() ) {
- if ( trigger->GetContents() == 0 ) {
- trigger->SetContents( CONTENTS_TRIGGER );
- }
- Show();
- }
- }
- if ( msg.HasChanged() ) {
- UpdateVisuals();
- }
- }
- /*
- ============
- idMoveableItem::Gib
- ============
- */
- void idMoveableItem::Gib( const idVec3 &dir, const char *damageDefName ) {
- // spawn smoke puff
- const char *smokeName = spawnArgs.GetString( "smoke_gib" );
- if ( *smokeName != '\0' ) {
- const idDeclParticle *smoke = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, smokeName ) );
- gameLocal.smokeParticles->EmitSmoke( smoke, gameLocal.time, gameLocal.random.CRandomFloat(), renderEntity.origin, renderEntity.axis, timeGroup /*_D3XP*/ );
- }
- // remove the entity
- PostEventMS( &EV_Remove, 0 );
- }
- /*
- ================
- idMoveableItem::Event_DropToFloor
- ================
- */
- void idMoveableItem::Event_DropToFloor() {
- // the physics will drop the moveable to the floor
- }
- /*
- ============
- idMoveableItem::Event_Gib
- ============
- */
- void idMoveableItem::Event_Gib( const char *damageDefName ) {
- Gib( idVec3( 0, 0, 1 ), damageDefName );
- }
- /*
- ===============================================================================
- idMoveablePDAItem
- ===============================================================================
- */
- CLASS_DECLARATION( idMoveableItem, idMoveablePDAItem )
- END_CLASS
- /*
- ================
- idMoveablePDAItem::GiveToPlayer
- ================
- */
- bool idMoveablePDAItem::GiveToPlayer( idPlayer * player, unsigned int giveFlags ) {
- if ( player == NULL ) {
- return false;
- }
- const char * pdaName = spawnArgs.GetString( "pda_name" );
- const char * invName = spawnArgs.GetString( "inv_name" );
- const idDeclPDA * pda = NULL;
- if ( pdaName != NULL && pdaName[0] != 0 ) {
- // An empty PDA name is legitimate, it means the personal PDA
- // But if the PDA name is not empty, it should be valid
- pda = static_cast<const idDeclPDA *>( declManager->FindType( DECL_PDA, pdaName, false ) );
- if ( pda == NULL ) {
- idLib::Warning( "PDA Item '%s' references unknown PDA %s", GetName(), pdaName );
- return false;
- }
- }
- if ( giveFlags & ITEM_GIVE_UPDATE_STATE ) {
- player->GivePDA( pda, invName );
- }
- return true;
- }
- /*
- ===============================================================================
- idItemRemover
- ===============================================================================
- */
- CLASS_DECLARATION( idEntity, idItemRemover )
- EVENT( EV_Activate, idItemRemover::Event_Trigger )
- END_CLASS
- /*
- ================
- idItemRemover::Spawn
- ================
- */
- void idItemRemover::Spawn() {
- }
- /*
- ================
- idItemRemover::RemoveItem
- ================
- */
- void idItemRemover::RemoveItem( idPlayer *player ) {
- const char *remove;
-
- remove = spawnArgs.GetString( "remove" );
- player->RemoveInventoryItem( remove );
- }
- /*
- ================
- idItemRemover::Event_Trigger
- ================
- */
- void idItemRemover::Event_Trigger( idEntity *activator ) {
- if ( activator->IsType( idPlayer::Type ) ) {
- RemoveItem( static_cast<idPlayer *>(activator) );
- }
- }
- /*
- ===============================================================================
- idObjectiveComplete
- ===============================================================================
- */
- CLASS_DECLARATION( idItemRemover, idObjectiveComplete )
- EVENT( EV_Activate, idObjectiveComplete::Event_Trigger )
- EVENT( EV_HideObjective, idObjectiveComplete::Event_HideObjective )
- EVENT( EV_GetPlayerPos, idObjectiveComplete::Event_GetPlayerPos )
- END_CLASS
- /*
- ================
- idObjectiveComplete::idObjectiveComplete
- ================
- */
- idObjectiveComplete::idObjectiveComplete() {
- playerPos.Zero();
- }
- /*
- ================
- idObjectiveComplete::Save
- ================
- */
- void idObjectiveComplete::Save( idSaveGame *savefile ) const {
- savefile->WriteVec3( playerPos );
- }
- /*
- ================
- idObjectiveComplete::Restore
- ================
- */
- void idObjectiveComplete::Restore( idRestoreGame *savefile ) {
- savefile->ReadVec3( playerPos );
- }
- /*
- ================
- idObjectiveComplete::Spawn
- ================
- */
- void idObjectiveComplete::Spawn() {
- spawnArgs.SetBool( "objEnabled", false );
- Hide();
- }
- /*
- ================
- idObjectiveComplete::Event_Trigger
- ================
- */
- void idObjectiveComplete::Event_Trigger( idEntity *activator ) {
- if ( !spawnArgs.GetBool( "objEnabled" ) ) {
- return;
- }
- idPlayer *player = gameLocal.GetLocalPlayer();
- if ( player ) {
- RemoveItem( player );
- if ( spawnArgs.GetString( "inv_objective", NULL ) ) {
- player->CompleteObjective( spawnArgs.GetString( "objectivetitle" ) );
- PostEventMS( &EV_GetPlayerPos, 2000 );
- }
- }
- }
- /*
- ================
- idObjectiveComplete::Event_GetPlayerPos
- ================
- */
- void idObjectiveComplete::Event_GetPlayerPos() {
- idPlayer *player = gameLocal.GetLocalPlayer();
- if ( player ) {
- playerPos = player->GetPhysics()->GetOrigin();
- PostEventMS( &EV_HideObjective, 100, player );
- }
- }
- /*
- ================
- idObjectiveComplete::Event_HideObjective
- ================
- */
- void idObjectiveComplete::Event_HideObjective( idEntity *e ) {
- idPlayer *player = gameLocal.GetLocalPlayer();
- if ( player ) {
- idVec3 v = player->GetPhysics()->GetOrigin();
- v -= playerPos;
- if ( v.Length() > 64.0f ) {
- player->HideObjective();
- PostEventMS( &EV_Remove, 0 );
- } else {
- PostEventMS( &EV_HideObjective, 100, player );
- }
- }
- }
|