1285 lines
39 KiB
Plaintext
1285 lines
39 KiB
Plaintext
//#include maps\mp\_utility;
|
|
#include common_scripts\utility;
|
|
|
|
init()
|
|
{
|
|
if ( getdvar( "scr_elevator_disabled" ) == "1" )
|
|
return;
|
|
|
|
// skip if no elevators in this level
|
|
elevator_groups = getentarray( "elevator_group", "targetname" );
|
|
if ( !isdefined( elevator_groups ) )
|
|
return;
|
|
if ( !elevator_groups.size )
|
|
return;
|
|
|
|
// Press and hold &&1 to call elevator.
|
|
precacheString( &"ELEVATOR_CALL_HINT" );
|
|
// Press and hold &&1 to use elevator.
|
|
precacheString( &"ELEVATOR_USE_HINT" );
|
|
// Press and hold &&1 to select floor.
|
|
precacheString( &"ELEVATOR_FLOOR_SELECT_HINT" );
|
|
|
|
precacheMenu( "elevator_floor_selector" );
|
|
|
|
thread elevator_update_global_dvars();
|
|
|
|
// find and build all elevators in the level
|
|
level.elevators = [];
|
|
|
|
// elevator construction dvars:
|
|
// vertical units for "call button" to link near by elevator per floor
|
|
level.elevator_callbutton_link_v = elevator_get_dvar_int( "scr_elevator_callbutton_link_v", "96" );
|
|
// horizontal units for "call button" to link near by elevator per floor
|
|
level.elevator_callbutton_link_h = elevator_get_dvar_int( "scr_elevator_callbutton_link_h", "256" );
|
|
|
|
build_elevators();
|
|
position_elevators();
|
|
elevator_call();
|
|
|
|
if ( !level.elevators.size )
|
|
return;
|
|
|
|
foreach ( elevator in level.elevators )
|
|
{
|
|
elevator thread elevator_think();
|
|
elevator thread elevator_sound_think();
|
|
}
|
|
|
|
thread elevator_debug();
|
|
}
|
|
|
|
elevator_update_global_dvars()
|
|
{
|
|
while ( 1 )
|
|
{
|
|
level.elevator_accel = elevator_get_dvar( "scr_elevator_accel", "0.2" ); // acceleration time in seconds
|
|
level.elevator_decel = elevator_get_dvar( "scr_elevator_decel", "0.2" ); // deceleration time in seconds
|
|
level.elevator_music = elevator_get_dvar_int( "scr_elevator_music", "1" ); // elevator music
|
|
level.elevator_speed = elevator_get_dvar_int( "scr_elevator_speed", "96" ); // units per second
|
|
level.elevator_innerdoorspeed = elevator_get_dvar_int( "scr_elevator_innerdoorspeed", "14" ); // inner door speed
|
|
level.elevator_outterdoorspeed = elevator_get_dvar_int( "scr_elevator_outterdoorspeed", "16" ); // outter door speed
|
|
level.elevator_return = elevator_get_dvar_int( "scr_elevator_return", "0" ); // 1: elevator returns to original floor
|
|
level.elevator_waittime = elevator_get_dvar_int( "scr_elevator_waittime", "6" ); // wait in seconds before closing door
|
|
level.elevator_aggressive_call = elevator_get_dvar_int( "scr_elevator_aggressive_call", "0" ); // calls all available elevators to floor
|
|
level.elevator_debug = elevator_get_dvar_int( "debug_elevator", "0" ); // 2: full 1: simple, 0: debug off
|
|
|
|
// mp & sp default differences:
|
|
if ( isSP() )
|
|
{
|
|
level.elevator_motion_detection = elevator_get_dvar_int( "scr_elevator_motion_detection", "0" );// calls elevators via motion detection
|
|
}
|
|
else
|
|
{
|
|
level.elevator_motion_detection = elevator_get_dvar_int( "scr_elevator_motion_detection", "1" );// calls elevators via motion detection
|
|
}
|
|
|
|
wait 1;
|
|
}
|
|
}
|
|
|
|
//==========================================================================//
|
|
// === ELEVATOR LOGIC === //
|
|
//==========================================================================//
|
|
|
|
elevator_think()
|
|
{
|
|
// self is elevator, self.e[]
|
|
self elevator_fsm( "[A]" );
|
|
}
|
|
|
|
elevator_call()
|
|
{
|
|
foreach ( callbutton in level.elevator_callbuttons )
|
|
callbutton thread monitor_callbutton();
|
|
}
|
|
|
|
floor_override( inside_trig )
|
|
{
|
|
self endon( "elevator_moving" );
|
|
|
|
self.floor_override = 0;
|
|
self.overrider = undefined;
|
|
|
|
while ( 1 )
|
|
{
|
|
inside_trig waittill( "trigger", player );
|
|
self.floor_override = 1;
|
|
self.overrider = player;
|
|
break;
|
|
}
|
|
self notify( "floor_override" );
|
|
}
|
|
|
|
elevator_fsm( state )
|
|
{
|
|
/* finite state machine
|
|
|
|
state A: rest
|
|
state B: closing doors - interrupt threaded
|
|
state C: opening doors
|
|
state D: moving elevator
|
|
?1: if not resting at initial floor
|
|
|
|
.-------delay-------.
|
|
| |
|
|
?1 V
|
|
start --> [A] --inside_trig--> [B] --delay--> [D]
|
|
^ | |
|
|
| door_trig |
|
|
| | |
|
|
| V |
|
|
'-----delay------- [C] <---delay---'
|
|
*/
|
|
|
|
/* self is elevator, self.e[] */
|
|
|
|
self.eState = state;
|
|
|
|
door_trig = self get_housing_door_trigger(); // triggers door interrupt
|
|
inside_trig = self get_housing_inside_trigger(); // presence
|
|
|
|
while ( 1 )
|
|
{
|
|
//state A: rest
|
|
if ( self.eState == "[A]" )
|
|
{
|
|
// ?1: if not resting at initial floor
|
|
if ( level.elevator_return && ( self get_curFloor() != self get_initFloor() ) )
|
|
{
|
|
self.moveto_floor = self get_initFloor();
|
|
self thread floor_override( inside_trig );
|
|
self waittill_or_timeout( "floor_override", level.elevator_waittime );
|
|
|
|
if ( self.floor_override && isdefined( self.overrider ) && isPlayer( self.overrider ) )
|
|
self get_floor( self.overrider );
|
|
|
|
self.eState = "[B]";
|
|
continue;
|
|
}
|
|
|
|
// wait for player use trigger
|
|
while ( 1 )
|
|
{
|
|
// if elevator already has destination but interrupted, it should continue previous order
|
|
if ( self.moveto_floor == self get_curFloor() )
|
|
param = inside_trig discrete_waittill( "trigger" );
|
|
else
|
|
param = "elevator_called"; // as if called onto the destination floor
|
|
|
|
// elevator call hack
|
|
if ( isString( param ) && ( param == "elevator_called" ) && ( self.moveto_floor != self get_curFloor() ) )
|
|
{
|
|
self.eState = "[B]";
|
|
break;
|
|
}
|
|
|
|
if ( isdefined( param ) && isPlayer( param ) && isAlive( param ) )
|
|
{
|
|
isTouching_trigger = ( param istouching( inside_trig ) );
|
|
isTouching_motion_trigger = ( isdefined( inside_trig.motion_trigger ) && param istouching( inside_trig.motion_trigger ) );
|
|
player_isTouching_trigger = ( isTouching_trigger || isTouching_motion_trigger );
|
|
|
|
if ( player_isTouching_trigger )
|
|
{
|
|
player = param;
|
|
self get_floor( player );
|
|
|
|
if ( self.moveto_floor == self get_curFloor() )
|
|
continue;
|
|
|
|
self.eState = "[B]";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//state B: closing doors - interrupt threaded
|
|
if ( self.eState == "[B]" )
|
|
{
|
|
self thread elevator_interrupt( door_trig );
|
|
floor_num = self get_curFloor();
|
|
|
|
// call to close doors
|
|
self thread close_inner_doors();
|
|
self thread close_outer_doors( floor_num );
|
|
|
|
self waittill_any( "closed_inner_doors", "interrupted" ); // Wait for inner doors to close for the safty of our valued customers.
|
|
|
|
if ( self.elevator_interrupted )
|
|
{
|
|
self.eState = "[C]";
|
|
continue;
|
|
}
|
|
|
|
self.eState = "[D]";
|
|
continue;
|
|
}
|
|
|
|
//state C: opening doors
|
|
if ( self.eState == "[C]" )
|
|
{
|
|
floor_num = self get_curFloor();
|
|
|
|
self thread open_inner_doors();
|
|
self thread open_outer_doors( floor_num );
|
|
|
|
self waittill( "opened_floor_" + floor_num + "_outer_doors" );
|
|
|
|
if ( self.elevator_interrupted )
|
|
{
|
|
self.eState = "[B]";
|
|
continue;
|
|
}
|
|
|
|
self.eState = "[A]";
|
|
continue;
|
|
}
|
|
|
|
//state D: moving elevator
|
|
if ( self.eState == "[D]" )
|
|
{
|
|
assertex( isdefined( self.moveto_floor ), "Missing destination floor number" );
|
|
|
|
if ( self.moveto_floor != self get_curFloor() )
|
|
{
|
|
self thread elevator_move( self.moveto_floor );
|
|
self waittill( "elevator_moved" );
|
|
}
|
|
|
|
self.eState = "[C]";
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
monitor_callbutton()
|
|
{
|
|
while ( 1 )
|
|
{
|
|
// call button used by player
|
|
player = self discrete_waittill( "trigger" );
|
|
|
|
call_floor = undefined;
|
|
call_elevators = [];
|
|
// fake loop, always loop only once
|
|
foreach ( idx, linked_elevators in self.e )
|
|
{
|
|
call_floor = idx;
|
|
call_elevators = linked_elevators;
|
|
}
|
|
assert( isdefined( call_floor ) && isdefined( call_elevators ) && call_elevators.size );
|
|
|
|
elevator_called = 0;
|
|
|
|
// prefilter elevators to see if any already at this floor
|
|
foreach ( elevator in call_elevators )
|
|
{
|
|
moving = elevator elevator_floor_update();
|
|
|
|
// if in non-aggressive mode; this elevator is already stationary at the requested floor, we skip!
|
|
if ( !level.elevator_aggressive_call && !moving )
|
|
{
|
|
if ( elevator get_curFloor() == call_floor )
|
|
{
|
|
elevator_called = 1;
|
|
call_elevators = [];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// check all elevators to see if any can be called to this floor
|
|
foreach ( elevator in call_elevators )
|
|
{
|
|
if ( elevator.eState == "[A]" )
|
|
{
|
|
// call only elevators in a state of rest [A]
|
|
elevator call_elevator( call_floor );
|
|
|
|
elevator_called = 1;
|
|
|
|
// aggressive call
|
|
if ( !level.elevator_aggressive_call )
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( elevator_called )
|
|
self playsound( "elev_bell_ding" );
|
|
}
|
|
}
|
|
|
|
call_elevator( call_floor )
|
|
{
|
|
self.moveto_floor = call_floor;
|
|
|
|
// call elevator via trigger hack
|
|
inside_trigger = self get_housing_inside_trigger();
|
|
inside_trigger notify( "trigger", "elevator_called" );
|
|
if ( level.elevator_motion_detection )
|
|
inside_trigger.motion_trigger notify( "trigger", "elevator_called" );
|
|
}
|
|
|
|
// opens menu to select floors
|
|
get_floor( player )
|
|
{
|
|
// skips popup menu if only two floors present
|
|
bifloor = self get_outer_doorsets();
|
|
if ( bifloor.size == 2 )
|
|
{
|
|
curFloor = self get_curFloor();
|
|
self.moveto_floor = !curFloor;
|
|
return;
|
|
}
|
|
|
|
player openpopupmenu( "elevator_floor_selector" );
|
|
player setClientDvar( "player_current_floor", self get_curFloor() );
|
|
|
|
while ( 1 )
|
|
{
|
|
player waittill( "menuresponse", menu, response );
|
|
|
|
if ( menu == "elevator_floor_selector" )
|
|
{
|
|
if ( response != "none" )
|
|
self.moveto_floor = int( response );
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
elevator_interrupt( door_trig )
|
|
{
|
|
self notify( "interrupt_watch" );
|
|
level notify( "elevator_interior_button_pressed" );
|
|
self endon( "interrupt_watch" ); // no duplicate interrupts
|
|
self endon( "elevator_moving" );
|
|
|
|
self.elevator_interrupted = 0;
|
|
wait 0.5;// buffer time to have the door jitter...
|
|
door_trig waittill( "trigger", player );
|
|
|
|
/*while ( 1 )
|
|
{
|
|
wait 0.5; // buffer time to have the door jitter... realisticaly, im serious!
|
|
|
|
door_trig waittill( "trigger", player );
|
|
if ( isdefined( player ) && isPlayer( player ) )
|
|
break;
|
|
}*/
|
|
|
|
self notify( "interrupted" );
|
|
self.elevator_interrupted = 1;
|
|
|
|
//self elevator_fsm( "[C]" );
|
|
}
|
|
|
|
// returns if elevator is moving, also updates the floor number if not moving
|
|
elevator_floor_update()
|
|
{
|
|
mainframe = self get_housing_mainframe();
|
|
cur_pos = mainframe.origin;
|
|
|
|
moving = 1;
|
|
foreach ( idx, eFloor in self get_outer_doorsets() )
|
|
{
|
|
floor_pos = self.e[ "floor" + idx + "_pos" ];
|
|
if ( cur_pos == floor_pos )
|
|
{
|
|
self.e[ "current_floor" ] = idx;
|
|
moving = 0;
|
|
}
|
|
}
|
|
|
|
return moving;
|
|
}
|
|
|
|
elevator_sound_think()
|
|
{
|
|
// self is elevator, self.e[]
|
|
// play elevator sounds on notify of behavior
|
|
|
|
// always play musak
|
|
musak_model = self get_housing_musak_model();
|
|
|
|
if ( level.elevator_music && isdefined( musak_model ) )
|
|
musak_model playloopsound( "elev_musak_loop" );
|
|
|
|
self thread listen_for ( "closing_inner_doors" );
|
|
self thread listen_for ( "opening_inner_doors" );
|
|
self thread listen_for ( "closed_inner_doors" );
|
|
self thread listen_for ( "opened_inner_doors" );
|
|
|
|
foreach ( idx, eFloor in self get_outer_doorsets() )
|
|
{
|
|
self thread listen_for ( "closing_floor_" + idx + "_outer_doors" );
|
|
self thread listen_for ( "opening_floor_" + idx + "_outer_doors" );
|
|
self thread listen_for ( "closed_floor_" + idx + "_outer_doors" );
|
|
self thread listen_for ( "opened_floor_" + idx + "_outer_doors" );
|
|
}
|
|
|
|
self thread listen_for ( "interrupted" );
|
|
//self thread listen_for( "interrupt_watch" );
|
|
self thread listen_for ( "elevator_moving" );
|
|
self thread listen_for ( "elevator_moved" );
|
|
}
|
|
|
|
/*
|
|
-elev_musak_loop,,music/mx_musak_stolen_elev_proc1.wav,1,1,foley,1,1,120,500,effects1,,,rlooping,,all_mp
|
|
-elev_door_open,,events/elev_door_open1.wav,1,1,foley,0.95,1.05,120,2500,voice,,,,,all_mp
|
|
-elev_door_close,,events/elev_door_close1.wav,1,1,foley,0.95,1.05,120,2500,voice,,,,,all_mp
|
|
-elev_door_interupt,,events/elev_door_interupt1.wav,1,1,foley,0.95,1.05,120,2500,voice,,,,,all_mp
|
|
-elev_bell_ding,,events/elev_bell_ding1.wav,1,1,foley,1,1,120,2500,voice,,,,,all_mp
|
|
-elev_run_start,,events/elev_run_start01.wav,1,1,foley,1,1,120,500,voice,,,,,all_mp
|
|
-elev_run_loop,,events/elev_run_loop01.wav,1,1,foley,1,1,120,500,voice,,,rlooping,,all_mp
|
|
-elev_run_end,,events/elev_run_stop01.wav,1,1,foley,1,1,120,500,voice,,,,,all_mp
|
|
*/
|
|
|
|
listen_for ( msg )
|
|
{
|
|
while ( 1 )
|
|
{
|
|
self waittill( msg );
|
|
mainframe = self get_housing_mainframe();
|
|
|
|
if ( issubstr( msg, "closing_" ) )
|
|
mainframe playsound( "elev_door_close" );
|
|
|
|
if ( issubstr( msg, "opening_" ) )
|
|
mainframe playsound( "elev_door_open" );
|
|
|
|
if ( msg == "elevator_moving" )
|
|
{
|
|
mainframe playsound( "elev_run_start" );
|
|
mainframe playloopsound( "elev_run_loop" );
|
|
}
|
|
|
|
if ( msg == "interrupted" )
|
|
mainframe playsound( "elev_door_interupt" );
|
|
|
|
if ( msg == "elevator_moved" )
|
|
{
|
|
mainframe stoploopsound( "elev_run_loop" );
|
|
mainframe playsound( "elev_run_end" );
|
|
mainframe playsound( "elev_bell_ding" );
|
|
}
|
|
|
|
//if ( isdefined( level.players[0] ) && level.elevator_debug )
|
|
// level.players[0] iprintln( "(e" + self.e[ "id" ] + ") " + msg );
|
|
}
|
|
}
|
|
|
|
//==========================================================================//
|
|
// === MOVEMENTS === //
|
|
//==========================================================================//
|
|
|
|
// position elevators
|
|
position_elevators()
|
|
{
|
|
// closing all outer doors on floors elevator isnt at
|
|
foreach ( e, elevator in level.elevators )
|
|
{
|
|
elevator.moveto_floor = elevator get_curFloor();
|
|
|
|
foreach ( floor_num, outer_doorset in elevator get_outer_doorsets() )
|
|
{
|
|
if ( elevator get_curFloor() != floor_num )
|
|
elevator thread close_outer_doors( floor_num );
|
|
}
|
|
}
|
|
}
|
|
|
|
elevator_move( floor_num )
|
|
{
|
|
// self is elevator, self.e[]
|
|
self notify( "elevator_moving" );
|
|
self endon( "elevator_moving" );
|
|
|
|
mainframe = self get_housing_mainframe();
|
|
delta_vec = self.e[ "floor" + floor_num + "_pos" ] - mainframe.origin;
|
|
|
|
speed = level.elevator_speed;
|
|
dist = abs( distance( self.e[ "floor" + floor_num + "_pos" ], mainframe.origin ) );
|
|
moveTime = dist / speed;
|
|
|
|
// move housing:
|
|
mainframe moveTo( mainframe.origin + delta_vec, moveTime, moveTime * level.elevator_accel, moveTime * level.elevator_decel );
|
|
|
|
// move doors and triggers and other script models
|
|
foreach ( part in self get_housing_children() )
|
|
{
|
|
moveto_pos = part.origin + delta_vec;
|
|
|
|
if ( !issubstr( part.classname, "trigger_" ) )
|
|
part moveTo( moveto_pos, moveTime, moveTime * level.elevator_accel, moveTime * level.elevator_decel );
|
|
else
|
|
part.origin = moveto_pos;
|
|
}
|
|
|
|
// making sure elevator housing gets to destination floor
|
|
self waittill_finish_moving( mainframe, self.e[ "floor" + floor_num + "_pos" ] );
|
|
|
|
self notify( "elevator_moved" );
|
|
}
|
|
|
|
close_inner_doors()
|
|
{
|
|
// self is elevator set
|
|
self notify( "closing_inner_doors" );
|
|
self endon( "closing_inner_doors" ); // when interrupted
|
|
self endon( "opening_inner_doors" ); // when interrupted
|
|
|
|
left_door = self get_housing_leftdoor(); // ent
|
|
right_door = self get_housing_rightdoor(); // ent
|
|
|
|
mainframe = self get_housing_mainframe(); // ent
|
|
old_closed_pos = self get_housing_closedpos(); // vec
|
|
closed_pos = ( old_closed_pos[ 0 ], old_closed_pos[ 1 ], mainframe.origin[ 2 ] ); // adjusted closed position after floor change
|
|
|
|
speed = level.elevator_innerdoorspeed; // scaler
|
|
dist = abs( distance( left_door.origin, closed_pos ) ); // scaler
|
|
moveTime = dist / speed; // scaler
|
|
|
|
left_door moveTo( closed_pos, moveTime, moveTime * 0.1, moveTime * 0.25 );
|
|
right_door moveTo( closed_pos, moveTime, moveTime * 0.1, moveTime * 0.25 );
|
|
|
|
self waittill_finish_moving( left_door, closed_pos, right_door, closed_pos );
|
|
self notify( "closed_inner_doors" );
|
|
}
|
|
|
|
open_inner_doors()
|
|
{
|
|
// self is elevator set
|
|
self notify( "opening_inner_doors" );
|
|
self endon( "opening_inner_doors" ); // when interrupted
|
|
|
|
left_door = self get_housing_leftdoor(); // ent
|
|
right_door = self get_housing_rightdoor(); // ent
|
|
|
|
mainframe = self get_housing_mainframe(); // ent
|
|
old_left_opened_pos = self get_housing_leftdoor_opened_pos(); // vec
|
|
old_right_opened_pos = self get_housing_rightdoor_opened_pos(); // vec
|
|
|
|
left_opened_pos = ( old_left_opened_pos[ 0 ], old_left_opened_pos[ 1 ], mainframe.origin[ 2 ] );
|
|
right_opened_pos = ( old_right_opened_pos[ 0 ], old_right_opened_pos[ 1 ], mainframe.origin[ 2 ] );
|
|
|
|
speed = level.elevator_innerdoorspeed; // scaler
|
|
dist = abs( distance( left_opened_pos, right_opened_pos ) * 0.5 ); // scaler
|
|
moveTime = ( dist / speed ) * 0.5; // scaler
|
|
|
|
left_door moveTo( left_opened_pos, moveTime, moveTime * 0.1, moveTime * 0.25 );
|
|
right_door moveTo( right_opened_pos, moveTime, moveTime * 0.1, moveTime * 0.25 );
|
|
|
|
self waittill_finish_moving( left_door, left_opened_pos, right_door, right_opened_pos );
|
|
self notify( "opened_inner_doors" );
|
|
}
|
|
|
|
// close outer elevator doors per floor
|
|
close_outer_doors( floor_num )
|
|
{
|
|
// self is elevator set
|
|
self notify( "closing_floor_" + floor_num + "_outer_doors" );
|
|
self endon( "closing_floor_" + floor_num + "_outer_doors" ); // when interrupted
|
|
self endon( "opening_floor_" + floor_num + "_outer_doors" ); // when interrupted
|
|
|
|
left_door = self get_outer_leftdoor( floor_num ); // ent
|
|
right_door = self get_outer_rightdoor( floor_num ); // ent
|
|
|
|
left_opened_pos = self get_outer_leftdoor_openedpos( floor_num ); // vec
|
|
closed_pos = self get_outer_closedpos( floor_num ); // vec
|
|
|
|
speed = level.elevator_outterdoorspeed; // scaler
|
|
dist = abs( distance( left_opened_pos, closed_pos ) ); // scaler
|
|
moveTime = dist / speed; // scaler
|
|
|
|
left_door moveTo( closed_pos, moveTime, moveTime * 0.1, moveTime * 0.25 );
|
|
right_door moveTo( closed_pos, moveTime, moveTime * 0.1, moveTime * 0.25 );
|
|
|
|
self waittill_finish_moving( left_door, closed_pos, right_door, closed_pos );
|
|
self notify( "closed_floor_" + floor_num + "_outer_doors" );
|
|
}
|
|
|
|
// open outer elevator doors per floor
|
|
open_outer_doors( floor_num )
|
|
{
|
|
// self is elevator set
|
|
level notify( "elevator_doors_opening" );
|
|
self notify( "opening_floor_" + floor_num + "_outer_doors" );
|
|
self endon( "opening_floor_" + floor_num + "_outer_doors" ); // when interrupted
|
|
|
|
left_door = self get_outer_leftdoor( floor_num ); // ent
|
|
right_door = self get_outer_rightdoor( floor_num ); // ent
|
|
|
|
left_opened_pos = self get_outer_leftdoor_openedpos( floor_num ); // vec
|
|
right_opened_pos = self get_outer_rightdoor_openedpos( floor_num ); // vec
|
|
closed_pos = self get_outer_closedpos( floor_num ); // vec
|
|
|
|
speed = level.elevator_outterdoorspeed; // scaler
|
|
dist = abs( distance( left_opened_pos, closed_pos ) ); // scaler
|
|
moveTime = ( dist / speed ) * 0.5; // scaler
|
|
|
|
left_door moveTo( left_opened_pos, moveTime, moveTime * 0.1, moveTime * 0.25 );
|
|
right_door moveTo( right_opened_pos, moveTime, moveTime * 0.1, moveTime * 0.25 );
|
|
|
|
self waittill_finish_moving( left_door, left_opened_pos, right_door, right_opened_pos );
|
|
self notify( "opened_floor_" + floor_num + "_outer_doors" );
|
|
}
|
|
|
|
//==========================================================================//
|
|
// === BUILD ELEVATORS === //
|
|
//==========================================================================//
|
|
|
|
// builds elevators into 'level.elevators' struct array containing parts list
|
|
build_elevators()
|
|
{
|
|
// triggers that enclose elevator, to distinguish between elevators
|
|
elevator_groups = getentarray( "elevator_group", "targetname" );
|
|
assertex( isdefined( elevator_groups ) && ( elevator_groups.size ), "Radiant: Missing elevator bounding origins" );
|
|
|
|
elevator_housings = getentarray( "elevator_housing", "targetname" );
|
|
assertex( isdefined( elevator_housings ) && ( elevator_housings.size >= elevator_groups.size ), "Fail! Missing the whole elevator, script_brushmodel with [targetname = elevator_housing] must be correctly placed" );
|
|
|
|
// sets of elevator outter door prefabs placed
|
|
elevator_doorsets = getentarray( "elevator_doorset", "targetname" );
|
|
assertex( isdefined( elevator_doorsets ) && ( elevator_doorsets.size >= elevator_groups.size ), "Radiant: Missing elevator door(s)" );
|
|
|
|
// build found elevators
|
|
foreach ( elevator_bound in elevator_groups )
|
|
{
|
|
elevator_bound_end = getent( elevator_bound.target, "targetname" );
|
|
|
|
min_max_xy = [];
|
|
min_max_xy[ 0 ] = min( elevator_bound.origin[ 0 ], elevator_bound_end.origin[ 0 ] );// min_x
|
|
min_max_xy[ 1 ] = max( elevator_bound.origin[ 0 ], elevator_bound_end.origin[ 0 ] );// max_x
|
|
min_max_xy[ 2 ] = min( elevator_bound.origin[ 1 ], elevator_bound_end.origin[ 1 ] );// min_y
|
|
min_max_xy[ 3 ] = max( elevator_bound.origin[ 1 ], elevator_bound_end.origin[ 1 ] );// max_y
|
|
|
|
parts = spawnstruct();
|
|
parts.e[ "id" ] = level.elevators.size;
|
|
|
|
// === build elevator housing ===
|
|
/*
|
|
Elevator's mainframe brushmodel
|
|
|
|
script_brushmodel targeting:
|
|
"elevator_housing" -> left door -> right door -> door trigger -> inside trigger
|
|
|
|
Housing is the body that moves between floors
|
|
*/
|
|
parts.e[ "housing" ] = [];
|
|
parts.e[ "housing" ][ "mainframe" ] = [];
|
|
|
|
foreach ( elevator_housing in elevator_housings )
|
|
{
|
|
if ( elevator_housing isInbound( min_max_xy ) )
|
|
{
|
|
parts.e[ "housing" ][ "mainframe" ][ parts.e[ "housing" ][ "mainframe" ].size ] = elevator_housing;
|
|
|
|
if ( elevator_housing.classname == "script_model" )
|
|
continue;
|
|
|
|
if ( elevator_housing.code_classname == "light" )
|
|
continue;
|
|
|
|
inner_leftdoor = getent( elevator_housing.target, "targetname" );
|
|
parts.e[ "housing" ][ "left_door" ] = inner_leftdoor;
|
|
parts.e[ "housing" ][ "left_door_opened_pos" ] = inner_leftdoor.origin;
|
|
|
|
inner_rightdoor = getent( inner_leftdoor.target, "targetname" );
|
|
parts.e[ "housing" ][ "right_door" ] = inner_rightdoor;
|
|
parts.e[ "housing" ][ "right_door_opened_pos" ] = inner_rightdoor.origin;
|
|
|
|
inner_door_closed_pos = ( inner_leftdoor.origin - inner_rightdoor.origin ) * ( 0.5, 0.5, 0.5 ) + inner_rightdoor.origin;
|
|
parts.e[ "housing" ][ "door_closed_pos" ] = inner_door_closed_pos;
|
|
|
|
door_trigger = getent( inner_rightdoor.target, "targetname" );
|
|
parts.e[ "housing" ][ "door_trigger" ] = door_trigger;
|
|
|
|
inside_trigger = getent( door_trigger.target, "targetname" );
|
|
parts.e[ "housing" ][ "inside_trigger" ] = inside_trigger;
|
|
inside_trigger make_discrete_trigger();
|
|
|
|
// for motion triggers
|
|
inside_trigger.motion_trigger = spawn( "trigger_radius", elevator_housing.origin, 0, 64, 128 );
|
|
assert( isdefined( inside_trigger.motion_trigger ) );
|
|
}
|
|
}
|
|
assert( isdefined( parts.e[ "housing" ] ) );
|
|
|
|
// === build elevator outer doorsets ===
|
|
/*
|
|
Elevator's outer door sets ( per floor ) are chained together from a script_origin
|
|
targeting to the left door, then left door targets to right door
|
|
|
|
Outer door sets are bodies that only moves to open/close
|
|
*/
|
|
parts.e[ "outer_doorset" ] = [];
|
|
foreach ( elevator_doorset in elevator_doorsets )
|
|
{
|
|
if ( elevator_doorset isInbound( min_max_xy ) )
|
|
{
|
|
|
|
// closed for lighting is for compiling lighting in the closed position rather than the open position.
|
|
door_starts_closed = isdefined( elevator_doorset.script_noteworthy ) && elevator_doorset.script_noteworthy == "closed_for_lighting";
|
|
|
|
door_set_id = parts.e[ "outer_doorset" ].size;
|
|
|
|
parts.e[ "outer_doorset" ][ door_set_id ] = [];
|
|
parts.e[ "outer_doorset" ][ door_set_id ][ "door_closed_pos" ] = elevator_doorset.origin;
|
|
|
|
leftdoor = getent( elevator_doorset.target, "targetname" );
|
|
parts.e[ "outer_doorset" ][ door_set_id ][ "left_door" ] = leftdoor;
|
|
parts.e[ "outer_doorset" ][ door_set_id ][ "left_door_opened_pos" ] = leftdoor.origin;
|
|
|
|
rightdoor = getent( leftdoor.target, "targetname" );
|
|
parts.e[ "outer_doorset" ][ door_set_id ][ "right_door" ] = rightdoor;
|
|
parts.e[ "outer_doorset" ][ door_set_id ][ "right_door_opened_pos" ] = rightdoor.origin;
|
|
|
|
//put them back into the would be positions
|
|
if( door_starts_closed )
|
|
{
|
|
left_door_vec = elevator_doorset.origin - leftdoor.origin;
|
|
elevator_doorset.origin = leftdoor.origin;
|
|
leftdoor.origin += left_door_vec;
|
|
rightdoor.origin -= left_door_vec;
|
|
parts.e[ "outer_doorset" ][ door_set_id ][ "door_closed_pos" ] = elevator_doorset.origin;
|
|
parts.e[ "outer_doorset" ][ door_set_id ][ "left_door_opened_pos" ] = leftdoor.origin;
|
|
parts.e[ "outer_doorset" ][ door_set_id ][ "right_door_opened_pos" ] = rightdoor.origin;
|
|
}
|
|
}
|
|
}
|
|
assert( isdefined( parts.e[ "outer_doorset" ] ) );
|
|
|
|
// bubble sort floors
|
|
for ( i = 0; i < parts.e[ "outer_doorset" ].size - 1; i++ )
|
|
{
|
|
for ( j = 0; j < parts.e[ "outer_doorset" ].size - 1 - i; j++ )
|
|
{
|
|
if ( parts.e[ "outer_doorset" ][ j + 1 ][ "door_closed_pos" ][ 2 ] < parts.e[ "outer_doorset" ][ j ][ "door_closed_pos" ][ 2 ] )
|
|
{
|
|
//swap j-1 with j
|
|
temp_left_door = parts.e[ "outer_doorset" ][ j ][ "left_door" ];
|
|
temp_left_door_opened_pos = parts.e[ "outer_doorset" ][ j ][ "left_door_opened_pos" ];
|
|
temp_right_door = parts.e[ "outer_doorset" ][ j ][ "right_door" ];
|
|
temp_right_door_opened_pos = parts.e[ "outer_doorset" ][ j ][ "right_door_opened_pos" ];
|
|
temp_closed_pos = parts.e[ "outer_doorset" ][ j ][ "door_closed_pos" ];
|
|
|
|
parts.e[ "outer_doorset" ][ j ][ "left_door" ] = parts.e[ "outer_doorset" ][ j + 1 ][ "left_door" ];
|
|
parts.e[ "outer_doorset" ][ j ][ "left_door_opened_pos" ] = parts.e[ "outer_doorset" ][ j + 1 ][ "left_door_opened_pos" ];
|
|
parts.e[ "outer_doorset" ][ j ][ "right_door" ] = parts.e[ "outer_doorset" ][ j + 1 ][ "right_door" ];
|
|
parts.e[ "outer_doorset" ][ j ][ "right_door_opened_pos" ] = parts.e[ "outer_doorset" ][ j + 1 ][ "right_door_opened_pos" ];
|
|
parts.e[ "outer_doorset" ][ j ][ "door_closed_pos" ] = parts.e[ "outer_doorset" ][ j + 1 ][ "door_closed_pos" ];
|
|
|
|
parts.e[ "outer_doorset" ][ j + 1 ][ "left_door" ] = temp_left_door;
|
|
parts.e[ "outer_doorset" ][ j + 1 ][ "left_door_opened_pos" ] = temp_left_door_opened_pos;
|
|
parts.e[ "outer_doorset" ][ j + 1 ][ "right_door" ] = temp_right_door;
|
|
parts.e[ "outer_doorset" ][ j + 1 ][ "right_door_opened_pos" ] = temp_right_door_opened_pos;
|
|
parts.e[ "outer_doorset" ][ j + 1 ][ "door_closed_pos" ] = temp_closed_pos;
|
|
}
|
|
}
|
|
}
|
|
|
|
// === build elevator floor pos ===
|
|
floor_pos = [];
|
|
foreach ( i, doorset in parts.e[ "outer_doorset" ] )
|
|
{
|
|
mainframe = parts get_housing_mainframe();
|
|
|
|
floor_pos = ( mainframe.origin[ 0 ], mainframe.origin[ 1 ], doorset[ "door_closed_pos" ][ 2 ] );
|
|
parts.e[ "floor" + i + "_pos" ] = floor_pos;
|
|
|
|
if ( mainframe.origin == floor_pos )
|
|
{
|
|
parts.e[ "initial_floor" ] = i;
|
|
parts.e[ "current_floor" ] = i;
|
|
}
|
|
}
|
|
|
|
// === save build info ===
|
|
level.elevators[ level.elevators.size ] = parts;
|
|
|
|
// trash all script origins no longer needed
|
|
elevator_bound delete();
|
|
elevator_bound_end delete();
|
|
}
|
|
foreach ( elevator_doorset in elevator_doorsets )
|
|
elevator_doorset delete();
|
|
|
|
build_call_buttons();
|
|
|
|
if ( !level.elevator_motion_detection )
|
|
setup_hints();
|
|
|
|
// turn on all primary lights for elevators if they have em
|
|
foreach ( elevator in level.elevators )
|
|
{
|
|
pLights = elevator get_housing_primarylight();
|
|
if ( isdefined( pLights ) && pLights.size )
|
|
{
|
|
foreach ( pLight in pLights )
|
|
pLight setlightintensity( 0.75 );
|
|
}
|
|
}
|
|
}
|
|
|
|
build_call_buttons()
|
|
{
|
|
level.elevator_callbuttons = getentarray( "elevator_call", "targetname" );
|
|
assertex( isdefined( level.elevator_callbuttons ) && ( level.elevator_callbuttons.size > 1 ), "Missing or not enough elevator call buttons" );
|
|
|
|
// per call button
|
|
foreach ( callbutton in level.elevator_callbuttons )
|
|
{
|
|
callbutton.e = [];
|
|
callbutton_v_vec = ( 0, 0, callbutton.origin[ 2 ] );
|
|
callbutton_h_vec = ( callbutton.origin[ 0 ], callbutton.origin[ 1 ], 0 );
|
|
|
|
temp_elevator_list = [];
|
|
// per elevator
|
|
foreach ( e_idx, elevator in level.elevators )
|
|
{
|
|
// per floor
|
|
foreach ( f_idx, eFloor in elevator get_outer_doorsets() )
|
|
{
|
|
v_vec = ( 0, 0, elevator.e[ "floor" + f_idx + "_pos" ][ 2 ] );
|
|
h_vec = ( elevator.e[ "floor" + f_idx + "_pos" ][ 0 ], elevator.e[ "floor" + f_idx + "_pos" ][ 1 ], 0 );
|
|
|
|
if ( abs( distance( callbutton_v_vec, v_vec ) ) <= level.elevator_callbutton_link_v )
|
|
{
|
|
if ( abs( distance( callbutton_h_vec, h_vec ) ) <= level.elevator_callbutton_link_h )
|
|
{
|
|
temp_elevator_list[ temp_elevator_list.size ] = elevator; // build list of elevators linked on floor f_idx
|
|
callbutton.e[ f_idx ] = temp_elevator_list;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
callbutton make_discrete_trigger();
|
|
assertex( isdefined( callbutton.e ) && callbutton.e.size, "Elevator call button at " + callbutton.origin + " failed to grab near by elevators, placed too far?" );
|
|
|
|
// build motion detection triggers for motion triggered calls
|
|
callbutton.motion_trigger = spawn( "trigger_radius", callbutton.origin + ( 0, 0, -32 ), 0, 32, 64 );
|
|
}
|
|
}
|
|
|
|
setup_hints()
|
|
{
|
|
// elevator inside use trigger hint
|
|
foreach ( elevator in level.elevators )
|
|
{
|
|
use_trig = elevator get_housing_inside_trigger();
|
|
floors = elevator get_outer_doorsets();
|
|
num_of_floors = floors.size;
|
|
|
|
use_trig SetCursorHint( "HINT_NOICON" );
|
|
if ( num_of_floors > 2 )
|
|
// Press and hold &&1 to select floor.
|
|
use_trig setHintString( &"ELEVATOR_FLOOR_SELECT_HINT" );
|
|
else
|
|
// Press and hold &&1 to use elevator.
|
|
use_trig setHintString( &"ELEVATOR_USE_HINT" );
|
|
}
|
|
|
|
// elevator call button hint
|
|
foreach ( callbutton in level.elevator_callbuttons )
|
|
{
|
|
callbutton SetCursorHint( "HINT_NOICON" );
|
|
// Press and hold &&1 to call elevator.
|
|
callbutton setHintString( &"ELEVATOR_CALL_HINT" );
|
|
}
|
|
}
|
|
|
|
//==========================================================================//
|
|
// === HELPERS === //
|
|
//==========================================================================//
|
|
|
|
// setup discrete trigger for discrete waittill
|
|
make_discrete_trigger()
|
|
{
|
|
self.enabled = 1; // enable now for disabling trigger
|
|
self disable_trigger(); // disable trigger, enable again only when waittill on
|
|
}
|
|
|
|
// trigger only exist when waittill upon
|
|
discrete_waittill( msg )
|
|
{
|
|
assert( isdefined( self.motion_trigger ) );
|
|
|
|
self enable_trigger(); // this is for disabling trigger immediately after triggering
|
|
|
|
if ( level.elevator_motion_detection )
|
|
self.motion_trigger waittill( msg, param );
|
|
else
|
|
self waittill( msg, param );
|
|
|
|
self disable_trigger();
|
|
return param;
|
|
}
|
|
|
|
|
|
enable_trigger()
|
|
{
|
|
if ( !self.enabled )
|
|
{
|
|
self.enabled = 1;
|
|
self.origin += ( 0, 0, 10000 );
|
|
|
|
if ( isdefined( self.motion_trigger ) )
|
|
self.motion_trigger.origin += ( 0, 0, 10000 );
|
|
}
|
|
}
|
|
|
|
disable_trigger()
|
|
{
|
|
self notify( "disable_trigger" );
|
|
if ( self.enabled )
|
|
self thread disable_trigger_helper();
|
|
}
|
|
|
|
disable_trigger_helper()
|
|
{
|
|
self endon( "disable_trigger" );
|
|
self.enabled = 0;
|
|
wait 1.5;
|
|
self.origin += ( 0, 0, -10000 );
|
|
|
|
if ( isdefined( self.motion_trigger ) )
|
|
self.motion_trigger.origin += ( 0, 0, -10000 );
|
|
}
|
|
|
|
// ========== OUTER DOOR SETS ===========
|
|
// returns array of outer doorsets for this floor - ent[]
|
|
get_outer_doorset( floor_num )
|
|
{
|
|
return self.e[ "outer_doorset" ][ floor_num ];
|
|
}
|
|
|
|
// returns array of floors of doorsets - int[]
|
|
get_outer_doorsets()
|
|
{
|
|
return self.e[ "outer_doorset" ];
|
|
}
|
|
|
|
// returns outer door closed position for this floor - vec
|
|
get_outer_closedpos( floor_num )
|
|
{
|
|
return self.e[ "outer_doorset" ][ floor_num ][ "door_closed_pos" ];
|
|
}
|
|
|
|
// returns left door entity for this floor - ent
|
|
get_outer_leftdoor( floor_num )
|
|
{
|
|
return self.e[ "outer_doorset" ][ floor_num ][ "left_door" ];
|
|
}
|
|
|
|
// returns right door entity for this floor - ent
|
|
get_outer_rightdoor( floor_num )
|
|
{
|
|
return self.e[ "outer_doorset" ][ floor_num ][ "right_door" ];
|
|
}
|
|
|
|
// returns left door opened position for this floor - vec
|
|
get_outer_leftdoor_openedpos( floor_num )
|
|
{
|
|
return self.e[ "outer_doorset" ][ floor_num ][ "left_door_opened_pos" ];
|
|
}
|
|
|
|
// returns right door opened position for this floor - vec
|
|
get_outer_rightdoor_openedpos( floor_num )
|
|
{
|
|
return self.e[ "outer_doorset" ][ floor_num ][ "right_door_opened_pos" ];
|
|
}
|
|
|
|
// ========= HOUSING =========
|
|
// returns all the entities that will move when the elevator moves between floors - ent[]
|
|
get_housing_children()
|
|
{
|
|
children = [];
|
|
|
|
door_trig = self get_housing_door_trigger();
|
|
use_trig = self get_housing_inside_trigger();
|
|
motion_trig = use_trig.motion_trigger;
|
|
left_door = self get_housing_leftdoor();
|
|
right_door = self get_housing_rightdoor();
|
|
|
|
children[ children.size ] = door_trig;
|
|
children[ children.size ] = use_trig;
|
|
children[ children.size ] = left_door;
|
|
children[ children.size ] = right_door;
|
|
|
|
if ( isdefined( motion_trig ) )
|
|
children[ children.size ] = motion_trig;
|
|
|
|
// append script models as children of elevator moving body
|
|
script_models = self get_housing_models();
|
|
foreach ( eModel in script_models )
|
|
children[ children.size ] = eModel;
|
|
|
|
// append primary light(s) as children of elevator moving body
|
|
primarylights = get_housing_primarylight();
|
|
foreach ( pLight in primarylights )
|
|
children[ children.size ] = pLight;
|
|
|
|
return children;
|
|
}
|
|
|
|
// returns only the mainframe script_brushmodel, there can only be one per elevator! - ent
|
|
get_housing_mainframe()
|
|
{
|
|
parts = self.e[ "housing" ][ "mainframe" ];
|
|
|
|
housing_model = undefined;
|
|
foreach ( part in parts )
|
|
{
|
|
if ( part.classname != "script_model" && part.code_classname != "light" )
|
|
{
|
|
assertex( !isdefined( housing_model ), "Fail! Found more than one elevator housing script_brushmodels per elevator" );
|
|
housing_model = part;
|
|
}
|
|
}
|
|
assertex( isdefined( housing_model ), "Epic fail! No elevator housing script_brushmodel found" );
|
|
return housing_model;
|
|
}
|
|
|
|
// returns an array of script_models used as part of the elevator prefab - ent[]
|
|
get_housing_models()
|
|
{
|
|
parts = self.e[ "housing" ][ "mainframe" ];
|
|
temp_model_array = [];
|
|
|
|
foreach ( part in parts )
|
|
{
|
|
if ( part.classname == "script_model" )
|
|
temp_model_array[ temp_model_array.size ] = part;
|
|
}
|
|
return temp_model_array;
|
|
}
|
|
|
|
// returns an array of lights - ent[]
|
|
get_housing_primarylight()
|
|
{
|
|
parts = self.e[ "housing" ][ "mainframe" ];
|
|
temp_primarylights = [];
|
|
|
|
foreach ( part in parts )
|
|
{
|
|
if ( part.code_classname == "light" )
|
|
temp_primarylights[ temp_primarylights.size ] = part;
|
|
}
|
|
return temp_primarylights;
|
|
}
|
|
|
|
// returns a single model to play elevator music on, this must exist and only one! - ent
|
|
get_housing_musak_model()
|
|
{
|
|
models = self get_housing_models();
|
|
musak_model = undefined;
|
|
|
|
foreach ( eModel in models )
|
|
{
|
|
if ( isdefined( eModel.script_noteworthy ) && eModel.script_noteworthy == "play_musak" )
|
|
musak_model = eModel;
|
|
}
|
|
//assertex( isdefined( musak_model ), "Fail! Missing script_model to play elevator music on, [script_noteworthy = play_musak]" );
|
|
|
|
return musak_model;
|
|
}
|
|
|
|
// returns interrupt trigger for elevator doors - ent trig
|
|
get_housing_door_trigger()
|
|
{
|
|
return self.e[ "housing" ][ "door_trigger" ];
|
|
}
|
|
|
|
// returns trigger for floor selection inside the elevator - ent trig
|
|
get_housing_inside_trigger()
|
|
{
|
|
return self.e[ "housing" ][ "inside_trigger" ];
|
|
}
|
|
|
|
// returns inner door's closing position - vec
|
|
get_housing_closedpos()
|
|
{
|
|
return self.e[ "housing" ][ "door_closed_pos" ];
|
|
}
|
|
|
|
// returns inner left door entity - ent
|
|
get_housing_leftdoor()
|
|
{
|
|
return self.e[ "housing" ][ "left_door" ];
|
|
}
|
|
|
|
// returns inner right door entity - ent
|
|
get_housing_rightdoor()
|
|
{
|
|
return self.e[ "housing" ][ "right_door" ];
|
|
}
|
|
|
|
// returns inner left door opened position - vec
|
|
get_housing_leftdoor_opened_pos()
|
|
{
|
|
return self.e[ "housing" ][ "left_door_opened_pos" ];
|
|
}
|
|
|
|
// returns inner right door opened position - vec
|
|
get_housing_rightdoor_opened_pos()
|
|
{
|
|
return self.e[ "housing" ][ "right_door_opened_pos" ];
|
|
}
|
|
|
|
// floor currently the elevator is on - int
|
|
get_curFloor()
|
|
{
|
|
moving = self elevator_floor_update();
|
|
return self.e[ "current_floor" ];
|
|
}
|
|
|
|
// floor elevator initially at on level load - int
|
|
get_initFloor()
|
|
{
|
|
return self.e[ "initial_floor" ];
|
|
}
|
|
|
|
waittill_finish_moving( ent1, ent1_moveto_pos, ent2, ent2_moveto_pos )
|
|
{
|
|
if ( !isdefined( ent2 ) && !isdefined( ent2_moveto_pos ) )
|
|
{
|
|
ent2 = ent1;
|
|
ent2_moveto_pos = ent1_moveto_pos;
|
|
}
|
|
|
|
while ( 1 )
|
|
{
|
|
ent1_current_pos = ent1.origin;
|
|
etn2_current_pos = ent2.origin;
|
|
|
|
if ( ent1_current_pos == ent1_moveto_pos && etn2_current_pos == ent2_moveto_pos )
|
|
break;
|
|
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
// return test of min max bound on xy plane, self = entity being tested - bool
|
|
isInbound( bounding_box )
|
|
{
|
|
|
|
assertex( isdefined( self ) && isdefined( self.origin ), "Fail! Can not test bounds with the entity called on" );
|
|
|
|
// the box isn't working on the angle that I have so I'm going to do it by a sphere shape.. -Nate
|
|
//special case cause I don't know if a sphere will break other levels.
|
|
if( level.script == "plaza" || level.script == "highrise_test" )
|
|
return isInBoundingSpere( bounding_box );
|
|
|
|
v_x = self.origin[ 0 ];
|
|
v_y = self.origin[ 1 ];
|
|
|
|
min_x = bounding_box[ 0 ];
|
|
max_x = bounding_box[ 1 ];
|
|
min_y = bounding_box[ 2 ];
|
|
max_y = bounding_box[ 3 ];
|
|
|
|
return ( v_x >= min_x && v_x <= max_x && v_y >= min_y && v_y <= max_y );
|
|
}
|
|
|
|
isInBoundingSpere( bounding_box )
|
|
{
|
|
v_x = self.origin[ 0 ];
|
|
v_y = self.origin[ 1 ];
|
|
min_x = bounding_box[ 0 ];
|
|
max_x = bounding_box[ 1 ];
|
|
min_y = bounding_box[ 2 ];
|
|
max_y = bounding_box[ 3 ];
|
|
|
|
mid_x = (min_x + max_x )/2;
|
|
mid_y = (min_y + max_y )/2;
|
|
radius = abs( Distance( (min_x,min_y,0 ), (mid_x,mid_y,0)) );
|
|
return( abs( distance( (v_x,v_y,0), (mid_x,mid_y,0) ) ) < radius );
|
|
}
|
|
|
|
waittill_or_timeout( msg, timer )
|
|
{
|
|
self endon( msg );
|
|
wait( timer );
|
|
}
|
|
|
|
elevator_get_dvar_int( dvar, def )
|
|
{
|
|
return int( elevator_get_dvar( dvar, def ) );
|
|
}
|
|
|
|
elevator_get_dvar( dvar, def )
|
|
{
|
|
if ( getdvar( dvar ) != "" )
|
|
return getdvarfloat( dvar );
|
|
else
|
|
{
|
|
setdvar( dvar, def );
|
|
return def;
|
|
}
|
|
}
|
|
|
|
elevator_debug()
|
|
{
|
|
if ( !level.elevator_debug )
|
|
return;
|
|
|
|
//print3d(<origin>, <text>, <color>, <alpha>, <scale>, <duration> )
|
|
|
|
while ( 1 )
|
|
{
|
|
// simple debug info:
|
|
|
|
if ( level.elevator_debug != 2 )
|
|
continue;
|
|
|
|
// full debug info:
|
|
|
|
// print all parts for all elevators
|
|
foreach ( i, elevator in level.elevators )
|
|
{
|
|
mainframe = elevator get_housing_mainframe();
|
|
musak_model = elevator get_housing_musak_model();
|
|
|
|
print3d( musak_model.origin, "[e" + i + "]musak_origin", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 );
|
|
print3d( mainframe.origin, "[e" + i + "]mainframe", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 );
|
|
print3d( elevator.e[ "housing" ][ "left_door" ].origin, "[e" + i + "]left door", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 );
|
|
print3d( elevator.e[ "housing" ][ "right_door" ].origin, "[e" + i + "]right door", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 );
|
|
print3d( elevator.e[ "housing" ][ "door_closed_pos" ], "[e" + i + "]->|<-", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 );
|
|
print3d( elevator.e[ "housing" ][ "inside_trigger" ].origin, "[e" + i + "]USE", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 );
|
|
|
|
foreach ( j, eFloor in elevator.e[ "outer_doorset" ] )
|
|
{
|
|
print3d( eFloor[ "left_door" ].origin + ( 0, 0, 8 ), "[e" + i + "][f" + j + "]left door", ( 0.75, 1.0, 0.75 ), 1, 0.25, 20 );
|
|
print3d( eFloor[ "right_door" ].origin + ( 0, 0, 8 ), "[e" + i + "][f" + j + "]right door", ( 0.75, 1.0, 0.75 ), 1, 0.25, 20 );
|
|
print3d( eFloor[ "door_closed_pos" ] + ( 0, 0, 8 ), "[e" + i + "][f" + j + "]->|<-", ( 0.75, 1.0, 0.75 ), 1, 0.25, 20 );
|
|
print3d( elevator.e[ "floor" + j + "_pos" ] + ( 0, 0, 8 ), "[e" + i + "][f" + j + "]stop", ( 1.0, 0.75, 0.75 ), 1, 0.25, 20 );
|
|
}
|
|
}
|
|
|
|
// per button
|
|
foreach ( callbutton in level.elevator_callbuttons )
|
|
{
|
|
print3d( callbutton.origin, "linked to:", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 );
|
|
|
|
// per floor
|
|
foreach ( f_idx, eFloor in callbutton.e )
|
|
{
|
|
// per elevator linked
|
|
printoffset = 0;
|
|
foreach ( e_idx, eLinked in eFloor )
|
|
{
|
|
printoffset++ ;
|
|
// e_idx is used to offset print
|
|
print_pos = callbutton.origin + ( 0, 0, ( printoffset ) * ( -4 ) );
|
|
print3d( print_pos, "[f" + f_idx + "][e" + eLinked.e[ "id" ] + "]", ( 0.75, 0.75, 1.0 ), 1, 0.25, 20 );
|
|
}
|
|
}
|
|
}
|
|
|
|
wait 0.05;
|
|
}
|
|
} |