From 4ee6781b07a564c6f0a1e726674dfc2ef1a2aeff Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Fri, 4 Oct 2024 21:58:23 +0100 Subject: [PATCH] photo_mode: add photo mode UI Adds a UI for photo mode, with customizable strings where applicable. --- data/tr1/ship/cfg/TR1X_gameflow.json5 | 13 ++ data/tr1/ship/cfg/TR1X_gameflow_demo_pc.json5 | 13 ++ data/tr1/ship/cfg/TR1X_gameflow_ub.json5 | 13 ++ src/tr1/game/game_string.def | 13 ++ src/tr1/game/overlay.c | 3 +- src/tr1/game/phase/phase_photo_mode.c | 27 +++ src/tr1/game/ui/widgets/photo_mode.c | 210 ++++++++++++++++++ src/tr1/game/ui/widgets/photo_mode.h | 5 + src/tr1/meson.build | 1 + 9 files changed, 297 insertions(+), 1 deletion(-) create mode 100644 src/tr1/game/ui/widgets/photo_mode.c create mode 100644 src/tr1/game/ui/widgets/photo_mode.h diff --git a/data/tr1/ship/cfg/TR1X_gameflow.json5 b/data/tr1/ship/cfg/TR1X_gameflow.json5 index e4a40615c..fee45efca 100644 --- a/data/tr1/ship/cfg/TR1X_gameflow.json5 +++ b/data/tr1/ship/cfg/TR1X_gameflow.json5 @@ -697,8 +697,10 @@ "KEYMAP_WALK": "Walk", "MISC_DEMO_MODE": "Demo Mode", "MISC_EMPTY_SLOT_FMT": "- EMPTY SLOT %d -", + "MISC_EXIT": "Exit", "MISC_OFF": "Off", "MISC_ON": "On", + "MISC_TOGGLE_HELP": "Toggle help", "OSD_AMBIGUOUS_INPUT_2": "Ambiguous input: %s and %s", "OSD_AMBIGUOUS_INPUT_3": "Ambiguous input: %s, %s, ...", "OSD_COMMAND_BAD_INVOCATION": "Invalid invocation: %s", @@ -743,6 +745,7 @@ "OSD_OBJECT_NOT_FOUND": "Object not found", "OSD_PERSPECTIVE_FILTER_OFF": "Perspective filter disabled", "OSD_PERSPECTIVE_FILTER_ON": "Perspective filter enabled", + "OSD_PHOTO_MODE_LAUNCHED": "Entering photo mode, press %s for help", "OSD_PLAY_LEVEL": "Loading %s", "OSD_POS_GET": "Room: %d\nPosition: %.3f, %.3f, %.3f\nRotation: %.3f,%.3f,%.3f", "OSD_POS_SET_ITEM": "Teleported to object: %s", @@ -786,6 +789,16 @@ "PAUSE_PAUSED": "Paused", "PAUSE_QUIT": "Quit", "PAUSE_YES": "Yes", + "PHOTO_MODE_FOV_PROMPT": "Adjust FOV", + "PHOTO_MODE_FOV_ROLE": "Draw <+Walk>", + "PHOTO_MODE_MOVE_PROMPT": "Move camera", + "PHOTO_MODE_RESET_PROMPT": "Reset camera", + "PHOTO_MODE_ROLL_PROMPT": "Roll camera", + "PHOTO_MODE_ROLL_ROLE": "Sidestep L/R", + "PHOTO_MODE_ROTATE90_PROMPT": "Rotate 90 degrees", + "PHOTO_MODE_ROTATE_PROMPT": "Rotate camera", + "PHOTO_MODE_SNAP_PROMPT": "Take picture", + "PHOTO_MODE_TITLE": "Photo Mode", "SOUND_SET_VOLUMES": "Set Volumes", "STATS_BONUS_STATISTICS": "Bonus Statistics", "STATS_DEATHS_FMT": "DEATHS %d", diff --git a/data/tr1/ship/cfg/TR1X_gameflow_demo_pc.json5 b/data/tr1/ship/cfg/TR1X_gameflow_demo_pc.json5 index 8f41377f8..ceb4d584c 100644 --- a/data/tr1/ship/cfg/TR1X_gameflow_demo_pc.json5 +++ b/data/tr1/ship/cfg/TR1X_gameflow_demo_pc.json5 @@ -190,8 +190,10 @@ "KEYMAP_WALK": "Walk", "MISC_DEMO_MODE": "Demo Mode", "MISC_EMPTY_SLOT_FMT": "- EMPTY SLOT %d -", + "MISC_EXIT": "Exit", "MISC_OFF": "Off", "MISC_ON": "On", + "MISC_TOGGLE_HELP": "Toggle help", "OSD_AMBIGUOUS_INPUT_2": "Ambiguous input: %s and %s", "OSD_AMBIGUOUS_INPUT_3": "Ambiguous input: %s, %s, ...", "OSD_COMMAND_BAD_INVOCATION": "Invalid invocation: %s", @@ -236,6 +238,7 @@ "OSD_OBJECT_NOT_FOUND": "Object not found", "OSD_PERSPECTIVE_FILTER_OFF": "Perspective filter disabled", "OSD_PERSPECTIVE_FILTER_ON": "Perspective filter enabled", + "OSD_PHOTO_MODE_LAUNCHED": "Entering photo mode, press %s for help", "OSD_PLAY_LEVEL": "Loading %s", "OSD_POS_GET": "Room: %d\nPosition: %.3f, %.3f, %.3f\nRotation: %.3f,%.3f,%.3f", "OSD_POS_SET_ITEM": "Teleported to object: %s", @@ -279,6 +282,16 @@ "PAUSE_PAUSED": "Paused", "PAUSE_QUIT": "Quit", "PAUSE_YES": "Yes", + "PHOTO_MODE_FOV_PROMPT": "Adjust FOV", + "PHOTO_MODE_FOV_ROLE": "Draw <+Walk>", + "PHOTO_MODE_MOVE_PROMPT": "Move camera", + "PHOTO_MODE_RESET_PROMPT": "Reset camera", + "PHOTO_MODE_ROLL_PROMPT": "Roll camera", + "PHOTO_MODE_ROLL_ROLE": "Sidestep L/R", + "PHOTO_MODE_ROTATE90_PROMPT": "Rotate 90 degrees", + "PHOTO_MODE_ROTATE_PROMPT": "Rotate camera", + "PHOTO_MODE_SNAP_PROMPT": "Take picture", + "PHOTO_MODE_TITLE": "Photo Mode", "SOUND_SET_VOLUMES": "Set Volumes", "STATS_BONUS_STATISTICS": "Bonus Statistics", "STATS_DEATHS_FMT": "DEATHS %d", diff --git a/data/tr1/ship/cfg/TR1X_gameflow_ub.json5 b/data/tr1/ship/cfg/TR1X_gameflow_ub.json5 index 991122d4f..1011ae01a 100644 --- a/data/tr1/ship/cfg/TR1X_gameflow_ub.json5 +++ b/data/tr1/ship/cfg/TR1X_gameflow_ub.json5 @@ -262,8 +262,10 @@ "KEYMAP_WALK": "Walk", "MISC_DEMO_MODE": "Demo Mode", "MISC_EMPTY_SLOT_FMT": "- EMPTY SLOT %d -", + "MISC_EXIT": "Exit", "MISC_OFF": "Off", "MISC_ON": "On", + "MISC_TOGGLE_HELP": "Toggle help", "OSD_AMBIGUOUS_INPUT_2": "Ambiguous input: %s and %s", "OSD_AMBIGUOUS_INPUT_3": "Ambiguous input: %s, %s, ...", "OSD_COMMAND_BAD_INVOCATION": "Invalid invocation: %s", @@ -308,6 +310,7 @@ "OSD_OBJECT_NOT_FOUND": "Object not found", "OSD_PERSPECTIVE_FILTER_OFF": "Perspective filter disabled", "OSD_PERSPECTIVE_FILTER_ON": "Perspective filter enabled", + "OSD_PHOTO_MODE_LAUNCHED": "Entering photo mode, press %s for help", "OSD_PLAY_LEVEL": "Loading %s", "OSD_POS_GET": "Room: %d\nPosition: %.3f, %.3f, %.3f\nRotation: %.3f,%.3f,%.3f", "OSD_POS_SET_ITEM": "Teleported to object: %s", @@ -351,6 +354,16 @@ "PAUSE_PAUSED": "Paused", "PAUSE_QUIT": "Quit", "PAUSE_YES": "Yes", + "PHOTO_MODE_FOV_PROMPT": "Adjust FOV", + "PHOTO_MODE_FOV_ROLE": "Draw <+Walk>", + "PHOTO_MODE_MOVE_PROMPT": "Move camera", + "PHOTO_MODE_RESET_PROMPT": "Reset camera", + "PHOTO_MODE_ROLL_PROMPT": "Roll camera", + "PHOTO_MODE_ROLL_ROLE": "Sidestep L/R", + "PHOTO_MODE_ROTATE90_PROMPT": "Rotate 90 degrees", + "PHOTO_MODE_ROTATE_PROMPT": "Rotate camera", + "PHOTO_MODE_SNAP_PROMPT": "Take picture", + "PHOTO_MODE_TITLE": "Photo Mode", "SOUND_SET_VOLUMES": "Set Volumes", "STATS_BONUS_STATISTICS": "Bonus Statistics", "STATS_DEATHS_FMT": "DEATHS %d", diff --git a/src/tr1/game/game_string.def b/src/tr1/game/game_string.def index 00e014610..b8daf0b78 100644 --- a/src/tr1/game/game_string.def +++ b/src/tr1/game/game_string.def @@ -153,6 +153,7 @@ GS_DEFINE(OSD_TEXTURE_FILTER_NN, "nearest-neighbor") GS_DEFINE(OSD_TEXTURE_FILTER_BILINEAR, "bilinear") GS_DEFINE(OSD_PERSPECTIVE_FILTER_ON, "Perspective filter enabled") GS_DEFINE(OSD_PERSPECTIVE_FILTER_OFF, "Perspective filter disabled") +GS_DEFINE(OSD_PHOTO_MODE_LAUNCHED, "Entering photo mode, press %s for help") GS_DEFINE(OSD_FPS_COUNTER_ON, "FPS counter enabled") GS_DEFINE(OSD_FPS_COUNTER_OFF, "FPS counter disabled") GS_DEFINE(OSD_UI_ON, "UI enabled") @@ -160,3 +161,15 @@ GS_DEFINE(OSD_UI_OFF, "UI disabled") GS_DEFINE(OSD_DOOR_OPEN, "Open Sesame!") GS_DEFINE(OSD_DOOR_CLOSE, "Close Sesame!") GS_DEFINE(OSD_DOOR_OPEN_FAIL, "No doors in Lara's proximity") +GS_DEFINE(MISC_TOGGLE_HELP, "Toggle help") +GS_DEFINE(MISC_EXIT, "Exit") +GS_DEFINE(PHOTO_MODE_TITLE, "Photo Mode") +GS_DEFINE(PHOTO_MODE_MOVE_PROMPT, "Move camera") +GS_DEFINE(PHOTO_MODE_ROTATE_PROMPT, "Rotate camera") +GS_DEFINE(PHOTO_MODE_ROLL_PROMPT, "Roll camera") +GS_DEFINE(PHOTO_MODE_ROTATE90_PROMPT, "Rotate 90 degrees") +GS_DEFINE(PHOTO_MODE_FOV_PROMPT, "Adjust FOV") +GS_DEFINE(PHOTO_MODE_RESET_PROMPT, "Reset camera") +GS_DEFINE(PHOTO_MODE_SNAP_PROMPT, "Take picture") +GS_DEFINE(PHOTO_MODE_ROLL_ROLE, "Sidestep L/R") +GS_DEFINE(PHOTO_MODE_FOV_ROLE, "Draw <+Walk>") diff --git a/src/tr1/game/overlay.c b/src/tr1/game/overlay.c index 70a0320b7..53914d6d2 100644 --- a/src/tr1/game/overlay.c +++ b/src/tr1/game/overlay.c @@ -741,7 +741,8 @@ void Overlay_DrawGameInfo(void) void Overlay_DrawFPSInfo(void) { - if (g_Config.rendering.enable_fps_counter && g_Config.ui.enable_ui) { + if (g_Config.rendering.enable_fps_counter && g_Config.ui.enable_ui + && Phase_Get() != PHASE_PHOTO_MODE) { const int32_t text_offset_x = 3; const int32_t text_height = 17; const int32_t text_inv_offset_y = 3; diff --git a/src/tr1/game/phase/phase_photo_mode.c b/src/tr1/game/phase/phase_photo_mode.c index 67695793b..4fc2df285 100644 --- a/src/tr1/game/phase/phase_photo_mode.c +++ b/src/tr1/game/phase/phase_photo_mode.c @@ -1,5 +1,6 @@ #include "game/phase/phase_photo_mode.h" +#include "config.h" #include "game/camera.h" #include "game/game.h" #include "game/input.h" @@ -8,9 +9,11 @@ #include "game/overlay.h" #include "game/shell.h" #include "game/sound.h" +#include "game/ui/widgets/photo_mode.h" #include "game/viewport.h" #include +#include #include @@ -23,10 +26,12 @@ typedef enum { PS_COOLDOWN, } PHOTO_STATUS; +static bool m_OldUIState; static int32_t m_OldFOV; static int32_t m_CurrentFOV; static PHOTO_STATUS m_Status = PS_NONE; +static UI_WIDGET *m_PhotoMode = NULL; static void M_Start(void *arg); static void M_End(void); @@ -38,12 +43,21 @@ static void M_Start(void *arg) { m_Status = PS_NONE; g_OldInputDB = g_Input; + m_OldUIState = g_Config.ui.enable_ui; m_OldFOV = Viewport_GetFOV(); m_CurrentFOV = m_OldFOV / PHD_DEGREE; Overlay_HideGameInfo(); Music_Pause(); Sound_PauseAll(); + + m_PhotoMode = UI_PhotoMode_Create(); + if (!g_Config.ui.enable_ui) { + Console_Log( + GS(OSD_PHOTO_MODE_LAUNCHED), + Input_GetKeyName( + CM_KEYBOARD, g_Config.input.layout, INPUT_ROLE_TOGGLE_UI)); + } } static void M_End(void) @@ -51,6 +65,14 @@ static void M_End(void) g_Input = g_OldInputDB; Viewport_SetFOV(m_OldFOV); + if (m_OldUIState != g_Config.ui.enable_ui) { + g_Config.ui.enable_ui ^= true; + Config_Write(); + } + + m_PhotoMode->free(m_PhotoMode); + m_PhotoMode = NULL; + Music_Unpause(); Sound_UnpauseAll(); } @@ -73,6 +95,7 @@ static PHASE_CONTROL M_Control(int32_t nframes) } else if (g_InputDB.action) { m_Status = PS_ACTIVE; } else { + m_PhotoMode->control(m_PhotoMode); M_AdjustFOV(); Camera_Update(); } @@ -111,6 +134,10 @@ static void M_Draw(void) Interpolation_Disable(); Game_DrawScene(false); Interpolation_Enable(); + + if (m_Status == PS_NONE) { + m_PhotoMode->draw(m_PhotoMode); + } } PHASER g_PhotoModePhaser = { diff --git a/src/tr1/game/ui/widgets/photo_mode.c b/src/tr1/game/ui/widgets/photo_mode.c new file mode 100644 index 000000000..4c01fe47f --- /dev/null +++ b/src/tr1/game/ui/widgets/photo_mode.c @@ -0,0 +1,210 @@ +#include "game/ui/widgets/photo_mode.h" + +#include "game/input.h" +#include "game/text.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define TITLE_MARGIN 5 +#define WINDOW_MARGIN 10 +#define DIALOG_PADDING 5 + +typedef struct { + UI_WIDGET_VTABLE vtable; + UI_WIDGET *window; + UI_WIDGET *title; + UI_WIDGET *outer_stack; + UI_WIDGET *inner_stack; + UI_WIDGET *left_stack; + UI_WIDGET *right_stack; + UI_WIDGET *spacer; + bool shown; + int32_t label_count; + UI_WIDGET **left_labels; + UI_WIDGET **right_labels; +} UI_PHOTO_MODE; + +static int32_t M_GetWidth(const UI_PHOTO_MODE *self); +static int32_t M_GetHeight(const UI_PHOTO_MODE *self); +static void M_SetPosition(UI_PHOTO_MODE *self, int32_t x, int32_t y); +static void M_Control(UI_PHOTO_MODE *self); +static void M_Draw(UI_PHOTO_MODE *self); +static void M_Free(UI_PHOTO_MODE *self); + +static int32_t M_GetWidth(const UI_PHOTO_MODE *const self) +{ + return UI_GetCanvasWidth() - 2 * WINDOW_MARGIN; +} + +static int32_t M_GetHeight(const UI_PHOTO_MODE *const self) +{ + return UI_GetCanvasHeight() - 2 * WINDOW_MARGIN; +} + +static void M_SetPosition(UI_PHOTO_MODE *const self, int32_t x, int32_t y) +{ + return self->window->set_position(self->window, x, y); +} + +static void M_Control(UI_PHOTO_MODE *const self) +{ + if (self->window->control != NULL) { + self->window->control(self->window); + } + + self->shown = g_Config.ui.enable_ui; +} + +static void M_Draw(UI_PHOTO_MODE *const self) +{ + if (self->shown && self->window->draw != NULL) { + self->window->draw(self->window); + } +} + +static void M_Free(UI_PHOTO_MODE *const self) +{ + for (int32_t i = 0; i < self->label_count; i++) { + self->left_labels[i]->free(self->left_labels[i]); + self->right_labels[i]->free(self->right_labels[i]); + } + self->spacer->free(self->spacer); + self->spacer->free(self->title); + self->spacer->free(self->outer_stack); + self->spacer->free(self->inner_stack); + self->spacer->free(self->left_stack); + self->spacer->free(self->right_stack); + self->spacer->free(self->window); + Memory_Free(self->left_labels); + Memory_Free(self->right_labels); + Memory_Free(self); +} + +UI_WIDGET *UI_PhotoMode_Create(void) +{ + UI_PHOTO_MODE *const self = Memory_Alloc(sizeof(UI_PHOTO_MODE)); + self->vtable = (UI_WIDGET_VTABLE) { + .control = (UI_WIDGET_CONTROL)M_Control, + .draw = (UI_WIDGET_DRAW)M_Draw, + .get_width = (UI_WIDGET_GET_WIDTH)M_GetWidth, + .get_height = (UI_WIDGET_GET_HEIGHT)M_GetHeight, + .set_position = (UI_WIDGET_SET_POSITION)M_SetPosition, + .free = (UI_WIDGET_FREE)M_Free, + }; + + self->outer_stack = UI_Stack_Create( + UI_STACK_LAYOUT_VERTICAL, UI_STACK_AUTO_SIZE, UI_STACK_AUTO_SIZE); + self->inner_stack = UI_Stack_Create( + UI_STACK_LAYOUT_HORIZONTAL, UI_STACK_AUTO_SIZE, UI_STACK_AUTO_SIZE); + self->left_stack = UI_Stack_Create( + UI_STACK_LAYOUT_VERTICAL, UI_STACK_AUTO_SIZE, UI_STACK_AUTO_SIZE); + self->right_stack = UI_Stack_Create( + UI_STACK_LAYOUT_VERTICAL, UI_STACK_AUTO_SIZE, UI_STACK_AUTO_SIZE); + + const char *const title = GS(PHOTO_MODE_TITLE); + self->title = UI_Label_Create(title, UI_LABEL_AUTO_SIZE, TEXT_HEIGHT_FIXED); + UI_Stack_AddChild(self->outer_stack, self->title); + + self->spacer = UI_Spacer_Create(TITLE_MARGIN, TITLE_MARGIN); + UI_Stack_AddChild(self->outer_stack, self->spacer); + UI_Stack_AddChild(self->outer_stack, self->inner_stack); + UI_Stack_AddChild(self->inner_stack, self->left_stack); + UI_Stack_AddChild(self->inner_stack, self->right_stack); + + char move_role[50]; + sprintf( + move_role, "%s%s%s%s%s%s: ", + Input_GetKeyName( + CM_KEYBOARD, g_Config.input.layout, INPUT_ROLE_CAMERA_UP), + Input_GetKeyName( + CM_KEYBOARD, g_Config.input.layout, INPUT_ROLE_CAMERA_DOWN), + Input_GetKeyName( + CM_KEYBOARD, g_Config.input.layout, INPUT_ROLE_CAMERA_FORWARD), + Input_GetKeyName( + CM_KEYBOARD, g_Config.input.layout, INPUT_ROLE_CAMERA_BACK), + Input_GetKeyName( + CM_KEYBOARD, g_Config.input.layout, INPUT_ROLE_CAMERA_LEFT), + Input_GetKeyName( + CM_KEYBOARD, g_Config.input.layout, INPUT_ROLE_CAMERA_RIGHT)); + + const char *const rot_role = "\200 \203 \202 \201 : "; + + char z_roll_role[100]; + sprintf(z_roll_role, "%s: ", GS(PHOTO_MODE_ROLL_ROLE)); + + char roll_role[100]; + sprintf(roll_role, "%s: ", GS(KEYMAP_ROLL)); + + char fov_role[100]; + sprintf(fov_role, "%s: ", GS(PHOTO_MODE_FOV_ROLE)); + + char reset_role[100]; + sprintf(reset_role, "%s: ", GS(KEYMAP_LOOK)); + + char help_role[20]; + sprintf( + help_role, "%s: ", + Input_GetKeyName( + CM_KEYBOARD, g_Config.input.layout, INPUT_ROLE_TOGGLE_UI)); + + char action_role[100]; + sprintf(action_role, "%s: ", GS(KEYMAP_ACTION)); + + char exit_role[100]; + sprintf( + exit_role, "%s/%s: ", + Input_GetKeyName( + CM_KEYBOARD, g_Config.input.layout, INPUT_ROLE_TOGGLE_PHOTO_MODE), + Input_GetKeyName( + CM_KEYBOARD, g_Config.input.layout, INPUT_ROLE_OPTION)); + + const char *const inputs[] = { + move_role, rot_role, z_roll_role, roll_role, fov_role, + reset_role, help_role, action_role, exit_role, NULL, + }; + + const char *const roles[] = { + GS(PHOTO_MODE_MOVE_PROMPT), + GS(PHOTO_MODE_ROTATE_PROMPT), + GS(PHOTO_MODE_ROLL_PROMPT), + GS(PHOTO_MODE_ROTATE90_PROMPT), + GS(PHOTO_MODE_FOV_PROMPT), + GS(PHOTO_MODE_RESET_PROMPT), + GS(MISC_TOGGLE_HELP), + GS(PHOTO_MODE_SNAP_PROMPT), + GS(MISC_EXIT), + NULL, + }; + + self->shown = true; + self->label_count = 0; + while (inputs[self->label_count] != NULL) { + self->label_count++; + } + + self->left_labels = Memory_Alloc(sizeof(UI_WIDGET *) * self->label_count); + self->right_labels = Memory_Alloc(sizeof(UI_WIDGET *) * self->label_count); + for (int32_t i = 0; i < self->label_count; i++) { + self->left_labels[i] = + UI_Label_Create(inputs[i], UI_LABEL_AUTO_SIZE, TEXT_HEIGHT_FIXED); + UI_Stack_AddChild(self->left_stack, self->left_labels[i]); + self->right_labels[i] = + UI_Label_Create(roles[i], UI_LABEL_AUTO_SIZE, TEXT_HEIGHT_FIXED); + UI_Stack_AddChild(self->right_stack, self->right_labels[i]); + } + + self->window = UI_Window_Create( + self->outer_stack, DIALOG_PADDING, DIALOG_PADDING, DIALOG_PADDING * 2, + DIALOG_PADDING); + + M_SetPosition(self, WINDOW_MARGIN, WINDOW_MARGIN); + return (UI_WIDGET *)self; +} diff --git a/src/tr1/game/ui/widgets/photo_mode.h b/src/tr1/game/ui/widgets/photo_mode.h new file mode 100644 index 000000000..e00b4c3ed --- /dev/null +++ b/src/tr1/game/ui/widgets/photo_mode.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +UI_WIDGET *UI_PhotoMode_Create(void); diff --git a/src/tr1/meson.build b/src/tr1/meson.build index b30afba19..69b17b202 100644 --- a/src/tr1/meson.build +++ b/src/tr1/meson.build @@ -114,6 +114,7 @@ sources = [ 'game/effect_routines/earthquake.c', 'game/ui/common.c', 'game/ui/widgets/label.c', + 'game/ui/widgets/photo_mode.c', 'game/ui/widgets/prompt.c', 'game/ui/widgets/window.c', 'game/effect_routines/explosion.c',