mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-15 14:18:37 +00:00
982 lines
33 KiB
C++
982 lines
33 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* Additional copyright for this file:
|
|
* Copyright (C) 1999-2000 Revolution Software Ltd.
|
|
* This code is based on source code created by Revolution Software,
|
|
* used with permission.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "engines/icb/common/px_rcutypes.h"
|
|
#include "engines/icb/common/ptr_util.h"
|
|
#include "engines/icb/global_objects.h"
|
|
#include "engines/icb/remora.h"
|
|
#include "engines/icb/text_sprites.h"
|
|
#include "engines/icb/icon_list_manager.h"
|
|
#include "engines/icb/global_switches.h"
|
|
#include "engines/icb/mission.h"
|
|
|
|
namespace ICB {
|
|
|
|
// This defines the maximum number of locks in the one-off mission 01 interface.
|
|
#define MAX_LOCKS_IN_M08 12
|
|
|
|
// This variable works like the L->looping flag, but controls a handful of tri-state functions in this file.
|
|
uint32 nFunctionState;
|
|
|
|
void RemoraStandardRestart(uint32 nRemoraID);
|
|
const char *SkipLineNumber(const char *pcLine);
|
|
|
|
mcodeFunctionReturnCodes fn_remora_script_activate(int32 &result, int32 *params) { return (MS->fn_remora_script_activate(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_script_deactivate(int32 &result, int32 *params) { return (MS->fn_remora_script_deactivate(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_is_active(int32 &result, int32 *params) { return (MS->fn_remora_is_active(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_get_mode(int32 &result, int32 *params) { return (MS->fn_remora_get_mode(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_set_mode(int32 &result, int32 *params) { return (MS->fn_remora_set_mode(result, params)); }
|
|
|
|
// These handle menus within the Remora.
|
|
mcodeFunctionReturnCodes fn_remora_add_icon(int32 &result, int32 *params) { return (MS->fn_remora_add_icon(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_remove_icon(int32 &result, int32 *params) { return (MS->fn_remora_remove_icon(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_reset_icon_list(int32 &result, int32 *params) { return (MS->fn_remora_reset_icon_list(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_choose(int32 &result, int32 *params) { return (MS->fn_remora_choose(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_wait_on_icon(int32 &result, int32 *params) { return (MS->fn_remora_wait_on_icon(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_new_menu(int32 &result, int32 *params) { return (MS->fn_remora_new_menu(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_new_menu_on_icon(int32 &result, int32 *params) { return (MS->fn_remora_new_menu_on_icon(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_menu_return(int32 &result, int32 *params) { return (MS->fn_remora_menu_return(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_menu_return_on_icon(int32 &result, int32 *params) { return (MS->fn_remora_menu_return_on_icon(result, params)); }
|
|
|
|
// These handle text display within the Remora.
|
|
mcodeFunctionReturnCodes fn_remora_paragraph_text(int32 &result, int32 *params) { return (MS->fn_remora_paragraph_text(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_main_heading(int32 &result, int32 *params) { return (MS->fn_remora_main_heading(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_sub_heading(int32 &result, int32 *params) { return (MS->fn_remora_sub_heading(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_option_text(int32 &result, int32 *params) { return (MS->fn_remora_option_text(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_warning_text(int32 &result, int32 *params) { return (MS->fn_remora_warning_text(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_blank_line(int32 &result, int32 *params) { return (MS->fn_remora_blank_line(result, params)); }
|
|
|
|
// These handle graphics within the Remora.
|
|
mcodeFunctionReturnCodes fn_remora_clear_screen(int32 &result, int32 *params) { return (MS->fn_remora_clear_screen(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_picture(int32 &result, int32 *params) { return (MS->fn_remora_picture(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_set_max_zoom(int32 &result, int32 *params) { return (MS->fn_remora_set_max_zoom(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_set_min_zoom(int32 &result, int32 *params) { return (MS->fn_remora_set_min_zoom(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_set_current_zoom(int32 &result, int32 *params) { return (MS->fn_remora_set_current_zoom(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_emp_flash(int32 &result, int32 *params) { return (MS->fn_remora_emp_flash(result, params)); }
|
|
|
|
// These deal with the Remora's email system.
|
|
mcodeFunctionReturnCodes fn_remora_send_email(int32 &result, int32 *params) { return (MS->fn_remora_send_email(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_is_email_waiting(int32 &result, int32 *params) { return (MS->fn_remora_is_email_waiting(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_mark_email_read(int32 &result, int32 *params) { return (MS->fn_remora_mark_email_read(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_check_email_id(int32 &result, int32 *params) { return (MS->fn_remora_check_email_id(result, params)); }
|
|
|
|
// Miscellaneous Remora functions.
|
|
mcodeFunctionReturnCodes fn_remora_fix_motion_scan_xz(int32 &result, int32 *params) { return (MS->fn_remora_fix_motion_scan_xz(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_default_logic(int32 &result, int32 *params) { return (MS->fn_remora_default_logic(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_mega_says(int32 &result, int32 *params) { return (MS->fn_remora_mega_says(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_add_floor_range(int32 &result, int32 *params) { return (MS->fn_remora_add_floor_range(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_reset_floor_ranges(int32 &result, int32 *params) { return (MS->fn_remora_reset_floor_ranges(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_set_map_knowledge_level(int32 &result, int32 *params) { return (MS->fn_remora_set_map_knowledge_level(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_update_player(int32 &result, int32 *params) { return (MS->fn_remora_update_player(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes fn_remora_progress_bar(int32 &result, int32 *params) { return (MS->fn_remora_progress_bar(result, params)); }
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_update_player(int32 &, int32 *) {
|
|
_input *state;
|
|
|
|
// If the Remora is now shut down, we need to return to player-standing mode.
|
|
if (!g_oRemora->IsActive()) {
|
|
return (IR_CONT);
|
|
}
|
|
|
|
// check keys/pads/etc. to see what the user is trying to do
|
|
player.Update_input_state();
|
|
|
|
state = player.Fetch_input_state();
|
|
|
|
// Now just run its logic. It will process the 'deactivate' message if one was posted in previous line.
|
|
g_oRemora->CycleRemoraLogic(*state);
|
|
|
|
// Cycle the inventory logic if it is active. Note though that the fact that the Remora is active does
|
|
// not mean the inventory is, because there could be a gap between menus being displayed.
|
|
if (g_oIconListManager->IsActive())
|
|
g_oIconListManager->CycleInventoryLogic(*state);
|
|
|
|
return (IR_REPEAT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_is_active(int32 &result, int32 *) {
|
|
// Call the function that does the work.
|
|
result = g_oRemora->IsActive();
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_get_mode(int32 &result, int32 *) {
|
|
// First check that the Remora is active.
|
|
if (g_oRemora->IsActive())
|
|
result = (int32)g_oRemora->GetMode();
|
|
else
|
|
result = REMORA_NOT_ACTIVE;
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_set_mode(int32 &, int32 *params) {
|
|
// Set the mode.
|
|
g_oRemora->SetMode((_remora::RemoraMode)params[0]);
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_picture(int32 &, int32 *params) {
|
|
uint32 nXOffset;
|
|
|
|
const char *picture_name = (const char *)MemoryUtil::resolvePtr(params[2]);
|
|
|
|
// Write the call in the debug file.
|
|
Zdebug("fn_remora_picture( %d, %d, %s )", (int32)params[0], (int32)params[1], picture_name);
|
|
|
|
// Neither can pixel offset.
|
|
nXOffset = ((int32)params[1] < 0) ? 0 : (uint32)params[1];
|
|
|
|
// Make the call to the Remora.
|
|
g_oRemora->SetupPicture(nXOffset, picture_name);
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_clear_screen(int32 &, int32 *) {
|
|
// Make the call to the Remora object.
|
|
g_oRemora->ClearAllText();
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_add_icon(int32 &, int32 *params) {
|
|
char pcIconPath[ENGINE_STRING_LEN];
|
|
|
|
const char *icon_name = (const char *)MemoryUtil::resolvePtr(params[0]);
|
|
|
|
// Make the call to the Remora object.
|
|
g_oIconListManager->AddIconToList(ICON_LIST_REMORA, icon_name);
|
|
|
|
// Preload the icon for PSX smoothing.
|
|
sprintf(pcIconPath, ICON_PATH);
|
|
g_oIconMenu->PreloadIcon(pcIconPath, icon_name);
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_remove_icon(int32 &, int32 *params) {
|
|
const char *icon_name = (const char *)MemoryUtil::resolvePtr(params[0]);
|
|
|
|
// Make the call to the Remora object.
|
|
g_oIconListManager->RemoveIconFromList(ICON_LIST_REMORA, icon_name);
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_reset_icon_list(int32 &, int32 *) {
|
|
// Make the call to the Remora object.
|
|
g_oIconListManager->ResetList(ICON_LIST_REMORA);
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_choose(int32 &, int32 *) {
|
|
// This function must be used from inside the Remora.
|
|
if (!g_oRemora->IsActive())
|
|
Fatal_error("fn_remora_choose() cannot be used outside the Remora");
|
|
|
|
// Make the call to the Remora object.
|
|
g_oIconListManager->ActivateIconMenu(ICON_LIST_REMORA, TRUE8, FALSE8);
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_paragraph_text(int32 &, int32 *params) {
|
|
const char *pcText;
|
|
|
|
// Find the text in the resources.
|
|
pcText = g_oRemora->LocateTextFromReference((uint32)params[1]);
|
|
|
|
if (pcText) {
|
|
// Skip line numbers.
|
|
pcText = SkipLineNumber(pcText);
|
|
|
|
// Set the text.
|
|
g_oRemora->SetText(pcText, REMORA_TEXT_PARAGRAPH, 1, PIN_AT_TOP_LEFT);
|
|
} else {
|
|
// We failed to find it.
|
|
Fatal_error("Unable to find text for reference %x in fn_remora_paragraph_text()", (uint32)params[1]);
|
|
}
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_main_heading(int32 &, int32 *params) {
|
|
const char *pcText;
|
|
|
|
// Find the text in the resources.
|
|
pcText = g_oRemora->LocateTextFromReference((uint32)params[0]);
|
|
|
|
if (pcText) {
|
|
// Skip line numbers.
|
|
pcText = SkipLineNumber(pcText);
|
|
|
|
// Set the text.
|
|
g_oRemora->SetText(pcText, REMORA_TEXT_HEADING, 0, PIN_AT_CENTRE);
|
|
} else {
|
|
// We failed to find it.
|
|
Fatal_error("Unable to find text for reference %x in fn_remora_main_heading()", (uint32)params[0]);
|
|
}
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_sub_heading(int32 &, int32 *params) {
|
|
const char *pcText;
|
|
|
|
// Find the text in the resources.
|
|
pcText = g_oRemora->LocateTextFromReference((uint32)params[1]);
|
|
|
|
if (pcText) {
|
|
// Skip line numbers.
|
|
pcText = SkipLineNumber(pcText);
|
|
|
|
// Set the text.
|
|
g_oRemora->SetText(pcText, REMORA_TEXT_HEADING, 0, PIN_AT_TOP_LEFT);
|
|
} else {
|
|
// We failed to find it.
|
|
Fatal_error("Unable to find text for reference %x in fn_remora_sub_heading()", (uint32)params[1]);
|
|
}
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_option_text(int32 &, int32 *params) {
|
|
const char *pcText;
|
|
|
|
// Find the text in the resources.
|
|
pcText = g_oRemora->LocateTextFromReference((uint32)params[1]);
|
|
|
|
if (pcText) {
|
|
// Skip line numbers.
|
|
pcText = SkipLineNumber(pcText);
|
|
|
|
// Set the text.
|
|
g_oRemora->SetText(pcText, REMORA_TEXT_OPTION, 0, PIN_AT_TOP_LEFT);
|
|
} else {
|
|
// We failed to find it.
|
|
Fatal_error("Unable to find text for reference %x in fn_remora_option_text()", (uint32)params[1]);
|
|
}
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_warning_text(int32 &, int32 *params) {
|
|
const char *pcText;
|
|
|
|
// Find the text in the resources.
|
|
pcText = g_oRemora->LocateTextFromReference((uint32)params[1]);
|
|
|
|
if (pcText) {
|
|
// Skip line numbers.
|
|
pcText = SkipLineNumber(pcText);
|
|
|
|
// Set the text.
|
|
g_oRemora->SetText(pcText, REMORA_TEXT_WARNING, 0, PIN_AT_CENTRE);
|
|
} else {
|
|
// We failed to find it.
|
|
Fatal_error("Unable to find text for reference %x in fn_remora_warning_text()", (uint32)params[1]);
|
|
}
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_blank_line(int32 &, int32 *) {
|
|
// Set the blank line.
|
|
g_oRemora->SetText(nullptr, 0, 0, PIN_AT_CENTRE);
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_progress_bar(int32 &, int32 *params) {
|
|
int32 nTargetCycles;
|
|
int32 nCurrentValue;
|
|
|
|
// Get cycles to run bar over.
|
|
nTargetCycles = (int32)params[0];
|
|
|
|
// Is this a new bar?
|
|
if (!L->looping) {
|
|
// We are now doing a script loop.
|
|
L->looping = TRUE8;
|
|
|
|
// Initially none of the bar is there.
|
|
g_oRemora->SetProgressBarValue(0);
|
|
|
|
// Set target value for bar.
|
|
g_oRemora->SetProgressBarTotal(nTargetCycles);
|
|
|
|
// And here I set a tri-state function control variable, to help with control.
|
|
nFunctionState = 1;
|
|
|
|
// Come back to this function next time.
|
|
return (IR_REPEAT);
|
|
}
|
|
|
|
// Check if we are incrementing progress bar or holding it for a cycle at 100%.
|
|
if (nFunctionState == 1) {
|
|
// Still increasing it. Get current bar position.
|
|
nCurrentValue = g_oRemora->GetProgressBarValue();
|
|
|
|
// Update bar count.
|
|
++nCurrentValue;
|
|
|
|
// Set current complete.
|
|
g_oRemora->SetProgressBarValue(nCurrentValue);
|
|
|
|
// Check if done yet.
|
|
if (nCurrentValue == nTargetCycles) {
|
|
// Finished, but we want to come back and hold it for a cycle.
|
|
nFunctionState = 2;
|
|
return (IR_REPEAT);
|
|
} else {
|
|
// Return to increment the bar some more next time.
|
|
return (IR_REPEAT);
|
|
}
|
|
} else {
|
|
// Now we have really finished.
|
|
L->looping = FALSE8;
|
|
g_oRemora->SetProgressBarValue(-1);
|
|
return (IR_CONT);
|
|
}
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_fix_motion_scan_xz(int32 &, int32 *) {
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_script_activate(int32 &, int32 *params) {
|
|
_input *psInputState;
|
|
|
|
// In case the script writer has forgotten to do it, drop any icon currently held.
|
|
g_oIconListManager->Drop();
|
|
|
|
// This tells the UI that the Remora is now active.
|
|
MS->player.Push_control_mode(ACTOR_RELATIVE);
|
|
MS->player.Set_player_status(REMORA);
|
|
|
|
// This flag is used to indicate that the Remora has been activated in a specific mode (i.e. from script,
|
|
// rather than the keyboard). It is used to stop the Remora dropping into its default menu selection upon
|
|
// activation; instead it will use the mode set here.
|
|
g_oRemora->SetModeOverride((_remora::RemoraMode)params[0]);
|
|
|
|
// This sets a flag which the Remora will pick up next cycle.
|
|
g_oRemora->ActivateRemora((_remora::RemoraMode)params[0]);
|
|
|
|
// Cycle the Remora's logic to make sure drawing code doesn't try to do a draw before the
|
|
// Remora has had a chance to set itself up.
|
|
MS->player.Update_input_state();
|
|
psInputState = MS->player.Fetch_input_state();
|
|
g_oRemora->CycleRemoraLogic(*psInputState);
|
|
|
|
// Stop key bounce.
|
|
MS->player.remora_lock = TRUE8;
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_script_deactivate(int32 &, int32 *) {
|
|
_input sInputState;
|
|
|
|
// Write the call in the debug files.
|
|
Zdebug("fn_remora_script_deactivate();");
|
|
|
|
// If the Remora is not active then there is nothing to do.
|
|
if (!g_oRemora->IsActive())
|
|
return (IR_CONT);
|
|
|
|
// The script may be set up in such a way that the icon that was selected to cause this deactivate
|
|
// to happen may not have cleared the currently-selected icon, so do it here to be safe.
|
|
g_oIconListManager->Drop();
|
|
|
|
// Deactivate the Remora.
|
|
g_oRemora->SetMode(_remora::MOTION_SCAN);
|
|
g_oRemora->DeactivateRemora(TRUE8);
|
|
sInputState.UnSetButton(__UNUSEDBUTTON);
|
|
g_oRemora->CycleRemoraLogic(sInputState);
|
|
|
|
// This tells the UI that the Remora is now gone and the player is back.
|
|
MS->player.Pop_control_mode();
|
|
|
|
logic_structs[player.Fetch_player_id()]->mega->weapon = __NOT_ARMED;
|
|
logic_structs[player.Fetch_player_id()]->voxel_info->___init(logic_structs[player.Fetch_player_id()]->mega->chr_name,
|
|
logic_structs[player.Fetch_player_id()]->mega->anim_set, __NOT_ARMED);
|
|
|
|
MS->player.Set_player_status(STOOD);
|
|
|
|
MS->Setup_prop_sleep_states(); // recompute prop sleep states once we leave remora
|
|
|
|
// Stop key bounce.
|
|
MS->player.remora_lock = TRUE8;
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_default_logic(int32 &, int32 *) {
|
|
// Check to see if we are already looping
|
|
if (!L->looping) {
|
|
// Mark the fact that we are now looping.
|
|
L->looping = 1;
|
|
|
|
// Clear any events outstanding for the Remora.
|
|
g_oEventManager->ClearAllEventsForObject(cur_id);
|
|
|
|
// Make sure there are no icons in the list for the Remora.
|
|
g_oIconListManager->ResetList(ICON_LIST_REMORA);
|
|
|
|
// Make sure the Remora's screen is clear.
|
|
g_oRemora->ClearAllText();
|
|
|
|
// Must call this function again.
|
|
return (IR_REPEAT);
|
|
} else {
|
|
// We are looping in this function call. Simply drop out if the Remora is not active.
|
|
if (!g_oRemora->IsActive()) {
|
|
// Remora not currently active.
|
|
return (IR_REPEAT);
|
|
} else {
|
|
// Remora has been activated. Either drop into the default menu mode, or do the one specified
|
|
// by script if there is one.
|
|
g_oRemora->SetDefaultOrOverrideMode();
|
|
|
|
// Make the Remora rerun its logic context.
|
|
g_oEventManager->PostNamedEventToObject(EVENT_LOGIC_RERUN, cur_id, cur_id);
|
|
|
|
// We are not looping from now on.
|
|
L->looping = 0;
|
|
|
|
// Calling script can continue now.
|
|
return (IR_CONT);
|
|
}
|
|
}
|
|
|
|
// To fix a GCC compiler warning
|
|
return (IR_REPEAT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_new_menu(int32 &, int32 *params) {
|
|
// Set the variables so we jump to the right menu when we restart.
|
|
g_oRemora->AccessMenuLevelVariables(params, _remora::SET);
|
|
|
|
// Jump.
|
|
RemoraStandardRestart(cur_id);
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_new_menu_on_icon(int32 &, int32 *params) {
|
|
const char *icon_name = (const char *)MemoryUtil::resolvePtr(params[5]);
|
|
|
|
// Check to see if we are already looping
|
|
if (!L->looping) {
|
|
// Set the variables so we jump to the right menu when we restart.
|
|
g_oRemora->AccessMenuLevelVariables(params, _remora::SET);
|
|
|
|
// Remove any icons from the icon list.
|
|
g_oIconListManager->ResetList(ICON_LIST_REMORA);
|
|
|
|
// Add the given icon to the Remora icon list.
|
|
g_oIconListManager->AddIconToList(ICON_LIST_REMORA, icon_name);
|
|
|
|
// Activate the chooser menu.
|
|
g_oIconListManager->ActivateIconMenu(ICON_LIST_REMORA, TRUE8, FALSE8);
|
|
|
|
// Mark the fact that we are now looping.
|
|
L->looping = 1;
|
|
|
|
// And here I set the tri-state function control variable, so we know which bit to run next.
|
|
nFunctionState = 1;
|
|
|
|
// Drop out but call this function again next time.
|
|
return (IR_REPEAT);
|
|
} else {
|
|
// We are looping on this function. The set-up part must already have been done. But the function has
|
|
// two subsequent states. See which one we're on.
|
|
if (nFunctionState == 1) {
|
|
// We are looping on this function. The set-up part must already have been done.
|
|
// Check for the icon being selected.
|
|
if (g_oIconListManager->ItemHeld() && g_oIconListManager->Holding(icon_name)) {
|
|
// Drop the item held.
|
|
g_oIconListManager->Drop();
|
|
|
|
// Cord speaks his instructions to the Remora.
|
|
g_oRemora->DisplayCharacterSpeech((uint32)params[6]);
|
|
|
|
// We are now moving to a new state in this function.
|
|
nFunctionState = 2;
|
|
return (IR_REPEAT);
|
|
} else {
|
|
// Icon has not been selected, so we need to come back to this function.
|
|
return (IR_REPEAT);
|
|
}
|
|
} else {
|
|
// Second stage of this function now: displaying mega speech.
|
|
if (g_oRemora->GetSpeechTimer() == 0) {
|
|
// Do the Remora script jump.
|
|
RemoraStandardRestart(cur_id);
|
|
|
|
// Allow calling script to continue.
|
|
nFunctionState = 0;
|
|
L->looping = 0;
|
|
return (IR_CONT);
|
|
} else {
|
|
// The speech hasn't been displayed long enough, so hold inside this fn_function().
|
|
return (IR_REPEAT);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_wait_on_icon(int32 &, int32 *params) {
|
|
const char *icon_name = (const char *)MemoryUtil::resolvePtr(params[0]);
|
|
|
|
// Check to see if we are already looping
|
|
if (!L->looping) {
|
|
// Remove any icons from the icon list.
|
|
g_oIconListManager->ResetList(ICON_LIST_REMORA);
|
|
|
|
// Add the given icon to the Remora icon list.
|
|
g_oIconListManager->AddIconToList(ICON_LIST_REMORA, icon_name);
|
|
|
|
// Activate the chooser menu.
|
|
g_oIconListManager->ActivateIconMenu(ICON_LIST_REMORA, TRUE8, FALSE8);
|
|
|
|
// Mark the fact that we are now looping.
|
|
L->looping = 1;
|
|
|
|
// And here I set the tri-state function control variable, so we know which bit to run next.
|
|
nFunctionState = 1;
|
|
|
|
// Drop out but call this function again next time.
|
|
return (IR_REPEAT);
|
|
} else {
|
|
// We are looping on this function. The set-up part must already have been done. But the function has
|
|
// two subsequent states. See which one we're on.
|
|
if (nFunctionState == 1) {
|
|
if (g_oIconListManager->ItemHeld() && g_oIconListManager->Holding(icon_name)) {
|
|
// Yes, user has selected the icon to start a new mode. First drop item held.
|
|
g_oIconListManager->Drop();
|
|
|
|
// Cord speaks his instructions to the Remora.
|
|
g_oRemora->DisplayCharacterSpeech((uint32)params[2]);
|
|
|
|
// We are now moving to a new state in this function.
|
|
nFunctionState = 2;
|
|
|
|
// Drop out but call this function again next time.
|
|
return (IR_REPEAT);
|
|
} else {
|
|
// Drop out but call this function again next time.
|
|
return (IR_REPEAT);
|
|
}
|
|
} else {
|
|
// Second stage of this function now: displaying mega speech.
|
|
if (g_oRemora->GetSpeechTimer() == 0) {
|
|
// Do the Remora new mode.
|
|
g_oRemora->SetMode((_remora::RemoraMode)params[1]);
|
|
RemoraStandardRestart(cur_id);
|
|
|
|
// Allow calling script to continue.
|
|
nFunctionState = 0;
|
|
L->looping = 0;
|
|
return (IR_CONT);
|
|
} else {
|
|
// The speech hasn't been displayed long enough, so hold inside this fn_function().
|
|
return (IR_REPEAT);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_menu_return(int32 &, int32 *params) {
|
|
int32 i;
|
|
uint32 nReturned;
|
|
int32 pnMenuVariables[REMORA_MENU_DEPTH];
|
|
|
|
// Get the current state of the menu variables.
|
|
g_oRemora->AccessMenuLevelVariables(pnMenuVariables, _remora::GET);
|
|
|
|
// Find out how deep we are already in the menu tree.
|
|
i = REMORA_MENU_DEPTH - 1;
|
|
while ((i >= 0) && (pnMenuVariables[i] == 0))
|
|
--i;
|
|
|
|
// If we ran off the end then we are already at the root, but there is little value in making this an error.
|
|
if (i < 0)
|
|
return (IR_CONT);
|
|
|
|
// We are at a certain depth in the menu tree, so back up the required amount. If we run off the end,
|
|
// this means user has requested to go back more levels than we are deep, but just ignore this.
|
|
nReturned = 0;
|
|
while ((i >= 0) && (nReturned < (uint32)params[0])) {
|
|
pnMenuVariables[i] = 0;
|
|
--i;
|
|
++nReturned;
|
|
}
|
|
|
|
// Put the new values back in the script object.
|
|
g_oRemora->AccessMenuLevelVariables(pnMenuVariables, _remora::SET);
|
|
|
|
// Jump.
|
|
RemoraStandardRestart(cur_id);
|
|
|
|
// Allow calling script to continue.
|
|
return (IR_CONT);
|
|
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_menu_return_on_icon(int32 &, int32 *params) {
|
|
int32 i;
|
|
uint32 nReturned;
|
|
int32 pnMenuVariables[REMORA_MENU_DEPTH];
|
|
|
|
const char *icon_name = (const char *)MemoryUtil::resolvePtr(params[1]);
|
|
|
|
// Check to see if we are already looping
|
|
if (!L->looping) {
|
|
// First time in, so display the icon.
|
|
g_oIconListManager->ResetList(ICON_LIST_REMORA);
|
|
g_oIconListManager->AddIconToList(ICON_LIST_REMORA, icon_name);
|
|
g_oIconListManager->ActivateIconMenu(ICON_LIST_REMORA, TRUE8, FALSE8);
|
|
|
|
// Mark the fact that we are now looping.
|
|
L->looping = 1;
|
|
|
|
// And here I set the tri-state function control variable, so we know which bit to run next.
|
|
nFunctionState = 1;
|
|
|
|
// Drop out but call this function again next time.
|
|
return (IR_REPEAT);
|
|
} else {
|
|
// We are looping on this function. The set-up part must already have been done. But the function has
|
|
// two subsequent states. See which one we're on.
|
|
if (nFunctionState == 1) {
|
|
if (g_oIconListManager->ItemHeld() && g_oIconListManager->Holding(icon_name)) {
|
|
// Clear the item held.
|
|
g_oIconListManager->Drop();
|
|
|
|
// Remove any icons from the icon list.
|
|
g_oIconListManager->ResetList(ICON_LIST_REMORA);
|
|
|
|
// Icon has been selected, so we are going to do the jump back up the menu tree. Get
|
|
// current state of the menu variables.
|
|
g_oRemora->AccessMenuLevelVariables(pnMenuVariables, _remora::GET);
|
|
|
|
// Find out how deep we are already in the menu tree.
|
|
i = REMORA_MENU_DEPTH - 1;
|
|
while ((i >= 0) && (pnMenuVariables[i] == 0))
|
|
--i;
|
|
|
|
// If we ran off the end then we are already at the root, but there is no value in
|
|
// making this an error.
|
|
if (i >= 0) {
|
|
// We are at a certain depth in the menu tree, so back up the required amount. If we run off the
|
|
// end,
|
|
// this means user has requested to go back more levels than we are deep, but just ignore this.
|
|
nReturned = 0;
|
|
while ((i >= 0) && (nReturned < (uint32)params[0])) {
|
|
pnMenuVariables[i] = 0;
|
|
--i;
|
|
++nReturned;
|
|
}
|
|
}
|
|
|
|
// Put the new values back in the script object.
|
|
g_oRemora->AccessMenuLevelVariables(pnMenuVariables, _remora::SET);
|
|
|
|
// Display what Cord needs to say.
|
|
g_oRemora->DisplayCharacterSpeech((uint32)params[2]);
|
|
|
|
// We are now moving to a new state in this function.
|
|
nFunctionState = 2;
|
|
|
|
// Drop out but call this function again next time.
|
|
return (IR_REPEAT);
|
|
} else {
|
|
// Icon has not been chosen, so call this function again next time.
|
|
return (IR_REPEAT);
|
|
}
|
|
} else {
|
|
// Second stage of this function now: displaying mega speech.
|
|
if (g_oRemora->GetSpeechTimer() == 0) {
|
|
// Do the Remora script jump.
|
|
RemoraStandardRestart(cur_id);
|
|
|
|
// Allow calling script to continue.
|
|
nFunctionState = 0;
|
|
L->looping = 0;
|
|
return (IR_CONT);
|
|
} else {
|
|
// The speech hasn't been displayed long enough, so hold inside this fn_function().
|
|
return (IR_REPEAT);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_mega_says(int32 &, int32 *params) {
|
|
// Check to see if we are already looping
|
|
if (!L->looping) {
|
|
// Mark the fact that we are now looping.
|
|
L->looping = 1;
|
|
|
|
// Find the text in the resources.
|
|
g_oRemora->DisplayCharacterSpeech((uint32)params[1]);
|
|
|
|
// Drop out but call this function again next time.
|
|
return (IR_REPEAT);
|
|
} else {
|
|
// Get the speech timer. If it has run down to zero, the supplied line has been displayed long enough,
|
|
// so we can go on to the next line of script.
|
|
if (g_oRemora->GetSpeechTimer() == 0) {
|
|
// Allow calling script to continue.
|
|
L->looping = 0;
|
|
return (IR_CONT);
|
|
}
|
|
|
|
// The speech hasn't been displayed long enough, so hold inside this fn_function().
|
|
return (IR_REPEAT);
|
|
}
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_add_floor_range(int32 &, int32 *params) {
|
|
// Simply pass the call on to the Remora.
|
|
g_oRemora->AddFloorRange((uint32)params[0], (uint32)params[1]);
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_reset_floor_ranges(int32 &, int32 *) {
|
|
// Simply pass the call on to the Remora.
|
|
g_oRemora->ResetFloorRanges();
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_send_email(int32 &, int32 *params) {
|
|
const char *email_id = (const char *)MemoryUtil::resolvePtr(params[0]);
|
|
|
|
// Set the email in the Remora.
|
|
g_oRemora->NewEmail(email_id);
|
|
|
|
// Here we borrow the logic in the icon menu which flashes added medipacks etc.
|
|
g_oIconListManager->SetEmailArrived();
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_is_email_waiting(int32 &result, int32 *) {
|
|
// Make the call to the Remora.
|
|
result = (int32)g_oRemora->IsEmailWaiting();
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_check_email_id(int32 &result, int32 *params) {
|
|
const char *email_id = (const char *)MemoryUtil::resolvePtr(params[0]);
|
|
|
|
// Check with the Remora if the string matches.
|
|
result = g_oRemora->IsThisEmailWaiting(email_id);
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_mark_email_read(int32 &, int32 *) {
|
|
// Turn off the email-waiting flag in the Remora.
|
|
g_oRemora->MarkEmailRead();
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_set_max_zoom(int32 &, int32 *params) {
|
|
// Call the Remora function to do it.
|
|
g_oRemora->SetMaximumZoom((uint32)params[0]);
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_set_min_zoom(int32 &, int32 *params) {
|
|
// Call the Remora function to do it.
|
|
g_oRemora->SetMinimumZoom((uint32)params[0]);
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_set_current_zoom(int32 &, int32 *params) {
|
|
// Call the Remora function to do it.
|
|
g_oRemora->SetCurrentZoom((uint32)params[0]);
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_emp_flash(int32 &, int32 *) {
|
|
// If the Remora is not active, just ignore this function.
|
|
if (g_oRemora->IsActive()) {
|
|
// Check to see if we are already looping
|
|
if (!L->looping) {
|
|
// Mark the fact that we are now looping.
|
|
L->looping = 1;
|
|
}
|
|
|
|
// See if the EMP effect is still running or not.
|
|
if (g_oRemora->EMPEffect()) {
|
|
// Menu still active, so we must continue cycling its logic next time through.
|
|
return (IR_REPEAT);
|
|
} else {
|
|
// A selection has been made or the menu has been cancelled. Calling script can now continue.
|
|
L->looping = 0;
|
|
return (IR_CONT);
|
|
}
|
|
}
|
|
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes _game_session::fn_remora_set_map_knowledge_level(int32 &, int32 * /*params*/) {
|
|
// Calling script can continue.
|
|
return (IR_CONT);
|
|
}
|
|
|
|
void RemoraStandardRestart(uint32 nRemoraID) {
|
|
// Clear the item held if any.
|
|
g_oIconListManager->Drop();
|
|
|
|
// This blockRemove any icons from the icon list.
|
|
g_oIconListManager->ResetList(ICON_LIST_REMORA);
|
|
|
|
// Clear all text.
|
|
g_oRemora->ClearAllText();
|
|
|
|
MS->logic_structs[nRemoraID]->context_request = TRUE8;
|
|
}
|
|
|
|
const char *SkipLineNumber(const char *pcLine) {
|
|
const char *pcParsePos;
|
|
|
|
// If line number display is turned on, don't do anything.
|
|
if (g_px->speechLineNumbers)
|
|
return (pcLine);
|
|
|
|
// Initialise parse pointer.
|
|
pcParsePos = pcLine;
|
|
|
|
// If the first character is one that marks the line as being spoken or not, skip it.
|
|
if ((*pcParsePos == TS_SPOKEN_LINE) || (*pcParsePos == TS_NON_SPOKEN_LINE))
|
|
++pcParsePos;
|
|
|
|
// The first character has to start the line number to be valid.
|
|
if (*pcParsePos == TS_LINENO_OPEN) {
|
|
// Okay, we appear to have a legal line number. Find the close brace for it.
|
|
while ((*pcParsePos != '\0') && (*pcParsePos != TS_LINENO_CLOSE))
|
|
++pcParsePos;
|
|
|
|
// If we didn't find one then this is an error.
|
|
if (*pcParsePos == '\0')
|
|
Fatal_error("Failed to find the end of the line number in [%s]", pcLine);
|
|
|
|
// Skip to first non-space after the line number.
|
|
++pcParsePos;
|
|
while ((*pcParsePos != '\0') && (*pcParsePos == ' '))
|
|
++pcParsePos;
|
|
|
|
// If we got to the end of the string then we have a line number with no text following it.
|
|
if (*pcParsePos == '\0')
|
|
Fatal_error("Found line number [%s] with no text in SkipLineNumber()", pcLine);
|
|
|
|
// Write the modified pointer back into the text block.
|
|
return (pcParsePos);
|
|
} else {
|
|
// No line number so nothing to chop off.
|
|
return (pcParsePos);
|
|
}
|
|
}
|
|
|
|
} // End of namespace ICB
|