summaryrefslogtreecommitdiff
path: root/kon/konrmfield.c
diff options
context:
space:
mode:
authorKonAki <konaki@anokonaki.org>2026-10-16 07:06:19 +0800
committerKonAki <konaki@anokonaki.org>2026-10-16 07:06:19 +0800
commitc821bab136a3fd46facf9a053359309ab2cc4d5c (patch)
treeffe2e848085930d5c729365a3cd16eb07777a879 /kon/konrmfield.c
parent54372d111804916459418e3ff8fb6d9c9e036fb1 (diff)
add script commands to rmfield: transfer, locate, route, self switch
Diffstat (limited to 'kon/konrmfield.c')
-rw-r--r--kon/konrmfield.c181
1 files changed, 180 insertions, 1 deletions
diff --git a/kon/konrmfield.c b/kon/konrmfield.c
index f165df7..92401de 100644
--- a/kon/konrmfield.c
+++ b/kon/konrmfield.c
@@ -423,7 +423,7 @@ void kon_rmFieldRefresh(kon_rmField_t *field)
for (i = 0; i < field->map->eventCount && i + 1 < field->count; i++) {
const kon_rmEvent_t *event = &field->map->events[i];
kon_rmChar_t *c = &field->chars[i + 1];
- int page = kon_rmEventPage(event, field->map->id, field->state);
+ int page = c->erased ? -1 : kon_rmEventPage(event, field->map->id, field->state);
if (page == c->pageIndex) continue;
if (page < 0) clearPage(c);
@@ -445,6 +445,7 @@ int kon_rmFieldInit(kon_rmField_t *field, const kon_rmMap_t *map, const kon_rmTi
field->chars = chars;
field->count = map->eventCount + 1;
field->seed = 2463534242u;
+ field->waitIndex = -1;
memset(chars, 0, sizeof *chars * (size_t)field->count);
for (i = 0; i < field->count; i++) {
kon_rmChar_t *c = &chars[i];
@@ -665,6 +666,184 @@ int kon_rmFieldRouteBusy(const kon_rmField_t *field, int index)
return field->chars[index].routeForced;
}
+/*** commands from scripts ***/
+
+/* the numbers of a text the way mzscript writes them, apart by tabs. what is not a number is 0 */
+static int parseInts(const char *text, int *out, int max)
+{
+ int n = 0;
+
+ if (!text) return 0;
+ while (*text && n < max) {
+ long v = 0;
+ int neg = 0, any = 0;
+
+ if (*text == '-') {
+ neg = 1;
+ text++;
+ }
+ while (*text >= '0' && *text <= '9') {
+ if (v < 100000000) v = v * 10 + (*text - '0');
+ any = 1;
+ text++;
+ }
+ out[n++] = any ? (int)(neg ? -v : v) : 0;
+ while (*text && *text != '\t') text++;
+ if (*text == '\t') text++;
+ else break;
+ }
+ return n;
+}
+
+static int variable(const kon_rmField_t *field, int id)
+{
+ return field->state && field->state->variable ? field->state->variable(id, field->state->user) : 0;
+}
+
+/* -1 is the player, 0 the event the script belongs to, the others are events by id */
+static int charIndex(const kon_rmField_t *field, int id)
+{
+ int i;
+
+ if (id == -1) return KON_RM_PLAYER;
+ if (id == 0) id = field->thisEvent;
+ if (id <= 0) return -1;
+ i = kon_rmFieldFind(field, id);
+ return i >= 0 && field->chars[i].active ? i : -1;
+}
+
+static void locate(kon_rmField_t *field, int index, int x, int y, int dir)
+{
+ kon_rmChar_t *c = &field->chars[index];
+
+ if (!kon_rmValid(field->map, x, y)) return;
+ c->x = kon_rmRoundX(field->map, x);
+ c->y = kon_rmRoundY(field->map, y);
+ c->remain = 0;
+ c->jumpCount = 0;
+ c->stopCount = 0;
+ if (validDir(dir)) setDir(c, dir);
+}
+
+static void hostRoute(kon_rmField_t *field, int index, int flags, const char *text)
+{
+ kon_rmChar_t *c = &field->chars[index];
+ int size = 0;
+ const char *s = text;
+
+ /* the route is read command by command, the whole ones that fit */
+ while (s && *s) {
+ int head[2], numbers[8], n, i;
+ const char *next = s;
+
+ if (parseInts(s, head, 2) < 2 || head[1] < 0 || head[1] > 8 || size + 2 + head[1] > KON_RM_ROUTE_MAX) break;
+ for (i = 0; i < 2 && *next; i++) {
+ while (*next && *next != '\t') next++;
+ if (*next == '\t') next++;
+ }
+ n = parseInts(next, numbers, head[1]);
+ if (n < head[1]) break;
+ c->routeData[size++] = head[0];
+ c->routeData[size++] = head[1];
+ for (i = 0; i < head[1]; i++) c->routeData[size++] = numbers[i];
+ for (i = 0; i < head[1]; i++) {
+ while (*next && *next != '\t') next++;
+ if (*next == '\t') next++;
+ }
+ s = next;
+ }
+ kon_rmFieldRoute(field, index, c->routeData, size, flags & 1, (flags >> 1) & 1);
+ if ((flags & 4) && !(flags & 1)) field->waitIndex = index;
+}
+
+int kon_rmFieldHost(kon_rmField_t *field, int code, int b, int c, int d, const char *text)
+{
+ int n[8] = {0}, count, index;
+
+ if (!field || !field->chars) return -1;
+ count = parseInts(text, n, 8);
+ if (count == 0) {
+ n[0] = b;
+ n[1] = c;
+ n[2] = d;
+ }
+ switch (code) {
+ case 123:
+ if (field->selfSwitchSet && field->thisEvent > 0 && text && text[0] >= 'A' && text[0] <= 'D') {
+ field->selfSwitchSet(field->map->id, field->thisEvent, text[0], n[1] == 0, field->user);
+ kon_rmFieldRefresh(field);
+ }
+ return 0;
+ case 201: {
+ kon_rmTransfer_t *t = &field->transfer;
+
+ t->mapId = n[0] == 1 ? variable(field, n[1]) : n[1];
+ t->x = n[0] == 1 ? variable(field, n[2]) : n[2];
+ t->y = n[0] == 1 ? variable(field, n[3]) : n[3];
+ t->dir = validDir(n[4]) ? n[4] : 0;
+ t->fade = n[5] >= 0 && n[5] <= 2 ? n[5] : 0;
+ if (t->mapId <= 0) return 0;
+ field->transferPending = 1;
+ return 1;
+ }
+ case 203:
+ index = charIndex(field, n[0]);
+ if (index < 0) return 0;
+ if (n[1] == 2) {
+ int other = charIndex(field, n[2]);
+
+ if (other >= 0) {
+ int ox = field->chars[other].x, oy = field->chars[other].y;
+
+ locate(field, other, field->chars[index].x, field->chars[index].y, n[4]);
+ locate(field, index, ox, oy, n[4]);
+ }
+ } else if (n[1] == 1) {
+ locate(field, index, variable(field, n[2]), variable(field, n[3]), n[4]);
+ } else {
+ locate(field, index, n[2], n[3], n[4]);
+ }
+ return 0;
+ case 205:
+ index = charIndex(field, b);
+ if (index < 0) return 0;
+ hostRoute(field, index, c, text);
+ return field->waitIndex == index ? 1 : 0;
+ case 211:
+ field->chars[KON_RM_PLAYER].transparent = b == 0;
+ return 0;
+ case 214:
+ index = charIndex(field, 0);
+ if (index > 0) {
+ field->chars[index].erased = 1;
+ clearPage(&field->chars[index]);
+ }
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+int kon_rmFieldBusy(const kon_rmField_t *field)
+{
+ if (!field || !field->chars) return 0;
+ if (field->transferPending) return 1;
+ if (field->waitIndex >= 0 && field->waitIndex < field->count) {
+ const kon_rmChar_t *c = &field->chars[field->waitIndex];
+
+ return c->active && c->routeForced;
+ }
+ return 0;
+}
+
+int kon_rmFieldTransfer(kon_rmField_t *field, kon_rmTransfer_t *transfer)
+{
+ if (!field || !field->transferPending) return 0;
+ field->transferPending = 0;
+ if (transfer) *transfer = field->transfer;
+ return 1;
+}
+
/*** drawing ***/
int kon_rmCharX(const kon_rmChar_t *c)