Add battle abilities and wire them into START_BATTLE cutscene parsing
Adds a battleability_t enum (starting with FIRE) and a fixed abilities[8] array on battlefighter_t. Extends the START_BATTLE cutscene item to parse an optional per-enemy "abilities" JSON array (via a new cutsceneJsonLookupBattleAbility name lookup) and copies abilities onto every spawned fighter, from the party roster for allies and from the parsed config for enemies. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "error/error.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BATTLE_ABILITY_NULL,
|
||||||
|
|
||||||
|
BATTLE_ABILITY_FIRE,
|
||||||
|
|
||||||
|
BATTLE_ABILITY_COUNT
|
||||||
|
} battleability_t;
|
||||||
@@ -7,6 +7,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
|
#include "battleability.h"
|
||||||
|
|
||||||
|
#define BATTLE_FIGHTER_ABILITY_COUNT_MAX 8
|
||||||
|
|
||||||
// An empty status means the slot in BATTLE.fighters is unused.
|
// An empty status means the slot in BATTLE.fighters is unused.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -55,6 +58,7 @@ typedef struct {
|
|||||||
uint16_t mpMax;
|
uint16_t mpMax;
|
||||||
|
|
||||||
battlefighterstats_t stats;
|
battlefighterstats_t stats;
|
||||||
|
battleability_t abilities[BATTLE_FIGHTER_ABILITY_COUNT_MAX];
|
||||||
} battlefighter_t;
|
} battlefighter_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,7 +10,9 @@
|
|||||||
#include "scene/scene.h"
|
#include "scene/scene.h"
|
||||||
#include "save/save.h"
|
#include "save/save.h"
|
||||||
#include "rpg/cutscene/item/json/cutscenejsonbattleencounter.h"
|
#include "rpg/cutscene/item/json/cutscenejsonbattleencounter.h"
|
||||||
|
#include "rpg/cutscene/item/json/cutscenejsonbattleability.h"
|
||||||
#include "rpg/cutscene/item/json/cutscenejsonfield.h"
|
#include "rpg/cutscene/item/json/cutscenejsonfield.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
|
||||||
void cutsceneStartBattleStart(
|
void cutsceneStartBattleStart(
|
||||||
const cutsceneitem_t *item,
|
const cutsceneitem_t *item,
|
||||||
@@ -34,14 +36,18 @@ void cutsceneStartBattleStart(
|
|||||||
fighter->health = member->health;
|
fighter->health = member->health;
|
||||||
fighter->mp = member->mp;
|
fighter->mp = member->mp;
|
||||||
fighter->status = member->status;
|
fighter->status = member->status;
|
||||||
|
memoryCopy(fighter->abilities, member->abilities, sizeof(fighter->abilities));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(uint8_t i = 0; i < config->enemyCount; i++) {
|
for(uint8_t i = 0; i < config->enemyCount; i++) {
|
||||||
const cutscenestartbattleenemy_t *enemy = &config->enemies[i];
|
const cutscenestartbattleenemy_t *enemy = &config->enemies[i];
|
||||||
battleAddFighter(
|
battlefighter_t *fighter = battleAddFighter(
|
||||||
BATTLE_FIGHTER_TEAM_ENEMY, BATTLE_FIGHTER_CONTROLLER_AI,
|
BATTLE_FIGHTER_TEAM_ENEMY, BATTLE_FIGHTER_CONTROLLER_AI,
|
||||||
enemy->stats, enemy->healthMax, enemy->mpMax
|
enemy->stats, enemy->healthMax, enemy->mpMax
|
||||||
);
|
);
|
||||||
|
if(fighter == NULL) continue;
|
||||||
|
|
||||||
|
memoryCopy(fighter->abilities, enemy->abilities, sizeof(fighter->abilities));
|
||||||
}
|
}
|
||||||
|
|
||||||
battleStart(config->encounterType, config->fleeAvailable);
|
battleStart(config->encounterType, config->fleeAvailable);
|
||||||
@@ -162,6 +168,37 @@ errorret_t cutsceneStartBattleLoad(
|
|||||||
(uint16_t)yyjson_get_int(yyjson_obj_get(enemyVal, "healthMax"));
|
(uint16_t)yyjson_get_int(yyjson_obj_get(enemyVal, "healthMax"));
|
||||||
enemy->mpMax =
|
enemy->mpMax =
|
||||||
(uint16_t)yyjson_get_int(yyjson_obj_get(enemyVal, "mpMax"));
|
(uint16_t)yyjson_get_int(yyjson_obj_get(enemyVal, "mpMax"));
|
||||||
|
|
||||||
|
yyjson_val *abilities = yyjson_obj_get(enemyVal, "abilities");
|
||||||
|
if(abilities != NULL) {
|
||||||
|
size_t abilityCount = yyjson_arr_size(abilities);
|
||||||
|
if(!yyjson_is_arr(abilities) ||
|
||||||
|
abilityCount > BATTLE_FIGHTER_ABILITY_COUNT_MAX) {
|
||||||
|
errorThrow(
|
||||||
|
"Cutscene item (START_BATTLE): enemies[%u].abilities must have "
|
||||||
|
"0-%u entries",
|
||||||
|
(uint32_t)e, (uint32_t)BATTLE_FIGHTER_ABILITY_COUNT_MAX
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
yyjson_arr_iter abilityIter = yyjson_arr_iter_with(abilities);
|
||||||
|
yyjson_val *abilityVal;
|
||||||
|
size_t a = 0;
|
||||||
|
while((abilityVal = yyjson_arr_iter_next(&abilityIter)) != NULL) {
|
||||||
|
battleability_t ability;
|
||||||
|
if(!cutsceneJsonLookupBattleAbility(
|
||||||
|
yyjson_get_str(abilityVal), &ability
|
||||||
|
)) {
|
||||||
|
errorThrow(
|
||||||
|
"Cutscene item (START_BATTLE): enemies[%u].abilities[%u] is "
|
||||||
|
"invalid",
|
||||||
|
(uint32_t)e, (uint32_t)a
|
||||||
|
);
|
||||||
|
}
|
||||||
|
enemy->abilities[a] = ability;
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
}
|
||||||
e++;
|
e++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ typedef struct {
|
|||||||
battlefighterstats_t stats;
|
battlefighterstats_t stats;
|
||||||
uint16_t healthMax;
|
uint16_t healthMax;
|
||||||
uint16_t mpMax;
|
uint16_t mpMax;
|
||||||
|
battleability_t abilities[BATTLE_FIGHTER_ABILITY_COUNT_MAX];
|
||||||
} cutscenestartbattleenemy_t;
|
} cutscenestartbattleenemy_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
cutscenejsonentitytype.c
|
cutscenejsonentitytype.c
|
||||||
cutscenejsonentitydir.c
|
cutscenejsonentitydir.c
|
||||||
cutscenejsonbattleencounter.c
|
cutscenejsonbattleencounter.c
|
||||||
|
cutscenejsonbattleability.c
|
||||||
cutscenejsonbattlestate.c
|
cutscenejsonbattlestate.c
|
||||||
cutscenejsonscenetype.c
|
cutscenejsonscenetype.c
|
||||||
cutscenejsonuiscreentype.c
|
cutscenejsonuiscreentype.c
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cutscenejsonbattleability.h"
|
||||||
|
#include "cutscenejsonenum.h"
|
||||||
|
|
||||||
|
static const cutscenejsonenumentry_t CUTSCENE_JSON_BATTLE_ABILITY_TABLE[] = {
|
||||||
|
{ "FIRE", BATTLE_ABILITY_FIRE },
|
||||||
|
};
|
||||||
|
#define CUTSCENE_JSON_BATTLE_ABILITY_TABLE_COUNT \
|
||||||
|
(sizeof(CUTSCENE_JSON_BATTLE_ABILITY_TABLE) / \
|
||||||
|
sizeof(cutscenejsonenumentry_t))
|
||||||
|
|
||||||
|
bool_t cutsceneJsonLookupBattleAbility(
|
||||||
|
const char_t *name,
|
||||||
|
battleability_t *out
|
||||||
|
) {
|
||||||
|
int32_t value;
|
||||||
|
if(!cutsceneJsonLookupEnumInsensitive(
|
||||||
|
CUTSCENE_JSON_BATTLE_ABILITY_TABLE,
|
||||||
|
CUTSCENE_JSON_BATTLE_ABILITY_TABLE_COUNT, name, &value
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out = (battleability_t)value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dusk.h"
|
||||||
|
#include "rpg/battle/battleability.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks up name (case-insensitively) against the battle ability table.
|
||||||
|
*
|
||||||
|
* @param name Name to search for.
|
||||||
|
* @param out Set to the matching ability on success.
|
||||||
|
* @return true if a matching entry was found, false otherwise.
|
||||||
|
*/
|
||||||
|
bool_t cutsceneJsonLookupBattleAbility(
|
||||||
|
const char_t *name,
|
||||||
|
battleability_t *out
|
||||||
|
);
|
||||||
Reference in New Issue
Block a user