SpaceQuakeHulk/Quake/sh_game.h
saarsena@gmail.com 8269b17aa7
Some checks failed
Linux / Build Linux (push) Has been cancelled
Linux / Build Linux-1 (push) Has been cancelled
macOS / Build macOS (push) Has been cancelled
macOS / Build macOS-1 (push) Has been cancelled
Windows (MinGW) / Build MinGW (push) Has been cancelled
Windows (MinGW) / Build MinGW-1 (push) Has been cancelled
Windows (MSVC) / Build Windows (push) Has been cancelled
Windows (MSVC) / Build Windows-1 (push) Has been cancelled
first
2026-03-24 10:46:22 -04:00

276 lines
6.8 KiB
C

/*
* sh_game.h -- Space Hulk turn-based game system for Quakespasm
*
* Copyright (C) 2026 fish fvch studios
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef SH_GAME_H
#define SH_GAME_H
/* ============================================================
* CONSTANTS
* ============================================================ */
#define SH_GRID_SIZE 128 /* quake units per grid cell */
#define SH_MAX_MARINES 5
#define SH_MAX_GENESTEALERS 32
#define SH_MAX_DOORS 16
#define SH_MAX_BLIP_ENTRIES 8
#define SH_MAX_LOG_MESSAGES 32
#define SH_LOG_MSG_LEN 80
#define SH_DEFAULT_AP 4
#define SH_MAX_COMMAND_POINTS 6 /* 1d6 bonus AP per round */
#define SH_GENESTEALER_MP 6 /* movement points per alien phase */
/* AP costs */
#define SH_AP_MOVE_FORWARD 1
#define SH_AP_TURN 0 /* free turns for snappy gameplay */
#define SH_AP_SHOOT 1
#define SH_AP_OVERWATCH 2
#define SH_AP_MELEE 1
#define SH_AP_DOOR 1
/* animation durations (seconds) */
#define SH_ANIM_MOVE_DURATION 0.2
#define SH_ANIM_TURN_DURATION 0.15
#define SH_ANIM_SHOOT_DURATION 0.3
#define SH_MAX_ANIMS 8
/* standing eye height above grid floor */
#define SH_EYE_HEIGHT 32
/* ============================================================
* ENUMERATIONS
* ============================================================ */
typedef enum {
SH_PHASE_INACTIVE, /* game not started */
SH_PHASE_BRIEFING, /* pre-mission screen */
SH_PHASE_PLAYER, /* player marine phase */
SH_PHASE_ALIEN, /* AI genestealer phase */
SH_PHASE_OVERWATCH_REACT, /* interrupt: marine reaction fire */
SH_PHASE_ROUND_END, /* cleanup, check win/lose */
SH_PHASE_VICTORY,
SH_PHASE_DEFEAT
} sh_phase_t;
typedef enum {
SH_ACTION_NONE,
SH_ACTION_MOVE_FORWARD,
SH_ACTION_TURN_LEFT,
SH_ACTION_TURN_RIGHT,
SH_ACTION_TURN_180,
SH_ACTION_SHOOT,
SH_ACTION_OVERWATCH,
SH_ACTION_MELEE,
SH_ACTION_DOOR,
SH_ACTION_END_TURN
} sh_action_t;
typedef enum {
SH_FACING_NORTH, /* +Y: yaw 90 */
SH_FACING_EAST, /* +X: yaw 0 */
SH_FACING_SOUTH, /* -Y: yaw 270 */
SH_FACING_WEST /* -X: yaw 180 */
} sh_facing_t;
typedef enum {
SH_WEAPON_STORM_BOLTER,
SH_WEAPON_ASSAULT_CANNON,
SH_WEAPON_POWER_FIST,
SH_WEAPON_FLAMER
} sh_weapon_t;
typedef enum {
SH_LOG_INFO,
SH_LOG_COMBAT,
SH_LOG_ALERT,
SH_LOG_KILL
} sh_log_type_t;
typedef enum {
SH_AI_IDLE,
SH_AI_ADVANCE,
SH_AI_ATTACK,
SH_AI_FLANK
} sh_ai_state_t;
/* ============================================================
* DATA STRUCTURES
* ============================================================ */
/* Sidecar data for a marine entity */
typedef struct {
qboolean active;
edict_t *ent; /* quake edict for rendering/collision */
int squad_index;
int grid_x, grid_y;
sh_facing_t facing;
int ap; /* action points remaining this turn */
int ap_max; /* base AP (default 4) */
sh_weapon_t weapon;
int health; /* 1 = alive in Space Hulk */
qboolean on_overwatch;
int overwatch_ap;
qboolean has_acted; /* activated this phase */
qboolean alive;
char name[32];
} sh_marine_t;
/* Sidecar data for a genestealer entity */
typedef struct {
qboolean active;
edict_t *ent;
int grid_x, grid_y;
sh_facing_t facing;
int mp; /* movement points remaining this phase */
sh_ai_state_t ai_state;
int target_marine; /* index into marines[], or -1 */
qboolean alive;
qboolean is_blip;
int blip_count; /* 1-3 genestealers per blip */
} sh_genestealer_t;
/* Door entity */
typedef struct {
qboolean active;
edict_t *ent;
int grid_x, grid_y;
qboolean is_open;
} sh_door_t;
/* Blip spawn entry point */
typedef struct {
int grid_x, grid_y;
sh_facing_t entry_facing;
qboolean active;
} sh_blip_entry_t;
/* Message log (adapted from ideas/turn_manager.c) */
typedef struct {
char text[SH_LOG_MSG_LEN];
sh_log_type_t type;
int round;
int stack_count;
} sh_log_msg_t;
typedef struct {
sh_log_msg_t messages[SH_MAX_LOG_MESSAGES];
int write_index;
int count;
qboolean updated;
} sh_message_log_t;
/* Animation lerp for smooth grid movement in 3D */
typedef struct {
qboolean active;
edict_t *ent;
vec3_t start_pos;
vec3_t end_pos;
float start_yaw;
float end_yaw;
double start_time;
double duration;
} sh_anim_t;
/* ============================================================
* MASTER GAME STATE
* ============================================================ */
typedef struct {
/* phase management */
sh_phase_t phase;
sh_phase_t phase_before_interrupt;
int round_number;
int command_points;
int command_points_used;
/* marines */
sh_marine_t marines[SH_MAX_MARINES];
int num_marines;
int selected_marine;
/* genestealers */
sh_genestealer_t genestealers[SH_MAX_GENESTEALERS];
int num_genestealers;
int current_alien;
/* doors */
sh_door_t doors[SH_MAX_DOORS];
int num_doors;
/* spawn points */
sh_blip_entry_t blip_entries[SH_MAX_BLIP_ENTRIES];
int num_blip_entries;
/* animation queue */
sh_anim_t anims[SH_MAX_ANIMS];
int num_anims;
/* message log */
sh_message_log_t log;
/* camera (follows selected marine for now) */
int camera_marine;
} sh_gamestate_t;
extern sh_gamestate_t sh_game;
/* ============================================================
* PUBLIC API -- sh_game.c
* ============================================================ */
void SH_Init (void);
void SH_Shutdown (void);
void SH_NewGame (void);
void SH_Frame (void);
qboolean SH_Active (void);
/* coordinate conversion */
void SH_GridToWorld (int gx, int gy, vec3_t out);
void SH_WorldToGrid (vec3_t pos, int *gx, int *gy);
/* facing helpers */
float SH_FacingToYaw (sh_facing_t facing);
sh_facing_t SH_YawToFacing (float yaw);
void SH_FacingToDir (sh_facing_t facing, int *dx, int *dy);
/* grid collision */
qboolean SH_GridBlocked (int gx, int gy, edict_t *ignore);
/* animation */
void SH_AnimPush (edict_t *ent, vec3_t start, vec3_t end,
float start_yaw, float end_yaw, double duration);
qboolean SH_AnimBusy (void);
/* logging */
void SH_Log (sh_log_type_t type, const char *fmt, ...) FUNC_PRINTF(2,3);
/* ============================================================
* PUBLIC API -- sh_marine.c
* ============================================================ */
void SH_Marine_Spawn (int index, int gx, int gy,
sh_facing_t facing, sh_weapon_t weapon, const char *name);
qboolean SH_Marine_TryAction (int marine_index, sh_action_t action);
void SH_Marine_BeginPlayerPhase (void);
qboolean SH_Marine_AllDone (void);
void SH_Marine_SelectNext (void);
void SH_Marine_SelectPrev (void);
/* ============================================================
* PUBLIC API -- sh_input.c
* ============================================================ */
void SH_Input_Init (void);
qboolean SH_Input_KeyEvent (int key, qboolean down);
#endif /* SH_GAME_H */