2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
16 * New Triggers and Switches.
55 #include "editor/editor.h"
58 trigger Triggers[MAX_TRIGGERS];
61 //link Links[MAX_WALL_LINKS];
65 fix trigger_time_count=F1_0;
67 //-----------------------------------------------------------------
68 // Initializes all the switches.
75 for (i=0;i<MAX_TRIGGERS;i++)
78 Triggers[i].flags = 0;
79 Triggers[i].num_links = 0;
80 Triggers[i].value = 0;
81 Triggers[i].time = -1;
86 //-----------------------------------------------------------------
87 // Executes a link, attached to a trigger.
88 // Toggles all walls linked to the switch.
89 // Opens doors, Blasts blast walls, turns off illusions.
90 void do_link(sbyte trigger_num)
94 mprintf((0, "Door link!\n"));
96 if (trigger_num != -1) {
97 for (i=0;i<Triggers[trigger_num].num_links;i++) {
98 wall_toggle(&Segments[Triggers[trigger_num].seg[i]], Triggers[trigger_num].side[i]);
99 mprintf((0," trigger_num %d : seg %d, side %d\n",
100 trigger_num, Triggers[trigger_num].seg[i], Triggers[trigger_num].side[i]));
106 void do_close_door(sbyte trigger_num)
110 mprintf((0, "Door close!\n"));
112 if (trigger_num != -1) {
113 for (i=0;i<Triggers[trigger_num].num_links;i++)
114 wall_close_door(&Segments[Triggers[trigger_num].seg[i]], Triggers[trigger_num].side[i]);
118 //turns lighting on. returns true if lights were actually turned on. (they
119 //would not be if they had previously been shot out).
120 int do_light_on(sbyte trigger_num)
124 mprintf((0, "Lighting on!\n"));
126 if (trigger_num != -1) {
127 for (i=0;i<Triggers[trigger_num].num_links;i++) {
129 segnum = Triggers[trigger_num].seg[i];
130 sidenum = Triggers[trigger_num].side[i];
132 //check if tmap2 casts light before turning the light on. This
133 //is to keep us from turning on blown-out lights
134 if (TmapInfo[Segments[segnum].sides[sidenum].tmap_num2 & 0x3fff].lighting) {
135 ret |= add_light(segnum, sidenum); //any light sets flag
136 enable_flicker(segnum, sidenum);
144 //turns lighting off. returns true if lights were actually turned off. (they
145 //would not be if they had previously been shot out).
146 int do_light_off(sbyte trigger_num)
150 mprintf((0, "Lighting off!\n"));
152 if (trigger_num != -1) {
153 for (i=0;i<Triggers[trigger_num].num_links;i++) {
155 segnum = Triggers[trigger_num].seg[i];
156 sidenum = Triggers[trigger_num].side[i];
158 //check if tmap2 casts light before turning the light off. This
159 //is to keep us from turning off blown-out lights
160 if (TmapInfo[Segments[segnum].sides[sidenum].tmap_num2 & 0x3fff].lighting) {
161 ret |= subtract_light(segnum, sidenum); //any light sets flag
162 disable_flicker(segnum, sidenum);
170 // Unlocks all doors linked to the switch.
171 void do_unlock_doors(sbyte trigger_num)
175 mprintf((0, "Door unlock!\n"));
177 if (trigger_num != -1) {
178 for (i=0;i<Triggers[trigger_num].num_links;i++) {
179 Walls[Segments[Triggers[trigger_num].seg[i]].sides[Triggers[trigger_num].side[i]].wall_num].flags &= ~WALL_DOOR_LOCKED;
180 Walls[Segments[Triggers[trigger_num].seg[i]].sides[Triggers[trigger_num].side[i]].wall_num].keys = KEY_NONE;
185 // Return trigger number if door is controlled by a wall switch, else return -1.
186 int door_is_wall_switched(int wall_num)
190 for (t=0; t<Num_triggers; t++) {
191 for (i=0; i<Triggers[t].num_links; i++) {
192 if (Segments[Triggers[t].seg[i]].sides[Triggers[t].side[i]].wall_num == wall_num) {
193 mprintf((0, "Wall #%i is keyed to trigger #%i, link #%i\n", wall_num, t, i));
202 void flag_wall_switched_doors(void)
206 for (i=0; i<Num_walls; i++) {
207 if (door_is_wall_switched(i))
208 Walls[i].flags |= WALL_WALL_SWITCH;
213 // Locks all doors linked to the switch.
214 void do_lock_doors(sbyte trigger_num)
218 mprintf((0, "Door lock!\n"));
220 if (trigger_num != -1) {
221 for (i=0;i<Triggers[trigger_num].num_links;i++) {
222 Walls[Segments[Triggers[trigger_num].seg[i]].sides[Triggers[trigger_num].side[i]].wall_num].flags |= WALL_DOOR_LOCKED;
227 // Changes walls pointed to by a trigger. returns true if any walls changed
228 int do_change_walls(sbyte trigger_num)
232 mprintf((0, "Wall remove!\n"));
234 if (trigger_num != -1) {
235 for (i=0;i<Triggers[trigger_num].num_links;i++) {
236 segment *segp,*csegp;
240 segp = &Segments[Triggers[trigger_num].seg[i]];
241 side = Triggers[trigger_num].side[i];
243 if (segp->children[side] < 0)
250 csegp = &Segments[segp->children[side]];
251 cside = find_connect_side(segp, csegp);
255 //segp->sides[side].wall_num = -1;
256 //csegp->sides[cside].wall_num = -1;
258 switch (Triggers[trigger_num].type) {
259 case TT_OPEN_WALL: new_wall_type = WALL_OPEN; break;
260 case TT_CLOSE_WALL: new_wall_type = WALL_CLOSED; break;
261 case TT_ILLUSORY_WALL: new_wall_type = WALL_ILLUSION; break;
263 Assert(0); /* new_wall_type unset */
268 if (Walls[segp->sides[side].wall_num].type == new_wall_type &&
269 (cside < 0 || csegp->sides[cside].wall_num < 0 ||
270 Walls[csegp->sides[cside].wall_num].type == new_wall_type))
271 continue; //already in correct state, so skip
275 switch (Triggers[trigger_num].type) {
278 mprintf((0,"Open wall\n"));
280 if ((TmapInfo[segp->sides[side].tmap_num].flags & TMI_FORCE_FIELD)) {
282 compute_center_point_on_side(&pos, segp, side );
283 digi_link_sound_to_pos( SOUND_FORCEFIELD_OFF, SEGMENT_NUMBER(segp), side, &pos, 0, F1_0 );
284 Walls[segp->sides[side].wall_num].type = new_wall_type;
285 digi_kill_sound_linked_to_segment(SEGMENT_NUMBER(segp), side, SOUND_FORCEFIELD_HUM);
286 if (cside > -1 && csegp->sides[cside].wall_num > -1)
288 Walls[csegp->sides[cside].wall_num].type = new_wall_type;
289 digi_kill_sound_linked_to_segment(SEGMENT_NUMBER(csegp), cside, SOUND_FORCEFIELD_HUM);
293 start_wall_cloak(segp,side);
300 mprintf((0,"Close wall\n"));
302 if ((TmapInfo[segp->sides[side].tmap_num].flags & TMI_FORCE_FIELD)) {
304 compute_center_point_on_side(&pos, segp, side );
305 digi_link_sound_to_pos(SOUND_FORCEFIELD_HUM, SEGMENT_NUMBER(segp), side, &pos, 1, F1_0/2);
306 Walls[segp->sides[side].wall_num].type = new_wall_type;
307 if (cside > -1 && csegp->sides[cside].wall_num > -1)
308 Walls[csegp->sides[cside].wall_num].type = new_wall_type;
311 start_wall_decloak(segp,side);
314 case TT_ILLUSORY_WALL:
315 mprintf((0,"Illusory wall\n"));
316 Walls[segp->sides[side].wall_num].type = new_wall_type;
317 if (cside > -1 && csegp->sides[cside].wall_num > -1)
318 Walls[csegp->sides[cside].wall_num].type = new_wall_type;
323 kill_stuck_objects(segp->sides[side].wall_num);
324 if (cside > -1 && csegp->sides[cside].wall_num > -1)
325 kill_stuck_objects(csegp->sides[cside].wall_num);
333 void print_trigger_message (int pnum,int trig,int shot,char *message)
335 char *pl; //points to 's' or nothing for plural word
337 if (pnum!=Player_num)
340 pl = (Triggers[trig].num_links>1)?"s":"";
342 if (!(Triggers[trig].flags & TF_NO_MESSAGE) && shot)
343 HUD_init_message (message,pl);
347 void do_matcen(sbyte trigger_num)
351 mprintf((0, "Matcen link!\n"));
353 if (trigger_num != -1) {
354 for (i=0;i<Triggers[trigger_num].num_links;i++) {
355 trigger_matcen(Triggers[trigger_num].seg[i] );
356 mprintf((0," trigger_num %d : seg %d\n",
357 trigger_num, Triggers[trigger_num].seg[i]));
363 void do_il_on(sbyte trigger_num)
367 mprintf((0, "Illusion ON\n"));
369 if (trigger_num != -1) {
370 for (i=0;i<Triggers[trigger_num].num_links;i++) {
371 wall_illusion_on(&Segments[Triggers[trigger_num].seg[i]], Triggers[trigger_num].side[i]);
372 mprintf((0," trigger_num %d : seg %d, side %d\n",
373 trigger_num, Triggers[trigger_num].seg[i], Triggers[trigger_num].side[i]));
378 void do_il_off(sbyte trigger_num)
382 mprintf((0, "Illusion OFF\n"));
384 if (trigger_num != -1) {
385 for (i=0;i<Triggers[trigger_num].num_links;i++) {
387 segment *seg = &Segments[Triggers[trigger_num].seg[i]];
388 int side = Triggers[trigger_num].side[i];
390 wall_illusion_off(seg, side);
392 mprintf((0," trigger_num %d : seg %d, side %d\n",
393 trigger_num, Triggers[trigger_num].seg[i], Triggers[trigger_num].side[i]));
395 compute_center_point_on_side(&cp, seg, side );
396 digi_link_sound_to_pos( SOUND_WALL_REMOVED, SEGMENT_NUMBER(seg), side, &cp, 0, F1_0 );
402 extern void EnterSecretLevel(void);
403 extern void ExitSecretLevel(void);
404 extern int p_secret_level_destroyed(void);
406 int wall_is_forcefield(trigger *trig)
410 for (i=0;i<trig->num_links;i++)
411 if ((TmapInfo[Segments[trig->seg[i]].sides[trig->side[i]].tmap_num].flags & TMI_FORCE_FIELD))
414 return (i<trig->num_links);
417 int check_trigger_sub(int trigger_num, int pnum,int shot)
419 trigger *trig = &Triggers[trigger_num];
421 mprintf ((0,"trignum=%d type=%d shot=%d\n",trigger_num,trig->type,shot));
423 if (trig->flags & TF_DISABLED)
424 return 1; //1 means don't send trigger hit to other players
426 if (trig->flags & TF_ONE_SHOT) //if this is a one-shot...
427 trig->flags |= TF_DISABLED; //..then don't let it happen again
429 switch (trig->type) {
433 if (pnum!=Player_num)
436 digi_stop_all(); //kill the sounds
438 if (Current_level_num > 0) {
439 start_endlevel_sequence();
440 mprintf((0,"WOOHOO! (leaving the mine!)\n"));
441 } else if (Current_level_num < 0) {
442 if ((Players[Player_num].shields < 0) || Player_is_dead)
449 nm_messagebox( "Yo!", 1, "You have hit the exit trigger!", "" );
451 Int3(); //level num == 0, but no editor!
457 case TT_SECRET_EXIT: {
462 if (pnum!=Player_num)
465 if ((Players[Player_num].shields < 0) || Player_is_dead)
468 if (Game_mode & GM_MULTI) {
469 HUD_init_message("Secret Level Teleporter disabled in multiplayer!");
470 digi_play_sample( SOUND_BAD_SELECTION, F1_0 );
475 truth = p_secret_level_destroyed();
477 if (Newdemo_state == ND_STATE_RECORDING) // record whether we're really going to the secret level
478 newdemo_record_secret_exit_blown(truth);
480 if ((Newdemo_state != ND_STATE_PLAYBACK) && truth) {
481 HUD_init_message("Secret Level destroyed. Exit disabled.");
482 digi_play_sample( SOUND_BAD_SELECTION, F1_0 );
488 HUD_init_message("Secret Level Teleporter disabled in Descent 2 Demo");
489 digi_play_sample( SOUND_BAD_SELECTION, F1_0 );
493 if (Newdemo_state == ND_STATE_RECORDING) // stop demo recording
494 Newdemo_state = ND_STATE_PAUSED;
496 digi_stop_all(); //kill the sounds
498 digi_play_sample( SOUND_SECRET_EXIT, F1_0 );
499 mprintf((0,"Exiting to secret level\n"));
501 // -- BOGUS -- IMPOSSIBLE -- if (Game_mode & GM_MULTI)
502 // -- BOGUS -- IMPOSSIBLE -- multi_send_endlevel_start(1);
503 // -- BOGUS -- IMPOSSIBLE --
504 // -- BOGUS -- IMPOSSIBLE -- if (Game_mode & GM_NETWORK)
505 // -- BOGUS -- IMPOSSIBLE -- network_do_frame(1, 1);
507 gr_palette_fade_out(gr_palette, 32, 0);
509 Control_center_destroyed = 0;
517 do_link(trigger_num);
518 print_trigger_message (pnum,trigger_num,shot,"Door%s opened!");
523 do_close_door(trigger_num);
524 print_trigger_message (pnum,trigger_num,shot,"Door%s closed!");
529 do_unlock_doors(trigger_num);
530 print_trigger_message (pnum,trigger_num,shot,"Door%s unlocked!");
536 do_lock_doors(trigger_num);
537 print_trigger_message (pnum,trigger_num,shot,"Door%s locked!");
542 if (do_change_walls(trigger_num))
544 if (wall_is_forcefield(trig))
545 print_trigger_message (pnum,trigger_num,shot,"Force field%s deactivated!");
547 print_trigger_message (pnum,trigger_num,shot,"Wall%s opened!");
552 if (do_change_walls(trigger_num))
554 if (wall_is_forcefield(trig))
555 print_trigger_message (pnum,trigger_num,shot,"Force field%s activated!");
557 print_trigger_message (pnum,trigger_num,shot,"Wall%s closed!");
561 case TT_ILLUSORY_WALL:
562 //don't know what to say, so say nothing
563 do_change_walls(trigger_num);
567 if (!(Game_mode & GM_MULTI) || (Game_mode & GM_MULTI_ROBOTS))
568 do_matcen(trigger_num);
573 do_il_on(trigger_num);
574 print_trigger_message (pnum,trigger_num,shot,"Illusion%s on!");
577 case TT_ILLUSION_OFF:
579 do_il_off(trigger_num);
580 print_trigger_message (pnum,trigger_num,shot,"Illusion%s off!");
584 if (do_light_off(trigger_num))
585 print_trigger_message (pnum,trigger_num,shot,"Lights off!");
589 if (do_light_on(trigger_num))
590 print_trigger_message (pnum,trigger_num,shot,"Lights on!");
602 //-----------------------------------------------------------------
603 // Checks for a trigger whenever an object hits a trigger side.
604 void check_trigger(segment *seg, short side, short objnum,int shot)
606 int wall_num, trigger_num; //, ctrigger_num;
612 if ((objnum == Players[Player_num].objnum) || ((Objects[objnum].type == OBJ_ROBOT) && (Robot_info[Objects[objnum].id].companion))) {
614 if ( Newdemo_state == ND_STATE_RECORDING )
615 newdemo_record_trigger( SEGMENT_NUMBER(seg), side, objnum, shot );
617 wall_num = seg->sides[side].wall_num;
618 if ( wall_num == -1 ) return;
620 trigger_num = Walls[wall_num].trigger;
622 if (trigger_num == -1)
625 //##if ( Newdemo_state == ND_STATE_PLAYBACK ) {
626 //## if (Triggers[trigger_num].type == TT_EXIT) {
627 //## start_endlevel_sequence();
632 if (check_trigger_sub(trigger_num, Player_num,shot))
635 //@@if (Triggers[trigger_num].flags & TRIGGER_ONE_SHOT) {
636 //@@ Triggers[trigger_num].flags &= ~TRIGGER_ON;
638 //@@ csegp = &Segments[seg->children[side]];
639 //@@ cside = find_connect_side(seg, csegp);
640 //@@ Assert(cside != -1);
642 //@@ wall_num = csegp->sides[cside].wall_num;
643 //@@ if ( wall_num == -1 ) return;
645 //@@ ctrigger_num = Walls[wall_num].trigger;
647 //@@ Triggers[ctrigger_num].flags &= ~TRIGGER_ON;
651 if (Game_mode & GM_MULTI)
652 multi_send_trigger(trigger_num);
657 void triggers_frame_process()
661 for (i=0;i<Num_triggers;i++)
662 if (Triggers[i].time >= 0)
663 Triggers[i].time -= FrameTime;
668 * reads a v29_trigger structure from a CFILE
670 extern void v29_trigger_read(v29_trigger *t, CFILE *fp)
674 t->type = cfile_read_byte(fp);
675 t->flags = cfile_read_short(fp);
676 t->value = cfile_read_fix(fp);
677 t->time = cfile_read_fix(fp);
678 t->link_num = cfile_read_byte(fp);
679 t->num_links = cfile_read_short(fp);
680 for (i=0; i<MAX_WALLS_PER_LINK; i++ )
681 t->seg[i] = cfile_read_short(fp);
682 for (i=0; i<MAX_WALLS_PER_LINK; i++ )
683 t->side[i] = cfile_read_short(fp);
687 * reads a v30_trigger structure from a CFILE
689 extern void v30_trigger_read(v30_trigger *t, CFILE *fp)
693 t->flags = cfile_read_short(fp);
694 t->num_links = cfile_read_byte(fp);
695 t->pad = cfile_read_byte(fp);
696 t->value = cfile_read_fix(fp);
697 t->time = cfile_read_fix(fp);
698 for (i=0; i<MAX_WALLS_PER_LINK; i++ )
699 t->seg[i] = cfile_read_short(fp);
700 for (i=0; i<MAX_WALLS_PER_LINK; i++ )
701 t->side[i] = cfile_read_short(fp);
705 * reads a trigger structure from a CFILE
707 extern void trigger_read(trigger *t, CFILE *fp)
711 t->type = cfile_read_byte(fp);
712 t->flags = cfile_read_byte(fp);
713 t->num_links = cfile_read_byte(fp);
714 t->pad = cfile_read_byte(fp);
715 t->value = cfile_read_fix(fp);
716 t->time = cfile_read_fix(fp);
717 for (i=0; i<MAX_WALLS_PER_LINK; i++ )
718 t->seg[i] = cfile_read_short(fp);
719 for (i=0; i<MAX_WALLS_PER_LINK; i++ )
720 t->side[i] = cfile_read_short(fp);
724 void trigger_write(trigger *t, short version, PHYSFS_file *fp)
729 PHYSFSX_writeU8(fp, t->type);
735 PHYSFS_writeSLE16(fp, TRIGGER_CONTROL_DOORS);
739 PHYSFS_writeSLE16(fp, TRIGGER_EXIT);
743 PHYSFS_writeSLE16(fp, TRIGGER_MATCEN);
746 case TT_ILLUSION_OFF:
747 PHYSFS_writeSLE16(fp, TRIGGER_ILLUSION_OFF);
751 PHYSFS_writeSLE16(fp, TRIGGER_SECRET_EXIT);
755 PHYSFS_writeSLE16(fp, TRIGGER_ILLUSION_ON);
759 PHYSFS_writeSLE16(fp, TRIGGER_UNLOCK_DOORS);
763 PHYSFS_writeSLE16(fp, TRIGGER_OPEN_WALL);
767 PHYSFS_writeSLE16(fp, TRIGGER_CLOSE_WALL);
770 case TT_ILLUSORY_WALL:
771 PHYSFS_writeSLE16(fp, TRIGGER_ILLUSORY_WALL);
776 PHYSFS_writeSLE16(fp, 0);
780 PHYSFSX_writeU8(fp, t->flags);
784 PHYSFSX_writeU8(fp, t->num_links);
785 PHYSFSX_writeU8(fp, t->pad);
788 PHYSFSX_writeFix(fp, t->value);
789 PHYSFSX_writeFix(fp, t->time);
793 PHYSFSX_writeU8(fp, -1); //t->link_num
794 PHYSFS_writeSLE16(fp, t->num_links);
797 for (i = 0; i < MAX_WALLS_PER_LINK; i++)
798 PHYSFS_writeSLE16(fp, t->seg[i]);
799 for (i = 0; i < MAX_WALLS_PER_LINK; i++)
800 PHYSFS_writeSLE16(fp, t->side[i]);