Player walks to the manager's office door before entering it

master
immibis 2025-02-18 16:26:16 +01:00
parent 04a3a748ce
commit 491a5b3331
3 changed files with 63 additions and 25 deletions

View File

@ -44,6 +44,7 @@ struct object *find_object_by_id(int id);
struct script *scene_add_script(int id, bool interrupt_existing);
struct script *scene_get_script(int id);
bool deliver_script_wakeup(int wakeupMode, int wakeupArg1, int wakeupType, int arg1, int arg2, int arg3, int arg4); // deliver to scripts with given wakeupMode and wakeupArg1. Returns true if scene changed.
void start_player_walk_to_point(int x, int y); // x and y are not corrected to lie within navmesh
// game-specific constants
#define SCENE_LOBBY 1

View File

@ -1,3 +1,5 @@
#include <assert.h>
#include <stdio.h>
#include "engine.h"
#define BGWIDTH 1280
@ -15,6 +17,7 @@ extern struct navmesh navmesh_lobby;
#define OBJID_DOOR_TO_LOBBY_FROM_MANAGERS_OFFICE 3
// #define OBJID_PLAYER 4
// #define SCRIPTID_PLAYER_WALK 5
#define OBJID_PLAYER_WALK_TO_DOOR_SCRIPT 6
void scene_setup(int scene) {
switch(scene) {
@ -32,12 +35,29 @@ void scene_setup(int scene) {
}
}
static void transition_scene_on_walk_finish(struct script *scr, int wakeupMode, int arg1, int arg2, int arg3, int arg4) {
scr->id = 0;
printf("walk finish transition %d %d\n", wakeupMode, scr->vars[0]);
if(wakeupMode == SCRIPT_WAKEUP_OTHER_SCRIPT)
transition_scene(scr->vars[0]);
else
assert(wakeupMode == SCRIPT_WAKEUP_OTHER_SCRIPT_INTERRUPTED);
}
void onclick(int curscene, int objid) {
switch(curscene) {
case SCENE_LOBBY:
switch(objid) {
case OBJID_DOOR_TO_MANAGERS_OFFICE_FROM_LOBBY:
transition_scene(SCENE_MANAGERS_OFFICE);
{
start_player_walk_to_point(312, 441);
struct script *scr = scene_add_script(OBJID_PLAYER_WALK_TO_DOOR_SCRIPT, true);
scr->wakeupMode = SCRIPT_WAKEUP_OTHER_SCRIPT;
scr->wakeupArg1 = OBJID_PLAYER_WALK_SCRIPT;
scr->wakeupFn = transition_scene_on_walk_finish;
scr->vars[0] = SCENE_MANAGERS_OFFICE;
}
return;
}
break;

View File

@ -202,12 +202,13 @@ struct object *find_object_by_id(int id) {
return nullptr;
}
struct script *scene_add_script(int id, bool interrupt_existing) {
if(interrupt_existing && id != OBJID_PLAYER_WALK_SCRIPT) error(1, 0, "scene_add_script: interrupt not implemented");
for(int i = 0; i < MAX_GAME_SCRIPTS; i++) {
if(scripts[i].id == id && interrupt_existing) {
// interrupt existing script?
// player walk script is safe to trivially cancel, at least
scripts[i].id = 0;
if(deliver_script_wakeup(SCRIPT_WAKEUP_OTHER_SCRIPT, id, SCRIPT_WAKEUP_OTHER_SCRIPT_INTERRUPTED, 0, 0, 0, 0))
return NULL; // scene changed. this probably crashes the caller. should be tested or we need a better way to cancel all running operations on scene change.
}
if(scripts[i].id == 0) {
memset(&scripts[i], 0, sizeof(scripts[i]));
@ -294,24 +295,18 @@ static int find_navmesh_tri(int x, int y, int tolerance) {
}
static void update_player_walk_script_on_frame(struct script *scr, int wakeupMode, int, int, int, int);
void handle_tap(int x, int y) {
uint32_t gencount = scene_generation_count;
for(int i = 0; i < MAX_GAME_OBJECTS; i++) {
if(objects[i].id && (unsigned int)(x - objects[i].x) < objects[i].width && (unsigned int)(y - objects[i].y) < objects[i].height) {
if(gencount != scene_generation_count) return; // early exit if scene changed
onclick(curscene, objects[i].id);
}
}
struct script_player_walk *player_walk_script = (struct script_player_walk *)scene_add_script(OBJID_PLAYER_WALK_SCRIPT, true);
static uint32_t player_walk_generation = 0;
void start_player_walk_to_point(int targetX, int targetY) {
player_walk_generation++;
struct object *player = find_object_by_id(OBJID_PLAYER);
if(player) {
int destTri = find_navmesh_tri(x, y, 50);
if(destTri != -1) {
int targetX = x, targetY = y;
closest_point_inside_tri(&targetX, &targetY, &cur_navmesh->tris[destTri]);
if(!player) error(1, 0, "start_player_walk_to_point: no player object");
int destTri = find_navmesh_tri(targetX, targetY, 999999);
if(destTri == -1) error(1, 0, "start_player_walk_to_point: no navmesh");
struct script_player_walk *player_walk_script = (struct script_player_walk *)scene_add_script(OBJID_PLAYER_WALK_SCRIPT, true);
player_walk_script->targetX = targetX;
player_walk_script->targetY = targetY;
player_walk_script->targetNavmeshTri = destTri;
@ -321,11 +316,28 @@ void handle_tap(int x, int y) {
int sourceTri = find_navmesh_tri(player->x+player->width*2, player->y+player->height, 1000000);
player_walk_script->currentNavmeshTri = sourceTri;
printf("set course from triangle %d to %d\n", sourceTri, destTri);
} else {
player_walk_script->id = 0;
}
void handle_tap(int x, int y) {
uint32_t gencount = scene_generation_count;
uint32_t walkgen = player_walk_generation;
for(int i = 0; i < MAX_GAME_OBJECTS; i++) {
if(objects[i].id && (unsigned int)(x - objects[i].x) < objects[i].width && (unsigned int)(y - objects[i].y) < objects[i].height) {
onclick(curscene, objects[i].id);
if(gencount != scene_generation_count) return; // early exit if scene changed, and don't walk the player either
}
}
if(walkgen == player_walk_generation) { // no other handler moved the player
struct object *player = find_object_by_id(OBJID_PLAYER);
if(player) {
int destTri = find_navmesh_tri(x, y, 50);
if(destTri != -1) {
int targetX = x, targetY = y;
closest_point_inside_tri(&targetX, &targetY, &cur_navmesh->tris[destTri]);
start_player_walk_to_point(targetX, targetY);
}
}
} else {
player_walk_script->id = 0;
}
}
@ -336,11 +348,13 @@ static int move_towards(int cur, int target, int maxrate) {
}
static void update_player_walk_script_on_frame(struct script *scr, int wakeupMode, int, int, int, int) {
int script_id = scr->id;
struct script_player_walk *player_walk_script = (struct script_player_walk *)scr;
if(!player_walk_script) return;
struct object *player = find_object_by_id(OBJID_PLAYER);
if(!player) {
player_walk_script->id = 0;
deliver_script_wakeup(SCRIPT_WAKEUP_OTHER_SCRIPT, script_id, SCRIPT_WAKEUP_OTHER_SCRIPT_INTERRUPTED, 0, 0, 0, 0);
return;
}
@ -349,6 +363,7 @@ static void update_player_walk_script_on_frame(struct script *scr, int wakeupMod
player->x = player_walk_script->targetX - player->width/2;
player->y = player_walk_script->targetY - player->height;
player_walk_script->id = 0;
deliver_script_wakeup(SCRIPT_WAKEUP_OTHER_SCRIPT, script_id, SCRIPT_WAKEUP_OTHER_SCRIPT, 0, 0, 0, 0);
need_rerender = true;
} else {
int x = player->x+player->width/2;
@ -372,6 +387,7 @@ static void update_player_walk_script_on_frame(struct script *scr, int wakeupMod
}
// shouldn't happen
player_walk_script->id = 0;
deliver_script_wakeup(SCRIPT_WAKEUP_OTHER_SCRIPT, script_id, SCRIPT_WAKEUP_OTHER_SCRIPT_INTERRUPTED, 0, 0, 0, 0);
return;
center_found:;
}
@ -379,6 +395,7 @@ static void update_player_walk_script_on_frame(struct script *scr, int wakeupMod
printf("in triangle %d, next triangle %d\n", nmtri, nextTri);
if(x == player_walk_script->targetX && y == player_walk_script->targetY) {
player_walk_script->id = 0;
deliver_script_wakeup(SCRIPT_WAKEUP_OTHER_SCRIPT, script_id, SCRIPT_WAKEUP_OTHER_SCRIPT, 0, 0, 0, 0);
} else {
player_walk_script->currentNavmeshTri = nextTri; // even if -1
}