keypad.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. // viola, the keypad
  2. // 0 QZ 1 ABC 2 DEF
  3. // 3 GHI 4 JKL 5 MNO
  4. // 6 PRS 7 TUV 8 WXY
  5. #include "../idlib/precompiled.h"
  6. #pragma hdrstop
  7. #include "Game_local.h"
  8. #define PRESSTIME 100
  9. const idEventDef EV_keypadopen( "keypadopen", "d" );
  10. CLASS_DECLARATION( idAnimatedEntity, idKeypad )
  11. EVENT( EV_keypadopen, idKeypad::Event_keypadopen)
  12. END_CLASS
  13. void idKeypad::Save( idSaveGame *savefile ) const
  14. {
  15. savefile->WriteInt(state);
  16. savefile->WriteInt(counter);
  17. savefile->WriteInt(nextStateTime);
  18. savefile->WriteObject(frobcubeMain);
  19. for (int i = 0; i < 9; i++)
  20. {
  21. savefile->WriteObject(frobcubes[i]);
  22. savefile->WriteSkin(skin_glow[i]);
  23. savefile->WriteInt(transitions[i]);
  24. }
  25. savefile->WriteInt( keys.Num() );
  26. for (int i = 0; i < keys.Num(); i++ )
  27. {
  28. savefile->WriteString( keys[ i ] );
  29. }
  30. for (int i = 0; i < 4; i++)
  31. {
  32. savefile->WriteInt(keycode[i]);
  33. savefile->WriteInt(input[i]);
  34. }
  35. savefile->WriteInt(keyIndex);
  36. savefile->WriteObject(bluebox);
  37. }
  38. void idKeypad::Restore( idRestoreGame *savefile )
  39. {
  40. savefile->ReadInt(state);
  41. savefile->ReadInt(counter);
  42. savefile->ReadInt(nextStateTime);
  43. savefile->ReadObject(reinterpret_cast<idClass *&>(frobcubeMain));
  44. for (int i = 0; i < 9; i++)
  45. {
  46. savefile->ReadObject(reinterpret_cast<idClass *&>(frobcubes[i]));
  47. savefile->ReadSkin(skin_glow[i]);
  48. savefile->ReadInt(transitions[i]);
  49. }
  50. int keyAmount;
  51. savefile->ReadInt( keyAmount );
  52. for (int i = 0; i < keyAmount; i++ )
  53. {
  54. idStr keyStr;
  55. savefile->ReadString( keyStr );
  56. keys.Append( keyStr );
  57. }
  58. for (int i = 0; i < 4; i++)
  59. {
  60. savefile->ReadInt(keycode[i]);
  61. savefile->ReadInt(input[i]);
  62. }
  63. savefile->ReadInt(keyIndex);
  64. savefile->ReadObject(reinterpret_cast<idClass *&>(bluebox));
  65. }
  66. void idKeypad::Event_keypadopen( int value )
  67. {
  68. if (state == CONFIRM_SUCCESS)
  69. return;
  70. if (value >= 1)
  71. {
  72. int i;
  73. GenerateKey();
  74. Event_PlayAnim( "opening" , 4 );
  75. state = ACTIVE;
  76. for (i = 0; i < 9; i++)
  77. {
  78. this->frobcubes[i]->isFrobbable = true;
  79. }
  80. this->frobcubeMain->GetPhysics()->SetContents(0);
  81. }
  82. else
  83. {
  84. this->frobcubeMain->GetPhysics()->SetContents( CONTENTS_RENDERMODEL );
  85. this->frobcubeMain->GetPhysics()->SetClipMask( MASK_SOLID | CONTENTS_MOVEABLECLIP );
  86. if (state == OFF)
  87. {
  88. return;
  89. }
  90. int i;
  91. Event_PlayAnim( "closing" , 4);
  92. state = OFF;
  93. for (i = 0; i < 9; i++)
  94. {
  95. this->frobcubes[i]->isFrobbable = false;
  96. }
  97. bluebox->Hide();
  98. }
  99. }
  100. //call this once.
  101. void idKeypad::GenerateDictionary( void )
  102. {
  103. void *buffer;
  104. idStr rawDictionary;
  105. int i;
  106. if (fileSystem->ReadFile( "keycodes.txt", &buffer) > 0)
  107. {
  108. rawDictionary = (char *) buffer;
  109. fileSystem->FreeFile( buffer );
  110. }
  111. else
  112. {
  113. gameLocal.Error("cannot load keycodes.txt");
  114. return;
  115. }
  116. rawDictionary.StripTrailingWhitespace(); //remove whitespace.
  117. rawDictionary.StripLeading( ' ' ); //remove whitespace.
  118. rawDictionary.ToUpper();
  119. keys.Clear();
  120. for (i = rawDictionary.Length(); i >= 0; i--)
  121. {
  122. if (rawDictionary[i] == '\n' || rawDictionary[i] == '\r')
  123. {
  124. if (rawDictionary.Mid(i+1, rawDictionary.Length()).IsEmpty())
  125. {
  126. rawDictionary = rawDictionary.Left(i);
  127. continue;
  128. }
  129. keys.AddUnique(rawDictionary.Mid(i+1, rawDictionary.Length() ));
  130. rawDictionary = rawDictionary.Left(i); //strip.
  131. }
  132. if (i <= 0)
  133. {
  134. keys.AddUnique(rawDictionary.Mid(0, rawDictionary.Length() ));
  135. }
  136. }
  137. }
  138. void idKeypad::GenerateKey( void )
  139. {
  140. int i;
  141. keyIndex = gameLocal.random.RandomInt(keys.Num());
  142. for (i = 0; i < 4; i++)
  143. {
  144. if (keys[keyIndex][i] == 'Q' || keys[keyIndex][i] == 'Z')
  145. {
  146. keycode[i] = 0;
  147. }
  148. else if (keys[keyIndex][i] == 'A' || keys[keyIndex][i] == 'B' || keys[keyIndex][i] == 'C')
  149. {
  150. keycode[i] = 1;
  151. }
  152. else if (keys[keyIndex][i] == 'D' || keys[keyIndex][i] == 'E' || keys[keyIndex][i] == 'F')
  153. {
  154. keycode[i] = 2;
  155. }
  156. else if (keys[keyIndex][i] == 'G' || keys[keyIndex][i] == 'H' || keys[keyIndex][i] == 'I')
  157. {
  158. keycode[i] = 3;
  159. }
  160. else if (keys[keyIndex][i] == 'J' || keys[keyIndex][i] == 'K' || keys[keyIndex][i] == 'L')
  161. {
  162. keycode[i] = 4;
  163. }
  164. else if (keys[keyIndex][i] == 'M' || keys[keyIndex][i] == 'N' || keys[keyIndex][i] == 'O')
  165. {
  166. keycode[i] = 5;
  167. }
  168. else if (keys[keyIndex][i] == 'P' || keys[keyIndex][i] == 'R' || keys[keyIndex][i] == 'S')
  169. {
  170. keycode[i] = 6;
  171. }
  172. else if (keys[keyIndex][i] == 'T' || keys[keyIndex][i] == 'U' || keys[keyIndex][i] == 'V')
  173. {
  174. keycode[i] = 7;
  175. }
  176. else
  177. {
  178. keycode[i] = 8;
  179. }
  180. }
  181. this->bluebox->GetRenderEntity()->gui[0]->SetStateString("gui_parm0", keys[keyIndex]);
  182. }
  183. void idKeypad::Spawn( void )
  184. {
  185. int i;
  186. idVec3 forward, right, up;
  187. this->GetPhysics()->GetAxis().ToAngles().ToVectors(&forward, &right, &up);
  188. //spawn the buttons.
  189. for (i = 0; i < 9; i++)
  190. {
  191. idDict args;
  192. idVec3 pos = this->GetPhysics()->GetOrigin() + (forward * 1.7f);
  193. if (i <= 0) { pos += (up * 2) + (right * 2); }
  194. else if (i == 1) { pos += (up * 2); }
  195. else if (i == 2) { pos += (up * 2) + (right * -2); }
  196. else if (i == 3) { pos += (right * 2); }
  197. else if (i == 4) { }
  198. else if (i == 5) { pos += (right * -2); }
  199. else if (i == 6) { pos += (up * -2) + (right * 2); }
  200. else if (i == 7) { pos += (up * -2); }
  201. else if (i == 8) { pos += (up * -2) + (right * -2); }
  202. args.SetVector( "origin", pos );
  203. args.Set( "model", "models/frob/cube_2x2.ase" );
  204. args.SetInt( "frobbable", 1 );
  205. args.SetInt( "corpse", 1 );
  206. args.SetInt( "noGrab", 1 );
  207. args.Set( "owner", this->GetName() );
  208. args.SetInt( "index", i );
  209. this->frobcubes[i] = gameLocal.SpawnEntityType( idStaticEntity::Type, &args );
  210. this->frobcubes[i]->isFrobbable = false;
  211. this->frobcubes[i]->SetAngles(this->GetPhysics()->GetAxis().ToAngles());
  212. }
  213. skin_glow[0] = declManager->FindSkin( "skins/keypad/qz_glow" );
  214. skin_glow[1] = declManager->FindSkin( "skins/keypad/abc_glow" );
  215. skin_glow[2] = declManager->FindSkin( "skins/keypad/def_glow" );
  216. skin_glow[3] = declManager->FindSkin( "skins/keypad/ghi_glow" );
  217. skin_glow[4] = declManager->FindSkin( "skins/keypad/jkl_glow" );
  218. skin_glow[5] = declManager->FindSkin( "skins/keypad/mno_glow" );
  219. skin_glow[6] = declManager->FindSkin( "skins/keypad/prs_glow" );
  220. skin_glow[7] = declManager->FindSkin( "skins/keypad/tuv_glow" );
  221. skin_glow[8] = declManager->FindSkin( "skins/keypad/wxy_glow" );
  222. idDict args1;
  223. args1.SetVector( "origin", this->GetPhysics()->GetOrigin() );
  224. args1.Set( "model", "models/keypad/tris_cm.ase" );
  225. args1.SetInt( "frobbable", 1 );
  226. args1.SetInt( "corpse", 1 );
  227. args1.SetInt( "noGrab", 1 );
  228. args1.Set( "owner", this->GetName() );
  229. args1.SetInt( "index", 16 );
  230. this->frobcubeMain = gameLocal.SpawnEntityType( idStaticEntity::Type, &args1 );
  231. this->frobcubeMain->isFrobbable = true;
  232. this->frobcubeMain->SetAngles(this->GetPhysics()->GetAxis().ToAngles());
  233. args1.Clear();
  234. args1.SetVector("origin", this->GetPhysics()->GetOrigin() );
  235. args1.Set("classname", "moveable_bluebox");
  236. args1.Set("gui", "guis/bluebox_pw.gui");
  237. gameLocal.SpawnEntityDef(args1, &bluebox);
  238. bluebox->Hide();
  239. for (i = 0; i < 4; i++)
  240. {
  241. input[i] = 0;
  242. }
  243. GenerateDictionary();
  244. this->nextStateTime = 0;
  245. this->counter = 0;
  246. this->state = OFF;
  247. BecomeActive( TH_THINK );
  248. }
  249. idStr idKeypad::GetJointViaIndex( int index )
  250. {
  251. switch ( index )
  252. {
  253. case 0: return "qz"; break;
  254. case 1: return "abc"; break;
  255. case 2: return "def"; break;
  256. case 3: return "ghi"; break;
  257. case 4: return "jkl"; break;
  258. case 5: return "mno"; break;
  259. case 6: return "prs"; break;
  260. case 7: return "tuv"; break;
  261. default: return "wxy"; break;
  262. }
  263. }
  264. void idKeypad::OnFrob( idEntity* activator )
  265. {
  266. int index;
  267. if (!activator->spawnArgs.GetInt( "index", "", index))
  268. {
  269. return;
  270. }
  271. //common->Printf("%d\n", index);
  272. if (index == 16)
  273. {
  274. this->StartSound( "snd_error" , SND_CHANNEL_ANY, 0, false, NULL );
  275. return;
  276. }
  277. //PostEventSec( &EV_Turret_muzzleflashoff, MUZZLEFLASHTIME);
  278. if (index >= 0 && index <= 8)
  279. {
  280. jointHandle_t joint;
  281. joint = animator.GetJointHandle( GetJointViaIndex(index) );
  282. animator.SetJointPos(joint, JOINTMOD_LOCAL, idVec3(-0.8f, 0, 0) );
  283. transitions[index] = gameLocal.time + PRESSTIME;
  284. }
  285. StartSound( "snd_press", SND_CHANNEL_ANY, 0, false, NULL );
  286. if (counter <= 0)
  287. {
  288. Event_PlayAnim("marker0", 4);
  289. }
  290. else if (counter == 1)
  291. {
  292. Event_PlayAnim("marker1", 4);
  293. }
  294. else if (counter == 2)
  295. {
  296. Event_PlayAnim("marker2", 4);
  297. }
  298. else if (counter == 3)
  299. {
  300. Event_PlayAnim("marker3", 4);
  301. }
  302. input[counter] = index;
  303. counter++;
  304. if (counter >= 4)
  305. {
  306. int i;
  307. for (i = 0; i < 9; i++)
  308. {
  309. this->frobcubes[i]->isFrobbable = false;
  310. }
  311. counter = 0;
  312. //TODO if successful.
  313. // gameLocal.GetLocalPlayer()->Event_useAmmo("ammo_hacktool", 1)
  314. if ( input[0] == keycode[0] && input[1] == keycode[1] && input[2] == keycode[2] && input[3] == keycode[3] )
  315. {
  316. //done success.
  317. bluebox->Hide();
  318. ActivateTargets( this );
  319. state = CONFIRM_SUCCESS;
  320. int doneTime = Event_PlayAnim("success", 4);
  321. nextStateTime = doneTime;
  322. SetSkin(declManager->FindSkin("skins/keypad/green"));
  323. //add hud message.
  324. StartSound( "snd_deactivated", SND_CHANNEL_ANY, 0, false, NULL);
  325. return;
  326. }
  327. else
  328. {
  329. //fail.
  330. state = CONFIRM_FAIL;
  331. int doneTime = Event_PlayAnim("fail", 4);
  332. nextStateTime = doneTime;
  333. SetSkin(declManager->FindSkin("skins/keypad/red"));
  334. return;
  335. }
  336. }
  337. }
  338. void idKeypad::UpdateStates( void )
  339. {
  340. if (state == CONFIRM_SUCCESS)
  341. {
  342. if (gameLocal.time > nextStateTime)
  343. {
  344. int i;
  345. //close ALL keypads.
  346. state = READY_TO_CLOSE;
  347. //Event_keypadopen( 0 );
  348. for ( i = 0; i < gameLocal.num_entities; i++ )
  349. {
  350. if ( !gameLocal.entities[ i ] )
  351. continue;
  352. if (!gameLocal.entities[i]->IsType(idKeypad::Type))
  353. continue;
  354. //skip self.
  355. //if (gameLocal.entities[i]->entityNumber == this->entityNumber)
  356. // continue;
  357. static_cast<idKeypad *>( gameLocal.entities[i] )->Event_keypadopen(0);
  358. }
  359. SetSkin(0);
  360. return;
  361. }
  362. }
  363. else if (state == CONFIRM_FAIL)
  364. {
  365. if (gameLocal.time > nextStateTime)
  366. {
  367. //close up.
  368. int i;
  369. for (i = 0; i < 9; i++)
  370. {
  371. this->frobcubes[i]->isFrobbable = true;
  372. }
  373. state = ACTIVE;
  374. SetSkin(0);
  375. return;
  376. }
  377. }
  378. }
  379. void idKeypad::Think( void )
  380. {
  381. int i;
  382. //glows.
  383. if (state == ACTIVE)
  384. {
  385. if (gameLocal.GetLocalPlayer()->focusFrobEnt)
  386. {
  387. bool isHover = false;
  388. int i;
  389. int hoverIndex = gameLocal.GetLocalPlayer()->focusFrobEnt->entityNumber;
  390. for (i = 0; i < 9; i++)
  391. {
  392. if (hoverIndex == frobcubes[i]->entityNumber)
  393. {
  394. SetSkin(skin_glow[i]);
  395. isHover = true;
  396. }
  397. }
  398. if (!isHover)
  399. {
  400. SetSkin(0); //default.
  401. bluebox->Hide();
  402. }
  403. else
  404. {
  405. //show bluebox.
  406. bluebox->Show();
  407. idAngles remoteAng = gameLocal.GetLocalPlayer()->viewAngles;
  408. remoteAng.yaw += 180 + 30;
  409. remoteAng.pitch *= -1;
  410. remoteAng.pitch += 3 * idMath::Sin(gameLocal.time * 0.0005f); //sway
  411. remoteAng.yaw += 3 + 3 * idMath::Sin(gameLocal.time * 0.0003f); //sway
  412. bluebox->SetAngles( remoteAng );
  413. idVec3 up, right;
  414. remoteAng.ToVectors( NULL, &right, &up );
  415. idVec3 finalPos = gameLocal.GetLocalPlayer()->GetEyePosition()
  416. + (gameLocal.GetLocalPlayer()->viewAngles.ToForward() * 12.0f)
  417. + (up * -5.0f)
  418. + (right * 7.0f);
  419. bluebox->GetPhysics()->SetOrigin(finalPos);
  420. //bluebox->GetPhysics()->SetOrigin(
  421. }
  422. }
  423. else
  424. {
  425. SetSkin(0); //default.
  426. //hide bluebox.
  427. bluebox->Hide();
  428. }
  429. }
  430. //handle the button animations.
  431. for (i = 0; i < 9; i++)
  432. {
  433. if (gameLocal.time > transitions[i])
  434. {
  435. jointHandle_t joint;
  436. joint = animator.GetJointHandle( GetJointViaIndex(i) );
  437. animator.ClearJoint(joint);
  438. }
  439. }
  440. UpdateStates();
  441. idAnimatedEntity::Think();
  442. idAnimatedEntity::Present();
  443. }