void F149 (PhysObjList *p1, uint tics, uint days) { s3 = p2; s2 = p3; [D7758] = [D9133]; for (esi=0x72, ebx=p1+0x9783, edi=p1+0x72; // offset 0x8b esi > 0; esi--, ebx+=338, edi--) { if (!(b[edi] & 1)) continue; if (--b[ebx] != 0) continue; // timeout b[ebx] = b[ebx-1]; s1 = esi*338 + p1 + 0x74; F144 (b[ebx-4], 5, &s3); // offset 0x87 } } // Simple wrapper for F635, shipgen func int F658 (int p1, word *p2) { return F635 (p1, p2); // random shipgen } // Various enemy generation functions // Specified position void F661 (Vec64 *p1) { F670 (0xe, p1); } void F662 (Vec64 *p1) { F670 (0x4, p1); } void F663 (Vec64 *p1) { F670 (0x2, p1); } // Something else void F664 (p1, p2, p3, p4, p5) { F672 (p1, p2, p3, p4, p5); } // Various enemy generation funcs // Random radial position // Use different shipgen tables void F665 (p1, p2) { F669 (0xc, p2, p1); } void F666 (p1, p2) { F669 (0x4, p2, p1); } void F667 (p1, p2) { F669 (0xe, p2, p1); } void F668 (p1, p2) { F669 (0x2, p2, p1); } PhysObj *F669 (int shiptable, int bounty?, int targindex) { ebx = F772 (p1); // generate ship equip if (ebx == 0) return 0; s1.w0 = 0x5000; s1.w1 = 0x31; // radial distance thingy F702 (ebx, s1); // generate random start pos b[ebx+0xff] = 9; // chase? b[ebx+0xfe] = p3; [ebx+0x11a] = p2; // set bounty, targindex eax = F1530 (); w[ebx+0x102] = eax >> 3; // random velocity w[ebx+0x106] = eax >> 3; w[ebx+0x104] = eax >> 6; F48 (0x17, 0, b[ebx+0x86]); return ebx; } // Creates new ship with same position as p2, target player PhysObj *F670 (int shiptable, Vec64 *p2) { ebx = F772 (p1) if (ebx == 0) return 0; Vec64Copy (ebx+0x3e, p2, 6*4); [ebx+0xfe] = b[D8857]; // player is target b[ebx+0x25] = 0; b[ebx+0x58] = 0; w[ebx+0x106] = 0xfff6; return ebx; } // Deviate object position in y direction by radius // Settles object onto pad void F671 (PhysObj *p1) { eax = F1521 ([p1+0x140], [p1+0xc]); In64Add32 (ebx+0x3e, [ebx+0x3e], [ebx+0x42], eax); eax = F1521 ([p1+0x140], [p1+0x10]); In64Add32 (ebx+0x46, [ebx+0x46], [ebx+0x4a], eax); eax = F1521 ([p1+0x140], [p1+0x14]); In64Add32 (ebx+0x4e, [ebx+0x4e], [ebx+0x52], eax); } // Generate assassination target? void F672 (int modelindex, p2, int stationindex, int tics, int days) { edi = F771 (D6259, 0x10, p1); // assassination target? if (edi == 0) return 0; F791 (0x12, ebp-0x38, [edi+0xa0], edi+0x124); // generate name esi = F1532 (p3, [D9133]); if (b[esi+0x14c] & 0x20) // starport, else station { memcpy (edi+0x3e, esi+0x3e, 6*4); memcpy (edi, esi, 9*4); b[edi+0x56] = b[esi+0x56]; b[edi+0x57] = 1; } else { b[edi+0x56] = b[esi+0x86]; // should zero? assumption. b[edi+0x57] = 1; } ebx = b[edi+0x86]; [edi+0x11a] = -1; b[edi+0x100] = 0; b[edi+0xfe] = b[esi+0x86]; eax = F650 (esi, ebx, ebp-0x24, &s1, &s2); // get pad pos if (eax != 0) // no room at the inn? { s3.w0 = 0x5000; s3.w1 = 0x31; F702 (edi, s3); b[edi+0x56] = b[edi+0x57] = 0; b[edi+0x100] = b[esi+0x86]; b[edi+0xff] = 0; } else { Vec64Add (edi+0x3e, ebp-0x24); // offset by pad pos b[edi+0xff] = 0x24; [edi+0xa8] = p4; [edi+0xac] = p5; // creation time in future? F671 (edi); if (b[esi+0x14c] & 0x40) b[[D7758]+b[edi+0x86]] = 0x4e; else b[[D7758]+b[edi+0x86]] = 0x2; // Hmm. } F48 (0x17, 0, b[edi+0x86]); } // Event 2 function void F673 (int p1) { switch (p1) { case 0x1: F674 (); break; // hyperspace entry? case 0x2: F680 (); break; // hyperspace exit? case 0x10: F686 (); break; // week event? case 0x13: F679 (); break; } } // Event 2, 0x1 void F674 () { esi = D9133; s1 = D9047; for (ebx=1; ebx<0x72; ebx++) { if (b[[D9133]+ebx] == 0) continue; F675 ([D9133] + 0x152*ebx + 0x74, &s1); } b[s1] = 0; } void F675 (PhysObj *p1, p2) { if ((b[p1+0x87] != 0xb || [p1+0x82] < 0xf || [p1+0x82] > 0x3f) && [p1+0x82] != 0x9a) return; if (b[p1+0x118] == 0xc) F677 (p1, p2); // bounty hunter else if ([p1+0x82] == 0x9a) F678 (p1, p2); // Trader else if (b[p1+0x118] == 0xfb) F676 (p1, p2); // pirate } void F676 (PhysObj *p1, p2) { F590 (p1, [D8861], &s4, &s1); if (!(b[p1+0xcb] & 1)) return; // HS cloud analyser F590 (p1, [D8861], &s4, &s1); // Get relative position of player if (s1 < 0x10) F677 (p1, p2); // s1 == exp. distance } void F677 (PhysObj *p1, p2) { edx = [p2]++; b[edx] = b[p1+0x86]; // add object index to list } void F678 (PhysObj *p1, p2) { if (w[p1+0x9e] >= 0) return; // entry/exit thing? if ([p1+0xf2] != [D8917]) return; F590 (p1, [D8861], &s4, &s1); // Get relative position of player w[p1+0x9e] = s1; // dist. between player and cloud. Hmm. edx = [p2]++; b[edx] = b[p1+0x86]; } // Event 2, 0x13 void F679 () { ebx = 0; for (ebx=0; (eax = b[D9047 + ebx++]) != 0; ) { eax = F1532 (eax, [D9133]); b[[D7758] + b[eax+0x86]] = 0xa; } } // Event 2, 0x2 void F680 () { for (esi=0; (eax = b[D9047 + esi++]) != 0; ) { ebx = F1532 (eax, [D9133]); [ebx+0xf2] = [D8916]; [ebx+0x56] = [ebx+0x57] = [ebx+0x25] = 0; if ([ebx+0x118] == 0xc) rv = F681 (ebx); // bounty hunter else if ([ebx+0x82] == 0x9a) rv = F683 (ebx); // Trader else rv = F682 (ebx); // pirate if (rv != 0) F940 (ebx); // Kill } b[D9046] &= 0xfe; F688 (); } int F681 (PhysObj *p1) { if ([p1+0x82] == 0x9a) { b[p1+0xff] = b[p1+0xf8]; // set AI mode [p1+0x82] = w[p1+0xe6]; // reset model F48 (0x17, 0x0, b[p1+0x86]); } return F682 (ebx); } int F682 (PhysObj *p1) { rv = F901 (p1, D9115, &s2, &s3, &s4, &s1, &s5); if (rv < 0) return 1; [p1+0xf6] = s5; // maxrange [p1+0xfa] = s1; // jumptime F684 (p1); w[p1+0xf8] = b[p1+0xff]; // Store AI mode b[p1+0xff] = 0x11; // Static? HS cloud... b[[D7758]+b[p1+0x86]] = 0x2; F48 (0x17, 0x0, b[p1+0x86]); return 0; } int F683 (PhysObj *p1) { if (w[p1+0x9e] >= 0xf) F685 (p1); // Check if close to player else F684 (p1); F606 (p1, [D9133]); // Update FOR F606 (p1, [D9133]); b[p1+0xff] = 0x12; // current w[p1+0xf8] = 0x8; // after HS w[p1+0x9e] = 0; // Set to exit cloud if (F700 (&s1) != 0) b[p1+0x100] = b[s1+0x130]; // Get starport else w[p1+0xf8] = 0x10; F48 (0x17, 0x0, b[p1+0x86]); return 0; } // Generate hyperspaced-in position close to player void F684 (PhysObj *p1) { s1.w0 = 0x5000; s1.w1 = 0x15; F702 (p1, &s1); Vec64Add (p1+0x3e, [D8861]+0x3e); b[p1+0x56] = b[[D8861]+0x56]; b[p1+0x57] = 0; } // Generates normal hyperspaced-in position void F685 (PhysObj *p1) { s1.w0 = 0x5000; s1.w1 = 0x33; F702 (p1, &s1); } // Event 2, 0x10 function void F686 () { if (b[D8870] != 0x4) { // if not in hyperspace b[D9046] |= 0x1; // indicates periodic update? F688 (); } } // Event 0 function void F687 (p1) { if (p1 & 0xff == 3) { b[D9046] &= 0xfe; F688 (); } } // Generates pirates etc. on entering a system? // also periodically... void F688 () { F869 ([D8885], &s1, &s2, &s4, &s5, &s6, &s7, &s8, &s3); [D7758] = [D9133]; // Ooh, important ebx = F922 (s7); for (; ebx > 0; ebx--) F689 (); ebx = F922 (F35 (0x16)); for (; ebx > 0; ebx--) F690 (); // various traders if (!(b[D9046] & 0x1)) // initial entry { esi = 0; if ([D8997] != 0) { ebx = F922 ([D8997] << 2); if (ebx > 0x19) ebx = 0x19; if (ebx == 0) esi = 1; for (; ebx > 0; ebx--) F691 (); // landed traders } if (esi == 0) { ebx = F922 (s7); for (; ebx > 0; ebx--) F699 (); // Lynx, LRC } } // J2903 ebx = s5; if (!(b[D9046] & 0x1)) ebx <<= 2; ebx = F922 (ebx); for (; ebx > 0; ebx--) F698 (); // generic pirates ebx = F922 (s5); for (; ebx > 0; ebx--) F692 (); // null } // F689 and F690 identical except for first param // Both appear to generate traders void F689 () { ebx = F772 (1); // trader? if (ebx == 0) return; s1.w0 = 0x5000; s1.w1 = 0x33; F702 (ebx, s1); b[ebx+0xff] = 0x11; w[ebx+0xf8] = 0x8; if (!F700 (&s2)) { F940 (ebx); return; } // Kill if no starport b[ebx+0x100] = b[ebx+0x130]; F1530 (); [ebx+0xa8] = [D8818] << 2; [ebx+0xac] = [D8818] >> 0x1e; if ((b[D8806] & 0x80) && (b[ebx+0xab] & 0x80)) [ebx+0xac]++; [ebx+0xa8] += [D8804]; [ebx+0xac] += [D8807]; if (!F775 (ebx)) { F940 (ebx); return; } b[[D7758]+b[ebx+0x86]] = 2; F48 (0x17, 0x0, b[ebx+0x86]); } void F690 () { ebx = F772 (0x11); if (ebx == 0) return; s1.w0 = 0x5000; s1.w1 = 0x33; F702 (ebx, s1); b[ebx+0xff] = 0x11; w[ebx+0xf8] = 0x8; if (!F700 (&s2)) { F940 (ebx); return; } b[ebx+0x100] = b[ebx+0x130]; F1530 (); [ebx+0xa8] = [D8818] << 2; [ebx+0xac] = [D8818] >> 0x1e; if ((b[D8806] & 0x80) && (b[ebx+0xab] & 0x80)) [ebx+0xac]++; [ebx+0xa8] += [D8804]; [ebx+0xac] += [D8807]; if (!F775 (ebx)) { F940 (ebx); return; } b[[D7758]+b[ebx+0x86]] = 2; F48 (0x17, 0x0, b[ebx+0x86]); } // Generate landed/docked traders void F691 () { edi = F772 (1); if (edi == 0) return; esi = F700 (&s3); if (esi == 0) { F940 (edi); return; } if (b[esi+0x14c] & 0x20) { memcpy (edi+0x3e, esi+0x3e, 6*4); memcpy (edi, esi, 9*4); b[edi+0x56] = b[esi+0x56]; b[edi+0x57] = 1; } else { b[edi+0x56] = b[esi+0x86]; b[edi+0x57] = 1; } if (F650 (esi, b[edi+0x86], &s9, &s1, &s2)) { F940 (edi); return; } // J2920 Vec64Add (edi+0x3e, &s9); b[edi+0xff] = 0x24; b[edi+0x100] = 0; b[edi+0xfe] = b[edi+0x86]; F1530 (); [ebx+0xa8] = [D8818] << 2; [ebx+0xac] = [D8818] >> 0x1e; if ((b[D8806] & 0x80) && (b[ebx+0xab] & 0x80)) [ebx+0xac]++; [ebx+0xa8] += [D8804]; [ebx+0xac] += [D8807]; F671 (edi); if (b[esi+0x14c] & 0x40) b[[D7758]+b[edi+0x86]] = 0x4e; else b[[D7758]+b[edi+0x86]] = 0x2; F48 (0x17, 0x0, b[edi+0x86]); } // Null function void F692 () { } // F693-F696 are pirate (group) generation funcs void F693 () { } // Single ship, high bounty void F694 (p1) { ebx = F772 (0xa); if (ebx == 0) return; b[ebx+0xfe] = p1; s1.w0 = 0x5000; s1.w1 = 0x33; F702 (ebx, s1); b[ebx+0xff] = 0x5; F697 (ebx, 4); F48 (0x17, 0x0, b[ebx+0x86]); } // Up to four identical ships in a group, small bounty for leader void F695 (p1) { Vec64Copy (&s7, D6270); // group spacing edi = F772 (0xb); if (edi == 0) return; b[edi+0xfe] = p1; s1.w0 = 0x5000; s1.w1 = 0x33; F702 (edi, s1); b[edi+0xff] = 5; F697 (edi, 2); F48 (0x17, 0x0, b[edi+0x86]); esi = edi; edi = F771 (esi, 0xb, [esi+0x82]); if (edi == 0) return; b[edi+0xff] = 0xb; b[edi+0xfe] = b[esi+0x86]; b[edi+0x100] = p1; b[edi+0x101]++; // retro power related. Abtraction of catchup... w[edi+0x102] = 0x1f4; // group position offset w[edi+0x106] = 0xfe0c; w[edi+0x104] = 0x0; Vec64Add (edi+0x3e, &s7); F697 (edi, 0); F48 (0x17, 0x0, b[edi+0x86]); if (F1530 () & 0x40) return; edi = F771 (esi, 0xb, [esi+0x82]); if (edi == 0) return; b[edi+0xff] = 0xb; b[edi+0xfe] = b[esi+0x86]; b[edi+0x100] = p1; b[edi+0x101]++; w[edi+0x102] = 0xfe0c; w[edi+0x106] = 0xfe0c; w[edi+0x104] = 0x0; Vec64Sub (edi+0x3e, &s7); Vec64Sub (edi+0x3e, &s7); F697 (edi, 0); F48 (0x17, 0x0, b[edi+0x86]); if (F1530 () & 0x40) return; edi = F771 (esi, 0xb, [esi+0x82]); if (edi == 0) return; b[edi+0xff] = 0xb; b[edi+0xfe] = b[esi+0x86]; b[edi+0x100] = p1; b[edi+0x101]++; w[edi+0x102] = 0x0; w[edi+0x106] = 0xfc18; w[edi+0x104] = 0x0; Vec64Sub (edi+0x3e, &s7); Vec64Sub (edi+0x3e, &s7); Vec64Sub (edi+0x3e, &s7); F697 (edi, 0); F48 (0x17, 0x0, b[edi+0x86]); } // Up to four random ships in a group, larger leader void F696 (p1) { Vec64Copy (&s8, D6271); // group spacing (2) ebx = F772 (0xa); if (ebx == 0) return; b[edi+0xfe] = p1; s2.w0 = 0x5000; s2.w1 = 0x33; F702 (ebx, s2); b[ebx+0xff] = 5; F697 (ebx, 4); F48 (0x17, 0x0, b[ebx+0x86]); esi = ebx; edi = F658 (0xb, &s1.s1); // call table lookup func directly ebx = F773 (esi, 0xb, edi); if (ebx == 0) return; b[ebx+0xff] = 0xb; b[ebx+0xfe] = b[esi+0x86]; b[ebx+0x100] = p1; b[edi+0x101]++; w[edi+0x102] = 0x1f4; w[edi+0x106] = 0xfe0c; w[edi+0x104] = 0x0; Vec64Add (ebx+0x3e, &s8); F697 (ebx, 0); F48 (0x17, 0x0, b[edi+0x86]); if (F1530 () & 0x40) return; edi = F658 (0xb, &s1.s1); ebx = F773 (esi, 0xb, edi); if (ebx == 0) return; b[ebx+0xff] = 0xb; b[ebx+0xfe] = b[esi+0x86]; b[ebx+0x100] = p1; b[edi+0x101]++; w[edi+0x102] = 0xfe0c; w[edi+0x106] = 0xfe0c; w[edi+0x104] = 0x0; Vec64Sub (ebx+0x3e, &s8); Vec64Sub (ebx+0x3e, &s8); F697 (ebx, 0); F48 (0x17, 0x0, b[edi+0x86]); if (F1530 () & 0x40) return; edi = F658 (0xb, &s1.s1); ebx = F773 (esi, 0xb, edi); if (ebx == 0) return; b[ebx+0xff] = 0xb; b[ebx+0xfe] = b[esi+0x86]; b[ebx+0x100] = p1; b[edi+0x101]++; w[edi+0x102] = 0x0; w[edi+0x106] = 0xfc18; w[edi+0x104] = 0x0; Vec64Sub (ebx+0x3e, &s8); Vec64Sub (ebx+0x3e, &s8); Vec64Sub (ebx+0x3e, &s8); F697 (ebx, 0); F48 (0x17, 0x0, b[edi+0x86]); } // Setup pirate? // second param alters bounty void F697 (PhysObj *p1, int p2) { [p1+0x11a] = [D6268 + ((F1530()&0xf)+p2)*4]; // bounty b[p1+0x118] = 0xfb; // pirate code } // Top-level pirate generation function void F698 () { switch F922 (4) { case 0: F694 (b[D8857]); break; // single ship case 1: F695 (b[D8857]); break; // group identical case 2: F696 (b[D8857]); break; // group random case 3: F693 (b[D8857]); break; // nothing } } // Generates objects close to stations (Lynx, LRC) void F699 () { if (!F701 (&s2)) return; ebx = F772 (0xf); if (ebx == 0) return; b[ebx+0x101] = 0xff; s1.w0 = 0x5000; s2.w0 = 0x18; F702 (ebx, s1); b[ebx+0xff] = 0xd; b[ebx+0x56] = b[s2+0x130]; F48 (0x17, 0x0, b[ebx+0x86]); } // Selects random starport/station pointer int F700 (PhysObj **p1) { if ([D8997] == 0) return 0; [p1] = D8999 + 0x322*F922 ([D8997]); // starport pointer return F1532 (b[[p1]+0x130], [D9133]); } // Selects random station pointer int F701 (Starport **p1) { if ([D9011] == 0 || [D8997] == 0) return 0; edx = F922 ([D9011]); for (eax=0; eax < [D8997]; eax++) { if (!(b[D8999 + eax*0x332 + 0x131] & 0x10)) continue; if (edx-- <= 0) break; } if (edx < 0) return 0; if (!(b[D8999 + eax*0x332 + 0x131] & 0x10)) return 0; [p1] = D8999 + eax*0x332; return 1; } // Generates hyperspaced-in type position void F702 (PhysObj *p1, p2) { F1530 (); F1507 (p1, p2, [D8818], [D8820]); // Calc "planet position" w[p1+0xb4] = 0; w[p1+0xb6] = 0; w[p1+0xb8] = 0; } // Name generator function? // p2 type-related byte void F703 (PhysObj *p1, int p2, p3) { F1530 (); [p1+0xa0] = [D8818]; F791 (p2, p3, [D8818], p1+0x124); } // Worker for event 5 void F704 (PhysObj *p1, uint p2, uint p3) { ecx = p3 - [p1+0xac]; if (p2 < [p1+0xa8]) ecx--; esi = p2 - [p1+0xa8]; [p1+0xa8] = p2; [p1+0xac] = p3; edx = [b[p1+0xff]*16 + D6256]; if (edx != 0) edx (p1, esi, ecx); } // Event 5 function void F705 (E5Struct *p1) { F704 ([p1+0x8], [p1], [p1+0x4]; } // Funcs in E5 table (D6256): F708 F709 F710 F711 F712 F713 F714 F715 F716 F717 F723 F724 F725 F727 F729 void F706 (PhysObj *p1, p2) { [D9045] = p2; eax = [b[p1+0xff]*16 + D6255]; if (eax != 0) eax (p1); } // Event 6 function void F707 (E6Struct *p1) { F706 ([p1], [p1+4]; } // Funcs in E6 table (D6255): F732 F733 F734 F735 F736 F737 F740 F741 F742 F743 F746 F747 F748 F749 F750 F751 F752 F755 F757 F758 F759 F760 F763 F764 F765 F766 F767 F768 F769 F770 // AI 0x1c, event 5 // dies after time a4, produces some smoke // Chaff? void F708 (PhysObj *p1, uint tics, uint days) { edx = [D9155] << 0xe >> 0x10; eax = (edx > [p1+0xa4] & 0xffff); [ebx+0xa4] -= edx; if (eax != 0) { F940 (); return; } eax = [ebx+0xa4] & 0xffff; if (eax < 0xc800 && eax >= 0xbc00) F939 (p1, p1+0x3e); F1512 (p1, p3, p2); } // AI 0x1a, event 5 // dies after time a4. Explosion? void F709 (PhysObj *p1, uint tics, uint days) { esi = [D9155] << 0xf >> 0x10; edi = [p1+0xa4] & 0xffff; F1512 (p1, p3, p2); [p1+0xa4] -= esi; if (esi > edi || b[p1+0x88] > 0xd) F940 (p1); } // AI 0x18, event 5 void F710 (PhysObj *p1, uint tics, uint days) { // Null function } // AI 0x19, event 5 // Constant random spin rate, nothing else void F711 (PhysObj *p1, uint tics, uint days) { edx = [p1+0xa0] & 0xff; ebx = [p1+0xa0] >> 0x10; esi = ([D8804] << ((ebx&7)+6) >> 0x10) + edx; edx = ([D8804] << ((edx&7)+6) >> 0x10) + ebx; MatBuildYZT (p1, edx, esi); } // AI 0x15, event 5 // Metal alloys? void F712 (PhysObj *p1, uint tics, uint days) { F939 (p1, p1+0x3e, 4); F713 (p1, p2, p3); } // AI 0x16, event 5 // Normal cargo? void F713 (PhysObj *p1, uint tics, uint days) { F1512 (p1, p3, p2); F603 (p1, [D9133], [D9155]); F714 (p1, p2, p3); } // AI 0x17, event 5 - cargo - includes scooping // No movement... void F714 (PhysObj *p1, uint tics, uint days) { if (b[D8870] == 0x2c) return; if (b[[D8861]+0xc9] & 4) { if (b[[D8861]+0x56] != b[p1+0x56]) return; if (b[[D8861]+0x57] != b[p1+0x57]) return; Vec64Copy (ebp-0x24, p1+0x3e); Vec64Sub (ebp-0x24, [D8861]+0x3e); eax = Vec64Truncate (ebp-0x24); if (eax >= 2) return; Vec64to32 (ebp-0x30, ebp-0x24); F1519 (ebp-0x30, ebp-0x30); edi = F1521 ([[D8861]+0x18], [ebp-0x30]); edi += F1521 ([[D8861]+0x1c], [ebp-0x2c]); edi += F1521 ([[D8861]+0x20], [ebp-0x28]); if (edi < 0x3fffffff) return; } else { F569 (p1, [D9133], &s1.b2, &s1.b3, &s3, &s2, &s1.b1); if (!(s2.b2 & 0x10)) return; if (s1.b3 != [D8857]) { F940 (p1); return; } } if ([D8891] >= [D8889]) return; // no space if ([p1+0x82] == 0x99 || [p1+0x82] == 0x6a) { [ebp-0x60] = 0x9905; [ebp-0x48] = -1; [ebp-0x44] = p1; [ebp-0x5c] = w[p1+0x9e] + 0x8e00; // cargo strings F349 (ebp-0x60); SoundPlaySample (0x11); [D8891] ++; // increment used cargo space w[D8896+w[p1+0x9e]*2] ++; // add to cargo F148 (0x16, w[p1+0x9e]); F940 (p1); return; } eax = F1538 ([[D8861]+0x82]); eax = w[[eax+0x38]+0x12]; while (--eax >= 0) { if (b[[D8861]+eax+0xd6] != 0) continue; if ([p1+0x82] == 0xc) b[[D8861]+eax+0xd6] = 0x88; else b[[D8861]+eax+0xd6] = 0xc0; [D8889]--; F940 (p1); } } // AI 0x1b, event 5 void F715 (PhysObj *p1, uint tics, uint days) { // Null function } // AI 0x14, event 5 - mine function void F716 (PhysObj *p1, uint tics, uint days) { F603 (p1, [D9133], [D9155]); F718 (p1, p2, p3); } // AI 0x13, event 5 - missile function void F717 (PhysObj *p1, uint tics, uint days) { b[p1+0x8b] = 0; // maximal update frequency F603 (p1, [D9133], [D9155]); // update accel, inc. gravity F601 (p1, p2); // update velocity F585 (p1, p2, 1, p2); // update orientation... and stuff F718 (p1, p2, p3); } void F718 (PhysObj *p1, uint tics, uint days) { F1512 (p1, p3, p2); // updates position if (w[p1+0x9e] != 0 && [p1+0x82] > 5) { Vec64Copy (ebp-0x24, p1+0x3e, 6*4); [ebp-0x24] -= [p1+0x8c]; [ebp-0x1c] -= [p1+0x90]; [ebp-0x14] -= [p1+0x94]; F939 (p1, ebp-0x24); // smoke! } F569 ([D9133], &s1.b2, &s1.b3, &s3, &s2, &s1.b1); // collision if (s1.b2 & 0x80) { F721 (p1, s3); return; } if (!([D8835] & 4)) return; // no ECM switch ([p1+0x82]) { case 0x7, 0x9, 0xa: if (!(b[D8835] & 4)) break; case 0x4, 0x8, 0xb, 0xc, 0xd: F719 (p1); } } // Generates explosion and kills missile void F719 (PhysObj *missile) { ebx = F928 ([D9133], p1, 0x9, 0x9b, &s1); if (ebx == 0) return; b[p1+0x87] = 0xb; b[p1+0xff] = 0x1c; [ebx+0xa4] = -1; w[ebx+0x9e] = -1; eax = F1530 (); MatBuildYZT (ebx, eax & 0xffff, eax >> 0x10); SoundPlaySampleLogVol (6, b[p1+0x88]); F925 (p1); } // Missile damage function void F720 (PhysObj *missile, PhysObj *target) { esi = [[p1+0x82]*4 + D6269]; eax = F953 (p2, esi, b[p1+0x100]); // Damage if (eax != 0) F719 (p1); // destroy missile else { SoundPlaySampleLogVol (6, b[p1+0x88]); F925 (p1); // destroy object... } } // Missile hit function void F721 (PhysObj *missile, PhysObj *target) { if (b[p2+0x86] == b[p1+0x100] && w[p1+0x9e] <= 2) return; if ([p1+0x82] == 0xd) if (F722 (p1, p2) > 0) return; F720 (p1, p2); } // Nuke function int F722 (PhysObj *missile, PhysObj *target) { for (edx=[D9084];;) { if (--edx < 0) return 0; ebx = edx*0x34 + D9085; eax = b[ebx+0x4] & 0xf; if (eax != 5 && eax != 6) continue; if ([ebx+0x6] != [D8885]) continue; if (b[ebx+0x1a] == 0) continue; if (b[ebx+0x1a] == b[p1+0xfe]) break; } if (b[ebx+0x1a] != b[p2+0x86]) { eax = F1532 (b[ebx+0x1a], [D9133]); if (b[eax+0x56] != b[p2+0x86]) return 0; } F719 (p1); [p2+0x7e] = 0xa; b[ebx+0x5] = 0xff; eax = F1532 (b[ebx+0x1a], [D9133]); [eax+0x82] = 0xa2; [eax+0x7e] = 6; b[[D7758]+b[eax+0x86] = 8; if (b[p2+0x88] <= 0x10) F953 ([D8861], 0xc8, 0); return 1; } // AI 0x20, event 5 void F723 (PhysObj *p1, uint tics, uint days) { esi = F1532 (b[p1+0xfe], [D9133]); if (b[p1+0x14c] != 0x40) return; // wrong? F589 (p1, esi, -1); F591 (p1, esi, &s6); [p1+0x8c] = (s6>>7) | ((s5&0x7f)<<0x19); [p1+0x90] = (s4>>7) | ((s3&0x7f)<<0x19); [p1+0x94] = (s2>>7) | ((s1&0x7f)<<0x19); F1512 (p1, p3, p2); } // AI 0x2, event 5 // head towards player, fire laser void F724 (PhysObj *p1, uint tics, uint days) { F725 (p1, p2, p3); F931 (p1, 0); // fire laser } // AI 0x1, 0x3, 0x6, 0xc, event 5 // Basic combat AI func // no thrust, reqd roll. void F725 (PhysObj *p1, uint tics, uint days) { b[p1+0x8b] = 0; F603 (p1, [D9133], [D9155]); // gravity F585 (p1, p2, 1, p2); // orientation F601 (p1, p2); // velocity ; Needs fix for missile-assassinations F726 (p1+0x8c, D8839, p2, 0xd); // fudge F1512 (p1, p3, p2); // update pos F730 (p1, p2, p3); // animation, pulse if (b[p1+0x14e] != 0) F939 (p1, p1+0x3e, 0); // smoke F569 (p1, [D9133], &s1.b2, &s2.b3, &s1, &s3, &s2.b1); // collision } // Used by player code // Modify p1 by (p1 - p2) * (p3 << p4) F726 (Vec32 *p1, Vec32 *p2, uint tics, int p4) { if (p3 >= 0xc22e || p3 <= 0) return; if (abs ([p1+0x0] - [p2+0x0]) > 0x64) [p1+0x0] -= F1521 ([p1+0x0] - [p2+0x0], p3 << p4); if (abs ([p1+0x4] - [p2+0x4]) > 0x64) [p1+0x4] -= F1521 ([p1+0x4] - [p2+0x4], p3 << p4); if (abs ([p1+0x8] - [p2+0x8]) > 0x64) [p1+0x8] -= F1521 ([p1+0x8] - [p2+0x8], p3 << p4); } // AI 0x0, 0x4, 0x5, 0x7, 0x8, 0x9, 0xa, 0x1f, 0x23, event 5 // All navigation types? void F727 (PhysObj *p1, uint tics, uint days) { b[p1+0x8b] = 0; // each-frame update F603 (p1, [D9133], [D9155]); // gravity F601 (p1, p2); // orientation F585 (p1, p2, 1, p2); // velocity F1512 (p1, p3, p2); // position F730 (p1, p2, p3); // animation if (b[p1+0x14e] != 0) F939 (p1, p1+0x3e); // smoke if (b[p1+0xff] != 7) F569 ([D9133], &s2.b2, &s2.b3, &s1, &s3, &s2.b1); if (s2.b2 == 0 || b[p1+0xff] != 0x23) return; if (!(s2.b2 & 0x40) || !(s2.b2 & 0x20)) return; // not landed eax = F652 (b[p1+0x86], s1); // Currently docking if (eax != 0) { b[p1+0xff] = 0x20; // docked F48 (0x17, 0, b[p1+0x86]); } else F745 (p1, s1); // request permission } // Formation maintenance? void F728 (PhysObj *p1) { eax = F1532 (b[p1+0xfe], [D9133]); b[p1+0x8b] = 0; b[p1+0x56] = b[eax+0x56]; b[p1+0x57] = b[eax+0x57]; memcpy (p1, eax, 9*4); [p1+0x8c] = [eax+0x8c]; [p1+0x90] = [eax+0x90]; [p1+0x94] = [eax+0x94]; F593 (p1, eax, &s6); // Relative position +0x102 Vec64Add (p1+0x3e, &s6); b[p1+0x25] = 0; b[p1+0x58] = 0; } // AI 0xb, event 5 - formation? void F729 (PhysObj *p1, uint tics, uint days) { F728 (p1); F730 (p1, p2, p3); if (b[p1+0x14e] != 0) F939 (p1, p1+0x3e); F569 (p1, [D9133], &s2.b2, &s2.b1, &s1, &s3, &s2.b1); } // 0x9e update - animation, pulse timeout void F730 (PhysObj *p1) { ecx = [D9155] >> 0x10; edx = [D9155] & 0xffff; if (w[p1+0xe8] != 0) { // pulse timeout if (ecx > 0 && edx < w[p1+0xe8]) w[p1+0xe8] -= edx; // BUG! else w[p1+0xe8] = 0; } if (b[p1+0xff] < 0x1e) { if (w[p1+0x9e] == 0) return; if (w[p1+0x9e] < [D9155]>>1) w[p1+0x9e] = 0; else w[p1+0x9e] -= [D9155] >> 1; } else { if (b[p1+0xff] <= 0xc || w[p1+0x9e] == 0xffff) return; if (0xffff - w[p1+0x9e] < [D9155]>>1) w[p1+0x9e] = 0xffff; else w[p1+0x9e] += [D9155] >> 1; } } // Something to do with assassination targets // Used when something dies... void F731 (PhysObj *p1, p2, p3, int objindex) { if (b[p1+0x118] != 0x10) return; // assass. target if (p4 != [D8857]) return; eax = [D8804+0x4ef0] - 1; // mission roster entries while --eax >= 0) { ebx = [D8804+0x4ef4+eax*68]; // mission roster if (ebx != [p1+0xa0]) continue; b[D8804+0x4ef9+eax*68] = b[p1+0x11a]; return; } } // Event 6, AI 0x17 // General E6 update function - cooling, fuel, FOR void F732 (PhysObj *p1) { F938 (p1, [D9045]); // general equipment update b[p1+0x14d] -= [D9045]; if (b[p1+0x14d] >= 0) return; F606 (p1, [D9133]); // FOR update, with timeout b[p1+0x14d] = 0x13; } // Event 6, AI 0x24 - landed/docked? void F733 (PhysObj *p1) { s1 = [p1+0xa8]; s2 = [p1+0xac]; eax = F739 (&s2, &s1, D8807, D8804); if (eax == 0) return; [p1+0xa8] = [D8804]; [p1+0xac] = [D8807]; if (b[p1+0x118] == 0x10) b[p1+0x100] = 0; b[p1+0xff] = 0x1f; F48 (0x17, 0, b[p1+0x86]); F734 (p1); } // Event 6, AI 0x1f - request launch? void F734 (PhysObj *p1) { esi = F1532 (n[p1+0xfe], [D9133]); eax = F654 (b[p1+0x86], esi); // launch request if (eax == 0) return; b[[D7758]+b[p1+0x86]] = 0x4f; b[p1+0x57] = 1; b[p1+0xff] = 0x21; F48 (0x17, 0, b[p1+0x86]); } // Event 6, AI 0x21 - launching? void F735 (PhysObj *p1) { esi = F1532 (b[p1+0xfe], [D9133]); if (b[esi+0xc9] != 0xfe && b[esi+0xc9] != 0) return; b[p1+0xff] = 7; if (b[p1+0x14c] & 0x20) // starport { s1 = F1530 () & 0xffff; s3 = 0x1398; s2 = 0x3a98; VecMatMul (&s3, &s3, esi); w[p1+0x102] = s3; // set navigation pos w[p1+0x104] = s2; w[p1+0x106] = s1; } else { // station w[p1+0x106] = (F1530 () & 0x1ff) + 0x1388; w[p1+0x104] = w[p1+0x102] = 0; } [p1+0x8c] = [p1+0x90] = [p1+0x94] = 0; F736 (p1); // fly, be free... } // Event 6, AI 0x7 - fly away from starport/station // Variant on standard navigation - different thrust/roll void F736 (PhysObj *p1) { F732 (p1); // equipment update esi = F1532 (b[p1+0xfe], [D9133]); F610 (p1, esi, b[p1+0x101], &s1, &s4, [D9133]); // Nav if (s1 > 6) { F600 (p1, &s4, &s7); // thrusters F586 (p1); // roll, odd... return; } // Reached target... F651 (b[p1+0x86], esi); // clear traffic control if (b[p1+0x100] == 0) F761 (p1); else if (b[p1+0x100] != b[p1+0xfe] F741 (p1); // fly to new target else F745 (p1, esi); // Docking req. } // Event 6, AI 0x11 // Wait until object time, then enter HS & switch to 0x12 void F737 (PhysObj *p1) { if ([D8807] < [p1+0xac]) return; if ([D8807] == [p1+0xac] && [D8804] < [p1+0xa8]) return; b[p1+0xff] = 0x12; w[p1+0x9e] = 0; F48 (0x17, 0, b[p1+0x86]); F738 (p1); } // Hyperspace entry function void F738 (PhysObj *p1) { w[p1+0xb6] = w[p1+0xb8] = w[p1+0xba] = 0; // thrust w[p1+0xe6] = w[p1+0x82]; w[p1+0x82] = 0x9a; // HS cloud b[[D7758]+b[p1+0x86]] = 0xa; [p1+0x7e] = 8; ecx = [p1+0xfa] << 0x10; edx = [p1+0xfa] >> 0x10; if (ecx & 0x80000000 && b[p1+0xab] & 0x80) [p1+0xac]++; // BUG! [p1+0xa8] += ecx; [p1+0xac] += edx; } // returns 1 if first time < second time // modifies first time to first - second int F739 (int *edays, int *etics, int *cdays, int *ctics) { edx = [p2] < [p4]; [p2] -= [p4]; if (([p1] == 0 && edx != 0) || [p1]-edx < [p3]) { // Surely wrong... [p1] = [p1] - [p3] - edx; return 1; } else { [p1] = [p1] - [p3] - edx; return 0; } } // Event 6, AI 0x12 - Hyperspace - check for exit // Creates remnant, animates. void F740 (PhysObj *p1) { s1 = [D8804]; s2 = [D8807]; eax = F739 (&s2, &s1, p1+0xac, p1+0xa8); // freaky... if (eax != 0) { // curtime < [p1+0xa4] = (s1>>3) | (s2<<0x1d); // anim. for HS cloud? return; } esi = F928 ([D9133], p1, 0xa, 0, &s3); // copy object if (esi != 0) { b[esi+0xff] = 0x1e; b[esi+0x118] = 0xfe; [esi+0xa8] = 0xff9e8e; [esi+0xac] = 0; w[esi+0x9e] = 1; // remnant? } b[[D7758]+b[p1+0x86]] = 0x4f; [p1+0xf2] = 0; [p1+0x7e] = 0; [p1+0x82] = w[p1+0xe6]; b[p1+0xff] = b[p1+0xf8]; [p1+0x8c] = [p1+0x90] = 0; [p1+0x94] = 0x71b7; [p1+0xf2] = [p1+0xf6] = [p1+0xfa] = 0; F48 (0x17, 1, b[p1+0x86]); } // Event 6, AI 0x8 - exit from hyperspace // Sets target, offset, switches to mode 0x0 void F741 (PhysObj *p1) { b[p1+0xfe] = b[p1+0x100]; esi = F1532 (b[p1+0xfe], [D9133]); b[p1+0xff] = 0; F48 (0x17, 0, b[p1+0x86]); if (b[esi+0x14c] & 0x10) { if (b[esi+0x14c] & 0x20) { // starport s3 = 0; s2 = 0x1770; s1 = 0; VecMatMul (&s3, &s3, esi); } else { s3 = 0; s2 = 0; s1 = 0xfa0; } w[p1+0x102] = s3; w[p1+0x104] = s2; w[p1+0x106] = s1; } else { w[p1+0x102] = w[p1+0x104] = w[p1+0x106] = 0; } F742 (p1); } // Event 6, AI 0x0 // Basic nav function? void F742 (PhysObj *p1) { F732 (p1); esi = F1532 (b[p1+0xfe], [D9133]); F610 (p1, esi, b[p1+0x101], &s1, &s4, [D9133]); if (s1 > 6) { F599 (p1, &s4, &s7); F587 (p1); return; } if (b[p1+0x100] == 0) F761 (p1); else if (b[p1+0x100] != b[p1+0xfe]) F741 (p1); // fly to new target else F745 (p1, esi); // dock } // Event 6, AI 0xa // Patrol mode? void F743 (PhysObj *p1) { F732 (p1); edi = F1532 (b[p1+0xfe], [D9133]); eax = F1538 ([esi+0x82]); esi = [eax+0x14] + [eax+0x18] - 0xc; if (esi > 0) esi = 0; if (esi < -15) esi = -15; edx = abs (w[p1+0x102]) + abs (w[p1+0x104]) + abs (w[p1+0x106]); if (edx < 0x2000 >> -esi) { F1505 (&s4, F922(0xffff), F922(0xffff)); w[p1+0x102] = s4 >> -esi; w[p1+0x104] = s4 >> -esi; w[p1+0x106] = s4 >> -esi; } F610 (p1, edi, b[p1+0x101]-2, &s1, &s4, [D9133]); if (s1 > 6) { F599 (p1, &s4, &s7); F587 (p1); return; } F1505 (&s4, F922(0xffff), F922(0xffff)); w[p1+0x102] = s4 >> -esi; w[p1+0x104] = s4 >> -esi; w[p1+0x106] = s4 >> -esi; } // Pad/bay contact function void F744 (p1, p2) { eax = F652 (b[p1+0x86], p2); // signal docking completion if (eax != 0) { // current docking b[p1+0xff] = 0x20; // landed? F48 (0x17, 0, b[p1+0x86]); } else F745 (p1, p2); // Docking request } // Docking request & setup function void F745 (p1, p2) { if (!(b[p2+0x14c] & 0x10)) return; eax = F655 (p1, p2, &s7, &s1); // request permission & pad if (eax != 0) return; w[p1+0x102] = s7 >> 0xa; w[p1+0x104] = s5 >> 0xa; w[p1+0x106] = s3 >> 0xa; // target offset SoundPlaySampleLogVol (0xc, b[p1+0x88]); b[p1+0xff] = 0x23; // docking mode F48 (0x17, 0, b[p1+0x86]); } // Event 6, AI 0x23 - docking function void F746 (PhysObj *p1) { F732 (p1); esi = F1532 (b[p1+0xfe], [D9133]); F596 (p1, esi, -2, &s1, &s4, [D9133]); // fudge... if (s1 <= 0 && [D7706] != 0x3e2) { F744 (p1, esi); // docking completion if (b[esi+0x14c] & 0x20) memcpy (p1, esi, 9*4); else memcpy (p1, identity, 9*4); F671 (p1); // offset on pad by radius } F589 (p1, esi, -1); // equalises orientation F599 (p1, &s4, &s7); // set thrusters - limited } // Event 6, AI 0x20 - docked, waiting for timeout function void F747 (PhysObj *p1) { esi = F1532 (b[p1+0xfe], [D9133]); if (b[esi+0xc9] == 3) return; // waiting for traffic control F653 (esi); // clear if (b[esi+0x14c] & 0x40) b[[D7758]+b[p1+0x86]] = 0x4e; else b[[D7758]+b[p1+0x86]] = 2; b[p1+0xff] = 0x24; b[p1+0x100] = 0; F1530 (); [p1+0xa8] = [D8804] + [D8818]; [p1+0xac] = [D8807] + 2; if (b[D8806] & 8 && b[D8819] & 8) [p1+0xac]++; F48 (0x17, 0, b[p1+0x86]); } // Event 6, AI 0x22 void F748 (PhysObj *p1) { F732 (p1); if (b[[D9092]+0xc9] == -2 || b[[D9092]+0xc9] == 0) { b[p1+0xff] = 1; F48 (0x17, 0, b[p1+0x86]); } } // Event 6, AI 0x5 void F749 (PhysObj *p1) { esi = [D8818] & 0xffff; F1530 (); w[p1+0x102] = Sin16 (esi) >> 5; w[p1+0x104] = Sin16 (esi+0x4000) >> 5; w[p1+0x106] = [D8820] >> 0x16; b[p1+0xff] = 4; F48 (0x17, 0, b[p1+0x86]); } // Event 6, AI 0x4 - interception void F750 (PhysObj *p1) { F732 (p1); eax = F1532 (b[p1+0xfe], [D9133]); if (b[eax+0xff] == 0x24) { w[p1+0xb6] = w[p1+0xb8] = w[p1+0xba] = 0; return; } F596 (p1, eax, 1, &s1, &s4, [D9133]); // get pos/vel, fudge if (s1 >= 10) { F599 (p1, &s4, &s7); // set thrusters F587 (p1); // face target return; } b[p1+0xff] = 1; // enter combat. Woo. for (ebx=0x72; ebx > 0; ebx--) // sort out escorts? { if (!(b[[D9133]+ebx] & 0x40)) continue; edi = F1532 (p1, [D9133]); if (b[edi+0xff] != 0xb) continue; if (b[edi+0xfe] != b[p1+0x86]) continue; F728 (edi); b[edi+0xff] = 1; b[edi+0xfe] = b[edi+0x100]; w[edi+0x102] = w[edi+0x104] = w[edi+0x106] = 0; } if (b[p1+0xfe] == [D8857] && b[D8870] != 4 && SysMenuPlayTime ()) { [ebp-0x4c] = 0x98c3; [ebp-0x34] = -1; F349 (ebp-0x4c); eax = F1532 (b[[D8861]+0x56], [D9133]); if (b[eax+0x14c] & 0x10 || [D8867] < 0x9c40) { [D8839] = [D8840] = [D8841] = [D8842] = 0; } else { [D8839] = [[D8861]+0x8c]; [D8840] = [[D8861]+0x90]; [D8841] = [[D8861]+0x94]; [D8842] = [D8866]; } SoundPlaySample (0x1e); if (b[D9035] & b[D9039) SoundPlaySong (0xe); else SoundStopSong (); } w[p1+0x102] = w[p1+0x104] = w[p1+0x106] = 0; F48 (0x17, 0, b[p1+0x86]); F753 (p1); } // Event 6, AI 0xb - formation/escort void F751 (PhysObj *p1) { eax = F1532 (b[p1+0xfe], [D9133]); if (b[eax+0xff] != 1) return; b[p1+0xff] = 1; b[p1+0xfe] = b[p1+0x100]; w[p1+0x102] = 0; w[p1+0x104] = 0; w[p1+0x106] = 0; F732 (p1); F753 (p1); } // Event 6, AI 0x1, 0x2 - close, shoot void F752 (PhysObj *p1) { F732 (p1); F753 (p1); } // AI-attack update function void F753 (PhysObj *p1) { eax = F1532 (b[p1+0xfe], [D9133]); F610 (p1, eax, 1, &s1, &s4, [D9133]); // Set autopilot thrust if (s1 > 0xa) { F749 (p1); return; } // distance check b[D9046] |= 2; // combat mode ConsoleSetButtonImage (0x37, 1); if (s1 < 5) { b[p1+0xff] = 0x3; // evasion mode F756 (p1); F48 (0x17, 0, b[p1+0x86]); return; } if (s1 >= 9) { b[p1+0xff] = 0x1; // turn to attack mode F587 (p1); // face target F599 (p1, &s4, &s7); // set thrusters (max) } else { F587 (p1); // face target F598 (p1, &s4, &s7); // set thrusters F754 (p1); // missile/bomb, modeswitch } F48 (0x17, 0, b[p1+0x86]); } // Attack process function - missile, energy bomb, mode 1/2 void F754 (PhysObj *p1) { if (b[p1+0xff] == 1 || b[p1+0xff] == 2) // attack { s6 = w[p1+0x108]; s5 = w[p1+0x10a]; s4 = w[p1+0x10c]; F1518 (&s3, &s6); // normalise, fix15 eax = ([p1+0x18] >> 0x10) * s3; eax += ([p1+0x1c] >> 0x10) * s2; eax += ([p1+0x20] >> 0x10) * s1; if (eax <= 0x20000000) b[p1+0xff] = 1; else b[p1+0xff] = 0x2; } esi = F1530 (); if (esi >= 0x2000) return; eax = F941 (p1, (esi&0x7)+1, b[p1+0xfe]); // launch missile if (eax == 0) F937 (p1); // energy bomb } // Event 6, AI 0x3 - attack/evasion mode void F755 (PhysObj *p1) { F732 (p1); F756 (p1); } // Worker function for AI 0x3 void F756 (PhysObj *p1) { eax = F1532 (b[p1+0xfe], [D9133]); F590 (p1, eax, &s4, &s1); w[p1+0x108] = s4; w[p1+0x10a] = s3; w[p1+0x10c] = s2; w[p1+0x10e] = s1; F588 (p1); s10 = [p1+0x8c] - [D8839]; s9 = [p1+0x90] - [D8840]; s8 = [p1+0x94] - [D8841]; esi = -F1521 ([p1+0xc], s10); esi += F1521 ([p1+0x10], s9); esi += F1521 ([p1+0x14], s8); s4 = esi << 2; esi = -F1521 ([p1+0x0], s10); esi += F1521 ([p1+0x4], s9); esi += F1521 ([p1+0x8], s8); s3 = esi << 2; s2 = 0x7fff; F598 (p1, &s4, &s7); if (s1 > 0xa) { F749 (p1); return; } // mode 5->4 b[D9046] |= 2; ConsoleSetButtonImage (0x37, 1); if (s1 > 6) { b[p1+0xff] = 1; F48 (0x17, 0, b[p1+0x86]); } F754 (p1); } // Event 6, AI 0xc - missile evasion mode void F757 (PhysObj *p1) { F732 (p1); s2 = s3 = 0; s1 = 0x7fff; F599 (p1, &s3, &s6); F588 (p1); esi = F1530 (); if (esi > 0xa000) F935 (); w[p1+0xb2] = esi & 0xff; w[p1+0xb0] = (esi>>8) & 0xff; } // Event 6, AI 0x13 - missile function void F758 (PhysObj *p1) { if (++w[ebx+0x9e] > 0x3c) F719 (p1); // timeout F732 (p1); esi = F1532 (b[p1+0xfe], [D9133]); // get target pointer F596 (p1, esi, 3, &s1, &s4, [D9133]); // accel fudge function if (s1 > 4) { F599 (p1, &s4, &s7); // sets thrusters F586 (p1); // turn to face } else F721 (p1, esi); // proximity detonation } // Event 6, AI 0x6 - nothing void F759 (PhysObj *p1) { F732 (p1); } // Event 6, AI 0x10 - move by 0x1312d00, select trading target void F760 (PhysObj *p1) { edx = [p1+0x3e]; [p1+0x3e] += 0x1312d00; if (edx > [p1+0x3e]) [p1+0x42]++; F761 (p1); } // Select trading target - either HS or local void F761 (PhysObj *p1) { if (F775 (p1) && F775 (p1)) { F762 (p1); return; } b[p1+0xff] = 0x1d; w[p1+0x9e] = 0xffff; [p1+0xa4] = -1; F738 (p1); F48 (0x17, 0, b[p1+0x86]); } // Local trading target selection void F762 (PhysObj *p1) { esi = F700 (&s1); if (esi == 0) F925 (p1); else { b[p1+0x100] = b[esi+0x86]; b[p1+0xff] = 0; F48 (0x17, 0, b[p1+0x86]); } } // Event 6, AI 0x1e // Cloud remnant? Cycles HS anim, dies at obj. time void F763 (PhysObj *p1) { s1 = [D8804]; s2 = [D8807]; eax = F739 (&s2, &s1, p1+0xac, p1+0xa8); if (eax != 0) { eax = s1; if (eax < 0) eax += 0xff; [p1+0xa4] = -((eax>>8)+1); } else F925 (p1); } // Event 6, AI 0x1d // HS Entrance cloud - cycles, dies at obj time. void F764 (PhysObj *p1) { s1 = [D8804]; s2 = [D8807]; eax = F739 (&s2, &s1, p1+0xac, p1+0xa8); if (eax != 0) { [p1+0xa4] = ~((s1>>3) & (s2<<0x1d)); } else F925 (p1); } // Event 6, AI 0x19 - asteroid void F765 (PhysObj *p1) { if b[p1+0x88] < 0x10) return; b[D9102] --; F925 (p1); } // Event 6, AI 0x18 // dies at small distance from player void F766 (PhysObj *p1) { if (b[p1+0x88] < 0xf) return; F940 (p1); } // Event 6, AI 0x16 - normal cargo? void F767 (PhysObj *p1) { F732 (p1); if (b[p1+0x88] < 0xd) return; F925 (p1); } // Event 6, AI 0x15 - metal alloys? // smokes for a bit void F768 (PhysObj *p1) { b[p1+0x14e]--; if (b[p1+0x14e] >= 0) return; b[p1+0xff] = 0x16; F48 (0x17, 0, b[p1+0x86]); } // Event 6, AI 0x1b - space dust void F769 (PhysObj *p1) { if (b[p1+0x8b] == 0 && b[p1+0x88] <= 0x14) { [p1+0xb0] += [D9045] << 8; if ([p1+0xb0] < [D7706]) return; } F940 (p1); } // Event 6, AI 0x9 - bounty hunters intercept function void F770 (PhysObj *p1) { F732 (p1); eax = F1532 (b[p1+0xfe], [D9133]); F596 (p1, eax, b[p1+0x101], &s1, &s4, [D9133]); if (s1 >= 0xa) { F599 (p1, &s4, &s7); F587 (p1); return; } if (b[p1+0xfe] == b[D8857]) { [ebp-0x4c] = 0x98d0; // ...regret dealing with... [ebp-0x34] = 0xd; [ebp-0x40] = [p1+0xa0]; [ebp-0x28] = [p1+0x11a]; [ebp-0x30] = p1; F349 (ebp-0x4c); SoundStopSong (); } b[p1+0xff] = 1; // combat mode F48 (0x17, 0, b[p1+0x86]); } // Pure F773 wrapper PhysObj *F771 (PhysObj *copyfrom, int shiptable, int modelindex) { return F773 (p1, p2, p3); } // Object gen of some kind PhysObj *F772 (int shiptable) { eax = F658 (p1, &s1.w1); // Generate model index return F773 (D6259, p1, eax); } PhysObj *F773 (PhysObj *copyfrom, int shiptable, int modelindex) { esi = F927 ([D9133], p1, 0x4f, p3, &s1); // create object if (s1 == 0) return 0; b[esi+0x87] = 0xb; b[esi+0x118] = p2; // store shiptable F703 (esi, b[p2+D6267], ebp-0x28); // ship name? s5 = [F1538 ([esi+0x82])+0x38]; // stats pointer s3.w1 = F1530 () & 0xffff; // tech/wealth? if (b[esi+0x118] == 0xe) { // police [esi+0xa0] = 0; // Uniform colour s3.w1 = [D8995] << 8; } if (b[esi+0x118] == 0x10) s3.w1 = 0xffff; // assass. targets s2 = w[esi+0x116]; // remain. int cap edi = 0; edx = F1530 (); eax = w[s5+0x14]; // drive if (b[esi+0x118] == 0xc) edx = 0xffff; // bounty hunters? if (edx > 0xf000 && b[esi+0x118] != 1) { s2--; edi |= 0x100; } // HS cloud analyser if (eax >= 0) { if (edx > 0xc000) eax >>= 8; // 1/3 chance of altern. eax &= 0xf; b[esi+0xd0] = eax; s2 -= [eax*4 + D6261]; // actual drive } eax = b[esi+0xd0]; [esi+0x11e] = [eax*4 + D6266] << 0x18; // fuel ebx = [eax*4 + D6262]; if (ebx >= s2) ebx = s2; s2 -= ebx; // J3101 b[esi+0x119] = ebx; // cargo fuel b[esi+0xd2] = F774 (esi, &s2); // laser ebx = s2; if (ebx > 0x12c) ebx = 0x12c; if (b[esi+0x118] == 1) ebx = ebx / 4; ebx = ebx / 4; ebx = ebx * s3.w1 / 0xffff; ebx = F922 (ebx); ebx = F922 (ebx) * 2; s2 -= ebx; w[esi+0xe2] = ebx << 4; // shields if (s2 >= 2) { ebx = F922 (s3.w1); if (ebx >= 0xc000) { edi |= 0x80; s2 -= 2; // naval ECM } else if (ebx >= 0x4000) { edi |= 0x8; s2 -= 2; // ECM } } if (s2 > 0) { s4 = w[s5+0x12]; // missiles s4 = F922 (s4+1); if (s4 >= 1) { ebx = [(s3.w1>>0xc) + D6260]; while (s2 > 0 && s4 != 0) { [esi+s4+0xd6] = ebx; s2--; s4--; } } } // J3108 if (s2 > 0) { eax = F922 (s3.w1); if (eax >= 0x800) { s2--; edi |= 4; } // scanner eax = F922 (s3.w1); if (eax >= 0xfc00 && s2 >= 4 && b[esi+0x118] != 0xe) { s2--; edi |= 0x400; } // energy bomb } edi |= 0x4000; // atmos. shield ebx = s2 * [b[esi+0x118]*4 + D6263]; if (ebx > 0xaf) ebx = 0xaf; s2 -= ebx; b[esi+0x119] += ebx; // Cargo fuel again? w[esi+0x116] = s2; // remaining capacity [esi+0xc8] = edi >> 0x10 | edi << 0x10; // equipment return esi; } // Laser selection function - returns laser index // Also reduces remaining capacity appropriately int F774 (PhysObj *p1, int *capacity) { edx = F922 (0x33); edx += [b[p1+0x118]*4 + D6264]; edx = edx * p2 >> 8; for (eax=1; eax < 9; eax++) if (edx < [eax*8+D6265+4]) break; eax--; [p2] -= [eax*8+D6265+4]; return b[eax*8+D6265]; } // Searches for suitable HS destination? // Used to see whether trading ships etc. should be generated int F775 (PhysObj *p1) { ebx = F776 (p1, 1); if (ebx != 0) return ebx; ebx = F776 (p1, 1); if (ebx != 0) return ebx; ebx = F776 (p1, 0); if (ebx != 0) return ebx; ebx = F776 (p1, 0); if (ebx != 0) return ebx; return 0; } // Finds and checks random HS destination int F776 (PhysObj *p1, int p2) { [ebp-0x2c] = F857 ([D8885], p2); // picks a system if ([ebp-0x2c] == 0) return 0; [p1+0xf2] = [ebp-0x2c]; // system F870 ([ebp-0x2c], &s6, &s3, &s4, &s5); // get system type if (s3 <= 3) return 0; // Used to get system distance s1 = F859 ([ebp-0x2c], ebp-0x44, ebp-0x30, ebp-0x34, ebp-0x38); // Used to get jump time, maxrange eax = F901 (p1, &s1, ebp-0x20, ebp-0x24, ebp-0x28, ebp-0x1c, &s2); if (eax < 0) return 0; w[p1+0xf6] = s2; // max jump range [p1+0xfa] = [ebp-0x1c]; // jump time return [ebp-0x2c]; } // Death event worker function void F777 (PhysObj *p1, int deadobjindex, int killerobj) { F731 (p1, [D8804], [D8807], p3); for (edi=0x72; edi>0; edi--) { if (b[[D9133]+edi] == 0) continue; F780 ([D9133]+0x152*edi+0x74, p1, p2); } } // Damage event worker function void F778 (PhysObj *p1, int damagedobj) { if (b[p1+0x87] != 0xb) return; edx = [b[p1+0xff]*16 + D6258]; if (edx != 0) edx (p1, p2); } // Event 11 function void F779 (p1) { if ([p1+0x0] != 0) F778 ([p1+0x4], b[p1+0x8]); // damage else F777 ([p1+0x4], b[p1+0x8], b[p1+0x9]); // death } // Death event per-object worker function void F780 (PhysObj *p1, PhysObj *deadobj, int deadobjindex) { if (b[p1+0x87] != 0xb) return; edx = [b[p1+0xff]*16 + D6257] if (edx != 0) edx (p1, p2, p3); } // F781-F784 death functions int F781 (PhysObj *p1, PhysObj *deadobj, int deadobjindex) { if (p3 != b[p1+0xfe]) return; b[p1+0xfe] = b[p2+0x100]; if (b[p2+0x100] == 0) F783 (p1, p2, p3); else { b[p1+0xff] = 5; F48 (0x17, 0, b[p1+0x86]); } } int F782 (PhysObj *p1, PhysObj *deadobj, int deadobjindex) { if (p3 != b[p1+0xfe]) return; F783 (p1, p2, p3); } int F783 (PhysObj *p1, PhysObj *deadobj, int deadobjindex) { if (b[p1+0x118] == 0xe) { b[D8647] = 0; b[D8646] &= 0xfe; } F762 (p1); // select trading target } // Death event function for missile int F784 (PhysObj *p1, PhysObj *deadobj, int deadobjindex) { if (b[p1+0xfe] == p3) w[eax+0x9e] = 0x3c; if (b[p1+0x100] == p3) b[eax+0x100] = 0; } // F785-F790 damage functions void F785 (PhysObj *p1, int attackobj) { if (p2 != b[D8857]) return; w[p1+0xb2] = F1530 () >> 6; b[p1+0xff] = 3; F48 (0x17, 0, b[p1+0x86]); } void F786 (PhysObj *p1, int attackobj) { if (b[p1+0x118] == 0x10) [p1+0x11a] = 1; b[p1+0xff] = 0x1f; [p1+0xa8] = [D8804]; [p1+0xac] = [D8807]; F48 (0x17, 0, b[p1+0x86]); F790 (p1, p2); } void F787 (PhysObj *p1, int attackobj) { b[[D7758]+b[p1+0x86]] = 0x4f; b[p1+0xff] = 0x21; F48 (0x17, 0, b[p1+0x86]); } void F788 (PhysObj *p1, int attackobj) { eax = F1532 (b[p1+0xfe], [D9133]); F651 (b[p1+0x86], eax); } void F789 (PhysObj *p1, int attackobj) { if (p2 == b[D8857]) { b[p1+0xfe] = p2; b[p1+0xff] = 1; F48 (0x17, 0, b[p1+0x86]); } F790 (p1, p2); } void F790 (PhysObj *p1, int attackobj) { if (p2 == b[D8857] && b[D8860] & 3) F237 (0xa, 0); }