scummvm/engines/icb/function.cpp
2020-10-06 09:51:20 +02:00

3349 lines
110 KiB
C++

/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "engines/icb/common/px_common.h"
#include "engines/icb/common/ptr_util.h"
#include "engines/icb/icb.h"
#include "engines/icb/p4_generic.h"
#include "engines/icb/debug.h"
#include "engines/icb/mission.h"
#include "engines/icb/global_objects.h"
#include "engines/icb/global_switches.h"
#include "engines/icb/floors.h"
#include "engines/icb/fn_routines.h"
#include "engines/icb/p4_generic.h"
#include "engines/icb/sound.h" // to get PauseSounds()
#include "engines/icb/common/px_scriptengine.h"
#include "engines/icb/common/px_floor_map.h"
#include "engines/icb/common/px_features.h"
#include "engines/icb/direct_input.h"
#include "engines/icb/actor.h"
#include "engines/icb/remora.h"
#include "common/keyboard.h"
namespace ICB {
mcodeFunctionReturnCodes fn_set_voxel_image_path(int32 &result, int32 *params) { return (g_mission->session->fn_set_voxel_image_path(result, params)); }
mcodeFunctionReturnCodes fn_test(int32 &result, int32 *params) { return (g_mission->session->fn_test(result, params)); }
mcodeFunctionReturnCodes fn_create_mega(int32 &result, int32 *params) { return (g_mission->session->fn_create_mega(result, params)); }
mcodeFunctionReturnCodes fn_set_xyz(int32 &result, int32 *params) { return (g_mission->session->fn_set_xyz(result, params)); }
mcodeFunctionReturnCodes fn_set_to_floor(int32 &result, int32 *params) { return (g_mission->session->fn_set_to_floor(result, params)); }
mcodeFunctionReturnCodes fn_init_from_nico_file(int32 &result, int32 *params) { return (g_mission->session->fn_init_from_nico_file(result, params)); }
mcodeFunctionReturnCodes fn_init_from_marker_file(int32 &result, int32 *params) { return (MS->fn_init_from_marker_file(result, params)); }
mcodeFunctionReturnCodes fn_set_player_can_interact(int32 &result, int32 *params) { return (MS->fn_set_player_can_interact(result, params)); }
mcodeFunctionReturnCodes fn_set_player_cannot_interact(int32 &result, int32 *params) { return (MS->fn_set_player_cannot_interact(result, params)); }
mcodeFunctionReturnCodes fn_call_socket(int32 &result, int32 *params) { return (MS->fn_call_socket(result, params)); }
mcodeFunctionReturnCodes fn_prop_near_a_mega(int32 &result, int32 *params) { return (MS->fn_prop_near_a_mega(result, params)); }
mcodeFunctionReturnCodes socket_force_new_logic(int32 &result, int32 *params) { return (MS->socket_force_new_logic(result, params)); }
mcodeFunctionReturnCodes fn_reset_player(int32 &result, int32 *params) { return (MS->fn_reset_player(result, params)); }
mcodeFunctionReturnCodes fn_rig_test(int32 &result, int32 *params) { return (MS->fn_rig_test(result, params)); }
mcodeFunctionReturnCodes fn_teleport(int32 &result, int32 *params) { return (MS->fn_teleport(result, params)); }
mcodeFunctionReturnCodes fn_teleport_to_nico(int32 &result, int32 *params) { return (MS->fn_teleport_to_nico(result, params)); }
mcodeFunctionReturnCodes fn_get_pan_from_nico(int32 &result, int32 *params) { return (MS->fn_get_pan_from_nico(result, params)); }
mcodeFunctionReturnCodes fn_are_we_on_this_floor(int32 &result, int32 *params) { return (MS->fn_are_we_on_this_floor(result, params)); }
mcodeFunctionReturnCodes fn_is_object_on_our_floor(int32 &result, int32 *params) { return (MS->fn_is_object_on_our_floor(result, params)); }
mcodeFunctionReturnCodes fn_is_object_on_screen(int32 &result, int32 *params) { return (MS->fn_is_object_on_screen(result, params)); }
mcodeFunctionReturnCodes fn_is_object_dead(int32 &result, int32 *params) { return (MS->fn_is_object_dead(result, params)); }
mcodeFunctionReturnCodes fn_set_weapon(int32 &result, int32 *params) { return (g_mission->session->fn_set_weapon(result, params)); }
mcodeFunctionReturnCodes fn_set_custom(int32 &result, int32 *params) { return (g_mission->session->fn_set_custom(result, params)); }
mcodeFunctionReturnCodes fn_message(int32 &result, int32 *params) { return (g_mission->session->fn_message(result, params)); }
mcodeFunctionReturnCodes fn_message_var(int32 &result, int32 *params) { return (g_mission->session->fn_message_var(result, params)); }
mcodeFunctionReturnCodes fn_get_state_flag(int32 &result, int32 *params) { return (g_mission->session->fn_get_state_flag(result, params)); }
mcodeFunctionReturnCodes fn_near(int32 &result, int32 *params) { return (g_mission->session->fn_near(result, params)); }
mcodeFunctionReturnCodes fn_teleport_z(int32 &result, int32 *params) { return (MS->fn_teleport_z(result, params)); }
mcodeFunctionReturnCodes fn_on_screen(int32 &result, int32 *params) { return (MS->fn_on_screen(result, params)); }
mcodeFunctionReturnCodes fn_hold_if_off_screen(int32 &result, int32 *params) { return (MS->fn_hold_if_off_screen(result, params)); }
mcodeFunctionReturnCodes fn_object_near_nico(int32 &result, int32 *params) { return (MS->fn_object_near_nico(result, params)); }
mcodeFunctionReturnCodes fn_teleport_y_to_id(int32 &result, int32 *params) { return (MS->fn_teleport_y_to_id(result, params)); }
mcodeFunctionReturnCodes fn_call_socket_id(int32 &result, int32 *params) { return (MS->fn_call_socket_id(result, params)); }
mcodeFunctionReturnCodes fn_lift_process_list(int32 &result, int32 *params) { return (MS->fn_lift_process_list(result, params)); }
mcodeFunctionReturnCodes fn_add_object_id_to_list(int32 &result, int32 *params) { return (MS->fn_add_object_id_to_list(result, params)); }
mcodeFunctionReturnCodes fn_add_object_name_to_list(int32 &result, int32 *params) { return (MS->fn_add_object_name_to_list(result, params)); }
mcodeFunctionReturnCodes fn_hold_while_list_near_nico(int32 &result, int32 *params) { return (MS->fn_hold_while_list_near_nico(result, params)); }
mcodeFunctionReturnCodes fn_set_watch(int32 &result, int32 *params) { return (MS->fn_set_watch(result, params)); }
mcodeFunctionReturnCodes fn_three_sixty_interact(int32 &result, int32 *params) { return (MS->fn_three_sixty_interact(result, params)); }
mcodeFunctionReturnCodes fn_near_list(int32 &result, int32 *params) { return (MS->fn_near_list(result, params)); }
mcodeFunctionReturnCodes fn_get_list_result(int32 &result, int32 *params) { return (MS->fn_get_list_result(result, params)); }
mcodeFunctionReturnCodes fn_random(int32 &result, int32 *params) { return (MS->fn_random(result, params)); }
mcodeFunctionReturnCodes fn_change_session(int32 &result, int32 *params) { return (MS->fn_change_session(result, params)); }
mcodeFunctionReturnCodes fn_changed_sessions(int32 &result, int32 *params) { return (MS->fn_changed_sessions(result, params)); }
mcodeFunctionReturnCodes fn_is_object_adjacent(int32 &result, int32 *params) { return (MS->fn_is_object_adjacent(result, params)); }
mcodeFunctionReturnCodes fn_is_object_on_this_floor(int32 &result, int32 *params) { return (MS->fn_is_object_on_this_floor(result, params)); }
mcodeFunctionReturnCodes fn_get_objects_lvar_value(int32 &result, int32 *params) { return (MS->fn_get_objects_lvar_value(result, params)); }
mcodeFunctionReturnCodes fn_set_objects_lvar_value(int32 &result, int32 *params) { return (MS->fn_set_objects_lvar_value(result, params)); }
mcodeFunctionReturnCodes fn_switch_on_the_really_neat_and_special_script_debugging_facility(int32 &result, int32 *params) {
return (MS->fn_switch_on_the_really_neat_and_special_script_debugging_facility(result, params));
}
mcodeFunctionReturnCodes fn_switch_off_the_really_neat_and_special_script_debugging_facility(int32 &result, int32 *params) {
return (MS->fn_switch_off_the_really_neat_and_special_script_debugging_facility(result, params));
}
mcodeFunctionReturnCodes fn_no_logic(int32 &result, int32 *params) { return (MS->fn_no_logic(result, params)); }
mcodeFunctionReturnCodes fn_lift2_process(int32 &result, int32 *params) { return (MS->fn_lift2_process(result, params)); }
mcodeFunctionReturnCodes fn_preload_custom_mega_anim(int32 &result, int32 *params) { return (MS->fn_preload_custom_mega_anim(result, params)); }
mcodeFunctionReturnCodes fn_init_mega_from_nico(int32 &result, int32 *params) { return (MS->fn_init_mega_from_nico(result, params)); }
mcodeFunctionReturnCodes fn_mega_use_lift(int32 &result, int32 *params) { return (MS->fn_mega_use_lift(result, params)); }
mcodeFunctionReturnCodes fn_snap_to_nico_y(int32 &result, int32 *params) { return (MS->fn_snap_to_nico_y(result, params)); }
mcodeFunctionReturnCodes fn_lib_lift_chord_and_chi(int32 &result, int32 *params) { return (MS->fn_lib_lift_chord_and_chi(result, params)); }
mcodeFunctionReturnCodes fn_set_interacting(int32 &result, int32 *params) { return (MS->fn_set_interacting(result, params)); }
mcodeFunctionReturnCodes fn_clear_interacting(int32 &result, int32 *params) { return (MS->fn_clear_interacting(result, params)); }
mcodeFunctionReturnCodes fn_check_for_nico(int32 &result, int32 *params) { return (MS->fn_check_for_nico(result, params)); }
mcodeFunctionReturnCodes fn_set_ids_lvar_value(int32 &result, int32 *params) { return (MS->fn_set_ids_lvar_value(result, params)); }
mcodeFunctionReturnCodes fn_teleport_to_nico_y(int32 &result, int32 *params) { return (MS->fn_teleport_to_nico_y(result, params)); }
mcodeFunctionReturnCodes fn_set_evil(int32 &result, int32 *params) { return (MS->fn_set_evil(result, params)); }
mcodeFunctionReturnCodes fn_changed_via_this_shaft(int32 &result, int32 *params) { return (MS->fn_changed_via_this_shaft(result, params)); }
mcodeFunctionReturnCodes fn_get_objects_x(int32 &result, int32 *params) { return (MS->fn_get_objects_x(result, params)); }
mcodeFunctionReturnCodes fn_get_objects_y(int32 &result, int32 *params) { return (MS->fn_get_objects_y(result, params)); }
mcodeFunctionReturnCodes fn_get_objects_z(int32 &result, int32 *params) { return (MS->fn_get_objects_z(result, params)); }
mcodeFunctionReturnCodes fn_are_we_on_screen(int32 &result, int32 *params) { return (MS->fn_are_we_on_screen(result, params)); }
mcodeFunctionReturnCodes fn_is_mega_within_area(int32 &result, int32 *params) { return (MS->fn_is_mega_within_area(result, params)); }
mcodeFunctionReturnCodes fn_end_mission(int32 &result, int32 *params) { return (MS->fn_end_mission(result, params)); }
mcodeFunctionReturnCodes fn_set_pose(int32 &result, int32 *params) { return (MS->fn_set_pose(result, params)); }
mcodeFunctionReturnCodes fn_is_crouching(int32 &result, int32 *params) { return (MS->fn_is_crouching(result, params)); }
mcodeFunctionReturnCodes fn_is_armed(int32 &result, int32 *params) { return (MS->fn_is_armed(result, params)); }
mcodeFunctionReturnCodes fn_am_i_player(int32 &result, int32 *params) { return (MS->fn_am_i_player(result, params)); }
mcodeFunctionReturnCodes fn_start_conveyor(int32 &result, int32 *params) { return (MS->fn_start_conveyor(result, params)); }
mcodeFunctionReturnCodes fn_stop_conveyor(int32 &result, int32 *params) { return (MS->fn_stop_conveyor(result, params)); }
mcodeFunctionReturnCodes fn_register_stairway(int32 &result, int32 *params) { return (MS->fn_register_stairway(result, params)); }
mcodeFunctionReturnCodes fn_set_object_type(int32 &result, int32 *params) { return (MS->fn_set_object_type(result, params)); }
mcodeFunctionReturnCodes fn_register_ladder(int32 &result, int32 *params) { return (MS->fn_register_ladder(result, params)); }
mcodeFunctionReturnCodes fn_is_an_object_crouching(int32 &result, int32 *params) { return (MS->fn_is_an_object_crouching(result, params)); }
mcodeFunctionReturnCodes fn_align_with_floor(int32 &result, int32 *params) { return (MS->fn_align_with_floor(result, params)); }
mcodeFunctionReturnCodes fn_load_players_gun(int32 &result, int32 *params) { return (MS->fn_load_players_gun(result, params)); }
mcodeFunctionReturnCodes fn_flash_health(int32 &result, int32 *params) { return (MS->fn_flash_health(result, params)); }
mcodeFunctionReturnCodes fn_set_player_pose(int32 &result, int32 *params) { return (MS->fn_set_player_pose(result, params)); }
mcodeFunctionReturnCodes fn_set_anim_speed(int32 &result, int32 *params) { return (MS->fn_set_anim_speed(result, params)); }
mcodeFunctionReturnCodes fn_push_coords(int32 &result, int32 *params) { return (MS->fn_push_coords(result, params)); }
mcodeFunctionReturnCodes fn_pop_coords(int32 &result, int32 *params) { return (MS->fn_pop_coords(result, params)); }
mcodeFunctionReturnCodes fn_set_texture(int32 &result, int32 *params) { return (MS->fn_set_texture(result, params)); }
mcodeFunctionReturnCodes fn_set_palette(int32 &result, int32 *params) { return (MS->fn_set_palette(result, params)); }
mcodeFunctionReturnCodes fn_restart_gamescript(int32 &result, int32 *params) { return (MS->fn_restart_gamescript(result, params)); }
mcodeFunctionReturnCodes fn_quick_restart(int32 &result, int32 *params) { return (MS->fn_quick_restart(result, params)); }
mcodeFunctionReturnCodes fn_is_mega_near_mega(int32 &result, int32 *params) { return (MS->fn_is_mega_near_mega(result, params)); }
mcodeFunctionReturnCodes fn_make_remora_beep(int32 &result, int32 *params) { return (MS->fn_make_remora_beep(result, params)); }
mcodeFunctionReturnCodes fn_shadows_on(int32 &result, int32 *params) { return (MS->fn_shadows_on(result, params)); }
mcodeFunctionReturnCodes fn_shadows_off(int32 &result, int32 *params) { return (MS->fn_shadows_off(result, params)); }
mcodeFunctionReturnCodes fn_panless_teleport_to_nico(int32 &result, int32 *params) { return (MS->fn_panless_teleport_to_nico(result, params)); }
mcodeFunctionReturnCodes fn_can_mega_see_dead_megas(int32 &result, int32 *params) { return (MS->fn_can_mega_see_dead_megas(result, params)); }
mcodeFunctionReturnCodes fn_set_shade_percentage(int32 &result, int32 *params) { return (MS->fn_set_shade_percentage(result, params)); }
mcodeFunctionReturnCodes fn_do_not_disturb(int32 &result, int32 *params) { return (MS->fn_do_not_disturb(result, params)); }
mcodeFunctionReturnCodes fn_has_mega_our_height(int32 &result, int32 *params) { return (MS->fn_has_mega_our_height(result, params)); }
mcodeFunctionReturnCodes fn_register_platform_coords(int32 &result, int32 *params) { return (MS->fn_register_platform_coords(result, params)); }
mcodeFunctionReturnCodes fn_activate_stair_or_ladder(int32 &result, int32 *params) { return (MS->fn_activate_stair_or_ladder(result, params)); }
mcodeFunctionReturnCodes fn_deactivate_stair_or_ladder(int32 &result, int32 *params) { return (MS->fn_deactivate_stair_or_ladder(result, params)); }
mcodeFunctionReturnCodes fn_set_half_character_width(int32 &result, int32 *params) { return (MS->fn_set_half_character_width(result, params)); }
mcodeFunctionReturnCodes fn_set_interact_look_height(int32 &result, int32 *params) { return (MS->fn_set_interact_look_height(result, params)); }
mcodeFunctionReturnCodes fn_set_visible(int32 &result, int32 *params) { return (MS->fn_set_visible(result, params)); }
mcodeFunctionReturnCodes fn_set_object_visible(int32 &result, int32 *params) { return (MS->fn_set_object_visible(result, params)); }
mcodeFunctionReturnCodes fn_set_to_dead(int32 &result, int32 *params) { return (MS->fn_set_to_dead(result, params)); }
mcodeFunctionReturnCodes fn_set_camera_hold(int32 &result, int32 *params) { return (MS->fn_set_camera_hold(result, params)); }
mcodeFunctionReturnCodes fn_set_mega_wait_for_player(int32 &result, int32 *params) { return (MS->fn_set_mega_wait_for_player(result, params)); }
mcodeFunctionReturnCodes fn_set_mega_off_camera_hold(int32 &result, int32 *params) { return (MS->fn_set_mega_off_camera_hold(result, params)); }
mcodeFunctionReturnCodes fn_set_mega_slice_hold(int32 &result, int32 *params) { return (MS->fn_set_mega_slice_hold(result, params)); }
mcodeFunctionReturnCodes fn_set_mesh(int32 &result, int32 *params) { return (MS->fn_set_mesh(result, params)); }
mcodeFunctionReturnCodes fn_prop_crouch_interact(int32 &result, int32 *params) { return (MS->fn_prop_crouch_interact(result, params)); }
mcodeFunctionReturnCodes fn_set_sleep(int32 &result, int32 *params) { return (MS->fn_set_sleep(result, params)); }
mcodeFunctionReturnCodes fn_wait_for_button(int32 &result, int32 *params) { return (MS->fn_wait_for_button(result, params)); }
mcodeFunctionReturnCodes fn_trace(int32 &result, int32 *params) { return (MS->fn_trace(result, params)); }
mcodeFunctionReturnCodes fn_lock_y(int32 &result, int32 *params) { return (MS->fn_lock_y(result, params)); }
mcodeFunctionReturnCodes fn_unlock_y(int32 &result, int32 *params) { return (MS->fn_unlock_y(result, params)); }
mcodeFunctionReturnCodes fn_flip_pan(int32 &result, int32 *params) { return (MS->fn_flip_pan(result, params)); }
mcodeFunctionReturnCodes fn_snap_to_ladder_bottom(int32 &result, int32 *params) { return (MS->fn_snap_to_ladder_bottom(result, params)); }
mcodeFunctionReturnCodes fn_snap_to_ladder_top(int32 &result, int32 *params) { return (MS->fn_snap_to_ladder_top(result, params)); }
mcodeFunctionReturnCodes fn_PLEASE_REUSE_THIS_SLOT_2(int32 &, int32 *) { return IR_CONT; }
mcodeFunctionReturnCodes fn_PLEASE_REUSE_THIS_SLOT_3(int32 &, int32 *) { return IR_CONT; }
mcodeFunctionReturnCodes fn_swordfight(int32 &result, int32 *params) { return (MS->fn_swordfight(result, params)); }
mcodeFunctionReturnCodes _game_session::fn_swordfight(int32 &, int32 *) { return (IR_CONT); }
mcodeFunctionReturnCodes fn_set_as_player(int32 &result, int32 *params) { return (MS->fn_set_as_player(result, params)); }
mcodeFunctionReturnCodes _game_session::fn_set_as_player(int32 &, int32 *) { return (IR_CONT); }
mcodeFunctionReturnCodes _game_session::fn_rig_test(int32 &, int32 *) {
// no params
if (!MS->prev_save_state)
return IR_REPEAT;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_test(int32 & /*result*/, int32 * /*params*/) {
#if 0
char buf[256];
sprintf(buf, "z_%s.txt", object->GetName());
if (params[0] < 256)
Tdebug(buf, "%d", params[0]);
else
Tdebug(buf, "%s", params[0]);
result = TRUE8;
#endif
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_create_mega(int32 &, int32 *) {
Zdebug("FN_create_mega");
// assign _mega object
logic_structs[cur_id]->mega = &megas[num_megas];
logic_structs[cur_id]->mega->___init();
// set the view state to off camera for this cycle and last cycle
logic_structs[cur_id]->mega->viewState = OFF_OFF_CAMERA;
num_megas++;
if (num_megas == MAX_voxel_list)
Fatal_error("fn_create_mega - too many megas!");
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::socket_force_new_logic(int32 &, int32 *params) {
// force in a new logic script mega who owns the socket script
// IGNORES if already running
// params [0] extension part of script name
char *ad;
uint32 script_hash;
const char *script_name = (const char *)MemoryUtil::resolvePtr(params[0]);
script_hash = HashString(script_name);
if (px.socket_watch)
Message_box("socket_force_new_logic - obj %s, script %s", socket_object->GetName(), script_name);
// now try and find a script with the passed extention i.e. ???::looping
for (uint32 k = 0; k < socket_object->GetNoScripts(); k++) {
// now check for actual script name
if (script_hash == socket_object->GetScriptNamePartHash(k)) {
Zdebug("script %d matches", k);
// script k is the one to run
// get the address of the script we want to run
ad = (char *)scripts->Try_fetch_item_by_hash(socket_object->GetScriptNameFullHash(k));
if (px.socket_watch)
Message_box("replacing logic");
// write actual offset
logic_structs[socket_id]->logic[1] = ad;
// write reference for change script checks later - i.e. FN_context_chosen_script
logic_structs[socket_id]->logic_ref[1] = ad;
logic_structs[socket_id]->logic_level = 1; // reset to level 1
logic_structs[socket_id]->looping = 0; // reset logic
// if a mega then cancel interacting
if (logic_structs[socket_id]->image_type == VOXEL)
logic_structs[socket_id]->mega->interacting = 0;
logic_structs[socket_id]->do_not_disturb = 3; // object will not be caught by events this cycle - events pending will be cleared
return (IR_CONT);
}
}
// didnt find the script in the target
// shut that object down as its full of holes!
Fatal_error("socket_force_new_logic cant find script - obj %s, script %s", socket_object->GetName(), script_name);
return (IR_TERMINATE);
}
const char *default_palette = "default";
const char *default_texture = "material";
const char *default_mesh = "mesh";
mcodeFunctionReturnCodes _game_session::fn_set_voxel_image_path(int32 &, int32 *params) {
// set image_type to VOXEL and create the _vox_image object which inits all the animation set filenames and caps
// we are passed the character name AND the graphic set
// for example, cord, wetsuit
// **this routine inits an object as a voxel object**
// **more precisely, a mega character\actor with either voxel or polygon image to be sent to stage_draw**
// enforce this convention
if (!logic_structs[cur_id]->mega)
Fatal_error("fn_set_voxel_image_path %s is not a mega", object->GetName());
const char *param0Str = (const char *)MemoryUtil::resolvePtr(params[0]);
const char *param1Str = (const char *)MemoryUtil::resolvePtr(params[1]);
// set 'cord'
Set_string(const_cast<char *>(param0Str), logic_structs[cur_id]->mega->chr_name, MAX_CHAR_NAME_LENGTH);
// set 'casual_wear'
Set_string(const_cast<char *>(param1Str), logic_structs[cur_id]->mega->anim_set, MAX_OUTFIT_NAME_LENGTH);
// create _vox_image object
if (!logic_structs[cur_id]->voxel_info) {
// assign a struct
logic_structs[cur_id]->voxel_info = &vox_images[num_vox_images];
num_vox_images++;
}
logic_structs[cur_id]->voxel_info->___init(param0Str, param1Str, logic_structs[cur_id]->mega->Fetch_pose());
// Set the default texture & palette
logic_structs[cur_id]->voxel_info->Set_palette(default_palette);
logic_structs[cur_id]->voxel_info->Set_texture(default_texture);
logic_structs[cur_id]->voxel_info->Set_mesh(default_mesh);
// set type while here
logic_structs[cur_id]->image_type = VOXEL;
// script continues
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_set_xyz(int32 &, int32 *) {
// set a game objects x,y,z worldspace coords
Fatal_error("[%s] fn_set_xyz - not supported", object->GetName());
return IR_CONT;
}
mcodeFunctionReturnCodes fn_set_pan(int32 &result, int32 *params) {
// set a game objects pan value
return (g_mission->session->fn_set_pan(result, params));
}
mcodeFunctionReturnCodes _game_session::fn_set_pan(int32 &, int32 *) {
// params[0] pan value
Fatal_error("fn_set_pan - not supported");
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_init_from_nico_file(int32 &, int32 * /*params*/) {
// **this is for props - non mega actors**
// set the object position and pan
// if the object does not have a corresponding entry in the positions file then we may ULTIMATELY shut the game object down
// ** we may need to make this a status option via linc **
// no params
_feature_info *start_pos;
Zdebug("fn_init_from_nico_file - %s (cur_id %d)", object->GetName(), cur_id);
if (L->image_type == VOXEL)
Fatal_error("fn_init_from_nico_file called by a mega! [%s] - use fn_init_mega_from_nico", object->GetName());
// fetch tag file for this item
start_pos = (_feature_info *)features->Try_fetch_item_by_name(object->GetName());
if (!start_pos) {
Message_box("fn_init_from_nico_file - missing nico for item %s", object->GetName());
Shut_down_object("fn_init_from_nico_file - missing nico for item");
return IR_STOP;
}
// set coordinates
logic_structs[cur_id]->prop_xyz.x = start_pos->x;
if (start_pos->y < start_pos->floor_y) // nico is under the floor!
logic_structs[cur_id]->prop_xyz.y = start_pos->floor_y;
else
logic_structs[cur_id]->prop_xyz.y = start_pos->y;
logic_structs[cur_id]->prop_xyz.z = start_pos->z;
// set pan
logic_structs[cur_id]->pan = start_pos->direction; // is this right?
logic_structs[cur_id]->prop_interact_pan = start_pos->direction; // this might be more sensible
// set owner floor for things lile fn_on_screen
logic_structs[cur_id]->owner_floor_rect = floor_def->Return_floor_rect(start_pos->x, start_pos->z, start_pos->floor_y, 0);
if (logic_structs[cur_id]->owner_floor_rect == PXNULL) {
Message_box("fn_init_from_nico_file - %s nico not on a legal floor position - object has been shutdown", object->GetName());
Shut_down_object("fn_init_from_nico_file");
return IR_STOP;
}
// prop has coords
logic_structs[cur_id]->prop_coords_set = TRUE8;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_check_for_nico(int32 &result, int32 *) {
// check to see if there is a nico in this objects name
_feature_info *start_pos;
start_pos = (_feature_info *)features->Try_fetch_item_by_name(object->GetName());
if (!start_pos)
result = FALSE8;
else
result = TRUE8;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_init_from_marker_file(int32 &, int32 *) {
// set the object position and pan from an engine created map-marker file
// if the object does not have a corresponding entry in the positions file then we may ULTIMATELY shut the game object down
// ** we may need to make this a status option via linc **
// no params
_map_marker *start_pos;
Zdebug("fn_init_from_marker_file - %s (cur_id %d)", object->GetName(), cur_id);
// if this object does not have a voxel_info struct then we're done here!
if (!logic_structs[cur_id]->voxel_info)
Fatal_error("FN_INIT_FROM_MARKER_FILE fails because object is not registered as a mega.");
// fetch tag file for this item
start_pos = (_map_marker *)markers.Fetch_marker_by_object_name(const_cast<char *>(object->GetName()));
if (!start_pos) {
Message_box("fn_init_from_marker_file missing map marker file entry for item %s. You must edit the markers - dont play the game.", object->GetName());
Shut_down_object("fn_init_from_marker_file");
return IR_STOP;
}
logic_structs[cur_id]->mega->actor_xyz.x = start_pos->x;
logic_structs[cur_id]->mega->actor_xyz.y = start_pos->y;
logic_structs[cur_id]->mega->actor_xyz.z = start_pos->z;
// set pan
logic_structs[cur_id]->pan = start_pos->pan;
// has coords
logic_structs[cur_id]->prop_coords_set = TRUE8;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_init_mega_from_nico(int32 &, int32 *) {
// set the object position and pan from a MAX NICO marker
// no params
_feature_info *start_pos;
Zdebug("fn_init_mega_from_nico - %s (cur_id %d)", object->GetName(), cur_id);
// if this object does not have a voxel_info struct then we're done here!
if (!logic_structs[cur_id]->voxel_info)
Fatal_error("fn_init_mega_from_nico fails because object is not registered as a mega");
// fetch tag file for this item
start_pos = (_feature_info *)features->Try_fetch_item_by_name(object->GetName());
if (!start_pos) {
Message_box("fn_init_mega_from_nico missing nico for item %s", object->GetName());
Shut_down_object("fn_init_mega_from_nico missing nico for item");
return IR_STOP;
}
// set coordinates
logic_structs[cur_id]->mega->actor_xyz.x = start_pos->x;
logic_structs[cur_id]->mega->actor_xyz.y = start_pos->floor_y;
logic_structs[cur_id]->mega->actor_xyz.z = start_pos->z;
// set pan
logic_structs[cur_id]->pan = start_pos->direction;
// has coords
logic_structs[cur_id]->prop_coords_set = TRUE8;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_teleport_to_nico(int32 &, int32 *params) {
// set the object position and pan from a MAX NICO marker
// params 0 name of nico
_feature_info *start_pos;
const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
Zdebug("fn_teleport_to_nico - %s (to %s)", object->GetName(), nico_name);
// if this object does not have a voxel_info struct then we're done here!
if (!logic_structs[cur_id]->voxel_info)
Fatal_error("fn_teleport_to_nico fails because object is not registered as a mega");
// fetch tag file for this item
start_pos = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
if (!start_pos)
Fatal_error("no NICO marker (fn_teleport_to_nico) ob %s, nico %s", object->GetName(), nico_name);
// set coordinates
logic_structs[cur_id]->mega->actor_xyz.x = start_pos->x;
logic_structs[cur_id]->mega->actor_xyz.y = start_pos->floor_y; // Gravitise_y(start_pos->y);
logic_structs[cur_id]->mega->actor_xyz.z = start_pos->z;
// set pan
logic_structs[cur_id]->pan = start_pos->direction;
// for safety
logic_structs[cur_id]->cur_anim_type = __STAND;
logic_structs[cur_id]->anim_pc = 0;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_panless_teleport_to_nico(int32 &, int32 *params) {
// set the object position from a MAX NICO marker
// params 0 name of nico
_feature_info *start_pos;
const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
Zdebug("fn_panless_teleport_to_nico");
// if this object does not have a voxel_info struct then we're done here!
if (!logic_structs[cur_id]->voxel_info)
Fatal_error("fn_panless_teleport_to_nico_ fails because object is not registered as a mega");
// fetch tag file for this item
start_pos = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
if (!start_pos)
Fatal_error("no NICO marker (fn_panless_teleport_to_nico_) ob %s, nico %s", object->GetName(), nico_name);
// set coordinates
logic_structs[cur_id]->mega->actor_xyz.x = start_pos->x;
logic_structs[cur_id]->mega->actor_xyz.y = start_pos->floor_y; // Gravitise_y(start_pos->y);
logic_structs[cur_id]->mega->actor_xyz.z = start_pos->z;
// for safety
logic_structs[cur_id]->cur_anim_type = __STAND;
logic_structs[cur_id]->anim_pc = 0;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_teleport_to_nico_y(int32 &, int32 *params) {
// get y coord from a nico
// params 0 name of nico
_feature_info *start_pos;
const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
Zdebug("fn_teleport_to_nico_y - %s (to %s)", object->GetName(), nico_name);
// if this object does not have a voxel_info struct then we're done here!
if (!logic_structs[cur_id]->voxel_info)
Fatal_error("fn_teleport_to_nico_y fails because object is not registered as a mega");
// fetch tag file for this item
start_pos = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
if (!start_pos)
Fatal_error("no NICO marker (fn_teleport_to_nico_y) ob %s, nico %s", object->GetName(), nico_name);
// set coordinates
logic_structs[cur_id]->mega->actor_xyz.y = start_pos->floor_y; // Gravitise_y(start_pos->y);
// for safety
logic_structs[cur_id]->cur_anim_type = __STAND;
logic_structs[cur_id]->anim_pc = 0;
if (cur_id == player.Fetch_player_id())
Prepare_megas_route_barriers(TRUE8); // update barriers
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_snap_to_nico_y(int32 &, int32 *params) {
// get y from nico
// params 0 name of nico
_feature_info *start_pos;
const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
Zdebug("fn_snap_to_nico_y - %s (to %s)", object->GetName(), nico_name);
// if this object does not have a voxel_info struct then we're done here!
if (!logic_structs[cur_id]->voxel_info)
Fatal_error("fn_snap_to_nico_y fails because object is not registered as a mega");
// fetch tag file for this item
start_pos = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
if (!start_pos)
Fatal_error("no NICO marker (fn_snap_to_nico_y) ob %s, nico %s", object->GetName(), nico_name);
// set coordinates
logic_structs[cur_id]->mega->actor_xyz.y = start_pos->floor_y;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_get_pan_from_nico(int32 &, int32 *params) {
// set the object pan from a MAX NICO marker
// prop or mega
// params 0 name of nico
_feature_info *start_pos;
const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
Zdebug("fn_get_pan_from_nico - %s (nico %s)", object->GetName(), nico_name);
// fetch tag file for this item
start_pos = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
if (!start_pos) {
// item does not have an entry but clearly expects one
// for now, just carry on and log a warning
Zdebug("WARNING missing feature file entry for item %s", object->GetName());
Fatal_error("no NICO marker (fn_get_pan_from_nico) %s", object->GetName());
}
// set pan
logic_structs[cur_id]->pan = start_pos->direction;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_set_player_can_interact(int32 &, int32 *) {
Zdebug("set interact");
L->player_can_interact = TRUE8;
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_set_player_cannot_interact(int32 &, int32 *) {
Zdebug("stop interact");
L->player_can_interact = FALSE8;
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_call_socket(int32 &result, int32 *params) {
// call a script of another object
// the script must be of a run-once and terminate nature
// params 0 ascii name of target object
// 1 ascii name of socket script
int retval;
uint32 script_hash;
const char *target_object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
const char *socket_script_name = (const char *)MemoryUtil::resolvePtr(params[1]);
Zdebug("fn_call_socket - obj %s, script %s", target_object_name, socket_script_name);
if (px.socket_watch)
Message_box("%s fn_call_socket - obj %s, script %s", object->GetName(), target_object_name, socket_script_name);
script_hash = HashString(socket_script_name);
// get target object
socket_object = (c_game_object *)MS->objects->Try_fetch_item_by_name(target_object_name);
if (!socket_object)
Fatal_error("%s call to fn_call_socket - object %s doesnt exist", object->GetName(), target_object_name);
// set socket_id ready for any special socket functions
socket_id = MS->objects->Fetch_item_number_by_name(target_object_name);
if (socket_id == 0xffffffff)
Fatal_error("fn_call_socket couldnt find object [%s]", target_object_name);
// now try and find a script with the passed extention i.e. ???::looping
for (uint32 k = 0; k < socket_object->GetNoScripts(); k++) {
// now check for actual script name
if (script_hash == socket_object->GetScriptNamePartHash(k)) {
Zdebug("calling socket %d", k);
// script k is the one to run
// get the address of the script we want to run
const char *pc = (const char *)scripts->Try_fetch_item_by_hash(socket_object->GetScriptNameFullHash(k));
// run the script - pass its object so vars can be accessed
RunScript(pc, socket_object, &retval);
Zdebug("return val = %d", retval);
result = retval; // pass return value of socket call into result flag
return (IR_CONT);
}
}
Fatal_error("fn_call_socket couldnt find script %s", socket_script_name);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_call_socket_id(int32 &result, int32 *params) {
// call a script of another object
// the script must be of a run-once and terminate nature
// params 0 ID of target object
// 1 ascii name of socket script
int32 ret;
Zdebug("fn_call_socket_id id=%d", params[0]);
const char *socket_script_name = (const char *)MemoryUtil::resolvePtr(params[1]);
Call_socket(params[0], socket_script_name, &ret);
result = ret;
return (IR_CONT);
}
bool8 _game_session::Call_socket(uint32 id, const char *script, int32 *retval) {
// call a script of an object
// the script must be of a run-once and terminate nature
// this routine kept in here as its closely related to fn-call-socket
// we pass id and script name
// engine uses this
uint32 script_hash;
script_hash = HashString(script);
// get target object
socket_object = (c_game_object *)MS->objects->Fetch_item_by_number(id);
if (!socket_object)
Fatal_error("internal Call_socket - named object dont exist");
Zdebug("\nCall_socket - obj %s, script %s", socket_object->GetName(), script);
// set this for socket fn_ functions
socket_id = id;
// now try and find a script with the passed extention i.e. ???::looping
for (uint32 k = 0; k < socket_object->GetNoScripts(); k++) {
// skip past the object:: aspect
// now check for actual script name
if (script_hash == socket_object->GetScriptNamePartHash(k)) {
Zdebug("calling socket %d", k);
// script k is the one to run
// get the address of the script we want to run
const char *pc = (const char *)scripts->Try_fetch_item_by_hash(socket_object->GetScriptNameFullHash(k));
// run the script - pass its object so vars can be accessed
RunScript(pc, socket_object, retval);
return (TRUE8);
}
}
Tdebug("Call_socket_fails.txt", "[%s] couldnt find script [%s] in [%s]", object->GetName(), script, socket_object->GetName());
return (FALSE8);
}
mcodeFunctionReturnCodes _game_session::fn_prop_near_a_mega(int32 &result, int32 *params) {
// check all live megas against the coordinate of this prop for rough distance of param passed
// params 0 address of result variable
// 1 distance away value
uint32 j;
// run through all the objects calling their logic
for (j = 0; j < total_objects; j++) { // object 0 is used
// object must be alive and interactable and a mega
if ((logic_structs[j]->image_type == VOXEL) && (logic_structs[j]->ob_status != OB_STATUS_HELD)) { // not if the object has been manually switched out
if (PXfabs(L->prop_xyz.y - logic_structs[j]->mega->actor_xyz.y) < (200 * REAL_ONE)) { // slack for height calc
if ((PXfabs(L->prop_xyz.x - logic_structs[j]->mega->actor_xyz.x) < (PXreal)params[0]) &&
(PXfabs(L->prop_xyz.z - logic_structs[j]->mega->actor_xyz.z) < (PXreal)params[0])) {
// yes
result = TRUE8;
return (IR_CONT);
}
}
}
}
// no
result = FALSE8;
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_reset_player(int32 &, int32 *) {
// reset the player to standing - useful for after he's been interupted - perhaps after being shot...
player.Reset_player();
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_teleport(int32 &, int32 *params) {
// move the player to another objects coordinate
// params 0 name of target object
// 1 xoff
// 2 zoff
const char *target_object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
Zdebug("\nfn_teleport to %s x%d z%d", target_object_name, params[1], params[2]);
Zdebug("cur_id %d [%s]", cur_id, object->GetName());
// Made this so it takes a special name "from_origin" to indicate that the offset is to be applied
// from 0,0.
if (strcmp(target_object_name, "from_origin") != 0) {
uint32 tar = MS->objects->Fetch_item_number_by_name(target_object_name);
if (tar == 0xffffffff)
Fatal_error("'destination' teleport object [%s] does not exist", target_object_name);
if (!logic_structs[tar]->prop_coords_set)
Fatal_error("fn_teleport by [%s] finds object [%s] is not yet initialised :O - i.e. its not run its init script yet", object->GetName(),
target_object_name);
if (logic_structs[tar]->image_type == PROP) {
Tdebug("teleport.txt", "target prop y=%3.1f - our y=%3.1f", logic_structs[tar]->prop_xyz.y, logic_structs[cur_id]->mega->actor_xyz.y);
Zdebug("y=%3.1f , grav y =%3.1f", logic_structs[tar]->prop_xyz.y, floor_def->Gravitise_y(logic_structs[tar]->prop_xyz.y));
logic_structs[cur_id]->mega->actor_xyz.x = logic_structs[tar]->prop_xyz.x;
logic_structs[cur_id]->mega->actor_xyz.y = floor_def->Gravitise_y(logic_structs[tar]->prop_xyz.y); // logic_structs[tar]->prop_xyz.y;
logic_structs[cur_id]->mega->actor_xyz.z = logic_structs[tar]->prop_xyz.z;
} else { // mega
logic_structs[cur_id]->mega->actor_xyz.x = logic_structs[tar]->mega->actor_xyz.x;
logic_structs[cur_id]->mega->actor_xyz.y = logic_structs[tar]->mega->actor_xyz.y;
logic_structs[cur_id]->mega->actor_xyz.z = logic_structs[tar]->mega->actor_xyz.z;
}
// add offset
logic_structs[cur_id]->mega->actor_xyz.x += (PXfloat)params[1];
logic_structs[cur_id]->mega->actor_xyz.z += (PXfloat)params[2];
} else {
// Absolute jump has been requested, so just set the new x,z for the object to the given values.
logic_structs[cur_id]->mega->actor_xyz.x = (PXfloat)params[1];
logic_structs[cur_id]->mega->actor_xyz.z = (PXfloat)params[2];
}
// set floor rect value - used by stage draw to find indexed camera name
// gotta keep this bang up to date for player history system
floor_def->Set_floor_rect_flag(L);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_teleport_z(int32 &, int32 *params) {
// move the player to another objects Y coordinate
// params 0 name of target object
const char *target_object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
Zdebug("fn_teleport_z to %s", target_object_name);
uint32 tar = MS->objects->Fetch_item_number_by_name(target_object_name);
if (tar == 0xffffffff)
Fatal_error("'destination' teleport object [%s] does not exist", target_object_name);
if (!logic_structs[tar]->prop_coords_set)
Fatal_error("fn_teleport by [%s] finds object [%s] is not yet initialised :O - i.e. its not run its init script yet", object->GetName(), target_object_name);
if (logic_structs[tar]->image_type == PROP) {
logic_structs[cur_id]->mega->actor_xyz.y = floor_def->Gravitise_y(logic_structs[tar]->prop_xyz.y); // logic_structs[tar]->prop_xyz.y;
} else { // mega
logic_structs[cur_id]->mega->actor_xyz.y = logic_structs[tar]->mega->actor_xyz.y;
}
// set floor rect value - used by stage draw to find indexed camera name
// gotta keep this bang up to date for player history system
floor_def->Set_floor_rect_flag(L);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_teleport_y_to_id(int32 &, int32 *params) {
// move the player to another objects Y coordinate
// params 0 ID of target object
Zdebug("fn_teleport_y_to_id to %d", params[0]);
_ASSERT((uint32)params[0] < total_objects);
if (logic_structs[params[0]]->image_type == PROP) {
logic_structs[cur_id]->mega->actor_xyz.y = floor_def->Gravitise_y(logic_structs[params[0]]->prop_xyz.y); // logic_structs[tar]->prop_xyz.y;
} else { // mega
logic_structs[cur_id]->mega->actor_xyz.y = logic_structs[params[0]]->mega->actor_xyz.y;
}
// set floor rect value - used by stage draw to find indexed camera name
// gotta keep this bang up to date for player history system
floor_def->Set_floor_rect_flag(L);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_are_we_on_this_floor(int32 &result, int32 *params) {
// check to see if object is on the floor passed
// params 0 name of floor
uint32 floor_id;
result = FALSE8;
const char *floor_name = (const char *)MemoryUtil::resolvePtr(params[0]);
if (first_session_cycle)
return IR_CONT;
uint32 hash = HashString(floor_name);
floor_id = floor_def->floors->Fetch_item_number_by_hash(hash);
if (floor_id == 0xffffffff)
Fatal_error("fn_are_we_on_this_floor cant locate floor [%s]", floor_name);
if (floor_id == L->owner_floor_rect)
result = TRUE8;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_is_object_on_our_floor(int32 &result, int32 *params) {
// check to see if object is on the floor passed
// params 0 name of object
uint32 id, num_extra, j, cam;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
result = FALSE8;
if (first_session_cycle)
return IR_CONT;
id = objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_is_object_on_our_floor - illegal object [%s]", object_name);
// same camera means same floor
if (floor_to_camera_index[L->owner_floor_rect] == floor_to_camera_index[logic_structs[id]->owner_floor_rect]) {
result = TRUE8;
} else {
// ok, but is our floor linked to theirs?
cam = floor_to_camera_index[L->owner_floor_rect]; // the camera associated with calling objects (my) floor
num_extra = cam_floor_list[cam].num_extra_floors;
for (j = 0; j < num_extra; j++) {
if (cam_floor_list[cam].extra_floors[j] == logic_structs[id]->owner_floor_rect) {
result = TRUE8; // yes - the floors are linked
return IR_CONT;
}
}
}
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_can_mega_see_dead_megas(int32 &result, int32 *) {
// are there dead megas on this megas floor?
uint32 j, cam, num_extra;
for (j = 0; j < number_of_voxel_ids; j++) {
if (cur_id != voxel_id_list[j]) {
if ((logic_structs[voxel_id_list[j]]->mega->dead) && // dead
(logic_structs[voxel_id_list[j]]->ob_status != OB_STATUS_HELD)) { // not held
// found a dead mega who isnt us - is it on our floor?
// same camera means same floor
if (floor_to_camera_index[L->owner_floor_rect] == floor_to_camera_index[logic_structs[voxel_id_list[j]]->owner_floor_rect]) {
result = TRUE8; //
return IR_CONT; // cor, found one
}
// otherwise do a check to see if our camera is linked to others floor
cam = floor_to_camera_index[L->owner_floor_rect];
num_extra = cam_floor_list[cam].num_extra_floors;
for (uint32 k = 0; k < num_extra; k++) {
if (cam_floor_list[cam].extra_floors[k] == logic_structs[voxel_id_list[j]]->owner_floor_rect) {
result = TRUE8; // yes - the floors are linked
return IR_CONT;
}
}
}
}
}
result = FALSE8;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_is_object_on_screen(int32 &result, int32 *params) {
// check to see if object is in current camera space - i.e. will be drawn by actor-draw
// params 0 name of object
uint32 id;
PXvector pos;
bool8 resu = FALSE8;
PXvector filmpos;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
Zdebug("fn_is_object_on_screen [%s]", object_name);
if (!SetOK()) {
result = FALSE8; // no camera as yet
return (IR_CONT);
}
// get object to check
id = objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_is_object_on_screen - illegal object [%s]", object_name);
Zdebug(" id = %d", id);
// mega or prop
if (logic_structs[id]->image_type == PROP) {
Zdebug(" prop");
pos.x = logic_structs[id]->prop_xyz.x;
pos.y = logic_structs[id]->prop_xyz.y; // talks over head rather than from the feet
pos.z = logic_structs[id]->prop_xyz.z;
} else {
Zdebug(" mega");
pos.x = logic_structs[id]->mega->actor_xyz.x;
pos.y = logic_structs[id]->mega->actor_xyz.y; // talks over head rather than from the feet
pos.z = logic_structs[id]->mega->actor_xyz.z;
}
// setup camera
PXcamera &camera = GetCamera();
// compute screen coord
Zdebug(" PXWorldToFilm");
PXWorldToFilm(pos, camera, resu, filmpos);
result = (int32)resu;
Zdebug(" ~PXWorldToFilm");
// Ignore actors who are on the wrong side of the hither plane
if (filmpos.z > -g_actor_hither_plane)
result = 0;
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_are_we_on_screen(int32 &result, int32 *) {
// Similar to the above function but does the check just for the object calling the function, which
// must be a mega character.
// No params.
// Write the call in the debug file.
Zdebug("fn_are_we_on_screen() - object id = %d", cur_id);
// Check if we have a camera set up.
if (!SetOK()) {
result = FALSE8;
return (IR_CONT);
}
// Caller must be a mega. (We can change this if we find we need to.)
if (logic_structs[cur_id]->image_type != VOXEL)
Fatal_error("Non mega object (id=%d) called fn_are_we_on_screen()", cur_id);
result = 0;
if (Object_visible_to_camera(cur_id)) {
bool8 aresult = TRUE8;
PXvector filmPosition;
PXWorldToFilm(M->actor_xyz, set.GetCamera(), aresult, filmPosition);
if (filmPosition.z < -g_actor_hither_plane) {
VECTOR v;
v.vx = (int32)M->actor_xyz.x;
v.vy = (int32)M->actor_xyz.y;
v.vz = (int32)M->actor_xyz.z;
SVECTOR orient;
orient.vx = 0;
orient.vy = 0;
orient.vz = 0;
// finally if this is true then we are okay so on_screen is true
if (QuickActorCull((psxCamera *)&(set.GetCamera()), &v, &orient) != 1)
result = 1;
}
}
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_get_objects_lvar_value(int32 &result, int32 *params) {
// params 0 name of object
// 1 name of lvar
int32 ret;
c_game_object *ob;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
const char *lvar_name = (const char *)MemoryUtil::resolvePtr(params[1]);
Zdebug("fn_get_objects_lvar_value - [%s] [%s]", object_name, lvar_name);
uint32 hash = HashString(object_name);
ob = (c_game_object *)objects->Try_fetch_item_by_hash(hash);
if (!ob)
Fatal_error("fn_get_objects_lvar_value - illegal object [%s]", object_name);
ret = ob->GetVariable(lvar_name);
if (ret == -1)
Fatal_error("%s finds fn_get_objects_lvar_value - target object [%s] doesnt have [%s] lvar", object->GetName(), object_name, lvar_name);
result = ob->GetIntegerVariable(ret);
Zdebug(" var==%d", result);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_set_objects_lvar_value(int32 &, int32 *params) {
// params 0 name of object
// 1 name of lvar
// 2 new value of lvar
int32 var_num;
c_game_object *ob;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
const char *lvar_name = (const char *)MemoryUtil::resolvePtr(params[1]);
Zdebug("[%s] calls fn_set_objects_lvar_value - [%s] [%s, %d]", object->GetName(), object_name, lvar_name, params[2]);
ob = (c_game_object *)objects->Fetch_item_by_name(object_name);
if (!ob)
Fatal_error("fn_set_objects_lvar_value - illegal object [%s]", object_name);
var_num = ob->GetVariable(lvar_name);
if (var_num == -1)
Fatal_error("[%s] fn_set_objects_lvar_value - object [%s] doesnt have [%s] lvar", object->GetName(), object_name, lvar_name);
ob->SetIntegerVariable(var_num, params[2]);
Zdebug(" var==%d", params[2]);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_set_ids_lvar_value(int32 &, int32 *params) {
// params 0 id of object
// 1 name of lvar
// 2 new value of lvar
int32 var_num;
c_game_object *ob;
const char *lvar_name = (const char *)MemoryUtil::resolvePtr(params[1]);
Zdebug("fn_set_ids_lvar_value - [%s] [%s]", objects->Fetch_items_name_by_number(params[0]), lvar_name);
ob = (c_game_object *)objects->Fetch_item_by_number(params[0]);
if (!ob)
Fatal_error("fn_set_ids_lvar_value - illegal object [%d]", params[0]);
var_num = ob->GetVariable(lvar_name);
if (var_num == -1)
Fatal_error("fn_set_ids_lvar_value - object [%d] doesnt have [%s] lvar", params[0], lvar_name);
ob->SetIntegerVariable(var_num, params[2]);
Zdebug(" var==%d", params[2]);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_get_state_flag(int32 &result, int32 *params) {
// params 0 name of object
int32 ret;
c_game_object *ob;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
ob = (c_game_object *)objects->Fetch_item_by_name(object_name);
if (!ob)
Fatal_error("fn_get_state_flag - illegal object [%s]", object_name);
ret = ob->GetVariable("state");
if (ret == -1)
Fatal_error("fn_get_state_flag - object [%s] doesnt have 'state' lvar", object_name);
result = ob->GetIntegerVariable(ret);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_is_object_dead(int32 &result, int32 *params) {
// params 0 name of object
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
uint32 id = objects->Fetch_item_number_by_name(object_name);
if (!logic_structs[id]->mega)
Fatal_error("fn_get_state_flag - object [%s] not mega", object_name);
result = logic_structs[id]->mega->dead;
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_set_weapon(int32 &, int32 *params) {
// change/set the weapon type
// if the new one is not the current then an anim must be played...
// params 0 ascii name of weapon - should be compatible with weapon_text
const char *weapon_name = (const char *)MemoryUtil::resolvePtr(params[0]);
// search the weapon set table
uint32 j;
Zdebug("fn-set-weapon [%s]", weapon_name);
for (j = 0; j < __TOTAL_WEAPONS; j++) {
Zdebug("test [%s]", weapon_text[j]);
if (!strcmp(weapon_name, weapon_text[j])) {
Zdebug("found %d", j);
L->mega->weapon = (__weapon)j;
return (IR_CONT);
}
}
Fatal_error("WARNING - %s specified weapon does not exist [%s]", object->GetName(), weapon_name);
return (IR_STOP);
}
mcodeFunctionReturnCodes _game_session::fn_is_crouching(int32 &result, int32 *) {
// are we crouching yes or no
result = M->Is_crouched();
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_is_an_object_crouching(int32 &result, int32 *params) {
// is an object crouching yes or no
// params 0 name
uint32 id;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
id = objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_is_an_object_crouching - illegal object [%s]", object_name);
// Make sure it is a mega.
if (!logic_structs[id]->mega)
Fatal_error("fn_is_an_object_crouching - object [%s] not a mega", object_name);
result = logic_structs[id]->mega->Is_crouched();
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_is_armed(int32 &result, int32 *) {
// are we armed yes or no
result = Fetch_cur_megas_armed_status();
return IR_CONT;
}
extern _player_stat player_stat_table[__TOTAL_WEAPONS];
mcodeFunctionReturnCodes _game_session::fn_set_pose(int32 &, int32 *params) {
// change/set the weapon type
// set instantly - i.e. init the _vox_image
// params 0 ascii name of pose - should be compatible with weapon_text
// search the weapon set table
uint32 j;
const char *pose_name = (const char *)MemoryUtil::resolvePtr(params[0]);
Zdebug("fn-set-weapon [%s]", pose_name);
for (j = 0; j < __TOTAL_WEAPONS; j++) {
Zdebug("test [%s]", weapon_text[j]);
if (!strcmp(pose_name, weapon_text[j])) {
Zdebug("found %d", j);
L->mega->weapon = (__weapon)j;
// do this here as well as in fn-set-player-pose as its safer in-case of misuse
if (player.Player_exists())
if (cur_id == player.Fetch_player_id())
player.Set_player_status(player_stat_table[j]);
I->___init(M->chr_name, M->anim_set, (__weapon)j); // we pass the person, set names through
return (IR_CONT);
}
}
Fatal_error("WARNING - %s specified weapon does not exist [%s]", object->GetName(), pose_name);
return (IR_STOP);
}
mcodeFunctionReturnCodes _game_session::fn_set_texture(int32 &, int32 *params) {
// fn_set_texture(text)
const char *texture_name = (const char *)MemoryUtil::resolvePtr(params[0]);
L->voxel_info->Set_texture(texture_name);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_set_palette(int32 &, int32 *params) {
const char *palette = (const char *)MemoryUtil::resolvePtr(params[0]);
L->voxel_info->Set_palette(palette);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_set_mesh(int32 &, int32 *params) {
// fn_set_mesh(text)
const char *mesh = (const char *)MemoryUtil::resolvePtr(params[0]);
L->voxel_info->Set_mesh(mesh);
return (IR_CONT);
}
extern _player_stat player_stat_table[__TOTAL_WEAPONS];
mcodeFunctionReturnCodes _game_session::fn_set_player_pose(int32 &, int32 *params) {
// change/set the weapon type
// set instantly - i.e. init the _vox_image
// sets players status to equivelent mode
// params 0 ascii name of pose - should be compatible with weapon_text
// search the weapon set table
uint32 j;
const char *pose_name = (const char *)MemoryUtil::resolvePtr(params[0]);
Zdebug("fn_set_player_pose [%s]", pose_name);
for (j = 0; j < __TOTAL_WEAPONS; j++) {
Zdebug("test [%s]", weapon_text[j]);
if (!strcmp(pose_name, weapon_text[j])) {
Zdebug("found %d", j);
L->mega->weapon = (__weapon)j;
player.Set_player_status(player_stat_table[j]);
player.Push_player_stat(); // because its popped on return from a conversation - hmmm
I->___init(M->chr_name, M->anim_set, (__weapon)j); // we pass the person, set names through
return (IR_CONT);
}
}
Fatal_error("WARNING - fn_set_player_pose %s specified weapon does not exist [%s]", object->GetName(), pose_name);
return (IR_STOP);
}
mcodeFunctionReturnCodes _game_session::fn_set_custom(int32 &, int32 *params) {
// change/set the custom anim type
// if the new one is not the current then an anim must be played...
// params 0 ascii name of custom
const char *custom_name = (const char *)MemoryUtil::resolvePtr(params[0]);
Zdebug("fn_set_custom [%s]", custom_name);
if (!M)
Fatal_error("fn_set_custom finds [%s] is not a mega", object->GetName());
Set_string(custom_name, M->custom_set, MAX_CUSTOM_NAME_LENGTH);
M->custom = TRUE8;
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_message(int32 &, int32 *params) {
const char *message = (const char *)MemoryUtil::resolvePtr(params[0]);
// pc has to muck around to clear sticky ctrl key
// hold until ctrl key released
if ((Read_DI_keys(Common::KEYCODE_LCTRL)) && (!first_session_cycle))
return (IR_REPEAT);
if (params[0] < 256) {
Message_box("%d", params[0]);
} else {
Message_box("%s - %s", object->GetName(), message);
}
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_message_var(int32 &, int32 *params) {
const char *var_name = (const char *)MemoryUtil::resolvePtr(params[0]);
uint32 var = object->GetVariable(var_name);
if (var == 0xffffffff)
Fatal_error("fn_message_var - object %s has no var %s", object->GetName(), var_name);
// pc has to muck around to clear sticky ctrl key
// hold until ctrl key released
if (Read_DI_keys(Common::KEYCODE_LCTRL))
return (IR_REPEAT);
char txt[100];
if (object->IsVariableString(var))
sprintf(txt, "%s=\"%s\"", var_name, object->GetStringVariable(var));
else
sprintf(txt, "%s=%d", var_name, object->GetIntegerVariable(var));
Message_box(txt);
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_trace(int32 &, int32 *) { return (IR_CONT); }
mcodeFunctionReturnCodes _game_session::fn_get_objects_x(int32 &result, int32 *params) {
// return objects x coord
// params 0 name of object
uint32 id;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
id = (uint32)objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_get_objects_x - illegal object [%s]", object_name);
if (logic_structs[id]->image_type == PROP) {
result = (uint32)logic_structs[id]->prop_xyz.x;
} else {
result = (uint32)logic_structs[id]->mega->actor_xyz.x;
}
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_get_objects_y(int32 &result, int32 *params) {
// return objects y coord
// params 0 name of object
uint32 id;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
id = (uint32)objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_get_objects_y - illegal object [%s]", object_name);
if (logic_structs[id]->image_type == PROP) {
result = (uint32)logic_structs[id]->prop_xyz.y;
} else {
result = (uint32)logic_structs[id]->mega->actor_xyz.y;
}
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_get_objects_z(int32 &result, int32 *params) {
// return objects z coord
// params 0 name of object
uint32 id;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
id = (uint32)objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_get_objects_z - illegal object [%s]", object_name);
if (logic_structs[id]->image_type == PROP) {
result = (uint32)logic_structs[id]->prop_xyz.z;
} else {
result = (uint32)logic_structs[id]->mega->actor_xyz.z;
}
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_has_mega_our_height(int32 &result, int32 *params) {
// params 0 name of object
uint32 id;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
// get target
id = (uint32)objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_has_mega_our_height - illegal object [%s]", object_name);
// check its a mega
if (logic_structs[id]->image_type == PROP)
Fatal_error("fn_has_mega_our_height - [%s] not a mega", object_name);
// same y?
if (logic_structs[id]->mega->actor_xyz.y == M->actor_xyz.y)
result = 1; // yes!
else
result = 0; // no
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_near(int32 &result, int32 *params) {
// params 0 name of object
// 1 dist
uint32 id;
PXreal sub1, sub2, len;
PXreal ourx, oury, ourz;
PXreal itsx, itsy, itsz;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
id = (uint32)objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_is_object_dead - illegal object [%s]", object_name);
if (L->image_type == PROP) {
ourx = L->prop_xyz.x;
oury = L->prop_xyz.y;
ourz = L->prop_xyz.z;
} else {
ourx = M->actor_xyz.x;
oury = M->actor_xyz.y;
ourz = M->actor_xyz.z;
}
if (logic_structs[id]->image_type == PROP) {
itsx = logic_structs[id]->prop_xyz.x;
itsy = logic_structs[id]->prop_xyz.y;
itsz = logic_structs[id]->prop_xyz.z;
} else {
itsx = logic_structs[id]->mega->actor_xyz.x;
itsy = logic_structs[id]->mega->actor_xyz.y;
itsz = logic_structs[id]->mega->actor_xyz.z;
}
if (PXfabs(itsy - oury) < (200 * REAL_ONE)) { // slack for height calc
sub1 = itsx - ourx;
sub2 = itsz - ourz;
// dist
len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
if (len < (PXreal)(params[1] * params[1])) {
result = TRUE8;
} else {
result = FALSE8;
}
return (IR_CONT);
} else {
result = FALSE8;
return (IR_CONT);
}
}
mcodeFunctionReturnCodes _game_session::fn_is_mega_near_mega(int32 &result, int32 *params) {
// params 0 name of object
// 1 name of other
// 2 dist
uint32 id, id2;
PXreal sub1, sub2, len;
PXreal ourx, oury, ourz;
PXreal itsx, itsy, itsz;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
const char *other_object_name = (const char *)MemoryUtil::resolvePtr(params[1]);
id = (uint32)objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_is_mega_near_mega - illegal object [%s]", object_name);
id2 = (uint32)objects->Fetch_item_number_by_name(other_object_name);
if (id2 == 0xffffffff)
Fatal_error("fn_is_mega_near_mega - illegal object [%s]", other_object_name);
if (logic_structs[id]->image_type == PROP)
Fatal_error("fn_is_mega_near_mega %s not a mega", object_name);
if (logic_structs[id2]->image_type == PROP)
Fatal_error("fn_is_mega_near_mega %s not a mega", other_object_name);
itsx = logic_structs[id]->mega->actor_xyz.x;
itsy = logic_structs[id]->mega->actor_xyz.y;
itsz = logic_structs[id]->mega->actor_xyz.z;
ourx = logic_structs[id2]->mega->actor_xyz.x;
oury = logic_structs[id2]->mega->actor_xyz.y;
ourz = logic_structs[id2]->mega->actor_xyz.z;
if (PXfabs(itsy - oury) < (200 * REAL_ONE)) { // slack for height calc
sub1 = itsx - ourx;
sub2 = itsz - ourz;
// dist
len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
if (len < (PXreal)(params[2] * params[2]))
result = TRUE8;
else
result = FALSE8;
return IR_CONT;
} else { // failed on height
result = FALSE8;
return IR_CONT;
}
}
mcodeFunctionReturnCodes _game_session::fn_on_screen(int32 &result, int32 * /* params */) {
// no params
result = Object_visible_to_camera(cur_id);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_hold_if_off_screen(int32 &, int32 *) {
// no params
if (L->image_type != VOXEL)
Fatal_error("fn_hold_if_off_screen only works with megas [%s]", object->GetName());
if (!Object_visible_to_camera(cur_id)) {
return (IR_REPEAT);
}
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_object_near_nico(int32 &result, int32 *params) {
// params 0 object name
// 1 nico name
// 2 dist
uint32 id;
_feature_info *nico;
PXreal sub1, sub2, len;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[1]);
id = (uint32)objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_object_near_nico - illegal object [%s]", object_name);
if (logic_structs[id]->image_type == PROP)
Fatal_error("fn_object_near_nico object [%s] is not a mega!", object_name);
// fetch tag file for this item
nico = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
if (!nico)
Fatal_error("fn_object_near_nico cant find nico [%s]", nico_name);
if (PXfabs(logic_structs[id]->mega->actor_xyz.y - nico->y) < (200 * REAL_ONE)) { // slack for height calc
sub1 = logic_structs[id]->mega->actor_xyz.x - nico->x;
sub2 = logic_structs[id]->mega->actor_xyz.z - nico->z;
// dist
len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
if (len < (PXreal)(params[2] * params[2])) {
// near
result = TRUE8;
} else {
result = FALSE8;
}
} else
result = FALSE8; // failed on y
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_add_object_name_to_list(int32 &, int32 *params) {
// params 0 object name
int32 id;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
// check for list overflow
if (L->total_list == MAX_list)
Fatal_error("fn_object_name_to_list [%s] has exceeded list size of %d", object->GetName(), MAX_list);
id = objects->Fetch_item_number_by_name(object_name);
if (id == -1)
Fatal_error("[%s] callling fn_add_object_name_to_list finds [%s] is not a legal object", object->GetName(), object_name);
L->list[L->total_list++] = (uint32)id;
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_add_object_id_to_list(int32 &, int32 *params) {
// params 0 object id
// check for list overflow
if (L->total_list == MAX_list)
Fatal_error("fn_object_id_to_list [%s] has exceeded list size of %d", object->GetName(), MAX_list);
_ASSERT((uint32)params[0] < total_objects);
L->list[L->total_list++] = params[0];
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_lift_process_list(int32 &result, int32 *params) {
// special lift logic function - checks all megas in the lift against named nico
// params 0 name of nico
// 1 distance
// 2 0 top, 1 bottom
// returns FALSE8 did nothing
// TRUE8 someone used lift - ascend or descend
uint32 j;
_feature_info *monica; // or nico to you and i
PXreal sub1, sub2, len;
const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
// check for no people in list! Could be redefined as an error in-fact
if (!L->total_list) {
result = FALSE8; // did nothing
return (IR_CONT);
}
monica = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
if (!monica)
Fatal_error("fn_lift_process_list cant find nico [%s]", nico_name);
for (j = 0; j < L->total_list; j++) {
if (logic_structs[L->list[j]]->image_type != VOXEL)
Fatal_error("fn_lift_process_list finds [%s] is not a mega", (const char *)logic_structs[L->list[j]]->GetName());
if (PXfabs(logic_structs[L->list[j]]->mega->actor_xyz.y - monica->y) < (200 * REAL_ONE)) { // slack for height calc
sub1 = logic_structs[L->list[j]]->mega->actor_xyz.x - monica->x;
sub2 = logic_structs[L->list[j]]->mega->actor_xyz.z - monica->z;
// dist
len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
if (len < (PXreal)(params[1] * params[1])) {
// near
result = TRUE8; // did something
if (params[2]) { // bottom
// Call the function that does the work in the event manager.
g_oEventManager->PostNamedEventToObject(EVENT_LIFT_ASCEND, L->list[j], cur_id);
return (IR_CONT);
} else { // top
g_oEventManager->PostNamedEventToObject(EVENT_LIFT_DESCEND, L->list[j], cur_id);
return (IR_CONT);
}
}
}
}
result = FALSE8; // no action
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_lib_lift_chord_and_chi(int32 &result, int32 *params) {
// special lift platform handler for cord and chi
// look for player being on the lift
// params 0 name of nico (if not using platform coords)
// 1 distance
// 2 0 top, 1 bottom
// returns FALSE8 did nothing
// TRUE8 someone used lift - ascend or descend
_feature_info *monica; // or nico to you and i
PXreal sub1, sub2, len;
PXreal lifty = REAL_ZERO;
bool8 has_platform = FALSE8;
uint32 lift = 0; // lift number in platform list
bool8 hit = FALSE8;
uint32 j = 0;
static int issued_warning = FALSE8;
const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
if (!prev_save_state) { // could not save last go - then cant operate lift either. Player is in a private script
result = FALSE8;
return IR_CONT;
}
monica = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
if (!monica)
Fatal_error("fn_lift_process_list cant find nico [%s]", nico_name);
lifty = monica->y;
// see if the lift has registered a coordinate platform - if so, we use that
for (j = 0; j < num_lifts; j++) {
if (cur_id == lifts[j].id) {
has_platform = TRUE8;
lift = j;
break; // yup - found a platform
}
}
// issue one warning at a time
if ((!has_platform) && (!issued_warning)) {
issued_warning = TRUE8;
Message_box("lift [%s] says please can i have proper platform coords?", object->GetName());
}
if (PXfabs(logic_structs[player.Fetch_player_id()]->mega->actor_xyz.y - lifty) < (200 * REAL_ONE)) { // slack for height calc
if (!has_platform) {
sub1 = logic_structs[player.Fetch_player_id()]->mega->actor_xyz.x - monica->x;
sub2 = logic_structs[player.Fetch_player_id()]->mega->actor_xyz.z - monica->z;
// dist
len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
if (len < (PXreal)(params[1] * params[1]))
hit = TRUE8;
} else { // has a registered platform
if ((logic_structs[player.Fetch_player_id()]->mega->actor_xyz.x >= lifts[lift].x) && // area box method
(logic_structs[player.Fetch_player_id()]->mega->actor_xyz.x <= lifts[lift].x1) &&
(logic_structs[player.Fetch_player_id()]->mega->actor_xyz.z >= lifts[lift].z) &&
(logic_structs[player.Fetch_player_id()]->mega->actor_xyz.z <= lifts[lift].z1))
hit = TRUE8;
}
if (hit) {
// tell player logic - stop ability to interact with anything else
player.stood_on_lift = TRUE8;
if ((player.cur_state.IsButtonSet(__INTERACT)) && (!player.interact_lock) && (player.player_status == STOOD)) {
player.interact_lock = TRUE8;
result = TRUE8; // did something
if (params[2]) { // bottom
// Call the function that does the work in the event manager.
g_oEventManager->PostNamedEventToObject(EVENT_LIFT_ASCEND, player.Fetch_player_id(), cur_id);
return (IR_CONT);
} else { // top
g_oEventManager->PostNamedEventToObject(EVENT_LIFT_DESCEND, player.Fetch_player_id(), cur_id);
return (IR_CONT);
}
}
}
}
result = FALSE8; // no action
return IR_CONT;
}
typedef struct {
uint32 init;
int32 params[4];
} _lift_verify;
_lift_verify lift2s[MAX_session_objects];
mcodeFunctionReturnCodes _game_session::fn_lift2_process(int32 &result, int32 *params) {
// special lift logic function - checks all megas in the lift against named nico
// if no one is here we IR_CONT
// of someone hits the spot we teleport them
// params 0 name of nico
// 1 catch distance
// 2 0 top, 1 bottom
// 3 release distance
// returns FALSE8 did nothing
// TRUE8 someone used lift - ascend or descend
uint32 j = 0;
_feature_info *monica; // or nico to you and i
PXreal sub1, sub2, len;
bool8 hit = FALSE8;
bool8 has_platform = FALSE8;
PXreal lifty = REAL_ZERO;
uint32 lift = 0; // lift number in platform list
static int issued_warning = FALSE8;
const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
static int inited = FALSE8;
if (!inited) {
for (j = 0; j < MAX_session_objects; j++)
lift2s[j].init = 0;
inited = TRUE8;
}
if (!lift2s[cur_id].init) {
lift2s[cur_id].init = TRUE8;
lift2s[cur_id].params[0] = params[0];
lift2s[cur_id].params[1] = params[1];
lift2s[cur_id].params[2] = params[2];
lift2s[cur_id].params[3] = params[3];
}
if (lift2s[cur_id].params[0] != params[0])
Message_box("%s param 0 changed from %d to %d", object->GetName(), lift2s[cur_id].params[0], params[0]);
if (lift2s[cur_id].params[1] != params[1])
Message_box("%s param 1 changed from %d to %d", object->GetName(), lift2s[cur_id].params[1], params[1]);
if (lift2s[cur_id].params[2] != params[2])
Message_box("%s param 2 changed from %d to %d", object->GetName(), lift2s[cur_id].params[2], params[2]);
if (lift2s[cur_id].params[3] != params[3])
Message_box("%s param 3 changed from %d to %d", object->GetName(), lift2s[cur_id].params[3], params[3]);
// check for no people in list! Could be redefined as an error in-fact
if (!L->total_list) {
if (!issued_warning) {
Message_box("lift [%s] says no items in list", object->GetName());
issued_warning = TRUE8;
}
result = FALSE8; // did nothing
return (IR_CONT);
}
// get nico
monica = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
if (!monica)
Fatal_error("fn_lift_process_list cant find nico [%s]", nico_name);
lifty = monica->y;
// see if the lift has registered a coordinate platform - if so, we use that
for (j = 0; j < num_lifts; j++)
if (cur_id == lifts[j].id) {
has_platform = TRUE8;
lift = j;
break; // yup - found a platform
}
// issue one warning at a time
if ((!has_platform) && (!issued_warning)) {
issued_warning = TRUE8;
Message_box("lift [%s] says please can i have proper platform coords?", object->GetName());
}
for (j = 0; j < L->total_list; j++) {
if (logic_structs[L->list[j]]->image_type != VOXEL)
Fatal_error("fn_lift_process_list finds [%s] is not a mega", (const char *)logic_structs[L->list[j]]->GetName());
if (logic_structs[L->list[j]]->mega->dead)
continue;
if (PXfabs(logic_structs[L->list[j]]->mega->actor_xyz.y - lifty) < (200 * REAL_ONE)) { // slack for height calc
sub1 = logic_structs[L->list[j]]->mega->actor_xyz.x - monica->x;
sub2 = logic_structs[L->list[j]]->mega->actor_xyz.z - monica->z;
// dist
len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
// are we inside release distance
if (len < (PXreal)(params[3] * params[3])) {
hit = TRUE8; // hurray, we found someone inside the release distance
}
if (((!has_platform) && (len < (PXreal)(params[1] * params[1]))) || // crude inner nico method, or
((logic_structs[L->list[j]]->mega->actor_xyz.x >= lifts[lift].x) && // area box method
(logic_structs[L->list[j]]->mega->actor_xyz.x <= lifts[lift].x1) && (logic_structs[L->list[j]]->mega->actor_xyz.z >= lifts[lift].z) &&
(logic_structs[L->list[j]]->mega->actor_xyz.z <= lifts[lift].z1))) {
if (L->list[j] == player.Fetch_player_id()) {
// tell player logic - stop ability to interact with anything else
player.stood_on_lift = TRUE8;
if ((player.cur_state.IsButtonSet(__INTERACT)) && (!player.interact_lock) && (player.player_status == STOOD)) {
player.interact_lock = TRUE8;
L->list_result = L->list[j]; // save id for later retrieval
// near
Zdebug("%s hits lift", (const char *)logic_structs[L->list[j]]->GetName());
result = TRUE8;
return (IR_CONT);
}
} else { // other megas
L->list_result = L->list[j]; // save id for later retrieval
// near
Zdebug("mega %s hits lift", (const char *)logic_structs[L->list[j]]->GetName());
result = TRUE8;
return (IR_CONT);
}
}
}
}
// someone was within release range so hold
if (hit) {
Zdebug("repeating");
return (IR_REPEAT);
}
L->list_result = 999; // means no one - release
// detected no one so continue in script - which means doors will close
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_wait_for_button(int32 &, int32 *params) {
// wait for specified button
// params 0 button number
// 0 interact
// 1 punch
// 2 forward
// 3 backward
// 4 right
// 5 left
player.Update_input_state();
if ((params[0] == 0) && (player.cur_state.IsButtonSet(__INTERACT)))
return IR_CONT;
if ((params[0] == 1) && (player.cur_state.IsButtonSet(__ATTACK)))
return IR_CONT;
if ((params[0] == 2) && (player.cur_state.momentum == __FORWARD_1))
return IR_CONT;
if ((params[0] == 3) && (player.cur_state.momentum == __BACKWARD_1))
return IR_CONT;
if ((params[0] == 4) && ((player.cur_state.turn == __RIGHT) || (player.cur_state.turn == __HARD_RIGHT)))
return IR_CONT;
if ((params[0] == 5) && ((player.cur_state.turn == __LEFT) || (player.cur_state.turn == __HARD_LEFT)))
return IR_CONT;
return IR_REPEAT;
}
mcodeFunctionReturnCodes _game_session::fn_register_platform_coords(int32 &, int32 *params) {
// register coords of a lift platform
// params 0 x
// 1 z
// 2 x1
// 3 z1
// we'll still take the y from the nico
// safety
if (num_lifts == MAX_lift_platforms)
Fatal_error("too many lifts - max = %d", MAX_lift_platforms);
lifts[num_lifts].id = cur_id; // our id
lifts[num_lifts].x = (PXreal)params[0]; // x
lifts[num_lifts].z = (PXreal)params[1]; // z
lifts[num_lifts].x1 = (PXreal)params[2]; // x1
lifts[num_lifts].z1 = (PXreal)params[3]; // z1
num_lifts++;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_near_list(int32 &result, int32 *params) {
// works from our coordiate
// we can be prop or mega
// targets much be mega
// params 0 dist
uint32 j;
PXreal sub1, sub2, len;
PXreal ourx, oury, ourz;
if (L->image_type == PROP) {
ourx = L->prop_xyz.x;
oury = L->prop_xyz.y;
ourz = L->prop_xyz.z;
} else {
ourx = M->actor_xyz.x;
oury = M->actor_xyz.y;
ourz = M->actor_xyz.z;
}
for (j = 0; j < L->total_list; j++) {
if (logic_structs[L->list[j]]->image_type != VOXEL)
Fatal_error("fn_near_list finds [%s] is not a mega", (const char *)logic_structs[L->list[j]]->GetName());
if (!logic_structs[L->list[j]]->mega->dead) { // alive
Zdebug("%3.2f %3.2f", logic_structs[L->list[j]]->mega->actor_xyz.y, oury);
if (PXfabs(logic_structs[L->list[j]]->mega->actor_xyz.y - oury) < (200 * REAL_ONE)) { // slack for height calc
sub1 = logic_structs[L->list[j]]->mega->actor_xyz.x - ourx;
sub2 = logic_structs[L->list[j]]->mega->actor_xyz.z - ourz;
// dist
len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
if (len < (PXreal)(params[0] * params[0])) {
// near
L->list_result = L->list[j]; // save id for later retrieval
result = TRUE8; // did something
return (IR_CONT);
}
}
}
}
result = FALSE8; // no action
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_get_list_result(int32 &result, int32 *) {
// returns the result of a previous list process based function such as fn_near_list
// no params
result = L->list_result;
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_hold_while_list_near_nico(int32 &result, int32 *params) {
// function holds the script position while a mega from the list of megas registers as being near the named nico
// params 0 nico
// 1 distance
uint32 j;
_feature_info *monica; // or nico to you and i
PXreal sub1, sub2, len;
int32 ret, res;
const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
// check for no people in list! Could be redefined as an error in-fact
if (!L->total_list) {
result = FALSE8; // did nothing
return (IR_CONT);
}
monica = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
if (!monica)
Fatal_error("fn_lift_process_list cant find nico [%s]", nico_name);
for (j = 0; j < L->total_list; j++) {
if (logic_structs[L->list[j]]->image_type != VOXEL)
Fatal_error("fn_hold_while_list_near_nico finds [%s] is not a mega", (const char *)logic_structs[L->list[j]]->GetName());
// ignore people who are dead
res = Call_socket(L->list[j], "give_state", &ret);
if (!res)
Fatal_error("fn_hold_while_list_near_nico - object doesnt have 'give_state' script. Perhaps its not a mega");
if ((!ret) && (PXfabs(logic_structs[L->list[j]]->mega->actor_xyz.y - monica->y) < (200 * REAL_ONE))) { // slack for height calc
sub1 = logic_structs[L->list[j]]->mega->actor_xyz.x - monica->x;
sub2 = logic_structs[L->list[j]]->mega->actor_xyz.z - monica->z;
// dist
len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
if (len < (PXreal)(params[1] * params[1])) {
// near
return (IR_REPEAT);
}
}
}
// no one was near the nico
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_set_watch(int32 &, int32 *params) {
_input *psInputState;
_input sInputState;
// set the camera to follow the named mega
// params 0 name of object
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
uint32 id = objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_set_watch - object [%s] does not exist", object_name);
if (logic_structs[id]->image_type != VOXEL)
Fatal_error("fn_set_watch - object [%s] is not a person!", object_name);
// if setting back to player then cancel the camera overide
if (id == player.Fetch_player_id())
g_mission->camera_follow_id_overide = 0;
else
g_mission->camera_follow_id_overide = id;
// If we are switching back to the player then we need to put the Remora back up if
// it was up when we switched to a manual watch (but only in 3D).
if (px.display_mode == THREED) {
// Check if switching to player.
if (id == player.Fetch_player_id()) {
// If the Remora was active, need to bring it back up.
if (g_mission->remora_save_mode != -1) {
MS->player.Push_control_mode(ACTOR_RELATIVE);
g_oRemora->SetModeOverride((_remora::RemoraMode)g_mission->remora_save_mode);
g_oRemora->ActivateRemora((_remora::RemoraMode)g_mission->remora_save_mode);
MS->player.Set_player_status(REMORA);
MS->player.Update_input_state();
psInputState = MS->player.Fetch_input_state();
g_oRemora->CycleRemoraLogic(*psInputState);
g_mission->remora_save_mode = -1;
}
} else {
// Not switching to player so flag whether or not the Remora is active.
if (g_oRemora->IsActive()) {
// Deactivate it and remember its mode.
g_mission->remora_save_mode = (int32)g_oRemora->GetMode();
g_oRemora->SetMode(_remora::MOTION_SCAN);
g_oRemora->DeactivateRemora(TRUE8);
sInputState.UnSetButton((const ButtonEnums)(0xff));
g_oRemora->CycleRemoraLogic(sInputState);
MS->player.Pop_control_mode();
MS->player.Set_player_status(STOOD);
} else {
g_mission->remora_save_mode = -1;
}
}
}
// Deactivate the Remora.
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_three_sixty_interact(int32 &, int32 *) {
// set object to use the prop 360deg interaction type
if (L->image_type != PROP)
Fatal_error("fn_three_sixty_interact - object [%s] is not a prop!", object->GetName());
L->three_sixty_interact |= THREE_SIXTY_INTERACT;
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_prop_crouch_interact(int32 &, int32 *) {
// set object to use the prop 360deg interaction type
L->three_sixty_interact |= PROP_CROUCH_INTERACT;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_random(int32 &result, int32 *params) {
// return a random number to script
// params 0 largest number possible from choice
result = g_icb->getRandomSource()->getRandomNumber(params[0] - 1);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_change_session(int32 &, int32 *params) {
// change session within the current mission
// params 0 name of session
// params 1 name of new nico
uint32 ret;
const char *ses_name = (const char *)MemoryUtil::resolvePtr(params[0]);
const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[1]);
Tdebug("session_log.txt", "fn_change_session changing to [%s]", ses_name);
g_mission->Set_new_session_name(ses_name);
g_mission->Set_init_nico_name(nico_name);
// save the players 'hits' variable
c_game_object *ob;
ob = (c_game_object *)objects->Fetch_item_by_number(player.Fetch_player_id());
ret = ob->GetVariable("hits");
g_mission->old_hits_value = ob->GetIntegerVariable(ret);
return (IR_STOP); // do no more
}
mcodeFunctionReturnCodes _game_session::fn_changed_sessions(int32 &result, int32 *) {
// look for nico name logged by fn_change_session
// if found init there
// return yes or no
_feature_info *nico;
uint32 ret;
result = g_mission->Is_there_init_nico();
if (result) { // nico is waiting Removed explicit test against TRUE8 to get rid of VC5 warning
nico = (_feature_info *)features->Try_fetch_item_by_name(g_mission->Return_init_nico_name());
if (!nico)
Fatal_error("fn_changed_sessions cant find nico [%s]", g_mission->Return_init_nico_name());
#define XX logic_structs[cur_id]->mega->actor_xyz.x
#define ZZ logic_structs[cur_id]->mega->actor_xyz.z
logic_structs[cur_id]->mega->actor_xyz.x = nico->x;
logic_structs[cur_id]->mega->actor_xyz.y = nico->floor_y;
logic_structs[cur_id]->mega->actor_xyz.z = nico->z;
// set pan
logic_structs[cur_id]->pan = nico->direction;
// reset current hits from previous session
ret = object->GetVariable("hits");
object->SetIntegerVariable(ret, g_mission->old_hits_value);
// has coords
logic_structs[cur_id]->prop_coords_set = TRUE8;
// move player forwards a little
if (cur_id == objects->Fetch_item_number_by_name("chi")) {
// we are the player then jump player in-front of chi
PXfloat ang = nico->direction * TWO_PI;
PXfloat cang = (PXfloat)PXcos(ang);
PXfloat sang = (PXfloat)PXsin(ang);
XX += PXfloat2PXreal((75 * REAL_ONE) * sang);
ZZ += PXfloat2PXreal((75 * REAL_ONE) * cang);
}
}
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_changed_via_this_shaft(int32 &result, int32 *params) {
// a lib_session_changer_lift checks to see if its marker was the one that the player started the session on
// if so then the lift knows that it was the lift that has just arrived and therefore it is here and open
// params 0 name of our marker
const char *marker_name = (const char *)MemoryUtil::resolvePtr(params[0]);
if (g_mission->Is_there_init_nico()) {
// there is a nico
// is it ours
if (!strcmp(marker_name, g_mission->Return_init_nico_name())) {
// yes!
result = 1;
return IR_CONT;
}
}
result = 0; // no
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_is_object_adjacent(int32 &result, int32 *params) {
// is the name object on a floor adjacent to this objects floor
// params 0 name of object
_floor *our_floor;
uint32 their_floor;
uint32 id;
uint32 j;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
our_floor = floor_def->Fetch_floor_number(L->owner_floor_rect);
if (!our_floor->num_neighbours) {
result = FALSE8; // cant be adjacent as there are non - which is impossible of course but hey
return (IR_CONT);
}
id = objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_is_object_on_our_floor - illegal object [%s]", object_name);
their_floor = logic_structs[id]->owner_floor_rect;
// are they on our floor - haha
if (their_floor == L->owner_floor_rect) { //
result = FALSE8; //
return (IR_CONT);
}
// check each neighbour
for (j = 0; j < our_floor->num_neighbours; j++) {
if (our_floor->neighbour_map[j].neighbour == their_floor) {
result = TRUE8;
return (IR_CONT);
}
}
result = FALSE8;
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_is_object_on_this_floor(int32 &result, int32 *params) {
// check to see if object is on the floor passed
// params 0 name of object
// 1 name of floor
uint32 floor_id;
uint32 id;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
const char *floor_name = (const char *)MemoryUtil::resolvePtr(params[1]);
Zdebug("fn_is_object_on_this_floor [%s], [%s]", object_name, floor_name);
id = objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_is_object_on_our_floor - illegal object [%s]", object_name);
floor_id = floor_def->floors->Fetch_item_number_by_name(floor_name);
if (floor_id == 0xffffffff)
Fatal_error("fn_are_we_on_this_floor cant locate floor [%s]", floor_name);
if (floor_id == logic_structs[id]->owner_floor_rect)
result = TRUE8;
else
result = FALSE8;
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_switch_on_the_really_neat_and_special_script_debugging_facility(int32 &result, int32 *params) {
// switch on daves debugging
bool8 flag = (params[0] == 0) ? FALSE8 : TRUE8;
Zdebug("\n\n****** switching ON script debugging *******\n\n");
SetScriptDebugging(flag);
result = 0;
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_switch_off_the_really_neat_and_special_script_debugging_facility(int32 &result, int32 *) {
// switch off daves debugging
Zdebug("\n\n------ switching OFF script debugging ------\n\n");
SetScriptDebugging(FALSE8);
result = 0;
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_preload_custom_mega_anim(int32 &result, int32 *params) {
// set a resource loading
// we have devided fn_functions into types (i.e. mega animations) in-case there are cluster complications
// params 0 name of final anim
return (fn_prime_custom_anim(result, params));
}
mcodeFunctionReturnCodes _game_session::fn_no_logic(int32 &, int32 *) {
// set wait_status to no-logic which stops the script being invoked
Tdebug("logic_modes.txt", "fn_no_logic freezing [%s]", object->GetName());
L->big_mode = __NO_LOGIC;
L->cycle_time = 0; // for mt display
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_set_sleep(int32 &, int32 *params) {
// add or remove no-logic
// params 0 name
// 1 0 off, 1 on
uint32 id;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
id = objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_set_sleep - illegal object [%s]", object_name);
if (params[1]) {
logic_structs[id]->big_mode = __NO_LOGIC;
logic_structs[id]->cycle_time = 0; // for mt display
} else {
logic_structs[id]->big_mode = __SCRIPT;
}
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_mega_use_lift(int32 &, int32 *params) {
// trigger a lift - manually
// no safety checking here - scripts must assure all is in right position, etc.
// just set a request flag - putting in function gives us scope for seamless future changes
// params 0 name of lift
c_game_object *ob;
uint32 var_num;
const char *lift_name = (const char *)MemoryUtil::resolvePtr(params[0]);
ob = (c_game_object *)objects->Fetch_item_by_name(lift_name);
if (!ob)
Fatal_error("fn_use_lift - illegal object [%s]", lift_name);
var_num = ob->GetVariable("request");
if (var_num == (uint32)-1)
Fatal_error("fn_use_lift - object [%s] doesnt have REQUEST variable", lift_name);
ob->SetIntegerVariable(var_num, 2); // two is trigger value
return (IR_CONT);
}
// fn_make_remora_beep(1) makes the remora beep notice us, 0 makes it not do...
mcodeFunctionReturnCodes _game_session::fn_make_remora_beep(int32 &, int32 *params) {
if (logic_structs[cur_id]->image_type != VOXEL)
Fatal_error("fn_make_remora_beep - object %s is not a person! what is this?", object->GetName());
if (params[0] == 0) {
L->mega->make_remora_beep = FALSE8;
Zdebug("%s->fn_make_remora_beep(no beep)\n", object->GetName());
} else if (params[0] == 1) {
L->mega->make_remora_beep = TRUE8;
Zdebug("%s->fn_make_remora_beep(beep)\n", object->GetName());
} else
Fatal_error("fn_make_remora_beep - object [%s] called with value %d", object->GetName(), params[0]);
return (IR_CONT);
}
// fn_set_evil(1) sets us to evil mode for beeping and possibly scanner, fn_set_evil(0) sets us to harmless
mcodeFunctionReturnCodes _game_session::fn_set_evil(int32 &, int32 *params) {
if (logic_structs[cur_id]->image_type != VOXEL)
Fatal_error("fn_set_evil - object %s is not a person! what is this?", object->GetName());
if (params[0] == 0) {
L->mega->is_evil = FALSE8;
Zdebug("%s->fn_set_evil(NOT_EVIL!)\n", object->GetName());
} else if (params[0] == 1) {
L->mega->is_evil = TRUE8;
Zdebug("%s->fn_set_evil(EVIL!)\n", object->GetName());
} else
Fatal_error("fn_set_evil - object [%s] called with value %d", object->GetName(), params[0]);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_set_object_type(int32 &, int32 *params) {
// This allows an object to set its type variable. At the moment, this is picked up only by the
// Remora, for the purposes of displaying a suitable symbol, but we may be able to add other
// functionality on it if we require.
logic_structs[cur_id]->object_type = (__object_type)params[0];
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_do_not_disturb(int32 &, int32 *params) {
bool8 bDoNotDisturb;
Zdebug("fn_do_not_disturb( %d ) called by object %d", (uint32)params[0], cur_id);
// Typesafe convert the parameter.
bDoNotDisturb = ((uint32)params[0] == 0) ? FALSE8 : TRUE8;
logic_structs[cur_id]->do_not_disturb = bDoNotDisturb;
// Calling script can continue.
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_is_mega_within_area(int32 &result, int32 *params) {
// is the named object within the specified rect
// params 0 name of object
// 1,2,3,4 x,z, x1,z1
// returns true/false
uint32 id;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
id = (uint32)objects->Fetch_item_number_by_name(object_name);
if (id == 0xffffffff)
Fatal_error("fn_is_mega_within_area - illegal object [%s]", object_name);
if (logic_structs[id]->image_type == PROP)
Fatal_error("fn_is_mega_within_area - object [%s] not a mega", object_name);
if ((logic_structs[id]->mega->actor_xyz.x > (PXreal)params[1]) && (logic_structs[id]->mega->actor_xyz.x < (PXreal)params[3]) &&
(logic_structs[id]->mega->actor_xyz.z > (PXreal)params[2]) && (logic_structs[id]->mega->actor_xyz.z < (PXreal)params[4])) {
result = TRUE8;
} else {
result = FALSE8;
}
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_end_mission(int32 &, int32 *) {
// end the mission and drop back to console, or, the main script
// shhhhhh - make everything quiet
PauseSounds();
g_mission->End_mission();
return IR_STOP;
}
mcodeFunctionReturnCodes _game_session::fn_restart_gamescript(int32 &, int32 *) {
// reset gamescript so that game begins afresh
// presumably first thing in GS will be Start new game/Restore previous screen
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_am_i_player(int32 &result, int32 *) {
// This function returns true if the player calls it, false otherwise. Allows an interact
// script to tell if the player is using it or another mega.
if (cur_id == player.Fetch_player_id())
result = 1;
else
result = 0;
// Calling script can continue.
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_start_conveyor(int32 &, int32 *params) {
// start a conveyor belt
// params 0 x
// 1 y
// 2 z
// 3 x1
// 4 z1
// 5 xm
// 6 zm
uint32 j;
for (j = 0; j < MAX_conveyors; j++) {
if (conveyors[j].moving == FALSE8) {
// found a slot
conveyors[j].x = (PXreal)params[0];
conveyors[j].y = (PXreal)params[1];
conveyors[j].z = (PXreal)params[2];
conveyors[j].x1 = (PXreal)params[3];
conveyors[j].z1 = (PXreal)params[4];
conveyors[j].xm = (PXreal)params[5];
conveyors[j].zm = (PXreal)params[6];
conveyors[j].moving = TRUE8;
Tdebug("conveyor.txt", "conveyor %d = %d,%d,%d %d,%d %d,%d", j, params[0], params[1], params[2], params[3], params[4], params[5], params[6]);
return IR_CONT;
}
}
Fatal_error("too many conveyors!");
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_stop_conveyor(int32 &, int32 *params) {
// stop a conveyor
uint32 j;
for (j = 0; j < MAX_conveyors; j++) {
if (conveyors[j].moving == TRUE8) {
if ((conveyors[j].x == (PXreal)params[0]) && (conveyors[j].z == (PXreal)params[1])) {
Tdebug("conveyor.txt", "conveyor %d stopped", j);
conveyors[j].moving = FALSE8;
return IR_CONT;
}
}
}
Fatal_error("no conveyor @ %d,%d", params[0], params[1]);
return IR_CONT;
}
void _game_session::Process_conveyors() {
uint32 j;
for (j = 0; j < MAX_conveyors; j++) {
if (conveyors[j].moving == TRUE8) {
if ((logic_structs[player.Fetch_player_id()]->mega->actor_xyz.x > conveyors[j].x) &&
(logic_structs[player.Fetch_player_id()]->mega->actor_xyz.y == conveyors[j].y) &&
(logic_structs[player.Fetch_player_id()]->mega->actor_xyz.x < conveyors[j].x1) &&
(logic_structs[player.Fetch_player_id()]->mega->actor_xyz.z > conveyors[j].z) &&
(logic_structs[player.Fetch_player_id()]->mega->actor_xyz.z < conveyors[j].z1)) {
logic_structs[player.Fetch_player_id()]->mega->actor_xyz.x += conveyors[j].xm;
logic_structs[player.Fetch_player_id()]->mega->actor_xyz.z += conveyors[j].zm;
}
}
}
}
mcodeFunctionReturnCodes _game_session::fn_register_ladder(int32 &result, int32 *params) {
// register a ladder
// params 0 target marker name
// 1 1==top (else bottom)
// 2 length
const char *marker_name = (const char *)MemoryUtil::resolvePtr(params[0]);
result = Register_stair_or_ladder(marker_name, (bool8)params[1], params[2], FALSE8, 24);
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_register_stairway(int32 &result, int32 *params) {
// register a stairway
// params 0 target marker name
// 1 1==top (else bottom)
// 2 length
const char *marker_name = (const char *)MemoryUtil::resolvePtr(params[0]);
result = Register_stair_or_ladder(marker_name, (bool8)params[1], params[2], TRUE8, 18);
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_activate_stair_or_ladder(int32 &, int32 *params) {
Set_state_of_stair_or_ladder((uint32)params[0], TRUE8);
return (IR_CONT);
}
mcodeFunctionReturnCodes _game_session::fn_deactivate_stair_or_ladder(int32 &, int32 *params) {
Set_state_of_stair_or_ladder((uint32)params[0], FALSE8);
return (IR_CONT);
}
void _game_session::Set_state_of_stair_or_ladder(uint32 nIndex, bool8 bState) {
if (nIndex > num_stairs)
Fatal_error("Index %d out or range 0-%d in _game_session::Set_state_of_stair_or_ladder()", nIndex, num_stairs - 1);
stairs[nIndex].live = bState;
// do the other end
stairs[stairs[nIndex].opposite_number].live = bState;
}
uint32 _game_session::Register_stair_or_ladder(const char *target, bool8 top, uint32 length, bool8 isstair, uint32 stepcms) {
_feature_info *stair;
_feature_info *dest_stair;
PXreal x1, z1, x2, z2, x3, z3;
uint32 dest_stair_id;
uint8 j = 0;
if (!length)
Fatal_error("%s has 0 length", object->GetName());
if (length > 1000)
Fatal_error("%s has illegal length %d", object->GetName(), length);
// get our nico
stair = (_feature_info *)features->Try_fetch_item_by_name(const_cast<char *>(object->GetName()));
// get other end
dest_stair = (_feature_info *)features->Try_fetch_item_by_name(target);
dest_stair_id = objects->Fetch_item_number_by_name(target);
if (!stair)
Fatal_error("fn_register_stairway - cant find nico %s", object->GetName());
if (!dest_stair)
Fatal_error("fn_register_stairway - cant find nico %s", target);
if (num_stairs == MAX_stairs)
Fatal_error("too many stairs - max = %d", MAX_stairs);
stairs[num_stairs].pan = stair->direction;
stairs[num_stairs].pan_ref = stair->direction;
stairs[num_stairs].x = stair->x;
stairs[num_stairs].z = stair->z;
// link up with other end
for (j = 0; j < num_stairs; j++) {
if (stairs[j].stair_id == dest_stair_id) { // found the target - its already set itself up
stairs[j].opposite_number = (uint8)num_stairs; // its opposite is us
stairs[num_stairs].opposite_number = j; // its our opposite number
break;
}
}
PXfloat ang = stair->direction * TWO_PI;
PXfloat cang = (PXfloat)PXcos(ang);
PXfloat sang = (PXfloat)PXsin(ang);
PXreal dx = PXfloat2PXreal((PXfloat)length * cang);
PXreal dz = PXfloat2PXreal((PXfloat)length * sang);
#define STAIR_BARRIER_OFFSET 0
x1 = stair->x + PXfloat2PXreal(STAIR_BARRIER_OFFSET * sang);
z1 = stair->z + PXfloat2PXreal(STAIR_BARRIER_OFFSET * cang);
x2 = x1 - dx;
z2 = z1 + dz;
x3 = x1 + dx;
z3 = z1 - dz;
// new constructor for barrier...
stairs[num_stairs].bar = _route_barrier(x2, z2, x3, z3, stair->floor_y, (PXreal)0 /* dont care */, BRICK /* dont care */);
// create the BCM maths----------------------------------------------
// The barrier has coordinates x2, z2 to x3, z3.
// Fill in the structure that holds the extra collision maths.
stairs[num_stairs].bar.bcm().Generate(x2, z2, x3, z3);
stairs[num_stairs].bar.Create_pan();
Tdebug("stairs.txt", "try this: %.4f, %g,%g,%g %g,%g %g,%g %g,%g\n", stairs[num_stairs].bar.pan(), stairs[num_stairs].bar.bcm().linedist(),
stairs[num_stairs].bar.bcm().alinedist(), stairs[num_stairs].bar.bcm().blinedist(), stairs[num_stairs].bar.bcm().lpx(), stairs[num_stairs].bar.bcm().lpz(),
stairs[num_stairs].bar.bcm().alpx(), stairs[num_stairs].bar.bcm().alpz(), stairs[num_stairs].bar.bcm().blpx(), stairs[num_stairs].bar.bcm().blpz());
// create the BCM maths----------------------------------------------
// work out unit height
stairs[num_stairs].units = (uint8)((PXfabs(dest_stair->floor_y - stair->floor_y) + (stepcms / 2)) / stepcms);
// dir
if (!top) // if not the top
stairs[num_stairs].up = TRUE8; // then its the bottom which means we're going up
else {
stairs[num_stairs].up = FALSE8; // else down
// top of ladders have their pan adjusted
if (!isstair)
stairs[num_stairs].pan_ref = stair->direction + HALF_TURN;
}
// set id
stairs[num_stairs].stair_id = (uint8)cur_id;
// type
stairs[num_stairs].is_stair = isstair;
// make stair active
stairs[num_stairs].live = TRUE8;
// diagnostics
if (isstair)
Tdebug("stairs.txt", "\nInit stair %d", num_stairs);
else
Tdebug("stairs.txt", "\nInit ladder %d", num_stairs);
Tdebug("stairs.txt", "marker %3.2f,%3.2f, %3.2f", stair->x, stair->floor_y, stair->z);
Tdebug("stairs.txt", "point 1 = %3.2f, %3.2f", x2, z2);
Tdebug("stairs.txt", "point 2 = %3.2f, %3.2f", x3, z3);
Tdebug("stairs.txt", "units = %d", stairs[num_stairs].units);
if (stairs[num_stairs].up)
Tdebug("stairs.txt", "going up");
else
Tdebug("stairs.txt", "going down");
L->list_result = num_stairs; // script needs to get this
return stairs[num_stairs++].units; // set to uploop in object - instead of implementor!
}
mcodeFunctionReturnCodes _game_session::fn_align_with_floor(int32 &, int32 *) {
// mega climbing stairs and ladder calls this afterward to realign with artist misaligned floors
floor_def->Allign_with_floor(M);
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_load_players_gun(int32 &, int32 *params) {
// put bullets in the players gun
player.SetBullets(params[0]);
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_flash_health(int32 &, int32 *) {
// flash the health when you get shot
health_time = 12;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_set_anim_speed(int32 &, int32 *params) {
// set a megas animation playback rate
// params 0 rate
if (logic_structs[cur_id]->image_type != VOXEL)
Fatal_error("fn_set_anim_speed says people only!");
M->anim_speed = (uint8)params[0];
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_push_coords(int32 &, int32 *) {
// push coordinates - used before megas attempt to climb stairs or ladders - for save games
M->pushed = TRUE8;
memcpy(&M->pushed_actor_xyz, &M->actor_xyz, sizeof(PXvector));
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_pop_coords(int32 &, int32 *) {
// remove previous pop
M->pushed = FALSE8;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_quick_restart(int32 &result, int32 *) {
// reset game now or not
// if not then mission ends
// if so then simply reset the player
// if ( MessageBox(windowHandle, "reset player?", "would you like to...", MB_YESNO | MB_DEFBUTTON2 ) == IDYES )
{
result = 1; // do
MS->Restart_player();
}
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_shadows_on(int32 &, int32 *) {
// shadows back on
if (logic_structs[cur_id]->image_type != VOXEL)
Fatal_error("fn_shadows_on says people only!");
M->drawShadow = TRUE8; // shadows back on
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_shadows_off(int32 &, int32 *) {
// shadows back on
if (logic_structs[cur_id]->image_type != VOXEL)
Fatal_error("fn_shadows_off says people only!");
M->drawShadow = FALSE8; // shadows back on
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_set_shade_percentage(int32 &, int32 *params) {
// set shade percentage figure for mega
if (L->image_type != VOXEL)
Fatal_error("fn_set_shade_percentage [%s] says people only!", object->GetName());
if (params[0] > 99)
Fatal_error("fn_set_shade_percentage [%s] percentages usually go 0-99", object->GetName());
M->inShadePercentage = (uint8)params[0];
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_set_half_character_width(int32 &, int32 *params) {
// adjust the default barrier extrapolation for route barriers - for people like spectre who is very big
if (!M)
Fatal_error("fn_set_door_width only for megas [%s]", object->GetName());
M->extrap_size = (uint8)params[0];
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_set_visible(int32 &, int32 *params) {
// set high level on off clip
// params 0 0 off 1 on
if (!M)
Fatal_error("%s fn_set_visible is for megas only", object->GetName());
M->display_me = (bool8)params[0];
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_set_object_visible(int32 &, int32 *params) {
uint32 nObjectID;
const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
// Find the target object's ID.
nObjectID = objects->Fetch_item_number_by_name(object_name);
// Make sure object is a mega character.
if (!(logic_structs[nObjectID]->mega))
Fatal_error("fn_set_object_visible is for megas only");
// Right it is a mega, so set its flag.
logic_structs[nObjectID]->mega->display_me = ((int32)params[1] == 0) ? FALSE8 : TRUE8;
// Calling script can continue.
return (IR_CONT);
}
// fn_set_interact_look_height(h)
// sets the height of an interact object for the looking around code
// the units are cm above the floor...
mcodeFunctionReturnCodes _game_session::fn_set_interact_look_height(int32 &, int32 *params) {
int32 h = params[0];
L->look_height = h;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_set_to_dead(int32 &, int32 *) {
// set the dead flag - we have a flag for speed of access
if (!L->mega)
Fatal_error("fn_set_to_dead called for [%s] but not a mega", object->GetName());
L->mega->dead = TRUE8;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_set_camera_hold(int32 &, int32 *params) {
// switch camera hold mode on or off
if (M)
Fatal_error("fn_set_camera_hold called for [%s] but this is for props only", object->GetName());
// find entry for this object via its name, which we find via its number :(
if (!prop_anims->Try_fetch_item_by_name(object->GetName()))
return IR_CONT; // item has no prop entry - so keep it live
if (params[0])
L->hold_mode = prop_camera_hold;
else
L->hold_mode = none;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_set_mega_wait_for_player(int32 &, int32 *) {
// mega will pause until the player arrives
if (!M)
Fatal_error("fn_set_mega_wait_for_player called for [%s] but not a mega", object->GetName());
L->big_mode = __MEGA_INITIAL_FLOOR_HELD;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_set_mega_off_camera_hold(int32 &, int32 *) {
// mega will pause when not on_camera
if (!M)
Fatal_error("fn_set_mega_off_camera_hold called for [%s] but not a mega", object->GetName());
L->big_mode = __MEGA_PLAYER_FLOOR_HELD;
L->hold_mode = mega_player_floor_hold;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_set_mega_slice_hold(int32 &, int32 *params) {
// mega will pause until the player arrives
// params 0 y distance to stray before character holds again
if (!M)
Fatal_error("fn_set_mega_slice_hold called for [%s] but not a mega", object->GetName());
L->big_mode = __MEGA_SLICE_HELD;
L->hold_mode = mega_slice_hold;
M->slice_hold_tolerance = (uint32)params[0];
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_lock_y(int32 &, int32 *params) {
// lock a y coord of a named nico marker - the floor chooser will use this value. Good for lifts that cross multiple slices, etc
_feature_info *nico;
const char *marker_name = (const char *)MemoryUtil::resolvePtr(params[0]);
nico = (_feature_info *)features->Try_fetch_item_by_name(marker_name);
if (!nico)
Fatal_error("fn_lock_y by [%s] for nico [%s] finds no such nico", object->GetName(), marker_name);
M->y_locked = TRUE8;
M->y_lock = nico->y;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_unlock_y(int32 &, int32 *) {
// cancel locked y
M->y_locked = FALSE8;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_flip_pan(int32 &, int32 *) {
// flip the pan 180deg - used, for example, when megas get off the bottom of ladders
// this is why we are going to engine code this type of logic next time
L->pan += HALF_TURN;
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_snap_to_ladder_bottom(int32 &, int32 *) {
// used to position non player megas going up ladders
#define MEGA_SNAP_UP 40
for (uint8 j = 0; j < num_stairs; j++) {
if (stairs[j].stair_id == M->target_id) { // found the target - its already set itself up
Snap_to_ladder(&stairs[j], MEGA_SNAP_UP);
return IR_CONT;
}
}
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_snap_to_ladder_top(int32 &, int32 *) {
// used to position non player megas going down ladders
#define MEGA_SNAP_DOWN 85
for (uint8 j = 0; j < num_stairs; j++) {
if (stairs[j].stair_id == M->target_id) { // found the target - its already set itself up
Snap_to_ladder(&stairs[j], MEGA_SNAP_DOWN);
return IR_CONT;
}
}
return IR_CONT;
}
mcodeFunctionReturnCodes _game_session::fn_set_to_floor(int32 &, int32 *params) {
// locate a character onto a specified floor
// crudely sticks the character in the middle of the first floor LRECT
// params[0] ascii name of floor
_floor *floor;
const char *floor_name = (const char *)MemoryUtil::resolvePtr(params[0]);
// get the floor
floor = (_floor *)floor_def->Fetch_named_floor(floor_name);
return IR_CONT;
}
} // End of namespace ICB