#include #include #include "engine.h" #include "objids.h" #include "inventory.h" #include "compiled_structures.h" #define BGWIDTH 1066 #define BGHEIGHT 800 extern const char _binary_sprite_managers_office_safe_raw_start[]; extern const char _binary_sprite_item_pager_raw_start[]; extern const char _binary_sprite_stickman_raw_start[]; extern const struct level_predef_data predef_basement, predef_lobby, predef_managers_office, predef_cloakroom, predef_hallway1, predef_hallway2, predef_hallway3, predef_stairway1, predef_hallwayb1, predef_hallwayb2, predef_hallwayb3; static void create_player(scene *me, int x, int y) { const int WIDTH=51, HEIGHT=111; scene_add_object(me, OBJID_PLAYER, x-WIDTH/2, y-HEIGHT, WIDTH, HEIGHT, _binary_sprite_stickman_raw_start); } static const struct level_predef_point *find_level_predef_point(const struct level_predef_data *predef, int id) { for(const struct level_predef_point *pt = predef->points; pt->x || pt->y; pt++) { if(pt->id == id) return pt; } return nullptr; } static void create_player_startpt(scene *me, int fromscene) { int x, y; assert(me->predef); const struct level_predef_point *pt = (fromscene < 0 ? nullptr : find_level_predef_point(me->predef, OBJID_PLAYER_START+fromscene)); if(!pt) pt = find_level_predef_point(me->predef, OBJID_PLAYER_START_DEFAULT); if(pt) { x = pt->x; y = pt->y; } else { x = BGWIDTH/2; y = BGHEIGHT/2; } create_player(me, x, y); } void scene_setup(scene *me, int scene, int fromscene) { switch(scene) { case SCENE_LOBBY: scene_load_predef(me, &predef_lobby); create_player_startpt(me, fromscene); if(fromscene == -1) { push_scene_textbox("Welcome\n\nto\n\ntestgame"); } break; case SCENE_MANAGERS_OFFICE: scene_load_predef(me, &predef_managers_office); create_player_startpt(me, fromscene); break; case SCENE_MANAGERS_OFFICE_SAFE: scene_add_object(me, OBJID_BACKGROUND, 248, 0, 787, BGHEIGHT, _binary_sprite_managers_office_safe_raw_start); scene_add_object(me, OBJID_CLOSE_MODAL, 0, 0, 248, 800, nullptr); scene_add_object(me, OBJID_CLOSE_MODAL, 1035, 0, 1280-1035, 800, nullptr); me->dim_background = true; me->use_standard_inventory = false; break; case SCENE_BASEMENT: scene_load_predef(me, &predef_basement); if(!savefile.got_pager_from_basement) { scene_add_object(me, OBJID_PAGER, 556, 520, 87, 87, _binary_sprite_item_pager_raw_start); } create_player_startpt(me, fromscene); break; case SCENE_CLOAKROOM: scene_load_predef(me, &predef_cloakroom); create_player_startpt(me, fromscene); break; case SCENE_HALLWAY1: scene_load_predef(me, &predef_hallway1); create_player_startpt(me, fromscene); break; case SCENE_HALLWAY2: scene_load_predef(me, &predef_hallway2); create_player_startpt(me, fromscene); break; case SCENE_HALLWAY3: scene_load_predef(me, &predef_hallway3); create_player_startpt(me, fromscene); break; case SCENE_STAIRWAY1: scene_load_predef(me, &predef_stairway1); create_player_startpt(me, fromscene); break; case SCENE_HALLWAY_B1: scene_load_predef(me, &predef_hallwayb1); create_player_startpt(me, fromscene); break; case SCENE_HALLWAY_B2: scene_load_predef(me, &predef_hallwayb2); create_player_startpt(me, fromscene); break; case SCENE_HALLWAY_B3: scene_load_predef(me, &predef_hallwayb3); create_player_startpt(me, fromscene); break; } } static void transition_scene_on_walk_finish(struct script *scr, int wakeupMode, int arg1, int arg2, int arg3, int arg4) { scr->id = 0; if(wakeupMode == SCRIPT_WAKEUP_OTHER_SCRIPT) { if(scr->vars[0] == SCENE_MANAGERS_OFFICE_SAFE) { push_scene(scr->vars[0]); } else { replace_scene(scr->vars[0]); } } else assert(wakeupMode == SCRIPT_WAKEUP_OTHER_SCRIPT_INTERRUPTED); } static void start_player_walk_to_point_then_transition_scene(int x, int y, int scene) { start_player_walk_to_point(x, y); 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; } static void do_popcorn_on_walk_finish(struct script *scr, int wakeupMode, int arg1, int arg2, int arg3, int arg4) { scr->id = 0; if(wakeupMode == SCRIPT_WAKEUP_OTHER_SCRIPT) { if(count_item_in_inventory(INVITEM_POPCORN) >= 3) { push_scene_textbox( "You already have\n" "enough popcorn." ); } else { if(add_to_inventory(INVITEM_POPCORN) < 0) push_scene_textbox("Inventory is full."); else push_scene_textbox("You got popcorn."); } } else assert(wakeupMode == SCRIPT_WAKEUP_OTHER_SCRIPT_INTERRUPTED); } static void get_pager_on_walk_finish(struct script *scr, int wakeupMode, int arg1, int arg2, int arg3, int arg4) { scr->id = 0; if(wakeupMode == SCRIPT_WAKEUP_OTHER_SCRIPT) { struct object *obj = find_object_by_id(OBJID_PAGER); if(obj) { if(add_to_inventory(INVITEM_PAGER) < 0) { push_scene_textbox("Inventory is full."); } else { obj->id = 0; savefile.got_pager_from_basement = true; push_scene_textbox( "You found your pager.\n" "Now you can get out of here." ); } } } else assert(wakeupMode == SCRIPT_WAKEUP_OTHER_SCRIPT_INTERRUPTED); } static void start_player_walk_to_point_then(int x, int y, script_wake_fn wake_fn) { start_player_walk_to_point(x, y); 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 = wake_fn; } static void do_leave_lobby_on_walk_finish(struct script *scr, int wakeupMode, int arg1, int arg2, int arg3, int arg4) { scr->id = 0; if(wakeupMode == SCRIPT_WAKEUP_OTHER_SCRIPT) { if(count_item_in_inventory(INVITEM_PAGER) == 0) { push_scene_textbox( "You can't leave without\n" "finding your pager." ); } else { push_scene_textbox( "You got killed in a mugging\n" "and we rewound time for you,\n" "as required by the plot to\n" "keep you inside the theatre." ); } } else assert(wakeupMode == SCRIPT_WAKEUP_OTHER_SCRIPT_INTERRUPTED); } void onclick(int curscene, struct object *obj) { if(obj->id == OBJID_CLOSE_MODAL) { pop_scene(); return; } if(obj->id >= OBJID_INVENTORY_SLOTS && obj->id < OBJID_INVENTORY_SLOTS + INVENTORY_SIZE) { standard_inventory_onclick(obj); return; } switch(curscene) { case SCENE_LOBBY: switch(obj->id) { case OBJID_DOOR_TO_MANAGERS_OFFICE_FROM_LOBBY: start_player_walk_to_point_then_transition_scene(256, 441, SCENE_MANAGERS_OFFICE); return; case OBJID_LEAVE_ROOM: start_player_walk_to_point_then(obj->x + obj->width/2, obj->y + obj->height, do_leave_lobby_on_walk_finish); return; case OBJID_LOBBY_TO_CLOAKROOM: start_player_walk_to_point_then_transition_scene(777, 441, SCENE_CLOAKROOM); return; } break; case SCENE_MANAGERS_OFFICE: switch(obj->id) { case OBJID_DOOR_TO_LOBBY_FROM_MANAGERS_OFFICE: start_player_walk_to_point_then_transition_scene(815, 713, SCENE_LOBBY); return; case OBJID_MANAGERS_OFFICE_SAFE: start_player_walk_to_point_then_transition_scene(895, 497, SCENE_MANAGERS_OFFICE_SAFE); return; case OBJID_MANAGERS_OFFICE_TRAPDOOR: start_player_walk_to_point_then_transition_scene(408, 559, SCENE_BASEMENT); return; case OBJID_MANAGERS_OFFICE_TO_HALLWAY: start_player_walk_to_point_then_transition_scene(665, 418, SCENE_HALLWAY1); return; } break; case SCENE_BASEMENT: switch(obj->id) { case OBJID_BASEMENT_LADDER: start_player_walk_to_point_then_transition_scene(438, 402, SCENE_MANAGERS_OFFICE); return; case OBJID_POPCORN_BARREL: start_player_walk_to_point_then(obj->x + obj->width/2, obj->y + obj->height, do_popcorn_on_walk_finish); return; case OBJID_PAGER: start_player_walk_to_point_then(obj->x + obj->width/2, obj->y + obj->height, get_pager_on_walk_finish); return; } break; case SCENE_CLOAKROOM: switch(obj->id) { case OBJID_LEAVE_ROOM: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_LOBBY); return; } break; case SCENE_HALLWAY1: switch(obj->id) { case OBJID_LEAVE_ROOM: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_MANAGERS_OFFICE); return; case OBJID_NEXT_ROOM: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_HALLWAY2); return; case OBJID_GO_LEFT: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_STAIRWAY1); return; } break; case SCENE_HALLWAY2: switch(obj->id) { case OBJID_LEAVE_ROOM: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_HALLWAY1); return; case OBJID_NEXT_ROOM: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_HALLWAY3); return; } break; case SCENE_HALLWAY3: switch(obj->id) { case OBJID_LEAVE_ROOM: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_HALLWAY2); return; } break; case SCENE_STAIRWAY1: switch(obj->id) { case OBJID_STAIRWAY1_TOP: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_HALLWAY_B2); return; case OBJID_STAIRWAY1_BOTTOM: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_HALLWAY1); return; } break; case SCENE_HALLWAY_B1: switch(obj->id) { case OBJID_GO_RIGHT: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_HALLWAY_B2); return; } break; case SCENE_HALLWAY_B2: switch(obj->id) { case OBJID_GO_LEFT: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_HALLWAY_B1); return; case OBJID_GO_RIGHT: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_HALLWAY_B3); return; case OBJID_LEAVE_ROOM: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_STAIRWAY1); return; } break; case SCENE_HALLWAY_B3: switch(obj->id) { case OBJID_GO_LEFT: start_player_walk_to_point_then_transition_scene(obj->x + obj->width/2, obj->y + obj->height, SCENE_HALLWAY_B2); return; } break; } }