/* * This program source code file is part of SystemK, a library in the KTag project. * * 🛡️ 🃞 * * Copyright © 2016-2025 Joseph P. Kearney and the KTag developers. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * There should be a copy of the GNU Affero General Public License in the LICENSE * file in the root of this repository. If not, see . */ #ifndef GAME_H #define GAME_H #include "Weapons.h" #define MAX_HEALTH 10 //! Implemented according to the 2024-07-20 "KTag Teams Compatibility Matrix". typedef enum { TEAM_PURPLE = 0, TEAM_RED = 1, TEAM_BLUE = 2, TEAM_WHITE = 3, COMMON_TEAM_ID_MASK = 3, TEAM_ORANGE = 4, TEAM_GREEN = 5, TEAM_YELLOW = 6, TEAM_BLACK = 7, EXTENDED_TEAM_ID_MASK = 7 } TeamID_t; __attribute__((always_inline)) inline TeamID_t Resolve_Common_Team_ID(uint8_t team_ID) { return (team_ID & COMMON_TEAM_ID_MASK); } __attribute__((always_inline)) inline bool Team_Can_Tag_Me(uint8_t tagging_team_ID) { bool can_tag = false; uint8_t team_ID; (void) SETTINGS_get_uint8_t(SYSTEMK_SETTING_TEAMID, &team_ID); TeamID_t my_common_team_ID = Resolve_Common_Team_ID(team_ID); if (tagging_team_ID == TEAM_PURPLE) { can_tag = true; } else if (tagging_team_ID != my_common_team_ID) { if ((tagging_team_ID == TEAM_RED) || (tagging_team_ID == TEAM_BLUE)) { can_tag = true; } } return can_tag; } typedef struct { uint8_t My_Health; WeaponID_t My_Weapon; uint8_t My_Shield_Strength; uint32_t Time_Remaining_in_Game_in_ms; uint32_t Time_Remaining_Until_Countdown_in_ms; uint16_t Shots_Fired; uint16_t Tags_Received; uint16_t Times_Tagged_Out; uint8_t Bombs_Remaining; } KTag_Game_Data_T; extern KTag_Game_Data_T KTAG_Game_Data; __attribute__((always_inline)) inline uint8_t Get_Health() { return KTAG_Game_Data.My_Health; } __attribute__((always_inline)) inline void Set_Health(uint8_t health) { KTAG_Game_Data.My_Health = health; if (KTAG_Game_Data.My_Health == 0) { KEvent_T tagged_out_event = { .ID = KEVENT_TAGGED_OUT, .Data = (void *)0x00 }; Post_KEvent(&tagged_out_event); } } __attribute__((always_inline)) inline void Reduce_Health(uint8_t reduction) { if (reduction < KTAG_Game_Data.My_Health) { KTAG_Game_Data.My_Health -= reduction; } else { KTAG_Game_Data.My_Health = 0; KEvent_T tagged_out_event = { .ID = KEVENT_TAGGED_OUT, .Data = (void *)0x00 }; Post_KEvent(&tagged_out_event); } } __attribute__((always_inline)) inline WeaponID_t Get_Weapon() { return KTAG_Game_Data.My_Weapon; } __attribute__((always_inline)) inline void Set_Weapon(WeaponID_t weapon) { KTAG_Game_Data.My_Weapon = weapon; } __attribute__((always_inline)) inline uint16_t Get_Shield_Strength() { return KTAG_Game_Data.My_Shield_Strength; } __attribute__((always_inline)) inline void Set_Shield_Strength(uint16_t strength) { KTAG_Game_Data.My_Shield_Strength = strength; } __attribute__((always_inline)) inline void Reset_Shots_Fired() { KTAG_Game_Data.Shots_Fired = 0; } __attribute__((always_inline)) inline void Increment_Shots_Fired() { if (KTAG_Game_Data.Shots_Fired < UINT16_MAX) { KTAG_Game_Data.Shots_Fired++; } } __attribute__((always_inline)) inline void Reset_Tags_Received() { KTAG_Game_Data.Tags_Received = 0; } __attribute__((always_inline)) inline void Increment_Tags_Received() { if (KTAG_Game_Data.Tags_Received < UINT16_MAX) { KTAG_Game_Data.Tags_Received++; } } __attribute__((always_inline)) inline void Reset_Times_Tagged_Out() { KTAG_Game_Data.Times_Tagged_Out = 0; } __attribute__((always_inline)) inline void Increment_Times_Tagged_Out() { if (KTAG_Game_Data.Times_Tagged_Out < UINT16_MAX) { KTAG_Game_Data.Times_Tagged_Out++; } } __attribute__((always_inline)) inline bool Still_Playing() { return (KTAG_Game_Data.My_Health > 0); } __attribute__((always_inline)) inline bool Back_In() { return Still_Playing(); } __attribute__((always_inline)) inline void Set_Time_Remaining_in_Game(uint32_t time_in_ms) { KTAG_Game_Data.Time_Remaining_in_Game_in_ms = time_in_ms; } __attribute__((always_inline)) inline uint32_t Get_Time_Remaining_in_Game_in_ms() { return KTAG_Game_Data.Time_Remaining_in_Game_in_ms; } __attribute__((always_inline)) inline void Set_Time_Remaining_Until_Countdown(uint32_t time_in_ms) { KTAG_Game_Data.Time_Remaining_Until_Countdown_in_ms = time_in_ms; } __attribute__((always_inline)) inline uint32_t Get_Time_Remaining_Until_Countdown_in_ms() { return KTAG_Game_Data.Time_Remaining_Until_Countdown_in_ms; } __attribute__((always_inline)) inline uint16_t Get_Shots_Fired() { return KTAG_Game_Data.Shots_Fired; } __attribute__((always_inline)) inline uint16_t Get_Tags_Received() { return KTAG_Game_Data.Tags_Received; } __attribute__((always_inline)) inline uint16_t Get_Times_Tagged_Out() { return KTAG_Game_Data.Times_Tagged_Out; } __attribute__((always_inline)) inline void Set_Available_Bombs(uint8_t n_bombs) { KTAG_Game_Data.Bombs_Remaining = n_bombs; } __attribute__((always_inline)) inline bool Use_Bomb_If_Available() { bool available = false; if (KTAG_Game_Data.Bombs_Remaining > 0) { KTAG_Game_Data.Bombs_Remaining--; available = true; } return available; } #endif // GAME_H