2006-03-20 17:12:09 +00:00
/*
2014-06-01 17:55:23 +00:00
* Portions of this file are copyright Rebirth contributors and licensed as
* described in COPYING . txt .
* Portions of this file are copyright Parallax Software and licensed
* according to the Parallax license below .
* See COPYING . txt for license details .
2006-03-20 17:12:09 +00:00
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ( " PARALLAX " ) . PARALLAX , IN DISTRIBUTING THE CODE TO
END - USERS , AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN , GRANTS A
ROYALTY - FREE , PERPETUAL LICENSE TO SUCH END - USERS FOR USE BY SUCH END - USERS
IN USING , DISPLAYING , AND CREATING DERIVATIVE WORKS THEREOF , SO LONG AS
SUCH USE , DISPLAY OR CREATION IS FOR NON - COMMERCIAL , ROYALTY OR REVENUE
FREE PURPOSES . IN NO EVENT SHALL THE END - USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE - BEARING PURPOSES . THE END - USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE .
COPYRIGHT 1993 - 1999 PARALLAX SOFTWARE CORPORATION . ALL RIGHTS RESERVED .
*/
/*
*
* New Triggers and Switches .
*
*/
2015-03-22 04:16:49 +00:00
# include <stdexcept>
2006-03-20 17:12:09 +00:00
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
# include <string.h>
# include "gauges.h"
# include "newmenu.h"
# include "game.h"
# include "switch.h"
# include "inferno.h"
# include "segment.h"
2012-07-07 18:35:06 +00:00
# include "dxxerror.h"
2006-03-20 17:12:09 +00:00
# include "gameseg.h"
# include "wall.h"
# include "texmap.h"
2014-11-23 04:36:58 +00:00
# include "object.h"
2006-03-20 17:12:09 +00:00
# include "fuelcen.h"
# include "cntrlcen.h"
# include "newdemo.h"
# include "player.h"
# include "endlevel.h"
# include "gameseq.h"
# include "multi.h"
# include "palette.h"
2015-04-19 04:18:51 +00:00
# include "hudmsg.h"
2006-03-20 17:12:09 +00:00
# include "robot.h"
# include "bm.h"
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2006-03-20 17:12:09 +00:00
# include "editor/editor.h"
# endif
2014-01-12 23:00:43 +00:00
# include "physfs-serial.h"
2014-12-08 04:19:26 +00:00
# include "compiler-range_for.h"
# include "partial_range.h"
2014-01-12 23:00:43 +00:00
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2006-03-20 17:12:09 +00:00
//-----------------------------------------------------------------
// Initializes all the switches.
void trigger_init ( )
{
2016-02-06 22:12:53 +00:00
Triggers . set_count ( 0 ) ;
2006-03-20 17:12:09 +00:00
}
# endif
2016-01-09 16:38:11 +00:00
template < typename T1 , typename T2 >
2017-06-10 03:31:03 +00:00
static inline void trigger_wall_op ( const trigger & t , T1 & segment_factory , const T2 & op )
2016-01-09 16:38:11 +00:00
{
for ( unsigned i = 0 , num_links = t . num_links ; i ! = num_links ; + + i )
op ( segment_factory ( t . seg [ i ] ) , t . side [ i ] ) ;
}
2006-03-20 17:12:09 +00:00
//-----------------------------------------------------------------
// Executes a link, attached to a trigger.
// Toggles all walls linked to the switch.
// Opens doors, Blasts blast walls, turns off illusions.
2016-01-09 16:38:11 +00:00
static void do_link ( const trigger & t )
2006-03-20 17:12:09 +00:00
{
2017-06-10 03:31:02 +00:00
trigger_wall_op ( t , vmsegptridx , wall_toggle ) ;
2006-03-20 17:12:09 +00:00
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2016-08-25 04:05:32 +00:00
namespace dsx {
2006-03-20 17:12:09 +00:00
//close a door
2016-01-09 16:38:11 +00:00
static void do_close_door ( const trigger & t )
2006-03-20 17:12:09 +00:00
{
2017-06-10 03:31:02 +00:00
trigger_wall_op ( t , vmsegptridx , wall_close_door ) ;
2006-03-20 17:12:09 +00:00
}
//turns lighting on. returns true if lights were actually turned on. (they
//would not be if they had previously been shot out).
2016-01-09 16:38:11 +00:00
static int do_light_on ( const trigger & t )
2006-03-20 17:12:09 +00:00
{
2016-01-09 16:38:11 +00:00
int ret = 0 ;
2017-06-10 03:31:02 +00:00
const auto op = [ & ret ] ( const vmsegptridx_t segnum , const unsigned sidenum ) {
2006-03-20 17:12:09 +00:00
//check if tmap2 casts light before turning the light on. This
//is to keep us from turning on blown-out lights
2015-11-19 03:23:34 +00:00
if ( TmapInfo [ segnum - > sides [ sidenum ] . tmap_num2 & 0x3fff ] . lighting ) {
2006-03-20 17:12:09 +00:00
ret | = add_light ( segnum , sidenum ) ; //any light sets flag
enable_flicker ( segnum , sidenum ) ;
}
2016-01-09 16:38:11 +00:00
} ;
2017-06-10 03:31:02 +00:00
trigger_wall_op ( t , vmsegptridx , op ) ;
2006-03-20 17:12:09 +00:00
return ret ;
}
//turns lighting off. returns true if lights were actually turned off. (they
//would not be if they had previously been shot out).
2016-01-09 16:38:11 +00:00
static int do_light_off ( const trigger & t )
2006-03-20 17:12:09 +00:00
{
2016-01-09 16:38:11 +00:00
int ret = 0 ;
2017-06-10 03:31:02 +00:00
const auto op = [ & ret ] ( const vmsegptridx_t segnum , const unsigned sidenum ) {
2006-03-20 17:12:09 +00:00
//check if tmap2 casts light before turning the light off. This
//is to keep us from turning off blown-out lights
2015-11-19 03:23:34 +00:00
if ( TmapInfo [ segnum - > sides [ sidenum ] . tmap_num2 & 0x3fff ] . lighting ) {
2006-03-20 17:12:09 +00:00
ret | = subtract_light ( segnum , sidenum ) ; //any light sets flag
disable_flicker ( segnum , sidenum ) ;
}
2016-01-09 16:38:11 +00:00
} ;
2017-06-10 03:31:02 +00:00
trigger_wall_op ( t , vmsegptridx , op ) ;
2006-03-20 17:12:09 +00:00
return ret ;
}
// Unlocks all doors linked to the switch.
2016-01-09 16:38:11 +00:00
static void do_unlock_doors ( const trigger & t )
2006-03-20 17:12:09 +00:00
{
2017-06-10 03:31:02 +00:00
const auto op = [ ] ( const vmsegptr_t segp , const unsigned sidenum ) {
2016-01-09 16:38:11 +00:00
const auto wall_num = segp - > sides [ sidenum ] . wall_num ;
2017-06-10 03:31:02 +00:00
auto & w = * vmwallptr ( wall_num ) ;
2016-01-09 16:38:11 +00:00
w . flags & = ~ WALL_DOOR_LOCKED ;
w . keys = KEY_NONE ;
2016-01-09 16:38:11 +00:00
} ;
2017-06-10 03:31:02 +00:00
trigger_wall_op ( t , vmsegptr , op ) ;
2006-03-20 17:12:09 +00:00
}
// Locks all doors linked to the switch.
2016-01-09 16:38:11 +00:00
static void do_lock_doors ( const trigger & t )
2006-03-20 17:12:09 +00:00
{
2017-06-10 03:31:02 +00:00
const auto op = [ ] ( const vmsegptr_t segp , const unsigned sidenum ) {
2016-01-09 16:38:11 +00:00
const auto wall_num = segp - > sides [ sidenum ] . wall_num ;
2017-06-10 03:31:02 +00:00
auto & w = * vmwallptr ( wall_num ) ;
2016-01-09 16:38:11 +00:00
w . flags | = WALL_DOOR_LOCKED ;
2016-01-09 16:38:11 +00:00
} ;
2017-06-10 03:31:02 +00:00
trigger_wall_op ( t , vmsegptr , op ) ;
2006-03-20 17:12:09 +00:00
}
// Changes walls pointed to by a trigger. returns true if any walls changed
2016-01-09 16:38:11 +00:00
static int do_change_walls ( const trigger & t , const uint8_t new_wall_type )
2006-03-20 17:12:09 +00:00
{
2016-01-09 16:38:11 +00:00
int ret = 0 ;
2006-03-20 17:12:09 +00:00
2016-01-09 16:38:11 +00:00
for ( unsigned i = 0 ; i < t . num_links ; + + i )
2015-04-26 20:15:50 +00:00
{
2016-01-09 16:38:11 +00:00
uint8_t cside ;
2017-06-10 03:31:02 +00:00
const auto & & segp = vmsegptridx ( t . seg [ i ] ) ;
2016-01-09 16:38:11 +00:00
const auto side = t . side [ i ] ;
2017-06-10 03:31:02 +00:00
imsegptridx_t csegp = segment_none ;
2006-03-20 17:12:09 +00:00
2015-04-26 20:15:50 +00:00
if ( ! IS_CHILD ( segp - > children [ side ] ) )
2006-03-20 17:12:09 +00:00
{
2016-01-09 16:38:11 +00:00
cside = side_none ;
2006-03-20 17:12:09 +00:00
}
else
{
2017-06-10 03:31:02 +00:00
csegp = imsegptridx ( segp - > children [ side ] ) ;
2006-03-20 17:12:09 +00:00
cside = find_connect_side ( segp , csegp ) ;
2016-01-03 20:21:35 +00:00
Assert ( cside ! = side_none ) ;
2006-03-20 17:12:09 +00:00
}
2016-10-08 18:02:34 +00:00
wall * w0p ;
const auto w0num = segp - > sides [ side ] . wall_num ;
2017-06-10 03:31:02 +00:00
if ( const auto & & uw0p = vmwallptr . check_untrusted ( w0num ) )
2017-01-28 18:12:20 +00:00
w0p = * uw0p ;
else
{
2016-10-17 03:49:32 +00:00
LevelError ( " trigger %p link %u tried to open segment %hu, side %u which is an invalid wall; ignoring. " , addressof ( t ) , i , static_cast < segnum_t > ( segp ) , side ) ;
2016-10-08 18:02:34 +00:00
continue ;
}
auto & wall0 = * w0p ;
2017-06-10 03:31:02 +00:00
imwallptr_t wall1 = nullptr ;
2016-04-05 01:10:18 +00:00
if ( ( cside = = side_none | | csegp - > sides [ cside ] . wall_num = = wall_none | |
2017-06-10 03:31:02 +00:00
( wall1 = vmwallptr ( csegp - > sides [ cside ] . wall_num ) ) - > type = = new_wall_type ) & &
2016-04-05 01:10:18 +00:00
wall0 . type = = new_wall_type )
2006-03-20 17:12:09 +00:00
continue ; //already in correct state, so skip
2016-01-09 16:38:11 +00:00
ret | = 1 ;
2006-03-20 17:12:09 +00:00
2016-01-09 16:38:11 +00:00
switch ( t . type )
{
2006-03-20 17:12:09 +00:00
case TT_OPEN_WALL :
if ( ( TmapInfo [ segp - > sides [ side ] . tmap_num ] . flags & TMI_FORCE_FIELD ) ) {
2016-01-09 16:38:11 +00:00
ret | = 2 ;
2014-10-30 03:32:27 +00:00
const auto pos = compute_center_point_on_side ( segp , side ) ;
2014-10-02 03:02:34 +00:00
digi_link_sound_to_pos ( SOUND_FORCEFIELD_OFF , segp , side , pos , 0 , F1_0 ) ;
digi_kill_sound_linked_to_segment ( segp , side , SOUND_FORCEFIELD_HUM ) ;
2016-01-09 16:38:11 +00:00
wall0 . type = new_wall_type ;
if ( wall1 )
2006-03-20 17:12:09 +00:00
{
2016-01-09 16:38:11 +00:00
wall1 - > type = new_wall_type ;
2014-10-02 03:02:34 +00:00
digi_kill_sound_linked_to_segment ( csegp , cside , SOUND_FORCEFIELD_HUM ) ;
2006-03-20 17:12:09 +00:00
}
}
else
start_wall_cloak ( segp , side ) ;
break ;
case TT_CLOSE_WALL :
if ( ( TmapInfo [ segp - > sides [ side ] . tmap_num ] . flags & TMI_FORCE_FIELD ) ) {
2016-01-09 16:38:11 +00:00
ret | = 2 ;
2016-01-09 16:38:11 +00:00
{
2014-10-30 03:32:27 +00:00
const auto pos = compute_center_point_on_side ( segp , side ) ;
2014-10-02 03:02:34 +00:00
digi_link_sound_to_pos ( SOUND_FORCEFIELD_HUM , segp , side , pos , 1 , F1_0 / 2 ) ;
2016-01-09 16:38:11 +00:00
}
case TT_ILLUSORY_WALL :
2016-01-09 16:38:11 +00:00
wall0 . type = new_wall_type ;
if ( wall1 )
wall1 - > type = new_wall_type ;
2006-03-20 17:12:09 +00:00
}
else
start_wall_decloak ( segp , side ) ;
break ;
2016-01-09 16:38:11 +00:00
default :
return 0 ;
2006-03-20 17:12:09 +00:00
}
kill_stuck_objects ( segp - > sides [ side ] . wall_num ) ;
2016-01-09 16:38:11 +00:00
if ( wall1 )
2006-03-20 17:12:09 +00:00
kill_stuck_objects ( csegp - > sides [ cside ] . wall_num ) ;
}
2016-07-21 01:43:21 +00:00
flush_fcd_cache ( ) ;
2006-03-20 17:12:09 +00:00
return ret ;
}
2013-01-03 16:00:40 +00:00
# define print_trigger_message(pnum,trig,shot,message) \
2016-01-09 16:38:11 +00:00
( ( void ) ( ( print_trigger_message ( pnum , trig , shot ) ) & & \
HUD_init_message ( HM_DEFAULT , message , & " s " [ trig . num_links < = 1 ] ) ) )
2006-03-20 17:12:09 +00:00
2016-01-09 16:38:11 +00:00
static int ( print_trigger_message ) ( int pnum , const trigger & t , int shot )
2013-01-03 16:00:40 +00:00
{
2016-01-09 16:38:11 +00:00
if ( shot & & pnum = = Player_num & & ! ( t . flags & TF_NO_MESSAGE ) )
2013-01-03 16:00:40 +00:00
return 1 ;
return 0 ;
2006-03-20 17:12:09 +00:00
}
2016-08-25 04:05:32 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2016-01-09 16:38:11 +00:00
static void do_matcen ( const trigger & t )
2006-03-20 17:12:09 +00:00
{
2016-02-12 04:02:28 +00:00
range_for ( auto & i , partial_const_range ( t . seg , t . num_links ) )
2017-06-10 03:31:02 +00:00
trigger_matcen ( vmsegptridx ( i ) ) ;
2006-03-20 17:12:09 +00:00
}
2016-01-09 16:38:11 +00:00
static void do_il_on ( const trigger & t )
2006-03-20 17:12:09 +00:00
{
2017-06-10 03:31:02 +00:00
trigger_wall_op ( t , vmsegptridx , wall_illusion_on ) ;
2006-03-20 17:12:09 +00:00
}
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-01-09 16:38:11 +00:00
static void do_il_off ( const trigger & t )
2006-03-20 17:12:09 +00:00
{
2016-01-09 16:38:11 +00:00
# if defined(DXX_BUILD_DESCENT_I)
auto & op = wall_illusion_off ;
# elif defined(DXX_BUILD_DESCENT_II)
2017-06-10 03:31:02 +00:00
const auto op = [ ] ( const vmsegptridx_t & seg , unsigned side ) {
2016-01-09 16:38:11 +00:00
wall_illusion_off ( seg , side ) ;
const auto & & cp = compute_center_point_on_side ( seg , side ) ;
digi_link_sound_to_pos ( SOUND_WALL_REMOVED , seg , side , cp , 0 , F1_0 ) ;
} ;
2013-03-03 01:03:33 +00:00
# endif
2017-06-10 03:31:02 +00:00
trigger_wall_op ( t , vmsegptridx , op ) ;
2006-03-20 17:12:09 +00:00
}
2016-12-24 08:50:29 +00:00
// Slight variation on window_event_result meaning
// 'ignored' means we still want check_trigger to call multi_send_trigger
// 'handled' or 'close' means we don't
// 'close' will still close the game window
2017-08-13 20:38:31 +00:00
window_event_result check_trigger_sub ( object & plrobj , const trgnum_t trigger_num , const playernum_t pnum , const unsigned shot )
2006-03-20 17:12:09 +00:00
{
2016-12-24 08:50:29 +00:00
auto result = window_event_result : : ignored ;
2017-08-13 20:38:32 +00:00
if ( ( Game_mode & GM_MULTI ) & & vcplayerptr ( pnum ) - > connected ! = CONNECT_PLAYING ) // as a host we may want to handle triggers for our clients. to do that properly we must check wether we (host) or client is actually playing.
2016-12-24 08:50:29 +00:00
return window_event_result : : handled ;
2017-06-10 03:31:02 +00:00
auto & trigger = * vmtrgptr ( trigger_num ) ;
2012-05-25 10:14:28 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
( void ) shot ;
if ( pnum = = Player_num ) {
2016-10-02 00:34:47 +00:00
auto & player_info = plrobj . ctype . player_info ;
2016-01-09 16:38:11 +00:00
if ( trigger . flags & TRIGGER_SHIELD_DAMAGE ) {
2016-10-02 00:34:47 +00:00
plrobj . shields - = trigger . value ;
2013-03-03 01:03:33 +00:00
}
2016-12-24 08:50:29 +00:00
if ( trigger . flags & TRIGGER_EXIT )
{
result = start_endlevel_sequence ( ) ;
if ( result = = window_event_result : : handled )
result = window_event_result : : ignored ; // call multi_send_trigger, or end game anyway
2013-03-03 01:03:33 +00:00
}
2016-01-09 16:38:11 +00:00
if ( trigger . flags & TRIGGER_SECRET_EXIT ) {
2016-12-24 08:50:29 +00:00
if ( trigger . flags & TRIGGER_EXIT )
2017-01-09 01:30:53 +00:00
LevelError ( " Trigger %u is both a regular and secret exit! This is not a recommended combination. " , trigger_num ) ;
2013-03-03 01:03:33 +00:00
if ( Newdemo_state = = ND_STATE_RECORDING ) // stop demo recording
Newdemo_state = ND_STATE_PAUSED ;
if ( Game_mode & GM_MULTI )
2016-11-12 18:10:09 +00:00
multi_send_endlevel_start ( multi_endlevel_type : : secret ) ;
2013-03-03 01:03:33 +00:00
if ( Game_mode & GM_NETWORK )
multi_do_protocol_frame ( 1 , 1 ) ;
2016-12-24 08:50:29 +00:00
result = std : : max ( PlayerFinishedLevel ( 1 ) , result ) ; //1 means go to secret level
2013-03-03 01:03:33 +00:00
Control_center_destroyed = 0 ;
2016-12-24 08:50:29 +00:00
return std : : max ( result , window_event_result : : handled ) ;
2013-03-03 01:03:33 +00:00
}
2016-01-09 16:38:11 +00:00
if ( trigger . flags & TRIGGER_ENERGY_DRAIN ) {
2016-09-11 18:49:13 +00:00
player_info . energy - = trigger . value ;
2013-03-03 01:03:33 +00:00
}
}
2016-01-09 16:38:11 +00:00
if ( trigger . flags & TRIGGER_CONTROL_DOORS ) {
do_link ( trigger ) ;
2013-03-03 01:03:33 +00:00
}
2016-01-09 16:38:11 +00:00
if ( trigger . flags & TRIGGER_MATCEN ) {
2013-03-03 01:03:33 +00:00
if ( ! ( Game_mode & GM_MULTI ) | | ( Game_mode & GM_MULTI_ROBOTS ) )
2016-01-09 16:38:11 +00:00
do_matcen ( trigger ) ;
2013-03-03 01:03:33 +00:00
}
2016-01-09 16:38:11 +00:00
if ( trigger . flags & TRIGGER_ILLUSION_ON ) {
do_il_on ( trigger ) ;
2013-03-03 01:03:33 +00:00
}
2016-01-09 16:38:11 +00:00
if ( trigger . flags & TRIGGER_ILLUSION_OFF ) {
do_il_off ( trigger ) ;
2013-03-03 01:03:33 +00:00
}
# elif defined(DXX_BUILD_DESCENT_II)
2016-01-09 16:38:11 +00:00
if ( trigger . flags & TF_DISABLED )
2016-12-24 08:50:29 +00:00
return window_event_result : : handled ; // don't send trigger hit to other players
2006-03-20 17:12:09 +00:00
2016-01-09 16:38:11 +00:00
if ( trigger . flags & TF_ONE_SHOT ) //if this is a one-shot...
trigger . flags | = TF_DISABLED ; //..then don't let it happen again
2006-03-20 17:12:09 +00:00
2016-01-09 16:38:11 +00:00
switch ( trigger . type )
{
2006-03-20 17:12:09 +00:00
case TT_EXIT :
if ( pnum ! = Player_num )
2016-12-24 08:50:29 +00:00
break ;
2006-03-20 17:12:09 +00:00
2016-12-24 08:50:29 +00:00
if ( ! EMULATING_D1 )
digi_stop_digi_sounds ( ) ; //Sound shouldn't cut out when exiting a D1 lvl
2010-06-14 08:13:16 +00:00
2006-03-20 17:12:09 +00:00
if ( Current_level_num > 0 ) {
2016-12-24 08:50:29 +00:00
result = start_endlevel_sequence ( ) ;
2006-03-20 17:12:09 +00:00
} else if ( Current_level_num < 0 ) {
2016-10-02 00:34:47 +00:00
if ( plrobj . shields < 0 | |
2015-12-15 04:09:35 +00:00
Player_dead_state ! = player_dead_state : : no )
2006-03-20 17:12:09 +00:00
break ;
2007-04-14 20:44:09 +00:00
// NMN 04/09/07 Do endlevel movie if we are
// playing a D1 secret level
2010-06-14 08:13:16 +00:00
if ( EMULATING_D1 )
2007-04-14 20:44:09 +00:00
{
2016-12-24 08:50:29 +00:00
result = start_endlevel_sequence ( ) ;
2007-04-14 20:44:09 +00:00
} else {
2016-12-24 08:50:29 +00:00
result = ExitSecretLevel ( ) ;
2007-04-14 20:44:09 +00:00
}
2016-12-24 08:50:29 +00:00
return std : : max ( result , window_event_result : : handled ) ;
2006-03-20 17:12:09 +00:00
} else {
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2013-12-04 22:38:04 +00:00
nm_messagebox_str ( " Yo! " , " You have hit the exit trigger! " , " " ) ;
2006-03-20 17:12:09 +00:00
# else
Int3 ( ) ; //level num == 0, but no editor!
# endif
}
2016-12-24 08:50:29 +00:00
return std : : max ( result , window_event_result : : handled ) ;
2006-03-20 17:12:09 +00:00
break ;
case TT_SECRET_EXIT : {
int truth ;
if ( pnum ! = Player_num )
break ;
2016-10-02 00:34:47 +00:00
if ( plrobj . shields < 0 | |
2015-12-15 04:09:35 +00:00
Player_dead_state ! = player_dead_state : : no )
2006-03-20 17:12:09 +00:00
break ;
2011-06-06 22:21:43 +00:00
if ( is_SHAREWARE | | is_MAC_SHARE ) {
2013-06-23 16:27:34 +00:00
HUD_init_message_literal ( HM_DEFAULT , " Secret Level Teleporter disabled in Descent 2 Demo " ) ;
2011-06-06 22:21:43 +00:00
digi_play_sample ( SOUND_BAD_SELECTION , F1_0 ) ;
break ;
}
2006-03-20 17:12:09 +00:00
if ( Game_mode & GM_MULTI ) {
2013-06-23 16:27:34 +00:00
HUD_init_message_literal ( HM_DEFAULT , " Secret Level Teleporter disabled in multiplayer! " ) ;
2006-03-20 17:12:09 +00:00
digi_play_sample ( SOUND_BAD_SELECTION , F1_0 ) ;
break ;
}
truth = p_secret_level_destroyed ( ) ;
if ( Newdemo_state = = ND_STATE_RECORDING ) // record whether we're really going to the secret level
newdemo_record_secret_exit_blown ( truth ) ;
if ( ( Newdemo_state ! = ND_STATE_PLAYBACK ) & & truth ) {
2013-06-23 16:27:34 +00:00
HUD_init_message_literal ( HM_DEFAULT , " Secret Level destroyed. Exit disabled. " ) ;
2006-03-20 17:12:09 +00:00
digi_play_sample ( SOUND_BAD_SELECTION , F1_0 ) ;
break ;
}
if ( Newdemo_state = = ND_STATE_RECORDING ) // stop demo recording
Newdemo_state = ND_STATE_PAUSED ;
2010-06-14 08:13:16 +00:00
digi_stop_digi_sounds ( ) ;
2006-03-20 17:12:09 +00:00
EnterSecretLevel ( ) ;
Control_center_destroyed = 0 ;
2016-12-24 08:50:29 +00:00
return window_event_result : : handled ;
2006-03-20 17:12:09 +00:00
break ;
}
case TT_OPEN_DOOR :
2016-01-09 16:38:11 +00:00
do_link ( trigger ) ;
print_trigger_message ( pnum , trigger , shot , " Door%s opened! " ) ;
2010-06-14 08:13:16 +00:00
2006-03-20 17:12:09 +00:00
break ;
case TT_CLOSE_DOOR :
2016-01-09 16:38:11 +00:00
do_close_door ( trigger ) ;
print_trigger_message ( pnum , trigger , shot , " Door%s closed! " ) ;
2006-03-20 17:12:09 +00:00
break ;
case TT_UNLOCK_DOOR :
2016-01-09 16:38:11 +00:00
do_unlock_doors ( trigger ) ;
print_trigger_message ( pnum , trigger , shot , " Door%s unlocked! " ) ;
2010-06-14 08:13:16 +00:00
2006-03-20 17:12:09 +00:00
break ;
2010-06-14 08:13:16 +00:00
2006-03-20 17:12:09 +00:00
case TT_LOCK_DOOR :
2016-01-09 16:38:11 +00:00
do_lock_doors ( trigger ) ;
print_trigger_message ( pnum , trigger , shot , " Door%s locked! " ) ;
2006-03-20 17:12:09 +00:00
break ;
2010-06-14 08:13:16 +00:00
2006-03-20 17:12:09 +00:00
case TT_OPEN_WALL :
2016-01-09 16:38:11 +00:00
if ( const auto w = do_change_walls ( trigger , WALL_OPEN ) )
2016-01-09 16:38:11 +00:00
print_trigger_message ( pnum , trigger , shot , ( w & 2 ) ? " Force field%s deactivated! " : " Wall%s opened! " ) ;
2006-03-20 17:12:09 +00:00
break ;
case TT_CLOSE_WALL :
2016-01-09 16:38:11 +00:00
if ( const auto w = do_change_walls ( trigger , WALL_CLOSED ) )
2016-01-09 16:38:11 +00:00
print_trigger_message ( pnum , trigger , shot , ( w & 2 ) ? " Force field%s activated! " : " Wall%s closed! " ) ;
2006-03-20 17:12:09 +00:00
break ;
case TT_ILLUSORY_WALL :
//don't know what to say, so say nothing
2016-01-09 16:38:11 +00:00
do_change_walls ( trigger , WALL_ILLUSION ) ;
2006-03-20 17:12:09 +00:00
break ;
case TT_MATCEN :
if ( ! ( Game_mode & GM_MULTI ) | | ( Game_mode & GM_MULTI_ROBOTS ) )
2016-01-09 16:38:11 +00:00
do_matcen ( trigger ) ;
2006-03-20 17:12:09 +00:00
break ;
2010-06-14 08:13:16 +00:00
2006-03-20 17:12:09 +00:00
case TT_ILLUSION_ON :
2016-01-09 16:38:11 +00:00
do_il_on ( trigger ) ;
print_trigger_message ( pnum , trigger , shot , " Illusion%s on! " ) ;
2006-03-20 17:12:09 +00:00
break ;
2010-06-14 08:13:16 +00:00
2006-03-20 17:12:09 +00:00
case TT_ILLUSION_OFF :
2016-01-09 16:38:11 +00:00
do_il_off ( trigger ) ;
print_trigger_message ( pnum , trigger , shot , " Illusion%s off! " ) ;
2006-03-20 17:12:09 +00:00
break ;
case TT_LIGHT_OFF :
2016-01-09 16:38:11 +00:00
if ( do_light_off ( trigger ) )
print_trigger_message ( pnum , trigger , shot , " Light%s off! " ) ;
2006-03-20 17:12:09 +00:00
break ;
case TT_LIGHT_ON :
2016-01-09 16:38:11 +00:00
if ( do_light_on ( trigger ) )
print_trigger_message ( pnum , trigger , shot , " Light%s on! " ) ;
2006-03-20 17:12:09 +00:00
break ;
default :
Int3 ( ) ;
break ;
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2016-12-24 08:50:29 +00:00
return result ;
2006-03-20 17:12:09 +00:00
}
//-----------------------------------------------------------------
// Checks for a trigger whenever an object hits a trigger side.
2016-12-24 08:50:29 +00:00
window_event_result check_trigger ( const vcsegptridx_t seg , short side , object & plrobj , const vcobjptridx_t objnum , int shot )
2006-03-20 17:12:09 +00:00
{
2015-07-25 23:10:46 +00:00
if ( ( Game_mode & GM_MULTI ) & & ( get_local_player ( ) . connected ! = CONNECT_PLAYING ) ) // as a host we may want to handle triggers for our clients. so this function may be called when we are not playing.
2016-12-24 08:50:29 +00:00
return window_event_result : : ignored ;
2012-05-25 10:14:28 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2016-10-02 00:34:47 +00:00
if ( objnum = = & plrobj )
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2016-10-02 00:34:47 +00:00
if ( objnum = = & plrobj | | ( objnum - > type = = OBJ_ROBOT & & Robot_info [ get_robot_id ( objnum ) ] . companion ) )
2013-03-03 01:03:33 +00:00
# endif
{
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
if ( Newdemo_state = = ND_STATE_PLAYBACK )
2016-12-24 08:50:29 +00:00
return window_event_result : : ignored ;
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
if ( Newdemo_state = = ND_STATE_RECORDING )
2014-10-02 03:02:34 +00:00
newdemo_record_trigger ( seg , side , objnum , shot ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2016-02-12 04:02:28 +00:00
const auto wall_num = seg - > sides [ side ] . wall_num ;
2016-12-24 08:50:29 +00:00
if ( wall_num = = wall_none ) return window_event_result : : ignored ;
2010-06-14 08:13:16 +00:00
2017-06-10 03:31:02 +00:00
const auto trigger_num = vmwallptr ( wall_num ) - > trigger ;
2015-04-26 20:15:50 +00:00
if ( trigger_num = = trigger_none )
2016-12-24 08:50:29 +00:00
return window_event_result : : ignored ;
2006-03-20 17:12:09 +00:00
2016-12-24 08:50:29 +00:00
{
auto result = check_trigger_sub ( plrobj , trigger_num , Player_num , shot ) ;
if ( result ! = window_event_result : : ignored )
return result ;
}
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2017-06-10 03:31:02 +00:00
auto & t = * vmtrgptr ( trigger_num ) ;
2016-02-06 22:12:54 +00:00
if ( t . flags & TRIGGER_ONE_SHOT )
{
t . flags & = ~ TRIGGER_ON ;
2013-03-03 01:03:33 +00:00
2015-07-12 01:04:21 +00:00
const auto & & csegp = vcsegptr ( seg - > children [ side ] ) ;
2014-09-06 04:06:18 +00:00
auto cside = find_connect_side ( seg , csegp ) ;
2016-01-03 20:21:35 +00:00
Assert ( cside ! = side_none ) ;
2013-03-03 01:03:33 +00:00
2016-02-12 04:02:28 +00:00
const auto cwall_num = csegp - > sides [ cside ] . wall_num ;
if ( cwall_num = = wall_none )
2016-12-24 08:50:29 +00:00
return window_event_result : : ignored ;
2013-03-03 01:03:33 +00:00
2017-06-10 03:31:02 +00:00
const auto ctrigger_num = vmwallptr ( cwall_num ) - > trigger ;
const auto & & ct = vmtrgptr ( ctrigger_num ) ;
2016-02-06 22:12:54 +00:00
ct - > flags & = ~ TRIGGER_ON ;
2013-03-03 01:03:33 +00:00
}
# endif
2006-03-20 17:12:09 +00:00
if ( Game_mode & GM_MULTI )
multi_send_trigger ( trigger_num ) ;
}
2016-12-24 08:50:29 +00:00
return window_event_result : : handled ;
2006-03-20 17:12:09 +00:00
}
/*
2016-01-09 16:38:14 +00:00
* reads a v29_trigger structure from a PHYSFS_File
2006-03-20 17:12:09 +00:00
*/
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2014-02-09 05:56:44 +00:00
void v26_trigger_read ( PHYSFS_File * fp , trigger & t )
{
int type ;
switch ( ( type = PHYSFSX_readByte ( fp ) ) )
{
case TT_OPEN_DOOR : // door
t . flags = TRIGGER_CONTROL_DOORS ;
break ;
case TT_MATCEN : // matcen
t . flags = TRIGGER_MATCEN ;
break ;
case TT_EXIT : // exit
t . flags = TRIGGER_EXIT ;
break ;
case TT_SECRET_EXIT : // secret exit
t . flags = TRIGGER_SECRET_EXIT ;
break ;
case TT_ILLUSION_OFF : // illusion off
t . flags = TRIGGER_ILLUSION_OFF ;
break ;
case TT_ILLUSION_ON : // illusion on
t . flags = TRIGGER_ILLUSION_ON ;
break ;
default :
con_printf ( CON_URGENT , " Warning: unsupported trigger type %d " , type ) ;
throw std : : runtime_error ( " unsupported trigger type " ) ;
}
2016-02-06 22:12:54 +00:00
if ( PHYSFSX_readByte ( fp ) & 2 ) // one shot
t . flags | = TRIGGER_ONE_SHOT ;
2014-02-09 05:56:44 +00:00
t . num_links = PHYSFSX_readShort ( fp ) ;
t . value = PHYSFSX_readInt ( fp ) ;
2016-02-06 22:12:55 +00:00
PHYSFSX_readInt ( fp ) ;
2014-02-09 05:56:44 +00:00
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
t . seg [ i ] = PHYSFSX_readShort ( fp ) ;
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
t . side [ i ] = PHYSFSX_readShort ( fp ) ;
}
2016-01-09 16:38:14 +00:00
void v25_trigger_read ( PHYSFS_File * fp , trigger * t )
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2016-01-09 16:38:14 +00:00
extern void v29_trigger_read ( v29_trigger * t , PHYSFS_File * fp )
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
{
2014-02-08 23:25:29 +00:00
# if defined(DXX_BUILD_DESCENT_I)
PHYSFSX_readByte ( fp ) ;
# elif defined(DXX_BUILD_DESCENT_II)
2011-06-01 07:59:55 +00:00
t - > type = PHYSFSX_readByte ( fp ) ;
2014-02-08 23:25:29 +00:00
# endif
2011-06-01 07:59:55 +00:00
t - > flags = PHYSFSX_readShort ( fp ) ;
t - > value = PHYSFSX_readFix ( fp ) ;
2016-02-06 22:12:55 +00:00
PHYSFSX_readFix ( fp ) ;
2011-06-01 07:59:55 +00:00
t - > link_num = PHYSFSX_readByte ( fp ) ;
t - > num_links = PHYSFSX_readShort ( fp ) ;
2017-10-14 17:10:31 +00:00
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
2011-06-01 07:59:55 +00:00
t - > seg [ i ] = PHYSFSX_readShort ( fp ) ;
2017-10-14 17:10:31 +00:00
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
2011-06-01 07:59:55 +00:00
t - > side [ i ] = PHYSFSX_readShort ( fp ) ;
2006-03-20 17:12:09 +00:00
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
/*
2016-01-09 16:38:14 +00:00
* reads a v30_trigger structure from a PHYSFS_File
2006-03-20 17:12:09 +00:00
*/
2016-01-09 16:38:14 +00:00
extern void v30_trigger_read ( v30_trigger * t , PHYSFS_File * fp )
2006-03-20 17:12:09 +00:00
{
2011-06-01 07:59:55 +00:00
t - > flags = PHYSFSX_readShort ( fp ) ;
t - > num_links = PHYSFSX_readByte ( fp ) ;
t - > pad = PHYSFSX_readByte ( fp ) ;
t - > value = PHYSFSX_readFix ( fp ) ;
t - > time = PHYSFSX_readFix ( fp ) ;
2017-10-14 17:10:31 +00:00
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
2011-06-01 07:59:55 +00:00
t - > seg [ i ] = PHYSFSX_readShort ( fp ) ;
2017-10-14 17:10:31 +00:00
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
2011-06-01 07:59:55 +00:00
t - > side [ i ] = PHYSFSX_readShort ( fp ) ;
2006-03-20 17:12:09 +00:00
}
/*
2016-01-09 16:38:14 +00:00
* reads a trigger structure from a PHYSFS_File
2006-03-20 17:12:09 +00:00
*/
2016-01-09 16:38:14 +00:00
extern void trigger_read ( trigger * t , PHYSFS_File * fp )
2006-03-20 17:12:09 +00:00
{
2011-06-01 07:59:55 +00:00
t - > type = PHYSFSX_readByte ( fp ) ;
t - > flags = PHYSFSX_readByte ( fp ) ;
t - > num_links = PHYSFSX_readByte ( fp ) ;
2014-01-12 23:00:43 +00:00
PHYSFSX_readByte ( fp ) ;
2011-06-01 07:59:55 +00:00
t - > value = PHYSFSX_readFix ( fp ) ;
2016-02-06 22:12:55 +00:00
PHYSFSX_readFix ( fp ) ;
2017-10-14 17:10:31 +00:00
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
2011-06-01 07:59:55 +00:00
t - > seg [ i ] = PHYSFSX_readShort ( fp ) ;
2017-10-14 17:10:31 +00:00
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
2011-06-01 07:59:55 +00:00
t - > side [ i ] = PHYSFSX_readShort ( fp ) ;
2006-03-20 17:12:09 +00:00
}
2014-02-09 05:45:27 +00:00
static ubyte trigger_type_from_flags ( short flags )
{
if ( flags & TRIGGER_CONTROL_DOORS )
return TT_OPEN_DOOR ;
2015-11-08 18:55:51 +00:00
else if ( flags & ( TRIGGER_SHIELD_DAMAGE | TRIGGER_ENERGY_DRAIN ) )
{
}
2014-02-09 05:45:27 +00:00
else if ( flags & TRIGGER_EXIT )
return TT_EXIT ;
else if ( flags & TRIGGER_MATCEN )
return TT_MATCEN ;
else if ( flags & TRIGGER_ILLUSION_OFF )
return TT_ILLUSION_OFF ;
else if ( flags & TRIGGER_SECRET_EXIT )
return TT_SECRET_EXIT ;
else if ( flags & TRIGGER_ILLUSION_ON )
return TT_ILLUSION_ON ;
else if ( flags & TRIGGER_UNLOCK_DOORS )
return TT_UNLOCK_DOOR ;
else if ( flags & TRIGGER_OPEN_WALL )
return TT_OPEN_WALL ;
else if ( flags & TRIGGER_CLOSE_WALL )
return TT_CLOSE_WALL ;
else if ( flags & TRIGGER_ILLUSORY_WALL )
return TT_ILLUSORY_WALL ;
2015-11-08 18:55:51 +00:00
throw std : : runtime_error ( " unsupported trigger type " ) ;
2014-02-09 05:45:27 +00:00
}
static void v30_trigger_to_v31_trigger ( trigger & t , const v30_trigger & trig )
{
t . type = trigger_type_from_flags ( trig . flags & ~ TRIGGER_ON ) ;
t . flags = ( trig . flags & TRIGGER_ONE_SHOT ) ? TF_ONE_SHOT : 0 ;
t . num_links = trig . num_links ;
t . num_links = trig . num_links ;
t . value = trig . value ;
t . seg = trig . seg ;
t . side = trig . side ;
}
static void v29_trigger_read_as_v30 ( PHYSFS_File * fp , v30_trigger & trig )
{
v29_trigger trig29 ;
v29_trigger_read ( & trig29 , fp ) ;
trig . flags = trig29 . flags ;
// skip trig29.link_num. v30_trigger does not need it
trig . num_links = trig29 . num_links ;
trig . value = trig29 . value ;
trig . time = trig29 . time ;
trig . seg = trig29 . seg ;
trig . side = trig29 . side ;
}
void v29_trigger_read_as_v31 ( PHYSFS_File * fp , trigger & t )
{
v30_trigger trig ;
v29_trigger_read_as_v30 ( fp , trig ) ;
v30_trigger_to_v31_trigger ( t , trig ) ;
}
void v30_trigger_read_as_v31 ( PHYSFS_File * fp , trigger & t )
{
v30_trigger trig ;
v30_trigger_read ( & trig , fp ) ;
v30_trigger_to_v31_trigger ( t , trig ) ;
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2016-02-06 22:12:55 +00:00
DEFINE_SERIAL_UDT_TO_MESSAGE ( trigger , t , ( serial : : pad < 1 > ( ) , t . flags , t . value , serial : : pad < 4 > ( ) , t . link_num , t . num_links , t . seg , t . side ) ) ;
2014-01-12 23:00:43 +00:00
ASSERT_SERIAL_UDT_MESSAGE_SIZE ( trigger , 54 ) ;
# elif defined(DXX_BUILD_DESCENT_II)
2016-02-06 22:12:55 +00:00
DEFINE_SERIAL_UDT_TO_MESSAGE ( trigger , t , ( t . type , t . flags , t . num_links , serial : : pad < 1 > ( ) , t . value , serial : : pad < 4 > ( ) , t . seg , t . side ) ) ;
2014-01-12 23:00:43 +00:00
ASSERT_SERIAL_UDT_MESSAGE_SIZE ( trigger , 52 ) ;
2013-03-03 01:03:33 +00:00
# endif
2016-02-06 22:12:54 +00:00
}
2009-10-05 02:51:37 +00:00
/*
2016-01-09 16:38:14 +00:00
* reads n trigger structs from a PHYSFS_File and swaps if specified
2009-10-05 02:51:37 +00:00
*/
2016-01-09 16:38:14 +00:00
void trigger_read ( PHYSFS_File * fp , trigger & t )
2009-10-05 02:51:37 +00:00
{
2014-01-12 23:00:43 +00:00
PHYSFSX_serialize_read ( fp , t ) ;
}
2010-06-14 08:13:16 +00:00
2016-01-09 16:38:14 +00:00
void trigger_write ( PHYSFS_File * fp , const trigger & t )
2014-01-12 23:00:43 +00:00
{
PHYSFSX_serialize_write ( fp , t ) ;
2009-10-05 02:51:37 +00:00
}
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-01-09 16:38:14 +00:00
void v29_trigger_write ( PHYSFS_File * fp , const trigger & rt )
2006-03-20 17:12:09 +00:00
{
2014-02-09 18:41:42 +00:00
const trigger * t = & rt ;
PHYSFSX_writeU8 ( fp , 0 ) ; // unused 'type'
# if defined(DXX_BUILD_DESCENT_I)
PHYSFS_writeSLE16 ( fp , t - > flags ) ;
# elif defined(DXX_BUILD_DESCENT_II)
switch ( t - > type )
2013-03-03 01:03:33 +00:00
{
2014-02-09 18:41:42 +00:00
case TT_OPEN_DOOR :
PHYSFS_writeSLE16 ( fp , TRIGGER_CONTROL_DOORS | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
case TT_EXIT :
PHYSFS_writeSLE16 ( fp , TRIGGER_EXIT | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
case TT_MATCEN :
PHYSFS_writeSLE16 ( fp , TRIGGER_MATCEN | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
case TT_ILLUSION_OFF :
PHYSFS_writeSLE16 ( fp , TRIGGER_ILLUSION_OFF | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
case TT_SECRET_EXIT :
PHYSFS_writeSLE16 ( fp , TRIGGER_SECRET_EXIT | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
case TT_ILLUSION_ON :
PHYSFS_writeSLE16 ( fp , TRIGGER_ILLUSION_ON | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
case TT_UNLOCK_DOOR :
PHYSFS_writeSLE16 ( fp , TRIGGER_UNLOCK_DOORS | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
case TT_OPEN_WALL :
PHYSFS_writeSLE16 ( fp , TRIGGER_OPEN_WALL | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
case TT_CLOSE_WALL :
PHYSFS_writeSLE16 ( fp , TRIGGER_CLOSE_WALL | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
case TT_ILLUSORY_WALL :
PHYSFS_writeSLE16 ( fp , TRIGGER_ILLUSORY_WALL | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
default :
Int3 ( ) ;
PHYSFS_writeSLE16 ( fp , 0 ) ;
break ;
}
# endif
PHYSFSX_writeFix ( fp , t - > value ) ;
2016-02-06 22:12:55 +00:00
PHYSFSX_writeFix ( fp , 0 ) ;
2014-02-09 18:41:42 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2014-02-09 18:41:42 +00:00
PHYSFSX_writeU8 ( fp , t - > link_num ) ;
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2014-02-09 18:41:42 +00:00
PHYSFSX_writeU8 ( fp , - 1 ) ; //t->link_num
2013-03-03 01:03:33 +00:00
# endif
2014-02-09 18:41:42 +00:00
PHYSFS_writeSLE16 ( fp , t - > num_links ) ;
2006-03-20 17:12:09 +00:00
2014-02-09 18:41:42 +00:00
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
PHYSFS_writeSLE16 ( fp , t - > seg [ i ] ) ;
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
PHYSFS_writeSLE16 ( fp , t - > side [ i ] ) ;
}
2016-08-25 04:05:32 +00:00
}
2014-02-09 18:41:42 +00:00
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-01-09 16:38:14 +00:00
void v30_trigger_write ( PHYSFS_File * fp , const trigger & rt )
2014-02-09 18:41:42 +00:00
{
const trigger * t = & rt ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2014-02-09 18:41:42 +00:00
if ( t - > flags & TRIGGER_CONTROL_DOORS )
PHYSFSX_writeU8 ( fp , TT_OPEN_DOOR ) ; // door
else if ( t - > flags & TRIGGER_MATCEN )
PHYSFSX_writeU8 ( fp , TT_MATCEN ) ; // matcen
else if ( t - > flags & TRIGGER_EXIT )
PHYSFSX_writeU8 ( fp , TT_EXIT ) ; // exit
else if ( t - > flags & TRIGGER_SECRET_EXIT )
PHYSFSX_writeU8 ( fp , TT_SECRET_EXIT ) ; // secret exit
else if ( t - > flags & TRIGGER_ILLUSION_OFF )
PHYSFSX_writeU8 ( fp , TT_ILLUSION_OFF ) ; // illusion off
else if ( t - > flags & TRIGGER_ILLUSION_ON )
PHYSFSX_writeU8 ( fp , TT_ILLUSION_ON ) ; // illusion on
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2014-02-09 18:41:42 +00:00
PHYSFSX_writeU8 ( fp , t - > type ) ;
# endif
2006-03-20 17:12:09 +00:00
2014-02-09 18:41:42 +00:00
# if defined(DXX_BUILD_DESCENT_I)
PHYSFS_writeSLE16 ( fp , t - > flags ) ;
# elif defined(DXX_BUILD_DESCENT_II)
switch ( t - > type )
{
case TT_OPEN_DOOR :
PHYSFS_writeSLE16 ( fp , TRIGGER_CONTROL_DOORS | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
2006-03-20 17:12:09 +00:00
2014-02-09 18:41:42 +00:00
case TT_EXIT :
PHYSFS_writeSLE16 ( fp , TRIGGER_EXIT | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
2010-06-14 08:13:16 +00:00
2014-02-09 18:41:42 +00:00
case TT_MATCEN :
PHYSFS_writeSLE16 ( fp , TRIGGER_MATCEN | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
2010-06-14 08:13:16 +00:00
2014-02-09 18:41:42 +00:00
case TT_ILLUSION_OFF :
PHYSFS_writeSLE16 ( fp , TRIGGER_ILLUSION_OFF | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
2010-06-14 08:13:16 +00:00
2014-02-09 18:41:42 +00:00
case TT_SECRET_EXIT :
PHYSFS_writeSLE16 ( fp , TRIGGER_SECRET_EXIT | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
2010-06-14 08:13:16 +00:00
2014-02-09 18:41:42 +00:00
case TT_ILLUSION_ON :
PHYSFS_writeSLE16 ( fp , TRIGGER_ILLUSION_ON | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
2010-06-14 08:13:16 +00:00
2014-02-09 18:41:42 +00:00
case TT_UNLOCK_DOOR :
PHYSFS_writeSLE16 ( fp , TRIGGER_UNLOCK_DOORS | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
2010-06-14 08:13:16 +00:00
2014-02-09 18:41:42 +00:00
case TT_OPEN_WALL :
PHYSFS_writeSLE16 ( fp , TRIGGER_OPEN_WALL | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
2010-06-14 08:13:16 +00:00
2014-02-09 18:41:42 +00:00
case TT_CLOSE_WALL :
PHYSFS_writeSLE16 ( fp , TRIGGER_CLOSE_WALL | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
2010-06-14 08:13:16 +00:00
2014-02-09 18:41:42 +00:00
case TT_ILLUSORY_WALL :
PHYSFS_writeSLE16 ( fp , TRIGGER_ILLUSORY_WALL | ( ( t - > flags & TF_ONE_SHOT ) ? TRIGGER_ONE_SHOT : 0 ) ) ;
break ;
default :
Int3 ( ) ;
PHYSFS_writeSLE16 ( fp , 0 ) ;
break ;
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2014-02-09 18:41:42 +00:00
PHYSFSX_writeU8 ( fp , t - > num_links ) ;
PHYSFSX_writeU8 ( fp , 0 ) ; // t->pad
2006-03-20 17:12:09 +00:00
PHYSFSX_writeFix ( fp , t - > value ) ;
2016-02-06 22:12:55 +00:00
PHYSFSX_writeFix ( fp , 0 ) ;
2006-03-20 17:12:09 +00:00
2014-02-09 18:41:42 +00:00
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
PHYSFS_writeSLE16 ( fp , t - > seg [ i ] ) ;
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
PHYSFS_writeSLE16 ( fp , t - > side [ i ] ) ;
}
2016-08-25 04:05:32 +00:00
}
2014-02-09 18:41:42 +00:00
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-01-09 16:38:14 +00:00
void v31_trigger_write ( PHYSFS_File * fp , const trigger & rt )
2014-02-09 18:41:42 +00:00
{
const trigger * t = & rt ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2014-02-09 18:41:42 +00:00
if ( t - > flags & TRIGGER_CONTROL_DOORS )
PHYSFSX_writeU8 ( fp , TT_OPEN_DOOR ) ; // door
else if ( t - > flags & TRIGGER_MATCEN )
PHYSFSX_writeU8 ( fp , TT_MATCEN ) ; // matcen
else if ( t - > flags & TRIGGER_EXIT )
PHYSFSX_writeU8 ( fp , TT_EXIT ) ; // exit
else if ( t - > flags & TRIGGER_SECRET_EXIT )
PHYSFSX_writeU8 ( fp , TT_SECRET_EXIT ) ; // secret exit
else if ( t - > flags & TRIGGER_ILLUSION_OFF )
PHYSFSX_writeU8 ( fp , TT_ILLUSION_OFF ) ; // illusion off
else if ( t - > flags & TRIGGER_ILLUSION_ON )
PHYSFSX_writeU8 ( fp , TT_ILLUSION_ON ) ; // illusion on
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2014-02-09 18:41:42 +00:00
PHYSFSX_writeU8 ( fp , t - > type ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2014-02-09 18:41:42 +00:00
# if defined(DXX_BUILD_DESCENT_I)
PHYSFSX_writeU8 ( fp , ( t - > flags & TRIGGER_ONE_SHOT ) ? 2 : 0 ) ; // flags
# elif defined(DXX_BUILD_DESCENT_II)
PHYSFSX_writeU8 ( fp , t - > flags ) ;
# endif
PHYSFSX_writeU8 ( fp , t - > num_links ) ;
PHYSFSX_writeU8 ( fp , 0 ) ; // t->pad
PHYSFSX_writeFix ( fp , t - > value ) ;
2016-02-06 22:12:55 +00:00
PHYSFSX_writeFix ( fp , 0 ) ;
2014-02-09 18:41:42 +00:00
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
2006-03-20 17:12:09 +00:00
PHYSFS_writeSLE16 ( fp , t - > seg [ i ] ) ;
2014-02-09 18:41:42 +00:00
for ( unsigned i = 0 ; i < MAX_WALLS_PER_LINK ; i + + )
2006-03-20 17:12:09 +00:00
PHYSFS_writeSLE16 ( fp , t - > side [ i ] ) ;
}
2016-08-25 04:05:32 +00:00
}