Rise
The Vieneo Province
CAS.cpp
Go to the documentation of this file.
1 #include "Module.h"
2 #include <algorithm> // for std::sort
3 
4 Cas::Cas(Bus* prmBus, Logger* prmLogger, Sound* prmSound) : Module(prmBus)
5 {
6  logger = prmLogger;
7  sound = prmSound;
8 }
9 
10 void Cas::FrameMove(float fElapsed)
11 {
12  if (ourcockpit.gndvehicle && ourcockpit.texturelib != T27) return;
13 
14  if (ourcockpit.texturelib == Apartment || ourcockpit.texturelib == SimBay || ourcockpit.texturelib == ControlTower) return;
15 
16  if (ourcockpit.power < 0.5f) // unpowered
17  {
18  secsincelast = -2.0f; // 2 second intro delay
19  return;
20  }
21 
22  if (secsincelast < 0.0f) // 2 second power-up delay
23  {
24  secsincelast += fElapsed;
25  if (secsincelast >= 0.0f)
26  {
27  secsincelast = 2.0f;
28  bus->messages.clear(); // reset on power-up
29  }
30  else
31  {
32  return;
33  }
34  }
35 
36  secsincelast += fElapsed;
37 
39 
40  for (UINT i = 0; i < bus->commandStream.size(); i++)
41  {
42  const Command command = bus->commandStream.at(i);
43  //if (command.delay != 0.0f) continue;
44 
45  if (command.name == "AcknowledgeAllMessages")
46  {
48  bus->commandStream.erase(bus->commandStream.begin() + i);
49  }
50  }
51 
52  const bool weightOnWheels = playerships[0].reference == REF_ONGROUND;
53 
54  if (!weightOnWheels)
55  {
56  weightOnWheelsTime = 0.0f;
57  weightOffWheelsTime += fElapsed;
58  }
59  else
60  {
61  weightOffWheelsTime = 0.0f;
62  weightOnWheelsTime += fElapsed;
63  }
64  if (bus->RadioAltitudeKm < 0.12192f)
65  below400Time += fElapsed;
66  else
67  below400Time = 0.0f;
68 
69  // @todo probably need to move these values to the Bus if more people start using them
70  bool takeoffThrust = false;
71  bool takeoffInhibit = true;
72  bool takeoffRelease = false;
73  for (int i = 0; i < ourcockpit.engines; i++)
74  {
75  takeoffThrust |= bus->EngineThrustLever[i] >= 0.7f; // if ANY one engine is over 70%
76  takeoffInhibit &= bus->EngineThrustLever[i] > 0.79f; // if ALL engines are over 79%
77  takeoffRelease |= bus->EngineThrustLever[i] < 0.676f; // if ANY one engine is below 67.6%
78  }
79 
80  const bool takeoffConfig = true;
81  if (takeoffInhibit && weightOnWheels && bus->IndicatedAirspeedKms < 0.0514444f) // 100 KIAS
82  inhibit = true;
83  else if (!weightOnWheels && bus->RadioAltitudeKm < 0.12192f && bus->LandingGearExtended) // 400 AGL
84  inhibit = true;
85  else if (takeoffRelease || (takeoffInhibit && bus->IndicatedAirspeedKms > 0.0514444f) || (bus->RadioAltitudeKm > 0.12192f && weightOffWheelsTime > 30.0f)) // 100 KIAS, 400 AGL
86  inhibit = false;
87  else if (weightOnWheelsTime > 30.0f || (bus->RadioAltitudeKm < 0.12192f && below400Time > 3.0f))
88  inhibit = false;
89 
90  switch (evaluating++)
91  {
92  case 0:
93  if ((!bus->YawDamperStatus || ourcockpit.vdat.yawdamper < 64) && ourcockpit.vdat.yawdamper > -1)
94  AddMessage(L"YAW DAMPER", MessageLevel::Caution, false);
95  else
96  // ReSharper disable once CppExpressionWithoutSideEffects
97  RemoveMessage(L"YAW DAMPER");
98  break;
99  case 1:
100  if (ourcockpit.vdat.thrustaug != -1 && (!g_bAugment || ourcockpit.vdat.thrustaug < 64))
101  {
102  if (!inhibit)
103  AddMessage(L"THRUST AUG", MessageLevel::Caution, false);
104  }
105  else
106  // ReSharper disable once CppExpressionWithoutSideEffects
107  RemoveMessage(L"THRUST AUG");
108  break;
109  case 2:
111  {
112  if (!inhibit)
113  AddMessage(L"CARGO DOOR", MessageLevel::Caution, false);
114  }
115  else
116  // ReSharper disable once CppExpressionWithoutSideEffects
117  RemoveMessage(L"CARGO DOOR");
118  break;
119  case 3:
120  if ((GetKeyState(VK_CAPITAL) & 0x0001) != 0)
121  AddMessage(L"CAPS LOCK ON", MessageLevel::Advisory, false);
122  else
123  // ReSharper disable once CppExpressionWithoutSideEffects
124  RemoveMessage(L"CAPS LOCK ON");
125  break;
126  case 4:
127  if ((GetKeyState(VK_NUMLOCK) & 0x0001) == 0)
128  AddMessage(L"NUM LOCK OFF", MessageLevel::Advisory, false);
129  else
130  // ReSharper disable once CppExpressionWithoutSideEffects
131  RemoveMessage(L"NUM LOCK OFF");
132  break;
133  case 5:
134  if (ourcockpit.parkingBrake && weightOnWheels && !takeoffThrust)
135  AddMessage(L"PARKING BRAKE ON", MessageLevel::Advisory, false);
136  else
137  // ReSharper disable once CppExpressionWithoutSideEffects
138  RemoveMessage(L"PARKING BRAKE ON");
139  break;
140  case 6:
141  if (ourcockpit.parkingBrake && (!weightOnWheels || (takeoffConfig && takeoffThrust)))
142  {
143  if (AddMessage(L"PARKING BRAKE", MessageLevel::Warning, false) && weightOnWheels)
144  {
145  Command newCommand;
146  newCommand.name = "CASConfigBrake";
147  newCommand.delay = 1.5f; // give master warn time
148  bus->commandStream.emplace_back(newCommand);
149  logger->Log("CAS::AddMessage ConfigBrake requested!");
150  secsincelast = 0.0f;
151  }
152  }
153  else
154  // ReSharper disable once CppExpressionWithoutSideEffects
155  RemoveMessage(L"PARKING BRAKE");
156  break;
157  case 7:
158  if (bus->IceDetected)
159  {
160  if (!bus->AntiIce)
161  AddMessage(L"ICE", MessageLevel::Caution, false);
162  else
163  AddMessage(L"ICE", MessageLevel::Advisory, false);
164  }
165  else
166  // ReSharper disable once CppExpressionWithoutSideEffects
167  RemoveMessage(L"ICE");
168  case 8:
169  if (bus->AntiIce)
170  AddMessage(L"WING/COWL A/I ON", MessageLevel::Advisory, false);
171  else
172  // ReSharper disable once CppExpressionWithoutSideEffects
173  RemoveMessage(L"WING/COWL A/I ON");
174  break;
175  case 9:
176  if (bus->AFCS.AutopilotEngaged && weightOnWheels && takeoffConfig && takeoffThrust)
177  {
178  if (AddMessage(L"CONFIG AF", MessageLevel::Warning, false))
179  {
180  Command newCommand;
181  newCommand.name = "CASConfigAF";
182  newCommand.delay = 1.5f; // give master warn time
183  bus->commandStream.emplace_back(newCommand);
184  logger->Log("CAS::AddMessage ConfigAF requested!");
185  secsincelast = 0.0f;
186  }
187  }
188  else
189  // ReSharper disable once CppExpressionWithoutSideEffects
190  RemoveMessage(L"CONFIG AF");
191  break;
192  case 10:
193  if (weightOnWheels && takeoffConfig && takeoffThrust && bus->TrailingEdgeFlapsPosition > 20.0f)
194  {
195  if (AddMessage(L"CONFIG FLAPS", MessageLevel::Warning, false))
196  {
197  Command newCommand;
198  newCommand.name = "CASConfigFlaps";
199  newCommand.delay = 1.5f; // give master warn time
200  bus->commandStream.emplace_back(newCommand);
201  logger->Log("CAS::AddMessage ConfigFlaps requested!");
202  secsincelast = 0.0f;
203  }
204  }
205  else
206  // ReSharper disable once CppExpressionWithoutSideEffects
207  RemoveMessage(L"CONFIG FLAPS");
208  break;
209  case 11:
210  if (weightOnWheels && takeoffConfig && takeoffThrust && fabsf(bus->PitchTrimSurfacePositionDegrees) > 10.0f)
211  {
212  if (AddMessage(L"CONFIG STAB", MessageLevel::Warning, false))
213  {
214  Command newCommand;
215  newCommand.name = "CASConfigTrim";
216  newCommand.delay = 1.5f; // give master warn time
217  bus->commandStream.emplace_back(newCommand);
218  logger->Log("CAS::AddMessage ConfigTrim requested!");
219  secsincelast = 0.0f;
220  }
221  }
222  else
223  // ReSharper disable once CppExpressionWithoutSideEffects
224  RemoveMessage(L"CONFIG STAB");
225  break;
226  case 12:
227  if (bus->ProximityAlert)
228  {
229  if (AddMessage(L"PROXIMITY ALERT", MessageLevel::Caution, false))
230  {
231  sound->PlayEx(SOUND_PROXIMITY, true);
232  }
233  }
234  else
235  {
236  // ReSharper disable once CppExpressionWithoutSideEffects
237  RemoveMessage(L"PROXIMITY ALERT");
239  }
240  break;
241  case 13:
242  if (bus->AirframeTemperatureCelsius > 225)
243  AddMessage(L"WING OVHT", MessageLevel::Warning, false);
244  else if (bus->AirframeTemperatureCelsius > 125)
245  AddMessage(L"WING OVHT", MessageLevel::Caution, false);
246  else
247  // ReSharper disable once CppExpressionWithoutSideEffects
248  RemoveMessage(L"WING OVHT");
249  break;
250  case 14:
252  AddMessage(L"AILERONS FAULT", MessageLevel::Caution, false);
253  else
254  // ReSharper disable once CppExpressionWithoutSideEffects
255  RemoveMessage(L"AILERONS FAULT");
257  AddMessage(L"RCS ROLL FAULT", MessageLevel::Caution, false);
258  else
259  // ReSharper disable once CppExpressionWithoutSideEffects
260  RemoveMessage(L"RCS ROLL FAULT");
261  break;
262  case 15:
263  if (fuel < (ourcockpit.fuelmax * 0.03f)) // fuel for go-around for air vehicles
264  AddMessage(L"FUEL LO LEVEL", MessageLevel::Caution, false);
265  else
266  // ReSharper disable once CppExpressionWithoutSideEffects
267  RemoveMessage(L"FUEL LO LEVEL");
268  break;
269  case 16:
270  for (int i = 0; i < ourcockpit.engines; i++)
271  {
272  swprintf_s(temporaryMessage, 99, L"ENG %i FAIL", i + 1);
273  if ((bus->EngineThrustCommand[i] - bus->EngineThrustOutput[i]) >= 0.25f)
275  else
277  }
278  break;
279  case 17:
280  if (bus->CabinPressureMb < 703.2652f) // 10000'
281  {
282  if (AddMessage(L"CABIN ALT", MessageLevel::Warning, false))
283  {
284  Command newCommand;
285  newCommand.name = "CASCabinPressure";
286  newCommand.delay = 1.5f; // give master warn time
287  bus->commandStream.emplace_back(newCommand);
288  logger->Log("CAS::AddMessage CabinPressure requested!");
289  secsincelast = 0.0f;
290  }
291  }
292  else
293  RemoveMessage(L"CABIN ALT", false);
294  if (bus->CabinPressureMb >= 703.2652f && bus->CabinPressureMb < 737.0f) // 8500'
295  AddMessage(L"CABIN ALT", MessageLevel::Caution, false);
296  else
297  RemoveMessage(L"CABIN ALT", false);
298  break;
299  default:
300  evaluating = 0;
301  break;
302  }
303 
304  // rules
305  bus->MasterWarning = false;
306  bus->MasterCaution = false;
307  for (UINT i = 0; i < bus->messages.size(); i++)
308  {
309  if (!bus->messages.at(i).acknowledged)
310  {
311  if (bus->messages.at(i).level == MessageLevel::Advisory)
312  {
313  // auto-ack after 5 seconds
314  if ((bus->ProgramTime - bus->messages.at(i).time) > 5.0f)
315  {
316  bus->messages.at(i).acknowledged = true;
317  }
318  }
319  if (bus->messages.at(i).level == MessageLevel::Warning)
320  {
321  bus->MasterWarning = true;
322  }
323  if (bus->messages.at(i).level == MessageLevel::Caution)
324  {
325  bus->MasterCaution = true;
326  }
327  }
328  }
329 }
330 
332 {
333  for (UINT i = 0; i < bus->messages.size(); i++)
334  {
335  bus->messages.at(i).acknowledged = true;
336  }
337  logger->Log("CAS::AcknowledgeAllMessages Completed!");
338 }
339 
340 bool Cas::IsMessageOnStack(std::wstring text, MessageLevel level, bool renew) const
341 {
342  for (UINT i = 0; i < bus->messages.size(); i++)
343  {
344  if (bus->messages.at(i).text == text)
345  {
346  if (renew || level != bus->messages.at(i).level)
347  {
348  char msg[99];
349  sprintf_s(msg, 99, "CAS::IsMessageOnStack Retripped: %S", bus->messages.at(i).text.c_str());
350  logger->Log(msg);
351  bus->messages.erase(bus->messages.begin() + i);
352  return false;
353  }
354  return true;
355  }
356  }
357  return false;
358 }
359 
360 bool Cas::RemoveMessage(const std::wstring& text, bool onlyIfAcknowledged) const
361 {
362  for (UINT i = 0; i < bus->messages.size(); i++)
363  {
364  if (bus->messages.at(i).text == text && (!onlyIfAcknowledged || bus->messages.at(i).acknowledged))
365  {
366  bus->messages.erase(bus->messages.begin() + i);
367  char msg[99];
368  sprintf_s(msg, 99, "CAS::RemoveMessage Removed: %S", text.c_str());
369  logger->Log(msg);
370  return true;
371  }
372  }
373  return false;
374 }
375 
376 bool Cas::AddMessage(const std::wstring& text, MessageLevel level, bool renew = true)
377 {
378  if (IsMessageOnStack(text, level, renew))
379  return false;
380 
381  Message message;
382  message.acknowledged = false;
383  message.text = text;
384  message.level = level;
385  message.time = bus->ProgramTime;
386  bus->messages.emplace_back(message);
387  char msg[99];
388  sprintf_s(msg, 99, "CAS::AddMessage Added: %S (%i)", text.c_str(), level);
389  logger->Log(msg);
390 
391  // uses less-than operator in Message class!
392  std::sort(bus->messages.begin(), bus->messages.end());
393 
394  if (secsincelast >= 2.0f)
395  {
396  if (level == Warning)
397  {
399  secsincelast = 0.0f;
400  }
401  else if (level == Caution)
402  {
404  secsincelast = 0.0f;
405  }
406  }
407 
408  return true;
409 }
Scockpit ourcockpit
Definition: globals.cpp:176
std::vector< Message > messages
Definition: Bus.h:345
bool AntiIce
Definition: Bus.h:296
bool inhibit
Definition: Module.h:155
bool g_bAugment
Definition: globals.cpp:63
double ProgramTime
Definition: Bus.h:373
float power
Definition: globals.h:608
float LandingGearExtended
Definition: Bus.h:224
float fuel
Definition: globals.cpp:143
struct Bus::Afcs AFCS
Definition: Sound.h:276
std::vector< Command > commandStream
Definition: Bus.h:342
Definition: Logger.h:9
char bays
Definition: globals.h:627
MessageLevel
Definition: Message.h:5
s_network_objects playerships[MAX_SCAN]
Definition: globals.cpp:174
short texturelib
Definition: globals.h:612
float RadioAltitudeKm
Definition: Bus.h:134
int evaluating
Definition: Module.h:154
float below400Time
Definition: Module.h:158
bool ComponentRcsRollFail
Definition: Bus.h:382
Definition: Message.h:7
void FrameMove(float fElapsedTime) override
Definition: CAS.cpp:10
bool ComponentFcsRollFail
Definition: Bus.h:383
bool IsMessageOnStack(std::wstring text, MessageLevel level, bool renew) const
Definition: CAS.cpp:340
MessageLevel level
Definition: Message.h:17
Definition: Bus.h:16
std::string name
Definition: Command.h:11
float fuelmax
Definition: globals.h:637
bool IceDetected
Definition: Bus.h:274
float weightOnWheelsTime
Definition: Module.h:157
Definition: Message.h:8
bool acknowledged
Definition: Message.h:18
WCHAR temporaryMessage[99]
Definition: Module.h:159
float IndicatedAirspeedKms
Definition: Bus.h:27
float weightOffWheelsTime
Definition: Module.h:156
Definition: Module.h:12
char engines
Definition: globals.h:627
float AirframeTemperatureCelsius
Definition: Bus.h:69
float EngineThrustOutput[MAX_ENGINES]
Definition: Bus.h:43
Definition: Command.h:5
bool MasterWarning
Definition: Bus.h:148
float EngineThrustCommand[MAX_ENGINES]
Definition: Bus.h:267
float TrailingEdgeFlapsPosition
Definition: Bus.h:324
Sound * sound
Definition: Module.h:162
bool AddMessage(const std::wstring &text, MessageLevel level, bool renew)
Definition: CAS.cpp:376
bool RemoveMessage(const std::wstring &text, bool onlyIfAcknowledged=false) const
Definition: CAS.cpp:360
void Log(const char *msg, Level level=Info, int errorCode=0)
Definition: Logger.cpp:11
Bus * bus
Definition: Module.h:17
bool MasterCaution
Definition: Bus.h:375
float PitchTrimSurfacePositionDegrees
Definition: Bus.h:53
float Play(int soundEnum)
Definition: Sound.cpp:577
std::wstring text
Definition: Message.h:16
bool YawDamperStatus
Definition: Bus.h:333
double time
Definition: Message.h:19
Cas(Bus *prmBus, Logger *prmLogger, Sound *prmSound)
Definition: CAS.cpp:4
float CabinPressureMb
Definition: Bus.h:307
bool AutopilotEngaged
Definition: Bus.h:74
void Stop(int soundEnum)
Definition: Sound.cpp:1946
float delay
Definition: Command.h:8
void PlayEx(int soundEnum, bool loop, float volume=1.0f, float frequencyMod=1.0f, float pan=0.0f, bool restart=true)
Definition: Sound.cpp:606
bool parkingBrake
Definition: globals.h:685
float secsincelast
Definition: Module.h:153
bool gndvehicle
Definition: globals.h:604
bool ProximityAlert
Definition: Bus.h:376
void AcknowledgeAllMessages() const
Definition: CAS.cpp:331
float EngineThrustLever[MAX_ENGINES]
Definition: Bus.h:264
SVesselDC vdat
Definition: globals.h:669
Logger * logger
Definition: Module.h:161