Target.cpp 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition 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 BFG Edition 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 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. 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.
  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. /*
  21. Invisible entities that affect other entities or the world when activated.
  22. */
  23. #include "../idlib/precompiled.h"
  24. #pragma hdrstop
  25. #include "Game_local.h"
  26. /*
  27. ===============================================================================
  28. idTarget
  29. ===============================================================================
  30. */
  31. CLASS_DECLARATION( idEntity, idTarget )
  32. END_CLASS
  33. /*
  34. ===============================================================================
  35. idTarget_Remove
  36. ===============================================================================
  37. */
  38. CLASS_DECLARATION( idTarget, idTarget_Remove )
  39. EVENT( EV_Activate, idTarget_Remove::Event_Activate )
  40. END_CLASS
  41. /*
  42. ================
  43. idTarget_Remove::Event_Activate
  44. ================
  45. */
  46. void idTarget_Remove::Event_Activate( idEntity *activator ) {
  47. int i;
  48. idEntity *ent;
  49. for( i = 0; i < targets.Num(); i++ ) {
  50. ent = targets[ i ].GetEntity();
  51. if ( ent ) {
  52. ent->PostEventMS( &EV_Remove, 0 );
  53. }
  54. }
  55. // delete our self when done
  56. PostEventMS( &EV_Remove, 0 );
  57. }
  58. /*
  59. ===============================================================================
  60. idTarget_Show
  61. ===============================================================================
  62. */
  63. CLASS_DECLARATION( idTarget, idTarget_Show )
  64. EVENT( EV_Activate, idTarget_Show::Event_Activate )
  65. END_CLASS
  66. /*
  67. ================
  68. idTarget_Show::Event_Activate
  69. ================
  70. */
  71. void idTarget_Show::Event_Activate( idEntity *activator ) {
  72. int i;
  73. idEntity *ent;
  74. for( i = 0; i < targets.Num(); i++ ) {
  75. ent = targets[ i ].GetEntity();
  76. if ( ent ) {
  77. ent->Show();
  78. }
  79. }
  80. // delete our self when done
  81. PostEventMS( &EV_Remove, 0 );
  82. }
  83. /*
  84. ===============================================================================
  85. idTarget_Damage
  86. ===============================================================================
  87. */
  88. CLASS_DECLARATION( idTarget, idTarget_Damage )
  89. EVENT( EV_Activate, idTarget_Damage::Event_Activate )
  90. END_CLASS
  91. /*
  92. ================
  93. idTarget_Damage::Event_Activate
  94. ================
  95. */
  96. void idTarget_Damage::Event_Activate( idEntity *activator ) {
  97. int i;
  98. const char *damage;
  99. idEntity * ent;
  100. damage = spawnArgs.GetString( "def_damage", "damage_generic" );
  101. for( i = 0; i < targets.Num(); i++ ) {
  102. ent = targets[ i ].GetEntity();
  103. if ( ent ) {
  104. ent->Damage( this, this, vec3_origin, damage, 1.0f, INVALID_JOINT );
  105. }
  106. }
  107. }
  108. /*
  109. ===============================================================================
  110. idTarget_SessionCommand
  111. ===============================================================================
  112. */
  113. CLASS_DECLARATION( idTarget, idTarget_SessionCommand )
  114. EVENT( EV_Activate, idTarget_SessionCommand::Event_Activate )
  115. END_CLASS
  116. /*
  117. ================
  118. idTarget_SessionCommand::Event_Activate
  119. ================
  120. */
  121. void idTarget_SessionCommand::Event_Activate( idEntity *activator ) {
  122. gameLocal.sessionCommand = spawnArgs.GetString( "command" );
  123. }
  124. /*
  125. ===============================================================================
  126. idTarget_EndLevel
  127. Just a modified form of idTarget_SessionCommand
  128. ===============================================================================
  129. */
  130. CLASS_DECLARATION( idTarget, idTarget_EndLevel )
  131. EVENT( EV_Activate, idTarget_EndLevel::Event_Activate )
  132. END_CLASS
  133. /*
  134. ================
  135. idTarget_EndLevel::Event_Activate
  136. ================
  137. */
  138. void idTarget_EndLevel::Event_Activate( idEntity *activator ) {
  139. extern idCVar g_demoMode;
  140. if ( g_demoMode.GetInteger() > 0 ) {
  141. gameLocal.sessionCommand = "disconnect";
  142. return;
  143. }
  144. idPlayer * player = gameLocal.GetLocalPlayer();
  145. const bool isTutorialMap = ( idStr::FindText( gameLocal.GetMapFileName(), "mars_city1" ) >= 0 ) ||
  146. ( idStr::FindText( gameLocal.GetMapFileName(), "mars_city2" ) >= 0 ) ||
  147. ( idStr::FindText( gameLocal.GetMapFileName(), "mc_underground" ) >= 0 );
  148. if ( !isTutorialMap && player != NULL ) {
  149. if ( !player->GetAchievementManager().GetPlayerTookDamage() ) {
  150. player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_COMPLETE_LEVEL_WITHOUT_TAKING_DMG );
  151. }
  152. player->GetAchievementManager().SetPlayerTookDamage( false );
  153. }
  154. if ( !isTutorialMap && spawnArgs.GetBool( "endOfGame" ) ) {
  155. if ( player != NULL ) {
  156. gameExpansionType_t expansion = player->GetExpansionType();
  157. switch ( expansion ) {
  158. case GAME_D3XP:
  159. // The fall-through is done here on purpose so compleating the game on one difficulty will unlock all the easier difficulties
  160. switch ( g_skill.GetInteger() ) {
  161. case 3: player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_3 );
  162. case 2: player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_2 );
  163. case 1: player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_1 );
  164. case 0: player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_ROE_COMPLETED_DIFFICULTY_0 );
  165. }
  166. break;
  167. case GAME_D3LE:
  168. // The fall-through is done here on purpose so compleating the game on one difficulty will unlock all the easier difficulties
  169. switch ( g_skill.GetInteger() ) {
  170. case 3: player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_3 );
  171. case 2: player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_2 );
  172. case 1: player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_1 );
  173. case 0: player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_LE_COMPLETED_DIFFICULTY_0 );
  174. }
  175. break;
  176. case GAME_BASE:
  177. // The fall-through is done here on purpose so compleating the game on one difficulty will unlock all the easier difficulties
  178. switch ( g_skill.GetInteger() ) {
  179. case 3: player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_COMPLETED_DIFFICULTY_3 );
  180. case 2: player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_COMPLETED_DIFFICULTY_2 );
  181. case 1: player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_COMPLETED_DIFFICULTY_1 );
  182. case 0: player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_COMPLETED_DIFFICULTY_0 );
  183. }
  184. break;
  185. }
  186. if ( player->GetPlayedTime() <= 36000 && expansion == GAME_BASE ) {
  187. player->GetAchievementManager().EventCompletesAchievement( ACHIEVEMENT_SPEED_RUN );
  188. }
  189. switch ( expansion ) {
  190. case GAME_D3XP: {
  191. cvarSystem->SetCVarBool( "g_roeNightmare", true );
  192. break;
  193. }
  194. case GAME_D3LE: {
  195. cvarSystem->SetCVarBool( "g_leNightmare", true );
  196. break;
  197. }
  198. case GAME_BASE: {
  199. cvarSystem->SetCVarBool( "g_nightmare", true );
  200. break;
  201. }
  202. }
  203. }
  204. gameLocal.Shell_SetGameComplete();
  205. return;
  206. }
  207. idStr nextMap;
  208. if ( !spawnArgs.GetString( "nextMap", "", nextMap ) ) {
  209. gameLocal.Printf( "idTarget_SessionCommand::Event_Activate: no nextMap key\n" );
  210. return;
  211. }
  212. if ( spawnArgs.GetInt( "devmap", "0" ) ) {
  213. gameLocal.sessionCommand = "devmap "; // only for special demos
  214. } else {
  215. gameLocal.sessionCommand = "map ";
  216. }
  217. gameLocal.sessionCommand += nextMap;
  218. }
  219. /*
  220. ===============================================================================
  221. idTarget_WaitForButton
  222. ===============================================================================
  223. */
  224. CLASS_DECLARATION( idTarget, idTarget_WaitForButton )
  225. EVENT( EV_Activate, idTarget_WaitForButton::Event_Activate )
  226. END_CLASS
  227. /*
  228. ================
  229. idTarget_WaitForButton::Event_Activate
  230. ================
  231. */
  232. void idTarget_WaitForButton::Event_Activate( idEntity *activator ) {
  233. if ( thinkFlags & TH_THINK ) {
  234. BecomeInactive( TH_THINK );
  235. } else {
  236. // always allow during cinematics
  237. cinematic = true;
  238. BecomeActive( TH_THINK );
  239. }
  240. }
  241. /*
  242. ================
  243. idTarget_WaitForButton::Think
  244. ================
  245. */
  246. void idTarget_WaitForButton::Think() {
  247. idPlayer *player;
  248. if ( thinkFlags & TH_THINK ) {
  249. player = gameLocal.GetLocalPlayer();
  250. if ( player != NULL && ( !( player->oldButtons & BUTTON_ATTACK ) ) && ( player->usercmd.buttons & BUTTON_ATTACK ) ) {
  251. player->usercmd.buttons &= ~BUTTON_ATTACK;
  252. BecomeInactive( TH_THINK );
  253. ActivateTargets( player );
  254. }
  255. } else {
  256. BecomeInactive( TH_ALL );
  257. }
  258. }
  259. /*
  260. ===============================================================================
  261. idTarget_SetGlobalShaderParm
  262. ===============================================================================
  263. */
  264. CLASS_DECLARATION( idTarget, idTarget_SetGlobalShaderTime )
  265. EVENT( EV_Activate, idTarget_SetGlobalShaderTime::Event_Activate )
  266. END_CLASS
  267. /*
  268. ================
  269. idTarget_SetGlobalShaderTime::Event_Activate
  270. ================
  271. */
  272. void idTarget_SetGlobalShaderTime::Event_Activate( idEntity *activator ) {
  273. int parm = spawnArgs.GetInt( "globalParm" );
  274. float time = -MS2SEC( gameLocal.time );
  275. if ( parm >= 0 && parm < MAX_GLOBAL_SHADER_PARMS ) {
  276. gameLocal.globalShaderParms[parm] = time;
  277. }
  278. }
  279. /*
  280. ===============================================================================
  281. idTarget_SetShaderParm
  282. ===============================================================================
  283. */
  284. CLASS_DECLARATION( idTarget, idTarget_SetShaderParm )
  285. EVENT( EV_Activate, idTarget_SetShaderParm::Event_Activate )
  286. END_CLASS
  287. /*
  288. ================
  289. idTarget_SetShaderParm::Event_Activate
  290. ================
  291. */
  292. void idTarget_SetShaderParm::Event_Activate( idEntity *activator ) {
  293. int i;
  294. idEntity * ent;
  295. float value;
  296. idVec3 color;
  297. int parmnum;
  298. // set the color on the targets
  299. if ( spawnArgs.GetVector( "_color", "1 1 1", color ) ) {
  300. for( i = 0; i < targets.Num(); i++ ) {
  301. ent = targets[ i ].GetEntity();
  302. if ( ent ) {
  303. ent->SetColor( color[ 0 ], color[ 1 ], color[ 2 ] );
  304. }
  305. }
  306. }
  307. // set any shader parms on the targets
  308. for( parmnum = 0; parmnum < MAX_ENTITY_SHADER_PARMS; parmnum++ ) {
  309. if ( spawnArgs.GetFloat( va( "shaderParm%d", parmnum ), "0", value ) ) {
  310. for( i = 0; i < targets.Num(); i++ ) {
  311. ent = targets[ i ].GetEntity();
  312. if ( ent ) {
  313. ent->SetShaderParm( parmnum, value );
  314. }
  315. }
  316. if (spawnArgs.GetBool("toggle") && (value == 0 || value == 1)) {
  317. int val = value;
  318. val ^= 1;
  319. value = val;
  320. spawnArgs.SetFloat(va("shaderParm%d", parmnum), value);
  321. }
  322. }
  323. }
  324. }
  325. /*
  326. ===============================================================================
  327. idTarget_SetShaderTime
  328. ===============================================================================
  329. */
  330. CLASS_DECLARATION( idTarget, idTarget_SetShaderTime )
  331. EVENT( EV_Activate, idTarget_SetShaderTime::Event_Activate )
  332. END_CLASS
  333. /*
  334. ================
  335. idTarget_SetShaderTime::Event_Activate
  336. ================
  337. */
  338. void idTarget_SetShaderTime::Event_Activate( idEntity *activator ) {
  339. int i;
  340. idEntity * ent;
  341. float time;
  342. time = -MS2SEC( gameLocal.time );
  343. for( i = 0; i < targets.Num(); i++ ) {
  344. ent = targets[ i ].GetEntity();
  345. if ( ent ) {
  346. ent->SetShaderParm( SHADERPARM_TIMEOFFSET, time );
  347. if ( ent->IsType( idLight::Type ) ) {
  348. static_cast<idLight *>(ent)->SetLightParm( SHADERPARM_TIMEOFFSET, time );
  349. }
  350. }
  351. }
  352. }
  353. /*
  354. ===============================================================================
  355. idTarget_FadeEntity
  356. ===============================================================================
  357. */
  358. CLASS_DECLARATION( idTarget, idTarget_FadeEntity )
  359. EVENT( EV_Activate, idTarget_FadeEntity::Event_Activate )
  360. END_CLASS
  361. /*
  362. ================
  363. idTarget_FadeEntity::idTarget_FadeEntity
  364. ================
  365. */
  366. idTarget_FadeEntity::idTarget_FadeEntity() {
  367. fadeFrom.Zero();
  368. fadeStart = 0;
  369. fadeEnd = 0;
  370. }
  371. /*
  372. ================
  373. idTarget_FadeEntity::Save
  374. ================
  375. */
  376. void idTarget_FadeEntity::Save( idSaveGame *savefile ) const {
  377. savefile->WriteVec4( fadeFrom );
  378. savefile->WriteInt( fadeStart );
  379. savefile->WriteInt( fadeEnd );
  380. }
  381. /*
  382. ================
  383. idTarget_FadeEntity::Restore
  384. ================
  385. */
  386. void idTarget_FadeEntity::Restore( idRestoreGame *savefile ) {
  387. savefile->ReadVec4( fadeFrom );
  388. savefile->ReadInt( fadeStart );
  389. savefile->ReadInt( fadeEnd );
  390. }
  391. /*
  392. ================
  393. idTarget_FadeEntity::Event_Activate
  394. ================
  395. */
  396. void idTarget_FadeEntity::Event_Activate( idEntity *activator ) {
  397. idEntity *ent;
  398. int i;
  399. if ( !targets.Num() ) {
  400. return;
  401. }
  402. // always allow during cinematics
  403. cinematic = true;
  404. BecomeActive( TH_THINK );
  405. ent = this;
  406. for( i = 0; i < targets.Num(); i++ ) {
  407. ent = targets[ i ].GetEntity();
  408. if ( ent ) {
  409. ent->GetColor( fadeFrom );
  410. break;
  411. }
  412. }
  413. fadeStart = gameLocal.time;
  414. fadeEnd = gameLocal.time + SEC2MS( spawnArgs.GetFloat( "fadetime" ) );
  415. }
  416. /*
  417. ================
  418. idTarget_FadeEntity::Think
  419. ================
  420. */
  421. void idTarget_FadeEntity::Think() {
  422. int i;
  423. idEntity *ent;
  424. idVec4 color;
  425. idVec4 fadeTo;
  426. float frac;
  427. if ( thinkFlags & TH_THINK ) {
  428. GetColor( fadeTo );
  429. if ( gameLocal.time >= fadeEnd ) {
  430. color = fadeTo;
  431. BecomeInactive( TH_THINK );
  432. } else {
  433. frac = ( float )( gameLocal.time - fadeStart ) / ( float )( fadeEnd - fadeStart );
  434. color.Lerp( fadeFrom, fadeTo, frac );
  435. }
  436. // set the color on the targets
  437. for( i = 0; i < targets.Num(); i++ ) {
  438. ent = targets[ i ].GetEntity();
  439. if ( ent ) {
  440. ent->SetColor( color );
  441. }
  442. }
  443. } else {
  444. BecomeInactive( TH_ALL );
  445. }
  446. }
  447. /*
  448. ===============================================================================
  449. idTarget_LightFadeIn
  450. ===============================================================================
  451. */
  452. CLASS_DECLARATION( idTarget, idTarget_LightFadeIn )
  453. EVENT( EV_Activate, idTarget_LightFadeIn::Event_Activate )
  454. END_CLASS
  455. /*
  456. ================
  457. idTarget_LightFadeIn::Event_Activate
  458. ================
  459. */
  460. void idTarget_LightFadeIn::Event_Activate( idEntity *activator ) {
  461. idEntity *ent;
  462. idLight *light;
  463. int i;
  464. float time;
  465. if ( !targets.Num() ) {
  466. return;
  467. }
  468. time = spawnArgs.GetFloat( "fadetime" );
  469. ent = this;
  470. for( i = 0; i < targets.Num(); i++ ) {
  471. ent = targets[ i ].GetEntity();
  472. if ( !ent ) {
  473. continue;
  474. }
  475. if ( ent->IsType( idLight::Type ) ) {
  476. light = static_cast<idLight *>( ent );
  477. light->FadeIn( time );
  478. } else {
  479. gameLocal.Printf( "'%s' targets non-light '%s'", name.c_str(), ent->GetName() );
  480. }
  481. }
  482. }
  483. /*
  484. ===============================================================================
  485. idTarget_LightFadeOut
  486. ===============================================================================
  487. */
  488. CLASS_DECLARATION( idTarget, idTarget_LightFadeOut )
  489. EVENT( EV_Activate, idTarget_LightFadeOut::Event_Activate )
  490. END_CLASS
  491. /*
  492. ================
  493. idTarget_LightFadeOut::Event_Activate
  494. ================
  495. */
  496. void idTarget_LightFadeOut::Event_Activate( idEntity *activator ) {
  497. idEntity *ent;
  498. idLight *light;
  499. int i;
  500. float time;
  501. if ( !targets.Num() ) {
  502. return;
  503. }
  504. time = spawnArgs.GetFloat( "fadetime" );
  505. ent = this;
  506. for( i = 0; i < targets.Num(); i++ ) {
  507. ent = targets[ i ].GetEntity();
  508. if ( !ent ) {
  509. continue;
  510. }
  511. if ( ent->IsType( idLight::Type ) ) {
  512. light = static_cast<idLight *>( ent );
  513. light->FadeOut( time );
  514. } else {
  515. gameLocal.Printf( "'%s' targets non-light '%s'", name.c_str(), ent->GetName() );
  516. }
  517. }
  518. }
  519. /*
  520. ===============================================================================
  521. idTarget_Give
  522. ===============================================================================
  523. */
  524. CLASS_DECLARATION( idTarget, idTarget_Give )
  525. EVENT( EV_Activate, idTarget_Give::Event_Activate )
  526. END_CLASS
  527. /*
  528. ================
  529. idTarget_Give::Spawn
  530. ================
  531. */
  532. void idTarget_Give::Spawn() {
  533. if ( spawnArgs.GetBool( "onSpawn" ) ) {
  534. PostEventMS( &EV_Activate, 50 );
  535. }
  536. }
  537. /*
  538. ================
  539. idTarget_Give::Event_Activate
  540. ================
  541. */
  542. void idTarget_Give::Event_Activate( idEntity *activator ) {
  543. if ( spawnArgs.GetBool( "development" ) && developer.GetInteger() == 0 ) {
  544. return;
  545. }
  546. static int giveNum = 0;
  547. idPlayer *player = gameLocal.GetLocalPlayer();
  548. if ( player ) {
  549. const idKeyValue *kv = spawnArgs.MatchPrefix( "item", NULL );
  550. while ( kv ) {
  551. const idDict *dict = gameLocal.FindEntityDefDict( kv->GetValue(), false );
  552. if ( dict ) {
  553. idDict d2;
  554. d2.Copy( *dict );
  555. d2.Set( "name", va( "givenitem_%i", giveNum++ ) );
  556. idEntity *ent = NULL;
  557. if ( gameLocal.SpawnEntityDef( d2, &ent ) && ent && ent->IsType( idItem::Type ) ) {
  558. idItem *item = static_cast<idItem*>(ent);
  559. item->GiveToPlayer( gameLocal.GetLocalPlayer(), ITEM_GIVE_FEEDBACK | ITEM_GIVE_UPDATE_STATE );
  560. }
  561. }
  562. kv = spawnArgs.MatchPrefix( "item", kv );
  563. }
  564. }
  565. }
  566. /*
  567. ===============================================================================
  568. idTarget_GiveEmail
  569. ===============================================================================
  570. */
  571. CLASS_DECLARATION( idTarget, idTarget_GiveEmail )
  572. EVENT( EV_Activate, idTarget_GiveEmail::Event_Activate )
  573. END_CLASS
  574. /*
  575. ================
  576. idTarget_GiveEmail::Event_Activate
  577. ================
  578. */
  579. void idTarget_GiveEmail::Event_Activate( idEntity *activator ) {
  580. idPlayer *player = gameLocal.GetLocalPlayer();
  581. const idDeclPDA *pda = player->GetPDA();
  582. if ( pda ) {
  583. player->GiveEmail( static_cast<const idDeclEmail *>( declManager->FindType( DECL_EMAIL, spawnArgs.GetString( "email" ), false ) ) );
  584. } else {
  585. player->ShowTip( spawnArgs.GetString( "text_infoTitle" ), spawnArgs.GetString( "text_PDANeeded" ), true );
  586. }
  587. }
  588. /*
  589. ===============================================================================
  590. idTarget_SetModel
  591. ===============================================================================
  592. */
  593. CLASS_DECLARATION( idTarget, idTarget_SetModel )
  594. EVENT( EV_Activate, idTarget_SetModel::Event_Activate )
  595. END_CLASS
  596. /*
  597. ================
  598. idTarget_SetModel::Spawn
  599. ================
  600. */
  601. void idTarget_SetModel::Spawn() {
  602. const char *model;
  603. model = spawnArgs.GetString( "newmodel" );
  604. if ( declManager->FindType( DECL_MODELDEF, model, false ) == NULL ) {
  605. // precache the render model
  606. renderModelManager->FindModel( model );
  607. // precache .cm files only
  608. collisionModelManager->LoadModel( model );
  609. }
  610. }
  611. /*
  612. ================
  613. idTarget_SetModel::Event_Activate
  614. ================
  615. */
  616. void idTarget_SetModel::Event_Activate( idEntity *activator ) {
  617. for( int i = 0; i < targets.Num(); i++ ) {
  618. idEntity *ent = targets[ i ].GetEntity();
  619. if ( ent ) {
  620. ent->SetModel( spawnArgs.GetString( "newmodel" ) );
  621. }
  622. }
  623. }
  624. /*
  625. ===============================================================================
  626. idTarget_SetInfluence
  627. ===============================================================================
  628. */
  629. const idEventDef EV_RestoreInfluence( "<RestoreInfluece>" );
  630. const idEventDef EV_GatherEntities( "<GatherEntities>" );
  631. const idEventDef EV_Flash( "<Flash>", "fd" );
  632. const idEventDef EV_ClearFlash( "<ClearFlash>", "f" );
  633. CLASS_DECLARATION( idTarget, idTarget_SetInfluence )
  634. EVENT( EV_Activate, idTarget_SetInfluence::Event_Activate )
  635. EVENT( EV_RestoreInfluence, idTarget_SetInfluence::Event_RestoreInfluence )
  636. EVENT( EV_GatherEntities, idTarget_SetInfluence::Event_GatherEntities )
  637. EVENT( EV_Flash, idTarget_SetInfluence::Event_Flash )
  638. EVENT( EV_ClearFlash, idTarget_SetInfluence::Event_ClearFlash )
  639. END_CLASS
  640. /*
  641. ================
  642. idTarget_SetInfluence::idTarget_SetInfluence
  643. ================
  644. */
  645. idTarget_SetInfluence::idTarget_SetInfluence() {
  646. flashIn = 0.0f;
  647. flashOut = 0.0f;
  648. delay = 0.0f;
  649. switchToCamera = NULL;
  650. soundFaded = false;
  651. restoreOnTrigger = false;
  652. }
  653. /*
  654. ================
  655. idTarget_SetInfluence::Save
  656. ================
  657. */
  658. void idTarget_SetInfluence::Save( idSaveGame *savefile ) const {
  659. int i;
  660. savefile->WriteInt( lightList.Num() );
  661. for( i = 0; i < lightList.Num(); i++ ) {
  662. savefile->WriteInt( lightList[ i ] );
  663. }
  664. savefile->WriteInt( guiList.Num() );
  665. for( i = 0; i < guiList.Num(); i++ ) {
  666. savefile->WriteInt( guiList[ i ] );
  667. }
  668. savefile->WriteInt( soundList.Num() );
  669. for( i = 0; i < soundList.Num(); i++ ) {
  670. savefile->WriteInt( soundList[ i ] );
  671. }
  672. savefile->WriteInt( genericList.Num() );
  673. for( i = 0; i < genericList.Num(); i++ ) {
  674. savefile->WriteInt( genericList[ i ] );
  675. }
  676. savefile->WriteFloat( flashIn );
  677. savefile->WriteFloat( flashOut );
  678. savefile->WriteFloat( delay );
  679. savefile->WriteString( flashInSound );
  680. savefile->WriteString( flashOutSound );
  681. savefile->WriteObject( switchToCamera );
  682. savefile->WriteFloat( fovSetting.GetStartTime() );
  683. savefile->WriteFloat( fovSetting.GetDuration() );
  684. savefile->WriteFloat( fovSetting.GetStartValue() );
  685. savefile->WriteFloat( fovSetting.GetEndValue() );
  686. savefile->WriteBool( soundFaded );
  687. savefile->WriteBool( restoreOnTrigger );
  688. savefile->WriteInt( savedGuiList.Num() );
  689. for( i = 0; i < savedGuiList.Num(); i++ ) {
  690. for(int j = 0; j < MAX_RENDERENTITY_GUI; j++) {
  691. savefile->WriteUserInterface(savedGuiList[i].gui[j], savedGuiList[i].gui[j] ? savedGuiList[i].gui[j]->IsUniqued() : false);
  692. }
  693. }
  694. }
  695. /*
  696. ================
  697. idTarget_SetInfluence::Restore
  698. ================
  699. */
  700. void idTarget_SetInfluence::Restore( idRestoreGame *savefile ) {
  701. int i, num;
  702. int itemNum;
  703. float set;
  704. savefile->ReadInt( num );
  705. for( i = 0; i < num; i++ ) {
  706. savefile->ReadInt( itemNum );
  707. lightList.Append( itemNum );
  708. }
  709. savefile->ReadInt( num );
  710. for( i = 0; i < num; i++ ) {
  711. savefile->ReadInt( itemNum );
  712. guiList.Append( itemNum );
  713. }
  714. savefile->ReadInt( num );
  715. for( i = 0; i < num; i++ ) {
  716. savefile->ReadInt( itemNum );
  717. soundList.Append( itemNum );
  718. }
  719. savefile->ReadInt( num );
  720. for ( i = 0; i < num; i++ ) {
  721. savefile->ReadInt( itemNum );
  722. genericList.Append( itemNum );
  723. }
  724. savefile->ReadFloat( flashIn );
  725. savefile->ReadFloat( flashOut );
  726. savefile->ReadFloat( delay );
  727. savefile->ReadString( flashInSound );
  728. savefile->ReadString( flashOutSound );
  729. savefile->ReadObject( reinterpret_cast<idClass *&>( switchToCamera ) );
  730. savefile->ReadFloat( set );
  731. fovSetting.SetStartTime( set );
  732. savefile->ReadFloat( set );
  733. fovSetting.SetDuration( set );
  734. savefile->ReadFloat( set );
  735. fovSetting.SetStartValue( set );
  736. savefile->ReadFloat( set );
  737. fovSetting.SetEndValue( set );
  738. savefile->ReadBool( soundFaded );
  739. savefile->ReadBool( restoreOnTrigger );
  740. savefile->ReadInt( num );
  741. for( i = 0; i < num; i++ ) {
  742. SavedGui_t temp;
  743. for(int j = 0; j < MAX_RENDERENTITY_GUI; j++) {
  744. savefile->ReadUserInterface(temp.gui[j]);
  745. }
  746. savedGuiList.Append( temp );
  747. }
  748. }
  749. /*
  750. ================
  751. idTarget_SetInfluence::Spawn
  752. ================
  753. */
  754. void idTarget_SetInfluence::Spawn() {
  755. PostEventMS( &EV_GatherEntities, 0 );
  756. flashIn = spawnArgs.GetFloat( "flashIn", "0" );
  757. flashOut = spawnArgs.GetFloat( "flashOut", "0" );
  758. flashInSound = spawnArgs.GetString( "snd_flashin" );
  759. flashOutSound = spawnArgs.GetString( "snd_flashout" );
  760. delay = spawnArgs.GetFloat( "delay" );
  761. soundFaded = false;
  762. restoreOnTrigger = false;
  763. // always allow during cinematics
  764. cinematic = true;
  765. }
  766. /*
  767. ================
  768. idTarget_SetInfluence::Event_Flash
  769. ================
  770. */
  771. void idTarget_SetInfluence::Event_Flash( float flash, int out ) {
  772. idPlayer *player = gameLocal.GetLocalPlayer();
  773. player->playerView.Fade( idVec4( 1, 1, 1, 1 ), flash );
  774. const idSoundShader *shader = NULL;
  775. if ( !out && flashInSound.Length() ){
  776. shader = declManager->FindSound( flashInSound );
  777. player->StartSoundShader( shader, SND_CHANNEL_VOICE, 0, false, NULL );
  778. } else if ( out && ( flashOutSound.Length() || flashInSound.Length() ) ) {
  779. shader = declManager->FindSound( flashOutSound.Length() ? flashOutSound : flashInSound );
  780. player->StartSoundShader( shader, SND_CHANNEL_VOICE, 0, false, NULL );
  781. }
  782. PostEventSec( &EV_ClearFlash, flash, flash );
  783. }
  784. /*
  785. ================
  786. idTarget_SetInfluence::Event_ClearFlash
  787. ================
  788. */
  789. void idTarget_SetInfluence::Event_ClearFlash( float flash ) {
  790. idPlayer *player = gameLocal.GetLocalPlayer();
  791. player->playerView.Fade( vec4_zero , flash );
  792. }
  793. /*
  794. ================
  795. idTarget_SetInfluence::Event_GatherEntities
  796. ================
  797. */
  798. void idTarget_SetInfluence::Event_GatherEntities() {
  799. int i, listedEntities;
  800. idEntity *entityList[ MAX_GENTITIES ];
  801. //bool demonicOnly = spawnArgs.GetBool( "effect_demonic" );
  802. bool lights = spawnArgs.GetBool( "effect_lights" );
  803. bool sounds = spawnArgs.GetBool( "effect_sounds" );
  804. bool guis = spawnArgs.GetBool( "effect_guis" );
  805. bool models = spawnArgs.GetBool( "effect_models" );
  806. bool vision = spawnArgs.GetBool( "effect_vision" );
  807. bool targetsOnly = spawnArgs.GetBool( "targetsOnly" );
  808. lightList.Clear();
  809. guiList.Clear();
  810. soundList.Clear();
  811. savedGuiList.Clear();
  812. if ( spawnArgs.GetBool( "effect_all" ) ) {
  813. lights = sounds = guis = models = vision = true;
  814. }
  815. if ( targetsOnly ) {
  816. listedEntities = targets.Num();
  817. for ( i = 0; i < listedEntities; i++ ) {
  818. entityList[i] = targets[i].GetEntity();
  819. }
  820. } else {
  821. float radius = spawnArgs.GetFloat( "radius" );
  822. listedEntities = gameLocal.EntitiesWithinRadius( GetPhysics()->GetOrigin(), radius, entityList, MAX_GENTITIES );
  823. }
  824. for( i = 0; i < listedEntities; i++ ) {
  825. idEntity *ent = entityList[ i ];
  826. if ( ent ) {
  827. if ( lights && ent->IsType( idLight::Type ) && ent->spawnArgs.FindKey( "color_demonic" ) ) {
  828. lightList.Append( ent->entityNumber );
  829. continue;
  830. }
  831. if ( sounds && ent->IsType( idSound::Type ) && ent->spawnArgs.FindKey( "snd_demonic" ) ) {
  832. soundList.Append( ent->entityNumber );
  833. continue;
  834. }
  835. if ( guis && ent->GetRenderEntity() && ent->GetRenderEntity()->gui[ 0 ] && ent->spawnArgs.FindKey( "gui_demonic" ) ) {
  836. guiList.Append( ent->entityNumber );
  837. SavedGui_t temp;
  838. savedGuiList.Append(temp);
  839. continue;
  840. }
  841. if ( ent->IsType( idStaticEntity::Type ) && ent->spawnArgs.FindKey( "color_demonic" ) ) {
  842. genericList.Append( ent->entityNumber );
  843. continue;
  844. }
  845. }
  846. }
  847. idStr temp;
  848. temp = spawnArgs.GetString( "switchToView" );
  849. switchToCamera = ( temp.Length() ) ? gameLocal.FindEntity( temp ) : NULL;
  850. }
  851. /*
  852. ================
  853. idTarget_SetInfluence::Event_Activate
  854. ================
  855. */
  856. void idTarget_SetInfluence::Event_Activate( idEntity *activator ) {
  857. int i, j;
  858. idEntity *ent;
  859. idLight *light;
  860. idSound *sound;
  861. idStaticEntity *generic;
  862. const char *parm;
  863. const char *skin;
  864. bool update;
  865. idVec3 color;
  866. idVec4 colorTo;
  867. idPlayer *player;
  868. player = gameLocal.GetLocalPlayer();
  869. if ( spawnArgs.GetBool( "triggerActivate" ) ) {
  870. if ( restoreOnTrigger ) {
  871. ProcessEvent( &EV_RestoreInfluence );
  872. restoreOnTrigger = false;
  873. return;
  874. }
  875. restoreOnTrigger = true;
  876. }
  877. float fadeTime = spawnArgs.GetFloat( "fadeWorldSounds" );
  878. if ( delay > 0.0f ) {
  879. PostEventSec( &EV_Activate, delay, activator );
  880. delay = 0.0f;
  881. // start any sound fading now
  882. if ( fadeTime ) {
  883. gameSoundWorld->FadeSoundClasses( 0, -40.0f, fadeTime );
  884. soundFaded = true;
  885. }
  886. return;
  887. } else if ( fadeTime && !soundFaded ) {
  888. gameSoundWorld->FadeSoundClasses( 0, -40.0f, fadeTime );
  889. soundFaded = true;
  890. }
  891. if ( spawnArgs.GetBool( "triggerTargets" ) ) {
  892. ActivateTargets( activator );
  893. }
  894. if ( flashIn ) {
  895. PostEventSec( &EV_Flash, 0.0f, flashIn, 0 );
  896. }
  897. parm = spawnArgs.GetString( "snd_influence" );
  898. if ( parm != NULL && *parm != NULL ) {
  899. PostEventSec( &EV_StartSoundShader, flashIn, parm, SND_CHANNEL_ANY );
  900. }
  901. if ( switchToCamera ) {
  902. switchToCamera->PostEventSec( &EV_Activate, flashIn + 0.05f, this );
  903. }
  904. int fov = spawnArgs.GetInt( "fov" );
  905. if ( fov ) {
  906. fovSetting.Init( gameLocal.time, SEC2MS( spawnArgs.GetFloat( "fovTime" ) ), player->DefaultFov(), fov );
  907. BecomeActive( TH_THINK );
  908. }
  909. for ( i = 0; i < genericList.Num(); i++ ) {
  910. ent = gameLocal.entities[genericList[i]];
  911. if ( ent == NULL ) {
  912. continue;
  913. }
  914. generic = static_cast<idStaticEntity*>( ent );
  915. color = generic->spawnArgs.GetVector( "color_demonic" );
  916. colorTo.Set( color.x, color.y, color.z, 1.0f );
  917. generic->Fade( colorTo, spawnArgs.GetFloat( "fade_time", "0.25" ) );
  918. }
  919. for ( i = 0; i < lightList.Num(); i++ ) {
  920. ent = gameLocal.entities[lightList[i]];
  921. if ( ent == NULL || !ent->IsType( idLight::Type ) ) {
  922. continue;
  923. }
  924. light = static_cast<idLight *>(ent);
  925. parm = light->spawnArgs.GetString( "mat_demonic" );
  926. if ( parm && *parm ) {
  927. light->SetShader( parm );
  928. }
  929. color = light->spawnArgs.GetVector( "_color" );
  930. color = light->spawnArgs.GetVector( "color_demonic", color.ToString() );
  931. colorTo.Set( color.x, color.y, color.z, 1.0f );
  932. light->Fade( colorTo, spawnArgs.GetFloat( "fade_time", "0.25" ) );
  933. }
  934. for ( i = 0; i < soundList.Num(); i++ ) {
  935. ent = gameLocal.entities[soundList[i]];
  936. if ( ent == NULL || !ent->IsType( idSound::Type ) ) {
  937. continue;
  938. }
  939. sound = static_cast<idSound *>(ent);
  940. parm = sound->spawnArgs.GetString( "snd_demonic" );
  941. if ( parm && *parm ) {
  942. if ( sound->spawnArgs.GetBool( "overlayDemonic" ) ) {
  943. sound->StartSound( "snd_demonic", SND_CHANNEL_DEMONIC, 0, false, NULL );
  944. } else {
  945. sound->StopSound( SND_CHANNEL_ANY, false );
  946. sound->SetSound( parm );
  947. }
  948. }
  949. }
  950. for ( i = 0; i < guiList.Num(); i++ ) {
  951. ent = gameLocal.entities[guiList[i]];
  952. if ( ent == NULL || ent->GetRenderEntity() == NULL ) {
  953. continue;
  954. }
  955. update = false;
  956. for ( j = 0; j < MAX_RENDERENTITY_GUI; j++ ) {
  957. if ( ent->GetRenderEntity()->gui[ j ] && ent->spawnArgs.FindKey( j == 0 ? "gui_demonic" : va( "gui_demonic%d", j+1 ) ) ) {
  958. //Backup the old one
  959. savedGuiList[i].gui[j] = ent->GetRenderEntity()->gui[ j ];
  960. ent->GetRenderEntity()->gui[ j ] = uiManager->FindGui( ent->spawnArgs.GetString( j == 0 ? "gui_demonic" : va( "gui_demonic%d", j+1 ) ), true );
  961. update = true;
  962. }
  963. }
  964. if ( update ) {
  965. ent->UpdateVisuals();
  966. ent->Present();
  967. }
  968. }
  969. player->SetInfluenceLevel( spawnArgs.GetInt( "influenceLevel" ) );
  970. int snapAngle = spawnArgs.GetInt( "snapAngle" );
  971. if ( snapAngle ) {
  972. idAngles ang( 0, snapAngle, 0 );
  973. player->SetViewAngles( ang );
  974. player->SetAngles( ang );
  975. }
  976. if ( spawnArgs.GetBool( "effect_vision" ) ) {
  977. parm = spawnArgs.GetString( "mtrVision" );
  978. skin = spawnArgs.GetString( "skinVision" );
  979. player->SetInfluenceView( parm, skin, spawnArgs.GetInt( "visionRadius" ), this );
  980. }
  981. parm = spawnArgs.GetString( "mtrWorld" );
  982. if ( parm != NULL && *parm != NULL ) {
  983. gameLocal.SetGlobalMaterial( declManager->FindMaterial( parm ) );
  984. }
  985. if ( !restoreOnTrigger ) {
  986. PostEventMS( &EV_RestoreInfluence, SEC2MS( spawnArgs.GetFloat( "time" ) ) );
  987. }
  988. }
  989. /*
  990. ================
  991. idTarget_SetInfluence::Think
  992. ================
  993. */
  994. void idTarget_SetInfluence::Think() {
  995. if ( thinkFlags & TH_THINK ) {
  996. idPlayer *player = gameLocal.GetLocalPlayer();
  997. player->SetInfluenceFov( fovSetting.GetCurrentValue( gameLocal.time ) );
  998. if ( fovSetting.IsDone( gameLocal.time ) ) {
  999. if ( !spawnArgs.GetBool( "leaveFOV" ) ) {
  1000. player->SetInfluenceFov( 0 );
  1001. }
  1002. BecomeInactive( TH_THINK );
  1003. }
  1004. } else {
  1005. BecomeInactive( TH_ALL );
  1006. }
  1007. }
  1008. /*
  1009. ================
  1010. idTarget_SetInfluence::Event_RestoreInfluence
  1011. ================
  1012. */
  1013. void idTarget_SetInfluence::Event_RestoreInfluence() {
  1014. int i, j;
  1015. idEntity *ent;
  1016. idLight *light;
  1017. idSound *sound;
  1018. idStaticEntity *generic;
  1019. bool update;
  1020. idVec3 color;
  1021. idVec4 colorTo;
  1022. if ( flashOut ) {
  1023. PostEventSec( &EV_Flash, 0.0f, flashOut, 1 );
  1024. }
  1025. if ( switchToCamera ) {
  1026. switchToCamera->PostEventMS( &EV_Activate, 0.0f, this );
  1027. }
  1028. for ( i = 0; i < genericList.Num(); i++ ) {
  1029. ent = gameLocal.entities[genericList[i]];
  1030. if ( ent == NULL ) {
  1031. continue;
  1032. }
  1033. generic = static_cast<idStaticEntity*>( ent );
  1034. color = generic->spawnArgs.GetVector( "_color", "1 1 1" );
  1035. colorTo.Set( color.x, color.y, color.z, 1.0f );
  1036. generic->Fade( colorTo, spawnArgs.GetFloat( "fade_time", "0.25" ) );
  1037. }
  1038. for ( i = 0; i < lightList.Num(); i++ ) {
  1039. ent = gameLocal.entities[lightList[i]];
  1040. if ( ent == NULL || !ent->IsType( idLight::Type ) ) {
  1041. continue;
  1042. }
  1043. light = static_cast<idLight *>(ent);
  1044. if ( !light->spawnArgs.GetBool( "leave_demonic_mat" ) ) {
  1045. const char *texture = light->spawnArgs.GetString( "texture", "lights/squarelight1" );
  1046. light->SetShader( texture );
  1047. }
  1048. color = light->spawnArgs.GetVector( "_color" );
  1049. colorTo.Set( color.x, color.y, color.z, 1.0f );
  1050. light->Fade( colorTo, spawnArgs.GetFloat( "fade_time", "0.25" ) );
  1051. }
  1052. for ( i = 0; i < soundList.Num(); i++ ) {
  1053. ent = gameLocal.entities[soundList[i]];
  1054. if ( ent == NULL || !ent->IsType( idSound::Type ) ) {
  1055. continue;
  1056. }
  1057. sound = static_cast<idSound *>(ent);
  1058. sound->StopSound( SND_CHANNEL_ANY, false );
  1059. sound->SetSound( sound->spawnArgs.GetString( "s_shader" ) );
  1060. }
  1061. for ( i = 0; i < guiList.Num(); i++ ) {
  1062. ent = gameLocal.entities[guiList[i]];
  1063. if ( ent == NULL || GetRenderEntity() == NULL ) {
  1064. continue;
  1065. }
  1066. update = false;
  1067. for( j = 0; j < MAX_RENDERENTITY_GUI; j++ ) {
  1068. if ( ent->GetRenderEntity()->gui[ j ] ) {
  1069. ent->GetRenderEntity()->gui[ j ] = savedGuiList[i].gui[j];
  1070. update = true;
  1071. }
  1072. }
  1073. if ( update ) {
  1074. ent->UpdateVisuals();
  1075. ent->Present();
  1076. }
  1077. }
  1078. idPlayer *player = gameLocal.GetLocalPlayer();
  1079. player->SetInfluenceLevel( 0 );
  1080. player->SetInfluenceView( NULL, NULL, 0.0f, NULL );
  1081. player->SetInfluenceFov( 0 );
  1082. gameLocal.SetGlobalMaterial( NULL );
  1083. float fadeTime = spawnArgs.GetFloat( "fadeWorldSounds" );
  1084. if ( fadeTime ) {
  1085. gameSoundWorld->FadeSoundClasses( 0, 0.0f, fadeTime / 2.0f );
  1086. }
  1087. }
  1088. /*
  1089. ===============================================================================
  1090. idTarget_SetKeyVal
  1091. ===============================================================================
  1092. */
  1093. CLASS_DECLARATION( idTarget, idTarget_SetKeyVal )
  1094. EVENT( EV_Activate, idTarget_SetKeyVal::Event_Activate )
  1095. END_CLASS
  1096. /*
  1097. ================
  1098. idTarget_SetKeyVal::Event_Activate
  1099. ================
  1100. */
  1101. void idTarget_SetKeyVal::Event_Activate( idEntity *activator ) {
  1102. int i;
  1103. idStr key, val;
  1104. idEntity *ent;
  1105. const idKeyValue *kv;
  1106. int n;
  1107. for( i = 0; i < targets.Num(); i++ ) {
  1108. ent = targets[ i ].GetEntity();
  1109. if ( ent ) {
  1110. kv = spawnArgs.MatchPrefix("keyval");
  1111. while ( kv ) {
  1112. n = kv->GetValue().Find( ";" );
  1113. if ( n > 0 ) {
  1114. key = kv->GetValue().Left( n );
  1115. val = kv->GetValue().Right( kv->GetValue().Length() - n - 1 );
  1116. ent->spawnArgs.Set( key, val );
  1117. for ( int j = 0; j < MAX_RENDERENTITY_GUI; j++ ) {
  1118. if ( ent->GetRenderEntity()->gui[ j ] ) {
  1119. if ( idStr::Icmpn( key, "gui_", 4 ) == 0 ) {
  1120. ent->GetRenderEntity()->gui[ j ]->SetStateString( key, val );
  1121. ent->GetRenderEntity()->gui[ j ]->StateChanged( gameLocal.time );
  1122. }
  1123. }
  1124. }
  1125. }
  1126. kv = spawnArgs.MatchPrefix( "keyval", kv );
  1127. }
  1128. ent->UpdateChangeableSpawnArgs( NULL );
  1129. ent->UpdateVisuals();
  1130. ent->Present();
  1131. }
  1132. }
  1133. }
  1134. /*
  1135. ===============================================================================
  1136. idTarget_SetFov
  1137. ===============================================================================
  1138. */
  1139. CLASS_DECLARATION( idTarget, idTarget_SetFov )
  1140. EVENT( EV_Activate, idTarget_SetFov::Event_Activate )
  1141. END_CLASS
  1142. /*
  1143. ================
  1144. idTarget_SetFov::Save
  1145. ================
  1146. */
  1147. void idTarget_SetFov::Save( idSaveGame *savefile ) const {
  1148. savefile->WriteFloat( fovSetting.GetStartTime() );
  1149. savefile->WriteFloat( fovSetting.GetDuration() );
  1150. savefile->WriteFloat( fovSetting.GetStartValue() );
  1151. savefile->WriteFloat( fovSetting.GetEndValue() );
  1152. }
  1153. /*
  1154. ================
  1155. idTarget_SetFov::Restore
  1156. ================
  1157. */
  1158. void idTarget_SetFov::Restore( idRestoreGame *savefile ) {
  1159. float setting;
  1160. savefile->ReadFloat( setting );
  1161. fovSetting.SetStartTime( setting );
  1162. savefile->ReadFloat( setting );
  1163. fovSetting.SetDuration( setting );
  1164. savefile->ReadFloat( setting );
  1165. fovSetting.SetStartValue( setting );
  1166. savefile->ReadFloat( setting );
  1167. fovSetting.SetEndValue( setting );
  1168. fovSetting.GetCurrentValue( gameLocal.time );
  1169. }
  1170. /*
  1171. ================
  1172. idTarget_SetFov::Event_Activate
  1173. ================
  1174. */
  1175. void idTarget_SetFov::Event_Activate( idEntity *activator ) {
  1176. // always allow during cinematics
  1177. cinematic = true;
  1178. idPlayer *player = gameLocal.GetLocalPlayer();
  1179. fovSetting.Init( gameLocal.time, SEC2MS( spawnArgs.GetFloat( "time" ) ), player ? player->DefaultFov() : g_fov.GetFloat(), spawnArgs.GetFloat( "fov" ) );
  1180. BecomeActive( TH_THINK );
  1181. }
  1182. /*
  1183. ================
  1184. idTarget_SetFov::Think
  1185. ================
  1186. */
  1187. void idTarget_SetFov::Think() {
  1188. if ( thinkFlags & TH_THINK ) {
  1189. idPlayer *player = gameLocal.GetLocalPlayer();
  1190. player->SetInfluenceFov( fovSetting.GetCurrentValue( gameLocal.time ) );
  1191. if ( fovSetting.IsDone( gameLocal.time ) ) {
  1192. player->SetInfluenceFov( 0.0f );
  1193. BecomeInactive( TH_THINK );
  1194. }
  1195. } else {
  1196. BecomeInactive( TH_ALL );
  1197. }
  1198. }
  1199. /*
  1200. ===============================================================================
  1201. idTarget_SetPrimaryObjective
  1202. ===============================================================================
  1203. */
  1204. CLASS_DECLARATION( idTarget, idTarget_SetPrimaryObjective )
  1205. EVENT( EV_Activate, idTarget_SetPrimaryObjective::Event_Activate )
  1206. END_CLASS
  1207. /*
  1208. ================
  1209. idTarget_SetPrimaryObjective::Event_Activate
  1210. ================
  1211. */
  1212. void idTarget_SetPrimaryObjective::Event_Activate( idEntity *activator ) {
  1213. idPlayer *player = gameLocal.GetLocalPlayer();
  1214. if ( player != NULL ) {
  1215. player->SetPrimaryObjective( this );
  1216. }
  1217. }
  1218. /*
  1219. ===============================================================================
  1220. idTarget_LockDoor
  1221. ===============================================================================
  1222. */
  1223. CLASS_DECLARATION( idTarget, idTarget_LockDoor )
  1224. EVENT( EV_Activate, idTarget_LockDoor::Event_Activate )
  1225. END_CLASS
  1226. /*
  1227. ================
  1228. idTarget_LockDoor::Event_Activate
  1229. ================
  1230. */
  1231. void idTarget_LockDoor::Event_Activate( idEntity *activator ) {
  1232. int i;
  1233. idEntity *ent;
  1234. int lock;
  1235. lock = spawnArgs.GetInt( "locked", "1" );
  1236. for( i = 0; i < targets.Num(); i++ ) {
  1237. ent = targets[ i ].GetEntity();
  1238. if ( ent != NULL && ent->IsType( idDoor::Type ) ) {
  1239. if ( static_cast<idDoor *>( ent )->IsLocked() ) {
  1240. static_cast<idDoor *>( ent )->Lock( 0 );
  1241. } else {
  1242. static_cast<idDoor *>( ent )->Lock( lock );
  1243. }
  1244. }
  1245. }
  1246. }
  1247. /*
  1248. ===============================================================================
  1249. idTarget_CallObjectFunction
  1250. ===============================================================================
  1251. */
  1252. CLASS_DECLARATION( idTarget, idTarget_CallObjectFunction )
  1253. EVENT( EV_Activate, idTarget_CallObjectFunction::Event_Activate )
  1254. END_CLASS
  1255. /*
  1256. ================
  1257. idTarget_CallObjectFunction::Event_Activate
  1258. ================
  1259. */
  1260. void idTarget_CallObjectFunction::Event_Activate( idEntity *activator ) {
  1261. int i;
  1262. idEntity *ent;
  1263. const function_t *func;
  1264. const char *funcName;
  1265. idThread *thread;
  1266. funcName = spawnArgs.GetString( "call" );
  1267. for( i = 0; i < targets.Num(); i++ ) {
  1268. ent = targets[ i ].GetEntity();
  1269. if ( ent != NULL && ent->scriptObject.HasObject() ) {
  1270. func = ent->scriptObject.GetFunction( funcName );
  1271. if ( func == NULL ) {
  1272. gameLocal.Error( "Function '%s' not found on entity '%s' for function call from '%s'", funcName, ent->name.c_str(), name.c_str() );
  1273. return;
  1274. }
  1275. if ( func->type->NumParameters() != 1 ) {
  1276. gameLocal.Error( "Function '%s' on entity '%s' has the wrong number of parameters for function call from '%s'", funcName, ent->name.c_str(), name.c_str() );
  1277. }
  1278. if ( !ent->scriptObject.GetTypeDef()->Inherits( func->type->GetParmType( 0 ) ) ) {
  1279. gameLocal.Error( "Function '%s' on entity '%s' is the wrong type for function call from '%s'", funcName, ent->name.c_str(), name.c_str() );
  1280. }
  1281. // create a thread and call the function
  1282. thread = new idThread();
  1283. thread->CallFunction( ent, func, true );
  1284. thread->Start();
  1285. }
  1286. }
  1287. }
  1288. /*
  1289. ===============================================================================
  1290. idTarget_EnableLevelWeapons
  1291. ===============================================================================
  1292. */
  1293. CLASS_DECLARATION( idTarget, idTarget_EnableLevelWeapons )
  1294. EVENT( EV_Activate, idTarget_EnableLevelWeapons::Event_Activate )
  1295. END_CLASS
  1296. /*
  1297. ================
  1298. idTarget_EnableLevelWeapons::Event_Activate
  1299. ================
  1300. */
  1301. void idTarget_EnableLevelWeapons::Event_Activate( idEntity *activator ) {
  1302. int i;
  1303. const char *weap;
  1304. gameLocal.world->spawnArgs.SetBool( "no_Weapons", spawnArgs.GetBool( "disable" ) );
  1305. if ( spawnArgs.GetBool( "disable" ) ) {
  1306. for( i = 0; i < gameLocal.numClients; i++ ) {
  1307. if ( gameLocal.entities[ i ] ) {
  1308. gameLocal.entities[ i ]->ProcessEvent( &EV_Player_DisableWeapon );
  1309. }
  1310. }
  1311. } else {
  1312. weap = spawnArgs.GetString( "weapon" );
  1313. for( i = 0; i < gameLocal.numClients; i++ ) {
  1314. if ( gameLocal.entities[ i ] ) {
  1315. gameLocal.entities[ i ]->ProcessEvent( &EV_Player_EnableWeapon );
  1316. if ( weap != NULL && weap[ 0 ] != NULL ) {
  1317. gameLocal.entities[ i ]->PostEventSec( &EV_Player_SelectWeapon, 0.5f, weap );
  1318. }
  1319. }
  1320. }
  1321. }
  1322. }
  1323. /*
  1324. ===============================================================================
  1325. idTarget_Tip
  1326. ===============================================================================
  1327. */
  1328. const idEventDef EV_TipOff( "<TipOff>" );
  1329. extern const idEventDef EV_GetPlayerPos( "<getplayerpos>" );
  1330. CLASS_DECLARATION( idTarget, idTarget_Tip )
  1331. EVENT( EV_Activate, idTarget_Tip::Event_Activate )
  1332. EVENT( EV_TipOff, idTarget_Tip::Event_TipOff )
  1333. EVENT( EV_GetPlayerPos, idTarget_Tip::Event_GetPlayerPos )
  1334. END_CLASS
  1335. /*
  1336. ================
  1337. idTarget_Tip::idTarget_Tip
  1338. ================
  1339. */
  1340. idTarget_Tip::idTarget_Tip() {
  1341. playerPos.Zero();
  1342. }
  1343. /*
  1344. ================
  1345. idTarget_Tip::Spawn
  1346. ================
  1347. */
  1348. void idTarget_Tip::Spawn() {
  1349. }
  1350. /*
  1351. ================
  1352. idTarget_Tip::Save
  1353. ================
  1354. */
  1355. void idTarget_Tip::Save( idSaveGame *savefile ) const {
  1356. savefile->WriteVec3( playerPos );
  1357. }
  1358. /*
  1359. ================
  1360. idTarget_Tip::Restore
  1361. ================
  1362. */
  1363. void idTarget_Tip::Restore( idRestoreGame *savefile ) {
  1364. savefile->ReadVec3( playerPos );
  1365. }
  1366. /*
  1367. ================
  1368. idTarget_Tip::Event_Activate
  1369. ================
  1370. */
  1371. void idTarget_Tip::Event_GetPlayerPos() {
  1372. idPlayer *player = gameLocal.GetLocalPlayer();
  1373. if ( player ) {
  1374. playerPos = player->GetPhysics()->GetOrigin();
  1375. PostEventMS( &EV_TipOff, 100 );
  1376. }
  1377. }
  1378. /*
  1379. ================
  1380. idTarget_Tip::Event_Activate
  1381. ================
  1382. */
  1383. void idTarget_Tip::Event_Activate( idEntity *activator ) {
  1384. idPlayer *player = gameLocal.GetLocalPlayer();
  1385. if ( player ) {
  1386. if ( player->IsTipVisible() ) {
  1387. PostEventSec( &EV_Activate, 5.1f, activator );
  1388. return;
  1389. }
  1390. player->ShowTip( spawnArgs.GetString( "text_title" ), spawnArgs.GetString( "text_tip" ), false );
  1391. PostEventMS( &EV_GetPlayerPos, 2000 );
  1392. }
  1393. }
  1394. /*
  1395. ================
  1396. idTarget_Tip::Event_TipOff
  1397. ================
  1398. */
  1399. void idTarget_Tip::Event_TipOff() {
  1400. idPlayer *player = gameLocal.GetLocalPlayer();
  1401. if ( player ) {
  1402. idVec3 v = player->GetPhysics()->GetOrigin() - playerPos;
  1403. if ( v.Length() > 96.0f ) {
  1404. player->HideTip();
  1405. } else {
  1406. PostEventMS( &EV_TipOff, 100 );
  1407. }
  1408. }
  1409. }
  1410. /*
  1411. ===============================================================================
  1412. idTarget_GiveSecurity
  1413. ===============================================================================
  1414. */
  1415. CLASS_DECLARATION( idTarget, idTarget_GiveSecurity )
  1416. EVENT( EV_Activate, idTarget_GiveSecurity::Event_Activate )
  1417. END_CLASS
  1418. /*
  1419. ================
  1420. idTarget_GiveEmail::Event_Activate
  1421. ================
  1422. */
  1423. void idTarget_GiveSecurity::Event_Activate( idEntity *activator ) {
  1424. idPlayer *player = gameLocal.GetLocalPlayer();
  1425. if ( player ) {
  1426. player->GiveSecurity( spawnArgs.GetString( "text_security" ) );
  1427. }
  1428. }
  1429. /*
  1430. ===============================================================================
  1431. idTarget_RemoveWeapons
  1432. ===============================================================================
  1433. */
  1434. CLASS_DECLARATION( idTarget, idTarget_RemoveWeapons )
  1435. EVENT( EV_Activate, idTarget_RemoveWeapons::Event_Activate )
  1436. END_CLASS
  1437. /*
  1438. ================
  1439. idTarget_RemoveWeapons::Event_Activate
  1440. ================
  1441. */
  1442. void idTarget_RemoveWeapons::Event_Activate( idEntity *activator ) {
  1443. for( int i = 0; i < gameLocal.numClients; i++ ) {
  1444. if ( gameLocal.entities[ i ] ) {
  1445. idPlayer *player = static_cast< idPlayer* >( gameLocal.entities[i] );
  1446. // Everywhere that we use target_removeweapons the intent is to remove ALL of the
  1447. // weapons that hte player has (save a few: flashlights, fists, soul cube).
  1448. player->RemoveAllButEssentialWeapons();
  1449. player->SelectWeapon( player->weapon_fists, true );
  1450. }
  1451. }
  1452. }
  1453. /*
  1454. ===============================================================================
  1455. idTarget_LevelTrigger
  1456. ===============================================================================
  1457. */
  1458. CLASS_DECLARATION( idTarget, idTarget_LevelTrigger )
  1459. EVENT( EV_Activate, idTarget_LevelTrigger::Event_Activate )
  1460. END_CLASS
  1461. /*
  1462. ================
  1463. idTarget_LevelTrigger::Event_Activate
  1464. ================
  1465. */
  1466. void idTarget_LevelTrigger::Event_Activate( idEntity *activator ) {
  1467. for( int i = 0; i < gameLocal.numClients; i++ ) {
  1468. if ( gameLocal.entities[ i ] ) {
  1469. idPlayer *player = static_cast< idPlayer* >( gameLocal.entities[i] );
  1470. player->SetLevelTrigger( spawnArgs.GetString( "levelName" ), spawnArgs.GetString( "triggerName" ) );
  1471. }
  1472. }
  1473. }
  1474. /*
  1475. ===============================================================================
  1476. idTarget_Checkpoint
  1477. ===============================================================================
  1478. */
  1479. CLASS_DECLARATION( idTarget, idTarget_Checkpoint )
  1480. EVENT( EV_Activate, idTarget_Checkpoint::Event_Activate )
  1481. END_CLASS
  1482. idCVar g_checkpoints( "g_checkpoints", "1", CVAR_BOOL | CVAR_ARCHIVE, "Enable/Disable checkpoints" );
  1483. /*
  1484. ================
  1485. idTarget_Checkpoint::Event_Activate
  1486. ================
  1487. */
  1488. void idTarget_Checkpoint::Event_Activate( idEntity *activator ) {
  1489. extern idCVar g_demoMode; // no saving in demo mode
  1490. if ( g_checkpoints.GetBool() && !g_demoMode.GetBool() ) {
  1491. cmdSystem->AppendCommandText( "savegame autosave\n" );
  1492. }
  1493. }
  1494. /*
  1495. ===============================================================================
  1496. idTarget_EnableStamina
  1497. ===============================================================================
  1498. */
  1499. CLASS_DECLARATION( idTarget, idTarget_EnableStamina )
  1500. EVENT( EV_Activate, idTarget_EnableStamina::Event_Activate )
  1501. END_CLASS
  1502. /*
  1503. ================
  1504. idTarget_EnableStamina::Event_Activate
  1505. ================
  1506. */
  1507. void idTarget_EnableStamina::Event_Activate( idEntity *activator ) {
  1508. for( int i = 0; i < gameLocal.numClients; i++ ) {
  1509. if ( gameLocal.entities[ i ] ) {
  1510. idPlayer *player = static_cast< idPlayer* >( gameLocal.entities[i] );
  1511. if ( spawnArgs.GetBool( "enable" ) ) {
  1512. pm_stamina.SetFloat( player->spawnArgs.GetFloat( "pm_stamina" ) );
  1513. } else {
  1514. pm_stamina.SetFloat( 0.0f );
  1515. }
  1516. }
  1517. }
  1518. }
  1519. /*
  1520. ===============================================================================
  1521. idTarget_FadeSoundClass
  1522. ===============================================================================
  1523. */
  1524. const idEventDef EV_RestoreVolume( "<RestoreVolume>" );
  1525. CLASS_DECLARATION( idTarget, idTarget_FadeSoundClass )
  1526. EVENT( EV_Activate, idTarget_FadeSoundClass::Event_Activate )
  1527. EVENT( EV_RestoreVolume, idTarget_FadeSoundClass::Event_RestoreVolume )
  1528. END_CLASS
  1529. /*
  1530. ================
  1531. idTarget_FadeSoundClass::Event_Activate
  1532. ================
  1533. */
  1534. void idTarget_FadeSoundClass::Event_Activate( idEntity *activator ) {
  1535. float fadeTime = spawnArgs.GetFloat( "fadeTime" );
  1536. float fadeDB = spawnArgs.GetFloat( "fadeDB" );
  1537. float fadeDuration = spawnArgs.GetFloat( "fadeDuration" );
  1538. int fadeClass = spawnArgs.GetInt( "fadeClass" );
  1539. // start any sound fading now
  1540. if ( fadeTime ) {
  1541. gameSoundWorld->FadeSoundClasses( fadeClass, spawnArgs.GetBool( "fadeIn" ) ? fadeDB : 0.0f - fadeDB, fadeTime );
  1542. if ( fadeDuration ) {
  1543. PostEventSec( &EV_RestoreVolume, fadeDuration );
  1544. }
  1545. }
  1546. }
  1547. /*
  1548. ================
  1549. idTarget_FadeSoundClass::Event_RestoreVolume
  1550. ================
  1551. */
  1552. void idTarget_FadeSoundClass::Event_RestoreVolume() {
  1553. float fadeTime = spawnArgs.GetFloat( "fadeTime" );
  1554. float fadeDB = spawnArgs.GetFloat( "fadeDB" );
  1555. //int fadeClass = spawnArgs.GetInt( "fadeClass" );
  1556. // restore volume
  1557. gameSoundWorld->FadeSoundClasses( 0, fadeDB, fadeTime );
  1558. }
  1559. /*
  1560. ===============================================================================
  1561. idTarget_RumbleJoystick
  1562. ===============================================================================
  1563. */
  1564. CLASS_DECLARATION( idTarget, idTarget_RumbleJoystick )
  1565. EVENT( EV_Activate, idTarget_RumbleJoystick::Event_Activate )
  1566. END_CLASS
  1567. /*
  1568. ================
  1569. idTarget_RumbleJoystick::Event_Activate
  1570. ================
  1571. */
  1572. void idTarget_RumbleJoystick::Event_Activate( idEntity *activator ) {
  1573. idPlayer *player = gameLocal.GetLocalPlayer();
  1574. if ( player != NULL ) {
  1575. float highMagnitude = spawnArgs.GetFloat( "high_magnitude" );
  1576. int highDuration = spawnArgs.GetInt( "high_duration" );
  1577. float lowMagnitude = spawnArgs.GetFloat( "low_magnitude" );
  1578. int lowDuration = spawnArgs.GetInt( "low_duration" );
  1579. player->SetControllerShake( highMagnitude, highDuration, lowMagnitude, lowDuration );
  1580. }
  1581. }
  1582. /*
  1583. ===============================================================================
  1584. idTarget_Achievement
  1585. ===============================================================================
  1586. */
  1587. CLASS_DECLARATION( idTarget, idTarget_Achievement )
  1588. EVENT( EV_Activate, idTarget_Achievement::Event_Activate )
  1589. END_CLASS
  1590. /*
  1591. ================
  1592. idTarget_Achievement::Event_Activate
  1593. ================
  1594. */
  1595. void idTarget_Achievement::Event_Activate( idEntity *activator ) {
  1596. idPlayer *player = gameLocal.GetLocalPlayer();
  1597. if ( player != NULL ) {
  1598. int achievement = spawnArgs.GetFloat( "achievement" );
  1599. player->GetAchievementManager().EventCompletesAchievement( (achievement_t)achievement );
  1600. }
  1601. }