Trigger.cpp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. 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.
  17. 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.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "Game_local.h"
  23. /*
  24. ===============================================================================
  25. idTrigger
  26. ===============================================================================
  27. */
  28. const idEventDef EV_Enable( "enable", NULL );
  29. const idEventDef EV_Disable( "disable", NULL );
  30. const idEventDef EV_IsEnabled( "IsEnabled", NULL, 'd' );
  31. CLASS_DECLARATION( idEntity, idTrigger )
  32. EVENT( EV_Enable, idTrigger::Event_Enable )
  33. EVENT( EV_Disable, idTrigger::Event_Disable )
  34. EVENT( EV_IsEnabled, idTrigger::Event_IsEnabled )
  35. END_CLASS
  36. /*
  37. ================
  38. idTrigger::DrawDebugInfo
  39. ================
  40. */
  41. void idTrigger::DrawDebugInfo( void ) {
  42. idMat3 axis = gameLocal.GetLocalPlayer()->viewAngles.ToMat3();
  43. idVec3 up = axis[ 2 ] * 5.0f;
  44. idBounds viewTextBounds( gameLocal.GetLocalPlayer()->GetPhysics()->GetOrigin() );
  45. idBounds viewBounds( gameLocal.GetLocalPlayer()->GetPhysics()->GetOrigin() );
  46. idBounds box( idVec3( -4.0f, -4.0f, -4.0f ), idVec3( 4.0f, 4.0f, 4.0f ) );
  47. idEntity *ent;
  48. idEntity *target;
  49. int i;
  50. bool show;
  51. const function_t *func;
  52. viewTextBounds.ExpandSelf( 128.0f );
  53. viewBounds.ExpandSelf( 512.0f );
  54. for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
  55. if ( ent->GetPhysics()->GetContents() & ( CONTENTS_TRIGGER | CONTENTS_FLASHLIGHT_TRIGGER ) ) {
  56. show = viewBounds.IntersectsBounds( ent->GetPhysics()->GetAbsBounds() );
  57. if ( !show ) {
  58. for( i = 0; i < ent->targets.Num(); i++ ) {
  59. target = ent->targets[ i ].GetEntity();
  60. if ( target && viewBounds.IntersectsBounds( target->GetPhysics()->GetAbsBounds() ) ) {
  61. show = true;
  62. break;
  63. }
  64. }
  65. }
  66. if ( !show ) {
  67. continue;
  68. }
  69. gameRenderWorld->DebugBounds( colorOrange, ent->GetPhysics()->GetAbsBounds() );
  70. if ( viewTextBounds.IntersectsBounds( ent->GetPhysics()->GetAbsBounds() ) ) {
  71. gameRenderWorld->DrawText( ent->name.c_str(), ent->GetPhysics()->GetAbsBounds().GetCenter(), 0.1f, colorWhite, axis, 1 );
  72. gameRenderWorld->DrawText( ent->GetEntityDefName(), ent->GetPhysics()->GetAbsBounds().GetCenter() + up, 0.1f, colorWhite, axis, 1 );
  73. if ( ent->IsType( idTrigger::Type ) ) {
  74. func = static_cast<idTrigger *>( ent )->GetScriptFunction();
  75. } else {
  76. func = NULL;
  77. }
  78. if ( func ) {
  79. gameRenderWorld->DrawText( va( "call script '%s'", func->Name() ), ent->GetPhysics()->GetAbsBounds().GetCenter() - up, 0.1f, colorWhite, axis, 1 );
  80. }
  81. }
  82. for( i = 0; i < ent->targets.Num(); i++ ) {
  83. target = ent->targets[ i ].GetEntity();
  84. if ( target ) {
  85. gameRenderWorld->DebugArrow( colorYellow, ent->GetPhysics()->GetAbsBounds().GetCenter(), target->GetPhysics()->GetOrigin(), 10, 0 );
  86. gameRenderWorld->DebugBounds( colorGreen, box, target->GetPhysics()->GetOrigin() );
  87. if ( viewTextBounds.IntersectsBounds( target->GetPhysics()->GetAbsBounds() ) ) {
  88. gameRenderWorld->DrawText( target->name.c_str(), target->GetPhysics()->GetAbsBounds().GetCenter(), 0.1f, colorWhite, axis, 1 );
  89. }
  90. }
  91. }
  92. }
  93. }
  94. }
  95. /*
  96. ================
  97. idTrigger::Enable
  98. ================
  99. */
  100. void idTrigger::Enable( void ) {
  101. GetPhysics()->SetContents( CONTENTS_TRIGGER );
  102. GetPhysics()->EnableClip();
  103. }
  104. /*
  105. ================
  106. idTrigger::Disable
  107. ================
  108. */
  109. void idTrigger::Disable( void ) {
  110. // we may be relinked if we're bound to another object, so clear the contents as well
  111. GetPhysics()->SetContents( 0 );
  112. GetPhysics()->DisableClip();
  113. }
  114. /*
  115. ================
  116. idTrigger::CallScript
  117. ================
  118. */
  119. void idTrigger::CallScript( void ) const {
  120. idThread *thread;
  121. if ( scriptFunction ) {
  122. thread = new idThread( scriptFunction );
  123. thread->DelayedStart( 0 );
  124. }
  125. }
  126. /*
  127. ================
  128. idTrigger::GetScriptFunction
  129. ================
  130. */
  131. const function_t *idTrigger::GetScriptFunction( void ) const {
  132. return scriptFunction;
  133. }
  134. /*
  135. ================
  136. idTrigger::Save
  137. ================
  138. */
  139. void idTrigger::Save( idSaveGame *savefile ) const {
  140. if ( scriptFunction ) {
  141. savefile->WriteString( scriptFunction->Name() );
  142. } else {
  143. savefile->WriteString( "" );
  144. }
  145. }
  146. /*
  147. ================
  148. idTrigger::Restore
  149. ================
  150. */
  151. void idTrigger::Restore( idRestoreGame *savefile ) {
  152. idStr funcname;
  153. savefile->ReadString( funcname );
  154. if ( funcname.Length() ) {
  155. scriptFunction = gameLocal.program.FindFunction( funcname );
  156. if ( scriptFunction == NULL ) {
  157. gameLocal.Warning( "idTrigger_Multi '%s' at (%s) calls unknown function '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), funcname.c_str() );
  158. }
  159. } else {
  160. scriptFunction = NULL;
  161. }
  162. }
  163. void idTrigger::Event_IsEnabled( void )
  164. {
  165. if (GetPhysics()->GetContents() <= 0)
  166. {
  167. idThread::ReturnInt( 0 );
  168. return;
  169. }
  170. idThread::ReturnInt( 1 );
  171. }
  172. /*
  173. ================
  174. idTrigger::Event_Enable
  175. ================
  176. */
  177. void idTrigger::Event_Enable( void ) {
  178. Enable();
  179. }
  180. /*
  181. ================
  182. idTrigger::Event_Disable
  183. ================
  184. */
  185. void idTrigger::Event_Disable( void ) {
  186. Disable();
  187. }
  188. /*
  189. ================
  190. idTrigger::idTrigger
  191. ================
  192. */
  193. idTrigger::idTrigger() {
  194. scriptFunction = NULL;
  195. }
  196. /*
  197. ================
  198. idTrigger::Spawn
  199. ================
  200. */
  201. void idTrigger::Spawn( void ) {
  202. GetPhysics()->SetContents( CONTENTS_TRIGGER );
  203. idStr funcname = spawnArgs.GetString( "call", "" );
  204. if ( funcname.Length() ) {
  205. scriptFunction = gameLocal.program.FindFunction( funcname );
  206. if ( scriptFunction == NULL ) {
  207. gameLocal.Warning( "trigger '%s' at (%s) calls unknown function '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), funcname.c_str() );
  208. }
  209. } else {
  210. scriptFunction = NULL;
  211. }
  212. }
  213. /*
  214. ===============================================================================
  215. idTrigger_Multi
  216. ===============================================================================
  217. */
  218. const idEventDef EV_TriggerAction( "<triggerAction>", "e" );
  219. const idEventDef EV_TriggerActivate( "triggeractivate", "d" );
  220. CLASS_DECLARATION( idTrigger, idTrigger_Multi )
  221. EVENT( EV_Touch, idTrigger_Multi::Event_Touch )
  222. EVENT( EV_Activate, idTrigger_Multi::Event_Trigger )
  223. EVENT( EV_TriggerAction, idTrigger_Multi::Event_TriggerAction )
  224. EVENT( EV_TriggerActivate, idTrigger_Multi::Event_TriggerActivate )
  225. END_CLASS
  226. void idTrigger_Multi::Event_TriggerActivate( int value )
  227. {
  228. if (value >= 1)
  229. {
  230. triggerFirst = false;
  231. }
  232. else
  233. {
  234. triggerFirst = true;
  235. }
  236. }
  237. /*
  238. ================
  239. idTrigger_Multi::idTrigger_Multi
  240. ================
  241. */
  242. idTrigger_Multi::idTrigger_Multi( void ) {
  243. wait = 0.0f;
  244. random = 0.0f;
  245. delay = 0.0f;
  246. random_delay = 0.0f;
  247. nextTriggerTime = 0;
  248. removeItem = 0;
  249. touchClient = false;
  250. touchOther = false;
  251. triggerFirst = false;
  252. triggerWithSelf = false;
  253. }
  254. /*
  255. ================
  256. idTrigger_Multi::Save
  257. ================
  258. */
  259. void idTrigger_Multi::Save( idSaveGame *savefile ) const {
  260. savefile->WriteFloat( wait );
  261. savefile->WriteFloat( random );
  262. savefile->WriteFloat( delay );
  263. savefile->WriteFloat( random_delay );
  264. savefile->WriteInt( nextTriggerTime );
  265. savefile->WriteString( requires );
  266. savefile->WriteInt( removeItem );
  267. savefile->WriteBool( touchClient );
  268. savefile->WriteBool( touchOther );
  269. savefile->WriteBool( triggerFirst );
  270. savefile->WriteBool( triggerWithSelf );
  271. }
  272. /*
  273. ================
  274. idTrigger_Multi::Restore
  275. ================
  276. */
  277. void idTrigger_Multi::Restore( idRestoreGame *savefile ) {
  278. savefile->ReadFloat( wait );
  279. savefile->ReadFloat( random );
  280. savefile->ReadFloat( delay );
  281. savefile->ReadFloat( random_delay );
  282. savefile->ReadInt( nextTriggerTime );
  283. savefile->ReadString( requires );
  284. savefile->ReadInt( removeItem );
  285. savefile->ReadBool( touchClient );
  286. savefile->ReadBool( touchOther );
  287. savefile->ReadBool( triggerFirst );
  288. savefile->ReadBool( triggerWithSelf );
  289. }
  290. /*
  291. ================
  292. idTrigger_Multi::Spawn
  293. "wait" : Seconds between triggerings, 0.5 default, -1 = one time only.
  294. "call" : Script function to call when triggered
  295. "random" wait variance, default is 0
  296. Variable sized repeatable trigger. Must be targeted at one or more entities.
  297. so, the basic time between firing is a random time between
  298. (wait - random) and (wait + random)
  299. ================
  300. */
  301. void idTrigger_Multi::Spawn( void ) {
  302. spawnArgs.GetFloat( "wait", "0.5", wait );
  303. spawnArgs.GetFloat( "random", "0", random );
  304. spawnArgs.GetFloat( "delay", "0", delay );
  305. spawnArgs.GetFloat( "random_delay", "0", random_delay );
  306. if ( random && ( random >= wait ) && ( wait >= 0 ) ) {
  307. random = wait - 1;
  308. gameLocal.Warning( "idTrigger_Multi '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
  309. }
  310. if ( random_delay && ( random_delay >= delay ) && ( delay >= 0 ) ) {
  311. random_delay = delay - 1;
  312. gameLocal.Warning( "idTrigger_Multi '%s' at (%s) has random_delay >= delay", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
  313. }
  314. spawnArgs.GetString( "requires", "", requires );
  315. spawnArgs.GetInt( "removeItem", "0", removeItem );
  316. spawnArgs.GetBool( "triggerFirst", "0", triggerFirst );
  317. spawnArgs.GetBool( "triggerWithSelf", "0", triggerWithSelf );
  318. if ( spawnArgs.GetBool( "anyTouch" ) ) {
  319. touchClient = true;
  320. touchOther = true;
  321. } else if ( spawnArgs.GetBool( "noTouch" ) ) {
  322. touchClient = false;
  323. touchOther = false;
  324. } else if ( spawnArgs.GetBool( "noClient" ) ) {
  325. touchClient = false;
  326. touchOther = true;
  327. } else {
  328. touchClient = true;
  329. touchOther = false;
  330. }
  331. nextTriggerTime = 0;
  332. if ( spawnArgs.GetBool( "flashlight_trigger" ) ) {
  333. GetPhysics()->SetContents( CONTENTS_FLASHLIGHT_TRIGGER );
  334. } else {
  335. GetPhysics()->SetContents( CONTENTS_TRIGGER );
  336. }
  337. }
  338. /*
  339. ================
  340. idTrigger_Multi::CheckFacing
  341. ================
  342. */
  343. bool idTrigger_Multi::CheckFacing( idEntity *activator ) {
  344. if ( spawnArgs.GetBool( "facing" ) ) {
  345. if ( !activator->IsType( idPlayer::Type ) ) {
  346. return true;
  347. }
  348. idPlayer *player = static_cast< idPlayer* >( activator );
  349. float dot = player->viewAngles.ToForward() * GetPhysics()->GetAxis()[0];
  350. float angle = RAD2DEG( idMath::ACos( dot ) );
  351. if ( angle > spawnArgs.GetFloat( "angleLimit", "30" ) ) {
  352. return false;
  353. }
  354. }
  355. return true;
  356. }
  357. /*
  358. ================
  359. idTrigger_Multi::TriggerAction
  360. ================
  361. */
  362. void idTrigger_Multi::TriggerAction( idEntity *activator ) {
  363. ActivateTargets( triggerWithSelf ? this : activator );
  364. CallScript();
  365. if ( wait >= 0 ) {
  366. nextTriggerTime = gameLocal.time + SEC2MS( wait + random * gameLocal.random.CRandomFloat() );
  367. } else {
  368. // we can't just remove (this) here, because this is a touch function
  369. // called while looping through area links...
  370. #ifdef _D3XP
  371. // If the player spawned inside the trigger, the player Spawn function called Think directly,
  372. // allowing for multiple triggers on a trigger_once. Increasing the nextTriggerTime prevents it.
  373. nextTriggerTime = gameLocal.time + 99999;
  374. #else
  375. nextTriggerTime = gameLocal.time + 1;
  376. #endif
  377. PostEventMS( &EV_Remove, 0 );
  378. }
  379. }
  380. /*
  381. ================
  382. idTrigger_Multi::Event_TriggerAction
  383. ================
  384. */
  385. void idTrigger_Multi::Event_TriggerAction( idEntity *activator ) {
  386. TriggerAction( activator );
  387. }
  388. /*
  389. ================
  390. idTrigger_Multi::Event_Trigger
  391. the trigger was just activated
  392. activated should be the entity that originated the activation sequence (ie. the original target)
  393. activator should be set to the activator so it can be held through a delay
  394. so wait for the delay time before firing
  395. ================
  396. */
  397. void idTrigger_Multi::Event_Trigger( idEntity *activator ) {
  398. if ( nextTriggerTime > gameLocal.time ) {
  399. // can't retrigger until the wait is over
  400. return;
  401. }
  402. // see if this trigger requires an item
  403. if ( !gameLocal.RequirementMet( activator, requires, removeItem ) ) {
  404. return;
  405. }
  406. if ( !CheckFacing( activator ) ) {
  407. return;
  408. }
  409. if ( triggerFirst ) {
  410. triggerFirst = false;
  411. return;
  412. }
  413. // don't allow it to trigger twice in a single frame
  414. nextTriggerTime = gameLocal.time + 1;
  415. if ( delay > 0 ) {
  416. // don't allow it to trigger again until our delay has passed
  417. nextTriggerTime += SEC2MS( delay + random_delay * gameLocal.random.CRandomFloat() );
  418. PostEventSec( &EV_TriggerAction, delay, activator );
  419. } else {
  420. TriggerAction( activator );
  421. }
  422. //BC recording.
  423. idEntity *recordEnt;
  424. recordEnt = gameLocal.FindEntity( "world1" );
  425. if (recordEnt)
  426. {
  427. if (this->spawnArgs.GetBool("recordable", "0"))
  428. {
  429. static_cast<idWorldManager *>( recordEnt )->RecordFrob(this->GetName());
  430. }
  431. }
  432. }
  433. /*
  434. ================
  435. idTrigger_Multi::Event_Touch
  436. ================
  437. */
  438. void idTrigger_Multi::Event_Touch( idEntity *other, trace_t *trace ) {
  439. if( triggerFirst ) {
  440. return;
  441. }
  442. bool player = other->IsType( idPlayer::Type );
  443. if ( player ) {
  444. if ( !touchClient ) {
  445. return;
  446. }
  447. if ( static_cast< idPlayer * >( other )->spectating ) {
  448. return;
  449. }
  450. } else if ( !touchOther ) {
  451. return;
  452. }
  453. if ( nextTriggerTime > gameLocal.time ) {
  454. // can't retrigger until the wait is over
  455. return;
  456. }
  457. // see if this trigger requires an item
  458. if ( !gameLocal.RequirementMet( other, requires, removeItem ) ) {
  459. return;
  460. }
  461. if ( !CheckFacing( other ) ) {
  462. return;
  463. }
  464. if ( spawnArgs.GetBool( "toggleTriggerFirst" ) ) {
  465. triggerFirst = true;
  466. }
  467. if (player && spawnArgs.GetBool( "falltrigger" ))
  468. {
  469. StartSound( "snd_camerasnap" , SND_CHANNEL_ANY, 0, false, NULL );
  470. if (gameLocal.GetLocalPlayer()->inDeck)
  471. {
  472. //kick player out of deck.
  473. //cvarSystem->SetCVarBool("deckActive", true, 0);
  474. //gameLocal.GetLocalPlayer()->deckEnt.GetEntity()->GetPhysics()->SetOrigin(popcornpos);
  475. //gameLocal.sessionCommand = "stopgui";
  476. gameLocal.GetLocalPlayer()->ExitDeck(true);
  477. }
  478. const char *manualPos = this->spawnArgs.GetString("target");
  479. if (manualPos)
  480. {
  481. idEntity *manualEnt = gameLocal.FindEntity( manualPos );
  482. if (manualEnt)
  483. {
  484. other->SetOrigin( manualEnt->GetPhysics()->GetOrigin() + idVec3(0,0,1) );
  485. other->GetPhysics()->PutToRest();
  486. return;
  487. }
  488. }
  489. //current.velocity.Zero();
  490. idVec3 popcornpos = static_cast< idPlayer * >( other )->popcornPosition;
  491. if (popcornpos == vec3_zero)
  492. {
  493. //no valid popcorn position.
  494. //reset player to spawn point.
  495. int spawnIndex = 0;
  496. idEntity *recordEnt;
  497. recordEnt = gameLocal.FindEntity( "world1" );
  498. if (recordEnt)
  499. {
  500. spawnIndex = static_cast<idWorldManager *>( recordEnt )->index;
  501. }
  502. idEntity *spawnEnt;
  503. spawnEnt = gameLocal.FindEntity( va("heliinsertion%d", spawnIndex) );
  504. if (spawnEnt)
  505. {
  506. other->SetOrigin( spawnEnt->GetPhysics()->GetOrigin() + idVec3(0,0,1) );
  507. other->GetPhysics()->PutToRest();
  508. }
  509. }
  510. else
  511. {
  512. other->SetOrigin( popcornpos + idVec3(0,0,1) );
  513. other->GetPhysics()->PutToRest();
  514. }
  515. }
  516. nextTriggerTime = gameLocal.time + 1;
  517. if ( delay > 0 ) {
  518. // don't allow it to trigger again until our delay has passed
  519. nextTriggerTime += SEC2MS( delay + random_delay * gameLocal.random.CRandomFloat() );
  520. PostEventSec( &EV_TriggerAction, delay, other );
  521. } else {
  522. TriggerAction( other );
  523. }
  524. }
  525. CLASS_DECLARATION( idTrigger, idTrigger_classname )
  526. EVENT( EV_Touch, idTrigger_classname::Event_Touch )
  527. END_CLASS
  528. idTrigger_classname::idTrigger_classname( void )
  529. {
  530. wait = 0.0f;
  531. nextTriggerTime = 0;
  532. triggerFirst = false;
  533. }
  534. void idTrigger_classname::Spawn( void ) {
  535. spawnArgs.GetFloat( "wait", "0.5", wait );
  536. spawnArgs.GetBool( "triggerFirst", "0", triggerFirst );
  537. className = spawnArgs.GetString( "class" );
  538. if ( !className.Length() )
  539. {
  540. gameLocal.Error( "idTrigger_classname '%s' at (%s) doesn't have 'classname' key specified", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
  541. }
  542. nextTriggerTime = 0;
  543. GetPhysics()->SetContents( CONTENTS_TRIGGER );
  544. }
  545. void idTrigger_classname::TriggerAction( idEntity *activator )
  546. {
  547. ActivateTargets( activator );
  548. CallScript();
  549. if ( wait >= 0 )
  550. {
  551. nextTriggerTime = gameLocal.time + SEC2MS( wait );
  552. }
  553. else
  554. {
  555. // we can't just remove (this) here, because this is a touch function
  556. // called while looping through area links...
  557. nextTriggerTime = gameLocal.time + 1;
  558. PostEventMS( &EV_Remove, 0 );
  559. }
  560. }
  561. void idTrigger_classname::Event_TriggerAction( idEntity *activator )
  562. {
  563. TriggerAction( activator );
  564. }
  565. void idTrigger_classname::Event_Trigger( idEntity *activator )
  566. {
  567. if ( nextTriggerTime > gameLocal.time )
  568. {
  569. // can't retrigger until the wait is over
  570. return;
  571. }
  572. if ( !activator || ( activator->spawnArgs.GetString("classname") != className ) )
  573. {
  574. return;
  575. }
  576. if ( triggerFirst )
  577. {
  578. triggerFirst = false;
  579. return;
  580. }
  581. // don't allow it to trigger twice in a single frame
  582. nextTriggerTime = gameLocal.time + 1;
  583. TriggerAction( activator );
  584. }
  585. /*
  586. ================
  587. idTrigger_EntityName::Event_Touch
  588. ================
  589. */
  590. void idTrigger_classname::Event_Touch( idEntity *other, trace_t *trace )
  591. {
  592. if( triggerFirst )
  593. {
  594. return;
  595. }
  596. if ( nextTriggerTime > gameLocal.time )
  597. {
  598. // can't retrigger until the wait is over
  599. return;
  600. }
  601. if ( !other || ( other->spawnArgs.GetString("classname") != className ) )
  602. {
  603. return;
  604. }
  605. nextTriggerTime = gameLocal.time + 1;
  606. TriggerAction( other );
  607. }
  608. /*
  609. ===============================================================================
  610. idTrigger_EntityName
  611. ===============================================================================
  612. */
  613. CLASS_DECLARATION( idTrigger, idTrigger_EntityName )
  614. EVENT( EV_Touch, idTrigger_EntityName::Event_Touch )
  615. EVENT( EV_Activate, idTrigger_EntityName::Event_Trigger )
  616. EVENT( EV_TriggerAction, idTrigger_EntityName::Event_TriggerAction )
  617. END_CLASS
  618. /*
  619. ================
  620. idTrigger_EntityName::idTrigger_EntityName
  621. ================
  622. */
  623. idTrigger_EntityName::idTrigger_EntityName( void ) {
  624. wait = 0.0f;
  625. random = 0.0f;
  626. delay = 0.0f;
  627. random_delay = 0.0f;
  628. nextTriggerTime = 0;
  629. triggerFirst = false;
  630. }
  631. /*
  632. ================
  633. idTrigger_EntityName::Save
  634. ================
  635. */
  636. void idTrigger_EntityName::Save( idSaveGame *savefile ) const {
  637. savefile->WriteFloat( wait );
  638. savefile->WriteFloat( random );
  639. savefile->WriteFloat( delay );
  640. savefile->WriteFloat( random_delay );
  641. savefile->WriteInt( nextTriggerTime );
  642. savefile->WriteBool( triggerFirst );
  643. savefile->WriteString( entityName );
  644. }
  645. /*
  646. ================
  647. idTrigger_EntityName::Restore
  648. ================
  649. */
  650. void idTrigger_EntityName::Restore( idRestoreGame *savefile ) {
  651. savefile->ReadFloat( wait );
  652. savefile->ReadFloat( random );
  653. savefile->ReadFloat( delay );
  654. savefile->ReadFloat( random_delay );
  655. savefile->ReadInt( nextTriggerTime );
  656. savefile->ReadBool( triggerFirst );
  657. savefile->ReadString( entityName );
  658. }
  659. /*
  660. ================
  661. idTrigger_EntityName::Spawn
  662. ================
  663. */
  664. void idTrigger_EntityName::Spawn( void ) {
  665. spawnArgs.GetFloat( "wait", "0.5", wait );
  666. spawnArgs.GetFloat( "random", "0", random );
  667. spawnArgs.GetFloat( "delay", "0", delay );
  668. spawnArgs.GetFloat( "random_delay", "0", random_delay );
  669. if ( random && ( random >= wait ) && ( wait >= 0 ) ) {
  670. random = wait - 1;
  671. gameLocal.Warning( "idTrigger_EntityName '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
  672. }
  673. if ( random_delay && ( random_delay >= delay ) && ( delay >= 0 ) ) {
  674. random_delay = delay - 1;
  675. gameLocal.Warning( "idTrigger_EntityName '%s' at (%s) has random_delay >= delay", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
  676. }
  677. spawnArgs.GetBool( "triggerFirst", "0", triggerFirst );
  678. entityName = spawnArgs.GetString( "entityname" );
  679. if ( !entityName.Length() ) {
  680. gameLocal.Error( "idTrigger_EntityName '%s' at (%s) doesn't have 'entityname' key specified", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
  681. }
  682. nextTriggerTime = 0;
  683. if ( !spawnArgs.GetBool( "noTouch" ) ) {
  684. GetPhysics()->SetContents( CONTENTS_TRIGGER );
  685. }
  686. }
  687. /*
  688. ================
  689. idTrigger_EntityName::TriggerAction
  690. ================
  691. */
  692. void idTrigger_EntityName::TriggerAction( idEntity *activator ) {
  693. ActivateTargets( activator );
  694. CallScript();
  695. if ( wait >= 0 ) {
  696. nextTriggerTime = gameLocal.time + SEC2MS( wait + random * gameLocal.random.CRandomFloat() );
  697. } else {
  698. // we can't just remove (this) here, because this is a touch function
  699. // called while looping through area links...
  700. nextTriggerTime = gameLocal.time + 1;
  701. PostEventMS( &EV_Remove, 0 );
  702. }
  703. }
  704. /*
  705. ================
  706. idTrigger_EntityName::Event_TriggerAction
  707. ================
  708. */
  709. void idTrigger_EntityName::Event_TriggerAction( idEntity *activator ) {
  710. TriggerAction( activator );
  711. }
  712. /*
  713. ================
  714. idTrigger_EntityName::Event_Trigger
  715. the trigger was just activated
  716. activated should be the entity that originated the activation sequence (ie. the original target)
  717. activator should be set to the activator so it can be held through a delay
  718. so wait for the delay time before firing
  719. ================
  720. */
  721. void idTrigger_EntityName::Event_Trigger( idEntity *activator ) {
  722. if ( nextTriggerTime > gameLocal.time ) {
  723. // can't retrigger until the wait is over
  724. return;
  725. }
  726. if ( !activator || ( activator->name != entityName ) ) {
  727. return;
  728. }
  729. if ( triggerFirst ) {
  730. triggerFirst = false;
  731. return;
  732. }
  733. // don't allow it to trigger twice in a single frame
  734. nextTriggerTime = gameLocal.time + 1;
  735. if ( delay > 0 ) {
  736. // don't allow it to trigger again until our delay has passed
  737. nextTriggerTime += SEC2MS( delay + random_delay * gameLocal.random.CRandomFloat() );
  738. PostEventSec( &EV_TriggerAction, delay, activator );
  739. } else {
  740. TriggerAction( activator );
  741. }
  742. }
  743. /*
  744. ================
  745. idTrigger_EntityName::Event_Touch
  746. ================
  747. */
  748. void idTrigger_EntityName::Event_Touch( idEntity *other, trace_t *trace ) {
  749. if( triggerFirst ) {
  750. return;
  751. }
  752. if ( nextTriggerTime > gameLocal.time ) {
  753. // can't retrigger until the wait is over
  754. return;
  755. }
  756. if ( !other || ( other->name != entityName ) ) {
  757. return;
  758. }
  759. nextTriggerTime = gameLocal.time + 1;
  760. if ( delay > 0 )
  761. {
  762. // don't allow it to trigger again until our delay has passed
  763. nextTriggerTime += SEC2MS( delay + random_delay * gameLocal.random.CRandomFloat() );
  764. PostEventSec( &EV_TriggerAction, delay, other );
  765. }
  766. else
  767. {
  768. //bc this is VERY car-specific hack to ensure all four corners of the car are within the "hidey" trigger.
  769. if ( other->IsType( idActivator::Type ) )
  770. {
  771. idAngles otherAngles;
  772. idVec3 size;
  773. idVec3 forward;
  774. idVec3 right;
  775. other->spawnArgs.GetVector( "size", "0 0 0", size );
  776. if (size.x != 0 && size.y != 0 && size.z != 0)
  777. {
  778. otherAngles = other->GetPhysics()->GetAxis().ToAngles();
  779. forward = otherAngles.ToForward();
  780. otherAngles.yaw += 90;
  781. right = otherAngles.ToForward();
  782. idVec3 frontLeft = other->GetPhysics()->GetAbsBounds().GetCenter() + forward * (size.x/2) + right * (size.y/2);
  783. idVec3 frontRight = other->GetPhysics()->GetAbsBounds().GetCenter() + forward * (size.x/2) + right * -(size.y/2);
  784. idVec3 rearLeft = other->GetPhysics()->GetAbsBounds().GetCenter() + forward * -(size.x/2) + right * (size.y/2);
  785. idVec3 rearRight = other->GetPhysics()->GetAbsBounds().GetCenter() + forward * -(size.x/2) + right * -(size.y/2);
  786. /*
  787. gameRenderWorld->DebugCircle( colorWhite, frontLeft, idVec3(0,0,1), 4, 6, 500 );
  788. gameRenderWorld->DebugCircle( colorWhite, frontRight, idVec3(0,0,1), 4, 6, 500 );
  789. gameRenderWorld->DebugCircle( colorWhite, rearLeft, idVec3(0,0,1), 4, 6, 500 );
  790. gameRenderWorld->DebugCircle( colorWhite, rearRight, idVec3(0,0,1), 4, 6, 500 );
  791. */
  792. if (!this->GetPhysics()->GetAbsBounds().ContainsPoint( frontLeft)
  793. || !this->GetPhysics()->GetAbsBounds().ContainsPoint( frontRight)
  794. || !this->GetPhysics()->GetAbsBounds().ContainsPoint( rearLeft)
  795. || !this->GetPhysics()->GetAbsBounds().ContainsPoint( rearRight))
  796. {
  797. return;
  798. }
  799. else
  800. {
  801. //inside the trigger.
  802. idEntity *carMaster = gameLocal.FindEntity( other->spawnArgs.GetString( "master" ) );
  803. if (carMaster)
  804. {
  805. gameLocal.GetLocalPlayer()->UseFrob( carMaster, "inEntTrigger" );
  806. TriggerAction( other );
  807. return;
  808. }
  809. return;
  810. }
  811. }
  812. }
  813. TriggerAction( other );
  814. }
  815. }
  816. /*
  817. ===============================================================================
  818. idTrigger_Timer
  819. ===============================================================================
  820. */
  821. const idEventDef EV_Timer( "<timer>", NULL );
  822. CLASS_DECLARATION( idTrigger, idTrigger_Timer )
  823. EVENT( EV_Timer, idTrigger_Timer::Event_Timer )
  824. EVENT( EV_Activate, idTrigger_Timer::Event_Use )
  825. END_CLASS
  826. /*
  827. ================
  828. idTrigger_Timer::idTrigger_Timer
  829. ================
  830. */
  831. idTrigger_Timer::idTrigger_Timer( void ) {
  832. random = 0.0f;
  833. wait = 0.0f;
  834. on = false;
  835. delay = 0.0f;
  836. }
  837. /*
  838. ================
  839. idTrigger_Timer::Save
  840. ================
  841. */
  842. void idTrigger_Timer::Save( idSaveGame *savefile ) const {
  843. savefile->WriteFloat( random );
  844. savefile->WriteFloat( wait );
  845. savefile->WriteBool( on );
  846. savefile->WriteFloat( delay );
  847. savefile->WriteString( onName );
  848. savefile->WriteString( offName );
  849. }
  850. /*
  851. ================
  852. idTrigger_Timer::Restore
  853. ================
  854. */
  855. void idTrigger_Timer::Restore( idRestoreGame *savefile ) {
  856. savefile->ReadFloat( random );
  857. savefile->ReadFloat( wait );
  858. savefile->ReadBool( on );
  859. savefile->ReadFloat( delay );
  860. savefile->ReadString( onName );
  861. savefile->ReadString( offName );
  862. }
  863. /*
  864. ================
  865. idTrigger_Timer::Spawn
  866. Repeatedly fires its targets.
  867. Can be turned on or off by using.
  868. ================
  869. */
  870. void idTrigger_Timer::Spawn( void ) {
  871. spawnArgs.GetFloat( "random", "1", random );
  872. spawnArgs.GetFloat( "wait", "1", wait );
  873. spawnArgs.GetBool( "start_on", "0", on );
  874. spawnArgs.GetFloat( "delay", "0", delay );
  875. onName = spawnArgs.GetString( "onName" );
  876. offName = spawnArgs.GetString( "offName" );
  877. if ( random >= wait && wait >= 0 ) {
  878. random = wait - 0.001;
  879. gameLocal.Warning( "idTrigger_Timer '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
  880. }
  881. if ( on ) {
  882. PostEventSec( &EV_Timer, delay );
  883. }
  884. }
  885. /*
  886. ================
  887. idTrigger_Timer::Enable
  888. ================
  889. */
  890. void idTrigger_Timer::Enable( void ) {
  891. // if off, turn it on
  892. if ( !on ) {
  893. on = true;
  894. PostEventSec( &EV_Timer, delay );
  895. }
  896. }
  897. /*
  898. ================
  899. idTrigger_Timer::Disable
  900. ================
  901. */
  902. void idTrigger_Timer::Disable( void ) {
  903. // if on, turn it off
  904. if ( on ) {
  905. on = false;
  906. CancelEvents( &EV_Timer );
  907. }
  908. }
  909. /*
  910. ================
  911. idTrigger_Timer::Event_Timer
  912. ================
  913. */
  914. void idTrigger_Timer::Event_Timer( void ) {
  915. ActivateTargets( this );
  916. // set time before next firing
  917. if ( wait >= 0.0f ) {
  918. PostEventSec( &EV_Timer, wait + gameLocal.random.CRandomFloat() * random );
  919. }
  920. }
  921. /*
  922. ================
  923. idTrigger_Timer::Event_Use
  924. ================
  925. */
  926. void idTrigger_Timer::Event_Use( idEntity *activator ) {
  927. // if on, turn it off
  928. if ( on ) {
  929. if ( offName.Length() && offName.Icmp( activator->GetName() ) ) {
  930. return;
  931. }
  932. on = false;
  933. CancelEvents( &EV_Timer );
  934. } else {
  935. // turn it on
  936. if ( onName.Length() && onName.Icmp( activator->GetName() ) ) {
  937. return;
  938. }
  939. on = true;
  940. PostEventSec( &EV_Timer, delay );
  941. }
  942. }
  943. /*
  944. ===============================================================================
  945. idTrigger_Count
  946. ===============================================================================
  947. */
  948. CLASS_DECLARATION( idTrigger, idTrigger_Count )
  949. EVENT( EV_Activate, idTrigger_Count::Event_Trigger )
  950. EVENT( EV_TriggerAction, idTrigger_Count::Event_TriggerAction )
  951. END_CLASS
  952. /*
  953. ================
  954. idTrigger_Count::idTrigger_Count
  955. ================
  956. */
  957. idTrigger_Count::idTrigger_Count( void ) {
  958. goal = 0;
  959. count = 0;
  960. delay = 0.0f;
  961. }
  962. /*
  963. ================
  964. idTrigger_Count::Save
  965. ================
  966. */
  967. void idTrigger_Count::Save( idSaveGame *savefile ) const {
  968. savefile->WriteInt( goal );
  969. savefile->WriteInt( count );
  970. savefile->WriteFloat( delay );
  971. }
  972. /*
  973. ================
  974. idTrigger_Count::Restore
  975. ================
  976. */
  977. void idTrigger_Count::Restore( idRestoreGame *savefile ) {
  978. savefile->ReadInt( goal );
  979. savefile->ReadInt( count );
  980. savefile->ReadFloat( delay );
  981. }
  982. /*
  983. ================
  984. idTrigger_Count::Spawn
  985. ================
  986. */
  987. void idTrigger_Count::Spawn( void ) {
  988. spawnArgs.GetInt( "count", "1", goal );
  989. spawnArgs.GetFloat( "delay", "0", delay );
  990. count = 0;
  991. }
  992. /*
  993. ================
  994. idTrigger_Count::Event_Trigger
  995. ================
  996. */
  997. void idTrigger_Count::Event_Trigger( idEntity *activator ) {
  998. // goal of -1 means trigger has been exhausted
  999. if (goal >= 0) {
  1000. count++;
  1001. if ( count >= goal ) {
  1002. if (spawnArgs.GetBool("repeat")) {
  1003. count = 0;
  1004. } else {
  1005. goal = -1;
  1006. }
  1007. PostEventSec( &EV_TriggerAction, delay, activator );
  1008. }
  1009. }
  1010. }
  1011. /*
  1012. ================
  1013. idTrigger_Count::Event_TriggerAction
  1014. ================
  1015. */
  1016. void idTrigger_Count::Event_TriggerAction( idEntity *activator ) {
  1017. ActivateTargets( activator );
  1018. CallScript();
  1019. if ( goal == -1 ) {
  1020. PostEventMS( &EV_Remove, 0 );
  1021. }
  1022. }
  1023. const idEventDef EV_triggerpushactivate( "triggerpushactivate", "d" );
  1024. //bc trigger push.
  1025. CLASS_DECLARATION( idTrigger, idTrigger_Push )
  1026. EVENT( EV_Touch, idTrigger_Push::Event_Touch )
  1027. EVENT( EV_triggerpushactivate, idTrigger_Push::Event_triggerpushactivate )
  1028. END_CLASS
  1029. idTrigger_Push::idTrigger_Push( void )
  1030. {
  1031. on = false;
  1032. wait = 0.2f;
  1033. yaw = 0;
  1034. pitch = -20;
  1035. force = 256;
  1036. }
  1037. void idTrigger_Push::Save( idSaveGame *savefile ) const {
  1038. savefile->WriteBool( on );
  1039. savefile->WriteInt( nextTime );
  1040. savefile->WriteInt( yaw );
  1041. savefile->WriteInt( pitch);
  1042. savefile->WriteInt( force );
  1043. savefile->WriteFloat( wait );
  1044. }
  1045. /*
  1046. ================
  1047. idTrigger_Hurt::Restore
  1048. ================
  1049. */
  1050. void idTrigger_Push::Restore( idRestoreGame *savefile ) {
  1051. savefile->ReadBool( on );
  1052. savefile->ReadInt( nextTime );
  1053. savefile->ReadInt( yaw );
  1054. savefile->ReadInt( pitch);
  1055. savefile->ReadInt( force );
  1056. savefile->ReadFloat( wait );
  1057. }
  1058. void idTrigger_Push::Spawn( void )
  1059. {
  1060. spawnArgs.GetBool( "start_on", "1", on );
  1061. spawnArgs.GetFloat( "wait", "0.2", wait );
  1062. spawnArgs.GetInt( "yaw", "0", yaw );
  1063. spawnArgs.GetInt( "pitch", "-20", pitch );
  1064. spawnArgs.GetInt( "force", "256", force );
  1065. nextTime = gameLocal.time;
  1066. Enable();
  1067. }
  1068. void idTrigger_Push::Event_Touch( idEntity *other, trace_t *trace )
  1069. {
  1070. if ( on && other && gameLocal.time >= nextTime )
  1071. {
  1072. //push the thing.
  1073. idAngles ang;
  1074. ang.pitch = pitch;
  1075. ang.yaw = yaw;
  1076. ang.roll = 0;
  1077. idVec3 dir;
  1078. dir = ang.ToForward();
  1079. dir *= force;
  1080. other->GetPhysics()->SetLinearVelocity( other->GetPhysics()->GetLinearVelocity() + dir );
  1081. nextTime = gameLocal.time + SEC2MS( wait );
  1082. }
  1083. }
  1084. void idTrigger_Push::Event_triggerpushactivate( int value )
  1085. {
  1086. if (value > 0)
  1087. {
  1088. on = 1;
  1089. }
  1090. else
  1091. {
  1092. on = 0;
  1093. }
  1094. }
  1095. /*
  1096. ===============================================================================
  1097. idTrigger_Hurt
  1098. ===============================================================================
  1099. */
  1100. CLASS_DECLARATION( idTrigger, idTrigger_Hurt )
  1101. EVENT( EV_Touch, idTrigger_Hurt::Event_Touch )
  1102. EVENT( EV_Activate, idTrigger_Hurt::Event_Toggle )
  1103. END_CLASS
  1104. /*
  1105. ================
  1106. idTrigger_Hurt::idTrigger_Hurt
  1107. ================
  1108. */
  1109. idTrigger_Hurt::idTrigger_Hurt( void ) {
  1110. on = false;
  1111. delay = 0.0f;
  1112. nextTime = 0;
  1113. }
  1114. /*
  1115. ================
  1116. idTrigger_Hurt::Save
  1117. ================
  1118. */
  1119. void idTrigger_Hurt::Save( idSaveGame *savefile ) const {
  1120. savefile->WriteBool( on );
  1121. savefile->WriteFloat( delay );
  1122. savefile->WriteInt( nextTime );
  1123. }
  1124. /*
  1125. ================
  1126. idTrigger_Hurt::Restore
  1127. ================
  1128. */
  1129. void idTrigger_Hurt::Restore( idRestoreGame *savefile ) {
  1130. savefile->ReadBool( on );
  1131. savefile->ReadFloat( delay );
  1132. savefile->ReadInt( nextTime );
  1133. }
  1134. /*
  1135. ================
  1136. idTrigger_Hurt::Spawn
  1137. Damages activator
  1138. Can be turned on or off by using.
  1139. ================
  1140. */
  1141. void idTrigger_Hurt::Spawn( void ) {
  1142. spawnArgs.GetBool( "on", "1", on );
  1143. spawnArgs.GetFloat( "delay", "1.0", delay );
  1144. nextTime = gameLocal.time;
  1145. Enable();
  1146. }
  1147. /*
  1148. ================
  1149. idTrigger_Hurt::Event_Touch
  1150. ================
  1151. */
  1152. void idTrigger_Hurt::Event_Touch( idEntity *other, trace_t *trace ) {
  1153. const char *damage;
  1154. if ( on && other && gameLocal.time >= nextTime ) {
  1155. #ifdef _D3XP
  1156. bool playerOnly = spawnArgs.GetBool( "playerOnly" );
  1157. if ( playerOnly ) {
  1158. if ( !other->IsType( idPlayer::Type ) ) {
  1159. return;
  1160. }
  1161. }
  1162. #endif
  1163. damage = spawnArgs.GetString( "def_damage", "damage_painTrigger" );
  1164. #ifdef _D3XP
  1165. idVec3 dir = vec3_origin;
  1166. if(spawnArgs.GetBool("kick_from_center", "0")) {
  1167. dir = other->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
  1168. dir.Normalize();
  1169. }
  1170. other->Damage( NULL, NULL, dir, damage, 1.0f, INVALID_JOINT );
  1171. #else
  1172. other->Damage( NULL, NULL, vec3_origin, damage, 1.0f, INVALID_JOINT );
  1173. #endif
  1174. ActivateTargets( other );
  1175. CallScript();
  1176. nextTime = gameLocal.time + SEC2MS( delay );
  1177. }
  1178. }
  1179. /*
  1180. ================
  1181. idTrigger_Hurt::Event_Toggle
  1182. ================
  1183. */
  1184. void idTrigger_Hurt::Event_Toggle( idEntity *activator ) {
  1185. on = !on;
  1186. }
  1187. /*
  1188. ===============================================================================
  1189. idTrigger_Fade
  1190. ===============================================================================
  1191. */
  1192. CLASS_DECLARATION( idTrigger, idTrigger_Fade )
  1193. EVENT( EV_Activate, idTrigger_Fade::Event_Trigger )
  1194. END_CLASS
  1195. /*
  1196. ================
  1197. idTrigger_Fade::Event_Trigger
  1198. ================
  1199. */
  1200. void idTrigger_Fade::Event_Trigger( idEntity *activator ) {
  1201. idVec4 fadeColor;
  1202. int fadeTime;
  1203. idPlayer *player;
  1204. player = gameLocal.GetLocalPlayer();
  1205. if ( player ) {
  1206. fadeColor = spawnArgs.GetVec4( "fadeColor", "0, 0, 0, 1" );
  1207. fadeTime = SEC2MS( spawnArgs.GetFloat( "fadeTime", "0.5" ) );
  1208. player->playerView.Fade( fadeColor, fadeTime );
  1209. PostEventMS( &EV_ActivateTargets, fadeTime, activator );
  1210. }
  1211. }
  1212. /*
  1213. ===============================================================================
  1214. idTrigger_Touch
  1215. ===============================================================================
  1216. */
  1217. CLASS_DECLARATION( idTrigger, idTrigger_Touch )
  1218. EVENT( EV_Activate, idTrigger_Touch::Event_Trigger )
  1219. END_CLASS
  1220. /*
  1221. ================
  1222. idTrigger_Touch::idTrigger_Touch
  1223. ================
  1224. */
  1225. idTrigger_Touch::idTrigger_Touch( void ) {
  1226. clipModel = NULL;
  1227. }
  1228. /*
  1229. ================
  1230. idTrigger_Touch::Spawn
  1231. ================
  1232. */
  1233. void idTrigger_Touch::Spawn( void ) {
  1234. // get the clip model
  1235. clipModel = new idClipModel( GetPhysics()->GetClipModel() );
  1236. // remove the collision model from the physics object
  1237. GetPhysics()->SetClipModel( NULL, 1.0f );
  1238. if ( spawnArgs.GetBool( "start_on" ) ) {
  1239. BecomeActive( TH_THINK );
  1240. }
  1241. }
  1242. /*
  1243. ================
  1244. idTrigger_Touch::Save
  1245. ================
  1246. */
  1247. void idTrigger_Touch::Save( idSaveGame *savefile ) {
  1248. savefile->WriteClipModel( clipModel );
  1249. }
  1250. /*
  1251. ================
  1252. idTrigger_Touch::Restore
  1253. ================
  1254. */
  1255. void idTrigger_Touch::Restore( idRestoreGame *savefile ) {
  1256. savefile->ReadClipModel( clipModel );
  1257. }
  1258. /*
  1259. ================
  1260. idTrigger_Touch::TouchEntities
  1261. ================
  1262. */
  1263. void idTrigger_Touch::TouchEntities( void ) {
  1264. int numClipModels, i;
  1265. idBounds bounds;
  1266. idClipModel *cm, *clipModelList[ MAX_GENTITIES ];
  1267. if ( clipModel == NULL || scriptFunction == NULL ) {
  1268. return;
  1269. }
  1270. bounds.FromTransformedBounds( clipModel->GetBounds(), clipModel->GetOrigin(), clipModel->GetAxis() );
  1271. numClipModels = gameLocal.clip.ClipModelsTouchingBounds( bounds, -1, clipModelList, MAX_GENTITIES );
  1272. for ( i = 0; i < numClipModels; i++ ) {
  1273. cm = clipModelList[ i ];
  1274. if ( !cm->IsTraceModel() ) {
  1275. continue;
  1276. }
  1277. idEntity *entity = cm->GetEntity();
  1278. if ( !entity ) {
  1279. continue;
  1280. }
  1281. if ( !gameLocal.clip.ContentsModel( cm->GetOrigin(), cm, cm->GetAxis(), -1,
  1282. clipModel->Handle(), clipModel->GetOrigin(), clipModel->GetAxis() ) ) {
  1283. continue;
  1284. }
  1285. ActivateTargets( entity );
  1286. idThread *thread = new idThread();
  1287. thread->CallFunction( entity, scriptFunction, false );
  1288. thread->DelayedStart( 0 );
  1289. }
  1290. }
  1291. /*
  1292. ================
  1293. idTrigger_Touch::Think
  1294. ================
  1295. */
  1296. void idTrigger_Touch::Think( void ) {
  1297. if ( thinkFlags & TH_THINK ) {
  1298. TouchEntities();
  1299. }
  1300. idEntity::Think();
  1301. }
  1302. /*
  1303. ================
  1304. idTrigger_Touch::Event_Trigger
  1305. ================
  1306. */
  1307. void idTrigger_Touch::Event_Trigger( idEntity *activator ) {
  1308. if ( thinkFlags & TH_THINK ) {
  1309. BecomeInactive( TH_THINK );
  1310. } else {
  1311. BecomeActive( TH_THINK );
  1312. }
  1313. }
  1314. /*
  1315. ================
  1316. idTrigger_Touch::Enable
  1317. ================
  1318. */
  1319. void idTrigger_Touch::Enable( void ) {
  1320. BecomeActive( TH_THINK );
  1321. }
  1322. /*
  1323. ================
  1324. idTrigger_Touch::Disable
  1325. ================
  1326. */
  1327. void idTrigger_Touch::Disable( void ) {
  1328. BecomeInactive( TH_THINK );
  1329. }
  1330. #ifdef CTF
  1331. /*
  1332. ===============================================================================
  1333. idTrigger_Flag
  1334. ===============================================================================
  1335. */
  1336. CLASS_DECLARATION( idTrigger_Multi, idTrigger_Flag )
  1337. EVENT( EV_Touch, idTrigger_Flag::Event_Touch )
  1338. END_CLASS
  1339. idTrigger_Flag::idTrigger_Flag( void ) {
  1340. team = -1;
  1341. player = false;
  1342. eventFlag = NULL;
  1343. }
  1344. void idTrigger_Flag::Spawn( void ) {
  1345. team = spawnArgs.GetInt( "team", "0" );
  1346. player = spawnArgs.GetBool( "player", "0" );
  1347. idStr funcname = spawnArgs.GetString( "eventflag", "" );
  1348. if ( funcname.Length() ) {
  1349. eventFlag = idEventDef::FindEvent( funcname );// gameLocal.program.FindFunction( funcname );//, &idItemTeam::Type );
  1350. if ( eventFlag == NULL ) {
  1351. gameLocal.Warning( "trigger '%s' at (%s) event unknown '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), funcname.c_str() );
  1352. }
  1353. } else {
  1354. eventFlag = NULL;
  1355. }
  1356. idTrigger_Multi::Spawn();
  1357. }
  1358. void idTrigger_Flag::Event_Touch( idEntity *other, trace_t *trace ) {
  1359. bool bTrigger = false;
  1360. idItemTeam * flag = NULL;
  1361. if ( player ) {
  1362. if ( !other->IsType( idPlayer::Type ) )
  1363. return;
  1364. idPlayer * player = static_cast<idPlayer *>(other);
  1365. if ( player->carryingFlag == false )
  1366. return;
  1367. if ( team != -1 && ( player->team != team || (player->team != 0 && player->team != 1)) )
  1368. return;
  1369. idItemTeam * flags[2];
  1370. flags[0] = gameLocal.mpGame.GetTeamFlag( 0 );
  1371. flags[1] = gameLocal.mpGame.GetTeamFlag( 1 );
  1372. int iFriend = 1 - player->team; // index to the flag player team wants
  1373. int iOpp = player->team; // index to the flag opp team wants
  1374. // flag is captured if :
  1375. // 1)flag is truely bound to the player
  1376. // 2)opponent flag has been return
  1377. if ( flags[iFriend]->carried && !flags[iFriend]->dropped && //flags[iFriend]->IsBoundTo( player ) &&
  1378. !flags[iOpp]->carried && !flags[iOpp]->dropped )
  1379. flag = flags[iFriend];
  1380. else
  1381. return;
  1382. } else {
  1383. if ( !other->IsType( idItemTeam::Type ) )
  1384. return;
  1385. idItemTeam * item = static_cast<idItemTeam *>( other );
  1386. if ( item->team == team || team == -1 ) {
  1387. flag = item;
  1388. }
  1389. else
  1390. return;
  1391. }
  1392. if ( flag ) {
  1393. switch ( eventFlag->GetNumArgs() ) {
  1394. default :
  1395. case 0 :
  1396. flag->PostEventMS( eventFlag, 0 );
  1397. break;
  1398. case 1 :
  1399. flag->PostEventMS( eventFlag, 0, NULL );
  1400. break;
  1401. case 2 :
  1402. flag->PostEventMS( eventFlag, 0, NULL, NULL );
  1403. break;
  1404. }
  1405. /*
  1406. ServerSendEvent( eventFlag->GetEventNum(), NULL, true, false );
  1407. idThread *thread;
  1408. if ( scriptFlag ) {
  1409. thread = new idThread();
  1410. thread->CallFunction( flag, scriptFlag, false );
  1411. thread->DelayedStart( 0 );
  1412. }
  1413. */
  1414. idTrigger_Multi::Event_Touch( other, trace );
  1415. }
  1416. }
  1417. #endif