picker.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. //bc copied from the Grabber weapon.
  2. #include "../idlib/precompiled.h"
  3. #pragma hdrstop
  4. #include "Game_local.h"
  5. #include "Misc.h"
  6. #define MAX_DRAG_TRACE_DISTANCE 80.0f
  7. #define DRAG_FAIL_LEN 64.f
  8. #define THROW_SCALE 384 //throwing speed
  9. #define FIRING_DELAY 100.0f
  10. #define TRACE_BOUNDS_SIZE 3.f
  11. #define MAX_PICKUP_VELOCITY 1500 * 1500
  12. #define MAX_PICKUP_SIZE 96
  13. #define HOLD_DISTANCE_DEFAULT 32
  14. #define HOLD_DISTANCE_MIN 20
  15. #define HOLD_DISTANCE_MAX 50
  16. #define THROW_TIME_THRESHOLD 400 //if player holds left button down for this much milliseconds, then throw the held item.
  17. #define PICKUP_TIME_THRESHOLD 350 //if player holds left button down for this much milliseconds, then throw the held item.
  18. CLASS_DECLARATION( idEntity, idPicker )
  19. END_CLASS
  20. idPicker::idPicker( void )
  21. {
  22. dragEnt = NULL;
  23. owner = NULL;
  24. oldUcmdFlags = 0;
  25. holdingAF = false;
  26. dragFailTime = 0;
  27. startDragTime = 0;
  28. dragTraceDist = MAX_DRAG_TRACE_DISTANCE;
  29. holdDistance = HOLD_DISTANCE_DEFAULT;
  30. pickerHeld = false;
  31. this->attacktimerStart = 0;
  32. this->attackHeld = false;
  33. this->pickuptimerStart = 0;
  34. this->pickerHeld = false;
  35. this->holdstate = 0;
  36. rotationIndex = -1;
  37. rotationAngleStart = 0;
  38. rotationAngleEnd = 0;
  39. rotationTimeStart = 0;
  40. rotationTimeEnd = 0;
  41. }
  42. idPicker::~idPicker( void )
  43. {
  44. }
  45. void idPicker::Save( idSaveGame *savefile ) const
  46. {
  47. owner.Save(savefile);
  48. dragEnt.Save(savefile);
  49. savefile->WriteBool(attackHeld);
  50. savefile->WriteInt(attacktimerStart);
  51. savefile->WriteStaticObject( drag );
  52. savefile->WriteInt( id );
  53. savefile->WriteInt(pickuptimerStart);
  54. savefile->WriteInt(holdstate);
  55. savefile->WriteInt(holdDistance);
  56. savefile->WriteVec3(saveGravity);
  57. savefile->WriteInt(oldUcmdFlags);
  58. savefile->WriteVec3(localPlayerPoint);
  59. savefile->WriteInt(dragFailTime);
  60. savefile->WriteInt(startDragTime);
  61. savefile->WriteBool(holdingAF);
  62. savefile->WriteBool(pickerHeld);
  63. savefile->WriteFloat(dragTraceDist);
  64. savefile->WriteInt(rotationIndex);
  65. savefile->WriteInt(rotationAngleStart);
  66. savefile->WriteInt(rotationAngleEnd);
  67. savefile->WriteInt(rotationTimeStart);
  68. savefile->WriteInt(rotationTimeEnd);
  69. }
  70. void idPicker::Restore( idRestoreGame *savefile )
  71. {
  72. owner.Restore(savefile);
  73. dragEnt.Restore(savefile);
  74. savefile->ReadBool(attackHeld);
  75. savefile->ReadInt(attacktimerStart);
  76. savefile->ReadStaticObject( drag );
  77. savefile->ReadInt(id);
  78. savefile->ReadInt(pickuptimerStart);
  79. savefile->ReadInt(holdstate);
  80. savefile->ReadInt(holdDistance);
  81. savefile->ReadVec3(saveGravity);
  82. savefile->ReadInt(oldUcmdFlags);
  83. savefile->ReadVec3(localPlayerPoint);
  84. savefile->ReadInt(dragFailTime);
  85. savefile->ReadInt(startDragTime);
  86. savefile->ReadBool(holdingAF);
  87. savefile->ReadBool(pickerHeld);
  88. savefile->ReadFloat(dragTraceDist);
  89. savefile->ReadInt(rotationIndex);
  90. savefile->ReadInt(rotationAngleStart);
  91. savefile->ReadInt(rotationAngleEnd);
  92. savefile->ReadInt(rotationTimeStart);
  93. savefile->ReadInt(rotationTimeEnd);
  94. }
  95. void idPicker::SetDragDistance( float dist ) {
  96. dragTraceDist = dist;
  97. }
  98. //adjust how far/close the object is to the player.
  99. void idPicker::SetHoldDistance( int delta )
  100. {
  101. idPlayer *thePlayer = owner.GetEntity();
  102. int minDistance = HOLD_DISTANCE_MIN;
  103. if (dragEnt.GetEntity() != NULL)
  104. {
  105. int holdDistanceMin = dragEnt.GetEntity()->spawnArgs.GetInt("holddistancemin");
  106. if (holdDistanceMin > 0)
  107. {
  108. minDistance = holdDistanceMin;
  109. }
  110. }
  111. this->holdDistance += delta;
  112. this->holdDistance = idMath::ClampInt(minDistance, HOLD_DISTANCE_MAX, this->holdDistance);
  113. localPlayerPoint = ( thePlayer->firstPersonViewAxis[0] * holdDistance ) * thePlayer->firstPersonViewAxis.Transpose();
  114. }
  115. void idPicker::StartDrag( idEntity *grabEnt, int id ) {
  116. int clipModelId = id;
  117. idPlayer *thePlayer = owner.GetEntity();
  118. this->rotationIndex = -1;
  119. holdingAF = false;
  120. dragFailTime = gameLocal.slow.time;
  121. startDragTime = gameLocal.slow.time;
  122. oldUcmdFlags = thePlayer->usercmd.flags;
  123. // set grabbed state for networking
  124. grabEnt->SetGrabbedState( true );
  125. // This is the new object to drag around
  126. dragEnt = grabEnt;
  127. // Handle specific class types
  128. if ( grabEnt->IsType( idAI::Type ) )
  129. {
  130. idAI *aiEnt = static_cast<idAI*>(grabEnt);
  131. //aiEnt->Damage( thePlayer, thePlayer, vec3_origin, "damage_suicide", 1.0f, INVALID_JOINT );
  132. aiEnt->StartRagdoll();
  133. holdingAF = true;
  134. clipModelId = 0;
  135. }
  136. else if ( grabEnt->IsType( idAFEntity_Base::Type ) )
  137. {
  138. holdingAF = true;
  139. //clipModelId = 0;
  140. }
  141. else if ( grabEnt->IsType( idMoveableItem::Type ) )
  142. {
  143. if (static_cast<idMoveableItem*>(grabEnt)->frozen > 0)
  144. {
  145. if (static_cast<idMoveableItem*>(grabEnt)->frozen == 1)
  146. {
  147. grabEnt->StartSound( "snd_unfreeze", SND_CHANNEL_ANY, 0, false, NULL );
  148. }
  149. static_cast<idMoveableItem*>(grabEnt)->frozen = 2;
  150. grabEnt->Unbind();
  151. }
  152. grabEnt->PostEventMS( &EV_Touch, 250, thePlayer, NULL );
  153. }
  154. // Get the current physics object to manipulate
  155. idPhysics *phys = grabEnt->GetPhysics();
  156. // Turn off gravity on object
  157. //if ( !holdingAF )
  158. {
  159. //saveGravity = phys->GetGravity();
  160. //saveGravity = gameLocal.GetGravity();
  161. //phys->SetGravity( vec3_origin );
  162. //phys->
  163. }
  164. //find distance between object and player eyeball.
  165. float distanceToObject = ( thePlayer->firstPersonViewOrigin - grabEnt->GetPhysics()->GetOrigin() ).Normalize();
  166. if ( grabEnt->spawnArgs.GetInt( "isremote", "0" ) )
  167. {
  168. holdDistance = dragEnt.GetEntity()->spawnArgs.GetInt( "remote_x", "12" );
  169. }
  170. else if (distanceToObject < HOLD_DISTANCE_DEFAULT)
  171. {
  172. holdDistance = distanceToObject - 1;
  173. }
  174. else
  175. {
  176. //hold distance default override.
  177. int holddistOverride = grabEnt->spawnArgs.GetInt( "holddistance", "32" );
  178. holdDistance = holddistOverride;
  179. }
  180. // hold it directly in front of player
  181. localPlayerPoint = ( thePlayer->firstPersonViewAxis[0] * holdDistance ) * thePlayer->firstPersonViewAxis.Transpose();
  182. // Start up the Force_Drag to bring it in
  183. drag.Init( g_grabberDamping.GetFloat() );
  184. drag.SetPhysics( phys, clipModelId, thePlayer->firstPersonViewOrigin + localPlayerPoint * thePlayer->firstPersonViewAxis);
  185. attackHeld = true;
  186. pickerHeld = true;
  187. thePlayer->StartSound("snd_grab", SND_CHANNEL_WEAPON, 0, false, NULL);
  188. //bc 8-13-2015
  189. grabEnt->StartSound( "snd_onpick", SND_CHANNEL_ANY, 0, false, NULL );
  190. }
  191. void idPicker::StopDrag( bool dropOnly, bool isRightClick )
  192. {
  193. idPlayer *thePlayer = owner.GetEntity();
  194. if ( dragEnt.IsValid() )
  195. {
  196. idEntity *ent = dragEnt.GetEntity();
  197. // set grabbed state for networking
  198. ent->SetGrabbedState( false );
  199. // If a cinematic has started, let dropped object to think in cinematics
  200. if ( gameLocal.inCinematic ) {
  201. ent->cinematic = true;
  202. }
  203. // Restore Gravity
  204. if ( !holdingAF )
  205. {
  206. //ent->GetPhysics()->SetGravity( saveGravity );
  207. }
  208. // Move the object back to the slow group (helltime)
  209. ent->timeGroup = TIME_GROUP1;
  210. if ( holdingAF )
  211. {
  212. idAFEntity_Base *af = static_cast<idAFEntity_Base *>(ent);
  213. idPhysics_AF *af_Phys = static_cast<idPhysics_AF*>(af->GetPhysics());
  214. // Reset timers so that it isn't forcibly put to rest in mid-air
  215. af_Phys->PutToRest();
  216. af_Phys->Activate();
  217. af_Phys->SetTimeScaleRamp( MS2SEC(gameLocal.slow.time) - 1.5f, MS2SEC(gameLocal.slow.time) + 1.0f );
  218. }
  219. ent->lastThrowTime = gameLocal.time; //for the security turret. if player throws or drops an item, mark it as a turret target.
  220. // If the object isn't near its goal, just drop it in place.
  221. if ( !ent->IsType( idProjectile::Type ) && ( dropOnly || drag.GetDistanceToGoal() > DRAG_FAIL_LEN ) )
  222. {
  223. ent->GetPhysics()->SetLinearVelocity( vec3_origin );
  224. thePlayer->StartSound("snd_maindrop", SND_CHANNEL_WEAPON, 0, false, NULL);
  225. ent->StartSound( "snd_onunpick", SND_CHANNEL_ANY, 0, false, NULL );
  226. }
  227. else
  228. {
  229. // Shoot the object forward
  230. ent->ApplyImpulse( thePlayer, 0, ent->GetPhysics()->GetOrigin(), (thePlayer->firstPersonViewAxis[0] + idVec3(0, 0, 0.6f)) * THROW_SCALE * ent->GetPhysics()->GetMass() );
  231. thePlayer->StartSound("snd_release", SND_CHANNEL_WEAPON, 0, false, NULL);
  232. ent->StartSound( "snd_onunpick", SND_CHANNEL_ANY, 0, false, NULL );
  233. // Orient projectiles away from the player
  234. if ( ent->IsType( idMoveable::Type ) )
  235. {
  236. // Turn on damage for this object
  237. //idMoveable *obj = static_cast<idMoveable*>(ent);
  238. //obj->EnableDamage( true, 2.5f );
  239. //obj->SetAttacker( thePlayer );
  240. }
  241. /*
  242. else if ( ent->IsType( idMoveableItem::Type ) )
  243. {
  244. }
  245. */
  246. }
  247. // Remove the Force_Drag's control of the entity
  248. drag.RemovePhysics( ent->GetPhysics() );
  249. //if it's a remote, then call the onDrop call. onDrop triggers the selected item on the BlueBox.
  250. if ( dragEnt.GetEntity()->spawnArgs.GetInt( "isremote", "0" ))
  251. {
  252. if (thePlayer->launcherEnt.IsValid())
  253. {
  254. if (isRightClick)
  255. {
  256. //Execute the line.
  257. thePlayer->UseFrob( thePlayer->launcherEnt.GetEntity(), "onDrop");
  258. thePlayer->pickerHeld = true;
  259. if (thePlayer->launcherEnt.GetEntity()->IsType(idBluebox::Type))
  260. {
  261. static_cast<idBluebox *>( thePlayer->launcherEnt.GetEntity() )->OnExecute();
  262. }
  263. }
  264. else
  265. {
  266. //I just right clicked!!
  267. if (thePlayer->launcherEnt.GetEntity()->IsType(idBluebox::Type))
  268. {
  269. static_cast<idBluebox *>( thePlayer->launcherEnt.GetEntity() )->OnDrop();
  270. }
  271. }
  272. }
  273. }
  274. }
  275. dragEnt = NULL;
  276. this->holdstate = 2;
  277. /*
  278. if ( !(thePlayer->usercmd.buttons & BUTTON_PICKER) )
  279. {
  280. pickerHeld = false;
  281. }
  282. else
  283. {
  284. pickerHeld = true;
  285. }
  286. if ( !(thePlayer->usercmd.buttons & BUTTON_ATTACK) )
  287. {
  288. attackHeld = false;
  289. }
  290. else
  291. {
  292. attackHeld = true;
  293. }*/
  294. }
  295. int idPicker::UpdateHeld( idPlayer *player )
  296. {
  297. //if not holding anything.
  298. if (!dragEnt.GetEntity())
  299. {
  300. if ( !(player->usercmd.buttons & BUTTON_ATTACK) && attackHeld )
  301. {
  302. attackHeld = false;
  303. }
  304. return 0;
  305. }
  306. idPhysics *entPhys = dragEnt.GetEntity()->GetPhysics();
  307. idVec3 goalPos;
  308. if (this->holdstate == 0 && dragEnt.GetEntity() && pickerHeld == false && attackHeld == false )
  309. {
  310. this->holdstate = 1;
  311. }
  312. //holding an item.
  313. if (this->holdstate == 1)
  314. {
  315. if (player->usercmd.buttons & BUTTON_ATTACK)
  316. {
  317. if (!attackHeld)
  318. {
  319. this->attackHeld = true;
  320. this->attacktimerStart = gameLocal.time;
  321. //player->DebugMessage(va("uheld %d %d", this->attacktimerStart, gameLocal.time));
  322. }
  323. if (attacktimerStart + 400 < gameLocal.time)
  324. {
  325. //throw.
  326. player->StartSound("snd_exhale", SND_CHANNEL_ANY, 0, false, NULL);
  327. StopDrag( false, false );
  328. this->holdstate = 2;
  329. return 3;
  330. }
  331. }
  332. else if ( !(player->usercmd.buttons & BUTTON_ATTACK) && attackHeld)
  333. {
  334. this->attackHeld = false;
  335. if (attacktimerStart + 400 >= gameLocal.time)
  336. {
  337. //tap.
  338. //drop.
  339. StopDrag( true, true );
  340. this->holdstate = 2;
  341. return 3;
  342. }
  343. }
  344. int rotationSteps[8] = {180, 225, 270, 315, 0, 45, 90, 135 };
  345. if (dragEnt.IsValid())
  346. {
  347. if (dragEnt.GetEntity()->spawnArgs.GetInt("alt_rotation", "0") > 0)
  348. {
  349. rotationSteps[0] = 0;
  350. rotationSteps[1] = 45;
  351. rotationSteps[2] = 90;
  352. rotationSteps[3] = 135;
  353. rotationSteps[4] = 180;
  354. rotationSteps[5] = 225;
  355. rotationSteps[6] = 270;
  356. rotationSteps[7] = 315;
  357. }
  358. }
  359. if (player->usercmd.buttons & BUTTON_PICKER && !pickerHeld)
  360. {
  361. //pickerWeapon.dragEnt.GetEntity()->spawnArgs.GetInt( "isremote", "0" ) )
  362. //Remote (bluebox) special case.
  363. if (dragEnt.GetEntity()->spawnArgs.GetInt( "isremote", "0"))
  364. {
  365. idPlayer *thePlayer = owner.GetEntity();
  366. StopDrag(true, false); //right click. drop.
  367. thePlayer->pickerHeld = true;
  368. return 0;
  369. }
  370. pickerHeld = true;
  371. //rotate
  372. player->StartSound("snd_rotate", SND_CHANNEL_ANY, 0, false, NULL );
  373. rotationAngleStart = this->rotationIndex;
  374. if (rotationAngleStart < 0)
  375. rotationAngleStart = 0;
  376. int rotationSlots = sizeof(rotationSteps) / sizeof(int);
  377. this->rotationIndex++;
  378. if (this->rotationIndex >= rotationSlots)
  379. {
  380. this->rotationIndex = 0;
  381. }
  382. rotationAngleEnd = this->rotationIndex;
  383. rotationTimeStart = gameLocal.time;
  384. rotationTimeEnd = gameLocal.time + 100;
  385. }
  386. if (this->rotationIndex >= 0 && !holdingAF)
  387. {
  388. float lerpAmount;
  389. if (gameLocal.time >= rotationTimeEnd)
  390. {
  391. lerpAmount = 1;
  392. }
  393. else
  394. {
  395. lerpAmount = (gameLocal.time - rotationTimeStart) / 100.0f;
  396. }
  397. float lerpAng = idMath::Lerp(rotationSteps[rotationAngleStart], rotationSteps[rotationAngleEnd], lerpAmount);
  398. if (rotationSteps[rotationAngleStart] > rotationSteps[rotationAngleEnd])
  399. {
  400. //hack to resolve lerp weirdness when going from a big number to a small number.
  401. lerpAng = idMath::Lerp(rotationSteps[rotationAngleEnd] - 45, rotationSteps[rotationAngleEnd], lerpAmount);
  402. }
  403. //if (gameLocal.time < rotationTimeEnd)
  404. //common->Printf("%f %f \n", lerpAmount, lerpAng);
  405. idAngles ang = player->firstPersonViewAxis[0].ToAngles();
  406. ang.roll = 0.f;
  407. ang.pitch = 0.f;
  408. ang.yaw += lerpAng;
  409. entPhys->SetAxis( ang.ToMat3() );
  410. /*
  411. int angleToAdd = rotationSteps[this->rotationIndex];
  412. //orient the object.
  413. idAngles ang = player->firstPersonViewAxis[0].ToAngles();
  414. ang.roll = 0.f;
  415. ang.pitch = 0.f;
  416. ang.yaw += angleToAdd;
  417. entPhys->SetAxis( ang.ToMat3() );
  418. */
  419. }
  420. /*
  421. if (player->usercmd.buttons & BUTTON_PICKER)
  422. {
  423. if (!pickerHeld)
  424. {
  425. this->pickerHeld = true;
  426. this->pickuptimerStart = gameLocal.time;
  427. }
  428. if (pickuptimerStart + 400 < gameLocal.time)
  429. {
  430. //drop.
  431. StopDrag( true, false );
  432. this->holdstate = 2;
  433. return 3;
  434. }
  435. }
  436. else if ( !(player->usercmd.buttons & BUTTON_PICKER) && pickerHeld)
  437. {
  438. this->pickerHeld = false;
  439. if (pickuptimerStart + 400 >= gameLocal.time)
  440. {
  441. //Get.
  442. player->PerformImpulse(41);
  443. this->holdstate = 2;
  444. return 0;
  445. }
  446. }*/
  447. }
  448. //Handle object physics
  449. //=================================================================
  450. // Check if the player is standing on the object.
  451. if ( !holdingAF && dragEnt.GetEntity()->IsType( idMoveable::Type ))
  452. {
  453. idBounds playerBounds;
  454. idBounds objectBounds = entPhys->GetAbsBounds();
  455. idVec3 newPoint = player->GetPhysics()->GetOrigin();
  456. // create a bounds at the players feet
  457. playerBounds.Clear();
  458. playerBounds.AddPoint( newPoint );
  459. newPoint.z -= 1.f;
  460. playerBounds.AddPoint( newPoint );
  461. playerBounds.ExpandSelf( 8.f );
  462. // If it intersects the object bounds, then drop it
  463. if ( playerBounds.IntersectsBounds( objectBounds ) )
  464. {
  465. StopDrag( true, false );
  466. player->StartSound( "snd_error", SND_CHANNEL_ANY, 0, false, NULL );
  467. player->Event_hudMessage( common->GetLanguageDict()->GetString( "#str_02116" ) );
  468. return 3;
  469. }
  470. }
  471. // Set and evaluate drag force
  472. goalPos = player->firstPersonViewOrigin + localPlayerPoint * player->firstPersonViewAxis;
  473. if (holdingAF)
  474. {
  475. if ( dragEnt.GetEntity()->spawnArgs.GetInt( "isremote", "0" ) )
  476. {
  477. goalPos.z += dragEnt.GetEntity()->spawnArgs.GetInt( "remote_z", "2" );
  478. }
  479. else
  480. {
  481. int holdheight = dragEnt.GetEntity()->spawnArgs.GetInt( "holdheight", "4" );
  482. goalPos.z += holdheight; //held AFs look better when they're elevated up a bit.
  483. }
  484. }
  485. drag.SetGoalPosition( goalPos );
  486. drag.Evaluate( gameLocal.time );
  487. // If an object is flying too fast toward the player, stop it hard
  488. if ( g_grabberHardStop.GetBool() )
  489. {
  490. idPlane theWall;
  491. idVec3 toPlayerVelocity, objectCenter;
  492. float toPlayerSpeed;
  493. toPlayerVelocity = -player->firstPersonViewAxis[0];
  494. toPlayerSpeed = entPhys->GetLinearVelocity() * toPlayerVelocity;
  495. if ( toPlayerSpeed > 64.f )
  496. {
  497. objectCenter = entPhys->GetAbsBounds().GetCenter();
  498. theWall.SetNormal( player->firstPersonViewAxis[0] );
  499. theWall.FitThroughPoint( goalPos );
  500. if ( theWall.Side( objectCenter, 0.1f ) == PLANESIDE_BACK ) {
  501. int i, num;
  502. num = entPhys->GetNumClipModels();
  503. for ( i=0; i<num; i++ ) {
  504. entPhys->SetLinearVelocity( vec3_origin, i );
  505. }
  506. }
  507. }
  508. idVec3 angVel;
  509. angVel.x = 0;
  510. angVel.y = 0;
  511. angVel.z = 0;
  512. entPhys->SetAngularVelocity( angVel );
  513. }
  514. //=================================================================
  515. if ( !(player->usercmd.buttons & BUTTON_PICKER) && pickerHeld )
  516. {
  517. pickerHeld = false;
  518. }
  519. if ( !(player->usercmd.buttons & BUTTON_ATTACK) && attackHeld )
  520. {
  521. attackHeld = false;
  522. }
  523. if (this->holdstate > 0 && dragEnt.GetEntity() && dragEnt.GetEntity()->spawnArgs.GetInt("showhand", "1") <= 0 )
  524. {
  525. //BC 3-13-2016 add flag to hide finger. so that you can read letters.
  526. return 4;
  527. }
  528. else if (this->holdstate > 0 && dragEnt.GetEntity())
  529. {
  530. return 2;
  531. }
  532. return 0;
  533. }
  534. //Update return values:
  535. // 0 = holding nothing.
  536. // 1 = something valid in crosshair.
  537. // 2 = holding something.
  538. // 3 = dropped the object.
  539. int idPicker::Update( idPlayer *player, bool hide, idEntity *newEnt, int newEntID, bool forcePick )
  540. {
  541. // Dead players release the trigger
  542. if ( hide || player->health <= 0 )
  543. {
  544. StopDrag( true, false );
  545. return 3;
  546. }
  547. //player is HOLDING something. Do some checks to ensure it should still be held.
  548. if ( dragEnt.GetEntity() )
  549. {
  550. return 2;
  551. }
  552. owner = player;
  553. if (this->holdstate == 2 && !(player->usercmd.buttons & BUTTON_PICKER)
  554. && !(player->usercmd.buttons & BUTTON_ATTACK))
  555. {
  556. this->holdstate = 0;
  557. }
  558. // if no entity selected for dragging. search for stuff that's grabbable.
  559. if ( !dragEnt.GetEntity() )
  560. {
  561. // If the trace hit something
  562. if ( newEnt )
  563. {
  564. // if entity is already being grabbed then bypass
  565. if ( gameLocal.isMultiplayer && newEnt->IsGrabbed() )
  566. {
  567. return 0;
  568. }
  569. // Check if this is a valid entity to hold
  570. if ( newEnt &&
  571. ( newEnt->IsType( idMoveable::Type )
  572. || newEnt->IsType( idMoveableItem::Type )
  573. || newEnt->IsType( idProjectile::Type )
  574. || newEnt->IsType( idStaticEntity::Type )
  575. || newEnt->IsType( idScrew::Type )
  576. || newEnt->IsType( idFrobCube::Type )
  577. || newEnt->IsType( idAFEntity_Base::Type ))
  578. && newEnt->noGrab == false
  579. //&& newEnt->GetPhysics()->GetBounds().GetRadius() < MAX_PICKUP_SIZE
  580. && newEnt->GetPhysics()->GetLinearVelocity().LengthSqr() < MAX_PICKUP_VELOCITY)
  581. {
  582. //bc 9-26-2015 gettable frobcubes can be right clicked
  583. if (newEnt->IsType(idFrobCube::Type) && player->usercmd.buttons & BUTTON_PICKER)
  584. {
  585. if (newEnt->spawnArgs.GetBool("gettable"))
  586. {
  587. static_cast<idFrobCube *>( newEnt )->OnFrob(this);
  588. }
  589. return 0;
  590. }
  591. //BC 4-15-2016 moveables can be gotten
  592. if (newEnt->IsType(idMoveableItem::Type) && player->usercmd.buttons & BUTTON_PICKER)
  593. {
  594. if (newEnt->spawnArgs.GetBool("stashable"))
  595. {
  596. gameLocal.GetLocalPlayer()->StartSound( "snd_get", SND_CHANNEL_ANY, 0, false, NULL );
  597. idDict args;
  598. args.Clear();
  599. args.SetVector( "origin", newEnt->GetPhysics()->GetOrigin() );
  600. args.Set( "model", "pickupdust.prt" );
  601. args.SetBool( "start_off", false );
  602. gameLocal.SpawnEntityType( idExplodable::Type, &args );
  603. newEnt->PostEventMS(&EV_Remove, 0 );
  604. return 0;
  605. }
  606. }
  607. bool validAF = true;
  608. if (player->usercmd.buttons & BUTTON_PICKER)
  609. {
  610. player->PerformImpulse(41); //GET item.
  611. }
  612. if ( !dragEnt.GetEntity() && this->holdstate == 0 && forcePick )
  613. {
  614. //hold the button. hold the item.
  615. StartDrag(newEnt, newEntID);
  616. player->UseFrob( newEnt, "onPick");
  617. }
  618. /*
  619. if ( validAF && (( (player->usercmd.buttons & BUTTON_PICKER) && (this->pickuptimerStart + pickupThreshold < gameLocal.time) && !dragEnt.GetEntity() ) || forcePick) && !attackHeld && !pickerHeld)
  620. {
  621. // Grab this entity and start dragging it around.
  622. StartDrag( newEnt, newEntID );
  623. player->UseFrob( newEnt, "onPick");
  624. this->pickuptimerStart = gameLocal.time;
  625. this->pickerHeld = true;
  626. }
  627. else if (!(player->usercmd.buttons & BUTTON_PICKER) && this->pickerHeld && (this->pickuptimerStart + pickupThreshold > gameLocal.time))
  628. {
  629. //if player taps the right click, then GET the item.
  630. this->pickerHeld = false;
  631. player->PerformImpulse(41); //GET item.
  632. }*/
  633. else if ( validAF )
  634. {
  635. // A holdable object is ready to be grabbed
  636. if (pickerHeld && !(player->usercmd.buttons & BUTTON_PICKER))
  637. {
  638. pickerHeld = false;
  639. }
  640. return 1;
  641. }
  642. }
  643. }
  644. if (pickerHeld && !(player->usercmd.buttons & BUTTON_PICKER))
  645. pickerHeld = false;
  646. if (attackHeld && !(player->usercmd.buttons & BUTTON_ATTACK))
  647. attackHeld = false;
  648. }
  649. if (dragEnt.GetEntity())
  650. return 2;
  651. // Not holding, nothing to hold
  652. return 0;
  653. }