// Event 6 function void F1007 (E6Struct *p1) { esi = [p1+0x4]; if (esi & 0xffff > [D8886]) [D8886] = 0; else [D8886] -= esi & 0xffff; // time to target if ([D8921] != 0) { if (b[[D8861]+0xcb] & 0x40) [D8921] -= esi << 9; // cool booster else [D8921] -= esi << 7; if ([D8921] < 0) [D8921] = 0; // cabin temp } F934 ([D8861], esi); // drive/equip fail if (b[D8870] != 2) { F938 ([D8861], esi); return; } // cooling etc. esi = F1532 (b[D8861]+0xfe], [D9133]); F144 (0xb, 0x6, p1); // process autopilot stuff if ([[D8861]+0x138]*3 > [D8867]) F589 ([D8861], [D8862], -1); // equalise orientation - bug? if (b[[D8861]+0xff] == 0x20) // landed case { [D8862] = esi; b[D8859] = b[esi+0x86]; // starport index b[D8874] = 0; // navigation index if (!(b[esi+0x14c] & 0x40)) { // not open air b[D8871] &= 0xfb; // labels off? if (!(b[esi+0x14c] & 0x20) { b[D8870] = 0xa; // docking at station F1116 (); } else { b[D8870] = 0x8; // docking at closed starport [D8867] = 0; // Altitude F1116 (); } } else { b[D8870] = 0x2e; // landed starport F995 (); // Set orient, altitude F1116 (); // console process } F48 (1, 0, 0xd); F48 (1, 0, 0xe); } if (b[esi+0x14c] & 0x10) return; if (b[[D8861]+0xfe] != b[[D8861]+0x56]) return; // target planet/parent if (b[[D8861]+0x10e] >= 0x17]) return; // distance b[D8870] = 0; // free flight F1097 (0x8637, -1); // "Arrived in vicinity..." [D8918] = 0; // set speed F1116 (); F48 (1, 0, 0xe); } // Event 5 function F1009 (E5Struct *p1) { ebx = [p1+0x8]; ecx = [p1+0x0] - [ebx+0xa8]; esi = [p1+0x4] - [ebx+0xac]; // calc elapsed time if ([p1+0x0] < [ebx+0xa8]) esi -= 1; [ebx+0xa8] = [p1+0x0]; [ebx+0xac] = [p1+0x4]; [D8868] = ecx; [D8869] = esi; b[ebx+0x8a] = b[ebx+0x8b] = 0; // force each-frame update F1008 (ebx); // animation process eax = [D7255 + 8*(b[D8870]>>1)]; // call state function call [eax] (ebx); } // Atmosphere process function void F1014 (PhysObj *p1) { if ([D8867] > 0x1312d00) return; // altitude check if (b[p1+0xcb] & 0x40) eax = 0xb; // atmos shield else eax = 5; eax -= !(b[D8871] & 2); // undercarriage edx = [D8921] + [D8866] >> eax; // new cabin temp - speed rel. if (edx > 0xffff) F953 (p1, -1, 0); else { [D8921] += [D8866] >> eax; // increment temp edx = ([D8866] >> eax) >> 8; if (edx > 0) F953 (p1, edx, 0); // damage } if (b[D8804+0x3f62] != 0 && b[D8804+0x3f5c] != 0) { eax = F1532 (b[p1+0x56], [D9133]); if (w[eax+0xe0] < 0x116) { [D8835] |= 0x40; SoundPlaySample (0xe); // wind } } if ([D8866] < 0xbb8) { F1017 (p1); return; } // low speed if ([D9155] > 0xffff) esi = 0xffff << 0xb; else esi = [D9155] << 0xb; [p1+0x8c] -= F1521 ([p1+0x8c], esi); [p1+0x90] -= F1521 ([p1+0x90], esi); [p1+0x94] -= F1521 ([p1+0x94], esi); // atmos drag F1016 (p1); } void F1015 (PhysObj *p1) { b[D8835] &= 0xbf; // clear wind flag F1016 (p1); } void F1016 (PhysObj *p1) { if ([D8867] <= 0x1312d00) F1017 (p1); } void F1017 (PhysObj *p1) { // Null function } // Switch to manual void F1018 () { [D8918] = [D8866]; // setspeed->current b[D8870] = 0; // free flight F1116 (); // console -> nav mode SoundPlaySample (0x14); F48 (1, 0, 0xe); } // Event 5, state 0x2 - autopilot // Most of the process is actually in E6 base function void F1019 (PhysObj *p1) { // Combat manual-switch if (b[D9046] & 2 && [D9138] != 0) { F1018 (); return; } F1039 (p1); // Turret input process // Collision, some ex-atmos eax = F1033 (p1, [D9133], &s2, &s1.b3, &s1.b2); if (b[D8870] == 0x2c) return; // Dead if (!(eax & 0x20)) // not in effect region { if (eax & 0x1) F1014 (p1); // atmos process else F1035 (p1); // else asteroids, space dust } else if (eax & 0x40) // landed { if (eax & 0x80) return; // crashed [D8862] = s2; b[D8880] = 0; b[D8859] = b[s2+0x86]; F1042 (p1); // zero speed/thrust/roll F652 (b[D8857], s2); // docking-related if (b[s2+0x14c] & 0x40) { // open air b[D8870] = 0x2e; // landed mode F995 (); // fix altitude F1116 (); } else { [D8884] = 0x70000; // docking timeout SoundPlaySample (0x13); b[D8871] &= 0xdb; // text labels, engine noise? if (b[s2+0x14c] & 0x20) { // starport b[D8870] = 8; // Starport docking mode [D8804+0xdc] = 0; // zero altitude F1116 (); } else { b[D8870] = 0xa; // Station docking mode F1116 (); } } F48 (1, 0, 0xd); F48 (1, 0, 0xe); return; } else if (eax & 1) F1014 (p1); // atmos process else F1035 (p1); // asteroids, dust F1046 (p1); // smoke, pos, engine noise F603 (p1, [D9133], [D8868]); // gravity F601 (p1, [D8868]); // velocity F585 (p1, [D8868], 1, [D8868]); // orientation } // Switch to autopilot void F1020 () { if (b[D8870] >= 0x28) return; // not moving b[D8871] &= 0xfe; // clear engines-off b[[D8861]+0x100] = b[D8874]; // set navigation target if (b[D8874] == 0) return; // no target set if (!(b[[D8861]+0xca] & 0x20)) return; // no autopilot if (b[D8870] == 0x26) F1032 ([D8861]); // clears traffic ctrl. request? b[[D8861]+0xff] = 8; // basic navigation mode b[D8870] = 2; // autopilot state F48 (0x17, 0, b[[D8861]+0x86]); F1116 (); SoundPlaySample (0x14); F48 (1, 0, 0xe); } // Event 5, state 0x0 - free flight void F1021 (PhysObj *p1) { F1037 (p1); // Set-speed & heading update func F1041 (p1); // Orient, gravity, auto-roll, FOR, thrust if (b[D8871] & 1) F602 (p1, [D8868]); else F601 (p1, [D8868]); // Velocity updates - manual f2-capped if (b[D9046] & 2) // combat mode { if ([D9138] != 0) { if (b[D8870] == 2) F1018 (); // Disable autopilot F1120 (); // Switch console to combat mode b[D9135] = [D8871] & 1; [D9138] = 0; } F726 ([D8861]+0x8c, D8839, [D8868], 0xd); b[D8871] |= 1; // Set engines off F726 (D8839, [D8861]+0x8c, [D8868], 0xb); } else if ([D9138] == 0) { // switch out from combat mode b[D8871] &= 0xfe; b[D8871] |= b[D9135]; // return to previous mode F1117 (); F1119 (); // console abuse [D9138] = 1; // non-combat } F1046 (p1); // smoke, position, engine noise // collision and out-of-atmos process eax = F1033 (p1, [D9133], &s1, &s2.b3, &s2.b2); if (b[D8870] == 0x2c]) return; // death mode if (eax & 0x20) // Within starport region { if (eax & 0x40) { // landed b[D8870] = 0x24; // takeoff mode? or landing... F1116 (); F48 (1, 0, 0xe); } if (!(b[s1+0x14c] & 0x10)) return; // starport... eax = F657 ([D8857], s1); if (eax != 0) { // player currently docking b[D8870] = 6; // transitional state... F48 (1, 0, 0xe); return; } F1022 (s1); // vacate area immediately return; } if (eax & 0x40) { // landed [D8862] = s1; b[D8859] = b[s1+0x86]; F1042 (p1); // zero speed, thrust... b[D8880] = 0xff; b[D8870] = 0x32; // landed rough transition? F48 (1, 0, 0xd); F48 (1, 0, 0xe); return; } b[D8873] = 0; // time to traffic control warning if (eax & 1) { // Errr.... within atmosphere F1014 (p1); // atmos process func [D8839] = [D8840] = [D8841] = 0; // Zero velocity fudge [D8842] = [D8866]; // Set ? to player speed } F1035 (p1); // dust & asteroids } // Vacate the area immediately warning void F1022 (PhysObj *starport) { if (b[D8873] != 0) return; b[D8873] = 6; // delay between warnings [D8862] = p1; b[D8859] = b[p1+0x86]; [sb] = 0x98be; [sb+0x18] = 8; [sb+0x1c] = s1; [sb+0x4] = b[p1+0x86]; [sb+0x28] = [p1+0xa0]; F349 (sb); F48, 1, 0, 0xd); } void F570 (PhysObj *p1, PhysObjList *p2, int flags, int parentindex, PhysObj **parptr, uint distance, int padindex) flags == rval 0x1: Collision object with different radii 0x2: Distance valid? 0x40: Landing 0x80: Crash int F1033 (PhysObj *p1, PhysObjList *p2, PhysObj **parptr, byte *parindex, byte *padindex) { F569 (p1, p2, &s2, p4, p3, &s1, p5); // collision function b[D8934] = s2; // copy flags if (s1 == -1) [D8867] = 0x7fffffff; else [D8867] = s1; // set altitude if (s1 >= 0xb71b00) { if (b[D8870] != 0x2c) { if (b[D8860] & 0x40 && b[D8630] < 0) F1116 (); w[D8860] |= 0x40; // hyperspace allowed, not docked } } else { if (b[D8860] & 0x40 && b[D8630] < 0) F1116 (); w[D8860] &= 0xffbf; } if (!(b[D8934] & 1)) { // outside atmosphere F1034 (p1); // kill cargo return b[D8934]; } if ([[p3]+0x82] >= 0x86 && [[p3]+0x82] <= 0x94) // gas giant, star { if (b[p1+0xca] & 0x10) // fuel scoop { // check alt, speed, time... if (s1 > 0x1c9c380 || [D8866] < 0x23d8 || [D8804+0x1e8] > [D9155]) return b[D8934]; if ([D8891] < [D8889]) // used space < total { [D8891]++; w[D8901]++; // fill with fuel [sb+0x0] = 0x9906; [sb+0x4] = w[D8901]; [sb+0x18] = -1; F349 (sb); // print scooping message F148 (0x16, 0x8e13); // notify cargo module? SoundPlaySample (0x11); } } [D8804+0x1e8] = 0x2468a; // scoop delay if ([[p3]+0x82] >= 0x89) // sun, not gas giant { eax = [D8921]; // cabin temp mod if ([[p3]+0x82] >= 0x8c) [D8921] += [D9155]>>8; else [D8921] += [D9155]>>10; if (eax > [D8921]) F953 (p1, -1, 0); // destroy } } return b[D8934]; } // Check cargo life support void F1034 (PhysObj *p1) { if (b[p1+0xca] & 2) return; if (w[D8900] != 0) { w[D8900]--; w[D8898]++; } if (w[D8899] != 0) { w[D8899]--; w[D8897]++; } } // Space dust generation function F1035 () { } // Asteroid generation function F1036 () { } // Manual control specific input function void F1037 (PhysObj *p1) { if (b[D8630] >= 0) return; if (!([D8804+0xe9] & 1)) // not engines-off? { if (b[D7692] == 0) { // return pressed if ([D8918] < 0) { [D8918] = 0; F1038 (p1); return; } else { [D8918] += F1121 ([D8918]); if ([D8918] < 0) [D8918] = 0x7fffffff; // wraparound prevention } } if (b[D7694] == 0) { // shift pressed if ([D8918] <= 0) { if (!([D8804+0xe9] & 0x80)) { [D8918] -= [D9122] >> 8; // note constant rate if ([D8918] > 0) [D8918] = 0x80000000; } } else { edi = [D8918]; b[D8804+0xe9] |= 0x80; [D8918] -= F1121 ([D8918]); if (edi >= [D8918] || [D8918] < 0) [D8918] = 0; } } else b[D8804+0xe9] &= 0x7f; } F1038 (p1); } // Heading input update function void F1038 (PhysObj *p1) { s1 = [D8804+0xd0]; [D8804+0xd0] = GuiGetXYAccum (); s2.w0 = (w[D8804+0xd0] - s1.w0) << 6; s2.w1 = (w[D8804+0xd2] - s1.w2) << 6; if (b[D8804+0xea] != 2 && b[D8804+0xea] != 3) { if (b[D8804+0x3f54] == 0) s2.w0 = -s2.w0; if (b[D8804+0x3f55] == 0) s2.w1 = -s2.w1; w[p1+0xb0] += s2.w1; if (b[D8804+0x3f56] == 0) { w[p1+0xb4] -= s2.w0; return; } if (b[D8804+0x212] & 0x20) return; w[p1+0xb2] += s2.w0; if ([D8804+0xdc] <= 0x2625a00) { w[p1+0xb4] -= s2.w1; return; } } w[D8804+0x204] += s2.w0; w[D8804+0x206] -= s2.w1; if (w[D8804+0x206] < 0) { b[D8804+0xea] = 2; if (w[D8804+0x206] <= 0xc000) w[D8804+0x206] = 0xc001; return; } if (b[p1+0xd1] >= 4) { b[D8804+0xea] = 3; if (w[D8804+0x206] >= 0x4000) w[D8804+0x206] = 0x3fff; return; } w[D8804+0x206] = 0xffff; } // Turret input only function F1039 (PhysObj *p1) { // Run orientation input if in turret mode if (b[D8872] == 2 || b[D8873] == 3) F1038 (p1); } // General non-interactive update function (manual only?) // Updates orientation, velocity, auto-roll, FOR, thrust void F1041 (PhysObj *p1) { F585 (p1, [D9155]>>1, 0, [D9155]>>1); F585 (p1, [D9155]>>1, 0, [D9155]>>1); // Update orientation F603 (p1, [D9133], [D9155]); // Update gravity-vel if ([D8867] <= 0x2625a00) { // close to planet F609 (p1); // Set autopilot roll to D8708 w[p1+0xb2] = w[p1+0x112]; // Set real roll to auto } b[p1+0x14d]--; if (b[p1+0x14d] < 0) { F606 (p1, [D9133]); // Update FOR b[p1+0x14d] = 0xd; } if (b[D8870] == 0x24) { // takeoff? s1 = s3 = 0; s2 = 0xcc6; F599 (p1, &s3, &s6); // thrust upwards } else if (b[D8871] & 1) F1043 (p1); // engines off mode else { F607 (p1, [D8918], &s3); // Calculate setspeed thrust F599 (p1, &s3, &s6); // Thrust in direction } } // Speed/thrust etc zeroed for landing F1042 (PhysObj *p1) { [p1+0x8c] = [p1+0x90] = [p1+0x94] = 0; // speed zero w[p1+0xb0] = w[p1+0xb2] = 0; // roll rates zero [D8918] = 0; // set speed zero w[p1+0xb6] = w[p1+0xb8] = w[p1+0xba] = 0; // thrust zero; if (b[D8860] & 0x80) SoundModifyEngineNoise (3, 1, 0x12c, p1); } // Engines off thrust calculator // Has weird bit related to D8839, D9046 and side/top thrusters void F1043 (PhysObj *p1) { s3 = s2 = s1 = 0; if (b[D9046] & 2) // complete fucking mystery... { s9 = [p1+0x8c] - [D8839]; s8 = [p1+0x90] - [D8840]; s7 = [p1+0x94] - [D8841]; esi = F1521 ([p1+0xc], s9) + F1521 ([p1+0x10], s9) + F1521 ([p1+0x14], s9); edi = F1521 ([p1+0x0], s9) + F1521 ([p1+0x4], s9) + F1521 ([p1+0x8], s9); if (edi > 0x100) s3 = -edi << 2; if (edi < 0xffffff00) s3 = -edi << 2; if (esi > 0x100) s2 = -esi << 2; if (esi < 0xffffff00) s2 = -esi << 2; } if (b[D7692] == 0) s1 = 0x7fff; // shift, return else if (b[D7694] == 0) s1 = 0xffff8001; else SoundModifyEngineNoise (3, 1, 0x12c, p1); F599 (p1, &s3, &s6); // Update thrust } // Update position void F1045 (PhysObj *p1) { F1512 (p1, [D8869], [D8868]); } // Update smoke, position, engine noise void F1046 (PhysObj *p1) { if (b[p1+0x14e] != 0) F939 (p1, p1+0x3e); F1045 (p1); if (b[D9030] == 0 || b[D9116] == 0) return; // song playing // or engine-sound off edx = abs(w[p1+0xb6]); eax = abs(w[p1+0xb8]); ecx = abs(w[p1+0xba]); if (edx > eax) eax = edx; if (ecx > eax) eax = ecx; if ((eax -= 0x221) < 0) return; SoundModifyEngineNoise (3, eax, 0x1ae-eax, p1); w[D8860] |= 0x80; } // Global input-update function void F1056 (p1) { if (b[D8630] < 0 && b[D8804+0xea] == 4 && b[D7691+0x38] != 0) { // external control - rotate, zoom } if (b[D8870] != 0x2a) F1040 (p1); ebx = GuiGetLastAction (); if (ebx == 0) return; // Stuff that happens even when player module doesn't // have render control switch (ebx) { case 'm': // Launch missile for (edx=[D8861]+0xd6, eax=0; eax<10; eax++, edx++) { if (b[edx] == 0) continue; ebx = eax + 16; break; } if (ebx == 'm') break; if (ebx-15 != b[D8804+0xc4]) b[D8804+0xc4] = ebx-15; F1096 (); SoundPlaySample (0x14); return; case 'e': // ECM F935 (p1); SoundPlaySample (0x14); return; case 'x': // Escape capsule F1098 ([D8861]); SoundPlaySample (0x14); return; case 'b': // Energy bomb F937 (p1); F1119 (); SoundPlaySample (0x14); return; case '/': // Radar mapper b[D8871] ^= 0x40; SoundPlaySample (0x14); return; case 'd': // Camera, mining machine F1122 (p1); SoundPlaySample (0x14); return; case 'c': // Chaff if (b[D8630] >= 0) break; if (!(b[p1+0xc9] & 8)) break; if (w[D8804+0x174] == 0) break; eax = F291 ([D8861], 0x20); if (eax != 0) { [eax+0x82] = 0xa4; [D7253] = b[eax+0x86]; b[[D7758]+[D7253]] = 0x2b; F990 ([D9133], F1057); } SoundPlaySample (0x14); return; } if (b[D8630] >= 0) { GuiSetLastAction (ebx); return; } // Navigation computer if (b[[D8861]+0xc8] & 0x20 && ebx >= 0xd1 && ebx <= 0xe2) { edi = ebx - 0xd0; for (ebx=0x72, edx=[D9133]+0x9844, eax=[D9133]+0x72; ebx <= 0 && edi != 0; ebx--, eax--, edx-=0x152) { if (b[eax] == 0) continue; if (!(b[eax] & 0x10)) continue; if (--edi == 0) break; } b[D8804+0xec] = [[D9133] + 0x152*ebx + 0x74 + 0x86]; [D7246] = 0; if (b[D8870] != 2 && b[D8870] < 0x28) F1020 (); // goto auto if (b[D8870] == 2 && b[D8870] < 0x28) { b[D8870] = 0; F1020 (); } ConsoleSetButtonImage (0x11, 0); for (ebx=0xd1; ebx < 0xe3; ebx++) GuiRemoveHotArea (ebx); b[D7251] = b[D7250] = 0; return; } switch (ebx) { case 'l': // text labels b[D8871] ^= 0x4; if (b[D8871] & 4) ConsoleSetButtonImage (0x10, 1); else ConsoleSetButtonImage (0x10, 0); SoundPlaySample (0x14); return; case 0xf6: // Front view ConsoleSetButtonImage (0x18, 1); b[D8804+0xea] = 0; return; case 0xf7: // Rear view ConsoleSetButtonImage (0x17, 1); b[D8804+0xea] = 1; return; case 0xf8: // Turret view if (b[[D8861]+0xd1] <= 2) return; b[D8804+0xea] = 2; if (b[D8804+0x206] >= 0) b[D8804+0xea] = 3; ConsoleSetButtonImage (0x16, 1); return; case 0xf9: // External view ConsoleSetButtonImage (0x15, 1); b[D8804+0xea] = 4; return; case 0xfa: // Missile view if (b[D8804+0xef] == 0) return; if (!(b[[D8861]+0xc9] & 2)) return; ConsoleSetButtonImage (0x14, 1); b[D8804+0xea] = 5; return; case 0xfb: // Combat computer if (!(b[[D8861]+0xc8] & 0x40)) return; b[D8804+0xea] = 6; [D7270] = [D7269] = 0x320; [D7271] = 0; ConsoleSetButtonImage (0x13, 1); return; case 0xfc: // Esc. Capsule, again. F1098 ([D8861]); SoundPlaySample (0x14); return; // And more... } }