1 /* ResidualVM - A 3D game interpreter
2  *
3  * ResidualVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the AUTHORS
5  * file distributed with this source distribution.
6  *
7  * Additional copyright for this file:
8  * Copyright (C) 1999-2000 Revolution Software Ltd.
9  * This code is based on source code created by Revolution Software,
10  * used with permission.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25  *
26  */
27 
28 #include "engines/icb/common/px_common.h"
29 #include "engines/icb/common/ptr_util.h"
30 #include "engines/icb/icb.h"
31 #include "engines/icb/p4_generic.h"
32 #include "engines/icb/debug.h"
33 #include "engines/icb/mission.h"
34 #include "engines/icb/global_objects.h"
35 #include "engines/icb/global_switches.h"
36 #include "engines/icb/floors.h"
37 #include "engines/icb/fn_routines.h"
38 #include "engines/icb/p4_generic.h"
39 #include "engines/icb/sound.h" // to get PauseSounds()
40 #include "engines/icb/common/px_scriptengine.h"
41 #include "engines/icb/common/px_floor_map.h"
42 #include "engines/icb/common/px_features.h"
43 #include "engines/icb/direct_input.h"
44 #include "engines/icb/actor.h"
45 #include "engines/icb/remora.h"
46 
47 #include "common/keyboard.h"
48 
49 namespace ICB {
50 
fn_set_voxel_image_path(int32 & result,int32 * params)51 mcodeFunctionReturnCodes fn_set_voxel_image_path(int32 &result, int32 *params) { return (g_mission->session->fn_set_voxel_image_path(result, params)); }
52 
fn_test(int32 & result,int32 * params)53 mcodeFunctionReturnCodes fn_test(int32 &result, int32 *params) { return (g_mission->session->fn_test(result, params)); }
54 
fn_create_mega(int32 & result,int32 * params)55 mcodeFunctionReturnCodes fn_create_mega(int32 &result, int32 *params) { return (g_mission->session->fn_create_mega(result, params)); }
56 
fn_set_xyz(int32 & result,int32 * params)57 mcodeFunctionReturnCodes fn_set_xyz(int32 &result, int32 *params) { return (g_mission->session->fn_set_xyz(result, params)); }
58 
fn_set_to_floor(int32 & result,int32 * params)59 mcodeFunctionReturnCodes fn_set_to_floor(int32 &result, int32 *params) { return (g_mission->session->fn_set_to_floor(result, params)); }
60 
fn_init_from_nico_file(int32 & result,int32 * params)61 mcodeFunctionReturnCodes fn_init_from_nico_file(int32 &result, int32 *params) { return (g_mission->session->fn_init_from_nico_file(result, params)); }
62 
fn_init_from_marker_file(int32 & result,int32 * params)63 mcodeFunctionReturnCodes fn_init_from_marker_file(int32 &result, int32 *params) { return (MS->fn_init_from_marker_file(result, params)); }
64 
fn_set_player_can_interact(int32 & result,int32 * params)65 mcodeFunctionReturnCodes fn_set_player_can_interact(int32 &result, int32 *params) { return (MS->fn_set_player_can_interact(result, params)); }
66 
fn_set_player_cannot_interact(int32 & result,int32 * params)67 mcodeFunctionReturnCodes fn_set_player_cannot_interact(int32 &result, int32 *params) { return (MS->fn_set_player_cannot_interact(result, params)); }
68 
fn_call_socket(int32 & result,int32 * params)69 mcodeFunctionReturnCodes fn_call_socket(int32 &result, int32 *params) { return (MS->fn_call_socket(result, params)); }
70 
fn_prop_near_a_mega(int32 & result,int32 * params)71 mcodeFunctionReturnCodes fn_prop_near_a_mega(int32 &result, int32 *params) { return (MS->fn_prop_near_a_mega(result, params)); }
72 
socket_force_new_logic(int32 & result,int32 * params)73 mcodeFunctionReturnCodes socket_force_new_logic(int32 &result, int32 *params) { return (MS->socket_force_new_logic(result, params)); }
74 
fn_reset_player(int32 & result,int32 * params)75 mcodeFunctionReturnCodes fn_reset_player(int32 &result, int32 *params) { return (MS->fn_reset_player(result, params)); }
76 
fn_rig_test(int32 & result,int32 * params)77 mcodeFunctionReturnCodes fn_rig_test(int32 &result, int32 *params) { return (MS->fn_rig_test(result, params)); }
78 
fn_teleport(int32 & result,int32 * params)79 mcodeFunctionReturnCodes fn_teleport(int32 &result, int32 *params) { return (MS->fn_teleport(result, params)); }
80 
fn_teleport_to_nico(int32 & result,int32 * params)81 mcodeFunctionReturnCodes fn_teleport_to_nico(int32 &result, int32 *params) { return (MS->fn_teleport_to_nico(result, params)); }
82 
fn_get_pan_from_nico(int32 & result,int32 * params)83 mcodeFunctionReturnCodes fn_get_pan_from_nico(int32 &result, int32 *params) { return (MS->fn_get_pan_from_nico(result, params)); }
84 
fn_are_we_on_this_floor(int32 & result,int32 * params)85 mcodeFunctionReturnCodes fn_are_we_on_this_floor(int32 &result, int32 *params) { return (MS->fn_are_we_on_this_floor(result, params)); }
86 
fn_is_object_on_our_floor(int32 & result,int32 * params)87 mcodeFunctionReturnCodes fn_is_object_on_our_floor(int32 &result, int32 *params) { return (MS->fn_is_object_on_our_floor(result, params)); }
88 
fn_is_object_on_screen(int32 & result,int32 * params)89 mcodeFunctionReturnCodes fn_is_object_on_screen(int32 &result, int32 *params) { return (MS->fn_is_object_on_screen(result, params)); }
90 
fn_is_object_dead(int32 & result,int32 * params)91 mcodeFunctionReturnCodes fn_is_object_dead(int32 &result, int32 *params) { return (MS->fn_is_object_dead(result, params)); }
92 
fn_set_weapon(int32 & result,int32 * params)93 mcodeFunctionReturnCodes fn_set_weapon(int32 &result, int32 *params) { return (g_mission->session->fn_set_weapon(result, params)); }
94 
fn_set_custom(int32 & result,int32 * params)95 mcodeFunctionReturnCodes fn_set_custom(int32 &result, int32 *params) { return (g_mission->session->fn_set_custom(result, params)); }
96 
fn_message(int32 & result,int32 * params)97 mcodeFunctionReturnCodes fn_message(int32 &result, int32 *params) { return (g_mission->session->fn_message(result, params)); }
98 
fn_message_var(int32 & result,int32 * params)99 mcodeFunctionReturnCodes fn_message_var(int32 &result, int32 *params) { return (g_mission->session->fn_message_var(result, params)); }
100 
fn_get_state_flag(int32 & result,int32 * params)101 mcodeFunctionReturnCodes fn_get_state_flag(int32 &result, int32 *params) { return (g_mission->session->fn_get_state_flag(result, params)); }
102 
fn_near(int32 & result,int32 * params)103 mcodeFunctionReturnCodes fn_near(int32 &result, int32 *params) { return (g_mission->session->fn_near(result, params)); }
104 
fn_teleport_z(int32 & result,int32 * params)105 mcodeFunctionReturnCodes fn_teleport_z(int32 &result, int32 *params) { return (MS->fn_teleport_z(result, params)); }
106 
fn_on_screen(int32 & result,int32 * params)107 mcodeFunctionReturnCodes fn_on_screen(int32 &result, int32 *params) { return (MS->fn_on_screen(result, params)); }
108 
fn_hold_if_off_screen(int32 & result,int32 * params)109 mcodeFunctionReturnCodes fn_hold_if_off_screen(int32 &result, int32 *params) { return (MS->fn_hold_if_off_screen(result, params)); }
110 
fn_object_near_nico(int32 & result,int32 * params)111 mcodeFunctionReturnCodes fn_object_near_nico(int32 &result, int32 *params) { return (MS->fn_object_near_nico(result, params)); }
112 
fn_teleport_y_to_id(int32 & result,int32 * params)113 mcodeFunctionReturnCodes fn_teleport_y_to_id(int32 &result, int32 *params) { return (MS->fn_teleport_y_to_id(result, params)); }
114 
fn_call_socket_id(int32 & result,int32 * params)115 mcodeFunctionReturnCodes fn_call_socket_id(int32 &result, int32 *params) { return (MS->fn_call_socket_id(result, params)); }
116 
fn_lift_process_list(int32 & result,int32 * params)117 mcodeFunctionReturnCodes fn_lift_process_list(int32 &result, int32 *params) { return (MS->fn_lift_process_list(result, params)); }
118 
fn_add_object_id_to_list(int32 & result,int32 * params)119 mcodeFunctionReturnCodes fn_add_object_id_to_list(int32 &result, int32 *params) { return (MS->fn_add_object_id_to_list(result, params)); }
120 
fn_add_object_name_to_list(int32 & result,int32 * params)121 mcodeFunctionReturnCodes fn_add_object_name_to_list(int32 &result, int32 *params) { return (MS->fn_add_object_name_to_list(result, params)); }
122 
fn_hold_while_list_near_nico(int32 & result,int32 * params)123 mcodeFunctionReturnCodes fn_hold_while_list_near_nico(int32 &result, int32 *params) { return (MS->fn_hold_while_list_near_nico(result, params)); }
124 
fn_set_watch(int32 & result,int32 * params)125 mcodeFunctionReturnCodes fn_set_watch(int32 &result, int32 *params) { return (MS->fn_set_watch(result, params)); }
126 
fn_three_sixty_interact(int32 & result,int32 * params)127 mcodeFunctionReturnCodes fn_three_sixty_interact(int32 &result, int32 *params) { return (MS->fn_three_sixty_interact(result, params)); }
128 
fn_near_list(int32 & result,int32 * params)129 mcodeFunctionReturnCodes fn_near_list(int32 &result, int32 *params) { return (MS->fn_near_list(result, params)); }
130 
fn_get_list_result(int32 & result,int32 * params)131 mcodeFunctionReturnCodes fn_get_list_result(int32 &result, int32 *params) { return (MS->fn_get_list_result(result, params)); }
132 
fn_random(int32 & result,int32 * params)133 mcodeFunctionReturnCodes fn_random(int32 &result, int32 *params) { return (MS->fn_random(result, params)); }
134 
fn_change_session(int32 & result,int32 * params)135 mcodeFunctionReturnCodes fn_change_session(int32 &result, int32 *params) { return (MS->fn_change_session(result, params)); }
136 
fn_changed_sessions(int32 & result,int32 * params)137 mcodeFunctionReturnCodes fn_changed_sessions(int32 &result, int32 *params) { return (MS->fn_changed_sessions(result, params)); }
138 
fn_is_object_adjacent(int32 & result,int32 * params)139 mcodeFunctionReturnCodes fn_is_object_adjacent(int32 &result, int32 *params) { return (MS->fn_is_object_adjacent(result, params)); }
140 
fn_is_object_on_this_floor(int32 & result,int32 * params)141 mcodeFunctionReturnCodes fn_is_object_on_this_floor(int32 &result, int32 *params) { return (MS->fn_is_object_on_this_floor(result, params)); }
142 
fn_get_objects_lvar_value(int32 & result,int32 * params)143 mcodeFunctionReturnCodes fn_get_objects_lvar_value(int32 &result, int32 *params) { return (MS->fn_get_objects_lvar_value(result, params)); }
144 
fn_set_objects_lvar_value(int32 & result,int32 * params)145 mcodeFunctionReturnCodes fn_set_objects_lvar_value(int32 &result, int32 *params) { return (MS->fn_set_objects_lvar_value(result, params)); }
146 
fn_switch_on_the_really_neat_and_special_script_debugging_facility(int32 & result,int32 * params)147 mcodeFunctionReturnCodes fn_switch_on_the_really_neat_and_special_script_debugging_facility(int32 &result, int32 *params) {
148 	return (MS->fn_switch_on_the_really_neat_and_special_script_debugging_facility(result, params));
149 }
150 
fn_switch_off_the_really_neat_and_special_script_debugging_facility(int32 & result,int32 * params)151 mcodeFunctionReturnCodes fn_switch_off_the_really_neat_and_special_script_debugging_facility(int32 &result, int32 *params) {
152 	return (MS->fn_switch_off_the_really_neat_and_special_script_debugging_facility(result, params));
153 }
154 
fn_no_logic(int32 & result,int32 * params)155 mcodeFunctionReturnCodes fn_no_logic(int32 &result, int32 *params) { return (MS->fn_no_logic(result, params)); }
156 
fn_lift2_process(int32 & result,int32 * params)157 mcodeFunctionReturnCodes fn_lift2_process(int32 &result, int32 *params) { return (MS->fn_lift2_process(result, params)); }
158 
fn_preload_custom_mega_anim(int32 & result,int32 * params)159 mcodeFunctionReturnCodes fn_preload_custom_mega_anim(int32 &result, int32 *params) { return (MS->fn_preload_custom_mega_anim(result, params)); }
160 
fn_init_mega_from_nico(int32 & result,int32 * params)161 mcodeFunctionReturnCodes fn_init_mega_from_nico(int32 &result, int32 *params) { return (MS->fn_init_mega_from_nico(result, params)); }
162 
fn_mega_use_lift(int32 & result,int32 * params)163 mcodeFunctionReturnCodes fn_mega_use_lift(int32 &result, int32 *params) { return (MS->fn_mega_use_lift(result, params)); }
164 
fn_snap_to_nico_y(int32 & result,int32 * params)165 mcodeFunctionReturnCodes fn_snap_to_nico_y(int32 &result, int32 *params) { return (MS->fn_snap_to_nico_y(result, params)); }
166 
fn_lib_lift_chord_and_chi(int32 & result,int32 * params)167 mcodeFunctionReturnCodes fn_lib_lift_chord_and_chi(int32 &result, int32 *params) { return (MS->fn_lib_lift_chord_and_chi(result, params)); }
168 
fn_set_interacting(int32 & result,int32 * params)169 mcodeFunctionReturnCodes fn_set_interacting(int32 &result, int32 *params) { return (MS->fn_set_interacting(result, params)); }
170 
fn_clear_interacting(int32 & result,int32 * params)171 mcodeFunctionReturnCodes fn_clear_interacting(int32 &result, int32 *params) { return (MS->fn_clear_interacting(result, params)); }
172 
fn_check_for_nico(int32 & result,int32 * params)173 mcodeFunctionReturnCodes fn_check_for_nico(int32 &result, int32 *params) { return (MS->fn_check_for_nico(result, params)); }
174 
fn_set_ids_lvar_value(int32 & result,int32 * params)175 mcodeFunctionReturnCodes fn_set_ids_lvar_value(int32 &result, int32 *params) { return (MS->fn_set_ids_lvar_value(result, params)); }
176 
fn_teleport_to_nico_y(int32 & result,int32 * params)177 mcodeFunctionReturnCodes fn_teleport_to_nico_y(int32 &result, int32 *params) { return (MS->fn_teleport_to_nico_y(result, params)); }
178 
fn_set_evil(int32 & result,int32 * params)179 mcodeFunctionReturnCodes fn_set_evil(int32 &result, int32 *params) { return (MS->fn_set_evil(result, params)); }
180 
fn_changed_via_this_shaft(int32 & result,int32 * params)181 mcodeFunctionReturnCodes fn_changed_via_this_shaft(int32 &result, int32 *params) { return (MS->fn_changed_via_this_shaft(result, params)); }
182 
fn_get_objects_x(int32 & result,int32 * params)183 mcodeFunctionReturnCodes fn_get_objects_x(int32 &result, int32 *params) { return (MS->fn_get_objects_x(result, params)); }
184 
fn_get_objects_y(int32 & result,int32 * params)185 mcodeFunctionReturnCodes fn_get_objects_y(int32 &result, int32 *params) { return (MS->fn_get_objects_y(result, params)); }
186 
fn_get_objects_z(int32 & result,int32 * params)187 mcodeFunctionReturnCodes fn_get_objects_z(int32 &result, int32 *params) { return (MS->fn_get_objects_z(result, params)); }
188 
fn_are_we_on_screen(int32 & result,int32 * params)189 mcodeFunctionReturnCodes fn_are_we_on_screen(int32 &result, int32 *params) { return (MS->fn_are_we_on_screen(result, params)); }
190 
fn_is_mega_within_area(int32 & result,int32 * params)191 mcodeFunctionReturnCodes fn_is_mega_within_area(int32 &result, int32 *params) { return (MS->fn_is_mega_within_area(result, params)); }
192 
fn_end_mission(int32 & result,int32 * params)193 mcodeFunctionReturnCodes fn_end_mission(int32 &result, int32 *params) { return (MS->fn_end_mission(result, params)); }
194 
fn_set_pose(int32 & result,int32 * params)195 mcodeFunctionReturnCodes fn_set_pose(int32 &result, int32 *params) { return (MS->fn_set_pose(result, params)); }
196 
fn_is_crouching(int32 & result,int32 * params)197 mcodeFunctionReturnCodes fn_is_crouching(int32 &result, int32 *params) { return (MS->fn_is_crouching(result, params)); }
198 
fn_is_armed(int32 & result,int32 * params)199 mcodeFunctionReturnCodes fn_is_armed(int32 &result, int32 *params) { return (MS->fn_is_armed(result, params)); }
200 
fn_am_i_player(int32 & result,int32 * params)201 mcodeFunctionReturnCodes fn_am_i_player(int32 &result, int32 *params) { return (MS->fn_am_i_player(result, params)); }
202 
fn_start_conveyor(int32 & result,int32 * params)203 mcodeFunctionReturnCodes fn_start_conveyor(int32 &result, int32 *params) { return (MS->fn_start_conveyor(result, params)); }
204 
fn_stop_conveyor(int32 & result,int32 * params)205 mcodeFunctionReturnCodes fn_stop_conveyor(int32 &result, int32 *params) { return (MS->fn_stop_conveyor(result, params)); }
206 
fn_register_stairway(int32 & result,int32 * params)207 mcodeFunctionReturnCodes fn_register_stairway(int32 &result, int32 *params) { return (MS->fn_register_stairway(result, params)); }
208 
fn_set_object_type(int32 & result,int32 * params)209 mcodeFunctionReturnCodes fn_set_object_type(int32 &result, int32 *params) { return (MS->fn_set_object_type(result, params)); }
210 
fn_register_ladder(int32 & result,int32 * params)211 mcodeFunctionReturnCodes fn_register_ladder(int32 &result, int32 *params) { return (MS->fn_register_ladder(result, params)); }
212 
fn_is_an_object_crouching(int32 & result,int32 * params)213 mcodeFunctionReturnCodes fn_is_an_object_crouching(int32 &result, int32 *params) { return (MS->fn_is_an_object_crouching(result, params)); }
214 
fn_align_with_floor(int32 & result,int32 * params)215 mcodeFunctionReturnCodes fn_align_with_floor(int32 &result, int32 *params) { return (MS->fn_align_with_floor(result, params)); }
216 
fn_load_players_gun(int32 & result,int32 * params)217 mcodeFunctionReturnCodes fn_load_players_gun(int32 &result, int32 *params) { return (MS->fn_load_players_gun(result, params)); }
218 
fn_flash_health(int32 & result,int32 * params)219 mcodeFunctionReturnCodes fn_flash_health(int32 &result, int32 *params) { return (MS->fn_flash_health(result, params)); }
220 
fn_set_player_pose(int32 & result,int32 * params)221 mcodeFunctionReturnCodes fn_set_player_pose(int32 &result, int32 *params) { return (MS->fn_set_player_pose(result, params)); }
222 
fn_set_anim_speed(int32 & result,int32 * params)223 mcodeFunctionReturnCodes fn_set_anim_speed(int32 &result, int32 *params) { return (MS->fn_set_anim_speed(result, params)); }
224 
fn_push_coords(int32 & result,int32 * params)225 mcodeFunctionReturnCodes fn_push_coords(int32 &result, int32 *params) { return (MS->fn_push_coords(result, params)); }
226 
fn_pop_coords(int32 & result,int32 * params)227 mcodeFunctionReturnCodes fn_pop_coords(int32 &result, int32 *params) { return (MS->fn_pop_coords(result, params)); }
228 
fn_set_texture(int32 & result,int32 * params)229 mcodeFunctionReturnCodes fn_set_texture(int32 &result, int32 *params) { return (MS->fn_set_texture(result, params)); }
230 
fn_set_palette(int32 & result,int32 * params)231 mcodeFunctionReturnCodes fn_set_palette(int32 &result, int32 *params) { return (MS->fn_set_palette(result, params)); }
232 
fn_restart_gamescript(int32 & result,int32 * params)233 mcodeFunctionReturnCodes fn_restart_gamescript(int32 &result, int32 *params) { return (MS->fn_restart_gamescript(result, params)); }
234 
fn_quick_restart(int32 & result,int32 * params)235 mcodeFunctionReturnCodes fn_quick_restart(int32 &result, int32 *params) { return (MS->fn_quick_restart(result, params)); }
236 
fn_is_mega_near_mega(int32 & result,int32 * params)237 mcodeFunctionReturnCodes fn_is_mega_near_mega(int32 &result, int32 *params) { return (MS->fn_is_mega_near_mega(result, params)); }
238 
fn_make_remora_beep(int32 & result,int32 * params)239 mcodeFunctionReturnCodes fn_make_remora_beep(int32 &result, int32 *params) { return (MS->fn_make_remora_beep(result, params)); }
240 
fn_shadows_on(int32 & result,int32 * params)241 mcodeFunctionReturnCodes fn_shadows_on(int32 &result, int32 *params) { return (MS->fn_shadows_on(result, params)); }
242 
fn_shadows_off(int32 & result,int32 * params)243 mcodeFunctionReturnCodes fn_shadows_off(int32 &result, int32 *params) { return (MS->fn_shadows_off(result, params)); }
244 
fn_panless_teleport_to_nico(int32 & result,int32 * params)245 mcodeFunctionReturnCodes fn_panless_teleport_to_nico(int32 &result, int32 *params) { return (MS->fn_panless_teleport_to_nico(result, params)); }
246 
fn_can_mega_see_dead_megas(int32 & result,int32 * params)247 mcodeFunctionReturnCodes fn_can_mega_see_dead_megas(int32 &result, int32 *params) { return (MS->fn_can_mega_see_dead_megas(result, params)); }
248 
fn_set_shade_percentage(int32 & result,int32 * params)249 mcodeFunctionReturnCodes fn_set_shade_percentage(int32 &result, int32 *params) { return (MS->fn_set_shade_percentage(result, params)); }
250 
fn_do_not_disturb(int32 & result,int32 * params)251 mcodeFunctionReturnCodes fn_do_not_disturb(int32 &result, int32 *params) { return (MS->fn_do_not_disturb(result, params)); }
252 
fn_has_mega_our_height(int32 & result,int32 * params)253 mcodeFunctionReturnCodes fn_has_mega_our_height(int32 &result, int32 *params) { return (MS->fn_has_mega_our_height(result, params)); }
254 
fn_register_platform_coords(int32 & result,int32 * params)255 mcodeFunctionReturnCodes fn_register_platform_coords(int32 &result, int32 *params) { return (MS->fn_register_platform_coords(result, params)); }
256 
fn_activate_stair_or_ladder(int32 & result,int32 * params)257 mcodeFunctionReturnCodes fn_activate_stair_or_ladder(int32 &result, int32 *params) { return (MS->fn_activate_stair_or_ladder(result, params)); }
258 
fn_deactivate_stair_or_ladder(int32 & result,int32 * params)259 mcodeFunctionReturnCodes fn_deactivate_stair_or_ladder(int32 &result, int32 *params) { return (MS->fn_deactivate_stair_or_ladder(result, params)); }
260 
fn_set_half_character_width(int32 & result,int32 * params)261 mcodeFunctionReturnCodes fn_set_half_character_width(int32 &result, int32 *params) { return (MS->fn_set_half_character_width(result, params)); }
262 
fn_set_interact_look_height(int32 & result,int32 * params)263 mcodeFunctionReturnCodes fn_set_interact_look_height(int32 &result, int32 *params) { return (MS->fn_set_interact_look_height(result, params)); }
264 
fn_set_visible(int32 & result,int32 * params)265 mcodeFunctionReturnCodes fn_set_visible(int32 &result, int32 *params) { return (MS->fn_set_visible(result, params)); }
266 
fn_set_object_visible(int32 & result,int32 * params)267 mcodeFunctionReturnCodes fn_set_object_visible(int32 &result, int32 *params) { return (MS->fn_set_object_visible(result, params)); }
268 
fn_set_to_dead(int32 & result,int32 * params)269 mcodeFunctionReturnCodes fn_set_to_dead(int32 &result, int32 *params) { return (MS->fn_set_to_dead(result, params)); }
270 
fn_set_camera_hold(int32 & result,int32 * params)271 mcodeFunctionReturnCodes fn_set_camera_hold(int32 &result, int32 *params) { return (MS->fn_set_camera_hold(result, params)); }
272 
fn_set_mega_wait_for_player(int32 & result,int32 * params)273 mcodeFunctionReturnCodes fn_set_mega_wait_for_player(int32 &result, int32 *params) { return (MS->fn_set_mega_wait_for_player(result, params)); }
274 
fn_set_mega_off_camera_hold(int32 & result,int32 * params)275 mcodeFunctionReturnCodes fn_set_mega_off_camera_hold(int32 &result, int32 *params) { return (MS->fn_set_mega_off_camera_hold(result, params)); }
276 
fn_set_mega_slice_hold(int32 & result,int32 * params)277 mcodeFunctionReturnCodes fn_set_mega_slice_hold(int32 &result, int32 *params) { return (MS->fn_set_mega_slice_hold(result, params)); }
278 
fn_set_mesh(int32 & result,int32 * params)279 mcodeFunctionReturnCodes fn_set_mesh(int32 &result, int32 *params) { return (MS->fn_set_mesh(result, params)); }
280 
fn_prop_crouch_interact(int32 & result,int32 * params)281 mcodeFunctionReturnCodes fn_prop_crouch_interact(int32 &result, int32 *params) { return (MS->fn_prop_crouch_interact(result, params)); }
282 
fn_set_sleep(int32 & result,int32 * params)283 mcodeFunctionReturnCodes fn_set_sleep(int32 &result, int32 *params) { return (MS->fn_set_sleep(result, params)); }
284 
fn_wait_for_button(int32 & result,int32 * params)285 mcodeFunctionReturnCodes fn_wait_for_button(int32 &result, int32 *params) { return (MS->fn_wait_for_button(result, params)); }
286 
fn_trace(int32 & result,int32 * params)287 mcodeFunctionReturnCodes fn_trace(int32 &result, int32 *params) { return (MS->fn_trace(result, params)); }
288 
fn_lock_y(int32 & result,int32 * params)289 mcodeFunctionReturnCodes fn_lock_y(int32 &result, int32 *params) { return (MS->fn_lock_y(result, params)); }
290 
fn_unlock_y(int32 & result,int32 * params)291 mcodeFunctionReturnCodes fn_unlock_y(int32 &result, int32 *params) { return (MS->fn_unlock_y(result, params)); }
292 
fn_flip_pan(int32 & result,int32 * params)293 mcodeFunctionReturnCodes fn_flip_pan(int32 &result, int32 *params) { return (MS->fn_flip_pan(result, params)); }
294 
fn_snap_to_ladder_bottom(int32 & result,int32 * params)295 mcodeFunctionReturnCodes fn_snap_to_ladder_bottom(int32 &result, int32 *params) { return (MS->fn_snap_to_ladder_bottom(result, params)); }
296 
fn_snap_to_ladder_top(int32 & result,int32 * params)297 mcodeFunctionReturnCodes fn_snap_to_ladder_top(int32 &result, int32 *params) { return (MS->fn_snap_to_ladder_top(result, params)); }
298 
fn_PLEASE_REUSE_THIS_SLOT_2(int32 &,int32 *)299 mcodeFunctionReturnCodes fn_PLEASE_REUSE_THIS_SLOT_2(int32 &, int32 *) { return IR_CONT; }
300 
fn_PLEASE_REUSE_THIS_SLOT_3(int32 &,int32 *)301 mcodeFunctionReturnCodes fn_PLEASE_REUSE_THIS_SLOT_3(int32 &, int32 *) { return IR_CONT; }
302 
fn_swordfight(int32 & result,int32 * params)303 mcodeFunctionReturnCodes fn_swordfight(int32 &result, int32 *params) { return (MS->fn_swordfight(result, params)); }
304 
fn_swordfight(int32 &,int32 *)305 mcodeFunctionReturnCodes _game_session::fn_swordfight(int32 &, int32 *) { return (IR_CONT); }
306 
fn_set_as_player(int32 & result,int32 * params)307 mcodeFunctionReturnCodes fn_set_as_player(int32 &result, int32 *params) { return (MS->fn_set_as_player(result, params)); }
308 
fn_set_as_player(int32 &,int32 *)309 mcodeFunctionReturnCodes _game_session::fn_set_as_player(int32 &, int32 *) { return (IR_CONT); }
310 
fn_rig_test(int32 &,int32 *)311 mcodeFunctionReturnCodes _game_session::fn_rig_test(int32 &, int32 *) {
312 	//	no params
313 
314 	if (!MS->prev_save_state)
315 		return IR_REPEAT;
316 
317 	return IR_CONT;
318 }
319 
fn_test(int32 &,int32 *)320 mcodeFunctionReturnCodes _game_session::fn_test(int32 & /*result*/, int32 * /*params*/) {
321 #if 0
322 	char buf[256];
323 
324 	sprintf(buf, "z_%s.txt", object->GetName());
325 
326 	if (params[0] < 256)
327 		Tdebug(buf, "%d", params[0]);
328 	else
329 		Tdebug(buf, "%s", params[0]);
330 
331 	result = TRUE8;
332 #endif
333 	return IR_CONT;
334 }
335 
fn_create_mega(int32 &,int32 *)336 mcodeFunctionReturnCodes _game_session::fn_create_mega(int32 &, int32 *) {
337 	Zdebug("FN_create_mega");
338 
339 	// assign _mega object
340 	logic_structs[cur_id]->mega = g_megas[num_megas];
341 
342 	logic_structs[cur_id]->mega->___init();
343 
344 	// set the view state to off camera for this cycle and last cycle
345 	logic_structs[cur_id]->mega->viewState = OFF_OFF_CAMERA;
346 
347 	num_megas++;
348 
349 	if (num_megas == MAX_voxel_list)
350 		Fatal_error("fn_create_mega - too many megas!");
351 
352 	return IR_CONT;
353 }
354 
socket_force_new_logic(int32 &,int32 * params)355 mcodeFunctionReturnCodes _game_session::socket_force_new_logic(int32 &, int32 *params) {
356 	// force in a new logic script mega who owns the socket script
357 	// IGNORES if already running
358 
359 	// params    [0] extension part of script name
360 
361 	char *ad;
362 	uint32 script_hash;
363 	const char *script_name = (const char *)MemoryUtil::resolvePtr(params[0]);
364 
365 	script_hash = HashString(script_name);
366 
367 	if (g_px->socket_watch)
368 		Message_box("socket_force_new_logic - obj %s, script %s", socket_object->GetName(), script_name);
369 
370 	// now try and find a script with the passed extention i.e. ???::looping
371 	for (uint32 k = 0; k < socket_object->GetNoScripts(); k++) {
372 		// now check for actual script name
373 		if (script_hash == socket_object->GetScriptNamePartHash(k)) {
374 			Zdebug("script %d matches", k);
375 			// script k is the one to run
376 			// get the address of the script we want to run
377 			ad = (char *)scripts->Try_fetch_item_by_hash(socket_object->GetScriptNameFullHash(k));
378 
379 			if (g_px->socket_watch)
380 				Message_box("replacing logic");
381 
382 			// write actual offset
383 			logic_structs[socket_id]->logic[1] = ad;
384 
385 			// write reference for change script checks later - i.e. FN_context_chosen_script
386 			logic_structs[socket_id]->logic_ref[1] = ad;
387 
388 			logic_structs[socket_id]->logic_level = 1; // reset to level 1
389 
390 			logic_structs[socket_id]->looping = 0; // reset logic
391 
392 			// if a mega then cancel interacting
393 			if (logic_structs[socket_id]->image_type == VOXEL)
394 				logic_structs[socket_id]->mega->interacting = 0;
395 
396 			logic_structs[socket_id]->do_not_disturb = 3; // object will not be caught by events this cycle - events pending will be cleared
397 			return (IR_CONT);
398 		}
399 	}
400 
401 	// didnt find the script in the target
402 	// shut that object down as its full of holes!
403 
404 	Fatal_error("socket_force_new_logic cant find script - obj %s, script %s", socket_object->GetName(), script_name);
405 
406 	return (IR_TERMINATE);
407 }
408 
409 const char *default_palette = "default";
410 const char *default_texture = "material";
411 const char *default_mesh = "mesh";
412 
fn_set_voxel_image_path(int32 &,int32 * params)413 mcodeFunctionReturnCodes _game_session::fn_set_voxel_image_path(int32 &, int32 *params) {
414 	// set image_type to VOXEL and create the _vox_image object which inits all the animation set filenames and caps
415 	// we are passed the character name AND the graphic set
416 	// for example, cord, wetsuit
417 
418 	//	**this routine inits an object as a voxel object**
419 	// **more precisely, a mega character\actor with either voxel or polygon image to be sent to stage_draw**
420 
421 	// enforce this convention
422 	if (!logic_structs[cur_id]->mega)
423 		Fatal_error("fn_set_voxel_image_path %s is not a mega", object->GetName());
424 
425 	const char *param0Str = (const char *)MemoryUtil::resolvePtr(params[0]);
426 	const char *param1Str = (const char *)MemoryUtil::resolvePtr(params[1]);
427 
428 	// set 'cord'
429 	Set_string(const_cast<char *>(param0Str), logic_structs[cur_id]->mega->chr_name, MAX_CHAR_NAME_LENGTH);
430 
431 	// set 'casual_wear'
432 	Set_string(const_cast<char *>(param1Str), logic_structs[cur_id]->mega->anim_set, MAX_OUTFIT_NAME_LENGTH);
433 
434 	// create _vox_image object
435 	if (!logic_structs[cur_id]->voxel_info) {
436 		// assign a struct
437 		logic_structs[cur_id]->voxel_info = g_vox_images[num_vox_images];
438 		num_vox_images++;
439 	}
440 
441 	logic_structs[cur_id]->voxel_info->___init(param0Str, param1Str, logic_structs[cur_id]->mega->Fetch_pose());
442 
443 	// Set the default texture & palette
444 	logic_structs[cur_id]->voxel_info->Set_palette(default_palette);
445 	logic_structs[cur_id]->voxel_info->Set_texture(default_texture);
446 	logic_structs[cur_id]->voxel_info->Set_mesh(default_mesh);
447 
448 	// set type while here
449 	logic_structs[cur_id]->image_type = VOXEL;
450 
451 	// script continues
452 	return IR_CONT;
453 }
454 
fn_set_xyz(int32 &,int32 *)455 mcodeFunctionReturnCodes _game_session::fn_set_xyz(int32 &, int32 *) {
456 	// set a game objects x,y,z worldspace coords
457 
458 	Fatal_error("[%s] fn_set_xyz - not supported", object->GetName());
459 
460 	return IR_CONT;
461 }
462 
fn_set_pan(int32 & result,int32 * params)463 mcodeFunctionReturnCodes fn_set_pan(int32 &result, int32 *params) {
464 	// set a game objects pan value
465 	return (g_mission->session->fn_set_pan(result, params));
466 }
467 
fn_set_pan(int32 &,int32 *)468 mcodeFunctionReturnCodes _game_session::fn_set_pan(int32 &, int32 *) {
469 	//	params[0]    pan value
470 
471 	Fatal_error("fn_set_pan - not supported");
472 	return IR_CONT;
473 }
474 
fn_init_from_nico_file(int32 &,int32 *)475 mcodeFunctionReturnCodes _game_session::fn_init_from_nico_file(int32 &, int32 * /*params*/) {
476 	// **this is for props - non mega actors**
477 	// set the object position and pan
478 	// if the object does not have a corresponding entry in the positions file then we may ULTIMATELY shut the game object down
479 	// ** we may need to make this a status option via linc **
480 
481 	//	no params
482 
483 	_feature_info *start_pos;
484 
485 	Zdebug("fn_init_from_nico_file - %s (cur_id %d)", object->GetName(), cur_id);
486 
487 	if (L->image_type == VOXEL)
488 		Fatal_error("fn_init_from_nico_file called by a mega! [%s] - use fn_init_mega_from_nico", object->GetName());
489 
490 	// fetch tag file for this item
491 	start_pos = (_feature_info *)features->Try_fetch_item_by_name(object->GetName());
492 
493 	if (!start_pos) {
494 		Message_box("fn_init_from_nico_file - missing nico for item %s", object->GetName());
495 		Shut_down_object("fn_init_from_nico_file - missing nico for item");
496 		return IR_STOP;
497 	}
498 
499 	// set coordinates
500 	logic_structs[cur_id]->prop_xyz.x = start_pos->x;
501 
502 	if (start_pos->y < start_pos->floor_y) // nico is under the floor!
503 		logic_structs[cur_id]->prop_xyz.y = start_pos->floor_y;
504 
505 	else
506 		logic_structs[cur_id]->prop_xyz.y = start_pos->y;
507 
508 	logic_structs[cur_id]->prop_xyz.z = start_pos->z;
509 
510 	// set pan
511 	logic_structs[cur_id]->pan = start_pos->direction; // is this right?
512 
513 	logic_structs[cur_id]->prop_interact_pan = start_pos->direction; // this might be more sensible
514 
515 	// set owner floor for things lile fn_on_screen
516 	logic_structs[cur_id]->owner_floor_rect = floor_def->Return_floor_rect(start_pos->x, start_pos->z, start_pos->floor_y, 0);
517 
518 	if (logic_structs[cur_id]->owner_floor_rect == PXNULL) {
519 		Message_box("fn_init_from_nico_file - %s nico not on a legal floor position - object has been shutdown", object->GetName());
520 		Shut_down_object("fn_init_from_nico_file");
521 		return IR_STOP;
522 	}
523 
524 	// prop has coords
525 	logic_structs[cur_id]->prop_coords_set = TRUE8;
526 
527 	return IR_CONT;
528 }
529 
fn_check_for_nico(int32 & result,int32 *)530 mcodeFunctionReturnCodes _game_session::fn_check_for_nico(int32 &result, int32 *) {
531 	// check to see if there is a nico in this objects name
532 
533 	_feature_info *start_pos;
534 
535 	start_pos = (_feature_info *)features->Try_fetch_item_by_name(object->GetName());
536 
537 	if (!start_pos)
538 		result = FALSE8;
539 	else
540 		result = TRUE8;
541 
542 	return IR_CONT;
543 }
544 
fn_init_from_marker_file(int32 &,int32 *)545 mcodeFunctionReturnCodes _game_session::fn_init_from_marker_file(int32 &, int32 *) {
546 	// set the object position and pan from an engine created map-marker file
547 
548 	// if the object does not have a corresponding entry in the positions file then we may ULTIMATELY shut the game object down
549 	// ** we may need to make this a status option via linc **
550 
551 	//	no params
552 
553 	_map_marker *start_pos;
554 
555 	Zdebug("fn_init_from_marker_file - %s (cur_id %d)", object->GetName(), cur_id);
556 
557 	// if this object does not have a voxel_info struct then we're done here!
558 	if (!logic_structs[cur_id]->voxel_info)
559 		Fatal_error("FN_INIT_FROM_MARKER_FILE fails because object is not registered as a mega.");
560 
561 	// fetch tag file for this item
562 	start_pos = (_map_marker *)markers.Fetch_marker_by_object_name(const_cast<char *>(object->GetName()));
563 
564 	if (!start_pos) {
565 		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());
566 		Shut_down_object("fn_init_from_marker_file");
567 		return IR_STOP;
568 	}
569 
570 	logic_structs[cur_id]->mega->actor_xyz.x = start_pos->x;
571 	logic_structs[cur_id]->mega->actor_xyz.y = start_pos->y;
572 	logic_structs[cur_id]->mega->actor_xyz.z = start_pos->z;
573 
574 	// set pan
575 	logic_structs[cur_id]->pan = start_pos->pan;
576 
577 	// has coords
578 	logic_structs[cur_id]->prop_coords_set = TRUE8;
579 
580 	return IR_CONT;
581 }
582 
fn_init_mega_from_nico(int32 &,int32 *)583 mcodeFunctionReturnCodes _game_session::fn_init_mega_from_nico(int32 &, int32 *) {
584 	// set the object position and pan from a MAX NICO marker
585 
586 	//	no params
587 
588 	_feature_info *start_pos;
589 
590 	Zdebug("fn_init_mega_from_nico - %s (cur_id %d)", object->GetName(), cur_id);
591 
592 	// if this object does not have a voxel_info struct then we're done here!
593 	if (!logic_structs[cur_id]->voxel_info)
594 		Fatal_error("fn_init_mega_from_nico fails because object is not registered as a mega");
595 
596 	// fetch tag file for this item
597 	start_pos = (_feature_info *)features->Try_fetch_item_by_name(object->GetName());
598 
599 	if (!start_pos) {
600 		Message_box("fn_init_mega_from_nico missing nico for item %s", object->GetName());
601 		Shut_down_object("fn_init_mega_from_nico missing nico for item");
602 		return IR_STOP;
603 	}
604 
605 	// set coordinates
606 	logic_structs[cur_id]->mega->actor_xyz.x = start_pos->x;
607 	logic_structs[cur_id]->mega->actor_xyz.y = start_pos->floor_y;
608 	logic_structs[cur_id]->mega->actor_xyz.z = start_pos->z;
609 
610 	// set pan
611 	logic_structs[cur_id]->pan = start_pos->direction;
612 
613 	// has coords
614 	logic_structs[cur_id]->prop_coords_set = TRUE8;
615 
616 	return IR_CONT;
617 }
618 
fn_teleport_to_nico(int32 &,int32 * params)619 mcodeFunctionReturnCodes _game_session::fn_teleport_to_nico(int32 &, int32 *params) {
620 	// set the object position and pan from a MAX NICO marker
621 
622 	//	params 0     name of nico
623 
624 	_feature_info *start_pos;
625 
626 	const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
627 
628 	Zdebug("fn_teleport_to_nico - %s (to %s)", object->GetName(), nico_name);
629 
630 	// if this object does not have a voxel_info struct then we're done here!
631 	if (!logic_structs[cur_id]->voxel_info)
632 		Fatal_error("fn_teleport_to_nico fails because object is not registered as a mega");
633 
634 	// fetch tag file for this item
635 	start_pos = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
636 	if (!start_pos)
637 		Fatal_error("no NICO marker (fn_teleport_to_nico) ob %s, nico %s", object->GetName(), nico_name);
638 
639 	// set coordinates
640 	logic_structs[cur_id]->mega->actor_xyz.x = start_pos->x;
641 	logic_structs[cur_id]->mega->actor_xyz.y = start_pos->floor_y; // Gravitise_y(start_pos->y);
642 	logic_structs[cur_id]->mega->actor_xyz.z = start_pos->z;
643 
644 	// set pan
645 	logic_structs[cur_id]->pan = start_pos->direction;
646 
647 	// for safety
648 	logic_structs[cur_id]->cur_anim_type = __STAND;
649 	logic_structs[cur_id]->anim_pc = 0;
650 
651 	return IR_CONT;
652 }
653 
fn_panless_teleport_to_nico(int32 &,int32 * params)654 mcodeFunctionReturnCodes _game_session::fn_panless_teleport_to_nico(int32 &, int32 *params) {
655 	// set the object position from a MAX NICO marker
656 
657 	//	params 0     name of nico
658 
659 	_feature_info *start_pos;
660 
661 	const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
662 
663 	Zdebug("fn_panless_teleport_to_nico");
664 
665 	// if this object does not have a voxel_info struct then we're done here!
666 	if (!logic_structs[cur_id]->voxel_info)
667 		Fatal_error("fn_panless_teleport_to_nico_ fails because object is not registered as a mega");
668 
669 	// fetch tag file for this item
670 	start_pos = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
671 	if (!start_pos)
672 		Fatal_error("no NICO marker (fn_panless_teleport_to_nico_) ob %s, nico %s", object->GetName(), nico_name);
673 
674 	// set coordinates
675 	logic_structs[cur_id]->mega->actor_xyz.x = start_pos->x;
676 	logic_structs[cur_id]->mega->actor_xyz.y = start_pos->floor_y; // Gravitise_y(start_pos->y);
677 	logic_structs[cur_id]->mega->actor_xyz.z = start_pos->z;
678 
679 	// for safety
680 	logic_structs[cur_id]->cur_anim_type = __STAND;
681 	logic_structs[cur_id]->anim_pc = 0;
682 
683 	return IR_CONT;
684 }
685 
fn_teleport_to_nico_y(int32 &,int32 * params)686 mcodeFunctionReturnCodes _game_session::fn_teleport_to_nico_y(int32 &, int32 *params) {
687 	// get y coord from a nico
688 
689 	//	params 0     name of nico
690 
691 	_feature_info *start_pos;
692 
693 	const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
694 
695 	Zdebug("fn_teleport_to_nico_y - %s (to %s)", object->GetName(), nico_name);
696 
697 	// if this object does not have a voxel_info struct then we're done here!
698 	if (!logic_structs[cur_id]->voxel_info)
699 		Fatal_error("fn_teleport_to_nico_y fails because object is not registered as a mega");
700 
701 	// fetch tag file for this item
702 	start_pos = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
703 	if (!start_pos)
704 		Fatal_error("no NICO marker (fn_teleport_to_nico_y) ob %s, nico %s", object->GetName(), nico_name);
705 
706 	// set coordinates
707 	logic_structs[cur_id]->mega->actor_xyz.y = start_pos->floor_y; // Gravitise_y(start_pos->y);
708 
709 	// for safety
710 	logic_structs[cur_id]->cur_anim_type = __STAND;
711 	logic_structs[cur_id]->anim_pc = 0;
712 
713 	if (cur_id == player.Fetch_player_id())
714 		Prepare_megas_route_barriers(TRUE8); // update barriers
715 
716 	return IR_CONT;
717 }
718 
fn_snap_to_nico_y(int32 &,int32 * params)719 mcodeFunctionReturnCodes _game_session::fn_snap_to_nico_y(int32 &, int32 *params) {
720 	// get y from nico
721 
722 	//	params 0     name of nico
723 
724 	_feature_info *start_pos;
725 
726 	const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
727 
728 	Zdebug("fn_snap_to_nico_y - %s (to %s)", object->GetName(), nico_name);
729 
730 	// if this object does not have a voxel_info struct then we're done here!
731 	if (!logic_structs[cur_id]->voxel_info)
732 		Fatal_error("fn_snap_to_nico_y fails because object is not registered as a mega");
733 
734 	// fetch tag file for this item
735 	start_pos = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
736 	if (!start_pos)
737 		Fatal_error("no NICO marker (fn_snap_to_nico_y) ob %s, nico %s", object->GetName(), nico_name);
738 
739 	// set coordinates
740 	logic_structs[cur_id]->mega->actor_xyz.y = start_pos->floor_y;
741 
742 	return IR_CONT;
743 }
744 
fn_get_pan_from_nico(int32 &,int32 * params)745 mcodeFunctionReturnCodes _game_session::fn_get_pan_from_nico(int32 &, int32 *params) {
746 	// set the object pan from a MAX NICO marker
747 	// prop or mega
748 
749 	//	params 0     name of nico
750 
751 	_feature_info *start_pos;
752 
753 	const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
754 
755 	Zdebug("fn_get_pan_from_nico - %s (nico %s)", object->GetName(), nico_name);
756 
757 	// fetch tag file for this item
758 	start_pos = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
759 
760 	if (!start_pos) {
761 		// item does not have an entry but clearly expects one
762 		// for now, just carry on and log a warning
763 		Zdebug("WARNING missing feature file entry for item %s", object->GetName());
764 		Fatal_error("no NICO marker (fn_get_pan_from_nico) %s", object->GetName());
765 	}
766 
767 	// set pan
768 	logic_structs[cur_id]->pan = start_pos->direction;
769 
770 	return IR_CONT;
771 }
772 
fn_set_player_can_interact(int32 &,int32 *)773 mcodeFunctionReturnCodes _game_session::fn_set_player_can_interact(int32 &, int32 *) {
774 	Zdebug("set interact");
775 
776 	L->player_can_interact = TRUE8;
777 
778 	return (IR_CONT);
779 }
780 
fn_set_player_cannot_interact(int32 &,int32 *)781 mcodeFunctionReturnCodes _game_session::fn_set_player_cannot_interact(int32 &, int32 *) {
782 	Zdebug("stop interact");
783 
784 	L->player_can_interact = FALSE8;
785 
786 	return (IR_CONT);
787 }
788 
fn_call_socket(int32 & result,int32 * params)789 mcodeFunctionReturnCodes _game_session::fn_call_socket(int32 &result, int32 *params) {
790 	// call a script of another object
791 	// the script must be of a run-once and terminate nature
792 
793 	//	params   0       ascii name of target object
794 	//				1     ascii name of socket script
795 
796 	int32 retval;
797 	uint32 script_hash;
798 
799 	const char *target_object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
800 	const char *socket_script_name = (const char *)MemoryUtil::resolvePtr(params[1]);
801 
802 	Zdebug("fn_call_socket - obj %s, script %s", target_object_name, socket_script_name);
803 
804 	if (g_px->socket_watch)
805 		Message_box("%s fn_call_socket - obj %s, script %s", object->GetName(), target_object_name, socket_script_name);
806 
807 	script_hash = HashString(socket_script_name);
808 
809 	// get target object
810 	socket_object = (c_game_object *)MS->objects->Try_fetch_item_by_name(target_object_name);
811 	if (!socket_object)
812 		Fatal_error("%s call to fn_call_socket - object %s doesnt exist", object->GetName(), target_object_name);
813 
814 	// set socket_id ready for any special socket functions
815 	socket_id = MS->objects->Fetch_item_number_by_name(target_object_name);
816 	if (socket_id == 0xffffffff)
817 		Fatal_error("fn_call_socket couldnt find object [%s]", target_object_name);
818 
819 	// now try and find a script with the passed extention i.e. ???::looping
820 	for (uint32 k = 0; k < socket_object->GetNoScripts(); k++) {
821 		// now check for actual script name
822 		if (script_hash == socket_object->GetScriptNamePartHash(k)) {
823 			Zdebug("calling socket %d", k);
824 			// script k is the one to run
825 			// get the address of the script we want to run
826 
827 			const char *pc = (const char *)scripts->Try_fetch_item_by_hash(socket_object->GetScriptNameFullHash(k));
828 
829 			// run the script - pass its object so vars can be accessed
830 			RunScript(pc, socket_object, &retval);
831 
832 			Zdebug("return val = %d", retval);
833 
834 			result = retval; // pass return value of socket call into result flag
835 
836 			return (IR_CONT);
837 		}
838 	}
839 
840 	Fatal_error("fn_call_socket couldnt find script %s", socket_script_name);
841 
842 	return (IR_CONT);
843 }
844 
fn_call_socket_id(int32 & result,int32 * params)845 mcodeFunctionReturnCodes _game_session::fn_call_socket_id(int32 &result, int32 *params) {
846 	// call a script of another object
847 	// the script must be of a run-once and terminate nature
848 
849 	//	params   0       ID of target object
850 	//				1     ascii name of socket script
851 
852 	int32 ret;
853 
854 	Zdebug("fn_call_socket_id id=%d", params[0]);
855 
856 	const char *socket_script_name = (const char *)MemoryUtil::resolvePtr(params[1]);
857 
858 	Call_socket(params[0], socket_script_name, &ret);
859 
860 	result = ret;
861 
862 	return (IR_CONT);
863 }
864 
Call_socket(uint32 id,const char * script,int32 * retval)865 bool8 _game_session::Call_socket(uint32 id, const char *script, int32 *retval) {
866 	// call a script of an object
867 	// the script must be of a run-once and terminate nature
868 	// this routine kept in here as its closely related to fn-call-socket
869 	// we pass id and script name
870 
871 	// engine uses this
872 
873 	uint32 script_hash;
874 
875 	script_hash = HashString(script);
876 
877 	// get target object
878 	socket_object = (c_game_object *)MS->objects->Fetch_item_by_number(id);
879 	if (!socket_object)
880 		Fatal_error("internal Call_socket - named object dont exist");
881 
882 	Zdebug("\nCall_socket - obj %s, script %s", socket_object->GetName(), script);
883 
884 	// set this for socket fn_ functions
885 	socket_id = id;
886 
887 	// now try and find a script with the passed extention i.e. ???::looping
888 	for (uint32 k = 0; k < socket_object->GetNoScripts(); k++) {
889 		// skip past the object:: aspect
890 
891 		// now check for actual script name
892 		if (script_hash == socket_object->GetScriptNamePartHash(k)) {
893 			Zdebug("calling socket %d", k);
894 			// script k is the one to run
895 			// get the address of the script we want to run
896 			const char *pc = (const char *)scripts->Try_fetch_item_by_hash(socket_object->GetScriptNameFullHash(k));
897 
898 			int32 result = static_cast<int>(*retval);
899 
900 			// run the script - pass its object so vars can be accessed
901 			RunScript(pc, socket_object, &result);
902 
903 			*retval = result;
904 
905 			return (TRUE8);
906 		}
907 	}
908 
909 	Tdebug("Call_socket_fails.txt", "[%s] couldnt find script [%s] in [%s]", object->GetName(), script, socket_object->GetName());
910 
911 	return (FALSE8);
912 }
913 
fn_prop_near_a_mega(int32 & result,int32 * params)914 mcodeFunctionReturnCodes _game_session::fn_prop_near_a_mega(int32 &result, int32 *params) {
915 	// check all live megas against the coordinate of this prop for rough distance of param passed
916 
917 	//	params   0 address of result variable
918 	//				1 distance away value
919 
920 	uint32 j;
921 
922 	// run through all the objects calling their logic
923 	for (j = 0; j < total_objects; j++) { // object 0 is used
924 		// object must be alive and interactable and a mega
925 		if ((logic_structs[j]->image_type == VOXEL) && (logic_structs[j]->ob_status != OB_STATUS_HELD)) { // not if the object has been manually switched out
926 			if (PXfabs(L->prop_xyz.y - logic_structs[j]->mega->actor_xyz.y) < (200 * REAL_ONE)) {     // slack for height calc
927 				if ((PXfabs(L->prop_xyz.x - logic_structs[j]->mega->actor_xyz.x) < (PXreal)params[0]) &&
928 				    (PXfabs(L->prop_xyz.z - logic_structs[j]->mega->actor_xyz.z) < (PXreal)params[0])) {
929 					// yes
930 					result = TRUE8;
931 					return (IR_CONT);
932 				}
933 			}
934 		}
935 	}
936 
937 	// no
938 	result = FALSE8;
939 	return (IR_CONT);
940 }
941 
fn_reset_player(int32 &,int32 *)942 mcodeFunctionReturnCodes _game_session::fn_reset_player(int32 &, int32 *) {
943 	// reset the player to standing - useful for after he's been interupted - perhaps after being shot...
944 
945 	player.Reset_player();
946 
947 	return (IR_CONT);
948 }
949 
fn_teleport(int32 &,int32 * params)950 mcodeFunctionReturnCodes _game_session::fn_teleport(int32 &, int32 *params) {
951 	// move the player to another objects coordinate
952 
953 	// params        0 name of target object
954 	//				1 xoff
955 	//				2 zoff
956 
957 	const char *target_object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
958 
959 	Zdebug("\nfn_teleport to %s x%d z%d", target_object_name, params[1], params[2]);
960 	Zdebug("cur_id %d [%s]", cur_id, object->GetName());
961 
962 	// Made this so it takes a special name "from_origin" to indicate that the offset is to be applied
963 	// from 0,0.
964 	if (strcmp(target_object_name, "from_origin") != 0) {
965 		uint32 tar = MS->objects->Fetch_item_number_by_name(target_object_name);
966 
967 		if (tar == 0xffffffff)
968 			Fatal_error("'destination' teleport object [%s] does not exist", target_object_name);
969 
970 		if (!logic_structs[tar]->prop_coords_set)
971 			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(),
972 			            target_object_name);
973 
974 		if (logic_structs[tar]->image_type == PROP) {
975 			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);
976 			Zdebug("y=%3.1f , grav y =%3.1f", logic_structs[tar]->prop_xyz.y, floor_def->Gravitise_y(logic_structs[tar]->prop_xyz.y));
977 			logic_structs[cur_id]->mega->actor_xyz.x = logic_structs[tar]->prop_xyz.x;
978 			logic_structs[cur_id]->mega->actor_xyz.y = floor_def->Gravitise_y(logic_structs[tar]->prop_xyz.y); // logic_structs[tar]->prop_xyz.y;
979 			logic_structs[cur_id]->mega->actor_xyz.z = logic_structs[tar]->prop_xyz.z;
980 		} else { // mega
981 			logic_structs[cur_id]->mega->actor_xyz.x = logic_structs[tar]->mega->actor_xyz.x;
982 			logic_structs[cur_id]->mega->actor_xyz.y = logic_structs[tar]->mega->actor_xyz.y;
983 			logic_structs[cur_id]->mega->actor_xyz.z = logic_structs[tar]->mega->actor_xyz.z;
984 		}
985 
986 		// add offset
987 		logic_structs[cur_id]->mega->actor_xyz.x += (PXfloat)params[1];
988 		logic_structs[cur_id]->mega->actor_xyz.z += (PXfloat)params[2];
989 	} else {
990 		// Absolute jump has been requested, so just set the new x,z for the object to the given values.
991 		logic_structs[cur_id]->mega->actor_xyz.x = (PXfloat)params[1];
992 		logic_structs[cur_id]->mega->actor_xyz.z = (PXfloat)params[2];
993 	}
994 
995 	// set floor rect value - used by stage draw to find indexed camera name
996 	// gotta keep this bang up to date for player history system
997 	floor_def->Set_floor_rect_flag(L);
998 
999 	return (IR_CONT);
1000 }
1001 
fn_teleport_z(int32 &,int32 * params)1002 mcodeFunctionReturnCodes _game_session::fn_teleport_z(int32 &, int32 *params) {
1003 	// move the player to another objects Y coordinate
1004 
1005 	// params        0 name of target object
1006 
1007 	const char *target_object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1008 
1009 	Zdebug("fn_teleport_z to %s", target_object_name);
1010 
1011 	uint32 tar = MS->objects->Fetch_item_number_by_name(target_object_name);
1012 
1013 	if (tar == 0xffffffff)
1014 		Fatal_error("'destination' teleport object [%s] does not exist", target_object_name);
1015 	if (!logic_structs[tar]->prop_coords_set)
1016 		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);
1017 
1018 	if (logic_structs[tar]->image_type == PROP) {
1019 		logic_structs[cur_id]->mega->actor_xyz.y = floor_def->Gravitise_y(logic_structs[tar]->prop_xyz.y); // logic_structs[tar]->prop_xyz.y;
1020 	} else {                                                                                                   // mega
1021 		logic_structs[cur_id]->mega->actor_xyz.y = logic_structs[tar]->mega->actor_xyz.y;
1022 	}
1023 
1024 	// set floor rect value - used by stage draw to find indexed camera name
1025 	// gotta keep this bang up to date for player history system
1026 	floor_def->Set_floor_rect_flag(L);
1027 
1028 	return (IR_CONT);
1029 }
1030 
fn_teleport_y_to_id(int32 &,int32 * params)1031 mcodeFunctionReturnCodes _game_session::fn_teleport_y_to_id(int32 &, int32 *params) {
1032 	// move the player to another objects Y coordinate
1033 
1034 	// params        0 ID of target object
1035 
1036 	Zdebug("fn_teleport_y_to_id to %d", params[0]);
1037 
1038 	assert((uint32)params[0] < total_objects);
1039 
1040 	if (logic_structs[params[0]]->image_type == PROP) {
1041 		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;
1042 	} else {                                                                                                         // mega
1043 		logic_structs[cur_id]->mega->actor_xyz.y = logic_structs[params[0]]->mega->actor_xyz.y;
1044 	}
1045 
1046 	// set floor rect value - used by stage draw to find indexed camera name
1047 	// gotta keep this bang up to date for player history system
1048 	floor_def->Set_floor_rect_flag(L);
1049 
1050 	return (IR_CONT);
1051 }
1052 
fn_are_we_on_this_floor(int32 & result,int32 * params)1053 mcodeFunctionReturnCodes _game_session::fn_are_we_on_this_floor(int32 &result, int32 *params) {
1054 	// check to see if object is on the floor passed
1055 
1056 	// params        0 name of floor
1057 
1058 	uint32 floor_id;
1059 
1060 	result = FALSE8;
1061 
1062 	const char *floor_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1063 
1064 	if (first_session_cycle)
1065 		return IR_CONT;
1066 
1067 	uint32 hash = HashString(floor_name);
1068 	floor_id = floor_def->floors->Fetch_item_number_by_hash(hash);
1069 
1070 	if (floor_id == 0xffffffff)
1071 		Fatal_error("fn_are_we_on_this_floor cant locate floor [%s]", floor_name);
1072 
1073 	if (floor_id == L->owner_floor_rect)
1074 		result = TRUE8;
1075 
1076 	return IR_CONT;
1077 }
1078 
fn_is_object_on_our_floor(int32 & result,int32 * params)1079 mcodeFunctionReturnCodes _game_session::fn_is_object_on_our_floor(int32 &result, int32 *params) {
1080 	// check to see if object is on the floor passed
1081 
1082 	// params        0 name of object
1083 
1084 	uint32 id, num_extra, j, cam;
1085 
1086 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1087 
1088 	result = FALSE8;
1089 
1090 	if (first_session_cycle)
1091 		return IR_CONT;
1092 
1093 	id = objects->Fetch_item_number_by_name(object_name);
1094 	if (id == 0xffffffff)
1095 		Fatal_error("fn_is_object_on_our_floor - illegal object [%s]", object_name);
1096 
1097 	// same camera means same floor
1098 	if (floor_to_camera_index[L->owner_floor_rect] == floor_to_camera_index[logic_structs[id]->owner_floor_rect]) {
1099 		result = TRUE8;
1100 	} else {
1101 		// ok, but is our floor linked to theirs?
1102 		cam = floor_to_camera_index[L->owner_floor_rect]; // the camera associated with calling objects (my) floor
1103 		num_extra = cam_floor_list[cam].num_extra_floors;
1104 
1105 		for (j = 0; j < num_extra; j++) {
1106 			if (cam_floor_list[cam].extra_floors[j] == logic_structs[id]->owner_floor_rect) {
1107 				result = TRUE8; // yes - the floors are linked
1108 				return IR_CONT;
1109 			}
1110 		}
1111 	}
1112 
1113 	return (IR_CONT);
1114 }
1115 
fn_can_mega_see_dead_megas(int32 & result,int32 *)1116 mcodeFunctionReturnCodes _game_session::fn_can_mega_see_dead_megas(int32 &result, int32 *) {
1117 	// are there dead megas on this megas floor?
1118 
1119 	uint32 j, cam, num_extra;
1120 
1121 	for (j = 0; j < number_of_voxel_ids; j++) {
1122 		if (cur_id != voxel_id_list[j]) {
1123 			if ((logic_structs[voxel_id_list[j]]->mega->dead) &&                  // dead
1124 			    (logic_structs[voxel_id_list[j]]->ob_status != OB_STATUS_HELD)) { // not held
1125 				// found a dead mega who isnt us - is it on our floor?
1126 
1127 				// same camera means same floor
1128 				if (floor_to_camera_index[L->owner_floor_rect] == floor_to_camera_index[logic_structs[voxel_id_list[j]]->owner_floor_rect]) {
1129 					result = TRUE8; //
1130 					return IR_CONT; // cor, found one
1131 				}
1132 
1133 				// otherwise do a check to see if our camera is linked to others floor
1134 				cam = floor_to_camera_index[L->owner_floor_rect];
1135 				num_extra = cam_floor_list[cam].num_extra_floors;
1136 
1137 				for (uint32 k = 0; k < num_extra; k++) {
1138 					if (cam_floor_list[cam].extra_floors[k] == logic_structs[voxel_id_list[j]]->owner_floor_rect) {
1139 						result = TRUE8; // yes - the floors are linked
1140 						return IR_CONT;
1141 					}
1142 				}
1143 			}
1144 		}
1145 	}
1146 
1147 	result = FALSE8;
1148 	return IR_CONT;
1149 }
1150 
fn_is_object_on_screen(int32 & result,int32 * params)1151 mcodeFunctionReturnCodes _game_session::fn_is_object_on_screen(int32 &result, int32 *params) {
1152 	// check to see if object is in current camera space - i.e. will be drawn by actor-draw
1153 
1154 	// params        0 name of object
1155 
1156 	uint32 id;
1157 	PXvector pos;
1158 	bool8 resu = FALSE8;
1159 	PXvector filmpos;
1160 
1161 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1162 
1163 	Zdebug("fn_is_object_on_screen [%s]", object_name);
1164 
1165 	if (!SetOK()) {
1166 		result = FALSE8; // no camera as yet
1167 		return (IR_CONT);
1168 	}
1169 
1170 	// get object to check
1171 	id = objects->Fetch_item_number_by_name(object_name);
1172 	if (id == 0xffffffff)
1173 		Fatal_error("fn_is_object_on_screen - illegal object [%s]", object_name);
1174 
1175 	Zdebug(" id = %d", id);
1176 
1177 	// mega or prop
1178 	if (logic_structs[id]->image_type == PROP) {
1179 		Zdebug(" prop");
1180 		pos.x = logic_structs[id]->prop_xyz.x;
1181 		pos.y = logic_structs[id]->prop_xyz.y; // talks over head rather than from the feet
1182 		pos.z = logic_structs[id]->prop_xyz.z;
1183 	} else {
1184 		Zdebug(" mega");
1185 		pos.x = logic_structs[id]->mega->actor_xyz.x;
1186 		pos.y = logic_structs[id]->mega->actor_xyz.y; // talks over head rather than from the feet
1187 		pos.z = logic_structs[id]->mega->actor_xyz.z;
1188 	}
1189 
1190 	// setup camera
1191 	PXcamera &camera = GetCamera();
1192 
1193 	// compute screen coord
1194 	Zdebug(" PXWorldToFilm");
1195 	PXWorldToFilm(pos, camera, resu, filmpos);
1196 	result = (int32)resu;
1197 	Zdebug(" ~PXWorldToFilm");
1198 
1199 	// Ignore actors who are on the wrong side of the hither plane
1200 	if (filmpos.z > -g_actor_hither_plane)
1201 		result = 0;
1202 
1203 	return (IR_CONT);
1204 }
1205 
fn_are_we_on_screen(int32 & result,int32 *)1206 mcodeFunctionReturnCodes _game_session::fn_are_we_on_screen(int32 &result, int32 *) {
1207 	// Similar to the above function but does the check just for the object calling the function, which
1208 	// must be a mega character.
1209 
1210 	// No params.
1211 
1212 	// Write the call in the debug file.
1213 	Zdebug("fn_are_we_on_screen() - object id = %d", cur_id);
1214 
1215 	// Check if we have a camera set up.
1216 	if (!SetOK()) {
1217 		result = FALSE8;
1218 		return (IR_CONT);
1219 	}
1220 
1221 	// Caller must be a mega.  (We can change this if we find we need to.)
1222 	if (logic_structs[cur_id]->image_type != VOXEL)
1223 		Fatal_error("Non mega object (id=%d) called fn_are_we_on_screen()", cur_id);
1224 
1225 	result = 0;
1226 
1227 	if (Object_visible_to_camera(cur_id)) {
1228 		bool8 aresult = TRUE8;
1229 		PXvector filmPosition;
1230 		PXWorldToFilm(M->actor_xyz, set.GetCamera(), aresult, filmPosition);
1231 
1232 		if (filmPosition.z < -g_actor_hither_plane) {
1233 			VECTOR v;
1234 			v.vx = (int32)M->actor_xyz.x;
1235 			v.vy = (int32)M->actor_xyz.y;
1236 			v.vz = (int32)M->actor_xyz.z;
1237 
1238 			SVECTOR orient;
1239 			orient.vx = 0;
1240 			orient.vy = 0;
1241 			orient.vz = 0;
1242 
1243 			// finally if this is true then we are okay so on_screen is true
1244 			if (QuickActorCull((psxCamera *)&(set.GetCamera()), &v, &orient) != 1)
1245 				result = 1;
1246 		}
1247 	}
1248 
1249 	return (IR_CONT);
1250 }
1251 
fn_get_objects_lvar_value(int32 & result,int32 * params)1252 mcodeFunctionReturnCodes _game_session::fn_get_objects_lvar_value(int32 &result, int32 *params) {
1253 	// params        0 name of object
1254 	//				1 name of lvar
1255 
1256 	int32 ret;
1257 	c_game_object *ob;
1258 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1259 	const char *lvar_name = (const char *)MemoryUtil::resolvePtr(params[1]);
1260 
1261 	Zdebug("fn_get_objects_lvar_value - [%s] [%s]", object_name, lvar_name);
1262 
1263 	uint32 hash = HashString(object_name);
1264 	ob = (c_game_object *)objects->Try_fetch_item_by_hash(hash);
1265 	if (!ob)
1266 		Fatal_error("fn_get_objects_lvar_value - illegal object [%s]", object_name);
1267 
1268 	ret = ob->GetVariable(lvar_name);
1269 	if (ret == -1)
1270 		Fatal_error("%s finds fn_get_objects_lvar_value - target object [%s] doesnt have [%s] lvar", object->GetName(), object_name, lvar_name);
1271 
1272 	result = ob->GetIntegerVariable(ret);
1273 
1274 	Zdebug(" var==%d", result);
1275 
1276 	return (IR_CONT);
1277 }
1278 
fn_set_objects_lvar_value(int32 &,int32 * params)1279 mcodeFunctionReturnCodes _game_session::fn_set_objects_lvar_value(int32 &, int32 *params) {
1280 	// params        0 name of object
1281 	//				1 name of lvar
1282 	//				2 new value of lvar
1283 
1284 	int32 var_num;
1285 	c_game_object *ob;
1286 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1287 	const char *lvar_name = (const char *)MemoryUtil::resolvePtr(params[1]);
1288 
1289 	Zdebug("[%s] calls fn_set_objects_lvar_value - [%s] [%s, %d]", object->GetName(), object_name, lvar_name, params[2]);
1290 
1291 	ob = (c_game_object *)objects->Fetch_item_by_name(object_name);
1292 	if (!ob)
1293 		Fatal_error("fn_set_objects_lvar_value - illegal object [%s]", object_name);
1294 
1295 	var_num = ob->GetVariable(lvar_name);
1296 	if (var_num == -1)
1297 		Fatal_error("[%s] fn_set_objects_lvar_value - object [%s] doesnt have [%s] lvar", object->GetName(), object_name, lvar_name);
1298 
1299 	ob->SetIntegerVariable(var_num, params[2]);
1300 
1301 	Zdebug(" var==%d", params[2]);
1302 
1303 	return (IR_CONT);
1304 }
1305 
fn_set_ids_lvar_value(int32 &,int32 * params)1306 mcodeFunctionReturnCodes _game_session::fn_set_ids_lvar_value(int32 &, int32 *params) {
1307 	// params        0 id of object
1308 	//				1 name of lvar
1309 	//				2 new value of lvar
1310 
1311 	int32 var_num;
1312 	c_game_object *ob;
1313 	const char *lvar_name = (const char *)MemoryUtil::resolvePtr(params[1]);
1314 
1315 	Zdebug("fn_set_ids_lvar_value - [%s] [%s]", objects->Fetch_items_name_by_number(params[0]), lvar_name);
1316 
1317 	ob = (c_game_object *)objects->Fetch_item_by_number(params[0]);
1318 	if (!ob)
1319 		Fatal_error("fn_set_ids_lvar_value - illegal object [%d]", params[0]);
1320 
1321 	var_num = ob->GetVariable(lvar_name);
1322 	if (var_num == -1)
1323 		Fatal_error("fn_set_ids_lvar_value - object [%d] doesnt have [%s] lvar", params[0], lvar_name);
1324 
1325 	ob->SetIntegerVariable(var_num, params[2]);
1326 
1327 	Zdebug(" var==%d", params[2]);
1328 
1329 	return (IR_CONT);
1330 }
1331 
fn_get_state_flag(int32 & result,int32 * params)1332 mcodeFunctionReturnCodes _game_session::fn_get_state_flag(int32 &result, int32 *params) {
1333 	// params        0 name of object
1334 
1335 	int32 ret;
1336 	c_game_object *ob;
1337 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1338 
1339 	ob = (c_game_object *)objects->Fetch_item_by_name(object_name);
1340 	if (!ob)
1341 		Fatal_error("fn_get_state_flag - illegal object [%s]", object_name);
1342 	ret = ob->GetVariable("state");
1343 	if (ret == -1)
1344 		Fatal_error("fn_get_state_flag - object [%s] doesnt have 'state' lvar", object_name);
1345 	result = ob->GetIntegerVariable(ret);
1346 
1347 	return (IR_CONT);
1348 }
1349 
fn_is_object_dead(int32 & result,int32 * params)1350 mcodeFunctionReturnCodes _game_session::fn_is_object_dead(int32 &result, int32 *params) {
1351 	// params        0 name of object
1352 
1353 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1354 	uint32 id = objects->Fetch_item_number_by_name(object_name);
1355 
1356 	if (!logic_structs[id]->mega)
1357 		Fatal_error("fn_get_state_flag - object [%s] not mega", object_name);
1358 
1359 	result = logic_structs[id]->mega->dead;
1360 
1361 	return (IR_CONT);
1362 }
1363 
fn_set_weapon(int32 &,int32 * params)1364 mcodeFunctionReturnCodes _game_session::fn_set_weapon(int32 &, int32 *params) {
1365 	// change/set the weapon type
1366 	// if the new one is not the current then an anim must be played...
1367 
1368 	//	params   0 ascii name of weapon - should be compatible with weapon_text
1369 
1370 	const char *weapon_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1371 
1372 	// search the weapon set table
1373 
1374 	uint32 j;
1375 
1376 	Zdebug("fn-set-weapon [%s]", weapon_name);
1377 
1378 	for (j = 0; j < __TOTAL_WEAPONS; j++) {
1379 		Zdebug("test [%s]", weapon_text[j]);
1380 		if (!strcmp(weapon_name, weapon_text[j])) {
1381 			Zdebug("found %d", j);
1382 			L->mega->weapon = (__weapon)j;
1383 			return (IR_CONT);
1384 		}
1385 	}
1386 
1387 	Fatal_error("WARNING -  %s specified weapon does not exist [%s]", object->GetName(), weapon_name);
1388 
1389 	return (IR_STOP);
1390 }
1391 
fn_is_crouching(int32 & result,int32 *)1392 mcodeFunctionReturnCodes _game_session::fn_is_crouching(int32 &result, int32 *) {
1393 	// are we crouching yes or no
1394 
1395 	result = M->Is_crouched();
1396 
1397 	return IR_CONT;
1398 }
1399 
fn_is_an_object_crouching(int32 & result,int32 * params)1400 mcodeFunctionReturnCodes _game_session::fn_is_an_object_crouching(int32 &result, int32 *params) {
1401 	// is an object crouching yes or no
1402 
1403 	// params    0   name
1404 
1405 	uint32 id;
1406 
1407 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1408 
1409 	id = objects->Fetch_item_number_by_name(object_name);
1410 	if (id == 0xffffffff)
1411 		Fatal_error("fn_is_an_object_crouching - illegal object [%s]", object_name);
1412 
1413 	// Make sure it is a mega.
1414 	if (!logic_structs[id]->mega)
1415 		Fatal_error("fn_is_an_object_crouching - object [%s] not a mega", object_name);
1416 
1417 	result = logic_structs[id]->mega->Is_crouched();
1418 
1419 	return IR_CONT;
1420 }
1421 
fn_is_armed(int32 & result,int32 *)1422 mcodeFunctionReturnCodes _game_session::fn_is_armed(int32 &result, int32 *) {
1423 	// are we armed yes or no
1424 
1425 	result = Fetch_cur_megas_armed_status();
1426 
1427 	return IR_CONT;
1428 }
1429 
1430 extern _player_stat player_stat_table[__TOTAL_WEAPONS];
fn_set_pose(int32 &,int32 * params)1431 mcodeFunctionReturnCodes _game_session::fn_set_pose(int32 &, int32 *params) {
1432 	// change/set the weapon type
1433 	// set instantly - i.e. init the _vox_image
1434 
1435 	//	params   0 ascii name of pose - should be compatible with weapon_text
1436 
1437 	// search the weapon set table
1438 
1439 	uint32 j;
1440 	const char *pose_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1441 
1442 	Zdebug("fn-set-weapon [%s]", pose_name);
1443 
1444 	for (j = 0; j < __TOTAL_WEAPONS; j++) {
1445 		Zdebug("test [%s]", weapon_text[j]);
1446 		if (!strcmp(pose_name, weapon_text[j])) {
1447 			Zdebug("found %d", j);
1448 			L->mega->weapon = (__weapon)j;
1449 
1450 			// do this here as well as in fn-set-player-pose as its safer in-case of misuse
1451 			if (player.Player_exists())
1452 				if (cur_id == player.Fetch_player_id())
1453 					player.Set_player_status(player_stat_table[j]);
1454 
1455 			I->___init(M->chr_name, M->anim_set, (__weapon)j); // we pass the person, set names through
1456 
1457 			return (IR_CONT);
1458 		}
1459 	}
1460 
1461 	Fatal_error("WARNING -  %s specified weapon does not exist [%s]", object->GetName(), pose_name);
1462 
1463 	return (IR_STOP);
1464 }
1465 
fn_set_texture(int32 &,int32 * params)1466 mcodeFunctionReturnCodes _game_session::fn_set_texture(int32 &, int32 *params) {
1467 	// fn_set_texture(text)
1468 
1469 	const char *texture_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1470 
1471 	L->voxel_info->Set_texture(texture_name);
1472 
1473 	return (IR_CONT);
1474 }
1475 
fn_set_palette(int32 &,int32 * params)1476 mcodeFunctionReturnCodes _game_session::fn_set_palette(int32 &, int32 *params) {
1477 	const char *palette = (const char *)MemoryUtil::resolvePtr(params[0]);
1478 
1479 	L->voxel_info->Set_palette(palette);
1480 
1481 	return (IR_CONT);
1482 }
1483 
fn_set_mesh(int32 &,int32 * params)1484 mcodeFunctionReturnCodes _game_session::fn_set_mesh(int32 &, int32 *params) {
1485 	// fn_set_mesh(text)
1486 
1487 	const char *mesh = (const char *)MemoryUtil::resolvePtr(params[0]);
1488 
1489 	L->voxel_info->Set_mesh(mesh);
1490 
1491 	return (IR_CONT);
1492 }
1493 
1494 extern _player_stat player_stat_table[__TOTAL_WEAPONS];
1495 
fn_set_player_pose(int32 &,int32 * params)1496 mcodeFunctionReturnCodes _game_session::fn_set_player_pose(int32 &, int32 *params) {
1497 	// change/set the weapon type
1498 	// set instantly - i.e. init the _vox_image
1499 	// sets players status to equivelent mode
1500 
1501 	//	params   0 ascii name of pose - should be compatible with weapon_text
1502 
1503 	// search the weapon set table
1504 	uint32 j;
1505 	const char *pose_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1506 
1507 	Zdebug("fn_set_player_pose [%s]", pose_name);
1508 
1509 	for (j = 0; j < __TOTAL_WEAPONS; j++) {
1510 		Zdebug("test [%s]", weapon_text[j]);
1511 		if (!strcmp(pose_name, weapon_text[j])) {
1512 			Zdebug("found %d", j);
1513 			L->mega->weapon = (__weapon)j;
1514 			player.Set_player_status(player_stat_table[j]);
1515 
1516 			player.Push_player_stat(); // because its popped on return from a conversation - hmmm
1517 
1518 			I->___init(M->chr_name, M->anim_set, (__weapon)j); // we pass the person, set names through
1519 
1520 			return (IR_CONT);
1521 		}
1522 	}
1523 
1524 	Fatal_error("WARNING - fn_set_player_pose %s specified weapon does not exist [%s]", object->GetName(), pose_name);
1525 
1526 	return (IR_STOP);
1527 }
1528 
fn_set_custom(int32 &,int32 * params)1529 mcodeFunctionReturnCodes _game_session::fn_set_custom(int32 &, int32 *params) {
1530 	// change/set the custom anim type
1531 	// if the new one is not the current then an anim must be played...
1532 
1533 	//	params   0 ascii name of custom
1534 
1535 	const char *custom_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1536 
1537 	Zdebug("fn_set_custom [%s]", custom_name);
1538 
1539 	if (!M)
1540 		Fatal_error("fn_set_custom finds [%s] is not a mega", object->GetName());
1541 
1542 	Set_string(custom_name, M->custom_set, MAX_CUSTOM_NAME_LENGTH);
1543 	M->custom = TRUE8;
1544 
1545 	return (IR_CONT);
1546 }
1547 
fn_message(int32 &,int32 * params)1548 mcodeFunctionReturnCodes _game_session::fn_message(int32 &, int32 *params) {
1549 	const char *message = (const char *)MemoryUtil::resolvePtr(params[0]);
1550 
1551 	// pc has to muck around to clear sticky ctrl key
1552 	// hold until ctrl key released
1553 	if ((Read_DI_keys(Common::KEYCODE_LCTRL)) && (!first_session_cycle))
1554 		return (IR_REPEAT);
1555 
1556 	if (params[0] < 256) {
1557 		Message_box("%d", params[0]);
1558 	} else {
1559 		Message_box("%s - %s", object->GetName(), message);
1560 	}
1561 	return IR_CONT;
1562 }
1563 
fn_message_var(int32 &,int32 * params)1564 mcodeFunctionReturnCodes _game_session::fn_message_var(int32 &, int32 *params) {
1565 	const char *var_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1566 
1567 	uint32 var = object->GetVariable(var_name);
1568 	if (var == 0xffffffff)
1569 		Fatal_error("fn_message_var - object %s has no var %s", object->GetName(), var_name);
1570 
1571 	// pc has to muck around to clear sticky ctrl key
1572 	// hold until ctrl key released
1573 	if (Read_DI_keys(Common::KEYCODE_LCTRL))
1574 		return (IR_REPEAT);
1575 
1576 	char txt[100];
1577 
1578 	if (object->IsVariableString(var))
1579 		sprintf(txt, "%s=\"%s\"", var_name, object->GetStringVariable(var));
1580 	else
1581 		sprintf(txt, "%s=%d", var_name, object->GetIntegerVariable(var));
1582 
1583 	Message_box(txt);
1584 
1585 	return IR_CONT;
1586 }
1587 
fn_trace(int32 &,int32 *)1588 mcodeFunctionReturnCodes _game_session::fn_trace(int32 &, int32 *) { return (IR_CONT); }
1589 
fn_get_objects_x(int32 & result,int32 * params)1590 mcodeFunctionReturnCodes _game_session::fn_get_objects_x(int32 &result, int32 *params) {
1591 	// return objects x coord
1592 
1593 	// params    0   name of object
1594 
1595 	uint32 id;
1596 
1597 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1598 
1599 	id = (uint32)objects->Fetch_item_number_by_name(object_name);
1600 	if (id == 0xffffffff)
1601 		Fatal_error("fn_get_objects_x - illegal object [%s]", object_name);
1602 
1603 	if (logic_structs[id]->image_type == PROP) {
1604 		result = (uint32)logic_structs[id]->prop_xyz.x;
1605 	} else {
1606 		result = (uint32)logic_structs[id]->mega->actor_xyz.x;
1607 	}
1608 
1609 	return IR_CONT;
1610 }
1611 
fn_get_objects_y(int32 & result,int32 * params)1612 mcodeFunctionReturnCodes _game_session::fn_get_objects_y(int32 &result, int32 *params) {
1613 	// return objects y coord
1614 
1615 	// params    0   name of object
1616 
1617 	uint32 id;
1618 
1619 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1620 
1621 	id = (uint32)objects->Fetch_item_number_by_name(object_name);
1622 	if (id == 0xffffffff)
1623 		Fatal_error("fn_get_objects_y - illegal object [%s]", object_name);
1624 
1625 	if (logic_structs[id]->image_type == PROP) {
1626 		result = (uint32)logic_structs[id]->prop_xyz.y;
1627 	} else {
1628 		result = (uint32)logic_structs[id]->mega->actor_xyz.y;
1629 	}
1630 
1631 	return IR_CONT;
1632 }
1633 
fn_get_objects_z(int32 & result,int32 * params)1634 mcodeFunctionReturnCodes _game_session::fn_get_objects_z(int32 &result, int32 *params) {
1635 	// return objects z coord
1636 
1637 	// params    0   name of object
1638 
1639 	uint32 id;
1640 
1641 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1642 
1643 	id = (uint32)objects->Fetch_item_number_by_name(object_name);
1644 	if (id == 0xffffffff)
1645 		Fatal_error("fn_get_objects_z - illegal object [%s]", object_name);
1646 
1647 	if (logic_structs[id]->image_type == PROP) {
1648 		result = (uint32)logic_structs[id]->prop_xyz.z;
1649 	} else {
1650 		result = (uint32)logic_structs[id]->mega->actor_xyz.z;
1651 	}
1652 
1653 	return IR_CONT;
1654 }
1655 
fn_has_mega_our_height(int32 & result,int32 * params)1656 mcodeFunctionReturnCodes _game_session::fn_has_mega_our_height(int32 &result, int32 *params) {
1657 	// params    0   name of object
1658 
1659 	uint32 id;
1660 
1661 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1662 
1663 	// get target
1664 	id = (uint32)objects->Fetch_item_number_by_name(object_name);
1665 	if (id == 0xffffffff)
1666 		Fatal_error("fn_has_mega_our_height - illegal object [%s]", object_name);
1667 
1668 	// check its a mega
1669 	if (logic_structs[id]->image_type == PROP)
1670 		Fatal_error("fn_has_mega_our_height - [%s] not a mega", object_name);
1671 
1672 	// same y?
1673 	if (logic_structs[id]->mega->actor_xyz.y == M->actor_xyz.y)
1674 		result = 1; // yes!
1675 	else
1676 		result = 0; // no
1677 
1678 	return IR_CONT;
1679 }
1680 
fn_near(int32 & result,int32 * params)1681 mcodeFunctionReturnCodes _game_session::fn_near(int32 &result, int32 *params) {
1682 	// params    0   name of object
1683 	//			1  dist
1684 
1685 	uint32 id;
1686 	PXreal sub1, sub2, len;
1687 	PXreal ourx, oury, ourz;
1688 	PXreal itsx, itsy, itsz;
1689 
1690 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1691 
1692 	id = (uint32)objects->Fetch_item_number_by_name(object_name);
1693 	if (id == 0xffffffff)
1694 		Fatal_error("fn_is_object_dead - illegal object [%s]", object_name);
1695 
1696 	if (L->image_type == PROP) {
1697 		ourx = L->prop_xyz.x;
1698 		oury = L->prop_xyz.y;
1699 		ourz = L->prop_xyz.z;
1700 	} else {
1701 		ourx = M->actor_xyz.x;
1702 		oury = M->actor_xyz.y;
1703 		ourz = M->actor_xyz.z;
1704 	}
1705 
1706 	if (logic_structs[id]->image_type == PROP) {
1707 		itsx = logic_structs[id]->prop_xyz.x;
1708 		itsy = logic_structs[id]->prop_xyz.y;
1709 		itsz = logic_structs[id]->prop_xyz.z;
1710 	} else {
1711 		itsx = logic_structs[id]->mega->actor_xyz.x;
1712 		itsy = logic_structs[id]->mega->actor_xyz.y;
1713 		itsz = logic_structs[id]->mega->actor_xyz.z;
1714 	}
1715 
1716 	if (PXfabs(itsy - oury) < (200 * REAL_ONE)) { // slack for height calc
1717 		sub1 = itsx - ourx;
1718 		sub2 = itsz - ourz;
1719 
1720 		// dist
1721 		len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
1722 
1723 		if (len < (PXreal)(params[1] * params[1])) {
1724 			result = TRUE8;
1725 		} else {
1726 			result = FALSE8;
1727 		}
1728 		return (IR_CONT);
1729 	} else {
1730 		result = FALSE8;
1731 		return (IR_CONT);
1732 	}
1733 }
1734 
fn_is_mega_near_mega(int32 & result,int32 * params)1735 mcodeFunctionReturnCodes _game_session::fn_is_mega_near_mega(int32 &result, int32 *params) {
1736 	// params    0   name of object
1737 	//			1  name of other
1738 	//			2  dist
1739 
1740 	uint32 id, id2;
1741 	PXreal sub1, sub2, len;
1742 	PXreal ourx, oury, ourz;
1743 	PXreal itsx, itsy, itsz;
1744 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1745 	const char *other_object_name = (const char *)MemoryUtil::resolvePtr(params[1]);
1746 
1747 	id = (uint32)objects->Fetch_item_number_by_name(object_name);
1748 	if (id == 0xffffffff)
1749 		Fatal_error("fn_is_mega_near_mega - illegal object [%s]", object_name);
1750 	id2 = (uint32)objects->Fetch_item_number_by_name(other_object_name);
1751 	if (id2 == 0xffffffff)
1752 		Fatal_error("fn_is_mega_near_mega - illegal object [%s]", other_object_name);
1753 
1754 	if (logic_structs[id]->image_type == PROP)
1755 		Fatal_error("fn_is_mega_near_mega %s not a mega", object_name);
1756 	if (logic_structs[id2]->image_type == PROP)
1757 		Fatal_error("fn_is_mega_near_mega %s not a mega", other_object_name);
1758 
1759 	itsx = logic_structs[id]->mega->actor_xyz.x;
1760 	itsy = logic_structs[id]->mega->actor_xyz.y;
1761 	itsz = logic_structs[id]->mega->actor_xyz.z;
1762 
1763 	ourx = logic_structs[id2]->mega->actor_xyz.x;
1764 	oury = logic_structs[id2]->mega->actor_xyz.y;
1765 	ourz = logic_structs[id2]->mega->actor_xyz.z;
1766 
1767 	if (PXfabs(itsy - oury) < (200 * REAL_ONE)) { // slack for height calc
1768 		sub1 = itsx - ourx;
1769 		sub2 = itsz - ourz;
1770 
1771 		// dist
1772 		len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
1773 
1774 		if (len < (PXreal)(params[2] * params[2]))
1775 			result = TRUE8;
1776 		else
1777 			result = FALSE8;
1778 
1779 		return IR_CONT;
1780 	} else { // failed on height
1781 		result = FALSE8;
1782 		return IR_CONT;
1783 	}
1784 }
1785 
fn_on_screen(int32 & result,int32 *)1786 mcodeFunctionReturnCodes _game_session::fn_on_screen(int32 &result, int32 * /* params */) {
1787 	//	no params
1788 
1789 	result = Object_visible_to_camera(cur_id);
1790 
1791 	return (IR_CONT);
1792 }
1793 
fn_hold_if_off_screen(int32 &,int32 *)1794 mcodeFunctionReturnCodes _game_session::fn_hold_if_off_screen(int32 &, int32 *) {
1795 	//	no params
1796 
1797 	if (L->image_type != VOXEL)
1798 		Fatal_error("fn_hold_if_off_screen only works with megas [%s]", object->GetName());
1799 
1800 	if (!Object_visible_to_camera(cur_id)) {
1801 		return (IR_REPEAT);
1802 	}
1803 
1804 	return (IR_CONT);
1805 }
1806 
fn_object_near_nico(int32 & result,int32 * params)1807 mcodeFunctionReturnCodes _game_session::fn_object_near_nico(int32 &result, int32 *params) {
1808 	// params        0 object name
1809 	//				1 nico name
1810 	//				2 dist
1811 
1812 	uint32 id;
1813 	_feature_info *nico;
1814 	PXreal sub1, sub2, len;
1815 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1816 	const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[1]);
1817 
1818 	id = (uint32)objects->Fetch_item_number_by_name(object_name);
1819 
1820 	if (id == 0xffffffff)
1821 		Fatal_error("fn_object_near_nico - illegal object [%s]", object_name);
1822 
1823 	if (logic_structs[id]->image_type == PROP)
1824 		Fatal_error("fn_object_near_nico object [%s] is not a mega!", object_name);
1825 
1826 	// fetch tag file for this item
1827 	nico = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
1828 
1829 	if (!nico)
1830 		Fatal_error("fn_object_near_nico cant find nico [%s]", nico_name);
1831 
1832 	if (PXfabs(logic_structs[id]->mega->actor_xyz.y - nico->y) < (200 * REAL_ONE)) { // slack for height calc
1833 		sub1 = logic_structs[id]->mega->actor_xyz.x - nico->x;
1834 		sub2 = logic_structs[id]->mega->actor_xyz.z - nico->z;
1835 
1836 		// dist
1837 		len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
1838 
1839 		if (len < (PXreal)(params[2] * params[2])) {
1840 			// near
1841 			result = TRUE8;
1842 		} else {
1843 			result = FALSE8;
1844 		}
1845 	} else
1846 		result = FALSE8; // failed on y
1847 
1848 	return (IR_CONT);
1849 }
1850 
fn_add_object_name_to_list(int32 &,int32 * params)1851 mcodeFunctionReturnCodes _game_session::fn_add_object_name_to_list(int32 &, int32 *params) {
1852 	// params        0 object name
1853 
1854 	int32 id;
1855 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1856 
1857 	// check for list overflow
1858 	if (L->total_list == MAX_list)
1859 		Fatal_error("fn_object_name_to_list [%s] has exceeded list size of %d", object->GetName(), MAX_list);
1860 
1861 	id = objects->Fetch_item_number_by_name(object_name);
1862 
1863 	if (id == -1)
1864 		Fatal_error("[%s] callling fn_add_object_name_to_list finds [%s] is not a legal object", object->GetName(), object_name);
1865 
1866 	L->list[L->total_list++] = (uint32)id;
1867 
1868 	return (IR_CONT);
1869 }
1870 
fn_add_object_id_to_list(int32 &,int32 * params)1871 mcodeFunctionReturnCodes _game_session::fn_add_object_id_to_list(int32 &, int32 *params) {
1872 	// params        0 object id
1873 
1874 	// check for list overflow
1875 	if (L->total_list == MAX_list)
1876 		Fatal_error("fn_object_id_to_list [%s] has exceeded list size of %d", object->GetName(), MAX_list);
1877 
1878 	assert((uint32)params[0] < total_objects);
1879 
1880 	L->list[L->total_list++] = params[0];
1881 
1882 	return (IR_CONT);
1883 }
1884 
fn_lift_process_list(int32 & result,int32 * params)1885 mcodeFunctionReturnCodes _game_session::fn_lift_process_list(int32 &result, int32 *params) {
1886 	// special lift logic function - checks all megas in the lift against named nico
1887 
1888 	// params        0 name of nico
1889 	//				1 distance
1890 	//				2 0 top, 1 bottom
1891 
1892 	// returns   FALSE8  did nothing
1893 	//				TRUE8     someone used lift - ascend or descend
1894 
1895 	uint32 j;
1896 	_feature_info *monica; // or nico to you and i
1897 	PXreal sub1, sub2, len;
1898 
1899 	const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1900 
1901 	// check for no people in list! Could be redefined as an error in-fact
1902 	if (!L->total_list) {
1903 		result = FALSE8; // did nothing
1904 		return (IR_CONT);
1905 	}
1906 
1907 	monica = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
1908 	if (!monica)
1909 		Fatal_error("fn_lift_process_list cant find nico [%s]", nico_name);
1910 
1911 	for (j = 0; j < L->total_list; j++) {
1912 		if (logic_structs[L->list[j]]->image_type != VOXEL)
1913 			Fatal_error("fn_lift_process_list finds [%s] is not a mega", (const char *)logic_structs[L->list[j]]->GetName());
1914 
1915 		if (PXfabs(logic_structs[L->list[j]]->mega->actor_xyz.y - monica->y) < (200 * REAL_ONE)) { // slack for height calc
1916 			sub1 = logic_structs[L->list[j]]->mega->actor_xyz.x - monica->x;
1917 			sub2 = logic_structs[L->list[j]]->mega->actor_xyz.z - monica->z;
1918 
1919 			// dist
1920 			len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
1921 
1922 			if (len < (PXreal)(params[1] * params[1])) {
1923 				// near
1924 
1925 				result = TRUE8; // did something
1926 
1927 				if (params[2]) { // bottom
1928 
1929 					// Call the function that does the work in the event manager.
1930 					g_oEventManager->PostNamedEventToObject(EVENT_LIFT_ASCEND, L->list[j], cur_id);
1931 					return (IR_CONT);
1932 				} else { // top
1933 					g_oEventManager->PostNamedEventToObject(EVENT_LIFT_DESCEND, L->list[j], cur_id);
1934 					return (IR_CONT);
1935 				}
1936 			}
1937 		}
1938 	}
1939 
1940 	result = FALSE8; // no action
1941 	return (IR_CONT);
1942 }
1943 
fn_lib_lift_chord_and_chi(int32 & result,int32 * params)1944 mcodeFunctionReturnCodes _game_session::fn_lib_lift_chord_and_chi(int32 &result, int32 *params) {
1945 	// special lift platform handler for cord and chi
1946 
1947 	// look for player being on the lift
1948 
1949 	// params        0 name of nico (if not using platform coords)
1950 	//				1 distance
1951 	//				2 0 top, 1 bottom
1952 
1953 	// returns   FALSE8  did nothing
1954 	//				TRUE8     someone used lift - ascend or descend
1955 
1956 	_feature_info *monica; // or nico to you and i
1957 	PXreal sub1, sub2, len;
1958 	PXreal lifty = REAL_ZERO;
1959 	bool8 has_platform = FALSE8;
1960 	uint32 lift = 0; // lift number in platform list
1961 	bool8 hit = FALSE8;
1962 	uint32 j = 0;
1963 	static int32 issued_warning = FALSE8;
1964 	const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
1965 
1966 	if (!prev_save_state) { // could not save last go - then cant operate lift either. Player is in a private script
1967 		result = FALSE8;
1968 		return IR_CONT;
1969 	}
1970 
1971 	monica = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
1972 	if (!monica)
1973 		Fatal_error("fn_lift_process_list cant find nico [%s]", nico_name);
1974 	lifty = monica->y;
1975 
1976 	// see if the lift has registered a coordinate platform - if so, we use that
1977 	for (j = 0; j < num_lifts; j++) {
1978 		if (cur_id == lifts[j].id) {
1979 			has_platform = TRUE8;
1980 			lift = j;
1981 			break; // yup - found a platform
1982 		}
1983 	}
1984 
1985 	// issue one warning at a time
1986 	if ((!has_platform) && (!issued_warning)) {
1987 		issued_warning = TRUE8;
1988 		Message_box("lift [%s] says please can i have proper platform coords?", object->GetName());
1989 	}
1990 
1991 	if (PXfabs(logic_structs[player.Fetch_player_id()]->mega->actor_xyz.y - lifty) < (200 * REAL_ONE)) { // slack for height calc
1992 		if (!has_platform) {
1993 			sub1 = logic_structs[player.Fetch_player_id()]->mega->actor_xyz.x - monica->x;
1994 			sub2 = logic_structs[player.Fetch_player_id()]->mega->actor_xyz.z - monica->z;
1995 			// dist
1996 			len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
1997 			if (len < (PXreal)(params[1] * params[1]))
1998 				hit = TRUE8;
1999 		} else {                                                                                     // has a registered platform
2000 			if ((logic_structs[player.Fetch_player_id()]->mega->actor_xyz.x >= lifts[lift].x) && // area box method
2001 			    (logic_structs[player.Fetch_player_id()]->mega->actor_xyz.x <= lifts[lift].x1) &&
2002 			    (logic_structs[player.Fetch_player_id()]->mega->actor_xyz.z >= lifts[lift].z) &&
2003 			    (logic_structs[player.Fetch_player_id()]->mega->actor_xyz.z <= lifts[lift].z1))
2004 				hit = TRUE8;
2005 		}
2006 
2007 		if (hit) {
2008 			// tell player logic - stop ability to interact with anything else
2009 			player.stood_on_lift = TRUE8;
2010 
2011 			if ((player.cur_state.IsButtonSet(__INTERACT)) && (!player.interact_lock) && (player.player_status == STOOD)) {
2012 				player.interact_lock = TRUE8;
2013 
2014 				result = TRUE8; // did something
2015 
2016 				if (params[2]) { // bottom
2017 					// Call the function that does the work in the event manager.
2018 					g_oEventManager->PostNamedEventToObject(EVENT_LIFT_ASCEND, player.Fetch_player_id(), cur_id);
2019 					return (IR_CONT);
2020 				} else { // top
2021 					g_oEventManager->PostNamedEventToObject(EVENT_LIFT_DESCEND, player.Fetch_player_id(), cur_id);
2022 					return (IR_CONT);
2023 				}
2024 			}
2025 		}
2026 	}
2027 
2028 	result = FALSE8; // no action
2029 	return IR_CONT;
2030 }
2031 
2032 typedef struct {
2033 	uint32 init;
2034 	int32 params[4];
2035 } _lift_verify;
2036 
2037 _lift_verify lift2s[MAX_session_objects];
2038 
fn_lift2_process(int32 & result,int32 * params)2039 mcodeFunctionReturnCodes _game_session::fn_lift2_process(int32 &result, int32 *params) {
2040 	// special lift logic function - checks all megas in the lift against named nico
2041 	// if no one is here we IR_CONT
2042 	// of someone hits the spot we teleport them
2043 
2044 	// params        0 name of nico
2045 	//				1 catch distance
2046 	//				2 0 top, 1 bottom
2047 	//				3 release distance
2048 
2049 	// returns   FALSE8  did nothing
2050 	//				TRUE8     someone used lift - ascend or descend
2051 
2052 	uint32 j = 0;
2053 	_feature_info *monica; // or nico to you and i
2054 	PXreal sub1, sub2, len;
2055 	bool8 hit = FALSE8;
2056 	bool8 has_platform = FALSE8;
2057 	PXreal lifty = REAL_ZERO;
2058 	uint32 lift = 0; // lift number in platform list
2059 	static int32 issued_warning = FALSE8;
2060 	const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
2061 
2062 	static int32 inited = FALSE8;
2063 	if (!inited) {
2064 		for (j = 0; j < MAX_session_objects; j++)
2065 			lift2s[j].init = 0;
2066 		inited = TRUE8;
2067 	}
2068 
2069 	if (!lift2s[cur_id].init) {
2070 		lift2s[cur_id].init = TRUE8;
2071 		lift2s[cur_id].params[0] = params[0];
2072 		lift2s[cur_id].params[1] = params[1];
2073 		lift2s[cur_id].params[2] = params[2];
2074 		lift2s[cur_id].params[3] = params[3];
2075 	}
2076 
2077 	if (lift2s[cur_id].params[0] != params[0])
2078 		Message_box("%s param 0 changed from %d to %d", object->GetName(), lift2s[cur_id].params[0], params[0]);
2079 	if (lift2s[cur_id].params[1] != params[1])
2080 		Message_box("%s param 1 changed from %d to %d", object->GetName(), lift2s[cur_id].params[1], params[1]);
2081 	if (lift2s[cur_id].params[2] != params[2])
2082 		Message_box("%s param 2 changed from %d to %d", object->GetName(), lift2s[cur_id].params[2], params[2]);
2083 	if (lift2s[cur_id].params[3] != params[3])
2084 		Message_box("%s param 3 changed from %d to %d", object->GetName(), lift2s[cur_id].params[3], params[3]);
2085 
2086 	// check for no people in list! Could be redefined as an error in-fact
2087 	if (!L->total_list) {
2088 		if (!issued_warning) {
2089 			Message_box("lift [%s] says no items in list", object->GetName());
2090 			issued_warning = TRUE8;
2091 		}
2092 
2093 		result = FALSE8; // did nothing
2094 		return (IR_CONT);
2095 	}
2096 
2097 	// get nico
2098 	monica = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
2099 	if (!monica)
2100 		Fatal_error("fn_lift_process_list cant find nico [%s]", nico_name);
2101 	lifty = monica->y;
2102 
2103 	// see if the lift has registered a coordinate platform - if so, we use that
2104 	for (j = 0; j < num_lifts; j++)
2105 		if (cur_id == lifts[j].id) {
2106 			has_platform = TRUE8;
2107 			lift = j;
2108 			break; // yup - found a platform
2109 		}
2110 
2111 	// issue one warning at a time
2112 	if ((!has_platform) && (!issued_warning)) {
2113 		issued_warning = TRUE8;
2114 		Message_box("lift [%s] says please can i have proper platform coords?", object->GetName());
2115 	}
2116 
2117 	for (j = 0; j < L->total_list; j++) {
2118 		if (logic_structs[L->list[j]]->image_type != VOXEL)
2119 			Fatal_error("fn_lift_process_list finds [%s] is not a mega", (const char *)logic_structs[L->list[j]]->GetName());
2120 
2121 		if (logic_structs[L->list[j]]->mega->dead)
2122 			continue;
2123 
2124 		if (PXfabs(logic_structs[L->list[j]]->mega->actor_xyz.y - lifty) < (200 * REAL_ONE)) { // slack for height calc
2125 
2126 			sub1 = logic_structs[L->list[j]]->mega->actor_xyz.x - monica->x;
2127 			sub2 = logic_structs[L->list[j]]->mega->actor_xyz.z - monica->z;
2128 
2129 			// dist
2130 			len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
2131 
2132 			// are we inside release distance
2133 			if (len < (PXreal)(params[3] * params[3])) {
2134 				hit = TRUE8; // hurray, we found someone inside the release distance
2135 			}
2136 
2137 			if (((!has_platform) && (len < (PXreal)(params[1] * params[1]))) ||     // crude inner nico method, or
2138 			    ((logic_structs[L->list[j]]->mega->actor_xyz.x >= lifts[lift].x) && // area box method
2139 			     (logic_structs[L->list[j]]->mega->actor_xyz.x <= lifts[lift].x1) && (logic_structs[L->list[j]]->mega->actor_xyz.z >= lifts[lift].z) &&
2140 			     (logic_structs[L->list[j]]->mega->actor_xyz.z <= lifts[lift].z1))) {
2141 				if (L->list[j] == player.Fetch_player_id()) {
2142 					// tell player logic - stop ability to interact with anything else
2143 					player.stood_on_lift = TRUE8;
2144 
2145 					if ((player.cur_state.IsButtonSet(__INTERACT)) && (!player.interact_lock) && (player.player_status == STOOD)) {
2146 						player.interact_lock = TRUE8;
2147 
2148 						L->list_result = L->list[j]; // save id for later retrieval
2149 
2150 						// near
2151 						Zdebug("%s hits lift", (const char *)logic_structs[L->list[j]]->GetName());
2152 
2153 						result = TRUE8;
2154 
2155 						return (IR_CONT);
2156 					}
2157 				} else {                             // other megas
2158 					L->list_result = L->list[j]; // save id for later retrieval
2159 
2160 					// near
2161 					Zdebug("mega %s hits lift", (const char *)logic_structs[L->list[j]]->GetName());
2162 
2163 					result = TRUE8;
2164 
2165 					return (IR_CONT);
2166 				}
2167 			}
2168 		}
2169 	}
2170 
2171 	// someone was within release range so hold
2172 	if (hit) {
2173 		Zdebug("repeating");
2174 		return (IR_REPEAT);
2175 	}
2176 
2177 	L->list_result = 999; // means no one - release
2178 
2179 	// detected no one so continue in script - which means doors will close
2180 	return IR_CONT;
2181 }
2182 
fn_wait_for_button(int32 &,int32 * params)2183 mcodeFunctionReturnCodes _game_session::fn_wait_for_button(int32 &, int32 *params) {
2184 	// wait for specified button
2185 	//	params   0   button number
2186 	//					0 interact
2187 	//					1 punch
2188 	//					2 forward
2189 	//					3 backward
2190 	//					4 right
2191 	//					5 left
2192 
2193 	player.Update_input_state();
2194 
2195 	if ((params[0] == 0) && (player.cur_state.IsButtonSet(__INTERACT)))
2196 		return IR_CONT;
2197 	if ((params[0] == 1) && (player.cur_state.IsButtonSet(__ATTACK)))
2198 		return IR_CONT;
2199 	if ((params[0] == 2) && (player.cur_state.momentum == __FORWARD_1))
2200 		return IR_CONT;
2201 	if ((params[0] == 3) && (player.cur_state.momentum == __BACKWARD_1))
2202 		return IR_CONT;
2203 	if ((params[0] == 4) && ((player.cur_state.turn == __RIGHT) || (player.cur_state.turn == __HARD_RIGHT)))
2204 		return IR_CONT;
2205 	if ((params[0] == 5) && ((player.cur_state.turn == __LEFT) || (player.cur_state.turn == __HARD_LEFT)))
2206 		return IR_CONT;
2207 
2208 	return IR_REPEAT;
2209 }
2210 
fn_register_platform_coords(int32 &,int32 * params)2211 mcodeFunctionReturnCodes _game_session::fn_register_platform_coords(int32 &, int32 *params) {
2212 	// register coords of a lift platform
2213 
2214 	// params    0   x
2215 	//			1  z
2216 	//			2  x1
2217 	//			3  z1
2218 
2219 	//			we'll still take the y from the nico
2220 
2221 	// safety
2222 	if (num_lifts == MAX_lift_platforms)
2223 		Fatal_error("too many lifts - max = %d", MAX_lift_platforms);
2224 
2225 	lifts[num_lifts].id = cur_id;            // our id
2226 	lifts[num_lifts].x = (PXreal)params[0];  // x
2227 	lifts[num_lifts].z = (PXreal)params[1];  // z
2228 	lifts[num_lifts].x1 = (PXreal)params[2]; // x1
2229 	lifts[num_lifts].z1 = (PXreal)params[3]; // z1
2230 
2231 	num_lifts++;
2232 
2233 	return IR_CONT;
2234 }
2235 
fn_near_list(int32 & result,int32 * params)2236 mcodeFunctionReturnCodes _game_session::fn_near_list(int32 &result, int32 *params) {
2237 	// works from our coordiate
2238 	// we can be prop or mega
2239 	// targets much be mega
2240 
2241 	// params    0   dist
2242 
2243 	uint32 j;
2244 	PXreal sub1, sub2, len;
2245 	PXreal ourx, oury, ourz;
2246 
2247 	if (L->image_type == PROP) {
2248 		ourx = L->prop_xyz.x;
2249 		oury = L->prop_xyz.y;
2250 		ourz = L->prop_xyz.z;
2251 	} else {
2252 		ourx = M->actor_xyz.x;
2253 		oury = M->actor_xyz.y;
2254 		ourz = M->actor_xyz.z;
2255 	}
2256 
2257 	for (j = 0; j < L->total_list; j++) {
2258 		if (logic_structs[L->list[j]]->image_type != VOXEL)
2259 			Fatal_error("fn_near_list finds [%s] is not a mega", (const char *)logic_structs[L->list[j]]->GetName());
2260 
2261 		if (!logic_structs[L->list[j]]->mega->dead) { // alive
2262 
2263 			Zdebug("%3.2f %3.2f", logic_structs[L->list[j]]->mega->actor_xyz.y, oury);
2264 
2265 			if (PXfabs(logic_structs[L->list[j]]->mega->actor_xyz.y - oury) < (200 * REAL_ONE)) { // slack for height calc
2266 				sub1 = logic_structs[L->list[j]]->mega->actor_xyz.x - ourx;
2267 				sub2 = logic_structs[L->list[j]]->mega->actor_xyz.z - ourz;
2268 
2269 				// dist
2270 				len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
2271 
2272 				if (len < (PXreal)(params[0] * params[0])) {
2273 					// near
2274 
2275 					L->list_result = L->list[j]; // save id for later retrieval
2276 
2277 					result = TRUE8; // did something
2278 
2279 					return (IR_CONT);
2280 				}
2281 			}
2282 		}
2283 	}
2284 
2285 	result = FALSE8; // no action
2286 	return (IR_CONT);
2287 }
2288 
fn_get_list_result(int32 & result,int32 *)2289 mcodeFunctionReturnCodes _game_session::fn_get_list_result(int32 &result, int32 *) {
2290 	// returns the result of a previous list process based function such as fn_near_list
2291 
2292 	// no params
2293 
2294 	result = L->list_result;
2295 
2296 	return (IR_CONT);
2297 }
2298 
fn_hold_while_list_near_nico(int32 & result,int32 * params)2299 mcodeFunctionReturnCodes _game_session::fn_hold_while_list_near_nico(int32 &result, int32 *params) {
2300 	// function holds the script position while a mega from the list of megas registers as being near the named nico
2301 
2302 	// params        0       nico
2303 	//				1     distance
2304 
2305 	uint32 j;
2306 	_feature_info *monica; // or nico to you and i
2307 	PXreal sub1, sub2, len;
2308 	int32 ret, res;
2309 	const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[0]);
2310 
2311 	// check for no people in list! Could be redefined as an error in-fact
2312 	if (!L->total_list) {
2313 		result = FALSE8; // did nothing
2314 		return (IR_CONT);
2315 	}
2316 
2317 	monica = (_feature_info *)features->Try_fetch_item_by_name(nico_name);
2318 	if (!monica)
2319 		Fatal_error("fn_lift_process_list cant find nico [%s]", nico_name);
2320 
2321 	for (j = 0; j < L->total_list; j++) {
2322 		if (logic_structs[L->list[j]]->image_type != VOXEL)
2323 			Fatal_error("fn_hold_while_list_near_nico finds [%s] is not a mega", (const char *)logic_structs[L->list[j]]->GetName());
2324 
2325 		// ignore people who are dead
2326 		res = Call_socket(L->list[j], "give_state", &ret);
2327 		if (!res)
2328 			Fatal_error("fn_hold_while_list_near_nico - object doesnt have 'give_state' script. Perhaps its not a mega");
2329 
2330 		if ((!ret) && (PXfabs(logic_structs[L->list[j]]->mega->actor_xyz.y - monica->y) < (200 * REAL_ONE))) { // slack for height calc
2331 			sub1 = logic_structs[L->list[j]]->mega->actor_xyz.x - monica->x;
2332 			sub2 = logic_structs[L->list[j]]->mega->actor_xyz.z - monica->z;
2333 
2334 			// dist
2335 			len = (PXreal)((sub1 * sub1) + (sub2 * sub2));
2336 
2337 			if (len < (PXreal)(params[1] * params[1])) {
2338 				// near
2339 				return (IR_REPEAT);
2340 			}
2341 		}
2342 	}
2343 
2344 	// no one was near the nico
2345 	return (IR_CONT);
2346 }
2347 
fn_set_watch(int32 &,int32 * params)2348 mcodeFunctionReturnCodes _game_session::fn_set_watch(int32 &, int32 *params) {
2349 	_input *psInputState;
2350 	_input sInputState;
2351 
2352 	// set the camera to follow the named mega
2353 
2354 	// params        0       name of object
2355 
2356 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
2357 	uint32 id = objects->Fetch_item_number_by_name(object_name);
2358 
2359 	if (id == 0xffffffff)
2360 		Fatal_error("fn_set_watch - object [%s] does not exist", object_name);
2361 
2362 	if (logic_structs[id]->image_type != VOXEL)
2363 		Fatal_error("fn_set_watch - object [%s] is not a person!", object_name);
2364 
2365 	// if setting back to player then cancel the camera overide
2366 	if (id == player.Fetch_player_id())
2367 		g_mission->camera_follow_id_overide = 0;
2368 	else
2369 		g_mission->camera_follow_id_overide = id;
2370 
2371 	// If we are switching back to the player then we need to put the Remora back up if
2372 	// it was up when we switched to a manual watch (but only in 3D).
2373 	if (g_px->display_mode == THREED) {
2374 		// Check if switching to player.
2375 		if (id == player.Fetch_player_id()) {
2376 			// If the Remora was active, need to bring it back up.
2377 			if (g_mission->remora_save_mode != -1) {
2378 				MS->player.Push_control_mode(ACTOR_RELATIVE);
2379 				g_oRemora->SetModeOverride((_remora::RemoraMode)g_mission->remora_save_mode);
2380 				g_oRemora->ActivateRemora((_remora::RemoraMode)g_mission->remora_save_mode);
2381 				MS->player.Set_player_status(REMORA);
2382 				MS->player.Update_input_state();
2383 				psInputState = MS->player.Fetch_input_state();
2384 				g_oRemora->CycleRemoraLogic(*psInputState);
2385 				g_mission->remora_save_mode = -1;
2386 			}
2387 		} else {
2388 			// Not switching to player so flag whether or not the Remora is active.
2389 			if (g_oRemora->IsActive()) {
2390 				// Deactivate it and remember its mode.
2391 				g_mission->remora_save_mode = (int32)g_oRemora->GetMode();
2392 				g_oRemora->SetMode(_remora::MOTION_SCAN);
2393 				g_oRemora->DeactivateRemora(TRUE8);
2394 				sInputState.UnSetButton(__UNUSEDBUTTON);
2395 				g_oRemora->CycleRemoraLogic(sInputState);
2396 				MS->player.Pop_control_mode();
2397 				MS->player.Set_player_status(STOOD);
2398 			} else {
2399 				g_mission->remora_save_mode = -1;
2400 			}
2401 		}
2402 	}
2403 
2404 	// Deactivate the Remora.
2405 
2406 	return (IR_CONT);
2407 }
2408 
fn_three_sixty_interact(int32 &,int32 *)2409 mcodeFunctionReturnCodes _game_session::fn_three_sixty_interact(int32 &, int32 *) {
2410 	// set object to use the prop 360deg interaction type
2411 
2412 	if (L->image_type != PROP)
2413 		Fatal_error("fn_three_sixty_interact - object [%s] is not a prop!", object->GetName());
2414 
2415 	L->three_sixty_interact |= THREE_SIXTY_INTERACT;
2416 
2417 	return (IR_CONT);
2418 }
2419 
fn_prop_crouch_interact(int32 &,int32 *)2420 mcodeFunctionReturnCodes _game_session::fn_prop_crouch_interact(int32 &, int32 *) {
2421 	// set object to use the prop 360deg interaction type
2422 
2423 	L->three_sixty_interact |= PROP_CROUCH_INTERACT;
2424 
2425 	return IR_CONT;
2426 }
2427 
fn_random(int32 & result,int32 * params)2428 mcodeFunctionReturnCodes _game_session::fn_random(int32 &result, int32 *params) {
2429 	// return a random number to script
2430 
2431 	// params    0   largest number possible from choice
2432 
2433 	result = g_icb->getRandomSource()->getRandomNumber(params[0] - 1);
2434 
2435 	return (IR_CONT);
2436 }
2437 
fn_change_session(int32 &,int32 * params)2438 mcodeFunctionReturnCodes _game_session::fn_change_session(int32 &, int32 *params) {
2439 	// change session within the current mission
2440 
2441 	// params    0   name of session
2442 	// params    1   name of new nico
2443 
2444 	uint32 ret;
2445 	const char *ses_name = (const char *)MemoryUtil::resolvePtr(params[0]);
2446 	const char *nico_name = (const char *)MemoryUtil::resolvePtr(params[1]);
2447 
2448 	Tdebug("session_log.txt", "fn_change_session changing to [%s]", ses_name);
2449 
2450 	g_mission->Set_new_session_name(ses_name);
2451 	g_mission->Set_init_nico_name(nico_name);
2452 
2453 	// save the players 'hits' variable
2454 	c_game_object *ob;
2455 	ob = (c_game_object *)objects->Fetch_item_by_number(player.Fetch_player_id());
2456 	ret = ob->GetVariable("hits");
2457 	g_mission->old_hits_value = ob->GetIntegerVariable(ret);
2458 
2459 	return (IR_STOP); // do no more
2460 }
2461 
fn_changed_sessions(int32 & result,int32 *)2462 mcodeFunctionReturnCodes _game_session::fn_changed_sessions(int32 &result, int32 *) {
2463 	// look for nico name logged by fn_change_session
2464 	// if found init there
2465 	// return yes or no
2466 
2467 	_feature_info *nico;
2468 	uint32 ret;
2469 
2470 	result = g_mission->Is_there_init_nico();
2471 
2472 	if (result) { // nico is waiting Removed explicit test against TRUE8 to get rid of VC5 warning
2473 		nico = (_feature_info *)features->Try_fetch_item_by_name(g_mission->Return_init_nico_name());
2474 		if (!nico)
2475 			Fatal_error("fn_changed_sessions cant find nico [%s]", g_mission->Return_init_nico_name());
2476 
2477 #define XX logic_structs[cur_id]->mega->actor_xyz.x
2478 #define ZZ logic_structs[cur_id]->mega->actor_xyz.z
2479 
2480 		logic_structs[cur_id]->mega->actor_xyz.x = nico->x;
2481 		logic_structs[cur_id]->mega->actor_xyz.y = nico->floor_y;
2482 		logic_structs[cur_id]->mega->actor_xyz.z = nico->z;
2483 
2484 		// set pan
2485 		logic_structs[cur_id]->pan = nico->direction;
2486 
2487 		// reset current hits from previous session
2488 		ret = object->GetVariable("hits");
2489 		object->SetIntegerVariable(ret, g_mission->old_hits_value);
2490 
2491 		// has coords
2492 		logic_structs[cur_id]->prop_coords_set = TRUE8;
2493 
2494 		// move player forwards a little
2495 		if (cur_id == objects->Fetch_item_number_by_name("chi")) {
2496 			// we are the player then jump player in-front of chi
2497 
2498 			PXfloat ang = nico->direction * TWO_PI;
2499 			PXfloat cang = (PXfloat)PXcos(ang);
2500 			PXfloat sang = (PXfloat)PXsin(ang);
2501 
2502 			XX += PXfloat2PXreal((75 * REAL_ONE) * sang);
2503 			ZZ += PXfloat2PXreal((75 * REAL_ONE) * cang);
2504 		}
2505 	}
2506 
2507 	return (IR_CONT);
2508 }
2509 
fn_changed_via_this_shaft(int32 & result,int32 * params)2510 mcodeFunctionReturnCodes _game_session::fn_changed_via_this_shaft(int32 &result, int32 *params) {
2511 	// a lib_session_changer_lift checks to see if its marker was the one that the player started the session on
2512 	// if so then the lift knows that it was the lift that has just arrived and therefore it is here and open
2513 
2514 	// params    0   name of our marker
2515 
2516 	const char *marker_name = (const char *)MemoryUtil::resolvePtr(params[0]);
2517 
2518 	if (g_mission->Is_there_init_nico()) {
2519 		// there is a nico
2520 		// is it ours
2521 
2522 		if (!strcmp(marker_name, g_mission->Return_init_nico_name())) {
2523 			// yes!
2524 			result = 1;
2525 			return IR_CONT;
2526 		}
2527 	}
2528 
2529 	result = 0; // no
2530 	return IR_CONT;
2531 }
2532 
fn_is_object_adjacent(int32 & result,int32 * params)2533 mcodeFunctionReturnCodes _game_session::fn_is_object_adjacent(int32 &result, int32 *params) {
2534 	// is the name object on a floor adjacent to this objects floor
2535 
2536 	// params        0   name of object
2537 
2538 	_floor *our_floor;
2539 	uint32 their_floor;
2540 	uint32 id;
2541 	uint32 j;
2542 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
2543 
2544 	our_floor = floor_def->Fetch_floor_number(L->owner_floor_rect);
2545 
2546 	if (!our_floor->num_neighbours) {
2547 		result = FALSE8; // cant be adjacent as there are non - which is impossible of course but hey
2548 		return (IR_CONT);
2549 	}
2550 
2551 	id = objects->Fetch_item_number_by_name(object_name);
2552 	if (id == 0xffffffff)
2553 		Fatal_error("fn_is_object_on_our_floor - illegal object [%s]", object_name);
2554 
2555 	their_floor = logic_structs[id]->owner_floor_rect;
2556 
2557 	// are they on our floor - haha
2558 	if (their_floor == L->owner_floor_rect) { //
2559 		result = FALSE8;                  //
2560 		return (IR_CONT);
2561 	}
2562 
2563 	// check each neighbour
2564 	for (j = 0; j < our_floor->num_neighbours; j++) {
2565 		if (our_floor->neighbour_map[j].neighbour == their_floor) {
2566 			result = TRUE8;
2567 			return (IR_CONT);
2568 		}
2569 	}
2570 
2571 	result = FALSE8;
2572 
2573 	return (IR_CONT);
2574 }
2575 
fn_is_object_on_this_floor(int32 & result,int32 * params)2576 mcodeFunctionReturnCodes _game_session::fn_is_object_on_this_floor(int32 &result, int32 *params) {
2577 	// check to see if object is on the floor passed
2578 
2579 	// params        0 name of object
2580 	//				1 name of floor
2581 
2582 	uint32 floor_id;
2583 	uint32 id;
2584 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
2585 	const char *floor_name = (const char *)MemoryUtil::resolvePtr(params[1]);
2586 
2587 	Zdebug("fn_is_object_on_this_floor [%s], [%s]", object_name, floor_name);
2588 
2589 	id = objects->Fetch_item_number_by_name(object_name);
2590 	if (id == 0xffffffff)
2591 		Fatal_error("fn_is_object_on_our_floor - illegal object [%s]", object_name);
2592 
2593 	floor_id = floor_def->floors->Fetch_item_number_by_name(floor_name);
2594 	if (floor_id == 0xffffffff)
2595 		Fatal_error("fn_are_we_on_this_floor cant locate floor [%s]", floor_name);
2596 
2597 	if (floor_id == logic_structs[id]->owner_floor_rect)
2598 		result = TRUE8;
2599 	else
2600 		result = FALSE8;
2601 
2602 	return (IR_CONT);
2603 }
2604 
fn_switch_on_the_really_neat_and_special_script_debugging_facility(int32 & result,int32 * params)2605 mcodeFunctionReturnCodes _game_session::fn_switch_on_the_really_neat_and_special_script_debugging_facility(int32 &result, int32 *params) {
2606 	// switch on daves debugging
2607 	bool8 flag = (params[0] == 0) ? FALSE8 : TRUE8;
2608 
2609 	Zdebug("\n\n****** switching ON script debugging *******\n\n");
2610 
2611 	SetScriptDebugging(flag);
2612 
2613 	result = 0;
2614 
2615 	return (IR_CONT);
2616 }
2617 
fn_switch_off_the_really_neat_and_special_script_debugging_facility(int32 & result,int32 *)2618 mcodeFunctionReturnCodes _game_session::fn_switch_off_the_really_neat_and_special_script_debugging_facility(int32 &result, int32 *) {
2619 	// switch off daves debugging
2620 
2621 	Zdebug("\n\n------ switching OFF script debugging ------\n\n");
2622 
2623 	SetScriptDebugging(FALSE8);
2624 
2625 	result = 0;
2626 
2627 	return (IR_CONT);
2628 }
2629 
fn_preload_custom_mega_anim(int32 & result,int32 * params)2630 mcodeFunctionReturnCodes _game_session::fn_preload_custom_mega_anim(int32 &result, int32 *params) {
2631 	// set a resource loading
2632 	// we have devided fn_functions into types (i.e. mega animations) in-case there are cluster complications
2633 
2634 	// params    0   name of final anim
2635 
2636 	return (fn_prime_custom_anim(result, params));
2637 }
2638 
fn_no_logic(int32 &,int32 *)2639 mcodeFunctionReturnCodes _game_session::fn_no_logic(int32 &, int32 *) {
2640 	// set wait_status to no-logic which stops the script being invoked
2641 
2642 	Tdebug("logic_modes.txt", "fn_no_logic freezing [%s]", object->GetName());
2643 
2644 	L->big_mode = __NO_LOGIC;
2645 	L->cycle_time = 0; // for mt display
2646 
2647 	return (IR_CONT);
2648 }
2649 
fn_set_sleep(int32 &,int32 * params)2650 mcodeFunctionReturnCodes _game_session::fn_set_sleep(int32 &, int32 *params) {
2651 	// add or remove no-logic
2652 
2653 	// params        0       name
2654 	//				1     0 off, 1 on
2655 
2656 	uint32 id;
2657 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
2658 
2659 	id = objects->Fetch_item_number_by_name(object_name);
2660 	if (id == 0xffffffff)
2661 		Fatal_error("fn_set_sleep - illegal object [%s]", object_name);
2662 
2663 	if (params[1]) {
2664 		logic_structs[id]->big_mode = __NO_LOGIC;
2665 		logic_structs[id]->cycle_time = 0; // for mt display
2666 	} else {
2667 		logic_structs[id]->big_mode = __SCRIPT;
2668 	}
2669 
2670 	return IR_CONT;
2671 }
2672 
fn_mega_use_lift(int32 &,int32 * params)2673 mcodeFunctionReturnCodes _game_session::fn_mega_use_lift(int32 &, int32 *params) {
2674 	// trigger a lift - manually
2675 	// no safety checking here - scripts must assure all is in right position, etc.
2676 
2677 	// just set a request flag - putting in function gives us scope for seamless future changes
2678 
2679 	// params        0   name of lift
2680 
2681 	c_game_object *ob;
2682 	uint32 var_num;
2683 	const char *lift_name = (const char *)MemoryUtil::resolvePtr(params[0]);
2684 
2685 	ob = (c_game_object *)objects->Fetch_item_by_name(lift_name);
2686 	if (!ob)
2687 		Fatal_error("fn_use_lift - illegal object [%s]", lift_name);
2688 
2689 	var_num = ob->GetVariable("request");
2690 	if (var_num == (uint32)-1)
2691 		Fatal_error("fn_use_lift - object [%s] doesnt have REQUEST variable", lift_name);
2692 
2693 	ob->SetIntegerVariable(var_num, 2); // two is trigger value
2694 
2695 	return (IR_CONT);
2696 }
2697 
2698 // fn_make_remora_beep(1) makes the remora beep notice us, 0 makes it not do...
fn_make_remora_beep(int32 &,int32 * params)2699 mcodeFunctionReturnCodes _game_session::fn_make_remora_beep(int32 &, int32 *params) {
2700 	if (logic_structs[cur_id]->image_type != VOXEL)
2701 		Fatal_error("fn_make_remora_beep - object %s is not a person! what is this?", object->GetName());
2702 
2703 	if (params[0] == 0) {
2704 		L->mega->make_remora_beep = FALSE8;
2705 		Zdebug("%s->fn_make_remora_beep(no beep)\n", object->GetName());
2706 	} else if (params[0] == 1) {
2707 		L->mega->make_remora_beep = TRUE8;
2708 		Zdebug("%s->fn_make_remora_beep(beep)\n", object->GetName());
2709 	} else
2710 		Fatal_error("fn_make_remora_beep - object [%s] called with value %d", object->GetName(), params[0]);
2711 
2712 	return (IR_CONT);
2713 }
2714 
2715 // fn_set_evil(1) sets us to evil mode for beeping and possibly scanner, fn_set_evil(0) sets us to harmless
fn_set_evil(int32 &,int32 * params)2716 mcodeFunctionReturnCodes _game_session::fn_set_evil(int32 &, int32 *params) {
2717 	if (logic_structs[cur_id]->image_type != VOXEL)
2718 		Fatal_error("fn_set_evil - object %s is not a person! what is this?", object->GetName());
2719 
2720 	if (params[0] == 0) {
2721 		L->mega->is_evil = FALSE8;
2722 		Zdebug("%s->fn_set_evil(NOT_EVIL!)\n", object->GetName());
2723 	} else if (params[0] == 1) {
2724 		L->mega->is_evil = TRUE8;
2725 		Zdebug("%s->fn_set_evil(EVIL!)\n", object->GetName());
2726 	} else
2727 		Fatal_error("fn_set_evil - object [%s] called with value %d", object->GetName(), params[0]);
2728 
2729 	return (IR_CONT);
2730 }
2731 
fn_set_object_type(int32 &,int32 * params)2732 mcodeFunctionReturnCodes _game_session::fn_set_object_type(int32 &, int32 *params) {
2733 	// This allows an object to set its type variable.  At the moment, this is picked up only by the
2734 	// Remora, for the purposes of displaying a suitable symbol, but we may be able to add other
2735 	// functionality on it if we require.
2736 	logic_structs[cur_id]->object_type = (__object_type)params[0];
2737 	return (IR_CONT);
2738 }
2739 
fn_do_not_disturb(int32 &,int32 * params)2740 mcodeFunctionReturnCodes _game_session::fn_do_not_disturb(int32 &, int32 *params) {
2741 	bool8 bDoNotDisturb;
2742 
2743 	Zdebug("fn_do_not_disturb( %d ) called by object %d", (uint32)params[0], cur_id);
2744 
2745 	// Typesafe convert the parameter.
2746 	bDoNotDisturb = ((uint32)params[0] == 0) ? FALSE8 : TRUE8;
2747 
2748 	logic_structs[cur_id]->do_not_disturb = bDoNotDisturb;
2749 
2750 	// Calling script can continue.
2751 	return (IR_CONT);
2752 }
2753 
fn_is_mega_within_area(int32 & result,int32 * params)2754 mcodeFunctionReturnCodes _game_session::fn_is_mega_within_area(int32 &result, int32 *params) {
2755 	// is the named object within the specified rect
2756 
2757 	// params    0           name of object
2758 	//			1,2,3,4    x,z, x1,z1
2759 
2760 	// returns   true/false
2761 
2762 	uint32 id;
2763 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
2764 
2765 	id = (uint32)objects->Fetch_item_number_by_name(object_name);
2766 
2767 	if (id == 0xffffffff)
2768 		Fatal_error("fn_is_mega_within_area - illegal object [%s]", object_name);
2769 
2770 	if (logic_structs[id]->image_type == PROP)
2771 		Fatal_error("fn_is_mega_within_area - object [%s] not a mega", object_name);
2772 
2773 	if ((logic_structs[id]->mega->actor_xyz.x > (PXreal)params[1]) && (logic_structs[id]->mega->actor_xyz.x < (PXreal)params[3]) &&
2774 	    (logic_structs[id]->mega->actor_xyz.z > (PXreal)params[2]) && (logic_structs[id]->mega->actor_xyz.z < (PXreal)params[4])) {
2775 		result = TRUE8;
2776 	} else {
2777 		result = FALSE8;
2778 	}
2779 
2780 	return IR_CONT;
2781 }
2782 
fn_end_mission(int32 &,int32 *)2783 mcodeFunctionReturnCodes _game_session::fn_end_mission(int32 &, int32 *) {
2784 	// end the mission and drop back to console, or, the main script
2785 
2786 	// shhhhhh - make everything quiet
2787 	PauseSounds();
2788 
2789 	g_mission->End_mission();
2790 
2791 	return IR_STOP;
2792 }
2793 
fn_restart_gamescript(int32 &,int32 *)2794 mcodeFunctionReturnCodes _game_session::fn_restart_gamescript(int32 &, int32 *) {
2795 	// reset gamescript so that game begins afresh
2796 	// presumably first thing in GS will be Start new game/Restore previous screen
2797 
2798 	return IR_CONT;
2799 }
2800 
fn_am_i_player(int32 & result,int32 *)2801 mcodeFunctionReturnCodes _game_session::fn_am_i_player(int32 &result, int32 *) {
2802 	// This function returns true if the player calls it, false otherwise.  Allows an interact
2803 	// script to tell if the player is using it or another mega.
2804 
2805 	if (cur_id == player.Fetch_player_id())
2806 		result = 1;
2807 	else
2808 		result = 0;
2809 
2810 	// Calling script can continue.
2811 	return (IR_CONT);
2812 }
2813 
fn_start_conveyor(int32 &,int32 * params)2814 mcodeFunctionReturnCodes _game_session::fn_start_conveyor(int32 &, int32 *params) {
2815 	// start a conveyor belt
2816 
2817 	// params    0   x
2818 	//			1  y
2819 	//			2  z
2820 	//			3  x1
2821 	//			4  z1
2822 	//			5  xm
2823 	//			6  zm
2824 
2825 	uint32 j;
2826 
2827 	for (j = 0; j < MAX_conveyors; j++) {
2828 		if (conveyors[j].moving == FALSE8) {
2829 			// found a slot
2830 			conveyors[j].x = (PXreal)params[0];
2831 			conveyors[j].y = (PXreal)params[1];
2832 			conveyors[j].z = (PXreal)params[2];
2833 			conveyors[j].x1 = (PXreal)params[3];
2834 			conveyors[j].z1 = (PXreal)params[4];
2835 			conveyors[j].xm = (PXreal)params[5];
2836 			conveyors[j].zm = (PXreal)params[6];
2837 
2838 			conveyors[j].moving = TRUE8;
2839 
2840 			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]);
2841 
2842 			return IR_CONT;
2843 		}
2844 	}
2845 
2846 	Fatal_error("too many conveyors!");
2847 	return IR_CONT;
2848 }
2849 
fn_stop_conveyor(int32 &,int32 * params)2850 mcodeFunctionReturnCodes _game_session::fn_stop_conveyor(int32 &, int32 *params) {
2851 	// stop a conveyor
2852 
2853 	uint32 j;
2854 
2855 	for (j = 0; j < MAX_conveyors; j++) {
2856 		if (conveyors[j].moving == TRUE8) {
2857 			if ((conveyors[j].x == (PXreal)params[0]) && (conveyors[j].z == (PXreal)params[1])) {
2858 				Tdebug("conveyor.txt", "conveyor %d stopped", j);
2859 				conveyors[j].moving = FALSE8;
2860 				return IR_CONT;
2861 			}
2862 		}
2863 	}
2864 
2865 	Fatal_error("no conveyor @ %d,%d", params[0], params[1]);
2866 
2867 	return IR_CONT;
2868 }
2869 
Process_conveyors()2870 void _game_session::Process_conveyors() {
2871 	uint32 j;
2872 
2873 	for (j = 0; j < MAX_conveyors; j++) {
2874 		if (conveyors[j].moving == TRUE8) {
2875 			if ((logic_structs[player.Fetch_player_id()]->mega->actor_xyz.x > conveyors[j].x) &&
2876 			    (logic_structs[player.Fetch_player_id()]->mega->actor_xyz.y == conveyors[j].y) &&
2877 			    (logic_structs[player.Fetch_player_id()]->mega->actor_xyz.x < conveyors[j].x1) &&
2878 			    (logic_structs[player.Fetch_player_id()]->mega->actor_xyz.z > conveyors[j].z) &&
2879 			    (logic_structs[player.Fetch_player_id()]->mega->actor_xyz.z < conveyors[j].z1)) {
2880 				logic_structs[player.Fetch_player_id()]->mega->actor_xyz.x += conveyors[j].xm;
2881 				logic_structs[player.Fetch_player_id()]->mega->actor_xyz.z += conveyors[j].zm;
2882 			}
2883 		}
2884 	}
2885 }
2886 
fn_register_ladder(int32 & result,int32 * params)2887 mcodeFunctionReturnCodes _game_session::fn_register_ladder(int32 &result, int32 *params) {
2888 	// register a ladder
2889 
2890 	// params    0   target marker name
2891 	//			1  1==top (else bottom)
2892 	//			2  length
2893 
2894 	const char *marker_name = (const char *)MemoryUtil::resolvePtr(params[0]);
2895 
2896 	result = Register_stair_or_ladder(marker_name, (bool8)params[1], params[2], FALSE8, 24);
2897 
2898 	return IR_CONT;
2899 }
2900 
fn_register_stairway(int32 & result,int32 * params)2901 mcodeFunctionReturnCodes _game_session::fn_register_stairway(int32 &result, int32 *params) {
2902 	// register a stairway
2903 
2904 	// params    0   target marker name
2905 	//			1  1==top (else bottom)
2906 	//			2  length
2907 
2908 	const char *marker_name = (const char *)MemoryUtil::resolvePtr(params[0]);
2909 
2910 	result = Register_stair_or_ladder(marker_name, (bool8)params[1], params[2], TRUE8, 18);
2911 
2912 	return IR_CONT;
2913 }
2914 
fn_activate_stair_or_ladder(int32 &,int32 * params)2915 mcodeFunctionReturnCodes _game_session::fn_activate_stair_or_ladder(int32 &, int32 *params) {
2916 	Set_state_of_stair_or_ladder((uint32)params[0], TRUE8);
2917 
2918 	return (IR_CONT);
2919 }
2920 
fn_deactivate_stair_or_ladder(int32 &,int32 * params)2921 mcodeFunctionReturnCodes _game_session::fn_deactivate_stair_or_ladder(int32 &, int32 *params) {
2922 	Set_state_of_stair_or_ladder((uint32)params[0], FALSE8);
2923 
2924 	return (IR_CONT);
2925 }
2926 
Set_state_of_stair_or_ladder(uint32 nIndex,bool8 bState)2927 void _game_session::Set_state_of_stair_or_ladder(uint32 nIndex, bool8 bState) {
2928 	if (nIndex > num_stairs)
2929 		Fatal_error("Index %d out or range 0-%d in _game_session::Set_state_of_stair_or_ladder()", nIndex, num_stairs - 1);
2930 
2931 	stairs[nIndex].live = bState;
2932 	// do the other end
2933 	stairs[stairs[nIndex].opposite_number].live = bState;
2934 }
2935 
Register_stair_or_ladder(const char * target,bool8 top,uint32 length,bool8 isstair,uint32 stepcms)2936 uint32 _game_session::Register_stair_or_ladder(const char *target, bool8 top, uint32 length, bool8 isstair, uint32 stepcms) {
2937 	_feature_info *stair;
2938 	_feature_info *dest_stair;
2939 	PXreal x1, z1, x2, z2, x3, z3;
2940 	uint32 dest_stair_id;
2941 	uint8 j = 0;
2942 
2943 	if (!length)
2944 		Fatal_error("%s has 0 length", object->GetName());
2945 	if (length > 1000)
2946 		Fatal_error("%s has illegal length %d", object->GetName(), length);
2947 
2948 	// get our nico
2949 	stair = (_feature_info *)features->Try_fetch_item_by_name(const_cast<char *>(object->GetName()));
2950 	// get other end
2951 	dest_stair = (_feature_info *)features->Try_fetch_item_by_name(target);
2952 	dest_stair_id = objects->Fetch_item_number_by_name(target);
2953 
2954 	if (!stair)
2955 		Fatal_error("fn_register_stairway - cant find nico %s", object->GetName());
2956 	if (!dest_stair)
2957 		Fatal_error("fn_register_stairway - cant find nico %s", target);
2958 	if (num_stairs == MAX_stairs)
2959 		Fatal_error("too many stairs - max = %d", MAX_stairs);
2960 
2961 	stairs[num_stairs].pan = stair->direction;
2962 	stairs[num_stairs].pan_ref = stair->direction;
2963 	stairs[num_stairs].x = stair->x;
2964 	stairs[num_stairs].z = stair->z;
2965 
2966 	// link up with other end
2967 	for (j = 0; j < num_stairs; j++) {
2968 		if (stairs[j].stair_id == dest_stair_id) {             // found the target - its already set itself up
2969 			stairs[j].opposite_number = (uint8)num_stairs; // its opposite is us
2970 			stairs[num_stairs].opposite_number = j;        // its our opposite number
2971 			break;
2972 		}
2973 	}
2974 
2975 	PXfloat ang = stair->direction * TWO_PI;
2976 	PXfloat cang = (PXfloat)PXcos(ang);
2977 	PXfloat sang = (PXfloat)PXsin(ang);
2978 	PXreal dx = PXfloat2PXreal((PXfloat)length * cang);
2979 	PXreal dz = PXfloat2PXreal((PXfloat)length * sang);
2980 
2981 #define STAIR_BARRIER_OFFSET 0
2982 
2983 	x1 = stair->x + PXfloat2PXreal(STAIR_BARRIER_OFFSET * sang);
2984 	z1 = stair->z + PXfloat2PXreal(STAIR_BARRIER_OFFSET * cang);
2985 
2986 	x2 = x1 - dx;
2987 	z2 = z1 + dz;
2988 
2989 	x3 = x1 + dx;
2990 	z3 = z1 - dz;
2991 
2992 	// new constructor for barrier...
2993 	stairs[num_stairs].bar = _route_barrier(x2, z2, x3, z3, stair->floor_y, (PXreal)0 /* dont care */, BRICK /* dont care */);
2994 
2995 	// create the BCM maths----------------------------------------------
2996 	// The barrier has coordinates x2, z2 to x3, z3.
2997 	// Fill in the structure that holds the extra collision maths.
2998 
2999 	stairs[num_stairs].bar.bcm().Generate(x2, z2, x3, z3);
3000 	stairs[num_stairs].bar.Create_pan();
3001 
3002 	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(),
3003 	       stairs[num_stairs].bar.bcm().alinedist(), stairs[num_stairs].bar.bcm().blinedist(), stairs[num_stairs].bar.bcm().lpx(), stairs[num_stairs].bar.bcm().lpz(),
3004 	       stairs[num_stairs].bar.bcm().alpx(), stairs[num_stairs].bar.bcm().alpz(), stairs[num_stairs].bar.bcm().blpx(), stairs[num_stairs].bar.bcm().blpz());
3005 
3006 	// create the BCM maths----------------------------------------------
3007 
3008 	// work out unit height
3009 	stairs[num_stairs].units = (uint8)((PXfabs(dest_stair->floor_y - stair->floor_y) + (stepcms / 2)) / stepcms);
3010 
3011 	// dir
3012 	if (!top)                              // if not the top
3013 		stairs[num_stairs].up = TRUE8; // then its the bottom which means we're going up
3014 	else {
3015 		stairs[num_stairs].up = FALSE8; // else down
3016 
3017 		// top of ladders have their pan adjusted
3018 		if (!isstair)
3019 			stairs[num_stairs].pan_ref = stair->direction + HALF_TURN;
3020 	}
3021 
3022 	// set id
3023 	stairs[num_stairs].stair_id = (uint8)cur_id;
3024 
3025 	// type
3026 	stairs[num_stairs].is_stair = isstair;
3027 
3028 	// make stair active
3029 	stairs[num_stairs].live = TRUE8;
3030 
3031 	// diagnostics
3032 	if (isstair)
3033 		Tdebug("stairs.txt", "\nInit stair %d", num_stairs);
3034 	else
3035 		Tdebug("stairs.txt", "\nInit ladder %d", num_stairs);
3036 	Tdebug("stairs.txt", "marker %3.2f,%3.2f, %3.2f", stair->x, stair->floor_y, stair->z);
3037 	Tdebug("stairs.txt", "point 1 = %3.2f, %3.2f", x2, z2);
3038 	Tdebug("stairs.txt", "point 2 = %3.2f, %3.2f", x3, z3);
3039 	Tdebug("stairs.txt", "units = %d", stairs[num_stairs].units);
3040 	if (stairs[num_stairs].up)
3041 		Tdebug("stairs.txt", "going up");
3042 	else
3043 		Tdebug("stairs.txt", "going down");
3044 
3045 	L->list_result = num_stairs; // script needs to get this
3046 
3047 	return stairs[num_stairs++].units; // set to uploop in object - instead of implementor!
3048 }
3049 
fn_align_with_floor(int32 &,int32 *)3050 mcodeFunctionReturnCodes _game_session::fn_align_with_floor(int32 &, int32 *) {
3051 	// mega climbing stairs and ladder calls this afterward to realign with artist misaligned floors
3052 
3053 	floor_def->Allign_with_floor(M);
3054 
3055 	return IR_CONT;
3056 }
3057 
fn_load_players_gun(int32 &,int32 * params)3058 mcodeFunctionReturnCodes _game_session::fn_load_players_gun(int32 &, int32 *params) {
3059 	// put bullets in the players gun
3060 
3061 	player.SetBullets(params[0]);
3062 
3063 	return IR_CONT;
3064 }
3065 
fn_flash_health(int32 &,int32 *)3066 mcodeFunctionReturnCodes _game_session::fn_flash_health(int32 &, int32 *) {
3067 	// flash the health when you get shot
3068 
3069 	health_time = 12;
3070 
3071 	return IR_CONT;
3072 }
fn_set_anim_speed(int32 &,int32 * params)3073 mcodeFunctionReturnCodes _game_session::fn_set_anim_speed(int32 &, int32 *params) {
3074 	// set a megas animation playback rate
3075 
3076 	// params    0   rate
3077 
3078 	if (logic_structs[cur_id]->image_type != VOXEL)
3079 		Fatal_error("fn_set_anim_speed says people only!");
3080 
3081 	M->anim_speed = (uint8)params[0];
3082 
3083 	return IR_CONT;
3084 }
3085 
fn_push_coords(int32 &,int32 *)3086 mcodeFunctionReturnCodes _game_session::fn_push_coords(int32 &, int32 *) {
3087 	// push coordinates - used before megas attempt to climb stairs or ladders - for save games
3088 
3089 	M->pushed = TRUE8;
3090 
3091 	memcpy(&M->pushed_actor_xyz, &M->actor_xyz, sizeof(PXvector));
3092 
3093 	return IR_CONT;
3094 }
3095 
fn_pop_coords(int32 &,int32 *)3096 mcodeFunctionReturnCodes _game_session::fn_pop_coords(int32 &, int32 *) {
3097 	// remove previous pop
3098 
3099 	M->pushed = FALSE8;
3100 
3101 	return IR_CONT;
3102 }
3103 
fn_quick_restart(int32 & result,int32 *)3104 mcodeFunctionReturnCodes _game_session::fn_quick_restart(int32 &result, int32 *) {
3105 	// reset game now or not
3106 	// if not then mission ends
3107 	// if so then simply reset the player
3108 
3109 	// if ( MessageBox(windowHandle, "reset player?", "would you like to...", MB_YESNO | MB_DEFBUTTON2 ) == IDYES )
3110 	{
3111 		result = 1; // do
3112 		MS->Restart_player();
3113 	}
3114 
3115 	return IR_CONT;
3116 }
3117 
fn_shadows_on(int32 &,int32 *)3118 mcodeFunctionReturnCodes _game_session::fn_shadows_on(int32 &, int32 *) {
3119 	// shadows back on
3120 
3121 	if (logic_structs[cur_id]->image_type != VOXEL)
3122 		Fatal_error("fn_shadows_on says people only!");
3123 
3124 	M->drawShadow = TRUE8; // shadows back on
3125 
3126 	return IR_CONT;
3127 }
3128 
fn_shadows_off(int32 &,int32 *)3129 mcodeFunctionReturnCodes _game_session::fn_shadows_off(int32 &, int32 *) {
3130 	// shadows back on
3131 
3132 	if (logic_structs[cur_id]->image_type != VOXEL)
3133 		Fatal_error("fn_shadows_off says people only!");
3134 
3135 	M->drawShadow = FALSE8; // shadows back on
3136 
3137 	return IR_CONT;
3138 }
3139 
fn_set_shade_percentage(int32 &,int32 * params)3140 mcodeFunctionReturnCodes _game_session::fn_set_shade_percentage(int32 &, int32 *params) {
3141 	// set shade percentage figure for mega
3142 
3143 	if (L->image_type != VOXEL)
3144 		Fatal_error("fn_set_shade_percentage [%s] says people only!", object->GetName());
3145 	if (params[0] > 99)
3146 		Fatal_error("fn_set_shade_percentage [%s] percentages usually go 0-99", object->GetName());
3147 
3148 	M->inShadePercentage = (uint8)params[0];
3149 
3150 	return IR_CONT;
3151 }
3152 
fn_set_half_character_width(int32 &,int32 * params)3153 mcodeFunctionReturnCodes _game_session::fn_set_half_character_width(int32 &, int32 *params) {
3154 	// adjust the default barrier extrapolation for route barriers - for people like spectre who is very big
3155 
3156 	if (!M)
3157 		Fatal_error("fn_set_door_width only for megas [%s]", object->GetName());
3158 
3159 	M->extrap_size = (uint8)params[0];
3160 
3161 	return IR_CONT;
3162 }
3163 
fn_set_visible(int32 &,int32 * params)3164 mcodeFunctionReturnCodes _game_session::fn_set_visible(int32 &, int32 *params) {
3165 	// set high level on off clip
3166 	// params        0   0 off 1 on
3167 
3168 	if (!M)
3169 		Fatal_error("%s fn_set_visible is for megas only", object->GetName());
3170 
3171 	M->display_me = (bool8)params[0];
3172 
3173 	return IR_CONT;
3174 }
3175 
fn_set_object_visible(int32 &,int32 * params)3176 mcodeFunctionReturnCodes _game_session::fn_set_object_visible(int32 &, int32 *params) {
3177 	uint32 nObjectID;
3178 
3179 	const char *object_name = (const char *)MemoryUtil::resolvePtr(params[0]);
3180 
3181 	// Find the target object's ID.
3182 	nObjectID = objects->Fetch_item_number_by_name(object_name);
3183 
3184 	// Make sure object is a mega character.
3185 	if (!(logic_structs[nObjectID]->mega))
3186 		Fatal_error("fn_set_object_visible is for megas only");
3187 
3188 	// Right it is a mega, so set its flag.
3189 	logic_structs[nObjectID]->mega->display_me = ((int32)params[1] == 0) ? FALSE8 : TRUE8;
3190 
3191 	// Calling script can continue.
3192 	return (IR_CONT);
3193 }
3194 
3195 // fn_set_interact_look_height(h)
3196 // sets the height of an interact object for the looking around code
3197 // the units are cm above the floor...
fn_set_interact_look_height(int32 &,int32 * params)3198 mcodeFunctionReturnCodes _game_session::fn_set_interact_look_height(int32 &, int32 *params) {
3199 	int32 h = params[0];
3200 
3201 	L->look_height = h;
3202 
3203 	return IR_CONT;
3204 }
3205 
fn_set_to_dead(int32 &,int32 *)3206 mcodeFunctionReturnCodes _game_session::fn_set_to_dead(int32 &, int32 *) {
3207 	// set the dead flag - we have a flag for speed of access
3208 
3209 	if (!L->mega)
3210 		Fatal_error("fn_set_to_dead called for [%s] but not a mega", object->GetName());
3211 
3212 	L->mega->dead = TRUE8;
3213 
3214 	return IR_CONT;
3215 }
3216 
fn_set_camera_hold(int32 &,int32 * params)3217 mcodeFunctionReturnCodes _game_session::fn_set_camera_hold(int32 &, int32 *params) {
3218 	// switch camera hold mode on or off
3219 
3220 	if (M)
3221 		Fatal_error("fn_set_camera_hold called for [%s] but this is for props only", object->GetName());
3222 
3223 	// find entry for this object via its name, which we find via its number :(
3224 	if (!prop_anims->Try_fetch_item_by_name(object->GetName()))
3225 		return IR_CONT; // item has no prop entry - so keep it live
3226 
3227 	if (params[0])
3228 		L->hold_mode = prop_camera_hold;
3229 	else
3230 		L->hold_mode = none;
3231 
3232 	return IR_CONT;
3233 }
3234 
fn_set_mega_wait_for_player(int32 &,int32 *)3235 mcodeFunctionReturnCodes _game_session::fn_set_mega_wait_for_player(int32 &, int32 *) {
3236 	// mega will pause until the player arrives
3237 
3238 	if (!M)
3239 		Fatal_error("fn_set_mega_wait_for_player called for [%s] but not a mega", object->GetName());
3240 
3241 	L->big_mode = __MEGA_INITIAL_FLOOR_HELD;
3242 
3243 	return IR_CONT;
3244 }
3245 
fn_set_mega_off_camera_hold(int32 &,int32 *)3246 mcodeFunctionReturnCodes _game_session::fn_set_mega_off_camera_hold(int32 &, int32 *) {
3247 	// mega will pause when not on_camera
3248 
3249 	if (!M)
3250 		Fatal_error("fn_set_mega_off_camera_hold called for [%s] but not a mega", object->GetName());
3251 
3252 	L->big_mode = __MEGA_PLAYER_FLOOR_HELD;
3253 	L->hold_mode = mega_player_floor_hold;
3254 
3255 	return IR_CONT;
3256 }
3257 
fn_set_mega_slice_hold(int32 &,int32 * params)3258 mcodeFunctionReturnCodes _game_session::fn_set_mega_slice_hold(int32 &, int32 *params) {
3259 	// mega will pause until the player arrives
3260 
3261 	// params        0   y distance to stray before character holds again
3262 
3263 	if (!M)
3264 		Fatal_error("fn_set_mega_slice_hold called for [%s] but not a mega", object->GetName());
3265 
3266 	L->big_mode = __MEGA_SLICE_HELD;
3267 	L->hold_mode = mega_slice_hold;
3268 	M->slice_hold_tolerance = (uint32)params[0];
3269 
3270 	return IR_CONT;
3271 }
3272 
fn_lock_y(int32 &,int32 * params)3273 mcodeFunctionReturnCodes _game_session::fn_lock_y(int32 &, int32 *params) {
3274 	// lock a y coord of a named nico marker - the floor chooser will use this value. Good for lifts that cross multiple slices, etc
3275 
3276 	_feature_info *nico;
3277 	const char *marker_name = (const char *)MemoryUtil::resolvePtr(params[0]);
3278 
3279 	nico = (_feature_info *)features->Try_fetch_item_by_name(marker_name);
3280 	if (!nico)
3281 		Fatal_error("fn_lock_y by [%s] for nico [%s] finds no such nico", object->GetName(), marker_name);
3282 
3283 	M->y_locked = TRUE8;
3284 	M->y_lock = nico->y;
3285 
3286 	return IR_CONT;
3287 }
3288 
fn_unlock_y(int32 &,int32 *)3289 mcodeFunctionReturnCodes _game_session::fn_unlock_y(int32 &, int32 *) {
3290 	// cancel locked y
3291 
3292 	M->y_locked = FALSE8;
3293 
3294 	return IR_CONT;
3295 }
3296 
fn_flip_pan(int32 &,int32 *)3297 mcodeFunctionReturnCodes _game_session::fn_flip_pan(int32 &, int32 *) {
3298 	// flip the pan 180deg - used, for example, when megas get off the bottom of ladders
3299 	// this is why we are going to engine code this type of logic next time
3300 
3301 	L->pan += HALF_TURN;
3302 
3303 	return IR_CONT;
3304 }
3305 
fn_snap_to_ladder_bottom(int32 &,int32 *)3306 mcodeFunctionReturnCodes _game_session::fn_snap_to_ladder_bottom(int32 &, int32 *) {
3307 // used to position non player megas going up ladders
3308 
3309 #define MEGA_SNAP_UP 40
3310 
3311 	for (uint8 j = 0; j < num_stairs; j++) {
3312 		if (stairs[j].stair_id == M->target_id) { // found the target - its already set itself up
3313 			Snap_to_ladder(&stairs[j], MEGA_SNAP_UP);
3314 			return IR_CONT;
3315 		}
3316 	}
3317 
3318 	return IR_CONT;
3319 }
3320 
fn_snap_to_ladder_top(int32 &,int32 *)3321 mcodeFunctionReturnCodes _game_session::fn_snap_to_ladder_top(int32 &, int32 *) {
3322 // used to position non player megas going down ladders
3323 
3324 #define MEGA_SNAP_DOWN 85
3325 
3326 	for (uint8 j = 0; j < num_stairs; j++) {
3327 		if (stairs[j].stair_id == M->target_id) { // found the target - its already set itself up
3328 			Snap_to_ladder(&stairs[j], MEGA_SNAP_DOWN);
3329 			return IR_CONT;
3330 		}
3331 	}
3332 
3333 	return IR_CONT;
3334 }
3335 
fn_set_to_floor(int32 &,int32 * params)3336 mcodeFunctionReturnCodes _game_session::fn_set_to_floor(int32 &, int32 *params) {
3337 	// locate a character onto a specified floor
3338 	// crudely sticks the character in the middle of the first floor LRECT
3339 
3340 	//	params[0]    ascii name of floor
3341 
3342 	//const char *floor_name = (const char *)MemoryUtil::resolvePtr(params[0]);
3343 
3344 	// get the floor
3345 	//_floor *floor = (_floor *)floor_def->Fetch_named_floor(floor_name);
3346 
3347 	return IR_CONT;
3348 }
3349 
3350 } // End of namespace ICB
3351