mission.cpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. #include "pch.h"
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // IGCObjectFactory
  5. //
  6. //////////////////////////////////////////////////////////////////////////////
  7. #if 0
  8. typedef TRef<IObject> TRefIObject; //hack for VC5
  9. template<class ClassType>
  10. class TIGCObjectFactory : public IFunction
  11. {
  12. private:
  13. typedef TRef<IObject> (ClassType::*PFNMember)(ObjectStack& stack);
  14. TRef<ClassType> m_pobj;
  15. PFNMember m_pfn;
  16. public:
  17. TIGCObjectFactory(ClassType* pobj, PFNMember pfn) :
  18. m_pobj(pobj),
  19. m_pfn(pfn)
  20. {
  21. }
  22. TRefIObject Apply(ObjectStack& stack)
  23. {
  24. return (m_pobj->*m_pfn)(stack);
  25. }
  26. };
  27. //////////////////////////////////////////////////////////////////////////////
  28. //
  29. // SphericalRegion
  30. //
  31. //////////////////////////////////////////////////////////////////////////////
  32. class SphericalRegionImpl : public SphericalRegion
  33. {
  34. private:
  35. TRef<ImodelIGC> m_pmodelCenter;
  36. float m_radiusSquared;
  37. public:
  38. SphericalRegionImpl(ImodelIGC* pmodel, float radius) :
  39. m_pmodelCenter(pmodel),
  40. m_radiusSquared(radius * radius)
  41. {
  42. }
  43. bool InRegion(ImodelIGC* pmodel)
  44. {
  45. return ((pmodel->GetPosition()
  46. - m_pmodelCenter->GetPosition()).LengthSquared()
  47. <= m_radiusSquared);
  48. }
  49. };
  50. TRef<SphericalRegion> SphericalRegion::Create(ImodelIGC* pmodel, float radius)
  51. {
  52. return new SphericalRegionImpl(pmodel, radius);
  53. }
  54. //////////////////////////////////////////////////////////////////////////////
  55. //
  56. // RegionAdviseEntry
  57. //
  58. //////////////////////////////////////////////////////////////////////////////
  59. class RegionAdviseEntry : public IObject
  60. {
  61. private:
  62. TRef<Region> m_pregion;
  63. TMap<TRef<ImodelIGC>, bool> m_mapInRegion;
  64. TList<TRef<ImodelIGC> > m_lstUnadvise;
  65. public:
  66. RegionAdviseEntry(Region* pregion) :
  67. m_pregion(pregion)
  68. {
  69. }
  70. void Advise(ImodelIGC* pmodel)
  71. {
  72. m_mapInRegion.Set(pmodel, m_pregion->InRegion(pmodel));
  73. m_lstUnadvise.Remove(pmodel);
  74. }
  75. void Unadvise(ImodelIGC* pmodel)
  76. {
  77. m_lstUnadvise.PushEnd(pmodel);
  78. }
  79. void UpdateUnadvise()
  80. {
  81. TList<TRef<ImodelIGC> >::Iterator iter(m_lstUnadvise);
  82. while (!iter.End())
  83. {
  84. m_mapInRegion.Remove(iter.Value());
  85. iter.Next();
  86. }
  87. m_lstUnadvise.SetEmpty();
  88. }
  89. void Update(MissionManager* pmanager)
  90. {
  91. TMap<TRef<ImodelIGC>, bool>::Iterator iter(m_mapInRegion);
  92. while (!iter.End())
  93. {
  94. bool bInRegion = iter.Value();
  95. TRef<ImodelIGC> pmodel = iter.Key();
  96. if (bInRegion != m_pregion->InRegion(pmodel) &&
  97. !m_lstUnadvise.Find(pmodel))
  98. {
  99. if (bInRegion)
  100. pmanager->FireOnExitedRegion(pmodel, m_pregion);
  101. else
  102. pmanager->FireOnEnteredRegion(pmodel, m_pregion);
  103. m_mapInRegion.Set(pmodel, !bInRegion);
  104. }
  105. iter.Next();
  106. }
  107. UpdateUnadvise();
  108. }
  109. };
  110. //////////////////////////////////////////////////////////////////////////////
  111. //
  112. // MissionManager
  113. //
  114. //////////////////////////////////////////////////////////////////////////////
  115. class MissionManagerImpl : public MissionManager
  116. {
  117. private:
  118. TRef<MissionContext> m_pmissionContext;
  119. TList<TRef<MissionEventHandler> > m_lstEventHandlers;
  120. TMap<TRef<Region>, TRef<RegionAdviseEntry> > m_mapRegionAdviseEntries;
  121. TRef<MissionStage> m_pmissionStage;
  122. TRef<INameSpace> m_pnsClusters;
  123. TRef<INameSpace> m_pnsTechTree;
  124. short m_clusterIDNext;
  125. short m_asteroidIDNext;
  126. short m_stationTypeIDNext;
  127. short m_hullIDNext;
  128. short m_partTypeIDNext;
  129. short m_shipIDNext;
  130. short m_projectileTypeIDNext;
  131. short m_expendableTypeIDNext;
  132. public:
  133. MissionManagerImpl(MissionContext* pmissionContext) :
  134. m_pmissionContext(pmissionContext),
  135. m_clusterIDNext(0),
  136. m_asteroidIDNext(0),
  137. m_hullIDNext(0),
  138. m_stationTypeIDNext(0),
  139. m_partTypeIDNext(0),
  140. m_projectileTypeIDNext(0),
  141. m_expendableTypeIDNext(0),
  142. m_shipIDNext(0)
  143. {
  144. }
  145. TRef<IhullTypeIGC> GetHullType(const ZString& strHullType)
  146. {
  147. TRef<IhullTypeIGC> phullType;
  148. if (m_pnsTechTree)
  149. phullType = (IhullTypeIGC*)m_pnsTechTree->FindMember(strHullType);
  150. return phullType;
  151. }
  152. int ReadPartData(IhullTypeIGC* phullType, PartData* ppartData, IObjectList* ppartsList)
  153. {
  154. Mount rgMounts[ET_MAX - 1];
  155. memset(rgMounts, 0, sizeof(Mount)*(ET_MAX-1));
  156. int nParts = 0;
  157. ppartsList->GetFirst();
  158. while (NULL != ppartsList->GetCurrent())
  159. {
  160. TRef<IpartTypeIGC> ppartType = (IpartTypeIGC*)ppartsList->GetCurrent();
  161. EquipmentType et = ppartType->GetEquipmentType();
  162. Mount mountETMax = 1;
  163. if (ET_Weapon == et)
  164. mountETMax = phullType->GetMaxWeapons();
  165. nParts++;
  166. rgMounts[et-1]++;
  167. ppartData->partID = ppartType->GetObjectID();
  168. ppartData->mountID = rgMounts[et-1] > mountETMax ? NA : rgMounts[et-1]-1;
  169. ppartData->amount = 0;
  170. ppartData++;
  171. ppartsList->GetNext();
  172. }
  173. return nParts;
  174. }
  175. /*
  176. Drone* CreateDrone(DroneType dt, const ZString& strLoadout, SideID sideID, const ZString& strName,
  177. const Vector& pos, IclusterIGC* pcluster)
  178. {
  179. ZAssert(m_pnsTechTree);
  180. TRef<IObjectList> pparamList = (IObjectList*)m_pnsTechTree->FindMember(strLoadout);
  181. // hulltype
  182. TRef<IhullTypeIGC> phullType = (IhullTypeIGC*)pparamList->GetFirst();
  183. HullID hullID = phullType->GetObjectID();
  184. // parts
  185. TRef<IObjectList> ppartsList = (IObjectList*)pparamList->GetNext();
  186. PartData partData[10];
  187. int cParts = ReadPartData(phullType, partData, ppartsList);
  188. Drone* pdrone = g_drones.Create(
  189. m_pmissionContext->GetMissionIGC(),
  190. dt,
  191. strName,
  192. hullID,
  193. m_pmissionContext->GetMissionIGC()->GetSide(sideID),
  194. cParts,
  195. partData);
  196. pdrone->GetShip()->SetPosition(pos);
  197. pdrone->GetShip()->SetCluster(pcluster);
  198. return pdrone;
  199. }
  200. */
  201. TRef<IshipIGC> CreateShip(const ZString& strLoadout, SideID sideID, const ZString& strName)
  202. {
  203. ZAssert(m_pnsTechTree);
  204. char buf[4096];
  205. DataShipIGC* pdata = (DataShipIGC*)buf;
  206. PartData* ppartData = (PartData*)(buf + sizeof(DataShipIGC));
  207. TRef<IObjectList> pparamList = (IObjectList*)m_pnsTechTree->FindMember(strLoadout);
  208. TRef<IhullTypeIGC> phullType = (IhullTypeIGC*)pparamList->GetFirst();
  209. pdata->hullID = phullType->GetObjectID();
  210. pdata->shipID = m_shipIDNext++;
  211. pdata->sideID = 0;
  212. pdata->wingID = 0;
  213. pdata->nKills = 0;
  214. pdata->nDeaths = 0;
  215. strcpy(pdata->name, strName);
  216. pdata->partsOffset = sizeof(DataShipIGC);
  217. TRef<IObjectList> ppartsList = (IObjectList*)pparamList->GetNext();
  218. pdata->nParts = ReadPartData(phullType, ppartData, ppartsList);
  219. IshipIGC* pship = (IshipIGC*)m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(), OT_ship, pdata, sizeof(DataShipIGC) + sizeof(PartData)*pdata->nParts);
  220. pship->Release();
  221. return pship;
  222. }
  223. void LoadClusters(const ZString& strMdlFile)
  224. {
  225. TRef<INameSpace> pns =
  226. m_pmissionContext->GetModeler()->CreateNameSpace(
  227. "mission",
  228. m_pmissionContext->GetModeler()->GetNameSpace("model"));
  229. pns->AddMember("CreateCluster", new TIGCObjectFactory<MissionManagerImpl>(this, CreateCluster));
  230. pns->AddMember("CreateAsteroid", new TIGCObjectFactory<MissionManagerImpl>(this, CreateAsteroid));
  231. pns->AddMember("CreateSphericalRegion", new TIGCObjectFactory<MissionManagerImpl>(this, CreateSphericalRegion));
  232. //pns->AddMember("CreateDrone", new TIGCObjectFactory<MissionManagerImpl>(this, CreateDrone));
  233. pns->AddMember("CreateStation", new TIGCObjectFactory<MissionManagerImpl>(this, CreateStation));
  234. m_pnsClusters =
  235. m_pmissionContext->GetModeler()->GetNameSpace(strMdlFile);
  236. }
  237. void LoadTechTree(const ZString& strMdlFile)
  238. {
  239. TRef<INameSpace> pns =
  240. m_pmissionContext->GetModeler()->CreateNameSpace(
  241. "mission",
  242. m_pmissionContext->GetModeler()->GetNameSpace("model"));
  243. pns->AddMember("CreateStationType", new TIGCObjectFactory<MissionManagerImpl>(this, CreateStationType));
  244. pns->AddMember("CreateHullType", new TIGCObjectFactory<MissionManagerImpl>(this, CreateHullType));
  245. pns->AddMember("CreateAfterburnerType", new TIGCObjectFactory<MissionManagerImpl>(this, CreateAfterburnerType));
  246. pns->AddMember("CreatePackType", new TIGCObjectFactory<MissionManagerImpl>(this, CreatePackType));
  247. pns->AddMember("CreateProjectileType", new TIGCObjectFactory<MissionManagerImpl>(this, CreateProjectileType));
  248. pns->AddMember("CreateWeaponType", new TIGCObjectFactory<MissionManagerImpl>(this, CreateWeaponType));
  249. pns->AddMember("CreateMissileType", new TIGCObjectFactory<MissionManagerImpl>(this, CreateMissileType));
  250. pns->AddMember("CreateMissileLauncherType", new TIGCObjectFactory<MissionManagerImpl>(this, CreateMissileLauncherType));
  251. m_pnsTechTree =
  252. m_pmissionContext->GetModeler()->GetNameSpace(strMdlFile);
  253. }
  254. void ReadBuyableData(DataBuyableIGC* pdata, ObjectStack& stack)
  255. {
  256. pdata->price = (Money)GetNumber((IObject*)stack.Pop());
  257. strcpy(pdata->modelName, GetString((IObject*)stack.Pop()));
  258. pdata->iconName[0] = '\0';
  259. strcpy(pdata->name, GetString((IObject*)stack.Pop()));
  260. strcpy(pdata->description, GetString((IObject*)stack.Pop()));
  261. TRef<IObjectList> plistRequired; CastTo(plistRequired, (IObject*)stack.Pop());
  262. plistRequired->GetFirst();
  263. while (NULL != plistRequired->GetCurrent())
  264. {
  265. pdata->ttbmRequired.SetBit((int)GetNumber((IObject*)plistRequired->GetCurrent()));
  266. plistRequired->GetNext();
  267. }
  268. TRef<IObjectList> plistEffects; CastTo(plistEffects, (IObject*)stack.Pop());
  269. plistEffects->GetFirst();
  270. while (NULL != plistEffects->GetCurrent())
  271. {
  272. pdata->ttbmEffects.SetBit((int)GetNumber((IObject*)plistEffects->GetCurrent()));
  273. plistEffects->GetNext();
  274. }
  275. }
  276. void ReadPartTypeData(DataPartTypeIGC* pdata, EquipmentType et, ObjectStack& stack)
  277. {
  278. ReadBuyableData(pdata, stack);
  279. pdata->partID = m_partTypeIDNext++;
  280. pdata->successorPartID = NA;
  281. pdata->equipmentType = et;
  282. pdata->mass = GetNumber((IObject*)stack.Pop());
  283. pdata->signature = GetNumber((IObject*)stack.Pop());
  284. pdata->treasureChance = (short)GetNumber((IObject*)stack.Pop());
  285. pdata->partSize = (PartSize)GetNumber((IObject*)stack.Pop());
  286. }
  287. void ReadDataObject(DataObjectIGC* pdata, ObjectStack& stack)
  288. {
  289. pdata->color.r = pdata->color.g = pdata->color.b = pdata->color.a = 0; //GetColor((IObject*)stack.Pop());
  290. pdata->radius = GetNumber((IObject*)stack.Pop());
  291. pdata->rotation = GetNumber((IObject*)stack.Pop());
  292. strcpy(pdata->modelName, GetString((IObject*)stack.Pop()));
  293. strcpy(pdata->textureName, GetString((IObject*)stack.Pop()));
  294. }
  295. void ReadLauncherDef(LauncherDef* pdata, ObjectStack& stack)
  296. {
  297. ReadBuyableData(pdata, stack);
  298. pdata->signature = GetNumber((IObject*)stack.Pop());
  299. pdata->mass = GetNumber((IObject*)stack.Pop());
  300. pdata->partSize = (PartSize)GetNumber((IObject*)stack.Pop());
  301. }
  302. void ReadDataExpendableType(DataExpendableTypeIGC* pdata, ObjectStack& stack)
  303. {
  304. ReadDataObject(pdata, stack);
  305. pdata->expendabletypeID = m_expendableTypeIDNext++;
  306. pdata->loadTime = GetNumber((IObject*)stack.Pop());
  307. pdata->lifespan = GetNumber((IObject*)stack.Pop());
  308. pdata->signature = GetNumber((IObject*)stack.Pop());
  309. pdata->hitPoints = (HitPoints)GetNumber((IObject*)stack.Pop());
  310. ReadLauncherDef(&(pdata->launcherDef), stack);
  311. }
  312. TRef<IObject> CreateAfterburnerType(ObjectStack& stack)
  313. {
  314. DataAfterburnerTypeIGC afterburner;
  315. ReadPartTypeData(&afterburner, ET_Afterburner, stack);
  316. afterburner.fuelConsumption = GetNumber((IObject*)stack.Pop());
  317. afterburner.maxThrust = GetNumber((IObject*)stack.Pop());
  318. afterburner.onRate = GetNumber((IObject*)stack.Pop());
  319. afterburner.offRate = GetNumber((IObject*)stack.Pop());
  320. afterburner.thrustMultiplier = GetNumber((IObject*)stack.Pop());
  321. afterburner.interiorSound = (SoundID)GetNumber((IObject*)stack.Pop());
  322. afterburner.exteriorSound = (SoundID)GetNumber((IObject*)stack.Pop());
  323. IObject* pobject = m_pmissionContext->GetMissionIGC()->CreateObject(
  324. Time::Now(), OT_partType,
  325. &afterburner, sizeof(afterburner));
  326. pobject->Release();
  327. return pobject;
  328. }
  329. TRef<IObject> CreateMissileType(ObjectStack& stack)
  330. {
  331. DataMissileTypeIGC missile;
  332. ReadDataExpendableType(&missile, stack);
  333. missile.acceleration = GetNumber((IObject*)stack.Pop());
  334. missile.turnRate = GetNumber((IObject*)stack.Pop());
  335. missile.initialSpeed = GetNumber((IObject*)stack.Pop());
  336. missile.armTime = GetNumber((IObject*)stack.Pop());
  337. missile.lockTime = GetNumber((IObject*)stack.Pop());
  338. missile.readyTime = GetNumber((IObject*)stack.Pop());
  339. missile.dispersion = GetNumber((IObject*)stack.Pop());
  340. missile.lockAngle = GetNumber((IObject*)stack.Pop());
  341. missile.power = GetNumber((IObject*)stack.Pop());
  342. missile.blastPower = GetNumber((IObject*)stack.Pop());
  343. missile.blastRadius = GetNumber((IObject*)stack.Pop());
  344. missile.width = GetNumber((IObject*)stack.Pop());
  345. missile.damageType = (DamageTypeMask)GetNumber((IObject*)stack.Pop());
  346. missile.bDirectional = GetBoolean((IObject*)stack.Pop());
  347. missile.launchSound = (SoundID)GetNumber((IObject*)stack.Pop());
  348. missile.ambientSound = (SoundID)GetNumber((IObject*)stack.Pop());
  349. IObject* pobject = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(),
  350. OT_missileType, &missile, sizeof(missile));
  351. pobject->Release();
  352. return pobject;
  353. }
  354. TRef<IObject> CreateMissileLauncherType(ObjectStack& stack)
  355. {
  356. DataLauncherTypeIGC launcher;
  357. launcher.partID = m_partTypeIDNext++;
  358. launcher.successorPartID = NA;
  359. TRef<ImissileTypeIGC> pmissileType = (ImissileTypeIGC*)(IObject*)stack.Pop();
  360. launcher.expendabletypeID = pmissileType->GetObjectID();
  361. launcher.amount = (short)GetNumber((IObject*)stack.Pop());
  362. launcher.treasureChance = (short)GetNumber((IObject*)stack.Pop());
  363. IObject* pobject = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(),
  364. OT_partType, &launcher, sizeof(launcher));
  365. pobject->Release();
  366. return pobject;
  367. }
  368. TRef<IObject> CreatePackType(ObjectStack& stack)
  369. {
  370. DataPackTypeIGC pack;
  371. ReadPartTypeData(&pack, ET_Pack, stack);
  372. pack.amount = (short)GetNumber((IObject*)stack.Pop());
  373. pack.packType = (PackType)GetNumber((IObject*)stack.Pop());
  374. IObject* pobject = m_pmissionContext->GetMissionIGC()->CreateObject(
  375. Time::Now(), OT_partType, &pack, sizeof(pack));
  376. pobject->Release();
  377. return pobject;
  378. }
  379. TRef<IObject> CreateProjectileType(ObjectStack& stack)
  380. {
  381. DataProjectileTypeIGC projectile;
  382. projectile.projectileTypeID = m_projectileTypeIDNext++;
  383. ReadDataObject(&projectile, stack);
  384. projectile.power = GetNumber((IObject*)stack.Pop());
  385. projectile.blastPower = GetNumber((IObject*)stack.Pop());
  386. projectile.blastRadius = GetNumber((IObject*)stack.Pop());
  387. projectile.speed = GetNumber((IObject*)stack.Pop());
  388. projectile.lifespan = GetNumber((IObject*)stack.Pop());
  389. projectile.damageType = (DamageTypeMask)GetNumber((IObject*)stack.Pop());
  390. projectile.absoluteF = GetBoolean((IObject*)stack.Pop());
  391. projectile.bDirectional = GetBoolean((IObject*)stack.Pop());
  392. projectile.width = GetNumber((IObject*)stack.Pop());
  393. projectile.ambientSound = (SoundID)GetNumber((IObject*)stack.Pop());
  394. IObject* pobject = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(),
  395. OT_projectileType, &projectile, sizeof(projectile));
  396. pobject->Release();
  397. return pobject;
  398. }
  399. TRef<IObject> CreateStationType(ObjectStack& stack)
  400. {
  401. DataStationTypeIGC st;
  402. memset(&st, 0, sizeof(st));
  403. st.stationTypeID = m_stationTypeIDNext++;
  404. st.maxArmorHitPoints = 5000.0f;
  405. st.maxShieldHitPoints = 250.0f;
  406. st.armorRegeneration = 10.0f;
  407. st.shieldRegeneration = 5.0f;
  408. strcpy(st.modelName, "ss27");
  409. strcpy(st.iconName, "stationbmp");
  410. strcpy(st.name, "Mining Platform");
  411. strcpy(st.description, "Mining Platform");
  412. st.price = 1000;
  413. st.timeToBuild = 100;
  414. st.textureName[0] = '\0';
  415. st.radius = 125;
  416. st.animIdle.start = 0.0f;
  417. st.animIdle.stop = 40.0f;
  418. st.ttbmRequired.ClearAll();
  419. st.ttbmEffects.ClearAll();
  420. st.ttbmLocal.ClearAll();
  421. st.signature = 2.5f;
  422. st.scannerRange = 2000.0f;
  423. st.aabmBuild = (c_aabmSpecial << 0);
  424. st.successorStationTypeID = NA;
  425. st.sabmCapabilities = c_sabmUnload | c_sabmStart | c_sabmRestart | c_sabmLand | c_sabmRepair | c_sabmLoadoutMenu | c_sabmRipcord | c_sabmReload;
  426. st.interiorSound = 380;
  427. st.exteriorSound = 420;
  428. st.interiorAlertSound = 460;
  429. IObject* pobject = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(),
  430. OT_stationType, &st, sizeof(st));
  431. pobject->Release();
  432. return pobject;
  433. }
  434. TRef<IObject> CreateStation(ObjectStack& stack)
  435. {
  436. DataStationIGC ds;
  437. // get the clusterid
  438. TRef<IclusterIGC> pcluster; CastTo(pcluster, (IObject*)stack.Pop());
  439. ds.clusterID = pcluster->GetObjectID();
  440. // get the station type
  441. TRef<IstationTypeIGC> pstationType; CastTo(pstationType, (IObject*)stack.Pop());
  442. ds.stationTypeID = pstationType->GetObjectID();
  443. strcpy(ds.name, pstationType->GetName());
  444. ds.position = GetVector((IObject*)stack.Pop());
  445. ds.forward = Vector::RandomDirection();
  446. static const Vector xAxis(1.0, 0.0, 0.0);
  447. ds.up = CrossProduct(ds.forward, xAxis);
  448. if (ds.up.LengthSquared() < 0.1f)
  449. {
  450. static const Vector zAxis(0.0, 0.0, 1.0);
  451. ds.up = CrossProduct(ds.forward, zAxis);
  452. }
  453. assert (ds.up.LengthSquared() > 0.1f);
  454. ds.up.SetNormalize();
  455. ds.rotation.axis(ds.forward);
  456. ds.rotation.angle(0.05f + random(0.0f, 0.05f));
  457. ds.sideID = (SideID)GetNumber((IObject*)stack.Pop());
  458. ds.stationID = m_pmissionContext->GetMissionIGC()->GenerateNewStationID();
  459. IObject* pobject = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(),
  460. OT_station, &ds, sizeof(ds));
  461. pobject->Release();
  462. return pobject;
  463. }
  464. TRef<IObject> CreateHullType(ObjectStack& stack)
  465. {
  466. BYTE rgbData[4096];
  467. DataHullTypeIGC* pHullType = (DataHullTypeIGC*)rgbData;
  468. memset(pHullType, 0, sizeof(DataHullTypeIGC));
  469. pHullType->hullID = m_hullIDNext++;
  470. pHullType->successorHullID = NA;
  471. ReadBuyableData(pHullType, stack);
  472. pHullType->mass = GetNumber((IObject*)stack.Pop());
  473. pHullType->signature = GetNumber((IObject*)stack.Pop());
  474. pHullType->speed = GetNumber((IObject*)stack.Pop());
  475. for (int i = 0; i < 3; i++)
  476. pHullType->maxTurnRates[i] = GetNumber((IObject*)stack.Pop()); //yaw, pitch, roll
  477. for (i = 0; i < 3; i++)
  478. pHullType->turnTorques[i] = GetNumber((IObject*)stack.Pop()); //yaw, pitch, roll
  479. pHullType->thrust = GetNumber((IObject*)stack.Pop());
  480. pHullType->sideMultiplier = GetNumber((IObject*)stack.Pop());
  481. pHullType->backMultiplier = GetNumber((IObject*)stack.Pop());
  482. pHullType->scannerRange = GetNumber((IObject*)stack.Pop());
  483. pHullType->maxEnergy = GetNumber((IObject*)stack.Pop());
  484. pHullType->rechargeRate = GetNumber((IObject*)stack.Pop());
  485. pHullType->maxWeapons = (Mount)GetNumber((IObject*)stack.Pop());
  486. pHullType->hitPoints = (HitPoints)GetNumber((IObject*)stack.Pop());
  487. memset(pHullType->psEquipment, 0, sizeof(pHullType->psEquipment));
  488. pHullType->length = (short)GetNumber((IObject*)stack.Pop());
  489. pHullType->habmCapabilities = (HullAbilityBitMask)GetNumber((IObject*)stack.Pop());
  490. strcpy(pHullType->textureName, GetString((IObject*)stack.Pop()));
  491. pHullType->interiorSound = (SoundID)GetNumber((IObject*)stack.Pop());
  492. pHullType->exteriorSound = (SoundID)GetNumber((IObject*)stack.Pop());
  493. pHullType->mainThrusterInteriorSound = (SoundID)GetNumber((IObject*)stack.Pop());
  494. pHullType->mainThrusterExteriorSound = (SoundID)GetNumber((IObject*)stack.Pop());
  495. pHullType->manuveringThrusterInteriorSound = (SoundID)GetNumber((IObject*)stack.Pop());
  496. pHullType->manuveringThrusterExteriorSound = (SoundID)GetNumber((IObject*)stack.Pop());
  497. AnimationData* panimationData = pHullType->animations;
  498. TRef<IObjectList> plistAnimationData; CastTo(plistAnimationData, (IObject*)stack.Pop());
  499. plistAnimationData->GetFirst();
  500. while (NULL != plistAnimationData->GetCurrent())
  501. {
  502. TRef<IObjectPair> pparams; CastTo(pparams, (IObject*)plistAnimationData->GetCurrent());
  503. panimationData->start = GetNumber((IObject*)pparams->GetFirst());
  504. panimationData->stop = GetNumber((IObject*)pparams->GetSecond());
  505. panimationData++;
  506. plistAnimationData->GetNext();
  507. }
  508. pHullType->hardpointOffset = sizeof(DataHullTypeIGC);
  509. HardpointData* pHardPoint = (HardpointData *) (pHullType + 1);
  510. int cHardpoints = 0;
  511. TRef<IObjectList> plistHardPoints; CastTo(plistHardPoints, (IObject*)stack.Pop());
  512. plistHardPoints->GetFirst();
  513. while (NULL != plistHardPoints->GetCurrent())
  514. {
  515. TRef<IObjectPair> pparams; CastTo(pparams, (IObject*)plistHardPoints->GetCurrent());
  516. strcpy(pHardPoint->frameName, GetString((IObject*)pparams->GetFirst()));
  517. //NYI needs to be correctly initialized
  518. pHardPoint->bFixed = true;
  519. pHardPoint->minDot = (char)GetNumber((IObject*)pparams->GetSecond()) == 'n' ? 0.5f : 0.0f;
  520. cHardpoints++;
  521. pHardPoint++;
  522. plistHardPoints->GetNext();
  523. }
  524. IObject* pobject = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(),
  525. OT_hullType, rgbData, sizeof(DataHullTypeIGC) + sizeof(HardpointData)*cHardpoints);
  526. pobject->Release();
  527. return pobject;
  528. }
  529. TRef<IObject> CreateWeaponType(ObjectStack& stack)
  530. {
  531. DataWeaponTypeIGC weapon;
  532. ReadPartTypeData(&weapon, ET_Weapon, stack);
  533. weapon.dtimeReady = GetNumber((IObject*)stack.Pop());
  534. weapon.dtimeBurst = GetNumber((IObject*)stack.Pop());
  535. weapon.energyPerShot = GetNumber((IObject*)stack.Pop());
  536. weapon.dispersion = GetNumber((IObject*)stack.Pop());
  537. weapon.cAmmoPerShot = (short)GetNumber((IObject*)stack.Pop());
  538. TRef<IprojectileTypeIGC> pprojectileType = (IprojectileTypeIGC*)(IObject*)stack.Pop();
  539. weapon.projectileTypeID = pprojectileType->GetObjectID();
  540. weapon.activateSound = (short)GetNumber((IObject*)stack.Pop());
  541. weapon.singleShotSound = (short)GetNumber((IObject*)stack.Pop());
  542. weapon.burstSound = (short)GetNumber((IObject*)stack.Pop());
  543. IObject* pobject = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(),
  544. OT_partType, &weapon, sizeof(weapon));
  545. pobject->Release();
  546. return pobject;
  547. }
  548. TRef<IObject> CreateCluster(ObjectStack& stack)
  549. {
  550. DataClusterIGC data;
  551. memset(&data, 0, sizeof(data));
  552. // assign a new cluster id
  553. data.clusterID = m_clusterIDNext++;
  554. // name, etc
  555. strcpy(data.name, GetString((IObject*)stack.Pop()));
  556. strcpy(data.posterName, GetString((IObject*)stack.Pop()));
  557. // lighting
  558. data.lightDirection = Vector::RandomDirection(); //GetVector((IObject*)stack.Pop());
  559. data.lightColor = 0xffffffff; //D3DRGBA(color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha());
  560. // positioning
  561. data.screenX = GetNumber((IObject*)stack.Pop());
  562. data.screenY = GetNumber((IObject*)stack.Pop());
  563. // properties
  564. data.starSeed = rand();
  565. data.nDebris = randomInt(250, 750);
  566. data.nStars = randomInt(250, 750);
  567. data.activeF = false;
  568. IObject* pobject = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(),
  569. OT_cluster, &data, sizeof(data));
  570. pobject->Release();
  571. return pobject;
  572. }
  573. TRef<IObject> CreateSphericalRegion(ObjectStack& stack)
  574. {
  575. TRef<ImodelIGC> pmodel; CastTo(pmodel, (IObject*)stack.Pop());
  576. float radius = GetNumber((IObject*)stack.Pop());
  577. return (Region*)SphericalRegion::Create(pmodel, radius);
  578. }
  579. TRef<Region> GetRegion(const ZString& strRegion)
  580. {
  581. ZAssert(m_pnsClusters);
  582. return (Region*)m_pnsClusters->FindMember(strRegion);
  583. }
  584. /*
  585. TRef<IObject> CreateDrone(ObjectStack& stack)
  586. {
  587. // cluster
  588. TRef<IclusterIGC> pcluster; CastTo(pcluster, (IObject*)stack.Pop());
  589. // position
  590. Vector pos = GetVector((IObject*)stack.Pop());
  591. // name
  592. ZString strName = GetString((IObject*)stack.Pop());
  593. //dronetype
  594. DroneType dt = (DroneType)(WORD)GetNumber((IObject*)stack.Pop());
  595. //side
  596. SideID sideID = (SideID)GetNumber((IObject*)stack.Pop());
  597. // loadout
  598. TRef<IObjectList> pparamList; CastTo(pparamList, (IObject*)stack.Pop());
  599. // hulltype
  600. TRef<IhullTypeIGC> phullType = (IhullTypeIGC*)pparamList->GetFirst();
  601. HullID hullID = phullType->GetObjectID();
  602. // parts
  603. TRef<IObjectList> ppartsList = (IObjectList*)pparamList->GetNext();
  604. PartData partData[10];
  605. int cParts = ReadPartData(phullType, partData, ppartsList);
  606. Drone* pdrone = g_drones.Create(
  607. m_pmissionContext->GetMissionIGC(),
  608. dt,
  609. strName,
  610. hullID,
  611. m_pmissionContext->GetMissionIGC()->GetSide(sideID),
  612. cParts,
  613. partData);
  614. pdrone->GetShip()->SetPosition(pos);
  615. pdrone->GetShip()->SetCluster(pcluster);
  616. return pdrone->GetShip();
  617. }
  618. */
  619. TRef<IObject> CreateAsteroid(ObjectStack& stack)
  620. {
  621. DataAsteroidIGC data;
  622. memset(&data, 0, sizeof(data));
  623. // get the clusterid
  624. TRef<IclusterIGC> pcluster; CastTo(pcluster, (IObject*)stack.Pop());
  625. data.clusterID = pcluster->GetObjectID();
  626. // assign a new asteroid id
  627. data.asteroidDef.asteroidID = m_asteroidIDNext++;
  628. // name, texture, model
  629. strcpy(data.name, GetString((IObject*)stack.Pop()));
  630. strcpy(data.asteroidDef.modelName, GetString((IObject*)stack.Pop()));
  631. strcpy(data.asteroidDef.textureName, GetString((IObject*)stack.Pop()));
  632. // properties
  633. data.mass = GetNumber((IObject*)stack.Pop());
  634. data.asteroidDef.radius = (short)GetNumber((IObject*)stack.Pop());
  635. data.asteroidDef.hitpoints = (short)GetNumber((IObject*)stack.Pop());
  636. data.asteroidDef.ore = GetNumber((IObject*)stack.Pop());
  637. // positioning
  638. data.position = GetVector((IObject*)stack.Pop());
  639. data.forward = Vector::RandomDirection();
  640. static const Vector xAxis(1.0, 0.0, 0.0);
  641. data.up = CrossProduct(data.forward, xAxis);
  642. if (data.up.LengthSquared() < 0.1f)
  643. {
  644. static const Vector zAxis(0.0, 0.0, 1.0);
  645. data.up = CrossProduct(data.forward, zAxis);
  646. }
  647. assert (data.up.LengthSquared() > 0.1f);
  648. data.up.SetNormalize();
  649. data.rotation.axis(data.forward);
  650. data.rotation.angle(0.05f + random(0.0f, 0.05f));
  651. /* data.position = GetVector((IObject*)stack.Pop());
  652. data.up = GetVector((IObject*)stack.Pop());
  653. data.forward = GetVector((IObject*)stack.Pop());
  654. TRef<IObjectPair> ppair; CastTo(ppair, (IObject*)stack.Pop());
  655. data.rotation = Rotation(
  656. GetVector(ppair->GetFirst()),
  657. GetNumber(ppair->GetSecond()));
  658. */
  659. // capabilites
  660. TRef<IObjectList> plist; CastTo(plist, (IObject*)stack.Pop());
  661. plist->GetFirst();
  662. while (NULL != plist->GetCurrent())
  663. {
  664. data.asteroidDef.aabmCapabilities |= (short)GetNumber((IObject*)plist->GetCurrent());
  665. plist->GetNext();
  666. }
  667. IObject* pobject = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(),
  668. OT_asteroid, &data, sizeof(data));
  669. pobject->Release();
  670. return pobject;
  671. }
  672. void CreateDefaults()
  673. {
  674. IObject* pobj;
  675. //
  676. // Default Hull Type (EVA pod).
  677. //
  678. DataHullTypeIGC hullType;
  679. memset(&hullType, 0, sizeof(hullType));
  680. hullType.price = 0;
  681. strcpy(hullType.modelName, "utl22");
  682. strcpy(hullType.iconName, "fighterbmp");
  683. strcpy(hullType.name, "EVA Pod");
  684. strcpy(hullType.description, "Last hope home");
  685. hullType.ttbmRequired.ClearAll();
  686. hullType.ttbmEffects.ClearAll();
  687. hullType.mass = 2;
  688. hullType.signature = 50;
  689. hullType.speed = 20;
  690. hullType.maxTurnRates[0] = hullType.maxTurnRates[1] = pi / 2.0f;
  691. hullType.maxTurnRates[2] = 4.0f * pi / 9.0f;
  692. hullType.turnTorques[0] = hullType.turnTorques[1] = 3.0f * pi / 2.0f;
  693. hullType.turnTorques[2] = 4.0f * pi / 3.0f;
  694. hullType.thrust = hullType.mass * 10;
  695. hullType.sideMultiplier = 1.0f;
  696. hullType.backMultiplier = 1.0f;
  697. hullType.scannerRange = 1000;
  698. hullType.maxEnergy = 0;
  699. hullType.rechargeRate = 0;
  700. hullType.hullID = m_hullIDNext++;
  701. hullType.maxWeapons = 0;
  702. hullType.hitPoints = 50;
  703. memset(hullType.psEquipment, 0, sizeof(hullType.psEquipment));
  704. hullType.hardpointOffset = sizeof(hullType);
  705. hullType.length = 4;
  706. hullType.habmCapabilities = 29239;
  707. hullType.interiorSound = 140;
  708. hullType.exteriorSound = 180;
  709. hullType.mainThrusterInteriorSound = 220;
  710. hullType.mainThrusterExteriorSound = 260;
  711. hullType.manuveringThrusterInteriorSound = 300;
  712. hullType.manuveringThrusterExteriorSound = 340;
  713. pobj = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(), OT_hullType, &hullType, sizeof(hullType));
  714. assert (pobj);
  715. pobj->Release();
  716. // Default Station Type
  717. DataStationTypeIGC st;
  718. st.stationTypeID = 0;
  719. st.maxArmorHitPoints = 500.0f;
  720. st.maxShieldHitPoints = 250.0f;
  721. st.armorRegeneration = 1.0f;
  722. st.shieldRegeneration = 5.0f;
  723. strcpy(st.modelName, "acs05");
  724. strcpy(st.iconName, "stationbmp");
  725. strcpy(st.name, "Station");
  726. strcpy(st.description, "Station");
  727. st.price = 1000;
  728. st.timeToBuild = 100;
  729. st.textureName[0] = '\0';
  730. st.radius = 125;
  731. st.animIdle.start = 0.0f;
  732. st.animIdle.stop = 40.0f;
  733. st.ttbmRequired.ClearAll();
  734. st.ttbmEffects.ClearAll();
  735. st.ttbmLocal.ClearAll();
  736. st.signature = 2.5f;
  737. st.scannerRange = 2000.0f;
  738. st.aabmBuild = (c_aabmSpecial << 0);
  739. st.successorStationTypeID = NA;
  740. st.sabmCapabilities = c_sabmUnload | c_sabmStart | c_sabmRestart | c_sabmLand | c_sabmRepair | c_sabmLoadoutMenu | c_sabmRipcord | c_sabmReload;
  741. st.interiorSound = 380;
  742. st.exteriorSound = 420;
  743. st.interiorAlertSound = 460;
  744. pobj = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(), OT_stationType, &st, sizeof(st));
  745. assert (pobj);
  746. pobj->Release();
  747. /*
  748. // Construction Drone
  749. DataDroneTypeIGC d;
  750. d.timeToBuild = 30;
  751. d.droneTypeID = 0;
  752. d.hullTypeID = hullType.hullID;
  753. d.droneType = c_dtConstruction;
  754. d.moveSkill = d.shootSkill = 1.0f;
  755. d.bravery = 0.5f;
  756. d.nParts = 0;
  757. d.price = 500;
  758. strcpy(d.modelName, "utl19");
  759. d.iconName[0] = '\0';
  760. strcpy(d.name, "Construction");
  761. strcpy(d.description, "Construction drone");
  762. d.ttbmRequired.ClearAll();
  763. d.ttbmEffects.ClearAll();
  764. pobj = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(), OT_droneType, &d, sizeof(d));
  765. assert (pobj);
  766. pobj->Release();
  767. */
  768. // Create the 3 civilizations
  769. static const char* civNames[c_cSidesMax] =
  770. {"Rix", "Iron League", "Belorian"};
  771. DataCivilizationIGC c;
  772. c.lifepod = hullType.hullID;
  773. c.constructionDroneTypeID = 0;
  774. c.ttbmBaseTechs.ClearAll();
  775. c.gasBaseAttributes.Initialize();
  776. for (CivID cid = 0; (cid < 3); cid++)
  777. {
  778. strcpy(c.name, "Iron league");
  779. c.initialStationTypeID = 0;
  780. c.civilizationID = cid;
  781. pobj = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(), OT_civilization, &c, sizeof(c));
  782. assert (pobj);
  783. pobj->Release();
  784. }
  785. // Create the 3 teams
  786. static const float sideColors[3][3] =
  787. { {1.0f, 0.5f, 0.0f}, //orange
  788. {0.0f, 1.0f, 0.67f},//teal
  789. {0.0f, 0.0f, 1.0f}}; //blue
  790. static const char* sideNames[c_cSidesMax] =
  791. {"Orange", "Teal", "Blue"};
  792. for (SideID sid = 0; (sid < 3); sid++)
  793. {
  794. IcivilizationIGC* pcivilization = m_pmissionContext->GetMissionIGC()->GetCivilization(sid);
  795. DataSideIGC ds;
  796. ds.sideID = sid;
  797. ds.gasAttributes.Initialize();
  798. ds.civilizationID = sid;
  799. ds.color.SetRGBA(sideColors[sid][0],
  800. sideColors[sid][1],
  801. sideColors[sid][2]);
  802. strcpy(ds.name, sideNames[sid]);
  803. ds.gas = pcivilization->GetBaseAttributes();
  804. ds.ttbmDevelopmentTechs = pcivilization->GetBaseTechs();
  805. ds.squadID = NA;
  806. ds.nKills = ds.nDeaths = ds.nBaseKills = ds.nBaseCaptures = ds.nFlags = ds.nArtifacts = 0;
  807. pobj = m_pmissionContext->GetMissionIGC()->CreateObject(Time::Now(), OT_side, &ds, sizeof(ds));
  808. assert (pobj);
  809. pobj->Release();
  810. }
  811. }
  812. void SetMissionStage(MissionStage* pstageNew)
  813. {
  814. FireOnSwitchedMissionStage(pstageNew, m_pmissionStage);
  815. m_pmissionStage = pstageNew;
  816. }
  817. void AdviseRegion(Region* pregion, ImodelIGC* pmodel)
  818. {
  819. TRef<RegionAdviseEntry> pentry;
  820. if (!m_mapRegionAdviseEntries.Find(pregion, pentry))
  821. {
  822. pentry = new RegionAdviseEntry(pregion);
  823. m_mapRegionAdviseEntries.Set(pregion, pentry);
  824. }
  825. pentry->Advise(pmodel);
  826. // todo: make sure not in delete list
  827. }
  828. void UnadviseRegion(Region* pregion, ImodelIGC* pmodel)
  829. {
  830. TRef<RegionAdviseEntry> pentry;
  831. ZVerify(m_mapRegionAdviseEntries.Find(pregion, pentry));
  832. pentry->Unadvise(pmodel);
  833. // todo: mark this entry to be deleted
  834. }
  835. void AddMissionEventHandler(MissionEventHandler* phandler)
  836. {
  837. m_lstEventHandlers.PushEnd(phandler);
  838. }
  839. void RemoveMissionEventHandler(MissionEventHandler* phandler)
  840. {
  841. m_lstEventHandlers.Replace(phandler, NULL);
  842. }
  843. void Update(Time time, float dtime)
  844. {
  845. // check region collisions... this doesn't handle jumps all the way through a region
  846. TMap<TRef<Region>, TRef<RegionAdviseEntry> >::Iterator iterEntries(m_mapRegionAdviseEntries);
  847. while (!iterEntries.End())
  848. {
  849. TRef<RegionAdviseEntry> pentry = iterEntries.Value();
  850. pentry->Update(this);
  851. iterEntries.Next();
  852. }
  853. }
  854. void RemoveDeadHandlers()
  855. {
  856. // remove all of the NULL elements from the list
  857. while (m_lstEventHandlers.Remove(NULL))
  858. {
  859. }
  860. }
  861. #define ForEachHandler(fnc) \
  862. TList<TRef<MissionEventHandler> >::Iterator iter(m_lstEventHandlers); \
  863. while (!iter.End()) \
  864. { \
  865. if (iter.Value() != NULL) \
  866. if (!iter.Value()->fnc) \
  867. RemoveMissionEventHandler(iter.Value()); \
  868. iter.Next(); \
  869. } \
  870. RemoveDeadHandlers(); \
  871. void FireOnModelTerminated(ImodelIGC* pmodel)
  872. {
  873. ForEachHandler( OnModelTerminated(pmodel) )
  874. }
  875. void FireOnModelKilled(ImodelIGC* pmodel)
  876. {
  877. ForEachHandler( OnModelKilled(pmodel) )
  878. }
  879. void FireOnModelDamaged(ImodelIGC* pmodel)
  880. {
  881. ForEachHandler( OnModelDamaged(pmodel) )
  882. }
  883. void FireOnDocked(IshipIGC* pship, IstationIGC* pstation)
  884. {
  885. ForEachHandler( OnDocked(pship, pstation) )
  886. }
  887. void FireOnSwitchSector(IshipIGC* pship, IclusterIGC* pclusterOld, IclusterIGC* pclusterNew)
  888. {
  889. ForEachHandler( OnSwitchSector(pship, pclusterOld, pclusterNew) )
  890. }
  891. void FireOnHitTreasure(IshipIGC* pship, ItreasureIGC* ptreasure)
  892. {
  893. ForEachHandler( OnHitTreasure(pship, ptreasure) )
  894. }
  895. void FireOnEnteredRegion(ImodelIGC* pmodel, Region* pregion)
  896. {
  897. ForEachHandler( OnEnteredRegion(pmodel, pregion) )
  898. }
  899. void FireOnExitedRegion(ImodelIGC* pmodel, Region* pregion)
  900. {
  901. ForEachHandler( OnExitedRegion(pmodel, pregion) )
  902. }
  903. void FireOnDivergedPath(IshipIGC* pship, Path* ppath, float distance, float angle)
  904. {
  905. ForEachHandler( OnDivergedPath(pship, ppath, distance, angle) )
  906. }
  907. void FireOnSwitchedMissionStage(MissionStage* pstageNew, MissionStage* pstageOld)
  908. {
  909. ForEachHandler( OnSwitchedMissionStage(pstageNew, pstageOld) )
  910. }
  911. };
  912. TRef<MissionManager> MissionManager::Create(MissionContext* pcontext)
  913. {
  914. return new MissionManagerImpl(pcontext);
  915. }
  916. #endif