summaryrefslogtreecommitdiff
path: root/kon/konrmfield.h
blob: 17a44fd5b25a741fecd2c05ac4c6e02453f436ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/* 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