launcher.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. #include "../idlib/precompiled.h"
  2. #pragma hdrstop
  3. #include "Game_local.h"
  4. #define WHEEL_STEP 40
  5. #define YAW_STEP 0.7f
  6. #define MAX_FORCE 1024 //was 1024
  7. #define MIN_FORCE 96
  8. #define MULTIPLIER_MIN 1.1f
  9. #define MULTIPLIER_MAX 2.2f
  10. #define MIN_PITCH -10
  11. #define MAX_PITCH -89
  12. #define RESETTIME 50
  13. #define WHEELSPEED 2
  14. #define WHEELTIME 300
  15. #define RISETIME 300
  16. #define BEAMWIDTH 8
  17. #define JUMPPADWIDTH 32
  18. #define JUMPPADHEIGHT 128
  19. const idEventDef EV_launcherkill( "launcherkill" );
  20. CLASS_DECLARATION( idMoveableItem, idLauncher )
  21. EVENT( EV_launcherkill, idLauncher::launcherkill)
  22. END_CLASS
  23. void idLauncher::Save( idSaveGame *savefile ) const
  24. {
  25. savefile->WriteObject(peakEnt);
  26. savefile->WriteObject(jumpPad);
  27. savefile->WriteObject(gatorEnt);
  28. savefile->WriteObject(remoteEnt);
  29. savefile->WriteObject(hitpointEnt);
  30. savefile->WriteObject(displaymodel);
  31. savefile->WriteObject(particles);
  32. savefile->WriteObject(jumpPad);
  33. savefile->WriteInt(state);
  34. savefile->WriteVec3(lastLaunchdir);
  35. savefile->WriteFloat(lastForce);
  36. savefile->WriteInt(nextAimrecord);
  37. savefile->WriteInt(remoteLerpStart);
  38. savefile->WriteInt(remoteLerpEnd);
  39. savefile->WriteVec3(baseGatorPos);
  40. savefile->WriteInt(resettime_up);
  41. savefile->WriteInt(resettime_down);
  42. savefile->WriteInt(resettime_left);
  43. savefile->WriteInt(resettime_right);
  44. savefile->WriteInt(wheelValue);
  45. savefile->WriteInt(wheelMovetime);
  46. savefile->WriteInt(wheelMovedir);
  47. savefile->WriteInt(beamUpdateTime);
  48. savefile->WriteFloat(remoteRaiseLerp);
  49. savefile->WriteInt(lastGametime);
  50. for (int i = 0; i < LINECOUNT; i++)
  51. {
  52. savefile->WriteObject(beamStarts[i]);
  53. savefile->WriteObject(beamEnds[i]);
  54. }
  55. savefile->WriteVec3(hitpointPos);
  56. savefile->WriteVec3(launchDir);
  57. savefile->WriteFloat(force);
  58. forcefieldIgnore.Save(savefile);
  59. }
  60. void idLauncher::Restore( idRestoreGame *savefile )
  61. {
  62. savefile->ReadObject(reinterpret_cast<idClass *&>(peakEnt));
  63. savefile->ReadObject(reinterpret_cast<idClass *&>(jumpPad));
  64. savefile->ReadObject(reinterpret_cast<idClass *&>(gatorEnt));
  65. savefile->ReadObject(reinterpret_cast<idClass *&>(remoteEnt));
  66. savefile->ReadObject(reinterpret_cast<idClass *&>(hitpointEnt));
  67. savefile->ReadObject(reinterpret_cast<idClass *&>(displaymodel));
  68. savefile->ReadObject(reinterpret_cast<idClass *&>(particles));
  69. savefile->ReadObject(reinterpret_cast<idClass *&>(jumpPad));
  70. savefile->ReadInt(state);
  71. savefile->ReadVec3(lastLaunchdir);
  72. savefile->ReadFloat(lastForce);
  73. savefile->ReadInt(nextAimrecord);
  74. savefile->ReadInt(remoteLerpStart);
  75. savefile->ReadInt(remoteLerpEnd);
  76. savefile->ReadVec3(baseGatorPos);
  77. savefile->ReadInt(resettime_up);
  78. savefile->ReadInt(resettime_down);
  79. savefile->ReadInt(resettime_left);
  80. savefile->ReadInt(resettime_right);
  81. savefile->ReadInt(wheelValue);
  82. savefile->ReadInt(wheelMovetime);
  83. savefile->ReadInt(wheelMovedir);
  84. savefile->ReadInt(beamUpdateTime);
  85. savefile->ReadFloat(remoteRaiseLerp);
  86. savefile->ReadInt(lastGametime);
  87. for (int i = 0; i < LINECOUNT; i++)
  88. {
  89. savefile->ReadObject(reinterpret_cast<idClass *&>(beamStarts[i]));
  90. savefile->ReadObject(reinterpret_cast<idClass *&>(beamEnds[i]));
  91. }
  92. savefile->ReadVec3(hitpointPos);
  93. savefile->ReadVec3(launchDir);
  94. savefile->ReadFloat(force);
  95. forcefieldIgnore.Restore(savefile);
  96. //this->forcefieldIgnore = jumpPad;
  97. }
  98. void idLauncher::Spawn( void )
  99. {
  100. int i;
  101. idVec3 forward, right, up;
  102. idDict args;
  103. this->GetPhysics()->GetAxis().ToAngles().ToVectors(&forward, &right, &up);
  104. args.Clear();
  105. args.SetVector( "origin", this->GetPhysics()->GetOrigin() + idVec3(0,0,0.1f) );
  106. args.Set( "classname", "info_location" );
  107. gameLocal.SpawnEntityDef( args, &peakEnt );
  108. peakEnt->Bind(this, false);
  109. args.Clear();
  110. args.SetVector( "origin", this->GetPhysics()->GetOrigin() );
  111. args.SetVector( "mins", idVec3(-JUMPPADWIDTH, -JUMPPADWIDTH, 3) );
  112. args.SetVector( "maxs", idVec3(JUMPPADWIDTH, JUMPPADWIDTH, JUMPPADHEIGHT) );
  113. args.Set( "target", peakEnt->GetName() );
  114. args.Set("snd_jump", "launcher_fire");
  115. args.Set("smoke_jump", spawnArgs.GetString("smoke_burst"));
  116. args.Set("owner", this->GetName());
  117. jumpPad = ( idJumpPad * )gameLocal.SpawnEntityType( idJumpPad::Type, &args );
  118. jumpPad->Bind(this, false);
  119. args.Clear();
  120. args.SetVector("origin", this->GetPhysics()->GetOrigin() + (forward * -16) + (up * 4) );
  121. args.Set("skin", "skins/cable/nophone_brown");
  122. args.Set("classname", spawnArgs.GetString("model_cable"));
  123. args.SetInt("isremote", 1);
  124. args.Set("master", this->GetName());
  125. gameLocal.SpawnEntityDef(args, &gatorEnt);
  126. gatorEnt->GetPhysics()->SetAxis(forward.ToMat3());
  127. gatorEnt->Bind( this, false );
  128. //gatorEnt->ApplyImpulse( gatorEnt, 13 , gatorEnt->GetPhysics()->GetOrigin(), idVec3(0, 0, 4096));
  129. //gatorEnt->GetPhysics()->SetLinearVelocity(idVec3(0,0,4096));
  130. args.Clear();
  131. args.SetVector("origin", this->GetPhysics()->GetOrigin());
  132. args.Set("classname", "moveable_launcherremote");
  133. gameLocal.SpawnEntityDef(args, &remoteEnt);
  134. args.Clear();
  135. args.SetVector("origin", this->GetPhysics()->GetOrigin());
  136. args.SetInt("solid", 0);
  137. args.SetBool("noclipmodel", 1);
  138. args.Set("model", spawnArgs.GetString("model_hitpoint"));
  139. hitpointEnt = ( idStaticEntity * )gameLocal.SpawnEntityType( idStaticEntity::Type, &args );
  140. //hitpointEnt->BecomeActive(TH_UPDATEVISUALS);
  141. hitpointEnt->Bind(this, false);
  142. args.Clear();
  143. args.SetVector("origin", this->GetPhysics()->GetOrigin());
  144. args.Set("classname", "env_launchermodel");
  145. gameLocal.SpawnEntityDef(args, &displaymodel);
  146. displaymodel->SetAxis(this->GetPhysics()->GetAxis());
  147. displaymodel->Bind(this, true);
  148. args.Clear();
  149. args.SetVector("origin", this->GetPhysics()->GetOrigin());
  150. args.Set("classname", "func_emitter");
  151. args.Set( "model", spawnArgs.GetString("smoke_fan") );
  152. gameLocal.SpawnEntityDef(args, &particles);
  153. particles->Bind(this, true);
  154. this->forcefieldIgnore = jumpPad;
  155. force = 192;
  156. launchDir = idVec3(-45, 0, 0);
  157. nextAimrecord = 0;
  158. remoteLerpStart = 0;
  159. remoteLerpEnd = 0;
  160. remoteRaiseLerp = 0;
  161. lastGametime = 0;
  162. for (i = 0;i < LINECOUNT; i++)
  163. {
  164. idDict args;
  165. args.Clear();
  166. args.SetVector("origin", this->GetPhysics()->GetOrigin());
  167. beamEnds[i] = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type, &args );
  168. args.Clear();
  169. args.Set("skin", "skins/beam_launcher");
  170. args.SetInt("width", BEAMWIDTH);
  171. args.SetVector("origin", this->GetPhysics()->GetOrigin());
  172. args.Set("target", beamEnds[i]->GetName() );
  173. beamStarts[i] = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type, &args );
  174. if (i > 0)
  175. {
  176. beamEnds[i]->Bind(this, false);
  177. beamStarts[i]->Bind(this, false);
  178. }
  179. }
  180. //bind first beam to launcher model.
  181. beamStarts[0]->SetOrigin(this->GetPhysics()->GetOrigin());
  182. beamStarts[0]->Bind(this, false);
  183. beamEnds[0]->SetOrigin(peakEnt->GetPhysics()->GetOrigin());
  184. beamEnds[0]->Bind(peakEnt, false);
  185. beamStarts[0]->BecomeActive(TH_PHYSICS);
  186. resettime_up = 0;
  187. resettime_down = 0;
  188. resettime_left = 0;
  189. resettime_right = 0;
  190. wheelMovetime = 0;
  191. wheelValue = 0;
  192. beamUpdateTime = 0;
  193. UpdateBeams();
  194. UpdateMultiplier();
  195. BecomeActive( TH_THINK );
  196. StartSound( "snd_idle", SND_CHANNEL_HEART, 0, false, NULL );
  197. }
  198. void idLauncher::SetLaunchDir(idVec3 newdir, float newForce)
  199. {
  200. launchDir = newdir;
  201. force = newForce;
  202. UpdateBeams();
  203. }
  204. void idLauncher::UpdateBeams( void )
  205. {
  206. int i;
  207. idAngles launchdirNormalized = idAngles(launchDir.x, launchDir.y, launchDir.z);
  208. idVec3 forward = launchdirNormalized.ToForward();
  209. idVec3 peakPos = forward * force;
  210. peakEnt->SetOrigin(peakPos);
  211. idAngles particleDir = forward.ToAngles();
  212. //particleDir.yaw += 180;
  213. particleDir.pitch = particleDir.pitch + 90;
  214. particles->GetPhysics()->SetAxis(particleDir.ToMat3());
  215. //determine whether first beam hits a wall.
  216. trace_t trPeak;
  217. peakEnt->Unbind();
  218. gameLocal.clip.TracePoint(trPeak,
  219. GetPhysics()->GetOrigin(),
  220. peakEnt->GetPhysics()->GetOrigin(),
  221. MASK_SOLID, this);
  222. peakEnt->Bind(this, true);
  223. if (trPeak.fraction < 1)
  224. {
  225. peakEnt->Unbind();
  226. peakEnt->SetOrigin(trPeak.endpos);
  227. peakEnt->Bind(this, true);
  228. hitpointEnt->Unbind();
  229. hitpointEnt->GetPhysics()->SetOrigin(trPeak.endpos);
  230. hitpointEnt->GetPhysics()->SetAxis(trPeak.c.normal.ToMat3());
  231. hitpointEnt->Bind(this, false);
  232. hitpointPos = trPeak.endpos;
  233. //hide the rest of the beams.
  234. for (i = 1; i < LINECOUNT; i++)
  235. {
  236. beamStarts[i]->Hide();
  237. }
  238. return;
  239. }
  240. //set up the first descent beam.
  241. idAngles beam1Normalized = idAngles(0, launchDir.y, 0);
  242. idVec3 forwardbeam1 = beam1Normalized.ToForward();
  243. float horizontalDist = idVec3(peakPos.x, peakPos.y, 0).Length();
  244. float verticalDist = peakPos.z;
  245. idVec3 lastPos = peakPos;
  246. bool placedHitpoint = false;
  247. for (i = 1; i < LINECOUNT; i++)
  248. {
  249. idVec3 endPos = lastPos + (forwardbeam1 * horizontalDist) + (idVec3(0,0,-1) * verticalDist);
  250. beamStarts[i]->SetOrigin(lastPos);
  251. beamEnds[i]->SetOrigin(endPos);
  252. lastPos = endPos;
  253. verticalDist = verticalDist * 2;
  254. }
  255. if (gameLocal.time > nextAimrecord)
  256. {
  257. nextAimrecord = gameLocal.time + 200;
  258. if (lastLaunchdir.x != launchDir.x || lastLaunchdir.y != launchDir.y || lastLaunchdir.z != launchDir.z
  259. || lastForce != force)
  260. {
  261. idEntity *recordEnt;
  262. recordEnt = gameLocal.FindEntity( "world1" );
  263. if (recordEnt)
  264. {
  265. int id = this->spawnArgs.GetInt("id", "-1");
  266. static_cast<idWorldManager *>( recordEnt )->RecordLaunchAim(id, launchDir, force);
  267. }
  268. lastLaunchdir.x = launchDir.x;
  269. lastLaunchdir.y = launchDir.y;
  270. lastLaunchdir.z = launchDir.z;
  271. lastForce = force;
  272. }
  273. }
  274. int lastValidTraceIndex = 0;
  275. for (i = 1; i < LINECOUNT; i++)
  276. {
  277. trace_t tr;
  278. gameLocal.clip.TracePoint(tr,
  279. beamStarts[i]->GetPhysics()->GetOrigin(),
  280. beamEnds[i]->GetPhysics()->GetOrigin(),
  281. MASK_SOLID, this);
  282. if (tr.fraction >= 1)
  283. continue;
  284. lastValidTraceIndex = i;
  285. hitpointEnt->Unbind();
  286. hitpointEnt->GetPhysics()->SetOrigin(tr.endpos);
  287. hitpointEnt->GetPhysics()->SetAxis(tr.c.normal.ToMat3());
  288. hitpointEnt->UpdateVisuals();
  289. hitpointEnt->Bind(this, false);
  290. hitpointPos = tr.endpos;
  291. beamEnds[i]->Unbind();
  292. beamEnds[i]->GetPhysics()->SetOrigin(tr.endpos);
  293. beamEnds[i]->Bind(this, true);
  294. break;
  295. }
  296. for (i = 0; i < LINECOUNT; i++)
  297. {
  298. if (i > lastValidTraceIndex)
  299. beamStarts[i]->Hide();
  300. else
  301. beamStarts[i]->Show();
  302. }
  303. }
  304. void idLauncher::OnFrob( idEntity* activator )
  305. {
  306. gameLocal.GetLocalPlayer()->Event_usePicker(gatorEnt);
  307. }
  308. void idLauncher::OnYaw(int value)
  309. {
  310. launchDir.y += value * YAW_STEP;
  311. idAngles ang = displaymodel->GetPhysics()->GetAxis().ToAngles();
  312. ang.yaw = launchDir.y;
  313. jointHandle_t jointHandle;
  314. jointHandle = displaymodel->GetAnimator()->GetJointHandle( "body" );
  315. static_cast< idAnimatedEntity * >( displaymodel )->GetAnimator()->SetJointAxis(jointHandle, JOINTMOD_WORLD, ang.ToMat3());
  316. if (value > 0)
  317. {
  318. MoveBone("a", idVec3(-0.7f,0,0));
  319. if (resettime_right < gameLocal.time)
  320. {
  321. remoteEnt->StartSound( "snd_button", SND_CHANNEL_ANY, 0, false, NULL );
  322. }
  323. resettime_right = gameLocal.time + RESETTIME;
  324. }
  325. else
  326. {
  327. MoveBone("d", idVec3(-0.7f,0,0));
  328. if (resettime_left < gameLocal.time)
  329. {
  330. remoteEnt->StartSound( "snd_button", SND_CHANNEL_ANY, 0, false, NULL );
  331. }
  332. resettime_left = gameLocal.time + RESETTIME;
  333. }
  334. UpdateBeams();
  335. }
  336. void idLauncher::OnPitch(int value)
  337. {
  338. bool playError = false;
  339. launchDir.x += value;
  340. if (launchDir.x < MAX_PITCH)
  341. {
  342. launchDir.x = MAX_PITCH;
  343. playError = true;
  344. }
  345. else if (launchDir.x > MIN_PITCH)
  346. {
  347. launchDir.x = MIN_PITCH;
  348. playError = true;
  349. }
  350. if (value > 0)
  351. {
  352. MoveBone("w", idVec3(-0.7f,0,0));
  353. if (resettime_up < gameLocal.time)
  354. {
  355. remoteEnt->StartSound( "snd_button", SND_CHANNEL_ANY, 0, false, NULL );
  356. }
  357. resettime_up = gameLocal.time + RESETTIME;
  358. }
  359. else
  360. {
  361. MoveBone("s", idVec3(-0.7f,0,0));
  362. if (resettime_down < gameLocal.time)
  363. {
  364. remoteEnt->StartSound( "snd_button", SND_CHANNEL_ANY, 0, false, NULL );
  365. }
  366. resettime_down = gameLocal.time + RESETTIME;
  367. }
  368. if (playError)
  369. {
  370. remoteEnt->StartSound( "snd_error", SND_CHANNEL_ANY, 0, false, NULL );
  371. }
  372. UpdateBeams();
  373. }
  374. void idLauncher::OnWheelMove(int value)
  375. {
  376. bool playError = false;
  377. force += WHEEL_STEP * value;
  378. if (force > MAX_FORCE)
  379. {
  380. force = MAX_FORCE;
  381. playError = true;
  382. }
  383. else if (force < MIN_FORCE)
  384. {
  385. force = MIN_FORCE;
  386. playError = true;
  387. }
  388. if (value < 0)
  389. wheelMovedir = WHEELSPEED;
  390. else
  391. wheelMovedir = -WHEELSPEED;
  392. if (wheelMovetime < gameLocal.time)
  393. {
  394. remoteEnt->StartSound( "snd_dial", SND_CHANNEL_ANY, 0, false, NULL );
  395. }
  396. if (playError)
  397. {
  398. remoteEnt->StartSound( "snd_error", SND_CHANNEL_ANY, 0, false, NULL );
  399. }
  400. wheelMovetime = gameLocal.time + WHEELTIME;
  401. UpdateBeams();
  402. UpdateMultiplier();
  403. }
  404. void idLauncher::UpdateMultiplier()
  405. {
  406. //magic numbers hack........
  407. //determine force based on mousewheel power.
  408. float forceLerp = (force - MIN_FORCE) / (float)(MAX_FORCE - MIN_FORCE);
  409. float forceMultiplier = idMath::Lerp(MULTIPLIER_MIN, MULTIPLIER_MAX, forceLerp);
  410. //adjust force based on altitude delta.
  411. float altitudeDelta = this->GetPhysics()->GetOrigin().z - hitpointPos.z;
  412. float altitude_minMultiplier = 0.75f;
  413. float altitude_maxMultiplier = 1.0f;
  414. float altitude_distanceThreshold = 384.0f;
  415. if (altitudeDelta <= 0)
  416. {
  417. forceMultiplier *= altitude_minMultiplier;
  418. }
  419. else if (altitudeDelta >= altitude_distanceThreshold)
  420. {
  421. //use 100% force, so do nothing here.
  422. }
  423. else
  424. {
  425. //scale the force.
  426. float altitudeLerp = altitudeDelta / altitude_distanceThreshold;
  427. float scaleAmount = idMath::Lerp(altitude_minMultiplier, altitude_maxMultiplier, altitudeLerp);
  428. forceMultiplier *= scaleAmount;
  429. }
  430. jumpPad->Event_UpdateMultiplier(forceMultiplier);
  431. //common->Printf("new force multiplier: %f\n", forceMultiplier);
  432. }
  433. void idLauncher::MoveBone(const char *bonename, idVec3 direction)
  434. {
  435. jointHandle_t jointHandle;
  436. jointHandle = remoteEnt->GetAnimator()->GetJointHandle( bonename );
  437. static_cast< idAnimatedEntity * >( remoteEnt )->GetAnimator()->SetJointPos(jointHandle, JOINTMOD_LOCAL, direction);
  438. }
  439. idVec3 idLauncher::GetGatorPos( void )
  440. {
  441. jointHandle_t jointHandle;
  442. idVec3 jointPos;
  443. idMat3 jointAxis;
  444. jointHandle = gatorEnt->GetAnimator()->GetJointHandle( "bone16" );
  445. static_cast< idAnimatedEntity * >(gatorEnt)->GetJointWorldTransform(jointHandle, gameLocal.time, jointPos, jointAxis );
  446. return jointPos;
  447. }
  448. void idLauncher::Think( void )
  449. {
  450. int i;
  451. jumpPad->Event_UpdatePeak();
  452. if (gameLocal.time > resettime_up)
  453. {
  454. MoveBone("w", idVec3(0,0,0));
  455. }
  456. if (gameLocal.time > resettime_down)
  457. {
  458. MoveBone("s", idVec3(0,0,0));
  459. }
  460. if (gameLocal.time > resettime_left)
  461. {
  462. MoveBone("a", idVec3(0,0,0));
  463. }
  464. if (gameLocal.time > resettime_right)
  465. {
  466. MoveBone("d", idVec3(0,0,0));
  467. }
  468. if (gameLocal.time < wheelMovetime)
  469. {
  470. wheelValue += wheelMovedir;
  471. idAngles ang;
  472. ang.pitch = wheelValue;
  473. ang.yaw = 0;
  474. ang.roll = 0;
  475. jointHandle_t jointHandle;
  476. jointHandle = remoteEnt->GetAnimator()->GetJointHandle( "wheel" );
  477. static_cast< idAnimatedEntity * >( remoteEnt )->GetAnimator()->SetJointAxis(jointHandle, JOINTMOD_LOCAL, ang.ToMat3());
  478. }
  479. if (gameLocal.GetLocalPlayer()->Event_isHolding(gatorEnt))
  480. {
  481. if (remoteRaiseLerp <= 0)
  482. {
  483. baseGatorPos = GetGatorPos();
  484. }
  485. remoteRaiseLerp += gameLocal.time - lastGametime;
  486. if (remoteRaiseLerp >= RISETIME)
  487. {
  488. remoteRaiseLerp = RISETIME;
  489. }
  490. if (remoteEnt->IsBound())
  491. {
  492. remoteEnt->Unbind();
  493. }
  494. //gameLocal.GetLocalPlayer()->viewAngles
  495. idAngles remoteAng = gameLocal.GetLocalPlayer()->viewAngles;
  496. remoteAng.yaw += 180;
  497. remoteAng.pitch *= -1;
  498. remoteAng.pitch += 3 * idMath::Sin(gameLocal.time * 0.0005f); //sway
  499. remoteAng.yaw += 5 * idMath::Sin(gameLocal.time * 0.0003f); //sway
  500. remoteEnt->SetAngles( remoteAng );
  501. idVec3 up;
  502. remoteAng.ToVectors( NULL, NULL, &up );
  503. idVec3 finalPos = gameLocal.GetLocalPlayer()->GetEyePosition() + (gameLocal.GetLocalPlayer()->viewAngles.ToForward() * 6) + (up * -3.8f );
  504. if (remoteRaiseLerp < RISETIME)
  505. {
  506. //is raising.
  507. float amt = remoteRaiseLerp / RISETIME;
  508. finalPos.x = idMath::Lerp(baseGatorPos.x, finalPos.x, amt);
  509. finalPos.y = idMath::Lerp(baseGatorPos.y, finalPos.y, amt);
  510. finalPos.z = idMath::Lerp(baseGatorPos.z, finalPos.z, amt);
  511. }
  512. //remoteEnt->SetOrigin( gameLocal.GetLocalPlayer()->GetEyePosition() + (gameLocal.GetLocalPlayer()->viewAngles.ToForward() * 6) + (up * -3.8f ));
  513. remoteEnt->SetOrigin(finalPos);
  514. }
  515. else
  516. {
  517. remoteRaiseLerp -= gameLocal.time - lastGametime;
  518. if (remoteRaiseLerp <= 0)
  519. {
  520. remoteRaiseLerp = 0;
  521. }
  522. if (!remoteEnt->IsBound())
  523. {
  524. idVec3 jointPos = GetGatorPos();
  525. jointHandle_t jointHandle;
  526. jointHandle = gatorEnt->GetAnimator()->GetJointHandle( "bone16" );
  527. remoteEnt->SetOrigin(jointPos);
  528. remoteEnt->BindToJoint(gatorEnt, jointHandle, true);
  529. }
  530. }
  531. //common->Printf("%f\n", remoteRaiseLerp);
  532. lastGametime = gameLocal.time;
  533. if (gameLocal.time > beamUpdateTime)
  534. {
  535. beamUpdateTime = gameLocal.time + 300;
  536. UpdateBeams();
  537. }
  538. //RunPhysics();
  539. idMoveableItem::Think();
  540. //idMoveableItem::Present();
  541. }
  542. void idLauncher::OnGet( void )
  543. {
  544. StopSound( SND_CHANNEL_HEART, false );
  545. StopSound( SND_CHANNEL_ANY, false );
  546. //particle effect.
  547. idDict args;
  548. args.Clear();
  549. args.SetVector( "origin", GetPhysics()->GetOrigin());
  550. args.Set( "model", spawnArgs.GetString("smoke_pickup") );
  551. args.SetBool( "start_off", false );
  552. gameLocal.SpawnEntityType( idExplodable::Type, &args );
  553. hitpointEnt->PostEventMS( &EV_Remove, 0 );
  554. this->PostEventMS( &EV_Remove, 0 );
  555. gameLocal.GetLocalPlayer()->GiveInventoryItem("weapon_launcher");
  556. gameLocal.GetLocalPlayer()->GiveInventoryItem("ammo_launchers_small");
  557. gameLocal.GetLocalPlayer()->StartSound( "snd_get" , SND_CHANNEL_ANY, 0, false, NULL );
  558. }
  559. void idLauncher::launcherkill( void )
  560. {
  561. StopSound( SND_CHANNEL_HEART, false );
  562. StopSound( SND_CHANNEL_ANY, false );
  563. }