cadetscenes.cpp 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160
  1. #include "pch.h"
  2. #include "terrain.h"
  3. //////////////////////////////////////////////////////////////////////////////
  4. //
  5. // TextPanelImage
  6. //
  7. //////////////////////////////////////////////////////////////////////////////
  8. class TextPanelImage : public Image
  9. {
  10. private:
  11. TRef<Surface> m_psurface;
  12. Point m_pointImgCenter;
  13. WinPoint m_pointTextOffset;
  14. WinPoint m_pointNextLetter;
  15. int m_nTabStop;
  16. int m_iNextLetter;
  17. ZString m_str;
  18. public:
  19. TextPanelImage(const Point& pointImgCenter, const WinPoint& sizeImg, const WinPoint& pointTextOffset, int nTabStop):
  20. m_pointTextOffset(pointTextOffset),
  21. m_pointImgCenter(pointImgCenter),
  22. m_iNextLetter(0),
  23. m_nTabStop(nTabStop)
  24. {
  25. m_psurface = GetEngine()->CreateSurface(WinRect(0,0,sizeImg.X(),sizeImg.Y()), SurfaceType2D(), NULL);
  26. m_psurface->FillSurface(Color(0,.8f,0));
  27. m_psurface->SetTextColor(Color(0,0,1));
  28. }
  29. void SetText(const ZString str)
  30. {
  31. m_psurface->FillSurface(Color(0,.8f,0));
  32. m_iNextLetter = 0;
  33. m_pointNextLetter = m_pointTextOffset;
  34. m_str = str;
  35. }
  36. void Update(float dtime)
  37. {
  38. if (m_iNextLetter < m_str.GetLength())
  39. {
  40. char c = m_str[m_iNextLetter];
  41. ZString strOut(&c,1);
  42. if (c == '\r')
  43. {
  44. m_pointNextLetter += WinPoint(
  45. -(m_pointNextLetter.X()-m_pointTextOffset.X()),
  46. m_psurface->GetFont()->GetTextExtent('X').Y());
  47. }
  48. else if (c == '\t')
  49. {
  50. m_pointNextLetter.SetX(m_pointTextOffset.X() + m_nTabStop);
  51. }
  52. else
  53. {
  54. m_psurface->SetTextColor(Color(.1f,.1f,.1f));
  55. m_psurface->DrawString(m_pointNextLetter, strOut);
  56. m_pointNextLetter += WinPoint(m_psurface->GetFont()->GetTextExtent(strOut).X(),0);
  57. }
  58. m_iNextLetter++;
  59. }
  60. }
  61. void Render(Context* pcontext)
  62. {
  63. pcontext->SetShadeMode(ShadeModeFlat);
  64. pcontext->SetLinearFilter(false, true);
  65. pcontext->SetColor(Color(1,1,1,.25));
  66. pcontext->SetBlendMode(BlendModeSourceAlpha);
  67. pcontext->DrawImage3D(m_psurface, true, m_pointImgCenter);
  68. }
  69. };
  70. //////////////////////////////////////////////////////////////////////////////
  71. //
  72. // MenuImage
  73. //
  74. //////////////////////////////////////////////////////////////////////////////
  75. class MenuImage : public Image
  76. {
  77. private:
  78. TRef<Surface> m_psurface;
  79. int m_nItems;
  80. int m_iSelItem;
  81. WinPoint m_ptOffset;
  82. WinPoint m_ptItemSize;
  83. float m_fDelay;
  84. public:
  85. MenuImage(const ZString& strImage, const WinPoint& ptOffset, int nItems):
  86. m_ptOffset(ptOffset),
  87. m_nItems(nItems),
  88. m_iSelItem(0),
  89. m_fDelay(0.0f)
  90. {
  91. m_psurface = GetModeler()->LoadSurface(strImage, false);
  92. WinRect rect = m_psurface->GetRect();
  93. m_ptItemSize.SetX(rect.XSize());
  94. m_ptItemSize.SetY(rect.YSize()/(nItems*2));
  95. }
  96. void Update(bool bUp, bool bDown, float dtime)
  97. {
  98. m_fDelay = m_fDelay + dtime;
  99. if (m_fDelay > .5f && bUp)
  100. {
  101. m_iSelItem = (m_iSelItem == 0) ? m_nItems-1 : m_iSelItem-1;
  102. m_fDelay = 0.0f;
  103. }
  104. else if (m_fDelay > .5f && bDown)
  105. {
  106. m_iSelItem = (m_iSelItem == m_nItems-1) ? 0 : m_iSelItem+1;
  107. m_fDelay = 0.0f;
  108. }
  109. }
  110. void Render(Context* pcontext)
  111. {
  112. for (int iItem = 0; iItem < m_nItems; iItem++)
  113. {
  114. if (iItem == m_iSelItem)
  115. pcontext->DrawImage(m_psurface,
  116. Rect(0, (float)m_ptItemSize.Y()*(m_nItems+iItem), (float)m_ptItemSize.X(), (float)m_ptItemSize.Y()*(m_nItems+iItem+1)),
  117. false,
  118. Point((float)m_ptOffset.X(), (float)(m_ptOffset.Y() + m_ptItemSize.Y()*(m_nItems - iItem)))
  119. );
  120. else
  121. pcontext->DrawImage(m_psurface,
  122. Rect(0, (float)m_ptItemSize.Y()*iItem, (float)m_ptItemSize.X(), (float)m_ptItemSize.Y()*(iItem+1)),
  123. false,
  124. Point((float)m_ptOffset.X(), (float)(m_ptOffset.Y() + m_ptItemSize.Y()*(m_nItems - iItem)))
  125. );
  126. }
  127. }
  128. int GetSelection()
  129. {
  130. return m_iSelItem;
  131. }
  132. };
  133. //////////////////////////////////////////////////////////////////////////////
  134. //
  135. // WheelGeo
  136. //
  137. //////////////////////////////////////////////////////////////////////////////
  138. class WheelGeo : public WrapGeo
  139. {
  140. private:
  141. TRef<IntegerEventSourceImpl> m_peventSource;
  142. TRef<GroupGeo> m_pgroupGeo;
  143. TRef<RotateTransform> m_protTransform;
  144. float m_radius;
  145. float m_angleSep;
  146. short m_cItems;
  147. short m_iItemSel;
  148. float m_angleSel;
  149. float m_angleCur;
  150. public:
  151. WheelGeo(float angleDisk, float angleSep, float radius, float dz) :
  152. WrapGeo(Geo::GetEmpty()),
  153. m_radius(radius),
  154. m_angleSep(angleSep),
  155. m_cItems(0),
  156. m_iItemSel(0),
  157. m_angleSel(0),
  158. m_angleCur(0)
  159. {
  160. m_pgroupGeo = GroupGeo::Create();
  161. m_protTransform = new RotateTransform(Vector(0,1,0), 0);
  162. m_peventSource = new IntegerEventSourceImpl();
  163. SetGeo(
  164. new TransformGeo(
  165. new TransformGeo(
  166. new TransformGeo(
  167. m_pgroupGeo,
  168. m_protTransform
  169. ),
  170. new RotateTransform(Vector(1,0,0), angleDisk)
  171. ),
  172. new TranslateTransform(Vector(0, radius*sin(angleDisk), -(dz+radius*cos(angleDisk))))
  173. )
  174. );
  175. }
  176. IIntegerEventSource* GetEventSource()
  177. {
  178. return m_peventSource;
  179. }
  180. void AddItem(Geo* pgeo)
  181. {
  182. m_pgroupGeo->AddGeo(
  183. new TransformGeo(
  184. new TransformGeo(
  185. pgeo,
  186. new TranslateTransform(Vector(0, 0, m_radius))
  187. ),
  188. new RotateTransform(Vector(0,1,0), m_angleSep * m_cItems++)
  189. )
  190. );
  191. }
  192. short GetSelItem()
  193. {
  194. return m_iItemSel;
  195. }
  196. void SetSelItem(short iItem)
  197. {
  198. m_iItemSel = iItem;
  199. m_angleSel = - m_angleSep * iItem;
  200. m_peventSource->Trigger(iItem);
  201. }
  202. void Update(bool bLeft, bool bRight, float dtime)
  203. {
  204. if (m_angleSel != m_angleCur)
  205. {
  206. float angleMove = m_angleSel - m_angleCur;
  207. float angleMax = m_angleSep * dtime*4.0f;
  208. if (angleMove > angleMax)
  209. angleMove = angleMax;
  210. else if (angleMove < -angleMax)
  211. angleMove = -angleMax;
  212. m_angleCur = m_angleCur + angleMove;
  213. m_protTransform->SetAngle(m_angleCur);
  214. }
  215. else if (bLeft && m_iItemSel > 0)
  216. SetSelItem(m_iItemSel-1);
  217. else if (bRight && m_iItemSel < m_cItems-1)
  218. SetSelItem(m_iItemSel+1);
  219. }
  220. };
  221. //////////////////////////////////////////////////////////////////////////////
  222. //
  223. // MissionAction
  224. //
  225. //////////////////////////////////////////////////////////////////////////////
  226. class MissionAction : public IObject
  227. {
  228. public:
  229. virtual void Trigger() = 0;
  230. };
  231. class CreateDroneAction : public MissionAction
  232. {
  233. private:
  234. TRef<CadetGameContext> m_pcontext;
  235. public:
  236. CreateDroneAction(CadetGameContext* pcontext) :
  237. m_pcontext(pcontext)
  238. {
  239. }
  240. void Trigger()
  241. {
  242. Drone* pdrone = m_pcontext->GetMissionManager()->CreateDrone(c_dtWingman, "loadoutFighterDrone", 2, "Fighter",
  243. Vector(0,0,0), m_pcontext->GetShip()->GetCluster());
  244. pdrone->SetGoal(c_ctDestroy, m_pcontext->GetShip());
  245. }
  246. };
  247. //////////////////////////////////////////////////////////////////////////////
  248. //
  249. // EnteredRegionHandler
  250. //
  251. //////////////////////////////////////////////////////////////////////////////
  252. class EnteredRegionHandler : public MissionEventHandler
  253. {
  254. private:
  255. TRef<ImodelIGC> m_pmodel;
  256. TRef<Region> m_pregion;
  257. TRef<MissionAction> m_paction;
  258. bool m_bOnceOnly;
  259. public:
  260. EnteredRegionHandler(ImodelIGC* pmodel, Region* pregion, bool bOnceOnly, MissionAction* paction) :
  261. m_pmodel(pmodel),
  262. m_pregion(pregion),
  263. m_paction(paction),
  264. m_bOnceOnly(bOnceOnly)
  265. {
  266. }
  267. bool OnEnteredRegion(ImodelIGC* pmodel, Region* pregion)
  268. {
  269. if (pmodel == m_pmodel && pregion == m_pregion)
  270. {
  271. m_paction->Trigger();
  272. if (m_bOnceOnly)
  273. return false;
  274. }
  275. return true;
  276. }
  277. };
  278. //////////////////////////////////////////////////////////////////////////////
  279. //
  280. // CreateTestStage
  281. //
  282. //////////////////////////////////////////////////////////////////////////////
  283. void CreateTestStage(CadetGameContext* pcontext)
  284. {
  285. pcontext->GetMissionManager()->AdviseRegion(
  286. pcontext->GetMissionManager()->GetRegion("region1"),
  287. pcontext->GetShip()
  288. );
  289. pcontext->GetMissionManager()->AddMissionEventHandler(
  290. new EnteredRegionHandler(
  291. pcontext->GetShip(),
  292. pcontext->GetMissionManager()->GetRegion("region1"),
  293. true,
  294. new CreateDroneAction(pcontext)
  295. )
  296. );
  297. }
  298. //////////////////////////////////////////////////////////////////////////////
  299. //
  300. // CadetSceneObjects
  301. //
  302. //////////////////////////////////////////////////////////////////////////////
  303. class ICadetSceneObject : public IObject
  304. {
  305. public:
  306. virtual bool Update(Time time, float dtime) = 0;
  307. };
  308. template<class ClassType>
  309. class TDelayedCallback : public ICadetSceneObject
  310. {
  311. private:
  312. typedef void (ClassType::*PFNMember)();
  313. float m_timeDelay;
  314. TRef<ClassType> m_pobj;
  315. PFNMember m_pfn;
  316. public:
  317. TDelayedCallback(float timeDelay, ClassType* pobj, PFNMember pfn) :
  318. m_pobj(pobj),
  319. m_pfn(pfn),
  320. m_timeDelay(timeDelay)
  321. {
  322. }
  323. bool Update(Time time, float dtime)
  324. {
  325. m_timeDelay = m_timeDelay - dtime;
  326. if (m_timeDelay <= 0)
  327. {
  328. (m_pobj->*m_pfn)();
  329. return false;
  330. }
  331. return true;
  332. }
  333. };
  334. //////////////////////////////////////////////////////////////////////////////
  335. //
  336. // BaseCadetScene
  337. //
  338. //////////////////////////////////////////////////////////////////////////////
  339. class BaseCadetScene : public GameScene, public IKeyboardInput
  340. {
  341. protected:
  342. TRef<Image> m_pimage;
  343. TRef<CadetGameContext> m_pgameContext;
  344. TList<TRef<ICadetSceneObject> > m_lstSceneObjects;
  345. public:
  346. BaseCadetScene(CadetGameContext* pgameContext, Image* pimage, float dtimeDelay = 1) :
  347. m_pgameContext(pgameContext),
  348. m_pimage(pimage)
  349. {
  350. }
  351. TRef<Image> GetSceneImage()
  352. {
  353. return m_pimage;
  354. }
  355. virtual void Init()
  356. {
  357. }
  358. virtual void Term()
  359. {
  360. }
  361. virtual bool PreIgcUpdate(Time time, float dtime)
  362. {
  363. return false;
  364. }
  365. virtual void PostIgcUpdate(Time time, float dtime)
  366. {
  367. }
  368. void InitScene()
  369. {
  370. Init();
  371. GetWindow()->AddKeyboardInputFilter(this);
  372. }
  373. void TermScene()
  374. {
  375. Term();
  376. m_pimage = NULL;
  377. GetWindow()->RemoveKeyboardInputFilter(this);
  378. m_pgameContext = NULL;
  379. }
  380. void UpdateScene(Time time, float dtime)
  381. {
  382. TList<TRef<ICadetSceneObject> >::Iterator iter(m_lstSceneObjects);
  383. while (!iter.End())
  384. {
  385. if (iter.Value() != NULL)
  386. {
  387. if (!iter.Value()->Update(time, dtime))
  388. m_lstSceneObjects.Replace(iter.Value(), NULL); // mark for deletion
  389. }
  390. iter.Next();
  391. }
  392. while (m_lstSceneObjects.Remove(NULL)) {} // go through and delete
  393. if (PreIgcUpdate(time, dtime) && m_pgameContext)
  394. {
  395. AddRef(); // might terminate scene during IGC update
  396. m_pgameContext->GetMissionIGC()->Update(time);
  397. if (m_pgameContext) // this will tell us if we terminated
  398. PostIgcUpdate(time, dtime);
  399. Release();
  400. }
  401. }
  402. void AddSceneObject(ICadetSceneObject* psceneObject)
  403. {
  404. m_lstSceneObjects.PushEnd(psceneObject);
  405. }
  406. virtual bool OnKey(IInputProvider* pprovider, const KeyState& ks, bool& fForceTranslate)
  407. {
  408. if (ks.bDown)
  409. {
  410. switch (ks.vk)
  411. {
  412. case 'S':
  413. Sound::SetPlaySounds( !Sound::GetPlaySounds() );
  414. return true;
  415. case 'Q':
  416. GetWindow()->PostMessage(WM_QUIT);
  417. return true;
  418. case 'O':
  419. GetWindow()->OutputPerformanceCounters();
  420. return true;
  421. }
  422. }
  423. return false;
  424. }
  425. };
  426. //////////////////////////////////////////////////////////////////////////////
  427. //
  428. // SplashScene
  429. //
  430. //////////////////////////////////////////////////////////////////////////////
  431. class SplashScene : public BaseCadetScene
  432. {
  433. private:
  434. TRef<MenuImage> m_pmenuImage;
  435. public:
  436. SplashScene(CadetGameContext* pgameContext) :
  437. BaseCadetScene(pgameContext, Image::GetEmpty())
  438. {
  439. }
  440. void Init()
  441. {
  442. /*!!!test
  443. Sound::DefineLoopingSoundEffect(flightMusicSound, "flightmusic");
  444. Sound::PlaySoundEffect(flightMusicSound);
  445. */
  446. m_pimage = new GroupImage(
  447. m_pmenuImage = new MenuImage("cadetmenubmp", WinPoint(340,20), 3)
  448. );
  449. }
  450. void Term()
  451. {
  452. //!!!test Sound::StopSoundEffect(flightMusicSound);
  453. GetModeler()->UnloadNameSpace("splashbmp");
  454. GetModeler()->UnloadNameSpace("cadetmenubmp");
  455. }
  456. bool PreIgcUpdate(Time time, float dtime)
  457. {
  458. DIJOYSTATE dijs;
  459. Joystick::GetJoystick(&dijs);
  460. m_pmenuImage->Update(
  461. (bool)(dijs.rgbButtons[3]!=0),
  462. (bool)(dijs.rgbButtons[4]!=0),
  463. dtime);
  464. if (dijs.rgbButtons[1] || dijs.rgbButtons[2])
  465. {
  466. CadetMode cm = (CadetMode)m_pmenuImage->GetSelection();
  467. m_pgameContext->GetCadetPlay()->SetCadetMode(cm);
  468. m_pgameContext->LoadMap((cm == cmSinglePlayer) ? "spclusters" : "clusters");
  469. m_pgameContext->SwitchToScene(CreateLoadoutScene(m_pgameContext));
  470. }
  471. return false;
  472. }
  473. };
  474. TRef<GameScene> CreateSplashScene(CadetGameContext* pgameContext)
  475. {
  476. return new SplashScene(pgameContext);
  477. }
  478. //////////////////////////////////////////////////////////////////////////////
  479. //
  480. // LoadoutScene
  481. //
  482. //////////////////////////////////////////////////////////////////////////////
  483. class LoadoutScene : public BaseCadetScene, public EventTargetContainer<LoadoutScene>
  484. {
  485. private:
  486. TRef<Camera> m_pcamera;
  487. TRef<Viewport> m_pviewport;
  488. TRef<WheelGeo> m_pwheelGeo;
  489. TList<TRef<IshipIGC> > m_rgShips;
  490. bool m_bEnableStart;
  491. public:
  492. LoadoutScene(CadetGameContext* pgameContext) :
  493. BaseCadetScene(pgameContext, Image::GetEmpty()),
  494. m_bEnableStart(false)
  495. {
  496. }
  497. void AddShip(const ZString strLoadout)
  498. {
  499. SideID sideID = (m_pgameContext->GetCadetPlay()->GetCadetMode() == cmJoinSerial) ? 1 : 0;
  500. TRef<IshipIGC> pship = m_pgameContext->GetMissionManager()
  501. ->CreateShip(strLoadout, sideID, "");
  502. m_rgShips.PushEnd(pship);
  503. m_pwheelGeo->AddItem(
  504. new FaceCameraGeo(
  505. new TransformGeo(
  506. pship->GetThingSite()->GetThingGeo(),
  507. new RotateTransform(Vector(-.2f,1,.2f), RadiansFromDegrees(210))
  508. )
  509. )
  510. );
  511. }
  512. bool OnShipSel(int i)
  513. {
  514. /*ZString str;
  515. TRef<IhullTypeIGC> phullType = m_rgShips[i]->GetHullType();
  516. str += "Ship:\t" + ZString(phullType->GetDescription())
  517. + "\rMass:\t" + ZString((int)phullType->GetMass())
  518. + "\rLength:\t" + ZString((int)phullType->GetLength())
  519. + "\rSpeed:\t" + ZString((int)phullType->GetMaxSpeed())
  520. + "\rTurn Rate:\t" + ZString((int)phullType->GetMaxTurnRate(c_axisYaw))
  521. + "\rArmor:\t" + ZString(phullType->GetHitPoints());
  522. m_ptextPanelImage->SetText(str);*/
  523. return true;
  524. }
  525. void EnableStart()
  526. {
  527. m_bEnableStart = true;
  528. }
  529. TRef<Image> LoadImage24(const ZString& str)
  530. {
  531. HBITMAP hbitmap = GetModeler()->LoadBitmap(str);
  532. TRef<Surface> psurface24 = GetEngine()->CreateSurface(hbitmap);
  533. ZVerify(::DeleteObject(hbitmap));
  534. //
  535. // Convert the bitmap to 16bpp
  536. //
  537. TRef<Surface> psurface =
  538. GetEngine()->CreateSurface(
  539. psurface24->GetRect(),
  540. new PixelFormat(16, 0xf800, 0x07e0, 0x001f, 0x0000)
  541. );
  542. psurface->BitBlt(WinPoint(0, 0), psurface24);
  543. return new ConstantImage(psurface, str);
  544. }
  545. void Init()
  546. {
  547. //
  548. // Top and bottom images
  549. //
  550. //TRef<Image> pimageTop = LoadImage24("loadouttop.bmp");
  551. //TRef<Image> pimageBottom = LoadImage24("loadoutbottom.bmp");
  552. //
  553. //
  554. //
  555. m_pcamera = new Camera();
  556. m_pcamera->SetPosition(Vector(0, 0, 0));
  557. m_pcamera->SetOrientation(Orientation(Vector(0, 0, -1), Vector(0, 1, 0)));
  558. m_pcamera->SetZClip(1, 10000);
  559. m_pcamera->SetFOV(RadiansFromDegrees(65));
  560. m_pviewport = new Viewport(m_pcamera, GetWindow()->GetRenderRectValue());
  561. TRef<INameSpace> pns = GetWindow()->GetModeler()->GetNameSpace("globe");
  562. TRef<Geo> pgeoGlobe = Geo::Cast(pns->FindMember("object"));
  563. m_pwheelGeo = new WheelGeo(
  564. RadiansFromDegrees(30),
  565. RadiansFromDegrees(30),
  566. 50, 50);
  567. m_pimage =
  568. new GroupImage(
  569. //GetModeler()->LoadImage("loadoutbmp", true),
  570. //new TranslateImage(pimageTop, Point(0, 480 - pimageTop->GetBounds().GetRect().YSize())),
  571. //new TranslateImage(pimageBottom, Point(640 - pimageTop->GetBounds().GetRect().XSize(), 0)),
  572. new GeoImage(m_pwheelGeo, m_pviewport, true),
  573. new GeoImage(pgeoGlobe, m_pviewport, false)
  574. );
  575. AddEventTarget(OnShipSel, m_pwheelGeo->GetEventSource());
  576. AddSceneObject(new TDelayedCallback<LoadoutScene>(1.0f, this, EnableStart));
  577. AddShip("loadoutFighter");
  578. AddShip("loadoutBomber");
  579. AddShip("loadoutScarab");
  580. AddShip("loadoutFox");
  581. }
  582. void Term()
  583. {
  584. TList<TRef<IshipIGC> >::Iterator iter(m_rgShips);
  585. while (!iter.End())
  586. {
  587. iter.Value()->Terminate();
  588. iter.Next();
  589. }
  590. GetModeler()->UnloadNameSpace("loadoutbmp");
  591. }
  592. bool PreIgcUpdate(Time time, float dtime)
  593. {
  594. DIJOYSTATE dijs;
  595. Joystick::GetJoystick(&dijs);
  596. m_pwheelGeo->Update(
  597. (bool)(dijs.rgbButtons[5]!=0 || dijs.rgbButtons[10]!=0),
  598. (bool)(dijs.rgbButtons[6]!=0 || dijs.rgbButtons[9]!=0),
  599. dtime);
  600. if ((dijs.rgbButtons[1] || dijs.rgbButtons[2]) && m_bEnableStart)
  601. {
  602. TRef<IshipIGC> pship = m_rgShips[m_pwheelGeo->GetSelItem()];
  603. m_pgameContext->SetShip(pship);
  604. pship->SetPosition(Vector(.0001f,.0001f,.0001f));
  605. m_rgShips.Remove(pship);
  606. m_pgameContext->SwitchToScene(CreateFlightScene(m_pgameContext));
  607. return false;
  608. }
  609. return false;
  610. }
  611. };
  612. TRef<GameScene> CreateLoadoutScene(CadetGameContext* pgamecontext)
  613. {
  614. return new LoadoutScene(pgamecontext);
  615. }
  616. //////////////////////////////////////////////////////////////////////////////
  617. //
  618. // FlightScene
  619. //
  620. //////////////////////////////////////////////////////////////////////////////
  621. class FlightScene : public BaseCadetScene, public CadetPlaySite
  622. {
  623. private:
  624. TRef<TerrainTileData> m_ptileDataRight;
  625. TRef<TerrainTileData> m_ptileDataStraight;
  626. TRef<TerrainMap> m_pmap;
  627. TRef<TerrainTile> m_ptile;
  628. TRef<TextPanelImage> m_ptextPanelImage;
  629. bool m_bEnableStart;
  630. bool m_bCreatedHelp;
  631. enum ViewMode { vmChase, vmCockpit };
  632. ViewMode m_viewMode;
  633. ShipControlStateIGC m_fireMode;
  634. public:
  635. FlightScene(CadetGameContext* pgameContext) :
  636. BaseCadetScene(pgameContext, Image::GetEmpty()),
  637. m_bEnableStart(false),
  638. m_bCreatedHelp(false),
  639. m_viewMode(vmChase),
  640. m_fireMode(oneWeaponIGC)
  641. {
  642. }
  643. void EnableStart()
  644. {
  645. m_bEnableStart = true;
  646. }
  647. void CreateAttack()
  648. {
  649. int cAttackers = 0;
  650. SideID sideID = m_pgameContext->GetShip()->GetSide()->GetObjectID();
  651. const ModelListIGC* models = m_pgameContext->GetCluster()->GetModels();
  652. assert (models);
  653. for (ModelLinkIGC* l = models->first(); (l != NULL); l = l->next())
  654. {
  655. ImodelIGC* pmodel = l->data();
  656. if (pmodel->GetObjectType() == OT_ship &&
  657. pmodel->GetSide()->GetObjectID() != sideID)
  658. cAttackers++;
  659. }
  660. if (cAttackers < 7)
  661. {
  662. Drone* pdrone = m_pgameContext->GetMissionManager()->CreateDrone(c_dtWingman, "loadoutFighterDrone", 1, "Fighter",
  663. Vector(-1000,0,0), m_pgameContext->GetShip()->GetCluster());
  664. }
  665. else if (!m_bCreatedHelp)
  666. {
  667. m_bCreatedHelp = true;
  668. Drone* pdrone = m_pgameContext->GetMissionManager()->CreateDrone(c_dtWingman, "loadoutBomber", 0, "Bomber",
  669. Vector(-1000,0,0), m_pgameContext->GetShip()->GetCluster());
  670. }
  671. AddSceneObject(new TDelayedCallback<FlightScene>(15.0f, this, CreateAttack));
  672. }
  673. void CreateMiner()
  674. {
  675. int cFriendlies = 0;
  676. SideID sideID = m_pgameContext->GetShip()->GetSide()->GetObjectID();
  677. const ModelListIGC* models = m_pgameContext->GetCluster()->GetModels();
  678. assert (models);
  679. for (ModelLinkIGC* l = models->first(); (l != NULL); l = l->next())
  680. {
  681. ImodelIGC* pmodel = l->data();
  682. if (pmodel->GetObjectType() == OT_ship &&
  683. pmodel->GetSide()->GetObjectID() == sideID)
  684. cFriendlies++;
  685. }
  686. if (cFriendlies < 7)
  687. {
  688. Drone* pdrone = m_pgameContext->GetMissionManager()->CreateDrone(c_dtMining, "loadoutMinerDrone", 0, "Miner",
  689. Vector(700,0,-500), m_pgameContext->GetShip()->GetCluster());
  690. }
  691. AddSceneObject(new TDelayedCallback<FlightScene>(35.0f, this, CreateMiner));
  692. }
  693. void Init()
  694. {
  695. m_pimage = m_pgameContext->GetFlightImage();
  696. m_pgameContext->GetCadetPlay()->SetCadetPlaySite(this);
  697. if (m_pgameContext->GetCadetPlay()->GetCadetMode() == cmHostSerial ||
  698. m_pgameContext->GetCadetPlay()->GetCadetMode() == cmHostModem)
  699. {
  700. HRESULT hr = m_pgameContext->GetCadetPlay()->HostSession();
  701. ZAssert(SUCCEEDED(hr));
  702. }
  703. else if (m_pgameContext->GetCadetPlay()->GetCadetMode() == cmSinglePlayer)
  704. {
  705. AddSceneObject(new TDelayedCallback<FlightScene>(15.0f, this, CreateMiner));
  706. AddSceneObject(new TDelayedCallback<FlightScene>(15.0f, this, CreateAttack));
  707. AddSceneObject(new TDelayedCallback<FlightScene>(1.0f, this, EnableStart));
  708. }
  709. else
  710. {
  711. HRESULT hr = m_pgameContext->GetCadetPlay()->JoinSession(
  712. m_pgameContext->GetMissionIGC());
  713. ZAssert(SUCCEEDED(hr));
  714. }
  715. /*
  716. TRef<Geo> pgeo = GetModeler()->LoadGeo("canyon");
  717. m_pgameContext->GetFlightImage()->AddGeo(
  718. new TransformGeo(
  719. pgeo,
  720. new ScaleTransform(10)
  721. )
  722. );
  723. */
  724. Sound::PlaySoundEffect(inSound);
  725. }
  726. void Term()
  727. {
  728. if (m_ptextPanelImage)
  729. m_pgameContext->GetFlightImage()->RemoveImage(m_ptextPanelImage);
  730. m_pgameContext->GetCadetPlay()->SetCadetPlaySite(NULL);
  731. Sound::StopSoundEffect(inSound);
  732. Sound::StopSoundEffect(outSound);
  733. Sound::StopSoundEffect(turnSound);
  734. Sound::StopSoundEffect(accelSound);
  735. }
  736. bool PreIgcUpdate(Time time, float dtime)
  737. {
  738. if (m_pgameContext->GetCadetPlay()->GetCadetMode() != cmSinglePlayer)
  739. m_pgameContext->GetCadetPlay()->ReceiveMessages();
  740. if (m_ptextPanelImage)
  741. m_ptextPanelImage->Update(dtime);
  742. DIJOYSTATE dijs;
  743. Joystick::GetJoystick(&dijs);
  744. ControlData controls;
  745. controls.Reset();
  746. Time timeLastFrame = time - dtime;
  747. int buttonsM = m_pgameContext->GetShip()->GetStateM() & (noCollisionDetectionIGC |
  748. coastButtonIGC |
  749. cloakActiveIGC);
  750. if (dijs.rgbButtons[2] && m_bEnableStart) //Start
  751. {
  752. m_pgameContext->SwitchToScene(CreateLoadoutScene(m_pgameContext));
  753. return false;
  754. }
  755. if (dijs.rgbButtons[3])
  756. {
  757. if (m_viewMode != vmCockpit)
  758. {
  759. m_viewMode = vmCockpit;
  760. m_pgameContext->GetShip()->GetThingSite()->SetVisible(c_ucRenderNone);
  761. Sound::StopSoundEffect(outSound);
  762. Sound::PlaySoundEffect(inSound);
  763. }
  764. }
  765. else if (dijs.rgbButtons[4])
  766. {
  767. if (m_viewMode != vmChase)
  768. {
  769. m_viewMode = vmChase;
  770. m_pgameContext->GetShip()->GetThingSite()->SetVisible(c_ucRenderAll);
  771. Sound::StopSoundEffect(inSound);
  772. Sound::PlaySoundEffect(outSound);
  773. }
  774. }
  775. if (dijs.rgbButtons[5])
  776. m_fireMode = oneWeaponIGC;
  777. if (dijs.rgbButtons[6])
  778. m_fireMode = allWeaponsIGC;
  779. if (dijs.rgbButtons[0]) //B
  780. buttonsM |= m_fireMode;
  781. if (dijs.rgbButtons[1])
  782. buttonsM |= forwardButtonIGC; //A
  783. if (dijs.rgbButtons[7])
  784. buttonsM |= afterburnerButtonIGC; //Y
  785. if (dijs.rgbButtons[8])
  786. buttonsM |= missileFireIGC; //X
  787. if (dijs.rgbButtons[9])
  788. controls.jsValues[c_axisRoll] = -1.0f;
  789. if (dijs.rgbButtons[10])
  790. controls.jsValues[c_axisRoll] = 1.0f;
  791. controls.jsValues[c_axisYaw] = -dijs.lX/100.0f;
  792. controls.jsValues[c_axisPitch] = -dijs.lY/100.0f;
  793. m_pgameContext->GetShip()->SetControls(controls);
  794. m_pgameContext->GetShip()->SetStateBits(timeLastFrame, buttonsMaskIGC | weaponsMaskIGC | selectedWeaponMaskIGC | missileFireIGC, buttonsM);
  795. //Play sound effects appropriate for the maneuvers of the player's ship.
  796. float turn = (controls.jsValues[c_axisYaw] * controls.jsValues[c_axisYaw] +
  797. controls.jsValues[c_axisPitch] * controls.jsValues[c_axisPitch] +
  798. controls.jsValues[c_axisRoll] * controls.jsValues[c_axisRoll]);
  799. if (turn > 0.05f)
  800. Sound::PlaySoundEffect(turnSound);
  801. else
  802. Sound::StopSoundEffect(turnSound);
  803. float thrust = m_pgameContext->GetShip()->GetHullType()->GetThrust();
  804. if (m_pgameContext->GetShip()->GetEngineVector().LengthSquared() > 0.10f * thrust * thrust)
  805. Sound::PlaySoundEffect(accelSound);
  806. else
  807. Sound::StopSoundEffect(accelSound);
  808. return true;
  809. }
  810. void PostIgcUpdate(Time time, float dtime)
  811. {
  812. Orientation cameraOrientation = m_pgameContext->GetShip()->GetOrientation();
  813. Vector cameraPosition;
  814. if (m_viewMode == vmChase)
  815. {
  816. float vel2 = m_pgameContext->GetShip()->GetVelocity().LengthSquared();
  817. if (vel2 > 0.0f)
  818. {
  819. float maxVel = m_pgameContext->GetShip()->GetHullType()->GetMaxSpeed();
  820. cameraPosition = m_pgameContext->GetShip()->GetPosition()
  821. - m_pgameContext->GetShip()->GetVelocity().Normalize() * (.4f * m_pgameContext->GetShip()->GetRadius() * (sqrt(vel2) / maxVel))
  822. - cameraOrientation.GetForward() * (3.0f * m_pgameContext->GetShip()->GetRadius())
  823. + cameraOrientation.GetUp() * (.7f * m_pgameContext->GetShip()->GetRadius());
  824. }
  825. else
  826. cameraPosition = m_pgameContext->GetShip()->GetPosition()
  827. - cameraOrientation.GetForward() * (3.0f * m_pgameContext->GetShip()->GetRadius())
  828. + cameraOrientation.GetUp() * (.7f * m_pgameContext->GetShip()->GetRadius());
  829. }
  830. else
  831. {
  832. cameraPosition = m_pgameContext->GetShip()->GetPosition();
  833. }
  834. m_pgameContext->GetFlightImage()->SetCameraOrientation(cameraOrientation);
  835. m_pgameContext->GetFlightImage()->SetCameraPosition(cameraPosition);
  836. if (m_pgameContext->GetCadetPlay()->GetCadetMode() != cmSinglePlayer)
  837. m_pgameContext->GetCadetPlay()->SendShipUpdateMessages(
  838. m_pgameContext->GetMissionIGC());
  839. //detect collisions with map
  840. static bool hitLast = false;
  841. if (m_pmap)
  842. {
  843. if (hitLast && !m_pmap->HitTest(m_pgameContext->GetShip()->GetPosition()))
  844. hitLast = false;
  845. else if (!hitLast && m_pmap->HitTest(m_pgameContext->GetShip()->GetPosition()))
  846. {
  847. hitLast = true;
  848. Sound::PlaySoundEffect(myHullHitSound);
  849. }
  850. }
  851. }
  852. bool OnKey(IInputProvider* pprovider, const KeyState& ks, bool& fForceTranslate)
  853. {
  854. if (ks.bDown)
  855. {
  856. switch (ks.vk)
  857. {
  858. case '0':
  859. {
  860. // load map
  861. m_ptileDataStraight = TerrainTileData::Create(GetStraight());
  862. m_ptileDataRight = TerrainTileData::Create(GetRight());
  863. m_pmap = TerrainMap::Create();
  864. m_ptile = m_pmap->SetRoot(m_pmap->CreateTile(m_ptileDataStraight));
  865. m_pgameContext->GetFlightImage()->AddGeo(m_pmap->GetGeo());
  866. if (m_pgameContext->GetCadetPlay()->GetCadetMode() != cmSinglePlayer)
  867. {
  868. TerrainChangeMessage msg;
  869. msg.msgID = TerrainChangeMessageID;
  870. msg.cbMsg = sizeof(TerrainChangeMessage);
  871. msg.tc = tcInit;
  872. m_pgameContext->GetCadetPlay()->SendMessage(&msg);
  873. }
  874. return true;
  875. }
  876. case '1':
  877. {
  878. m_ptile = m_pmap->Connect(m_ptile, 0, m_pmap->CreateTile(m_ptileDataStraight));
  879. if (m_pgameContext->GetCadetPlay()->GetCadetMode() != cmSinglePlayer)
  880. {
  881. TerrainChangeMessage msg;
  882. msg.msgID = TerrainChangeMessageID;
  883. msg.cbMsg = sizeof(TerrainChangeMessage);
  884. msg.tc = tcStraight;
  885. m_pgameContext->GetCadetPlay()->SendMessage(&msg);
  886. }
  887. return true;
  888. }
  889. case '2':
  890. {
  891. m_ptile = m_pmap->Connect(m_ptile, 0, m_pmap->CreateTile(m_ptileDataRight));
  892. if (m_pgameContext->GetCadetPlay()->GetCadetMode() != cmSinglePlayer)
  893. {
  894. TerrainChangeMessage msg;
  895. msg.msgID = TerrainChangeMessageID;
  896. msg.cbMsg = sizeof(TerrainChangeMessage);
  897. msg.tc = tcTurn;
  898. m_pgameContext->GetCadetPlay()->SendMessage(&msg);
  899. }
  900. return true;
  901. }
  902. case 'C':
  903. {
  904. ChatMessage chatMsg;
  905. chatMsg.msgID = ChatMessageID;
  906. chatMsg.cbMsg = sizeof(ChatMessage);
  907. strcpy(chatMsg.szMsg, "This is a chat.");
  908. m_pgameContext->GetCadetPlay()->SendMessage(&chatMsg);
  909. return true;
  910. }
  911. case 'M':
  912. {
  913. Drone* pdrone = m_pgameContext->GetMissionManager()->CreateDrone(c_dtMining, "loadoutMinerDrone", 2, "Miner",
  914. Vector::RandomPosition(1000), m_pgameContext->GetShip()->GetCluster());
  915. return true;
  916. }
  917. }
  918. }
  919. return BaseCadetScene::OnKey(pprovider, ks, fForceTranslate);
  920. }
  921. void ShowText(const ZString& str)
  922. {
  923. if (!m_ptextPanelImage)
  924. {
  925. m_ptextPanelImage = new TextPanelImage(Point(320,100), WinPoint(256,128), WinPoint(10,10), 80);
  926. m_pgameContext->GetFlightImage()->AddImage(m_ptextPanelImage);
  927. }
  928. m_ptextPanelImage->SetText(str);
  929. }
  930. void HideText()
  931. {
  932. if (m_ptextPanelImage)
  933. {
  934. m_pgameContext->GetFlightImage()->RemoveImage(m_ptextPanelImage);
  935. m_ptextPanelImage = NULL;
  936. }
  937. }
  938. void OnAppMessage(CadetMessage* pmsg)
  939. {
  940. switch (pmsg->msgID)
  941. {
  942. case ChatMessageID:
  943. {
  944. ChatMessage* pchatMsg = (ChatMessage*)pmsg;
  945. debugf(pchatMsg->szMsg);
  946. debugf("\r\n");
  947. break;
  948. }
  949. case TerrainChangeMessageID:
  950. {
  951. TerrainChangeMessage* pterrainMsg = (TerrainChangeMessage*)pmsg;
  952. switch (pterrainMsg->tc)
  953. {
  954. case tcInit:
  955. {
  956. m_ptileDataStraight = TerrainTileData::Create(GetStraight());
  957. m_ptileDataRight = TerrainTileData::Create(GetRight());
  958. m_pmap = TerrainMap::Create();
  959. m_ptile = m_pmap->SetRoot(m_pmap->CreateTile(m_ptileDataStraight));
  960. m_pgameContext->GetFlightImage()->AddGeo(m_pmap->GetGeo());
  961. break;
  962. }
  963. case tcStraight:
  964. {
  965. m_ptile = m_pmap->Connect(m_ptile, 0, m_pmap->CreateTile(m_ptileDataStraight));
  966. break;
  967. }
  968. case tcTurn:
  969. {
  970. m_ptile = m_pmap->Connect(m_ptile, 0, m_pmap->CreateTile(m_ptileDataRight));
  971. break;
  972. }
  973. }
  974. break;
  975. }
  976. default:
  977. {
  978. m_pgameContext->GetCadetPlay()->HandleIGCMessage(
  979. m_pgameContext->GetMissionIGC(),
  980. pmsg);
  981. }
  982. }
  983. }
  984. };
  985. TRef<GameScene> CreateFlightScene(CadetGameContext* pgameContext)
  986. {
  987. return new FlightScene(pgameContext);
  988. }