‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
doors_shared.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\hud_util_shared;
4 #using scripts\shared\system_shared;
5 #using scripts\shared\flag_shared;
6 
7 #insert scripts\shared\shared.gsh;
8 
9 #namespace doors;
10 
11 #define HACKING_PLAYER_WEAPON "pda_hack"
12 #define DOOR_CLEARANCE_TIMER 0.3
13 
14 class ‪cDoor
15 {
16  var ‪m_s_bundle; // Bundle with info regarding the door.
20 
21  var ‪m_e_door; // Door Ent
22 
23  var ‪m_e_trigger; // Trigger Ent
24  var ‪m_e_trigger_player; // Player who opens the door
26 
27  var ‪m_n_hack_pct; // percentage of the current hack completed.
28  var ‪m_b_hacking; // true if hacking is currently taking place.
29 
31 
32  var ‪m_v_open_pos; // Door open and close positions (for slide doors)
34 
35  var ‪m_n_door_connect_paths; // Does door connect paths?
36 
37  var ‪m_b_is_open; // Is the door open?
38 
39  // Overrides that can be set in script
41 
42  var ‪m_door_open_delay_time; // Ability to delat the door opening
43 
45  {
46  ‪m_n_trigger_height = 80; // Default trigger height
47  ‪m_override_swing_angle = undefined;
49  ‪m_e_trigger_player = undefined;
50  }
51 
53  {
54  if( IsDefined(‪m_e_trigger) )
55  {
56  ‪m_e_trigger delete();
57  }
58  }
59 
60  function ‪init_xmodel( str_xmodel, ‪connect_paths, v_origin, v_angles )
61  {
62  if( !IsDefined(str_xmodel) )
63  {
64  str_xmodel = "script_origin";
65  //ASSERTMSG( "No model found in Door Script Bundle" );
66  //return;
67  }
68 
69  ‪m_e_door = ‪spawn( "script_model", v_origin, 1 );
70  ‪m_e_door setModel( str_xmodel );
71  ‪m_e_door.angles = v_angles;
72 
74  {
75  ‪m_e_door DisconnectPaths();
76  }
77  }
78 
79  function ‪get_hack_pos()
80  {
81  v_trigger_offset = ‪m_s_bundle.v_trigger_offset;
82 
83  v_pos = ‪calculate_offset_position( ‪m_e_door.origin, ‪m_e_door.angles, v_trigger_offset );
84  v_pos = ( v_pos[0], v_pos[1], v_pos[2]+50 ); // Its a look at trigger, so move the base of the trigger off the ground
85 
86  if ( IsDefined( ‪m_str_target ) )
87  {
88  ‪e_target = GetEnt( ‪m_str_target, "targetname" );
89  if ( IsDefined( ‪e_target ) )
90  {
91  return ‪e_target.origin;
92  }
93  }
94 
95  return v_pos;
96  }
97 
98  function ‪get_hack_angles()
99  {
100  v_angles = ‪m_e_door.angles;
101 
102  if ( IsDefined( ‪m_str_target ) )
103  {
104  ‪e_target = GetEnt( ‪m_str_target, "targetname" );
105  if ( IsDefined( ‪e_target ) )
106  {
107  return ‪e_target.angles;
108  }
109  }
110 
111  return v_angles;
112  }
113 
115  {
116  // Only certain types of doors have this trigger.
117  //
118  if ( ‪m_s_bundle.door_unlock_method == "default" && !‪IS_TRUE(‪m_s_bundle.door_trigger_at_target) )
119  {
120  return;
121  }
122 
123  // Keys don't use a hint trigger.
124  //
125  if ( ‪m_s_bundle.door_unlock_method == "key" )
126  {
127  return;
128  }
129 
130  v_offset = ‪m_s_bundle.v_trigger_offset;
131  n_radius = ‪m_s_bundle.door_trigger_radius;
132 
133  v_pos = ‪calculate_offset_position( ‪m_e_door.origin, ‪m_e_door.angles, v_offset );
134 
135  // Its a look at trigger, so move the base of the trigger off the ground
136  v_pos = ( v_pos[0], v_pos[1], v_pos[2]+50 );
137 
138  e_trig = ‪spawn( "trigger_radius_use", v_pos, 0, n_radius, ‪m_n_trigger_height );
139  e_trig TriggerIgnoreTeam();
140 
141  e_trig SetVisibleToAll();
142  e_trig SetTeamForTrigger( "none" );
143  e_trig UseTriggerRequireLookAt();
144 
145  e_trig SetCursorHint( "HINT_NOICON" );
146 
147  ‪m_e_hint_trigger = e_trig;
148 
150  }
151 
152  function ‪lock()
153  {
154  self ‪flag::set( "locked" );
156  }
157 
158  function ‪unlock()
159  {
160  self ‪flag::clear( "locked" );
161  }
162 
163  function ‪delete_door()
164  {
165  ‪m_e_door delete();
166  ‪m_e_door = undefined;
167 
168  if( IsDefined(‪m_e_trigger) )
169  {
170  ‪m_e_trigger delete();
171  ‪m_e_trigger = undefined;
172  }
173  }
174 
175  function ‪open()
176  {
177  self ‪flag::set( "open" );
178  }
179 
180  function ‪close_internal()
181  {
182  self ‪flag::clear( "open" );
183  ‪set_script_flags( false );
184 
185  self ‪flag::set( "animating" );
186 
187  if( ‪IS_TRUE( ‪m_s_bundle.b_loop_sound ) )
188  {
189  ‪m_e_door playsound( ‪m_s_bundle.door_start_sound );
190  sndEnt = ‪spawn( "script_origin", ‪m_e_door.origin );
191  sndEnt linkto( ‪m_e_door );
192  sndEnt playloopsound( ‪m_s_bundle.door_loop_sound, 1 );
193  }
194  else if ( IsDefined(‪m_s_bundle.door_stop_sound) && ‪m_s_bundle.door_stop_sound != "" )
195  {
196  ‪m_e_door playsound( ‪m_s_bundle.door_stop_sound );
197  }
198 
199  // Close Door
200  if( ‪m_s_bundle.door_open_method == "slide" )
201  {
202  ‪m_e_door MoveTo( ‪m_v_close_pos, ‪m_s_bundle.door_open_time );
203  }
204  else if( ‪m_s_bundle.door_open_method == "swing" )
205  {
206  angle = ‪GetSwingAngle();
207  v_angle = ( ‪m_e_door.angles[0], ‪m_e_door.angles[1]-angle, ‪m_e_door.angles[2] );
208  ‪m_e_door RotateTo( v_angle, ‪m_s_bundle.door_open_time );
209  }
210  // TODO: Animated - Closing
211 
212  wait( ‪m_s_bundle.door_open_time );
213 
215  {
216  ‪m_e_door DisconnectPaths();
217  }
218 
219  if( ‪IS_TRUE( ‪m_s_bundle.b_loop_sound ) )
220  {
221  sndEnt delete();
222  ‪m_e_door playsound( ‪m_s_bundle.door_stop_sound );
223  }
224 
225  ‪flag::clear( "animating" );
226 
228  }
229 
230  function ‪close()
231  {
232  self ‪flag::clear( "open" );
233  }
234 
235  function ‪open_internal()
236  {
237  self ‪flag::set( "animating" );
238 
239  ‪m_e_door notify( "door_opening" );
240 
241  // Play the opening sound.
242  if ( IsDefined(‪m_s_bundle.door_start_sound) && ‪m_s_bundle.door_start_sound != "" )
243  {
244  ‪m_e_door playsound( ‪m_s_bundle.door_start_sound );
245  }
246 
247  // Play the looping door "open" sound.
248  if( ‪IS_TRUE( ‪m_s_bundle.b_loop_sound ) )
249  {
250  sndEnt = ‪spawn( "script_origin", ‪m_e_door.origin );
251  sndEnt linkto( ‪m_e_door );
252  sndEnt playloopsound( ‪m_s_bundle.door_loop_sound, 1 );
253  }
254 
255  if( ‪m_s_bundle.door_open_method == "slide" )
256  {
257  ‪m_e_door MoveTo( ‪m_v_open_pos, ‪m_s_bundle.door_open_time );
258  }
259  else if( ‪m_s_bundle.door_open_method == "swing" )
260  {
261  angle = ‪GetSwingAngle();
262  v_angle = ( ‪m_e_door.angles[0], ‪m_e_door.angles[1]+angle, ‪m_e_door.angles[2] );
263  ‪m_e_door RotateTo( v_angle, ‪m_s_bundle.door_open_time );
264  }
265 
267  {
268  ‪m_e_door ConnectPaths();
269  }
270 
271  wait( ‪m_s_bundle.door_open_time );
272 
273  if( ‪IS_TRUE( ‪m_s_bundle.b_loop_sound ) )
274  {
275  sndEnt delete();
276  }
277 
278  if ( IsDefined(‪m_s_bundle.door_stop_sound) && ‪m_s_bundle.door_stop_sound != "" )
279  {
280  ‪m_e_door playsound( ‪m_s_bundle.door_stop_sound );
281  }
282 
283  ‪flag::clear( "animating" );
284  ‪set_script_flags( true );
285 
287  }
288 
290  {
291  if ( !‪IS_TRUE( ‪m_s_bundle.door_use_trigger ) )
292  {
293  return;
294  }
295 
296  if ( self ‪flag::get("open") )
297  {
298  if ( !‪IS_TRUE(‪m_s_bundle.door_closes) )
299  {
300 // m_e_trigger SetHintString( "" );
301  }
302  else
303  {
304 // m_e_trigger SetHintString( "Hold ^3[{+activate}]^7 to close door" );
305  }
306  }
307  else
308  {
309  // TODO - Localize the string, &"HINT_DOOR"
310  if( IsDefined(‪m_s_bundle.door_open_message) && (‪m_s_bundle.door_open_message != "") )
311  {
312 // m_e_trigger SetHintString( m_s_bundle.door_open_message );
313  }
314  else if (‪IS_TRUE(‪m_s_bundle.door_use_hold))
315  {
316 // m_e_trigger SetHintString( "Hold ^3[{+activate}]^7 to hold door open" );
317  }
318  else if (‪m_s_bundle.door_unlock_method == "key")
319  {
320 // m_e_trigger SetHintString( "Hold ^3[{+activate}]^7 to open door [cost: 1 key]" );
321  }
322  else if( self ‪flag::get( "locked" ) )
323  {
324 // m_e_trigger SetHintString( &"SCRIPT_DOOR_LOCKED" );
325  }
326  else
327  {
328 // m_e_trigger SetHintString( "Hold ^3[{+activate}]^7 to open door" );
329  }
330  }
331  }
332 
333  function ‪run_lock_fx()
334  {
335  if ( !IsDefined(‪m_s_bundle.door_locked_fx) && !IsDefined(‪m_s_bundle.door_unlocked_fx) )
336  {
337  return;
338  }
339 
340  e_fx = undefined;
341  v_pos = ‪get_hack_pos();
342  v_angles = ‪get_hack_angles();
343 
344  while ( true )
345  {
346  self ‪flag::wait_till( "locked" );
347 
348  if ( isdefined( e_fx ) )
349  {
350  e_fx delete();
351  e_fx = undefined;
352  }
353 
354  if ( IsDefined(‪m_s_bundle.door_locked_fx) )
355  {
356  e_fx = ‪Spawn( "script_model", v_pos );
357  e_fx SetModel( "tag_origin" );
358  e_fx.angles = v_angles;
359  PlayFXOnTag( ‪m_s_bundle.door_locked_fx, e_fx, "tag_origin" );
360  }
361 
362  self ‪flag::wait_till_clear( "locked" );
363 
364  if ( isdefined( e_fx ) )
365  {
366  e_fx delete();
367  e_fx = undefined;
368  }
369 
370  if ( IsDefined(‪m_s_bundle.door_unlocked_fx) )
371  {
372  e_fx = ‪Spawn( "script_model", v_pos );
373  e_fx SetModel( "tag_origin" );
374  e_fx.angles = v_angles;
375  PlayFXOnTag( ‪m_s_bundle.door_unlocked_fx, e_fx, "tag_origin" );
376  }
377  }
378  }
379 
381  {
382  str_hint = "";
383  if ( ‪IS_TRUE( ‪m_s_bundle.door_trigger_at_target ) )
384  {
385  str_hint = "This door is controlled elsewhere";
386  }
387  else if (‪m_s_bundle.door_unlock_method == "hack")
388  {
389  str_hint = "This door is electronically locked";
390  }
391 
392  while ( true )
393  {
394  ‪m_e_hint_trigger SetHintString(str_hint);
395 
396  if ( ‪IS_TRUE( ‪m_s_bundle.door_trigger_at_target ) )
397  {
398  self ‪flag::wait_till( "open" );
399  }
400  else
401  {
402  self ‪flag::wait_till_clear( "locked" );
403  }
404 
405  ‪m_e_hint_trigger SetHintString("");
406 
407  if ( ‪IS_TRUE( ‪m_s_bundle.door_trigger_at_target ) )
408  {
409  self ‪flag::wait_till_clear( "open" );
410  }
411  else
412  {
413  self ‪flag::wait_till( "locked" );
414  }
415  }
416  }
417 
418  function ‪init_trigger( v_offset, n_radius )
419  {
420  v_pos = ‪calculate_offset_position( ‪m_e_door.origin, ‪m_e_door.angles, v_offset );
421 
422  // Its a look at trigger, so move the base of the trigger off the ground
423  v_pos = ( v_pos[0], v_pos[1], v_pos[2]+50 );
424 
425  if ( ‪IS_TRUE( ‪m_s_bundle.door_trigger_at_target ) )
426  {
427  ‪e_target = GetEnt( ‪m_str_target, "targetname" );
428  if ( IsDefined( ‪e_target ) )
429  {
430  v_pos = ‪e_target.origin;
431  }
432  }
433 
434  // Does the trigger need a USE prompt?
435  if( ‪IS_TRUE(‪m_s_bundle.door_use_trigger) )
436  {
437  ‪m_e_trigger = ‪spawn( "trigger_radius_use", v_pos, 0, n_radius, ‪m_n_trigger_height );
438  ‪m_e_trigger TriggerIgnoreTeam();
439 
440  ‪m_e_trigger SetVisibleToAll();
441  ‪m_e_trigger SetTeamForTrigger( "none" );
442  ‪m_e_trigger UseTriggerRequireLookAt();
443 
444  ‪m_e_trigger SetCursorHint( "HINT_NOICON" );
445  }
446  else
447  {
448  ‪m_e_trigger = ‪spawn( "trigger_radius", v_pos, 0, n_radius, ‪m_n_trigger_height );
449  }
450  }
451 
452  function ‪set_script_flags( b_set )
453  {
454  if ( IsDefined( ‪m_str_script_flag ) )
455  {
456  a_flags = StrTok(‪m_str_script_flag, ",");
457  foreach( str_flag in a_flags )
458  {
459  if ( b_set )
460  {
461  level ‪flag::set(str_flag);
462  }
463  else
464  {
465  level ‪flag::clear(str_flag);
466  }
467  }
468  }
469  }
470 
471  function ‪init_movement( n_slide_up, n_slide_amount )
472  {
473  if( ‪m_s_bundle.door_open_method == "slide" )
474  {
475  // Setup the open and close offsets
476  if( n_slide_up )
477  {
478  v_offset = ( 0, 0, n_slide_amount );
479  }
480  else
481  {
482  v_offset = ( n_slide_amount, 0, 0 );
483  }
484 
486  ‪m_v_close_pos = ‪m_e_door.origin;
487  }
488  }
489 
490  function ‪set_door_paths( n_door_connect_paths )
491  {
492  ‪m_n_door_connect_paths = n_door_connect_paths;
493  }
494 
495  // TODO (Slone): There's no reason to pass these variables in. The info is available via the bundle.
496  //
497  function ‪calculate_offset_position( v_origin, v_angles, v_offset )
498  {
499  v_pos = v_origin;
500 
501  if( v_offset[0] )
502  {
503  v_side = anglestoforward( v_angles ); // X Axis = Forward
504  v_pos = v_pos + (v_offset[0] * v_side);
505  }
506  if( v_offset[1] )
507  {
508  v_dir = anglestoright( v_angles );
509  v_pos = v_pos + (v_offset[1] * v_dir);
510  }
511  if( v_offset[2] )
512  {
513  v_up = anglestoup( v_angles );
514  v_pos = v_pos + (v_offset[2] * v_up);
515  }
516 
517  return( v_pos );
518  }
519 
520  // Override the doors swing angle
521  function ‪set_swing_angle( angle )
522  {
524  }
525 
526  function ‪GetSwingAngle()
527  {
528  if( IsDefined(‪m_override_swing_angle) )
529  {
531  }
532  else
533  {
534  angle = ‪m_s_bundle.door_swing_angle;
535  }
536  return( angle );
537  }
538 
539  function ‪SetDoorOpenDelay( delay_time )
540  {
541  ‪m_door_open_delay_time = delay_time;
542  }
543 }
544 
545 
549 
550 ‪REGISTER_SYSTEM( "doors", &‪__init__, undefined )
551 
552 function ‪__init__()
553 {
554  a_doors = ‪struct::get_array( "scriptbundle_doors", "classname" ); // "_doors" auto generates from the TYPE field in the bundle
555  foreach ( s_instance in a_doors )
556  {
557  c_door = s_instance ‪init();
558  if (isdefined(c_door) )
559  {
560  s_instance.c_door = c_door;
561  }
562  }
563 }
564 
565 
566 //*****************************************************************************
567 //*****************************************************************************
568 
569 // self = door bundle instance (The Script Script Instance, holds position, angles, targetname etc..)
570 function ‪init()
571 {
572  if( !IsDefined(self.angles) )
573  {
574  self.angles = (0, 0 ,0 );
575  }
576 
577  s_door_bundle = level.scriptbundles[ "doors" ][ self.scriptbundlename ];
578 
579  return ‪setup_door_scriptbundle( s_door_bundle, self );
580 }
581 
582 
583 //*****************************************************************************
584 //*****************************************************************************
585 
586 function ‪setup_door_scriptbundle( s_door_bundle, s_door_instance )
587 {
588  c_door = new ‪cDoor();
589 
590  c_door ‪flag::init( "locked", false );
591  c_door ‪flag::init( "open", false );
592  c_door ‪flag::init( "animating", false );
593 
594  c_door.m_s_bundle = s_door_bundle;
595  c_door.m_str_targetname = s_door_instance.targetname;
596  c_door.m_str_target = s_door_instance.target;
597  c_door.m_str_script_flag = s_door_instance.script_flag;
598 
599  //*************************
600  // Get the Door Bundle Data
601  //*************************
602 
603  if ( c_door.m_s_bundle.door_unlock_method == "key" )
604  {
605  if ( IsDefined( c_door.m_s_bundle.door_key_model ) )
606  {
607  level.door_key_model = c_door.m_s_bundle.door_key_model;
608  }
609 
610  if ( IsDefined( c_door.m_s_bundle.door_key_icon ) )
611  {
612  level.door_key_icon = c_door.m_s_bundle.door_key_icon;
613  }
614 
615  if ( IsDefined( c_door.m_s_bundle.door_key_fx ) )
616  {
617  level.door_key_fx = c_door.m_s_bundle.door_key_fx;
618  }
619  }
620 
621  if ( c_door.m_s_bundle.door_unlock_method == "hack" && !‪IS_TRUE(level.door_hack_precached) )
622  {
623  level.door_hack_precached = true;
624  }
625 
626  str_door_xmodel = c_door.m_s_bundle.model;
627 
628  // Trigger Offset
629  if( IsDefined(c_door.m_s_bundle.door_triggerOffsetX) )
630  {
631  n_xOffset = c_door.m_s_bundle.door_triggerOffsetX;
632  }
633  else
634  {
635  n_xOffset = 0;
636  }
637  if( IsDefined(c_door.m_s_bundle.door_triggerOffsetY) )
638  {
639  n_yOffset = c_door.m_s_bundle.door_triggerOffsetY;
640  }
641  else
642  {
643  n_yOffset = 0;
644  }
645  if( IsDefined(c_door.m_s_bundle.door_triggerOffsetZ) )
646  {
647  n_zOffset = c_door.m_s_bundle.door_triggerOffsetZ;
648  }
649  else
650  {
651  n_zOffset = 0;
652  }
653 
654  v_trigger_offset = ( n_xOffset, n_yOffset, n_zOffset );
655  c_door.m_s_bundle.v_trigger_offset = v_trigger_offset; // Store this for later use.
656 
657  n_trigger_radius = c_door.m_s_bundle.door_trigger_radius;
658  if( ‪IS_TRUE(c_door.m_s_bundle.door_slide_horizontal) )
659  {
660  n_slide_up = 0;
661  }
662  else
663  {
664  n_slide_up = 1;
665  }
666  n_open_time = c_door.m_s_bundle.door_open_time;
667  n_slide_amount = c_door.m_s_bundle.door_slide_open_units;
668 
669  if( !IsDefined(c_door.m_s_bundle.door_swing_angle) )
670  {
671  c_door.m_s_bundle.door_swing_angle = 0;
672  }
673 
674  if( ‪IS_TRUE(c_door.m_s_bundle.door_closes) )
675  {
676  n_door_closes = 1;
677  }
678  else
679  {
680  n_door_closes = 0;
681  }
682 
683  if( ‪IS_TRUE(c_door.m_s_bundle.door_connect_paths) )
684  {
685  n_door_connect_paths = 1;
686  }
687  else
688  {
689  n_door_connect_paths = 0;
690  }
691 
692  if ( ‪IS_TRUE( c_door.m_s_bundle.door_start_open ) )
693  {
694  c_door ‪flag::set( "open" );
695  }
696 
697  if ( IsDefined( c_door.m_str_script_flag ) )
698  {
699  a_flags = StrTok(c_door.m_str_script_flag, ",");
700  foreach( str_flag in a_flags )
701  {
702  level ‪flag::init( str_flag );
703  }
704  }
705 
706  // Setup the Door
707  [[ c_door ]]->init_xmodel( str_door_xmodel, n_door_connect_paths, s_door_instance.origin, s_door_instance.angles);
708 
709  // Setup the trigger - Just using radius triggers for now
710  [[ c_door ]]->init_trigger( v_trigger_offset, n_trigger_radius, c_door.m_s_bundle );
711 
712  // Initialize the trigger to give hints regarding how to open the door.
713  //
714  [[ c_door ]]->init_hint_trigger();
715 
716  // Initialize any fx associated with this door being (or not being) locked.
717  thread [[ c_door ]]->run_lock_fx();
718 
719  // Setup door movement
720  [[ c_door ]]->init_movement( n_slide_up, n_slide_amount );
721 
722  if ( !IsDefined(c_door.m_s_bundle.door_open_time) )
723  {
724  c_door.m_s_bundle.door_open_time = 0.4;
725  }
726 
727  [[ c_door ]]->set_door_paths( n_door_connect_paths );
728 
729  // Setup door sounds
730  c_door.m_s_bundle.b_loop_sound = IsDefined( c_door.m_s_bundle.door_loop_sound ) && c_door.m_s_bundle.door_loop_sound != "";
731 
732  // Door update routine
733  level thread ‪door_update( c_door );
734 
735  return c_door;
736 }
737 
738 
739 //*****************************************************************************
740 //*****************************************************************************
741 
742 function ‪door_open_update( c_door )
743 {
744  str_unlock_method = "default";
745  if ( IsDefined( c_door.m_s_bundle.door_unlock_method ) )
746  {
747  str_unlock_method = c_door.m_s_bundle.door_unlock_method;
748  }
749 
750  b_auto_close = (‪IS_TRUE(c_door.m_s_bundle.door_closes) && !‪IS_TRUE(c_door.m_s_bundle.door_use_trigger));
751  b_hold_open = ‪IS_TRUE(c_door.m_s_bundle.door_use_hold);
752  b_manual_close = ‪IS_TRUE(c_door.m_s_bundle.door_use_trigger) && ‪IS_TRUE(c_door.m_s_bundle.door_closes);
753 
754  // Wait for the player to hit the door trigger, unless it's already set to be open.
755  while ( true )
756  {
757  c_door.m_e_trigger waittill( "trigger", e_who );
758  c_door.m_e_trigger_player = e_who;
759 
760  if ( !(c_door ‪flag::get( "open" )) )
761  {
762  if ( !(c_door ‪flag::get( "locked" ) ))
763  {
764  if ( b_hold_open || b_auto_close )
765  {
766  [[c_door]]->open();
767 
768  if ( b_hold_open )
769  {
770  e_who ‪player_freeze_in_place( true );
771  e_who DisableWeapons();
772  e_who DisableOffhandWeapons();
773  }
774 
775  ‪door_wait_until_clear( c_door, e_who );
776  [[c_door]]->close();
777 
778  if ( b_hold_open )
779  {
781  c_door ‪flag::wait_till_clear( "animating" );
782  e_who ‪player_freeze_in_place( false );
783  e_who EnableWeapons();
784  e_who EnableOffhandWeapons();
785  }
786 
787  } else if ( str_unlock_method == "key" )
788  {
789  if ( e_who ‪player_has_key( "door" ) )
790  {
791  e_who ‪player_take_key( "door" );
792  [[c_door]]->open();
793  } else {
794  IPrintLnBold( "You need a key." );
795  }
796  } else {
797  [[c_door]]->open();
798  }
799  }
800  } else if ( b_manual_close )
801  {
802  [[c_door]]->close();
803  }
804  }
805 }
806 
807 function ‪door_update( c_door )
808 {
809  str_unlock_method = "default";
810  if ( IsDefined( c_door.m_s_bundle.door_unlock_method ) )
811  {
812  str_unlock_method = c_door.m_s_bundle.door_unlock_method;
813  }
814 
815  // "Key" doors aren't *really* unlocked.
816  if ( ‪IS_TRUE( c_door.m_s_bundle.door_locked ) && str_unlock_method != "key" )
817  {
818  c_door ‪flag::set( "locked" );
819 
820  if (IsDefined(c_door.m_str_targetname))
821  {
822  thread ‪door_update_lock_scripted( c_door );
823  }
824  }
825 
826  thread ‪door_open_update( c_door );
827 
828  [[c_door]]->update_use_message();
829 
830  while( 1 )
831  {
832  // Wait for the door to unlock.
833  //
834  if( c_door ‪flag::get( "locked" ) )
835  {
836  c_door ‪flag::wait_till_clear( "locked" );
837  }
838 
839  c_door ‪flag::wait_till( "open" );
840 
841  // Check for a delay opening the door
842  if( c_door.m_door_open_delay_time > 0 )
843  {
844  c_door.m_e_door notify( "door_waiting_to_open", c_door.m_e_trigger_player );
845  wait( c_door.m_door_open_delay_time );
846  }
847 
848  [[c_door]]->open_internal();
849 
850  c_door ‪flag::wait_till_clear( "open" );
851 
852  [[c_door]]->close_internal();
853 
854  // If the door stays open, tidyup and exit
855  if( !‪IS_TRUE(c_door.m_s_bundle.door_closes) )
856  {
857  break;
858  }
859 
861  }
862 
863  // Cleanup
864  c_door.m_e_trigger delete();
865  c_door.m_e_trigger = undefined;
866 }
867 
869 {
870  door_str = c_door.m_str_targetname;
871  c_door.m_e_trigger.targetname = (door_str + "_trig");
872 
873  while ( true )
874  {
875  c_door.m_e_trigger waittill( "unlocked" );
876  [[c_door]]->unlock();
877  }
878 }
879 
880 function ‪player_freeze_in_place( b_do_freeze )
881 {
882  if ( !b_do_freeze )
883  {
884  if ( IsDefined(self.freeze_origin) )
885  {
886  self Unlink();
887  self.freeze_origin Delete();
888  self.freeze_origin = undefined;
889  }
890  } else {
891  if ( !IsDefined(self.freeze_origin) )
892  {
893  self.freeze_origin = ‪Spawn( "script_model", self.origin );
894  self.freeze_origin SetModel( "tag_origin" );
895  self.freeze_origin.angles = self.angles;
896  self PlayerLinkToDelta(self.freeze_origin, "tag_origin", 1.0, 45.0, 45.0, 45.0, 45.0 );
897  }
898  }
899 }
900 
901 //*****************************************************************************
902 // Waits for a trigger to be clear of all ENTS for X time
903 //*****************************************************************************
904 
905 // self = trigger
906 function ‪trigger_wait_until_clear( c_door )
907 {
908  self endon( "death" );
909 
910  last_trigger_time = gettime();
911  self.ents_in_trigger = true;
912 
913  str_kill_trigger_notify = "trigger_now_clear";
914  self thread ‪trigger_check_for_ents_touching( str_kill_trigger_notify );
915 
916  while( 1 )
917  {
918  time = gettime();
919 
920  // If there are still ents in the trigger, reset the time counter
921  if( self.ents_in_trigger == true )
922  {
923  self.ents_in_trigger = false;
924  last_trigger_time = time;
925  }
926 
927  // Have we waited long enough for all ents to the
928  dt = ( time - last_trigger_time ) / 1000;
929  if( dt >= ‪DOOR_CLEARANCE_TIMER )
930  {
931  break;
932  }
933 
935  }
936 
937  self notify( str_kill_trigger_notify );
938 }
939 
940 // Waits until the user releases the X button, or until they leave the area.
941 //
942 // self == interaction trigger
943 //
944 function ‪door_wait_until_user_release( c_door, e_triggerer, str_kill_on_door_notify )
945 {
946  if ( IsDefined( str_kill_on_door_notify ) )
947  {
948  c_door endon( str_kill_on_door_notify );
949  }
950 
951  // Brief grace period.
952  wait 0.25;
953 
954  max_dist_sq = c_door.m_s_bundle.door_trigger_radius * c_door.m_s_bundle.door_trigger_radius;
955  b_pressed = true;
956  n_dist = 0.0;
957 
958  do {
960  b_pressed = e_triggerer UseButtonPressed();
961  n_dist = DistanceSquared(e_triggerer.origin, self.origin);
962  }
963  while ( b_pressed && n_dist < max_dist_sq );
964 }
965 
966 //*****************************************************************************
967 // Waits for door to be clear of all ENTS for X time
968 //*****************************************************************************
969 function ‪door_wait_until_clear( c_door, e_triggerer )
970 {
971  e_trigger = c_door.m_e_trigger;
972  e_temp_trigger = undefined;
973 
974  // If the trigger is not at the door, we need to create a trigger at the door
975  // for temporary purposes.
976  if ( ‪IS_TRUE( c_door.m_s_bundle.door_trigger_at_target ) )
977  {
978  e_door = c_door.m_e_door;
979  v_trigger_offset = c_door.m_s_bundle.v_trigger_offset;
980  v_pos = [[c_door]]->calculate_offset_position( e_door.origin, e_door.angles, v_trigger_offset );
981  n_radius = c_door.m_s_bundle.door_trigger_radius;
982  n_height = c_door.m_n_trigger_height;
983 
984  // Spawn a trigger
985  e_temp_trigger = ‪spawn( "trigger_radius", v_pos, 0, n_radius, n_height );
986  e_trigger = e_temp_trigger;
987  }
988 
989  // Player must hold down the button to keep the door open.
990  if ( IsPlayer( e_triggerer ) && ‪IS_TRUE(c_door.m_s_bundle.door_use_hold) )
991  {
992  c_door.m_e_trigger ‪door_wait_until_user_release( c_door, e_triggerer );
993  }
994 
995  // Wait for trigger to be clear of any entity
996  e_trigger ‪trigger_wait_until_clear( c_door );
997 
998  if ( IsDefined( e_temp_trigger ) )
999  {
1000  e_temp_trigger Delete();
1001  }
1002 }
1003 
1004 
1005 //*****************************************************************************
1006 // Waits for a trigger to be free of all ents
1007 //*****************************************************************************
1008 
1009 // self = trigger
1010 function ‪trigger_check_for_ents_touching( str_kill_trigger_notify )
1011 {
1012  self endon( "death" );
1013  self endon( str_kill_trigger_notify );
1014 
1015  while( 1 )
1016  {
1017  self waittill( "trigger", e_who );
1018  self.ents_in_trigger = true;
1019  }
1020 }
1021 
1022 
1023 //*****************************************************************************
1024 //*****************************************************************************
1025 
1026 // self = door trigger
1027 function ‪door_debug_line( v_origin )
1028 {
1029  self endon( "death" );
1030 
1031  while( 1 )
1032  {
1033  v_start = v_origin;
1034  v_end = v_start + ( 0, 0, 1000 );
1035  v_col = ( 0, 0, 1 );
1036 
1037 /#
1038  line( v_start, v_end, (0,0,1) );
1039 #/
1040 
1041  wait( 0.1 );
1042  }
1043 }
1044 
1045 function ‪player_has_key( str_key_type )
1046 {
1047  if ( !IsDefined( self.collectible_keys ) )
1048  {
1049  return false;
1050  }
1051 
1052  if ( !IsDefined( self.collectible_keys[str_key_type] ) )
1053  {
1054  return false;
1055  }
1056 
1057  return self.collectible_keys[str_key_type].num_keys > 0;
1058 }
1059 
1060 function ‪player_take_key( str_key_type )
1061 {
1062  if (!‪player_has_key( str_key_type ) )
1063  {
1064  return;
1065  }
1066 
1067  self.collectible_keys[str_key_type].num_keys--;
1068  if ( self.collectible_keys[str_key_type].num_keys <= 0 && IsDefined( self.collectible_keys[str_key_type].hudelem ) )
1069  {
1070  self.collectible_keys[str_key_type].hudelem Destroy();
1071  self.collectible_keys[str_key_type].hudelem = undefined;
1072  }
1073 }
1074 
1076 {
1077  self endon( "death" );
1078  while ( true )
1079  {
1080  self RotateYaw( 180, 3.0 );
1081  wait 2.5;
1082  }
1083 }
1084 
1085 function ‪key_process_timeout( n_timeout_sec, e_trigger, e_model )
1086 {
1087  e_trigger endon( "death" );
1088 
1089  const blinking_time = 5.0;
1090  if ( n_timeout_sec < blinking_time )
1091  {
1092  n_timeout_sec = blinking_time + 1.0;
1093  }
1094 
1095  wait n_timeout_sec - blinking_time;
1096 
1097  n_stepsize = 0.5;
1098  b_on = true;
1099  for ( f = 0.0; f < blinking_time; f += n_stepsize )
1100  {
1101  if ( b_on )
1102  {
1103  e_model Hide();
1104  } else {
1105  e_model Show();
1106  }
1107  b_on = !b_on;
1108  wait n_stepsize;
1109 
1110  // Blinking gets faster over time.
1111  if ( n_stepsize > 0.15 )
1112  {
1113  n_stepsize *= 0.9;
1114  }
1115  }
1116 
1117  level notify( "key_drop_timeout" );
1118 
1119  e_model Delete();
1120  e_trigger Delete();
1121 }
1122 
1123 function ‪give_ai_key_internal( n_timeout_sec, str_key_type )
1124 {
1125  v_pos = self.origin;
1126 
1127  e_model = ‪spawn("script_model", v_pos + (0,0,80) );
1128  e_model.angles = (10,0,10);
1129  e_model SetModel( level.door_key_model );
1130 
1131  if ( IsDefined( level.door_key_fx ) )
1132  {
1133  PlayFXOnTag( level.door_key_fx, e_model, "tag_origin" );
1134  }
1135 
1136  while( IsAlive( self ) )
1137  {
1138  e_model MoveTo( self.origin + (0,0,80), 0.2 );
1139  e_model RotateYaw( 30, 0.2 );
1140  wait 0.1;
1141  }
1142 
1143  e_model MoveZ( -60, 1.0 );
1144  wait 1.0;
1145 
1146  e_model thread ‪rotate_key_forever();
1147 
1148  e_trigger = ‪spawn( "trigger_radius", e_model.origin, 0, 25.0, 100.0 );
1149 
1150  if ( isdefined( n_timeout_sec ) )
1151  {
1152  level thread ‪key_process_timeout( n_timeout_sec, e_trigger, e_model );
1153  }
1154 
1155  e_trigger endon( "death" );
1156 
1157  while ( true )
1158  {
1159  e_trigger waittill( "trigger", e_who );
1160  if ( IsPlayer( e_who ) )
1161  {
1162  e_who ‪give_player_key( str_key_type );
1163  break;
1164  }
1165  }
1166 
1167  e_model Delete();
1168  e_trigger Delete();
1169 }
1170 
1171 function ‪give_ai_key( n_timeout_sec = undefined, str_key_type = "door" )
1172 {
1173  assert( isdefined( level.door_key_model ), "Attempting to give ai a key, but no key model is associated with any door in this level." );
1174 
1175  self thread ‪give_ai_key_internal( n_timeout_sec, str_key_type );
1176 }
1177 
1178 function ‪give_player_key( str_key_type = "door" )
1179 {
1180  assert( isdefined( level.door_key_icon ), "Attempting to give player a key, but no key icon is associated with any door in this level." );
1181 
1182  if ( !IsDefined( self.collectible_keys ) )
1183  {
1184  self.collectible_keys = [];
1185  }
1186 
1187  if ( !IsDefined( self.collectible_keys[str_key_type] ) )
1188  {
1189  self.collectible_keys[str_key_type] = SpawnStruct();
1190  self.collectible_keys[str_key_type].num_keys = 0;
1191  self.collectible_keys[str_key_type].type = str_key_type;
1192  }
1193 
1194  hudelem = self.collectible_keys[str_key_type].hudelem;
1195  if ( !isdefined( hudelem ) )
1196  {
1197  hudelem = newclienthudelem( self );
1198  }
1199 
1200  hudelem.alignX = "right";
1201  hudelem.alignY = "bottom";
1202  hudelem.horzAlign = "right";
1203  hudelem.vertAlign = "bottom";
1204  hudelem.hidewheninmenu = true;
1205  hudelem.hideWhenInDemo = true;
1206  hudelem.y = -75;
1207  hudelem.x = -25;
1208 
1209  hudelem SetShader( level.door_key_icon, 16, 16 );
1210 
1211  self.collectible_keys[str_key_type].hudelem = hudelem;
1212 
1213  self.collectible_keys[str_key_type].num_keys++;
1214 }
1215 
1216 function ‪unlock_all( b_do_open = true )
1217 {
1218  a_s_inst_list = ‪struct::get_array( "scriptbundle_doors", "classname" );
1219  foreach( s_inst in a_s_inst_list )
1220  {
1221  c_door = s_inst.c_door;
1222  if ( isdefined( c_door ) )
1223  {
1224  [[c_door]]->unlock();
1225 
1226  if ( b_do_open )
1227  {
1228  [[c_door]]->open();
1229  }
1230  }
1231  }
1232 }
1233 
1234 function ‪unlock( str_name, str_name_type = "targetname", b_do_open = true )
1235 {
1236  a_s_inst_list = ‪struct::get_array( str_name, str_name_type );
1237  foreach( s_inst in a_s_inst_list )
1238  {
1239  if ( isdefined( s_inst.c_door ) )
1240  {
1241  [[s_inst.c_door]]->unlock();
1242 
1243  if ( b_do_open )
1244  {
1245  [[s_inst.c_door]]->open();
1246  }
1247  }
1248  }
1249 }
‪cDoor::get_hack_angles
‪function get_hack_angles()
Definition: doors_shared.gsc:98
‪cDoor::m_e_trigger
‪var m_e_trigger
Definition: doors_shared.gsc:23
‪DOOR_CLEARANCE_TIMER
‪#define DOOR_CLEARANCE_TIMER
Definition: doors_shared.gsc:12
‪__init__
‪class cDoor __init__()
Definition: doors_shared.gsc:552
‪cDoor::run_lock_fx
‪function run_lock_fx()
Definition: doors_shared.gsc:333
‪cDoor::init_trigger
‪function init_trigger(v_offset, n_radius)
Definition: doors_shared.gsc:418
‪cDoor::m_b_hacking
‪var m_b_hacking
Definition: doors_shared.gsc:28
‪give_ai_key_internal
‪function give_ai_key_internal(n_timeout_sec, str_key_type)
Definition: doors_shared.gsc:1123
‪cDoor::calculate_offset_position
‪function calculate_offset_position(v_origin, v_angles, v_offset)
Definition: doors_shared.gsc:497
‪cDoor::m_v_open_pos
‪var m_v_open_pos
Definition: doors_shared.gsc:32
‪cDoor::get_hack_pos
‪function get_hack_pos()
Definition: doors_shared.gsc:79
‪e_target
‪var e_target
Definition: traps_shared.gsc:2029
‪cDoor::destructor
‪destructor()
Definition: doors_shared.gsc:52
‪cDoor::update_use_message
‪function update_use_message()
Definition: doors_shared.gsc:289
‪cDoor::m_n_door_connect_paths
‪var m_n_door_connect_paths
Definition: doors_shared.gsc:35
‪cDoor::m_str_script_flag
‪var m_str_script_flag
Definition: doors_shared.gsc:19
‪give_player_key
‪function give_player_key(str_key_type="door")
Definition: doors_shared.gsc:1178
‪cDoor::m_s_bundle
‪var m_s_bundle
Definition: doors_shared.gsc:16
‪key_process_timeout
‪function key_process_timeout(n_timeout_sec, e_trigger, e_model)
Definition: doors_shared.gsc:1085
‪init
‪function init()
Definition: doors_shared.gsc:570
‪clear
‪function clear(str_flag)
Definition: flag_shared.csc:130
‪connect_paths
‪function connect_paths()
Definition: vehicle_shared.gsc:3592
‪cDoor::m_override_swing_angle
‪var m_override_swing_angle
Definition: doors_shared.gsc:40
‪cDoor::m_b_is_open
‪var m_b_is_open
Definition: doors_shared.gsc:37
‪get_array
‪function get_array(kvp_value, kvp_key="targetname")
Definition: struct.csc:34
‪cDoor::init_xmodel
‪function init_xmodel(str_xmodel, connect_paths, v_origin, v_angles)
Definition: doors_shared.gsc:60
‪cDoor::m_str_target
‪var m_str_target
Definition: doors_shared.gsc:18
‪door_debug_line
‪function door_debug_line(v_origin)
Definition: doors_shared.gsc:1027
‪cDoor::delete_door
‪function delete_door()
Definition: doors_shared.gsc:163
‪cDoor::close
‪function close()
Definition: doors_shared.gsc:230
‪cDoor::init_hint_trigger
‪function init_hint_trigger()
Definition: doors_shared.gsc:114
‪cDoor
Definition: doors_shared.gsc:14
‪cDoor::unlock
‪function unlock()
Definition: doors_shared.gsc:158
‪cDoor::open_internal
‪function open_internal()
Definition: doors_shared.gsc:235
‪cDoor::set_swing_angle
‪function set_swing_angle(angle)
Definition: doors_shared.gsc:521
‪player_freeze_in_place
‪function player_freeze_in_place(b_do_freeze)
Definition: doors_shared.gsc:880
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪get
‪function get(kvp_value, kvp_key="targetname")
Definition: struct.csc:13
‪player_has_key
‪function player_has_key(str_key_type)
Definition: doors_shared.gsc:1045
‪cDoor::SetDoorOpenDelay
‪function SetDoorOpenDelay(delay_time)
Definition: doors_shared.gsc:539
‪door_wait_until_user_release
‪function door_wait_until_user_release(c_door, e_triggerer, str_kill_on_door_notify)
Definition: doors_shared.gsc:944
‪cDoor::constructor
‪constructor()
Definition: doors_shared.gsc:44
‪cDoor::m_e_trigger_player
‪var m_e_trigger_player
Definition: doors_shared.gsc:24
‪setup_door_scriptbundle
‪function setup_door_scriptbundle(s_door_bundle, s_door_instance)
Definition: doors_shared.gsc:586
‪cDoor::m_e_door
‪var m_e_door
Definition: doors_shared.gsc:21
‪door_wait_until_clear
‪function door_wait_until_clear(c_door, e_triggerer)
Definition: doors_shared.gsc:969
‪rotate_key_forever
‪function rotate_key_forever()
Definition: doors_shared.gsc:1075
‪door_update
‪function door_update(c_door)
Definition: doors_shared.gsc:807
‪cDoor::process_hint_trigger_message
‪function process_hint_trigger_message()
Definition: doors_shared.gsc:380
‪door_open_update
‪function door_open_update(c_door)
Definition: doors_shared.gsc:742
‪give_ai_key
‪function give_ai_key(n_timeout_sec=undefined, str_key_type="door")
Definition: doors_shared.gsc:1171
‪trigger_wait_until_clear
‪function trigger_wait_until_clear(c_door)
Definition: doors_shared.gsc:906
‪cDoor::open
‪function open()
Definition: doors_shared.gsc:175
‪cDoor::m_n_trigger_height
‪var m_n_trigger_height
Definition: doors_shared.gsc:25
‪cDoor::set_door_paths
‪function set_door_paths(n_door_connect_paths)
Definition: doors_shared.gsc:490
‪wait_till
‪function wait_till(str_flag)
Definition: flag_shared.csc:189
‪cDoor::m_v_close_pos
‪var m_v_close_pos
Definition: doors_shared.gsc:33
‪REGISTER_SYSTEM
‪#define REGISTER_SYSTEM(__sys, __func_init_preload, __reqs)
Definition: shared.gsh:204
‪Spawn
‪function Spawn(parent, onDeathCallback)
Definition: _flak_drone.gsc:427
‪cDoor::m_str_targetname
‪var m_str_targetname
Definition: doors_shared.gsc:17
‪cDoor::init_movement
‪function init_movement(n_slide_up, n_slide_amount)
Definition: doors_shared.gsc:471
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪cDoor::GetSwingAngle
‪function GetSwingAngle()
Definition: doors_shared.gsc:526
‪unlock_all
‪function unlock_all(b_do_open=true)
Definition: doors_shared.gsc:1216
‪cDoor::m_n_hack_pct
‪var m_n_hack_pct
Definition: doors_shared.gsc:27
‪unlock
‪function unlock()
Definition: doors_shared.gsc:144
‪cDoor::m_e_hint_trigger
‪var m_e_hint_trigger
Definition: doors_shared.gsc:30
‪wait_till_clear
‪function wait_till_clear(str_flag)
Definition: flag_shared.csc:248
‪cDoor::lock
‪function lock()
Definition: doors_shared.gsc:152
‪player_take_key
‪function player_take_key(str_key_type)
Definition: doors_shared.gsc:1060
‪cDoor::m_door_open_delay_time
‪var m_door_open_delay_time
Definition: doors_shared.gsc:42
‪trigger_check_for_ents_touching
‪function trigger_check_for_ents_touching(str_kill_trigger_notify)
Definition: doors_shared.gsc:1010
‪cDoor::close_internal
‪function close_internal()
Definition: doors_shared.gsc:180
‪cDoor::set_script_flags
‪function set_script_flags(b_set)
Definition: doors_shared.gsc:452
‪door_update_lock_scripted
‪function door_update_lock_scripted(c_door)
Definition: doors_shared.gsc:868
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265