// FS2 "World War 1 Ace" combat mode (chunk3 / chunk4 / chunk5). // // FS2 spawns six enemy aircraft, each with a status code: // 0 = shot down, 1 = returning / home, 2 = attacking. // The player's score (`WW1AceScore`) and bomb count (`WW1AceBombsStr`) // drive the panel HUD overlay; the "War Report" screen (chunk3 L2455) // summarises the campaign so far. // // This port keeps the same six-enemy slot table and status semantics, // adds minimal AI (attacking enemies drift toward the player, returning // enemies head home), and renders each enemy as a small line sprite in // the world view. Hit detection / damage tracking are stubbed pending // the full chunk5 fire-control routines. #ifndef WW1ACE_H #define WW1ACE_H #include #include #include "camera.h" #include "framebuffer.h" #include "renderer.h" #define WW1_ENEMY_COUNT 6 #define WW1_BULLET_COUNT 12 // pool: 6 enemy + 6 player rounds #define WW1_BOMB_COUNT 4 // pool of bombs in flight typedef enum WW1EnemyStatusE { WW1_ENEMY_SHOT_DOWN = 0, WW1_ENEMY_RETURNING = 1, WW1_ENEMY_ATTACKING = 2 } WW1EnemyStatusE; typedef struct WW1EnemyT { WW1EnemyStatusE status; int32_t worldX; // Q16.16, matches AircraftT/CameraT int32_t worldY; int32_t worldZ; // Q8.8 velocity components in metres/frame. Drives the // maneuvering AI: enemies bank, climb, and turn rather than // sliding straight toward the player. int16_t velX; int16_t velY; int16_t velZ; uint8_t heading; // byte angle uint8_t maneuverPhase; // 0..255, drives sinusoidal jink uint8_t fireCooldown; // frames until next shot at player } WW1EnemyT; typedef struct WW1BulletT { bool active; bool fromEnemy; // true = enemy round, false = player int32_t worldX; // Q16.16 int32_t worldY; int32_t worldZ; int16_t velX; // Q8.8 metres / frame int16_t velY; int16_t velZ; uint8_t framesLeft; // self-expiry counter } WW1BulletT; typedef struct WW1BombT { bool active; int32_t worldX; // Q16.16 int32_t worldY; // descending under gravity int32_t worldZ; int16_t velX; // Q8.8 metres / frame (inherited from player) int16_t velY; // negative (falling), accelerates int16_t velZ; } WW1BombT; typedef struct WW1AceStateT { bool enabled; bool showWarReport; uint16_t score; // mirrors `WW1AceScore` (16-bit) uint8_t bombs; // mirrors `WW1AceBombsStr` countdown uint16_t damageByEnemy; // mirrors $08A4 uint16_t bombHits; // mirrors $A81B uint8_t playerFireCooldown; // throttles repeat gun fire to a burst rate WW1EnemyT enemies[WW1_ENEMY_COUNT]; WW1BulletT bullets[WW1_BULLET_COUNT]; WW1BombT bombsInFlight[WW1_BOMB_COUNT]; // Internal: next bomb impact frame, RNG seed for AI jitter. uint16_t rngState; } WW1AceStateT; void ww1aceInit(WW1AceStateT *s); // Toggle WW1 Ace mode. Spawns / despawns enemies and resets the // score/bomb counters. Player coords are Q16.16 world-units. void ww1aceToggle(WW1AceStateT *s, int32_t playerX, int32_t playerZ); // Drop a bomb at the player's current world position with the player's // horizontal velocity (Q8.8 metres/frame). The bomb then falls under // gravity in `ww1aceUpdate` and tries to score a hit on a ground // enemy at impact. void ww1aceDropBombAt(WW1AceStateT *s, int32_t playerX, int32_t playerY, int32_t playerZ, int16_t playerVelX_q88, int16_t playerVelZ_q88); // Fire the machine gun at any enemy in front. The closest attacking // enemy within `aimConeDeg` of the nose gets shot down. Player coords // are Q16.16 world-units. void ww1aceFireGun(WW1AceStateT *s, int32_t playerX, int32_t playerY, int32_t playerZ, uint8_t playerYaw); // Per-frame AI + projectile update. Attacking enemies maneuver toward // the player and fire bursts when aimed; returning enemies head home; // shot-down enemies stay down. Bullets and bombs in flight advance, // expire, and check hits. Player damage accumulates via // `damageByEnemy`; when it hits AC_FAIL_BY_DAMAGE the caller can // trigger a player crash. Returns true if a player-fatal hit occurred // this frame. bool ww1aceUpdate(WW1AceStateT *s, int32_t playerX, int32_t playerY, int32_t playerZ, uint8_t playerYaw); // Render bullets and bombs in flight as small dots through the camera // projection. Called alongside ww1aceRender. void ww1aceRenderProjectiles(const WW1AceStateT *s, const CameraT *cam, RenderStateT *renderer); // Render the enemies into the 3D viewport using the supplied camera. void ww1aceRender(const WW1AceStateT *s, const CameraT *cam, RenderStateT *renderer); // Draw the score / bomb overlay near the top of the panel. void ww1aceHudDraw(const WW1AceStateT *s, FramebufferT *fb); // Draw the full "War Report" screen. Caller is responsible for // freezing the simulation while the screen is shown. void ww1aceDrawWarReport(const WW1AceStateT *s, FramebufferT *fb); #endif