/* SPDX-License-Identifier: MIT */ /* * konrmfield.h * * Copyright (c) 2026 KonAki * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef KONRMFIELD_H #define KONRMFIELD_H #include "konrmmap.h" #ifdef __cplusplus extern "C" { #endif /*** definition ***/ /* the player and the events of one RPG Maker map, walking around on it by RPG Maker's rules: a step at a time at the speed of the character, events that wander or follow a route, what blocks what, and what starts an event. nothing is drawn and no script runs here, the game asks who wants to start and runs the page's script itself. a character is in chars[0] for the player, then one for each event of the map in the order of the map's events, so chars[i + 1] is events[i]. you give kon_rmFieldInit the array, it has to have room for eventCount + 1 */ #define KON_RM_PLAYER 0 #define KON_RM_ROUTE_MAX 256 /* the numbers a route given by a script can have, a longer one is cut after its last whole command */ typedef struct kon_rmChar { int active; /* the player always, an event when one of its pages is on */ int x, y, dir; /* the tile it is on, or is walking to, and where it looks (2, 4, 6, 8) */ int moveDx, moveDy, remain; /* a step still to do: its direction, and what is left of it in 256ths of a tile */ int jumpCount, jumpPeak, jumpDx, jumpDy; int moveSpeed, moveFrequency, dashing; int priority, trigger, moveType; int through, dirFix, walkAnime, stepAnime, transparent, opacity; int pageIndex, eventId, originalDir; const kon_rmPage_t *page; int stopCount, locked, preLockDir, starting; int steps; /* how many it has taken, for the walking animation */ int success; /* did the last step work */ const int32_t *route; /* what it follows: a page's route, or one it was told to */ int routeSize, routeIndex, routeWait, routeRepeat, routeSkippable, routeForced; int erased; /* taken off the map by a script until the map is entered again */ int32_t routeData[KON_RM_ROUTE_MAX]; /* where a route from a script is kept */ } kon_rmChar_t; /* where a script sends the player: map, tile, the way to look (2, 4, 6, 8, or 0 to keep looking the same way) and the fade (0 black, 1 white, 2 none) */ typedef struct kon_rmTransfer { int mapId, x, y, dir, fade; } kon_rmTransfer_t; typedef struct kon_rmField { const kon_rmMap_t *map; const kon_rmTileset_t *tileset; const kon_rmState_t *state; /* what the pages need to know, see konrmmap.h */ kon_rmChar_t *chars; int count; uint32_t seed; int busy; /* set it while a script that stops the player is running */ int steps; /* the steps of the player so far, for the game to use as it likes */ int thisEvent; /* the id of the event whose script is running, for the commands that mean "this event". set it before you run one */ int waitIndex; /* the character a script waits for, -1 for none */ int transferPending; int encounterCount; /* what is left until the next fight, in halves of a step */ int encounterHalf, encounterNone; /* set them to halve the steps that count, or to stop fights altogether */ kon_rmTransfer_t transfer; /* both can stay NULL. the first is how a route that turns a switch on or off reaches your game, the second says whether the script a page names has anything in it, an event with an empty one does not start */ void (*switchSet)(int id, int on, void *user); int (*hasScript)(const char *label, void *user); void (*selfSwitchSet)(int mapId, int eventId, char letter, int on, void *user); void *user; } kon_rmField_t; /* returns 0, or -1 when there is no room in chars or something is NULL. the events start on their first page that is on */ int kon_rmFieldInit(kon_rmField_t *field, const kon_rmMap_t *map, const kon_rmTileset_t *tileset, const kon_rmState_t *state, kon_rmChar_t *chars, int capacity); void kon_rmFieldSeed(kon_rmField_t *field, uint32_t seed); void kon_rmFieldPlace(kon_rmField_t *field, int x, int y, int dir); /* looks at the pages again, call it when a switch, variable, item or self switch has changed */ void kon_rmFieldRefresh(kon_rmField_t *field); /* one frame (a 60th of a second) for everybody */ void kon_rmFieldUpdate(kon_rmField_t *field); /*** the player ***/ /* tries a step. nothing happens while the player is still walking, while busy or in a forced route. it turns and returns 0 when something is in the way, and then an event in front that starts by touch does. dash only counts where the map allows it */ int kon_rmFieldPlayerStep(kon_rmField_t *field, int dir, int dash); /* the action button: an event on the player's tile or in front of it, or behind a counter. returns 1 when one starts */ int kon_rmFieldAction(kon_rmField_t *field); /*** fights ***/ /* the random fights of the map: every step of the player counts down, a bush counts twice, and when it runs out a troop is picked from the map's list by weight, only the ones whose regions include the one the player stands in. returns the troop id once, or 0 for no fight. call it when no script is running. nothing starts while the player is walking a forced route */ int kon_rmFieldEncounter(kon_rmField_t *field); /*** events that start ***/ /* the next event that wants its script to run, lowest first: the touched or talked to, and the autorun ones. call it when no script is running. returns 1 and fills eventId and pageIndex (the script is the page's script label), or 0 for none. events that started by touch or action look at the player until kon_rmFieldUnlock. parallel pages (trigger 4) never come out of here, they are for the game to run on the side */ int kon_rmFieldNextStart(kon_rmField_t *field, int *eventId, int *pageIndex); /* index into chars of the event with that id, or -1 */ int kon_rmFieldFind(const kon_rmField_t *field, int eventId); /* lets an event go on walking and turn back the way it was looking. for the ones that started by touch or action */ void kon_rmFieldUnlock(kon_rmField_t *field, int index); /*** moving by command ***/ /* makes a character follow a route (the same shape as a page's: code, count, count numbers). the page's own route waits until it is done. kon_rmFieldRouteBusy says 1 until the route has run to its end, a repeating one never ends */ void kon_rmFieldRoute(kon_rmField_t *field, int index, const int32_t *route, int size, int repeat, int skippable); int kon_rmFieldRouteBusy(const kon_rmField_t *field, int index); /*** commands from scripts ***/ /* the RPG Maker commands that are about the map, the way mzscript writes them: 201 move the player to another map, 203 put a character somewhere, 205 give a character a route, 211 the player's transparency, 214 take this event off the map and 123 a self switch. returns -1 when the code is not one of those, 0 when it is done, 1 when the script is meant to wait. that wait is over when kon_rmFieldBusy says 0, so the host function returns 1 and you call kon_scriptResume then. a transfer is not done here: you take it with kon_rmFieldTransfer, load the map and start another field. */ int kon_rmFieldHost(kon_rmField_t *field, int code, int b, int c, int d, const char *text); int kon_rmFieldBusy(const kon_rmField_t *field); /* 1 and the transfer when a script asked for one, once */ int kon_rmFieldTransfer(kon_rmField_t *field, kon_rmTransfer_t *transfer); /*** drawing ***/ /* where it is in 256ths of a tile, in the middle of a step too. a map that loops can give a bit past its edge, the picture wraps it. the jump height is in pixels, for what is drawn over the ground */ int kon_rmCharX(const kon_rmChar_t *c); int kon_rmCharY(const kon_rmChar_t *c); int kon_rmCharJump(const kon_rmChar_t *c); int kon_rmCharMoving(const kon_rmChar_t *c); #ifdef __cplusplus } #endif #endif