From c821bab136a3fd46facf9a053359309ab2cc4d5c Mon Sep 17 00:00:00 2001 From: KonAki Date: Fri, 16 Oct 2026 07:06:19 +0800 Subject: add script commands to rmfield: transfer, locate, route, self switch --- kon/konrmfield.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 1 deletion(-) (limited to 'kon/konrmfield.c') 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) -- cgit