Add battle fighter damage/heal cutscene items, wire up battle results
BATTLE_FIGHTER_DAMAGE/BATTLE_FIGHTER_HEAL let a move's own cutscene apply damage/healing to "target" or "user", resolved from BATTLE_FIGHTER_POS_TARGET/USER sentinels against the current action by battleStateExecutingInit. fire/slash now call BATTLE_FIGHTER_DAMAGE on their target. BATTLE_POST_MOVE checks fighter health after each move and sets BATTLE.result (now a real field, previously commented out) to win/loss, transitioning into BATTLE_STATE_WON/LOST; fleeing sets BATTLE_RESULT_FLED. All three end states now show a textbox before moving on to BATTLE_STATE_ENDING. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
@@ -11,6 +11,11 @@
|
||||
},
|
||||
{
|
||||
"type": "MODAL_CLOSE"
|
||||
},
|
||||
{
|
||||
"type": "BATTLE_FIGHTER_DAMAGE",
|
||||
"fighter": "target",
|
||||
"amount": 12
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
},
|
||||
{
|
||||
"type": "MODAL_CLOSE"
|
||||
},
|
||||
{
|
||||
"type": "BATTLE_FIGHTER_DAMAGE",
|
||||
"fighter": "target",
|
||||
"amount": 8
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
#include "rpg/battle/fighter/battlefighterpos.h"
|
||||
#include "rpg/battle/state/battlestate.h"
|
||||
|
||||
// typedef enum {
|
||||
// BATTLE_RESULT_NONE,
|
||||
// BATTLE_RESULT_WIN,
|
||||
// BATTLE_RESULT_LOSS,
|
||||
// BATTLE_RESULT_FLED,
|
||||
// BATTLE_RESULT_COUNT
|
||||
// } battleresult_t;
|
||||
typedef enum {
|
||||
BATTLE_RESULT_NONE,
|
||||
BATTLE_RESULT_WIN,
|
||||
BATTLE_RESULT_LOSS,
|
||||
BATTLE_RESULT_FLED,
|
||||
BATTLE_RESULT_COUNT
|
||||
} battleresult_t;
|
||||
|
||||
typedef struct {
|
||||
battlefighter_t *fighters[BATTLE_FIGHTER_POS_COUNT];
|
||||
@@ -33,6 +33,11 @@ typedef struct {
|
||||
|
||||
battlestate_t state;
|
||||
battlestatedata_t stateData;
|
||||
|
||||
// Set once a side has been wiped out (see cutsceneBattlePostMoveStart)
|
||||
// or the player has fled (see battleStateSelectionPlayerFlee). Stays
|
||||
// BATTLE_RESULT_NONE for the rest of the battle otherwise.
|
||||
battleresult_t result;
|
||||
} battle_t;
|
||||
|
||||
extern battle_t BATTLE;
|
||||
|
||||
@@ -25,3 +25,11 @@ typedef uint8_t battlefighterpos_t;
|
||||
#define BATTLE_FIGHTER_POS_7 BATTLE_FIGHTER_POS(7)
|
||||
|
||||
#define BATTLE_FIGHTER_POS_COUNT (BATTLE_FIGHTER_POS_7 + 1)
|
||||
|
||||
// Sentinels resolved by battleStateExecutingInit against the currently
|
||||
// resolving action, for cutscene items authored inside a move's own
|
||||
// cutscene (e.g. cutscenes/battle/moves/slash.jsonc) that need to refer
|
||||
// to "whoever is being hit"/"whoever is attacking" without knowing their
|
||||
// concrete BATTLE.fighters index ahead of time.
|
||||
#define BATTLE_FIGHTER_POS_TARGET BATTLE_FIGHTER_POS(0xFE)
|
||||
#define BATTLE_FIGHTER_POS_USER BATTLE_FIGHTER_POS(0xFD)
|
||||
@@ -18,6 +18,18 @@
|
||||
#include "util/string.h"
|
||||
|
||||
|
||||
void battleStateExecutingResolveFighterIndex(
|
||||
battlefighterpos_t *fighterIndex,
|
||||
const uint8_t userIndex,
|
||||
const battlemoveaction_t *action
|
||||
) {
|
||||
if(*fighterIndex == BATTLE_FIGHTER_POS_TARGET) {
|
||||
*fighterIndex = action->targets[0];
|
||||
} else if(*fighterIndex == BATTLE_FIGHTER_POS_USER) {
|
||||
*fighterIndex = userIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void battleStateExecutingInit(void) {
|
||||
cutsceneitem_t items[BATTLE_STATE_EXECUTING_ITEMS_MAX];
|
||||
uint8_t itemsCount = 0;
|
||||
@@ -60,6 +72,7 @@ void battleStateExecutingInit(void) {
|
||||
}
|
||||
|
||||
// Parse out cutscene items and append to the list.
|
||||
const uint8_t moveItemsStart = itemsCount;
|
||||
cutscene_t scene;
|
||||
errorret_t parseResult = cutsceneParseDoc(
|
||||
entry->data.json, &scene, &items[itemsCount],
|
||||
@@ -75,6 +88,21 @@ void battleStateExecutingInit(void) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Resolve BATTLE_FIGHTER_POS_TARGET/USER sentinels against this
|
||||
// action, now that its user/target fighters are known.
|
||||
for(uint8_t j = moveItemsStart; j < itemsCount; j++) {
|
||||
cutsceneitem_t *moveItem = &items[j];
|
||||
if(moveItem->type == CUTSCENE_ITEM_TYPE_BATTLE_FIGHTER_DAMAGE) {
|
||||
battleStateExecutingResolveFighterIndex(
|
||||
&moveItem->battleFighterDamage.fighterIndex, i, action
|
||||
);
|
||||
} else if(moveItem->type == CUTSCENE_ITEM_TYPE_BATTLE_FIGHTER_HEAL) {
|
||||
battleStateExecutingResolveFighterIndex(
|
||||
&moveItem->battleFighterHeal.fighterIndex, i, action
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert end of attack cutscene item.
|
||||
items[itemsCount++] = (cutsceneitem_t){
|
||||
.type = CUTSCENE_ITEM_TYPE_BATTLE_POST_MOVE
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
#include "rpg/battle/fighter/battlefighterpos.h"
|
||||
#include "rpg/battle/move/battlemoveaction.h"
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -19,6 +21,24 @@ typedef struct {
|
||||
*/
|
||||
void battleStateExecutingInit(void);
|
||||
|
||||
/**
|
||||
* Resolves a BATTLE_FIGHTER_POS_TARGET/BATTLE_FIGHTER_POS_USER sentinel
|
||||
* (as parsed onto a BATTLE_FIGHTER_DAMAGE/BATTLE_FIGHTER_HEAL item inside
|
||||
* a move's own cutscene) against the action currently being resolved
|
||||
* into cutscene items. Leaves fighterIndex untouched if it's already a
|
||||
* concrete BATTLE.fighters index.
|
||||
*
|
||||
* @param fighterIndex The field to resolve in place.
|
||||
* @param userIndex Index into BATTLE.fighters of the fighter performing
|
||||
* the action.
|
||||
* @param action The action being resolved.
|
||||
*/
|
||||
void battleStateExecutingResolveFighterIndex(
|
||||
battlefighterpos_t *fighterIndex,
|
||||
const uint8_t userIndex,
|
||||
const battlemoveaction_t *action
|
||||
);
|
||||
|
||||
/**
|
||||
* Updates BATTLE_STATE_EXECUTING for one frame.
|
||||
*/
|
||||
|
||||
@@ -6,9 +6,21 @@
|
||||
*/
|
||||
|
||||
#include "battlestatefled.h"
|
||||
#include "rpg/cutscene/item/cutsceneitem.h"
|
||||
#include "rpg/cutscene/cutscenesystem.h"
|
||||
|
||||
void battleStateFledInit(void) {
|
||||
|
||||
const cutsceneitem_t items[] = {
|
||||
{
|
||||
.type = CUTSCENE_ITEM_TYPE_TEXT,
|
||||
.text = { .text = "Got away safely!" }
|
||||
},
|
||||
{
|
||||
.type = CUTSCENE_ITEM_TYPE_BATTLE_SET_STATE,
|
||||
.battleSetState = { .state = BATTLE_STATE_ENDING }
|
||||
}
|
||||
};
|
||||
cutsceneSystemInsertItemsNext(items, sizeof(items) / sizeof(cutsceneitem_t));
|
||||
}
|
||||
|
||||
void battleStateFledUpdate(void) {
|
||||
|
||||
@@ -13,7 +13,9 @@ typedef struct {
|
||||
} battlestatefled_t;
|
||||
|
||||
/**
|
||||
* Called when the battle enters BATTLE_STATE_FLED.
|
||||
* Called when the battle enters BATTLE_STATE_FLED. Queues a textbox
|
||||
* announcing the escape, then transitions to BATTLE_STATE_ENDING once
|
||||
* dismissed.
|
||||
*/
|
||||
void battleStateFledInit(void);
|
||||
|
||||
|
||||
@@ -6,9 +6,21 @@
|
||||
*/
|
||||
|
||||
#include "battlestatelost.h"
|
||||
#include "rpg/cutscene/item/cutsceneitem.h"
|
||||
#include "rpg/cutscene/cutscenesystem.h"
|
||||
|
||||
void battleStateLostInit(void) {
|
||||
|
||||
const cutsceneitem_t items[] = {
|
||||
{
|
||||
.type = CUTSCENE_ITEM_TYPE_TEXT,
|
||||
.text = { .text = "You were defeated..." }
|
||||
},
|
||||
{
|
||||
.type = CUTSCENE_ITEM_TYPE_BATTLE_SET_STATE,
|
||||
.battleSetState = { .state = BATTLE_STATE_ENDING }
|
||||
}
|
||||
};
|
||||
cutsceneSystemInsertItemsNext(items, sizeof(items) / sizeof(cutsceneitem_t));
|
||||
}
|
||||
|
||||
void battleStateLostUpdate(void) {
|
||||
|
||||
@@ -13,7 +13,9 @@ typedef struct {
|
||||
} battlestatelost_t;
|
||||
|
||||
/**
|
||||
* Called when the battle enters BATTLE_STATE_LOST.
|
||||
* Called when the battle enters BATTLE_STATE_LOST. Queues a textbox
|
||||
* announcing the loss, then transitions to BATTLE_STATE_ENDING once
|
||||
* dismissed.
|
||||
*/
|
||||
void battleStateLostInit(void);
|
||||
|
||||
|
||||
@@ -101,5 +101,6 @@ void battleStateSelectionPlayerFlee(void) {
|
||||
battlefighter_t *fighter = battleStateSelectionGetCurrentFighter();
|
||||
if(fighter == NULL) return;
|
||||
|
||||
BATTLE.result = BATTLE_RESULT_FLED;
|
||||
battleSetState(BATTLE_STATE_FLED);
|
||||
}
|
||||
@@ -6,9 +6,21 @@
|
||||
*/
|
||||
|
||||
#include "battlestatewon.h"
|
||||
#include "rpg/cutscene/item/cutsceneitem.h"
|
||||
#include "rpg/cutscene/cutscenesystem.h"
|
||||
|
||||
void battleStateWonInit(void) {
|
||||
|
||||
const cutsceneitem_t items[] = {
|
||||
{
|
||||
.type = CUTSCENE_ITEM_TYPE_TEXT,
|
||||
.text = { .text = "You won the battle!" }
|
||||
},
|
||||
{
|
||||
.type = CUTSCENE_ITEM_TYPE_BATTLE_SET_STATE,
|
||||
.battleSetState = { .state = BATTLE_STATE_ENDING }
|
||||
}
|
||||
};
|
||||
cutsceneSystemInsertItemsNext(items, sizeof(items) / sizeof(cutsceneitem_t));
|
||||
}
|
||||
|
||||
void battleStateWonUpdate(void) {
|
||||
|
||||
@@ -13,7 +13,9 @@ typedef struct {
|
||||
} battlestatewon_t;
|
||||
|
||||
/**
|
||||
* Called when the battle enters BATTLE_STATE_WON.
|
||||
* Called when the battle enters BATTLE_STATE_WON. Queues a textbox
|
||||
* announcing the win, then transitions to BATTLE_STATE_ENDING once
|
||||
* dismissed.
|
||||
*/
|
||||
void battleStateWonInit(void);
|
||||
|
||||
|
||||
@@ -9,4 +9,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
cutscenebattlesetstate.c
|
||||
cutscenebattlewaitselection.c
|
||||
cutscenebattlepostmove.c
|
||||
cutscenebattlefighterdamage.c
|
||||
cutscenebattlefighterheal.c
|
||||
)
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "rpg/cutscene/item/cutsceneitem.h"
|
||||
#include "rpg/battle/battle.h"
|
||||
#include "rpg/cutscene/item/json/cutscenejsonfield.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/string.h"
|
||||
|
||||
#define CUTSCENE_BATTLE_FIGHTER_REF_MAX 16
|
||||
|
||||
void cutsceneBattleFighterDamageStart(
|
||||
const cutsceneitem_t *item,
|
||||
cutsceneitemdata_t *data
|
||||
) {
|
||||
const cutscenebattlefighterdamage_t *damage = &item->battleFighterDamage;
|
||||
assertTrue(
|
||||
damage->fighterIndex < BATTLE_FIGHTER_POS_COUNT,
|
||||
"fighterIndex sentinel was never resolved"
|
||||
);
|
||||
battlefighter_t *fighter = BATTLE.fighters[damage->fighterIndex];
|
||||
assertNotNull(fighter, "Fighter cannot be NULL");
|
||||
|
||||
battleFighterDamage(fighter, damage->amount);
|
||||
}
|
||||
|
||||
bool_t cutsceneBattleFighterDamageUpdate(
|
||||
const cutsceneitem_t *item,
|
||||
cutsceneitemdata_t *data
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
errorret_t cutsceneBattleFighterDamageLoad(
|
||||
yyjson_val *itemObj,
|
||||
cutsceneitem_t *item
|
||||
) {
|
||||
char_t fighterRef[CUTSCENE_BATTLE_FIGHTER_REF_MAX];
|
||||
if(!cutsceneJsonCopyString(
|
||||
itemObj, "fighter", NULL, fighterRef, CUTSCENE_BATTLE_FIGHTER_REF_MAX
|
||||
)) {
|
||||
errorThrow("Cutscene item (BATTLE_FIGHTER_DAMAGE): missing 'fighter'");
|
||||
}
|
||||
if(stringEquals(fighterRef, "target")) {
|
||||
item->battleFighterDamage.fighterIndex = BATTLE_FIGHTER_POS_TARGET;
|
||||
} else if(stringEquals(fighterRef, "user")) {
|
||||
item->battleFighterDamage.fighterIndex = BATTLE_FIGHTER_POS_USER;
|
||||
} else {
|
||||
errorThrow(
|
||||
"Cutscene item (BATTLE_FIGHTER_DAMAGE): 'fighter' must be "
|
||||
"'target' or 'user'"
|
||||
);
|
||||
}
|
||||
|
||||
const int32_t amount = cutsceneJsonGetInt(itemObj, "amount", -1);
|
||||
if(amount < 0 || amount > UINT16_MAX) {
|
||||
errorThrow(
|
||||
"Cutscene item (BATTLE_FIGHTER_DAMAGE): invalid/missing 'amount'"
|
||||
);
|
||||
}
|
||||
item->battleFighterDamage.amount = (uint16_t)amount;
|
||||
|
||||
errorOk();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "rpg/cutscene/item/cutsceneitembase.h"
|
||||
#include "rpg/battle/fighter/battlefighterpos.h"
|
||||
|
||||
typedef struct {
|
||||
// Index into BATTLE.fighters of the fighter to damage, or one of
|
||||
// BATTLE_FIGHTER_POS_TARGET/BATTLE_FIGHTER_POS_USER, resolved against
|
||||
// the currently-executing action by battleStateExecutingInit before
|
||||
// this item ever runs.
|
||||
battlefighterpos_t fighterIndex;
|
||||
uint16_t amount;
|
||||
} cutscenebattlefighterdamage_t;
|
||||
|
||||
/**
|
||||
* Starts a BATTLE_FIGHTER_DAMAGE item, applying the configured damage to
|
||||
* BATTLE.fighters[fighterIndex] immediately.
|
||||
*
|
||||
* @param item The cutscene item.
|
||||
* @param data Runtime data storage.
|
||||
*/
|
||||
void cutsceneBattleFighterDamageStart(
|
||||
const cutsceneitem_t *item,
|
||||
cutsceneitemdata_t *data
|
||||
);
|
||||
|
||||
/**
|
||||
* Updates a BATTLE_FIGHTER_DAMAGE item (always completes immediately).
|
||||
*
|
||||
* @param item The cutscene item.
|
||||
* @param data Runtime data storage.
|
||||
* @returns true always.
|
||||
*/
|
||||
bool_t cutsceneBattleFighterDamageUpdate(
|
||||
const cutsceneitem_t *item,
|
||||
cutsceneitemdata_t *data
|
||||
);
|
||||
|
||||
/**
|
||||
* Parses a BATTLE_FIGHTER_DAMAGE cutscene item's JSON fields into item.
|
||||
*
|
||||
* @param itemObj The item's JSON object.
|
||||
* @param item Destination item, already zeroed by the caller.
|
||||
* @return Error code indicating success or failure of the parse.
|
||||
*/
|
||||
errorret_t cutsceneBattleFighterDamageLoad(
|
||||
yyjson_val *itemObj,
|
||||
cutsceneitem_t *item
|
||||
);
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "rpg/cutscene/item/cutsceneitem.h"
|
||||
#include "rpg/battle/battle.h"
|
||||
#include "rpg/cutscene/item/json/cutscenejsonfield.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/string.h"
|
||||
|
||||
#define CUTSCENE_BATTLE_FIGHTER_REF_MAX 16
|
||||
|
||||
void cutsceneBattleFighterHealStart(
|
||||
const cutsceneitem_t *item,
|
||||
cutsceneitemdata_t *data
|
||||
) {
|
||||
const cutscenebattlefighterheal_t *heal = &item->battleFighterHeal;
|
||||
assertTrue(
|
||||
heal->fighterIndex < BATTLE_FIGHTER_POS_COUNT,
|
||||
"fighterIndex sentinel was never resolved"
|
||||
);
|
||||
battlefighter_t *fighter = BATTLE.fighters[heal->fighterIndex];
|
||||
assertNotNull(fighter, "Fighter cannot be NULL");
|
||||
|
||||
battleFighterHeal(fighter, heal->amount);
|
||||
}
|
||||
|
||||
bool_t cutsceneBattleFighterHealUpdate(
|
||||
const cutsceneitem_t *item,
|
||||
cutsceneitemdata_t *data
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
errorret_t cutsceneBattleFighterHealLoad(
|
||||
yyjson_val *itemObj,
|
||||
cutsceneitem_t *item
|
||||
) {
|
||||
char_t fighterRef[CUTSCENE_BATTLE_FIGHTER_REF_MAX];
|
||||
if(!cutsceneJsonCopyString(
|
||||
itemObj, "fighter", NULL, fighterRef, CUTSCENE_BATTLE_FIGHTER_REF_MAX
|
||||
)) {
|
||||
errorThrow("Cutscene item (BATTLE_FIGHTER_HEAL): missing 'fighter'");
|
||||
}
|
||||
if(stringEquals(fighterRef, "target")) {
|
||||
item->battleFighterHeal.fighterIndex = BATTLE_FIGHTER_POS_TARGET;
|
||||
} else if(stringEquals(fighterRef, "user")) {
|
||||
item->battleFighterHeal.fighterIndex = BATTLE_FIGHTER_POS_USER;
|
||||
} else {
|
||||
errorThrow(
|
||||
"Cutscene item (BATTLE_FIGHTER_HEAL): 'fighter' must be "
|
||||
"'target' or 'user'"
|
||||
);
|
||||
}
|
||||
|
||||
const int32_t amount = cutsceneJsonGetInt(itemObj, "amount", -1);
|
||||
if(amount < 0 || amount > UINT16_MAX) {
|
||||
errorThrow(
|
||||
"Cutscene item (BATTLE_FIGHTER_HEAL): invalid/missing 'amount'"
|
||||
);
|
||||
}
|
||||
item->battleFighterHeal.amount = (uint16_t)amount;
|
||||
|
||||
errorOk();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "rpg/cutscene/item/cutsceneitembase.h"
|
||||
#include "rpg/battle/fighter/battlefighterpos.h"
|
||||
|
||||
typedef struct {
|
||||
// Index into BATTLE.fighters of the fighter to heal, or one of
|
||||
// BATTLE_FIGHTER_POS_TARGET/BATTLE_FIGHTER_POS_USER, resolved against
|
||||
// the currently-executing action by battleStateExecutingInit before
|
||||
// this item ever runs.
|
||||
battlefighterpos_t fighterIndex;
|
||||
uint16_t amount;
|
||||
} cutscenebattlefighterheal_t;
|
||||
|
||||
/**
|
||||
* Starts a BATTLE_FIGHTER_HEAL item, applying the configured heal to
|
||||
* BATTLE.fighters[fighterIndex] immediately.
|
||||
*
|
||||
* @param item The cutscene item.
|
||||
* @param data Runtime data storage.
|
||||
*/
|
||||
void cutsceneBattleFighterHealStart(
|
||||
const cutsceneitem_t *item,
|
||||
cutsceneitemdata_t *data
|
||||
);
|
||||
|
||||
/**
|
||||
* Updates a BATTLE_FIGHTER_HEAL item (always completes immediately).
|
||||
*
|
||||
* @param item The cutscene item.
|
||||
* @param data Runtime data storage.
|
||||
* @returns true always.
|
||||
*/
|
||||
bool_t cutsceneBattleFighterHealUpdate(
|
||||
const cutsceneitem_t *item,
|
||||
cutsceneitemdata_t *data
|
||||
);
|
||||
|
||||
/**
|
||||
* Parses a BATTLE_FIGHTER_HEAL cutscene item's JSON fields into item.
|
||||
*
|
||||
* @param itemObj The item's JSON object.
|
||||
* @param item Destination item, already zeroed by the caller.
|
||||
* @return Error code indicating success or failure of the parse.
|
||||
*/
|
||||
errorret_t cutsceneBattleFighterHealLoad(
|
||||
yyjson_val *itemObj,
|
||||
cutsceneitem_t *item
|
||||
);
|
||||
@@ -6,15 +6,44 @@
|
||||
*/
|
||||
|
||||
#include "rpg/cutscene/item/cutsceneitem.h"
|
||||
#include "rpg/battle/battle.h"
|
||||
#include "rpg/cutscene/cutscenesystem.h"
|
||||
#include "console/console.h"
|
||||
|
||||
void cutsceneBattlePostMoveStart(
|
||||
const cutsceneitem_t *item,
|
||||
cutsceneitemdata_t *data
|
||||
) {
|
||||
// TODO: check fighter health etc. here to short-circuit into a
|
||||
// win/loss (BATTLE_STATE_WON/LOST) once a side has been wiped out.
|
||||
consolePrint("BATTLE_POST_MOVE\n");
|
||||
|
||||
// Once a result has already been decided (e.g. the player fled), there
|
||||
// is nothing left to check.
|
||||
if(BATTLE.result != BATTLE_RESULT_NONE) return;
|
||||
|
||||
bool_t allyAlive = false;
|
||||
bool_t enemyAlive = false;
|
||||
for(uint8_t i = 0; i < BATTLE_FIGHTER_POS_COUNT; i++) {
|
||||
battlefighter_t *fighter = BATTLE.fighters[i];
|
||||
if(fighter == NULL) continue;
|
||||
if(!battleFighterIsAlive(fighter)) continue;
|
||||
|
||||
if(fighter->team == BATTLE_FIGHTER_TEAM_ALLY) allyAlive = true;
|
||||
else enemyAlive = true;
|
||||
}
|
||||
|
||||
if(allyAlive && enemyAlive) return;
|
||||
|
||||
BATTLE.result = allyAlive ? BATTLE_RESULT_WIN : BATTLE_RESULT_LOSS;
|
||||
|
||||
const cutsceneitem_t items[] = {
|
||||
{
|
||||
.type = CUTSCENE_ITEM_TYPE_BATTLE_SET_STATE,
|
||||
.battleSetState = {
|
||||
.state = allyAlive ? BATTLE_STATE_WON : BATTLE_STATE_LOST
|
||||
}
|
||||
}
|
||||
};
|
||||
cutsceneSystemInsertItemsNext(items, sizeof(items) / sizeof(cutsceneitem_t));
|
||||
}
|
||||
|
||||
bool_t cutsceneBattlePostMoveUpdate(
|
||||
|
||||
@@ -10,10 +10,11 @@
|
||||
|
||||
/**
|
||||
* Starts a BATTLE_POST_MOVE item. Runs after each queued move's cutscene
|
||||
* finishes - eventually this is where we'll check things like fighter
|
||||
* health to short-circuit into a win/loss, but for now it just prints to
|
||||
* the console. Not JSON-authorable -- constructed dynamically by
|
||||
* battleStateExecutingInit.
|
||||
* finishes: checks whether every ally or every enemy fighter has been
|
||||
* knocked out and, if so, sets BATTLE.result and splices in a
|
||||
* BATTLE_SET_STATE to BATTLE_STATE_WON/LOST. No-ops the health check if
|
||||
* BATTLE.result is already set (e.g. the player fled). Not
|
||||
* JSON-authorable -- constructed dynamically by battleStateExecutingInit.
|
||||
*
|
||||
* @param item The cutscene item.
|
||||
* @param data Runtime data storage.
|
||||
|
||||
@@ -270,6 +270,20 @@ cutsceneitemcallbacks_t CUTSCENE_ITEM_CALLBACKS[CUTSCENE_ITEM_TYPE_COUNT] = {
|
||||
.update = cutsceneBattlePostMoveUpdate
|
||||
},
|
||||
|
||||
[CUTSCENE_ITEM_TYPE_BATTLE_FIGHTER_DAMAGE] = {
|
||||
.init = cutsceneBattleFighterDamageStart,
|
||||
.update = cutsceneBattleFighterDamageUpdate,
|
||||
.jsonName = "BATTLE_FIGHTER_DAMAGE",
|
||||
.load = cutsceneBattleFighterDamageLoad
|
||||
},
|
||||
|
||||
[CUTSCENE_ITEM_TYPE_BATTLE_FIGHTER_HEAL] = {
|
||||
.init = cutsceneBattleFighterHealStart,
|
||||
.update = cutsceneBattleFighterHealUpdate,
|
||||
.jsonName = "BATTLE_FIGHTER_HEAL",
|
||||
.load = cutsceneBattleFighterHealLoad
|
||||
},
|
||||
|
||||
// Save
|
||||
[CUTSCENE_ITEM_TYPE_SAVE_DEVICE_CHECK] = {
|
||||
.init = cutsceneSaveDeviceCheckStart,
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
#include "battle/cutscenebattlesetstate.h"
|
||||
#include "battle/cutscenebattlewaitselection.h"
|
||||
#include "battle/cutscenebattlepostmove.h"
|
||||
#include "battle/cutscenebattlefighterdamage.h"
|
||||
#include "battle/cutscenebattlefighterheal.h"
|
||||
#include "save/cutscenesavedevicecheck.h"
|
||||
#include "save/cutscenesaveloadallslots.h"
|
||||
#include "audio/cutsceneaudioplay.h"
|
||||
@@ -118,6 +120,8 @@ struct cutsceneitem_s {
|
||||
cutscenemapareawait_t mapAreaWait;
|
||||
cutscenebattlestart_t battleStart;
|
||||
cutscenebattlesetstate_t battleSetState;
|
||||
cutscenebattlefighterdamage_t battleFighterDamage;
|
||||
cutscenebattlefighterheal_t battleFighterHeal;
|
||||
cutsceneemoji_t emoji;
|
||||
cutsceneshake_t shake;
|
||||
cutscenemodal_t modal;
|
||||
|
||||
@@ -64,6 +64,8 @@ typedef enum {
|
||||
CUTSCENE_ITEM_TYPE_BATTLE_SET_STATE,
|
||||
CUTSCENE_ITEM_TYPE_BATTLE_WAIT_SELECTION,
|
||||
CUTSCENE_ITEM_TYPE_BATTLE_POST_MOVE,
|
||||
CUTSCENE_ITEM_TYPE_BATTLE_FIGHTER_DAMAGE,
|
||||
CUTSCENE_ITEM_TYPE_BATTLE_FIGHTER_HEAL,
|
||||
|
||||
// Save
|
||||
CUTSCENE_ITEM_TYPE_SAVE_DEVICE_CHECK,
|
||||
|
||||
Reference in New Issue
Block a user