PirateHearts

Eponymous main player class

Mar 5th, 2018
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 35.15 KB | None | 0 0
  1. #include "TulpaPlayer.h"
  2. #include "TulpaGame.h"
  3. #include "TulpaConstants.h"
  4. #include "NControllerComponent.h"
  5. #include "NPostureComponent.h"
  6. #include "EyeHeightComponent.h"
  7. #include "FocusComponent.h"
  8. #include "SprintComponent.h"
  9. #include "NCameraComponent.h"
  10. #include "NDebugLines.h"
  11. #include "NarrationComponent.h"
  12. #include "EditModeComponent.h"
  13. #include "ChimeComponent.h"
  14. #include "Door.h"
  15. #include "NLocMgr.h"
  16. #include "CamTrackComponent.h"
  17. #include "Trigger.h"
  18. #include "TwoTrigger.h"
  19. #include "CodexComponent.h"
  20.  
  21. TulpaPlayer::TulpaPlayer(EEnforcement) : Super(EE_Valid)
  22. {
  23. bCanPlayMantleFoley = true;
  24. }
  25.  
  26. TulpaPlayer::~TulpaPlayer()
  27. {
  28. }
  29.  
  30. bool TulpaPlayer::IsIndisposed()
  31. {
  32. return (IsIntroHappening() ||
  33. NMenuMgr::GetInstance()->IsAnyMenuOpen());
  34. }
  35.  
  36. bool TulpaPlayer::IsIntroHappening()
  37. {
  38. MAKESTRINGWITH(SubName1, "Game Intro (Chapter)");
  39. MAKESTRINGWITH(SubName2, "Game Intro (Fade)");
  40. MAKESTRINGWITH(SubName3, "Vinyl Scaling");
  41. return
  42. NSubroutineMgr::GetInstance()->IsSubroutineRunning(SubName1) ||
  43. NSubroutineMgr::GetInstance()->IsSubroutineRunning(SubName2)/* ||
  44. NSubroutineMgr::GetInstance()->IsSubroutineRunning(SubName3)*/;
  45. }
  46.  
  47. void TulpaPlayer::ReactToSurfaceType(const NHashedString& Type, const NCollisionResult& ThisHitRes)
  48. {
  49. Type, ThisHitRes;
  50. }
  51.  
  52. void TulpaPlayer::PostDefinition()
  53. {
  54. }
  55.  
  56. void TulpaPlayer::PostBuildEntity()
  57. {
  58. MAKESTRING(DevMode);
  59. if (NConfigFile::GetInstance()->Access(gNullStr, DevMode))
  60. {
  61. ChimeComponent* Chime = GetComponent<ChimeComponent>();
  62. if (Chime)
  63. {
  64. for (int i = 0; i < CA_MAX; ++i)
  65. {
  66. Chime->AddChime((ChimeAbility)(i), true);
  67. }
  68. }
  69.  
  70. CodexComponent* pCodex = GetComponent<CodexComponent>();
  71. if (pCodex)
  72. {
  73. pCodex->SetHasCodex(true);
  74. }
  75. }
  76.  
  77. NSpatialComponent* Space = GetComponent<NSpatialComponent>();
  78. if (Space)
  79. {
  80. //Space->Game_Curr.Position = NVec3(0,0,4) * VOXEL_SCALE;
  81. //Space->Init();
  82. }
  83.  
  84. TrySetPropsByPosture(EP_Standing);
  85.  
  86. EyeHeightComponent* Eye = GetComponent<EyeHeightComponent>();
  87. FocusComponent* Focus = GetComponent<FocusComponent>();
  88. SprintComponent* Sprint = GetComponent<SprintComponent>();
  89. MAKESTRING(CrouchSpeed);
  90. MAKESTRING(FocusSpeed);
  91. MAKESTRING(SprintSpeed);
  92. if (Eye && Focus && Sprint)
  93. {
  94. Eye->SetSmoothingSpeed(NConfigFile::GetInstance()->Access(gNullStr, CrouchSpeed));
  95. Focus->SetSmoothingSpeed(NConfigFile::GetInstance()->Access(gNullStr, FocusSpeed));
  96. Sprint->SetSmoothingSpeed(NConfigFile::GetInstance()->Access(gNullStr, SprintSpeed));
  97.  
  98. MAKESTRING(EyeHeight);
  99. Eye->SetTargetEyeHeight(NConfigFile::GetInstance()->Access(gNullStr, EyeHeight));
  100. Focus->SetTargetFocus(1.0f, true);
  101. Sprint->SetTargetFocus(1.0f, true);
  102. }
  103.  
  104. NPhysicsComponent* Phys = GetComponent<NPhysicsComponent>();
  105. if (Phys)
  106. {
  107. Phys->OnJump += OnJump;
  108. Phys->OnLand += OnLand;
  109. Phys->OnSlide += OnSlide;
  110. Phys->OnUnground += OnUnground;
  111. Phys->OnHitWall += OnHitWall;
  112. Phys->OnWallHug += OnWallHug;
  113. Phys->CanWallHugCallback += CanWallHug;
  114. Phys->CanDownJumpCallback += CanDownJump;
  115. Phys->PreserveGroundSpeedCallback += PreserveGroundSpeed;
  116. Phys->IgnoreShallowLedgesCallback += IgnoreShallowLedges;
  117.  
  118. // Oh heeeeyyyyy,
  119. Phys->SetStickyWalking(true);
  120. Phys->SetStickyWalkingScalar(FEET);//100.0f * INCHES);
  121. }
  122.  
  123. if (Space)
  124. {
  125. Space->OnCollision += OnCollision;
  126. }
  127.  
  128. NBasingComponent* Base = GetComponent<NBasingComponent>();
  129. if (Base)
  130. {
  131. Base->OnBaseMovedCallback += OnBaseMoved;
  132. }
  133.  
  134. NCollisionComponent* Coll = GetComponent<NCollisionComponent>();
  135. if (Coll)
  136. {
  137. Coll->dOnAnyHit += OnAnyHit;
  138. Coll->dOnActivatedQueuedPrimitive += OnActivatedQueuedPrimitive;
  139. }
  140.  
  141. NDataComponent* Data = GetComponent<NDataComponent>();
  142. if (Data)
  143. {
  144. Data->dWriteCallback += OnDataWritten;
  145. }
  146.  
  147. NDialogConsumerComponent* DialogCon = GetComponent<NDialogConsumerComponent>();
  148. if (DialogCon)
  149. {
  150. DialogCon->dDialogOpened += OnDialogOpened;
  151. DialogCon->dDialogClosed += OnDialogClosed;
  152. DialogCon->dModifyIncomingDialog += ModifyDialog;
  153. DialogCon->TULPAHACK_dSignalWantsToClose += HACK_SignalWantsToClose;
  154. }
  155.  
  156. NCameraComponent* Camera = GetComponent<NCameraComponent>();
  157. if (Camera)
  158. {
  159. Camera->Camera = TulpaGame::GetInstance()->GetGameSceneCamera();
  160. }
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168. // I miiiiight want this to be shorter for general interacting-with-things purposes, buuuuut...
  169. // It was 20 (e.g., 16.667 feet) in Banon, which sounds...long, BUT, 5 voxels is 16 feet, so.
  170. GetComponent<NFrobComponent>()->TraceDistance = VOXEL_SCALE * 3.0f;//5.0f;// * 2.0f;//20.0f;
  171. GetComponent<NFrobComponent>()->PrimitiveName = NHashedString("Trace");
  172. //GetComponent<NFrobComponent>()->SetFilter(CFT_All/*CFT_Frobbable*/);
  173. GetComponent<NFrobComponent>()->dCanFrobCallback = CanFrob;
  174. GetComponent<NFrobComponent>()->dOnFoundFrobbable = OnFoundFrobbable;
  175. GetComponent<NFrobComponent>()->dFormatString = FormatFrobString;
  176. GetComponent<NFrobComponent>()->dPositionString = PositionFrobString;
  177. GetComponent<NFrobComponent>()->SetFilter(CFT_Frobbable);
  178.  
  179. //// This can be moved to the definition, alongside the "Trace" primitive.
  180. //NCollisionPoint* FrobBounds = new NCollisionPoint(EE_Valid);
  181. //NCollisionSpace::GetInstance()->AddCollision(FrobBounds); // Required as it's no longer automatic in light of the list providers update.
  182. //GetComponent<NCollisionComponent>()->AddPrimitive(FrobBounds, NHashedString("Trace"));
  183. //FrobBounds->SetController(GetComponent<NSpatialComponent>()); // Must have a controller so it can early out of intersection tests against the player's collision box.
  184. //FrobBounds->SetCollisionFilterType(CFT_None);
  185.  
  186.  
  187.  
  188. //GetComponent<NarrationComponent>()->PlayClip(NHashedString("Intro"));
  189.  
  190.  
  191.  
  192. GetComponent<EditModeComponent>()->dOnEditModeToggled += OnEditModeToggled;
  193. }
  194.  
  195. void TulpaPlayer::TryGround(float LiftDist, float DropDist)
  196. {
  197. LiftDist, DropDist;
  198. }
  199.  
  200. void TulpaPlayer::OnInitialLevelLoad(float OverridePlayTime)
  201. {
  202. OverridePlayTime;
  203. }
  204.  
  205. void TulpaPlayer::Tick_CalcUpdate(float DeltaTime, ETickGroup TickGroup)
  206. {
  207. DeltaTime, TickGroup;
  208.  
  209. if (IS_TICK(TickGroup, ETG_Game))
  210. {
  211. // The TulpaPlayerControllerComponent now handles all input gathering, physics propagation, and state changes.
  212. }
  213. }
  214.  
  215. void TulpaPlayer::Tick_CommitUpdate(float DeltaTime, ETickGroup TickGroup)
  216. {
  217. DeltaTime, TickGroup;
  218.  
  219. if (IS_TICK(TickGroup, ETG_Game))
  220. {
  221. // Moved the commit phase of movement to the controller.
  222. }
  223.  
  224. if (IS_TICK(TickGroup, ETG_Render))
  225. {
  226. // This is where frob, dialog, and popup stuff would go. (See Xanadu's PlayerBase Commit step.)
  227.  
  228. NCamera* FPSCam = TulpaGame::GetInstance()->GetGameSceneCamera();
  229. NSpatialComponent* Space = GetComponent<NSpatialComponent>();
  230. NCollisionComponent* Coll = GetComponent<NCollisionComponent>();
  231. CamTrackComponent* CamTrack = GetComponent<CamTrackComponent>();
  232. if (FPSCam && Space && Coll)
  233. {
  234. NCollisionCapsule* Prim = Cast<NCollisionCapsule>(Coll->GetActivePrimitive());
  235. if (Prim)
  236. {
  237. EyeHeightComponent* Eye = GetComponent<EyeHeightComponent>();
  238. if (Eye)
  239. {
  240. // TODO: Include collision primitive's offset if I ever have one.
  241. float EyeOffset = Eye->GetCurrentEyeHeight() - (Prim->HalfHeight + Prim->Radius);
  242. float PrimOffsetCompensation = Dot(Prim->GetStandardOffset(), NPhysicsGlobals::GetWorldUp());
  243. EyeOffset += PrimOffsetCompensation;
  244. FPSCam->setPos(Space->Game_Curr.Position + (NPhysicsGlobals::GetWorldUp() * EyeOffset));
  245. }
  246.  
  247. FocusComponent* Focus = GetComponent<FocusComponent>();
  248. SprintComponent* SprintComp = GetComponent<SprintComponent>();
  249. if (Focus && SprintComp)
  250. {
  251. MAKESTRING(CamFOV);
  252. float EffFov = NConfigFile::GetInstance()->Access(gNullStr, CamFOV);
  253.  
  254. MAKESTRING(FocusScalar);
  255. float FocusRange = Focus->GetCurrentFocus();
  256. float SprintRange = SprintComp->GetCurrentFocus();
  257.  
  258. EffFov = atan(tan(EffFov * DEG2RAD * 0.5f) * FocusRange * SprintRange) * 2.0f * RAD2DEG;
  259.  
  260. FPSCam->setFOV(EffFov);
  261. }
  262. }
  263.  
  264. if (CamTrack && CamTrack->IsPlaying())
  265. {
  266. CamTrack->Update(DeltaTime);
  267. CamTrack->ModifyCamera(FPSCam);
  268. }
  269. }
  270.  
  271. NDialogConsumerComponent* Dialog = GetComponent<NDialogConsumerComponent>();
  272.  
  273. // This depends on having a pixel-perfect font at the moment.
  274. // I need a better system for drawing HUD elements of arbitrary sizes.
  275. // I thought I had something like that, but maybe not?
  276. MAKESTRING(AimingDotOpacity);
  277. float DotOpac = NConfigFile::GetInstance()->Access(gNullStr, AimingDotOpacity);
  278. if (DotOpac >= (0.5f / 256.0f) &&
  279. (!Dialog || !Dialog->HasDialog()) &&
  280. !IsIntroHappening())
  281. {
  282. NFontParams Params;
  283. Params.Text = NString::ResolveMarkup("<img src=\"hud:empty\" />");
  284. Params.Pos = NVec2(HALF_BANON_SCENE_WIDTH - 2, HALF_BANON_SCENE_HEIGHT - 2);
  285. Params.Color[0] = NColor8(255,255,255, (uchar)Clamp(DotOpac * 256.0f, 0.0f, 255.0f));
  286. Params.Scale = 8.0f / TulpaGame::GetInstance()->TheGameFont->GetFontGlyphHeight();
  287. TulpaGame::GetInstance()->TheGameFont->DrawText(Params);
  288. }
  289.  
  290. if (Dialog)
  291. {
  292. //DialogAnchor Anchor = DA_Top;
  293.  
  294. // TODO: Always top-anchor the status screen?
  295. if (Resolve<NEntity>(Dialog->GetProvider()) != this)
  296. {
  297. if (GetComponent<NSpatialComponent>() && GetComponent<NCameraComponent>() && GetComponent<NCameraComponent>()->Camera)
  298. {
  299. NVec3 Diff = GetComponent<NSpatialComponent>()->Render_Curr.Position - GetComponent<NCameraComponent>()->Camera->getPos();
  300. if (Diff.y < -0.0f)
  301. {
  302. //Anchor = DA_Bottom;
  303. }
  304. }
  305. }
  306.  
  307. Dialog->Tick();
  308. Dialog->Render(/*Anchor*/);
  309. }
  310.  
  311. NFrobComponent* Frob = GetComponent<NFrobComponent>();
  312. if (Frob && (!Dialog || !Dialog->HasDialog()))
  313. {
  314. Frob->Render();
  315. }
  316.  
  317. // This should maybe use engine time and not render time, so it continues in events in which
  318. // the game is paused but audio is still playing, as when dialog boxes are open.
  319. // This doesn't ever GET an engine tick though because it's a fixed game tickable.
  320. // Sooooo......
  321. NarrationComponent* Narr = GetComponent<NarrationComponent>();
  322. if (Narr)
  323. {
  324. Narr->Render(DeltaTime);
  325. }
  326.  
  327. EditModeComponent* Edit = GetComponent<EditModeComponent>();
  328. if (Edit)
  329. {
  330. Edit->DrawDebugOutput();
  331. }
  332.  
  333. NPopupComponent* Popup = GetComponent<NPopupComponent>();
  334. if (Popup)
  335. {
  336. // TODO: Add the position-based anchoring from Valk here? (See above, commented out dialog stuff.)
  337.  
  338. Popup->Tick(DeltaTime);
  339. Popup->Render();
  340. }
  341. }
  342. }
  343.  
  344. VOID_TYPE TulpaPlayer::OnJump(NEntity* OwnerEntity, int JumpNum)
  345. {
  346. OwnerEntity, JumpNum;
  347.  
  348. return VOID_TYPE();
  349. }
  350.  
  351. VOID_TYPE TulpaPlayer::OnLand(NEntity* OwnerEntity, const NCollisionResult& ThisHitRes, bool bEffectsReady)
  352. {
  353. OwnerEntity, ThisHitRes, bEffectsReady;
  354.  
  355. NSpatialComponent* Space = OwnerEntity->GetComponent<NSpatialComponent>();
  356. NPhysicsComponent* Phys = OwnerEntity->GetComponent<NPhysicsComponent>();
  357. if (Space && Phys)
  358. {
  359. float PrevSpeed = Dot(Projection(Space->Game_Prev.Velocity, NPhysicsGlobals::GetWorldUp()), NPhysicsGlobals::GetWorldUp());
  360. float CurrSpeed = Dot(Projection(Space->Game_Curr.Velocity, NPhysicsGlobals::GetWorldUp()), NPhysicsGlobals::GetWorldUp());
  361. float TermVel = Phys->GetJumpSpeed();//Phys->GetTerminalVelocity();
  362.  
  363. PrevSpeed, CurrSpeed, TermVel;
  364. ANCHOR;
  365.  
  366. if (Abs(PrevSpeed) >= Abs(TermVel * 0.9f))
  367. {
  368. // We landed hard enough to warrant animating eye height. (This will happen on any jump!)
  369. EyeHeightComponent* EyeHeight = OwnerEntity->GetComponent<EyeHeightComponent>();
  370. if (EyeHeight)
  371. {
  372. // We want to preserve the downward speed and smoothly bring it back to the current/target.
  373. // A Bezier curve might work here.
  374. EyeHeight->QueueAnimation(PrevSpeed);
  375. }
  376. }
  377. }
  378.  
  379. return VOID_TYPE();
  380. }
  381.  
  382. VOID_TYPE TulpaPlayer::OnUnground(NEntity* OwnerEntity)
  383. {
  384. OwnerEntity;
  385.  
  386. NPostureComponent* Posture = OwnerEntity->GetComponent<NPostureComponent>();
  387. if (Posture->IsInPosture(EP_Crouching))
  388. {
  389. // This works, but I'm gonna try commenting it out for Tulpa.
  390. //Cast<TulpaPlayer>(OwnerEntity)->TrySetPropsByPosture(EP_Standing);
  391. }
  392.  
  393. Cast<TulpaPlayer>(OwnerEntity)->bCanPlayMantleFoley = true;
  394.  
  395. return VOID_TYPE();
  396. }
  397.  
  398. VOID_TYPE TulpaPlayer::OnWallHug(NEntity* OwnerEntity, const NCollisionResult& ThisHitRes)
  399. {
  400. OwnerEntity, ThisHitRes;
  401.  
  402. return VOID_TYPE();
  403. }
  404.  
  405. bool TulpaPlayer::CanWallHug(NEntity* OwnerEntity, const NCollisionResult& ThisHitRes)
  406. {
  407. OwnerEntity, ThisHitRes;
  408.  
  409. return false;
  410. }
  411.  
  412. bool TulpaPlayer::CanDownJump(NEntity* OwnerEntity, const NCollisionResult& ThisHitRes)
  413. {
  414. OwnerEntity, ThisHitRes;
  415.  
  416. return false;
  417. }
  418.  
  419. bool TulpaPlayer::PreserveGroundSpeed(NEntity* OwnerEntity)
  420. {
  421. OwnerEntity;
  422.  
  423. return false;
  424. }
  425.  
  426. bool TulpaPlayer::IgnoreShallowLedges(NEntity* OwnerEntity)
  427. {
  428. OwnerEntity;
  429.  
  430. return false;
  431. }
  432.  
  433. VOID_TYPE TulpaPlayer::OnHitWall(NEntity* OwnerEntity, const NCollisionResult& ThisHitRes)
  434. {
  435. OwnerEntity, ThisHitRes;
  436.  
  437. TulpaWorld* AWorld = Resolve<TulpaWorld>(ThisHitRes.HitPrimitive);
  438. if (AWorld)
  439. {
  440. NPostureComponent* Posture = OwnerEntity->GetComponent<NPostureComponent>();
  441. NSpatialComponent* Space = OwnerEntity->GetComponent<NSpatialComponent>();
  442. NPhysicsComponent* Phys = OwnerEntity->GetComponent<NPhysicsComponent>();
  443. NCameraComponent* Cam = OwnerEntity->GetComponent<NCameraComponent>();
  444. TulpaPlayerControllerComponent* Controller = OwnerEntity->GetComponent<TulpaPlayerControllerComponent>();
  445. NCollisionComponent* Coll = OwnerEntity->GetComponent<NCollisionComponent>();
  446. if (Posture && Space && Phys && Cam && Cam->Camera && Controller && Coll)
  447. {
  448. // This is a little too aggressive.
  449. // We want to be able to sprint and slide along a wall.
  450. // Let's only do this when the wall normal strongly opposes our velocity (both taken in 2D, probably).
  451.  
  452. NVec3 PrevVel = Space->Game_Prev.Velocity;
  453. NVec3 HitNorm = ThisHitRes.HitNormal;
  454.  
  455. PrevVel = Normalize(PrevVel - Projection(PrevVel, NPhysicsGlobals::GetWorldUp()));
  456. HitNorm = Normalize(HitNorm - Projection(HitNorm, NPhysicsGlobals::GetWorldUp()));
  457.  
  458. const float STOP_SPRINT_DOT = -0.866025f; // 30 degrees in either direction.
  459. float DotProduct = Dot(PrevVel, HitNorm);
  460. if (DotProduct <= STOP_SPRINT_DOT)
  461. {
  462. // Flag the controller so we can't start sprinting next tick (to prevent "bouncing" the FOV)...
  463. Controller->bSuppressSprintNextTick = true;
  464.  
  465. // ... and kill the sprint if there was one.
  466. if (Posture->IsInPosture(EP_Sprinting))
  467. {
  468. Cast<TulpaPlayer>(OwnerEntity)->TrySetPropsByPosture(EP_Standing);
  469. }
  470. }
  471.  
  472. // Let's try to mantle!!
  473. // Conditions for mantling:
  474. // 1. We're ungrounded.
  475. // 2. We're actively pushing against the wall.
  476. // 3. Our upward velocity is less than the mantling velocity?
  477. // 4. There is room to mantle to.
  478.  
  479. ChimeComponent* Chime = OwnerEntity->GetComponent<ChimeComponent>();
  480.  
  481. if (Chime && Chime->HasChime(CA_Mantle))
  482. {
  483. // Do we accelerate or alter velocity to mantle?
  484. MAKESTRING(Gameplay);
  485. MAKESTRING(Jump);
  486. if ((!Phys->IsGrounded() || Phys->IsSliding()) &&
  487. Controller->IsDown(Gameplay, Jump))
  488. {
  489. // TODO: Maybe request the actual move attempt from the PC?
  490. NVec3 MoveAttemptGuess = Space->Game_Prev.Velocity;
  491. MoveAttemptGuess -= Projection(MoveAttemptGuess, NPhysicsGlobals::GetWorldUp());
  492. MoveAttemptGuess = Normalize(MoveAttemptGuess);
  493.  
  494. NVec3 Facing = Cam->Camera->getFwdFPS();
  495.  
  496. NVec3 FlatNormal = ThisHitRes.HitNormal;
  497. FlatNormal -= Projection(FlatNormal, NPhysicsGlobals::GetWorldUp());
  498. FlatNormal = Normalize(FlatNormal);
  499.  
  500. if (Dot(MoveAttemptGuess, FlatNormal) <= -0.866025f && // A little more lenient, can be within 60 degrees of opposing
  501. Dot(MoveAttemptGuess, Facing) >= 0.866025f) // A little less lenient, must be within 30 degrees of facing
  502. {
  503. MAKESTRING(DEBUG_NOTIFY_MANTLE);
  504. const char* DebugMantleString = "Mantling...";
  505. NBaseGame::GetInstance()->AddDebugString(DebugMantleString, 0.0f, DEBUG_NOTIFY_MANTLE);
  506.  
  507. // TODO: Fix the case of endlessly bumping against this ceiling due to discrepancies in voxel testing locations between player and target.
  508. /*
  509. XXX
  510.  
  511. XXXXXX
  512. XXXXXX
  513. XXXXXXXXXXXXXXXX
  514. */
  515.  
  516. // Let's fudge this and TargetVoxPos a bit so we can trust they're at the same height.
  517. // These heights should all be the same, or about the same.
  518. // If the hit position matches one of them exactly, it will be the previous one,
  519. // when we're starting from already against the wall.
  520. // I can worry about making this explicitly z-aligned later. Who cares.
  521. Space->Game_Curr.Position.z;
  522. Space->Game_Prev.Position.z;
  523. ThisHitRes.HitPosition.z;
  524. float AuthHeight = ThisHitRes.HitPosition.z;
  525. ANCHOR;
  526. NCollisionInterface* Prim = Coll->GetActivePrimitive();
  527. NCollisionCapsule* Capsule = Cast<NCollisionCapsule>(Prim);
  528. opt_assert(Capsule);
  529.  
  530. // Lower it to the floor.
  531. AuthHeight -= Capsule->Radius;
  532. AuthHeight -= Capsule->HalfHeight;
  533.  
  534. // Now raise it half a voxel.
  535. AuthHeight += (VOXEL_SCALE * 0.5f);
  536. ANCHOR;
  537.  
  538. NVec3 CurrVoxPos = Space->Game_Curr.Position;
  539. CurrVoxPos.z = AuthHeight;
  540. CurrVoxPos /= VOXEL_SCALE;
  541.  
  542. NVec3 TargetVoxPos = ThisHitRes.HitPosition;
  543. TargetVoxPos -= (FlatNormal * ((Capsule->Radius) + (VOXEL_SCALE * 0.5f)));
  544. TargetVoxPos.z = AuthHeight;
  545. TargetVoxPos /= VOXEL_SCALE;
  546.  
  547. NPoint3 CurrPt;
  548. CurrPt.x = (int)floor(CurrVoxPos.x + 0.5f);
  549. CurrPt.y = (int)floor(CurrVoxPos.y + 0.5f);
  550. CurrPt.z = (int)floor(CurrVoxPos.z + 0.5f);
  551.  
  552. NPoint3 TargetPt;
  553. TargetPt.x = (int)floor(TargetVoxPos.x + 0.5f);
  554. TargetPt.y = (int)floor(TargetVoxPos.y + 0.5f);
  555. TargetPt.z = (int)floor(TargetVoxPos.z + 0.5f);
  556.  
  557. opt_assert(CurrPt != TargetPt);
  558.  
  559. // Typically if this fails, it's because we're approaching from a diagonal.
  560. // I wonder if I should check all those cases. Hrrrmmmm.
  561. opt_assert((Abs(CurrPt.x - TargetPt.x) + Abs(CurrPt.y - TargetPt.y) + Abs(CurrPt.z - TargetPt.z) ) == 1);
  562.  
  563. TulpaWorld* TheWorld = Cast<TulpaWorld>(NBaseGame::GetInstance()->GetWorldHandle());
  564. if (TheWorld)
  565. {
  566. //const Voxel& CurrVox = TheWorld->GetVoxel(CurrPt);
  567. //const Voxel& TargetVox = TheWorld->GetVoxel(TargetPt);
  568.  
  569. //CurrVox, TargetVox;
  570.  
  571. //opt_assert(CurrVox.Kernel.Type == VOX_Empty);
  572. ////opt_assert(TargetVox.Kernel.Type != VOX_Empty); // May not be true, as this is the one at our feet when we're on or very near the ground.
  573.  
  574. bool bFoundLedge = false;
  575.  
  576. //const Voxel& TargetVox1 = TheWorld->GetVoxel(TargetPt + NPoint3(0,0,0)); // Usually the one at our feet unless we're in the air, then maybe the one in front of our eyes.
  577. //const Voxel& TargetVox2 = TheWorld->GetVoxel(TargetPt + NPoint3(0,0,1)); // Usually the one in front of our eyes unless we're in the air, then maybe the one above it.
  578. //const Voxel& TargetVox3 = TheWorld->GetVoxel(TargetPt + NPoint3(0,0,2)); // Definitely one above us.
  579. //const Voxel& TargetVox4 = TheWorld->GetVoxel(TargetPt + NPoint3(0,0,3)); // One above that for good measure?
  580.  
  581. TulpaPlayer* TheTulpaPlayer = Cast<TulpaPlayer>(OwnerEntity);
  582.  
  583. for (int z = -1; z < 1 && !bFoundLedge; ++z)
  584. {
  585. const Voxel& TargetVoxLower = TheWorld->GetVoxel(TargetPt + NPoint3(0,0,z));
  586. if (TargetVoxLower.IsCollider())
  587. {
  588. const Voxel& TargetVoxUpper = TheWorld->GetVoxel(TargetPt + NPoint3(0,0,z+1));
  589. if (!TargetVoxUpper.IsCollider())
  590. {
  591. const Voxel& TargetVoxUppermost = TheWorld->GetVoxel(TargetPt + NPoint3(0,0,z+2));
  592. if (!TargetVoxUppermost.IsCollider() || Posture->IsInPosture(EP_Crouching))
  593. {
  594. const Voxel& CurrVoxUpper = TheWorld->GetVoxel(CurrPt + NPoint3(0,0,z+1));
  595. const Voxel& CurrVoxUppermost = TheWorld->GetVoxel(CurrPt + NPoint3(0,0,z+2));
  596. if (!CurrVoxUpper.IsCollider() &&
  597. (!CurrVoxUppermost.IsCollider() || Posture->IsInPosture(EP_Crouching)))
  598. {
  599. bFoundLedge = true;
  600.  
  601. // Also see whether we should play the audio based on floor height:
  602. if (TheTulpaPlayer->bCanPlayMantleFoley)
  603. {
  604. const Voxel& CurrVoxLowermost = TheWorld->GetVoxel(CurrPt + NPoint3(0,0,z-1));
  605. if (CurrVoxLowermost.IsCollider())
  606. {
  607. TheTulpaPlayer->bCanPlayMantleFoley = false;
  608. }
  609. }
  610. }
  611. }
  612. }
  613. }
  614. }
  615.  
  616. if (bFoundLedge)
  617. {
  618. // This is relative to foot speed, so it changes when crouched.
  619. const float MANTLE_SPEED = 1.75f;
  620.  
  621. // Basically act like forward movement is redirected upward, I guess?
  622. // Kill any lateral movement?
  623.  
  624. // Instead of strictly using the up vector, let's use a vector that rounds up around the corner of the capsuled edge.
  625. NVec3 Cross1 = Cross(ThisHitRes.HitNormal, NPhysicsGlobals::GetWorldUp());
  626. NVec3 Cross2 = Cross(Cross1, ThisHitRes.HitNormal);
  627. NVec3 EffectiveUpVector = Cross2;
  628.  
  629.  
  630. NVec3 UpwardVel = Projection(Space->Game_Curr.Velocity, EffectiveUpVector);
  631. float CurrentUp = Dot(UpwardVel, EffectiveUpVector);
  632.  
  633. NVec3 UpwardPrevVel = Projection(Space->Game_Prev.Velocity, EffectiveUpVector);
  634. //float NewUp = (Space->Game_Prev.Velocity - UpwardPrevVel).length() * MANTLE_SPEED;
  635. float NewUp = Phys->GetFootSpeed() * MANTLE_SPEED;
  636.  
  637. if (NewUp > CurrentUp)
  638. {
  639. Space->Game_Curr.Velocity -= UpwardVel;
  640. Space->Game_Curr.Velocity += (EffectiveUpVector * NewUp);
  641.  
  642. // TODO: If we reach a point where ONLY the one at our feet is clear and NOT the one above it, auto-crouch?
  643. // TODO: Handle low ceilings, possibly the same case.
  644.  
  645. {
  646. {
  647. {
  648. // Mantle audio!!
  649. if (TheTulpaPlayer->bCanPlayMantleFoley)
  650. {
  651. TheTulpaPlayer->bCanPlayMantleFoley = false;
  652. MAKESTRINGWITH(MantleSound, "Mantle Foley");
  653. NStreamHandle hMantleStream = NAudioMgr::GetInstance()->GetStream(MantleSound);
  654. if (hMantleStream)
  655. {
  656. if (NAudioMgr::GetInstance()->GetNumSamplers(hMantleStream) == 0)
  657. {
  658. NAudioMgr::GetInstance()->CreateAndPlay(MantleSound, NBaseGame::GetInstance()->GetAudioBusSFX());
  659. }
  660. }
  661. }
  662. }
  663. }
  664. }
  665. }
  666. }
  667. }
  668. }
  669. }
  670. }
  671. }
  672. }
  673.  
  674. return VOID_TYPE();
  675. }
  676.  
  677. VOID_TYPE TulpaPlayer::OnSlide(NEntity* OwnerEntity, const NCollisionResult& ThisHitRes, bool bEffectsReady)
  678. {
  679. OwnerEntity, ThisHitRes, bEffectsReady;
  680.  
  681. return VOID_TYPE();
  682. }
  683.  
  684. VOID_TYPE TulpaPlayer::OnBaseMoved(NEntity* Owner, NEntity* Parent)
  685. {
  686. Owner, Parent;
  687.  
  688. return VOID_TYPE();
  689. }
  690.  
  691. VOID_TYPE TulpaPlayer::OnDialogOpened(NEntity* OwnerEntity)
  692. {
  693. OwnerEntity;
  694.  
  695. // If I comment this out, the audio keeps running but the text doesn't advance because the dialog component zeroes out the delta time,
  696. // which I probably don't want for this game specifically. (Normally I would, so I should make sure it's labeled as such.)
  697. //OwnerEntity->GetComponent<NarrationComponent>()->PauseClip(true);
  698.  
  699. return VOID_TYPE();
  700. }
  701.  
  702. VOID_TYPE TulpaPlayer::OnDialogClosed(NEntity* OwnerEntity)
  703. {
  704. OwnerEntity;
  705.  
  706. //OwnerEntity->GetComponent<NarrationComponent>()->PauseClip(false);
  707.  
  708. return VOID_TYPE();
  709. }
  710.  
  711. VOID_TYPE TulpaPlayer::ModifyDialog(NHandle hProvider, NHandle hConsumer, NString& InOutDialog)
  712. {
  713. CodexComponent* pCodex = Resolve<CodexComponent>(hConsumer);
  714. if (pCodex && !pCodex->GetHasCodex())
  715. {
  716. InOutDialog = NLocMgr::GetInstance()->GetString(NHashedString("TulpaGame"), NHashedString("Dialog"), NHashedString("NoCodex"));
  717. }
  718.  
  719. return VOID_TYPE();
  720. }
  721.  
  722. bool TulpaPlayer::HACK_SignalWantsToClose(NHandle hProvider, NHandle hConsumer)
  723. {
  724. bool bRetVal = false;
  725. CodexComponent* pCodex = Resolve<CodexComponent>(hConsumer);
  726. if (pCodex && !pCodex->GetHasCodex())
  727. {
  728. bRetVal = true;
  729. }
  730. return bRetVal;
  731. }
  732.  
  733. VOID_TYPE TulpaPlayer::HandleAttachment(NEntity* OwnerEntity, NEntity* AttEnt, NHashedString EntDef)
  734. {
  735. OwnerEntity, AttEnt, EntDef;
  736.  
  737. return VOID_TYPE();
  738. }
  739.  
  740. void TulpaPlayer::SetPhysicsProps()
  741. {
  742. }
  743.  
  744. VOID_TYPE TulpaPlayer::OnCollision(NEntity* OwnerEntity, const NCollisionResult& ThisHitRes)
  745. {
  746. OwnerEntity, ThisHitRes;
  747.  
  748. return VOID_TYPE();
  749. }
  750.  
  751. VOID_TYPE TulpaPlayer::OnAnyHit(NEntity* OwnerEntity, NCollisionInterface* Self, NCollisionInterface* Other, const NCollisionResult& ThisHitRes)
  752. {
  753. OwnerEntity, Self, Other, ThisHitRes;
  754.  
  755. RESOLVE(NCollectComponent, OtherColl, Other);
  756. RESOLVE(NDeleteComponent, OtherDel, Other);
  757. if (OtherColl && OtherDel)
  758. {
  759. ANCHOR;
  760. OtherDel->TryDelete(true);
  761.  
  762. // Do collection stuff.
  763. // This can be hardcoded for Tulpa, whatever.
  764.  
  765. // This probably duplicates other implementations of collection elsewhere.
  766. // Whatever.
  767.  
  768. {
  769. MAKESTRINGWITH(OnCollectedStr, "OnCollected");
  770. OtherColl->RunEvent(OnCollectedStr, OtherColl->GetHandle(), OwnerEntity->GetHandle());
  771.  
  772. OtherColl->dOnCollected(OtherColl->GetOwner(), OwnerEntity->GetHandle());
  773. }
  774. }
  775.  
  776. return VOID_TYPE();
  777. }
  778.  
  779. //bool TulpaPlayer::BlocksOther(NCollisionInterface* Self, NCollisionInterface* Other)
  780. //{
  781. // Self, Other;
  782. //
  783. // return false;
  784. //}
  785. //
  786. //bool TulpaPlayer::PingsOther(NCollisionInterface* Self, NCollisionInterface* Other)
  787. //{
  788. // Self, Other;
  789. //
  790. // return true;
  791. //}
  792.  
  793. void TulpaPlayer::PostApplySerialData()
  794. {
  795. }
  796.  
  797. VOID_TYPE TulpaPlayer::OnDataWritten(NEntity* CallbackOwner, NHashedString Key, GenericData& InOutValue)
  798. {
  799. CallbackOwner, Key, InOutValue;
  800.  
  801. return VOID_TYPE();
  802. }
  803.  
  804. void TulpaPlayer::TrySetPropsByPosture(EPosture InPosture)
  805. {
  806. NPostureComponent* Posture = GetComponent<NPostureComponent>();
  807.  
  808. if (Posture && !Posture->IsInPosture(InPosture))
  809. {
  810. SetPropsByPosture(InPosture);
  811. }
  812. }
  813.  
  814. void TulpaPlayer::SetPropsByPosture(EPosture InPosture)
  815. {
  816. NPostureComponent* Posture = GetComponent<NPostureComponent>();
  817. EyeHeightComponent* Eye = GetComponent<EyeHeightComponent>();
  818. FocusComponent* Focus = GetComponent<FocusComponent>();
  819. SprintComponent* Sprint = GetComponent<SprintComponent>();
  820. NPhysicsComponent* Phys = GetComponent<NPhysicsComponent>();
  821. NCollisionComponent* Coll = GetComponent<NCollisionComponent>();
  822. EditModeComponent* Edit = GetComponent<EditModeComponent>();
  823.  
  824. if (Posture && Eye && Focus && Sprint && Phys && Coll && Edit && !Edit->GetEditMode())
  825. {
  826. MAKESTRING(EyeHeight);
  827. MAKESTRING(EyeHeightCrouched);
  828. MAKESTRING(CrouchSpeed);
  829. MAKESTRING(FocusScalar);
  830. MAKESTRING(FocusSpeed);
  831. MAKESTRING(Crouch);
  832. MAKESTRING(Default);
  833. MAKESTRING(SprintFOVScalar);
  834. MAKESTRINGWITH(SprintStr, "Sprint");
  835.  
  836. // If we're uncrouching, clear our max jumps so it resets to two (or whatever).
  837. // This would be nice to roll into the physics component itself, but it clashes with some other rules.
  838. if (Posture->GetPosture() == EP_Crouching)
  839. {
  840. Phys->SetMaxJumps(-1);
  841. }
  842.  
  843. if (InPosture == EP_Standing)
  844. {
  845. if (Coll->ActivatePrimitive(Default))
  846. {
  847. Sprint->SetTargetFocus(1.0f);
  848. Posture->SetPosture(EP_Standing);
  849. Eye->SetTargetEyeHeight(NConfigFile::GetInstance()->Access(gNullStr, EyeHeight));
  850. Phys->InitNamedConstantsSet(gNullStr);
  851. }
  852. }
  853. else if (InPosture == EP_Sprinting)
  854. {
  855. if (Coll->ActivatePrimitive(Default))
  856. {
  857. Sprint->SetTargetFocus(NConfigFile::GetInstance()->Access(gNullStr, SprintFOVScalar));
  858. Posture->SetPosture(EP_Sprinting);
  859. Eye->SetTargetEyeHeight(NConfigFile::GetInstance()->Access(gNullStr, EyeHeight));
  860. Phys->InitNamedConstantsSet(SprintStr);
  861. }
  862. }
  863. else if (InPosture == EP_Crouching)
  864. {
  865. if (Coll->ActivatePrimitive(Crouch))
  866. {
  867. Sprint->SetTargetFocus(1.0f);
  868. Posture->SetPosture(EP_Crouching);
  869. Eye->SetTargetEyeHeight(NConfigFile::GetInstance()->Access(gNullStr, EyeHeightCrouched));
  870. Phys->InitNamedConstantsSet(Crouch);
  871. }
  872. }
  873. }
  874. }
  875.  
  876. VOID_TYPE TulpaPlayer::OnActivatedQueuedPrimitive(NEntity* OwnerEntity, NHashedString InPrimitiveName)
  877. {
  878. ANCHOR;
  879.  
  880. // Let's just assume we'll never switch to sprinting here.
  881. // (Power slide?)
  882.  
  883. MAKESTRING(Crouch);
  884. MAKESTRING(Default);
  885.  
  886. TulpaPlayer* Player = Cast<TulpaPlayer>(OwnerEntity);
  887.  
  888. if (InPrimitiveName == Crouch)
  889. {
  890. Player->SetPropsByPosture(EP_Crouching);
  891. }
  892. else
  893. {
  894. Player->SetPropsByPosture(EP_Standing);
  895. }
  896.  
  897. return VOID_TYPE();
  898. }
  899.  
  900. bool TulpaPlayer::CanFrob(NEntity* OwnerEntity, NHandle Other)
  901. {
  902. OwnerEntity, Other;
  903.  
  904. bool bRetVal = true;
  905.  
  906. // This works but it's bad UX; I should be ABLE to frob it; it just should FAIL and play some LOCKED effects.
  907. //Door* OtherDoor = Resolve<Door>(Other);
  908. //if (OtherDoor)
  909. //{
  910. // bRetVal = OwnerEntity->GetComponent<ChimeComponent>()->HasChime(CA_Open);
  911. //}
  912.  
  913. bRetVal = !(OwnerEntity->GetComponent<CamTrackComponent>()->IsPlaying());
  914.  
  915. return bRetVal;
  916. }
  917.  
  918. VOID_TYPE TulpaPlayer::OnFoundFrobbable(NEntity* OwnerEntity, NHandle Frobbable, const NCollisionResult& Result)
  919. {
  920. OwnerEntity;
  921.  
  922. if (Frobbable)
  923. {
  924. if (Frobbable->IsA(TulpaWorld::StaticGetClassName()))
  925. // Unnecessary, as we toggle the world's frobbability on edit mode toggled instead.
  926. //if (OwnerEntity->GetComponent<EditModeComponent>()->GetEditMode())
  927. {
  928. // Show widget at position
  929. //NDebugLines::GetInstance()->Draw(Result.HitPosition, Result.HitPosition + (Result.HitNormal * VOXEL_SCALE * 0.5f), 0.0f, NColor8(255,0,0));
  930.  
  931. // Also draw a quantized box.
  932.  
  933. // THIS IS COPIED FROM THE PC. GENERALIZE IT!!
  934.  
  935. {
  936. {
  937. {
  938. NPoint3 FrontPt, BackPt;
  939. NVec3 OtherAxis1, OtherAxis2;
  940. Resolve<TulpaPlayerControllerComponent>(OwnerEntity)->GetVoxelsFromTrace(Result, FrontPt, BackPt, OtherAxis1, OtherAxis2);
  941.  
  942. {
  943. {
  944. {
  945. ANCHOR;
  946.  
  947. NVec3 vi = -Result.HitNormal;
  948. NVec3 vj = -OtherAxis1;
  949. NVec3 vk = -OtherAxis2;
  950.  
  951. float fx = (float)FrontPt.x;
  952. float fy = (float)FrontPt.y;
  953. float fz = (float)FrontPt.z;
  954.  
  955. NVec3 Corner[4];
  956.  
  957. Corner[0] = NVec3(fx,fy,fz) + (vi * +0.5f) + (vj * +0.5f) + (vk * +0.5f);
  958. Corner[1] = NVec3(fx,fy,fz) + (vi * +0.5f) + (vj * -0.5f) + (vk * +0.5f);
  959. Corner[2] = NVec3(fx,fy,fz) + (vi * +0.5f) + (vj * +0.5f) + (vk * -0.5f);
  960. Corner[3] = NVec3(fx,fy,fz) + (vi * +0.5f) + (vj * -0.5f) + (vk * -0.5f);
  961.  
  962. // Push these in a bit to address z-fighting.
  963. const float PushAmt = -0.025f;
  964. Corner[0] += ((vi + vj + vk) * PushAmt);
  965. Corner[1] += ((vi - vj + vk) * PushAmt);
  966. Corner[2] += ((vi + vj - vk) * PushAmt);
  967. Corner[3] += ((vi - vj - vk) * PushAmt);
  968.  
  969. float Brightness = fastsin(NBaseGame::GetInstance()->renderAbsTime * TAU * 3.0f);
  970. Brightness = (Brightness + 1.0f) * 0.5f;
  971. Brightness = Lerp(0.25f, 0.75f, Brightness);
  972. uchar ucBright = (uchar)(Brightness * 255);
  973.  
  974. NDebugLines::GetInstance()->Draw(Corner[0] * VOXEL_SCALE, Corner[1] * VOXEL_SCALE, 0.0f, NColor8(ucBright));
  975. NDebugLines::GetInstance()->Draw(Corner[0] * VOXEL_SCALE, Corner[2] * VOXEL_SCALE, 0.0f, NColor8(ucBright));
  976. NDebugLines::GetInstance()->Draw(Corner[1] * VOXEL_SCALE, Corner[3] * VOXEL_SCALE, 0.0f, NColor8(ucBright));
  977. NDebugLines::GetInstance()->Draw(Corner[2] * VOXEL_SCALE, Corner[3] * VOXEL_SCALE, 0.0f, NColor8(ucBright));
  978. }
  979. }
  980. }
  981. }
  982. }
  983. }
  984. }
  985. else
  986. {
  987. ANCHOR;
  988. }
  989. }
  990. else
  991. {
  992. // Hide widget
  993. }
  994.  
  995. return VOID_TYPE();
  996. }
  997.  
  998. VOID_TYPE TulpaPlayer::FormatFrobString(const NString& InString, NString& InOutString, bool bInputChanged)
  999. {
  1000. if (bInputChanged)
  1001. {
  1002. // TODO: Provide this string somewhere else.
  1003. //InOutString = NString("Press ") + InString + NString(" to Use");
  1004. MAKESTRINGWITH(TulpaGameStr, "TulpaGame");
  1005. MAKESTRING(Prompts);
  1006. MAKESTRING(FrobPrompt);
  1007. InOutString = NLocMgr::GetInstance()->GetString(TulpaGameStr, Prompts, FrobPrompt).Replace("%s", InString);
  1008. }
  1009.  
  1010. return VOID_TYPE();
  1011. }
  1012.  
  1013. VOID_TYPE TulpaPlayer::PositionFrobString(const NVec2& InDims, NVec2& OutPosition)
  1014. {
  1015. // TODO: Use a delegate to position these on-screen, given the entity (or its transform only?) and the dimensions of the prompt.
  1016.  
  1017. // TODO: TEST THIS IN NFML!! The floor() may not be correct there. It PROBABLY is fine, but I SHOULD KNOW.
  1018. OutPosition = NVec2(320.0f, 160.0f);
  1019.  
  1020. OutPosition.x = floor(OutPosition.x - InDims.x*0.5f);
  1021. OutPosition.y = floor(OutPosition.y - InDims.y*0.5f);
  1022.  
  1023. return VOID_TYPE();
  1024. }
  1025.  
  1026. VOID_TYPE TulpaPlayer::OnEditModeToggled(NEntity* OwnerEntity, bool bEditMode)
  1027. {
  1028. RESOLVE(NCollisionComponent, Coll, OwnerEntity);
  1029. RESOLVE(NPhysicsComponent, Phys, OwnerEntity);
  1030.  
  1031. opt_assert(Coll && Phys);
  1032. ANCHOR;
  1033.  
  1034. if (bEditMode)
  1035. {
  1036. Coll->SetSweepFilter(CFT_None);
  1037. //Coll->SetDefaultPrimitiveName(NHashedString("DOES NOT EXIST"));
  1038. //Phys->SetPhysicsDisabled(true);
  1039. Phys->InitNamedConstantsSet(NHashedString("EditFlying"));
  1040.  
  1041. #ifdef _DEBUG
  1042. OwnerEntity->GetComponent<NFrobComponent>()->TraceDistance = VOXEL_SCALE * 6.0f;
  1043. #else
  1044. OwnerEntity->GetComponent<NFrobComponent>()->TraceDistance = VOXEL_SCALE * 6.0f;//20.0f;
  1045. #endif
  1046. }
  1047. else
  1048. {
  1049. Coll->SetSweepFilter(0x0a000105);
  1050. //Coll->SetDefaultPrimitiveName(NHashedString("Default"));
  1051. //Phys->SetPhysicsDisabled(false);
  1052. Phys->InitNamedConstantsSet(gNullStr);
  1053.  
  1054. OwnerEntity->GetComponent<NFrobComponent>()->TraceDistance = VOXEL_SCALE * 3.0f;//5.0f;// * 2.0f;//20.0f;
  1055. }
  1056.  
  1057. //// Why had I commented this out?
  1058. //// (Because it doesn't work.)
  1059. //TulpaWorld* TheWorld = Cast<TulpaWorld>(NBaseGame::GetInstance()->GetWorldHandle());
  1060. //if (TheWorld)
  1061. //{
  1062. // NFrobComponent* WorldFrob = TheWorld->GetComponent<NFrobComponent>();
  1063. // if (WorldFrob)
  1064. // {
  1065. // WorldFrob->SetFrobbable(bEditMode);
  1066. // }
  1067. //}
  1068.  
  1069. OwnerEntity->GetComponent<NFrobComponent>()->SetFilter(bEditMode ? (CFT_Frobbable | CFT_FrobbableInEditModeOnly) : (CFT_Frobbable));
  1070.  
  1071.  
  1072.  
  1073. // Toggle vis of all triggers:
  1074. {
  1075. {
  1076. {
  1077. NUtilVector<Trigger*> Triggers = TulpaGame::GetInstance()->FindAllDynamicEntitiesOfType<Trigger>();
  1078. for (int i = 0; i < Triggers.size(); ++i)
  1079. {
  1080. Triggers[i]->GetComponent<NRenderableComponent>()->SetVisibility(bEditMode);
  1081. }
  1082. NUtilVector<TwoTrigger*> TwoTriggers = TulpaGame::GetInstance()->FindAllDynamicEntitiesOfType<TwoTrigger>();
  1083. for (int i = 0; i < TwoTriggers.size(); ++i)
  1084. {
  1085. TwoTriggers[i]->GetComponent<NRenderableComponent>()->SetVisibility(bEditMode);
  1086. }
  1087. }
  1088. }
  1089. }
  1090.  
  1091.  
  1092.  
  1093. return VOID_TYPE();
  1094. }
  1095.  
  1096. //VOID_TYPE TulpaPlayer::OnVinylIntroEnded(const NAudioEventRecord& Record, void* pContext)
  1097. //{
  1098. // Record, pContext;
  1099. //
  1100. // // TODO: Handle the case of this happening after the menu already closed because we're hammering the button.
  1101. //
  1102. // MAKESTRING(InEarBus);
  1103. // NSamplerHandle hSampler = NAudioMgr::GetInstance()->CreateAndPlay(NHashedString("Vinyl (Loop)"), InEarBus/*NBaseGame::GetInstance()->GetAudioBusSFX()*/, true);
  1104. // hSampler;
  1105. //
  1106. // return VOID_TYPE();
  1107. //}
Add Comment
Please, Sign In to add comment