Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //#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;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement