laserwire.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. #include "../idlib/precompiled.h"
  2. #pragma hdrstop
  3. #include "Game_local.h"
  4. #define LASERTHINKTIME 200
  5. #define MAXWIDTH 7
  6. #define MINWIDTH 0.5
  7. #define REDCOLOR_R 1
  8. #define REDCOLOR_G 0.5
  9. #define REDCOLOR_B 0.5
  10. #define CAMERAGHOST_LIFETIME 9 //how long ghost sits there.
  11. const idEventDef EV_LaserWire_camOff( "laseroff", "f" );
  12. const idEventDef EV_LaserWire_camOn( "laseron" );
  13. const idEventDef EV_LaserWire_KillGhost( "<killghost>" );
  14. const idEventDef EV_LaserWire_laserenable( "laserenable", "f" );
  15. CLASS_DECLARATION( idEntity, idLaserWire )
  16. EVENT( EV_LaserWire_camOff, idLaserWire::Event_off)
  17. EVENT( EV_LaserWire_camOn, idLaserWire::Event_on)
  18. EVENT( EV_LaserWire_KillGhost, idLaserWire::Event_KillGhost)
  19. EVENT( EV_LaserWire_laserenable, idLaserWire::Event_laserenable)
  20. END_CLASS
  21. void idLaserWire::Save( idSaveGame *savefile ) const
  22. {
  23. savefile->WriteInt(nextThinkTime);
  24. savefile->WriteInt(state);
  25. savefile->WriteInt(dimEndTime);
  26. savefile->WriteInt(dimStartTime);
  27. savefile->WriteInt(turnonTime);
  28. savefile->WriteInt(nextAlarmTime);
  29. savefile->WriteInt(softAlarmTime);
  30. savefile->WriteBool(softAlarmReady);
  31. savefile->WriteObject(ghostImage);
  32. int i;
  33. for (i = 0; i < BEAMCOUNT; i++)
  34. {
  35. savefile->WriteObject(boundBeam[i]);
  36. savefile->WriteObject(boundBeamTarget[i]);
  37. }
  38. savefile->WriteInt(softAlarmTimeMax);
  39. }
  40. void idLaserWire::Restore( idRestoreGame *savefile )
  41. {
  42. savefile->ReadInt(nextThinkTime);
  43. savefile->ReadInt(state);
  44. savefile->ReadInt(dimEndTime);
  45. savefile->ReadInt(dimStartTime);
  46. savefile->ReadInt(turnonTime);
  47. savefile->ReadInt(nextAlarmTime);
  48. savefile->ReadInt(softAlarmTime);
  49. savefile->ReadBool(softAlarmReady);
  50. savefile->ReadObject(reinterpret_cast<idClass *&>(ghostImage));
  51. int i;
  52. for (i = 0; i < BEAMCOUNT; i++)
  53. {
  54. savefile->ReadObject(reinterpret_cast<idClass *&>(boundBeam[i]));
  55. savefile->ReadObject(reinterpret_cast<idClass *&>(boundBeamTarget[i]));
  56. }
  57. savefile->ReadInt(softAlarmTimeMax);
  58. }
  59. void idLaserWire::Spawn( void ) {
  60. int i;
  61. int gapdistance = this->spawnArgs.GetInt("gapdistance", "15");
  62. softAlarmTimeMax = (int)(this->spawnArgs.GetFloat("softalarmtime", "3") * 1000);
  63. this->softAlarmReady = false;
  64. this->nextAlarmTime = 0;
  65. this->state = IDLE;
  66. this->nextThinkTime = 0;
  67. this->dimEndTime = 0;
  68. this->turnonTime = 0;
  69. this->softAlarmTime = 0;
  70. //Spawn the beams.
  71. for (i = 0; i < 5; i++)
  72. {
  73. idDict args;
  74. idVec3 beamOrigin;
  75. idVec3 forward, right;
  76. int rightAmount;
  77. idVec3 beamTargetOrigin;
  78. trace_t tr;
  79. bool shouldSkip;
  80. shouldSkip = false;
  81. switch (i)
  82. {
  83. case 0:
  84. rightAmount = gapdistance * 2;
  85. shouldSkip = this->spawnArgs.GetBool("beam0skip", "0");
  86. break;
  87. case 1:
  88. rightAmount = gapdistance;
  89. shouldSkip = this->spawnArgs.GetBool("beam1skip", "0");
  90. break;
  91. case 2:
  92. rightAmount = 0;
  93. shouldSkip = this->spawnArgs.GetBool("beam2skip", "0");
  94. break;
  95. case 3:
  96. rightAmount = -gapdistance;
  97. shouldSkip = this->spawnArgs.GetBool("beam3skip", "0");
  98. break;
  99. case 4:
  100. rightAmount = -gapdistance * 2;
  101. shouldSkip = this->spawnArgs.GetBool("beam4skip", "0");
  102. break;
  103. default:
  104. rightAmount = 8;
  105. break;
  106. }
  107. if (shouldSkip)
  108. {
  109. this->boundBeam[i] = NULL;
  110. this->boundBeamTarget[i] = NULL;
  111. continue;
  112. }
  113. this->GetPhysics()->GetAxis().ToAngles().ToVectors(&forward, &right);
  114. beamOrigin = this->GetPhysics()->GetOrigin() + (forward * 1.5) + (right * rightAmount);
  115. //TODO: don't spawn beam if it starts in geometry.
  116. //do the trace. Determine if beam starts off in a solid.
  117. //gameLocal.clip.TracePoint( tr, beamOrigin, beamOrigin + (forward * 32), /*idBounds(idVec3(-4,-4,-4),idVec3(4,4,4)),*/ MASK_SOLID, this );
  118. //common->Printf(va("%f %d %f\n", tr.fraction, tr.c.contents, tr.c.dist));
  119. args.SetVector( "origin", vec3_origin );
  120. this->boundBeamTarget[i] = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type, &args );
  121. args.Clear();
  122. args.Set( "target", boundBeamTarget[i]->name.c_str() );
  123. args.SetVector( "origin", beamOrigin );
  124. args.SetBool( "start_off", false );
  125. args.Set( "skin", "skins/beam_red" );
  126. this->boundBeam[i] = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type, &args );
  127. this->boundBeam[i]->Event_SetWidth( MAXWIDTH );
  128. this->boundBeam[i]->Bind(this, false);
  129. }
  130. //tell it to think.
  131. BecomeActive( TH_THINK );
  132. //the flares.
  133. renderEntity.shaderParms[ SHADERPARM_RED ] = REDCOLOR_R;
  134. renderEntity.shaderParms[ SHADERPARM_GREEN ] = REDCOLOR_G;
  135. renderEntity.shaderParms[ SHADERPARM_BLUE ] = REDCOLOR_B;
  136. //spawn the Laser Ghost.
  137. idDict args;
  138. args.Clear();
  139. args.SetVector( "origin", vec3_origin );
  140. args.Set( "classname", "env_cameradummy" );
  141. args.Set( "solid", "0" );
  142. gameLocal.SpawnEntityDef( args, &this->ghostImage );
  143. this->ghostImage->Hide();
  144. StartSound( "snd_idle" , SND_CHANNEL_RADIO, 0, false, NULL );
  145. }
  146. void idLaserWire::Event_laserenable( int value )
  147. {
  148. if (value <= 0)
  149. {
  150. int i;
  151. this->state = DISABLED;
  152. renderEntity.shaderParms[ SHADERPARM_RED ] = 0;
  153. renderEntity.shaderParms[ SHADERPARM_GREEN ] = 0;
  154. renderEntity.shaderParms[ SHADERPARM_BLUE ] = 0;
  155. UpdateVisuals();
  156. for (i = 0; i < 5; i++)
  157. {
  158. if (this->boundBeam[i] == NULL)
  159. continue;
  160. this->boundBeam[i]->Hide();
  161. }
  162. }
  163. else
  164. {
  165. Event_on();
  166. }
  167. }
  168. void idLaserWire::Event_KillGhost( void )
  169. {
  170. this->ghostImage->Hide();
  171. }
  172. void idLaserWire::Event_off( float delay )
  173. {
  174. if (!this->softAlarmReady)
  175. {
  176. this->softAlarmReady = true;
  177. this->softAlarmTime = gameLocal.time + (softAlarmTimeMax);
  178. }
  179. if (this->state == IDLE)
  180. {
  181. float dimTime;
  182. dimTime = this->spawnArgs.GetFloat("dimtime", "1.3");
  183. if (dimTime <= 0)
  184. {
  185. dimTime = 0.1;
  186. }
  187. this->state = DIMMING;
  188. this->dimStartTime = gameLocal.time;
  189. this->dimEndTime = gameLocal.time + (dimTime * 1000);
  190. StartSound( "snd_laserhumdown" , SND_CHANNEL_ANY, 0, false, NULL );
  191. StopSound(SND_CHANNEL_RADIO, false);
  192. }
  193. if (delay <= 0)
  194. {
  195. this->turnonTime = gameLocal.time + (9000 * 1000);
  196. }
  197. else
  198. {
  199. this->turnonTime = gameLocal.time + (delay * 1000);
  200. }
  201. uiHackTimer = gameLocal.time + UIHACKTIME;
  202. }
  203. void idLaserWire::Event_on( void )
  204. {
  205. if (this->state == IDLE)
  206. return;
  207. uiHackTimer = gameLocal.time + UIHACKTIME;
  208. this->state = TURNON;
  209. this->turnonTime = 0;
  210. }
  211. /*
  212. ================
  213. idSecurityCamera::Think
  214. ================
  215. */
  216. void idLaserWire::Think( void )
  217. {
  218. //power down the beams.
  219. if (this->state == DIMMING)
  220. {
  221. int i;
  222. float beamWidth, curLerp, endTime;
  223. curLerp = gameLocal.time - this->dimStartTime;
  224. endTime = this->dimEndTime - this->dimStartTime;
  225. curLerp = idMath::ClampFloat(0, 1, (float)curLerp / endTime);
  226. beamWidth = MAXWIDTH * (1 - curLerp);
  227. for (i = 0; i < 5; i++)
  228. {
  229. if (this->boundBeam[i] == NULL)
  230. continue;
  231. this->boundBeam[i]->Event_SetWidth(beamWidth);
  232. }
  233. if (curLerp >= 1)
  234. {
  235. idDict args;
  236. this->state = OFF;
  237. renderEntity.shaderParms[ SHADERPARM_RED ] = 0;
  238. renderEntity.shaderParms[ SHADERPARM_GREEN ] = 0;
  239. renderEntity.shaderParms[ SHADERPARM_BLUE ] = 0;
  240. UpdateVisuals();
  241. for (i = 0; i < 5; i++)
  242. {
  243. if (this->boundBeam[i] == NULL)
  244. continue;
  245. this->boundBeam[i]->Hide();
  246. args.Clear();
  247. args.SetVector( "origin", boundBeam[i]->GetPhysics()->GetOrigin() );
  248. args.Set( "model", "sparkburst2.prt" );
  249. args.SetBool( "start_off", false );
  250. gameLocal.SpawnEntityType( idExplodable::Type, &args );
  251. }
  252. StartSound( "snd_laseroff" , SND_CHANNEL_ANY, 0, false, NULL );
  253. SetSkin(declManager->FindSkin("skins/laserwire/off"));
  254. }
  255. }
  256. //turn on the beams.
  257. if ((this->state == DIMMING || this->state == OFF || this->state == TURNON) && gameLocal.time > this->turnonTime)
  258. {
  259. int i;
  260. //turn back on.
  261. this->state = IDLE;
  262. //reset flares.
  263. renderEntity.shaderParms[ SHADERPARM_RED ] = REDCOLOR_R;
  264. renderEntity.shaderParms[ SHADERPARM_GREEN ] = REDCOLOR_G;
  265. renderEntity.shaderParms[ SHADERPARM_BLUE ] = REDCOLOR_B;
  266. UpdateVisuals();
  267. //reset beams.
  268. for (i = 0; i < 5; i++)
  269. {
  270. if (this->boundBeam[i] == NULL)
  271. continue;
  272. this->boundBeam[i]->Event_SetWidth( MAXWIDTH );
  273. this->boundBeam[i]->Show();
  274. }
  275. //disable soft alarm
  276. this->softAlarmReady = false;
  277. StartSound( "snd_laseron" , SND_CHANNEL_ANY, 0, false, NULL );
  278. SetSkin(declManager->FindSkin("skins/laserwire/skin"));
  279. this->softAlarmTime = 0;
  280. StartSound( "snd_idle" , SND_CHANNEL_RADIO, 0, false, NULL );
  281. }
  282. //check for soft alarm.
  283. if ((this->state == DIMMING || this->state == OFF) && this->softAlarmTime < gameLocal.time && this->softAlarmReady && softAlarmTimeMax > 0)
  284. {
  285. uiAlarmTimer = gameLocal.time + UIALARMTIME;
  286. //only fire it once. reset soft alarm when it's turned back on.
  287. this->softAlarmReady = false;
  288. common->Printf("Event: 3-SECOND ALARM TRIGGERED: %s\n", this->GetName() );
  289. gameLocal.GetLocalPlayer()->Event_hudMessage( va( common->GetLanguageDict()->GetString( "#str_01203" ), this->GetName() ) );
  290. //BC 11-23-2013
  291. //turn on laser after soft alarm.
  292. Event_on();
  293. idStr funcname = spawnArgs.GetString( "softalarmtarget", "" );
  294. if ( funcname.Length() )
  295. {
  296. idEntity *softAlarmEnt;
  297. softAlarmEnt = gameLocal.FindEntity( funcname );
  298. if ( softAlarmEnt->RespondsTo( EV_Activate ) || softAlarmEnt->HasSignal( SIG_TRIGGER ) )
  299. {
  300. softAlarmEnt->Signal( SIG_TRIGGER );
  301. softAlarmEnt->ProcessEvent( &EV_Activate, this );
  302. }
  303. }
  304. //pneumo functionality. BLOW IT UP.
  305. idStr pneumoName = spawnArgs.GetString( "pneumomaster", "" );
  306. if ( pneumoName.Length() )
  307. {
  308. idEntity *pneumoEnt;
  309. pneumoEnt = gameLocal.FindEntity( pneumoName );
  310. if ( pneumoEnt )
  311. {
  312. //UseFrob( deckMaster.GetEntity(), "getAndClose");
  313. gameLocal.GetLocalPlayer()->UseFrob( pneumoEnt, "onLaserHit" );
  314. }
  315. }
  316. }
  317. //detect player.
  318. if (nextThinkTime < gameLocal.time && (this->state == DIMMING || this->state == IDLE))
  319. {
  320. int i;
  321. /*
  322. idPlayer *playerEnt;
  323. playerEnt = static_cast<idPlayer*>(gameLocal.entities[ 0 ]);
  324. if ( !playerEnt || ( playerEnt->fl.notarget ) || playerEnt->noclip)
  325. {
  326. Present();
  327. return;
  328. }
  329. */
  330. //how often to update.
  331. nextThinkTime = gameLocal.time + LASERTHINKTIME;
  332. for (i = 0; i < 5; i++)
  333. {
  334. idVec3 beamOrigin, beamTarget;
  335. idVec3 forward;
  336. trace_t tr;
  337. if (this->boundBeam[i] == NULL || this->boundBeamTarget[i] == NULL)
  338. continue;
  339. this->GetPhysics()->GetAxis().ToAngles().ToVectors(&forward);
  340. beamOrigin = this->boundBeam[i]->GetPhysics()->GetOrigin();
  341. beamTarget = beamOrigin + (forward * 1024);
  342. //do the trace.
  343. gameLocal.clip.TracePoint( tr, beamOrigin, beamTarget, MASK_SHOT_RENDERMODEL | MASK_SHOT_BOUNDINGBOX, this );
  344. //move the beam target.
  345. boundBeamTarget[i]->SetOrigin(tr.endpos);
  346. if (g_skill.GetInteger() <= 0)
  347. continue;
  348. //check if player is hit.
  349. if (!gameLocal.GetTraceEntity( tr ))
  350. {
  351. continue;
  352. }
  353. if (gameLocal.GetTraceEntity( tr )->IsType( idWorldspawn::Type ))
  354. {
  355. continue;
  356. }
  357. if (gameLocal.GetTraceEntity( tr )->IsType( idStaticEntity::Type ))
  358. {
  359. continue;
  360. }
  361. if (gameLocal.GetTraceEntity( tr )->IsType( idPlayer::Type ))
  362. {
  363. idPlayer *playerEnt;
  364. playerEnt = static_cast<idPlayer*>(gameLocal.GetTraceEntity( tr ));
  365. if ( playerEnt->fl.notarget || playerEnt->noclip )
  366. {
  367. continue;
  368. }
  369. }
  370. //common->Printf("name %s %s\n", gameLocal.GetTraceEntity( tr )->Type.super );
  371. if ( gameLocal.GetTraceEntity( tr )->IsType( idEntity::Type))
  372. {
  373. //player is hit.
  374. boundBeamTarget[i]->SetOrigin(tr.endpos);
  375. //hit the alarm.
  376. if (this->nextAlarmTime < gameLocal.time)
  377. {
  378. this->nextAlarmTime = gameLocal.time + 2000;
  379. ActivateTargets(this);
  380. //pneumo functionality. BLOW IT UP.
  381. idStr pneumoName = spawnArgs.GetString( "pneumomaster", "" );
  382. if ( pneumoName.Length() )
  383. {
  384. idEntity *pneumoEnt;
  385. pneumoEnt = gameLocal.FindEntity( pneumoName );
  386. if ( pneumoEnt )
  387. {
  388. //UseFrob( deckMaster.GetEntity(), "getAndClose");
  389. gameLocal.GetLocalPlayer()->UseFrob( pneumoEnt, "onLaserHit" );
  390. }
  391. }
  392. uiAlarmTimer = gameLocal.time + UIALARMTIME;
  393. common->Printf("Event: ALARM TRIGGERED: %s\n", this->GetName() );
  394. gameLocal.GetLocalPlayer()->Event_hudMessage( va( common->GetLanguageDict()->GetString( "#str_01204" ), this->GetName() ) );
  395. CancelEvents( &EV_LaserWire_KillGhost );
  396. if (gameLocal.GetTraceEntity( tr )->IsType( idPlayer::Type))
  397. {
  398. this->ghostImage->SetOrigin( gameLocal.GetTraceEntity( tr )->GetPhysics()->GetOrigin() );
  399. //set the ghost angle.
  400. idAngles playerAng;
  401. playerAng.yaw = static_cast<idPlayer *>( gameLocal.GetTraceEntity( tr ) )->viewAngles.yaw;
  402. //playerAng.yaw = gameLocal.GetTraceEntity( tr )->GetPhysics()->GetAxis().ToAngles().yaw;
  403. playerAng.pitch = 0;
  404. playerAng.roll = 0;
  405. this->ghostImage->SetAxis( playerAng.ToMat3() );
  406. PostEventSec( &EV_LaserWire_KillGhost, CAMERAGHOST_LIFETIME );
  407. this->ghostImage->Show();
  408. }
  409. }
  410. }
  411. }
  412. }
  413. Present();
  414. }
  415. /*
  416. ================
  417. idSecurityCamera::Present
  418. Present is called to allow entities to generate refEntities, lights, etc for the renderer.
  419. ================
  420. */
  421. void idLaserWire::Present( void )
  422. {
  423. // don't present to the renderer if the entity hasn't changed
  424. if ( !( thinkFlags & TH_UPDATEVISUALS ) )
  425. {
  426. return;
  427. }
  428. BecomeInactive( TH_UPDATEVISUALS );
  429. // if set to invisible, skip
  430. if ( !renderEntity.hModel || IsHidden() )
  431. {
  432. return;
  433. }
  434. // add to refresh list
  435. if ( modelDefHandle == -1 )
  436. {
  437. modelDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
  438. }
  439. else
  440. {
  441. gameRenderWorld->UpdateEntityDef( modelDefHandle, &renderEntity );
  442. }
  443. }