‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_zm_unitrigger.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\system_shared;
4 
5 #insert scripts\shared\shared.gsh;
6 #insert scripts\zm\_zm_utility.gsh;// for the "is_drinking" check for unitriggers.
7 
8 #using scripts\zm\_zm_utility;
9 #using scripts\zm\_zm_zonemgr;
10 
11 /*
12  * _zm_unitgrigger.gsc.
13  * User: dlaufer
14  * Date: 5/9/2012
15  * Time: 11:45 AM
16  *
17  * To change this template use Tools | Options | Coding | Edit Standard Headers.
18  */
19 
20 #define PLAYER_RADIUS 15.0
21 #define PLAYER_STAND_MAX_Z 70.0
22 #define UNITRIGGER_MAX_RADIUS (128 - PLAYER_RADIUS)
23 
24 #namespace zm_unitrigger;
25 
26 ‪REGISTER_SYSTEM( "zm_unitrigger", &‪__init__, undefined )
27 
28 function ‪__init__()
29 {
30  level._unitriggers = SpawnStruct();
31  level._unitriggers._deferredInitList = []; // calls to register static triggers end up stashed here, if they're made before the zones are set up.
32  level._unitriggers.trigger_pool = []; // indexed by player entity number - 1 trigger per player is the goal here.
33  level._unitriggers.trigger_stubs = []; // all registered stubs.
34  level._unitriggers.dynamic_stubs = []; // stubs that aren't associated with zones.
35  level._unitriggers.system_trigger_funcs = [];
36  level._unitriggers.largest_radius = 64; // radius of the largest unitrigger in the level
37 
38  stubs_keys = ‪array("unitrigger_radius", "unitrigger_radius_use", "unitrigger_box", "unitrigger_box_use");
39 
40  stubs = [];
41 
42  for(i = 0; i < stubs_keys.size; i ++)
43  {
44  stubs = ArrayCombine(stubs, ‪struct::get_array(stubs_keys[i], "script_unitrigger_type"), true, false);
45  }
46 
47  for(i = 0; i < stubs.size; i ++)
48  {
49  ‪register_unitrigger(stubs[i]);
50  }
51 }
52 
53 function ‪register_unitrigger_system_func(system, trigger_func)
54 {
55  level._unitriggers.system_trigger_funcs[system] = trigger_func;
56 }
57 
58 function ‪unitrigger_force_per_player_triggers(unitrigger_stub, opt_on_off)
59 {
60  if (!isdefined(opt_on_off))
61  opt_on_off = 1;
62  unitrigger_stub.trigger_per_player = opt_on_off;
63 }
64 
65 function ‪unitrigger_trigger( player )
66 {
67  if(self.trigger_per_player)
68  {
69  return self.playertrigger[player GetEntityNumber()];
70  }
71  else
72  {
73  return self.trigger;
74  }
75 }
76 
78 {
79  if (isdefined(self.originFunc))
80  origin = self [[self.originFunc]]();
81  else
82  origin = self.origin;
83  return origin;
84 }
85 
86 function ‪register_unitrigger_internal(unitrigger_stub, trigger_func)
87 {
88  if(!isdefined(unitrigger_stub.script_unitrigger_type))
89  {
90 
91  return;
92  }
93  if(isdefined(trigger_func))
94  {
95  unitrigger_stub.trigger_func = trigger_func;
96  }
97  else if(isdefined(unitrigger_stub.unitrigger_system) && isdefined(level._unitriggers.system_trigger_funcs[unitrigger_stub.unitrigger_system]))
98  {
99  unitrigger_stub.trigger_func = level._unitriggers.system_trigger_funcs[unitrigger_stub.unitrigger_system];
100  }
101 
102  // Make sure defaults are in place for poorly setup stubs.
103 
104  switch(unitrigger_stub.script_unitrigger_type)
105  {
106  case "unitrigger_radius":
107  case "unitrigger_radius_use":
108  if(!isdefined(unitrigger_stub.radius))
109  {
110  unitrigger_stub.radius = 32;
111  }
112 
113  if(!isdefined(unitrigger_stub.script_height))
114  {
115  unitrigger_stub.script_height = 64;
116  }
117  unitrigger_stub.test_radius_sq = ( unitrigger_stub.radius + ‪PLAYER_RADIUS ) * ( unitrigger_stub.radius + ‪PLAYER_RADIUS );
118  break;
119  case "unitrigger_box":
120  case "unitrigger_box_use":
121  if(!isdefined(unitrigger_stub.script_width))
122  {
123  unitrigger_stub.script_width = 64;
124  }
125 
126  if(!isdefined(unitrigger_stub.script_height))
127  {
128  unitrigger_stub.script_height = 64;
129  }
130 
131  if(!isdefined(unitrigger_stub.script_length))
132  {
133  unitrigger_stub.script_length = 64;
134  }
135  box_radius = Length( (unitrigger_stub.script_width/2,unitrigger_stub.script_length/2,unitrigger_stub.script_height/2) );
136  if(!isdefined(unitrigger_stub.radius) || unitrigger_stub.radius<box_radius)
137  {
138  unitrigger_stub.radius = box_radius;
139  }
140  unitrigger_stub.test_radius_sq = ( box_radius + ‪PLAYER_RADIUS ) * ( box_radius + ‪PLAYER_RADIUS );
141  break;
142  default:
143 
144  return;
145 
146  }
147 
148  if ( unitrigger_stub.radius > level._unitriggers.largest_radius )
149  {
150  level._unitriggers.largest_radius = min(‪UNITRIGGER_MAX_RADIUS, unitrigger_stub.radius );
151  if ( IsDefined(level.fixed_max_player_use_radius) )
152  {
153  if ( level.fixed_max_player_use_radius > GetDVarFloat( "player_useRadius_zm" ) )
154  SetDvar( "player_useRadius_zm", level.fixed_max_player_use_radius );
155  }
156  else if ( level._unitriggers.largest_radius > GetDVarFloat( "player_useRadius_zm" ) )
157  {
158  SetDvar( "player_useRadius_zm", level._unitriggers.largest_radius );
159  }
160  }
161 
162  level._unitriggers.trigger_stubs[level._unitriggers.trigger_stubs.size] = unitrigger_stub;
163  unitrigger_stub.registered = 1;
164 }
165 
166 function ‪register_unitrigger(unitrigger_stub, trigger_func)
167 {
168  ‪register_unitrigger_internal(unitrigger_stub, trigger_func);
169 
170  level._unitriggers.dynamic_stubs[level._unitriggers.dynamic_stubs.size] = unitrigger_stub;
171 }
172 
173 function ‪unregister_unitrigger(unitrigger_stub)
174 {
175  // thread this off to avoid leaving orphaned triggers
176  thread ‪unregister_unitrigger_internal(unitrigger_stub);
177 }
178 
179 function ‪unregister_unitrigger_internal(unitrigger_stub)
180 {
181  if (!isdefined( unitrigger_stub ))
182  return;
183  unitrigger_stub.registered = 0;
184  if(‪IS_TRUE(unitrigger_stub.trigger_per_player))
185  {
186  if(isdefined(unitrigger_stub.playertrigger) && (unitrigger_stub.playertrigger.size > 0))
187  {
188  keys = GetArrayKeys(unitrigger_stub.playertrigger);
189  foreach( key in keys )
190  {
191  trigger = unitrigger_stub.playertrigger[key];
192  trigger notify("kill_trigger");
193  if (isdefined(trigger))
194  trigger delete();
195  }
196  unitrigger_stub.playertrigger = [];
197  }
198  }
199  else
200  {
201  if ( isdefined(unitrigger_stub.trigger) )
202  {
203  trigger = unitrigger_stub.trigger;
204  trigger notify("kill_trigger");
205  trigger.stub.trigger = undefined;
206  trigger delete();
207  }
208  }
209  if (isdefined( unitrigger_stub.in_zone ))
210  {
211  ArrayRemoveValue( level.zones[unitrigger_stub.in_zone].unitrigger_stubs, unitrigger_stub );
212  unitrigger_stub.in_zone = undefined;
213  }
214 
215  ArrayRemoveValue( level._unitriggers.trigger_stubs, unitrigger_stub );
216  ArrayRemoveValue( level._unitriggers.dynamic_stubs, unitrigger_stub );
217 }
218 
220 {
221  self.last_used_time = 0;
222 
223  while(1)
224  {
225  wait(1);
226 
227  if((GetTime() - self.last_used_time) > 1000) // Not used in a second
228  {
229  self delete();
230  level._unitriggers.contact_ent = undefined;
231  return;
232  }
233  }
234 }
235 
236 function ‪register_static_unitrigger(unitrigger_stub, trigger_func, recalculate_zone)
237 {
238  if(level.zones.size == 0)
239  {
240  unitrigger_stub.trigger_func = trigger_func;
241  level._unitriggers._deferredInitList[level._unitriggers._deferredInitList.size] = unitrigger_stub;
242  return;
243  }
244 
245  if(!isdefined(level._unitriggers.contact_ent)) // Optimisation to prevent server thread badness while lots of static triggers are being registered at the same time.
246  {
247  level._unitriggers.contact_ent = ‪spawn("script_origin", (0,0,0));
248  level._unitriggers.contact_ent thread ‪delay_delete_contact_ent(); // contact ent will get deleted and set to undefined after 1 second of inactivity.
249  }
250 
251  ‪register_unitrigger_internal(unitrigger_stub, trigger_func);
252 
253  if(!isdefined(level._no_static_unitriggers))
254  {
255 
256  level._unitriggers.contact_ent.last_used_time = GetTime();
257  level._unitriggers.contact_ent.origin = unitrigger_stub.origin;
258 
259  if(isdefined(unitrigger_stub.in_zone) && !isdefined(recalculate_zone))
260  {
261  level.zones[unitrigger_stub.in_zone].unitrigger_stubs[level.zones[unitrigger_stub.in_zone].unitrigger_stubs.size] = unitrigger_stub;
262  return;
263  }
264 
265  keys = GetArrayKeys(level.zones);
266 
267  for(i = 0; i < keys.size; i ++)
268  {
269  if(level._unitriggers.contact_ent ‪zm_zonemgr::entity_in_zone(keys[i], true))
270  {
271  if(!isdefined(level.zones[keys[i]].unitrigger_stubs))
272  {
273  level.zones[keys[i]].unitrigger_stubs = [];
274  }
275 
276  level.zones[keys[i]].unitrigger_stubs[level.zones[keys[i]].unitrigger_stubs.size] = unitrigger_stub;
277  unitrigger_stub.in_zone = keys[i];
278  return;
279  }
280  }
281  }
282 
283  level._unitriggers.dynamic_stubs[level._unitriggers.dynamic_stubs.size] = unitrigger_stub; // stub wasn't in a zone - register it as dynamic.
284  unitrigger_stub.registered = 1;
285 }
286 
287 function ‪register_dyn_unitrigger(unitrigger_stub, trigger_func, recalculate_zone)
288 {
289  if(level.zones.size == 0)
290  {
291  unitrigger_stub.trigger_func = trigger_func;
292  level._unitriggers._deferredInitList[level._unitriggers._deferredInitList.size] = unitrigger_stub;
293  return;
294  }
295 
296  if(!isdefined(level._unitriggers.contact_ent)) // Optimisation to prevent server thread badness while lots of static triggers are being registered at the same time.
297  {
298  level._unitriggers.contact_ent = ‪spawn("script_origin", (0,0,0));
299  level._unitriggers.contact_ent thread ‪delay_delete_contact_ent(); // contact ent will get deleted and set to undefined after 1 second of inactivity.
300  }
301 
302  ‪register_unitrigger_internal(unitrigger_stub, trigger_func);
303 
304  level._unitriggers.dynamic_stubs[level._unitriggers.dynamic_stubs.size] = unitrigger_stub; // stub wasn't in a zone - register it as dynamic.
305  unitrigger_stub.registered = 1;
306 }
307 
308 function ‪reregister_unitrigger_as_dynamic(unitrigger_stub)
309 {
310  ‪unregister_unitrigger_internal(unitrigger_stub);
311  ‪register_unitrigger(unitrigger_stub, unitrigger_stub.trigger_func );
312 }
313 
314 
316 {
317 }
318 
319 function ‪cleanup_trigger(trigger,player)
320 {
321  trigger notify("kill_trigger");
322  if(‪IS_TRUE(trigger.stub.trigger_per_player))
323  {
324  trigger.stub.playerTrigger[player GetEntityNumber()] = undefined;
325  }
326  else
327  {
328  trigger.stub.trigger = undefined;
329  }
330 
331  trigger delete();
332  level._unitriggers.trigger_pool[player GetEntityNumber()] = undefined;
333 }
334 
335 function ‪assess_and_apply_visibility( trigger, stub, player, default_keep )
336 {
337  if (!isdefined(trigger) || !isdefined(stub))
338  return false;
339  keep_thread = default_keep;
340  if (!isdefined(stub.prompt_and_visibility_func) ||
341  trigger [[stub.prompt_and_visibility_func]]( player ) )
342  {
343  keep_thread = true;
344  if (!‪IS_TRUE(trigger.thread_running))
345  trigger thread ‪trigger_thread(trigger.stub.trigger_func);
346  trigger.thread_running = true;
347  if (IsDefined(trigger.reassess_time) && trigger.reassess_time <= 0.0)
348  trigger.reassess_time = undefined;
349  }
350  else
351  {
352  if (‪IS_TRUE(trigger.thread_running))
353  keep_thread = false;
354  trigger.thread_running = false;
355  // check again in 1 second
356  if ( IsDefined(stub.inactive_reassess_time) )
357  trigger.reassess_time = stub.inactive_reassess_time;
358  else
359  trigger.reassess_time = 1.0;
360  }
361  return keep_thread;
362 }
363 
364 function ‪main()
365 {
366  level thread ‪debug_unitriggers();
367 
368  if(level._unitriggers._deferredInitList.size)
369  {
370  for(i = 0; i < level._unitriggers._deferredInitList.size; i ++)
371  {
372  ‪register_static_unitrigger(level._unitriggers._deferredInitList[i], level._unitriggers._deferredInitList[i].trigger_func);
373  }
374 
375  for(i = 0; i < level._unitriggers._deferredInitList.size; i ++)
376  {
377  level._unitriggers._deferredInitList[i] = undefined;
378  }
379 
380  level._unitriggers._deferredInitList = undefined;
381  }
382 
383  valid_range = level._unitriggers.largest_radius + ‪PLAYER_RADIUS;
384  valid_range_sq = valid_range * valid_range;
385 
386  while( !isdefined( level.active_zone_names ) )
387  {
388  wait( 0.1 );
389  }
390 
391  while(1)
392  {
393  waited = false;
394  active_zone_names = level.active_zone_names;//zm_zonemgr::get_active_zone_names();
395 
396  candidate_list = [];
397 
398  for(j = 0; j < active_zone_names.size; j ++)
399  {
400  if(isdefined(level.zones[active_zone_names[j]].unitrigger_stubs))
401  {
402  candidate_list = ArrayCombine(candidate_list, level.zones[active_zone_names[j]].unitrigger_stubs, true, false);
403  }
404  }
405 
406  candidate_list = ArrayCombine(candidate_list, level._unitriggers.dynamic_stubs, true, false);
407 
408  players = GetPlayers();
409 
410  for(i = 0; i < players.size; i ++)
411  {
412  player = players[i];
413 
414  if(!isdefined(player))
415  {
416  continue;
417  }
418 
419  player_origin = player.origin + (0,0,‪PLAYER_STAND_MAX_Z/2);
420 
421  trigger = level._unitriggers.trigger_pool[player GetEntityNumber()];
422 
423  old_trigger = undefined;
424  closest = [];
425 
426  if(isdefined(trigger))
427  {
428  dst = valid_range_sq;
429  origin = trigger ‪unitrigger_origin();
430 
431  dst = trigger.stub.test_radius_sq;
432  time_to_ressess = false;
433  trigger_still_valid = false;
434 
435  if( Distance2DSquared(player_origin, origin) < dst) // Currently enabled trigger is still the most healthy, leave it alone.
436  {
437  if (isdefined(trigger.reassess_time))
438  {
439  trigger.reassess_time -= 0.05;
440  if (trigger.reassess_time > 0.0)
441  continue;
442  time_to_ressess = true;
443  }
444  /*
445  else if (player zm_utility::is_player_looking_at(trigger.stub.origin, 0.9, false)) //Do not reassess if player is looking at the trigger
446  {
447  if (assess_and_apply_visibility( trigger, trigger.stub, player, true ))
448  continue;
449  }
450  */
451  trigger_still_valid = true;
452  }
453 
454  // Gets all the unitriggers in range (roughly)
455  closest = ‪get_closest_unitriggers( player_origin, candidate_list, valid_range );
456 
457  // no need to reasses if there is only one nearby trigger - we do need to reassess the prompt and visibility though
458  if ( IsDefined(trigger) && time_to_ressess && (closest.size < 2 || ‪IS_TRUE(trigger.thread_running) ) )
459  {
460  if (‪assess_and_apply_visibility( trigger, trigger.stub, player, true ))
461  continue;
462  }
463 
464  if (trigger_still_valid && closest.size < 2)
465  {
466  if (‪assess_and_apply_visibility( trigger, trigger.stub, player, true ))
467  continue;
468  }
469 
470  /*
471  // We've moved away from this trigger or it's time to reassess - throw it out.
472  if (IsDefined(trigger))
473  cleanup_trigger(trigger,player);
474  */
475 
476  //Old trigger is still valid. Do not release the old trigger untill we are sure we don't need it.
477  if (trigger_still_valid)
478  {
479  old_trigger = trigger;
480  trigger = undefined;
481  level._unitriggers.trigger_pool[player GetEntityNumber()] = undefined;
482  }
483  else if (IsDefined(trigger))
484  ‪cleanup_trigger(trigger,player);
485  }
486  else
487  {
488  // Gets all the unitriggers in range (roughly)
489  closest = ‪get_closest_unitriggers( player_origin, candidate_list, valid_range );
490  }
491 
492  index = 0;
493 
494  first_usable=undefined;
495  first_visible=undefined;
496  trigger_found = false;
497 
498  // One thing I don't like about this is that if you have two unitriggers in range and they are both unusable, but visible, it will tend to show the far one
499  while (index < closest.size)
500  {
501  if( !‪zm_utility::is_player_valid( player ) && !(‪IS_TRUE( closest[index].ignore_player_valid )) )
502  {
503  index++;
504  continue;
505  }
506 
507  if(!‪IS_TRUE(closest[index].registered))
508  {
509  index++;
510  continue;
511  }
512 
513  trigger = ‪check_and_build_trigger_from_unitrigger_stub(closest[index], player);
514 
515  if (isdefined(trigger))
516  {
517 
518  trigger.parent_player = player;
519 
520  if ( ‪assess_and_apply_visibility( trigger, closest[index], player, false ) )
521  {
522  //If player is looking at the trigger and it's usable, it takes the highest priority
523  if (player ‪zm_utility::is_player_looking_at(closest[index].origin, 0.9, false))
524  {
525  if (!‪is_same_trigger(old_trigger, trigger) && isdefined(old_trigger))
526  {
527  ‪cleanup_trigger(old_trigger, player);
528  }
529  level._unitriggers.trigger_pool[player GetEntityNumber()] = trigger;
530  trigger_found = true;
531  break;
532  }
533 
534  //save the closest usable trigger
535  if (!isdefined(first_usable))
536  {
537  first_usable = index;
538  }
539  }
540  //save the closest visible trigger
541  if (!isdefined(first_visible))
542  {
543  first_visible = index;
544  }
545 
546 
547  if (isdefined(trigger))
548  {
549  if (‪is_same_trigger(old_trigger, trigger))
550  level._unitriggers.trigger_pool[player GetEntityNumber()] = undefined;
551  else ‪cleanup_trigger(trigger,player);
552  }
553  last_trigger = trigger;
554  }
555  index++;
556 
557  waited = true;
559  }
560 
561  if (!IsDefined(player))
562  continue;
563  if (trigger_found)
564  continue;
565  //Player wasn't looking at any of the triggers
566  //First usable trigger has higher priority then the first visible trigger
567  if (isdefined(first_usable))
568  index = first_usable;
569  else if (isdefined(first_visible))
570  index = first_visible;
571 
572  trigger = ‪check_and_build_trigger_from_unitrigger_stub(closest[index], player);
573  if (isdefined(trigger))
574  {
575  trigger.parent_player = player;
576  level._unitriggers.trigger_pool[player GetEntityNumber()] = trigger;
577  if (‪is_same_trigger(old_trigger, trigger))
578  continue;
579 
580  if (isdefined(old_trigger))
581  {
582  ‪cleanup_trigger(old_trigger, player);
583  }
584 
585  //Rebuild the trigger and make it running
586  if (isdefined(trigger))
587  {
588  ‪assess_and_apply_visibility( trigger, trigger.stub, player, false );
589  }
590  }
591  }
592  if (!waited)
593  {
595  }
596  }
597 }
598 
600 {
601  if(!isdefined(self.prompt_and_visibility_func))
602  {
603  return;
604  }
605 
606  if(‪IS_TRUE(self.trigger_per_player))
607  {
608  if(!isdefined(self.playertrigger))
609  {
610  return;
611  }
612 
613  players = GetPlayers();
614 
615  for(i = 0; i < players.size; i ++)
616  {
617  if(isdefined(self.playertrigger[players[i] GetEntityNumber()]))
618  {
619  self.playertrigger[players[i] GetEntityNumber()] [[self.prompt_and_visibility_func]](players[i]);
620  }
621  }
622  }
623  else
624  {
625  if(isdefined(self.trigger))
626  {
627  self.trigger [[self.prompt_and_visibility_func]](GetPlayers()[0]);
628  }
629  }
630 }
631 
632 function ‪is_same_trigger(old_trigger, trigger)
633 {
634  return isdefined(old_trigger) && old_trigger == trigger && trigger.parent_player == old_trigger.parent_player;
635 }
636 
638 {
639  if (!isdefined(stub))
640  return undefined;
641 
642  if(‪IS_TRUE(stub.trigger_per_player))
643  {
644  if (!isdefined(stub.playertrigger))
645  stub.playertrigger = [];
646  if(!isdefined(stub.playertrigger[player GetEntityNumber()]))
647  {
648  trigger = ‪build_trigger_from_unitrigger_stub(stub,player);
649  level._unitriggers.trigger_pool[player GetEntityNumber()] = trigger;
650  }
651  else
652  trigger = stub.playertrigger[player GetEntityNumber()];
653  }
654  else
655  {
656  if(!isdefined(stub.trigger))
657  {
658  trigger = ‪build_trigger_from_unitrigger_stub(stub,player);
659  level._unitriggers.trigger_pool[player GetEntityNumber()] = trigger;
660  } else trigger = stub.trigger;
661  }
662  return trigger;
663 }
664 
666 {
667  if( isdefined( level._zm_build_trigger_from_unitrigger_stub_override ) )
668  {
669  if( stub [[ level._zm_build_trigger_from_unitrigger_stub_override ]]( player ) )
670  {
671  return;
672  }
673  }
674 
675  radius = stub.radius;
676 
677  if(!isdefined(radius))
678  {
679  radius = 64;
680  }
681 
682  script_height = stub.script_height;
683  if(!isdefined(script_height))
684  {
685  script_height = 64;
686  }
687 
688  script_width = stub.script_width;
689  if(!isdefined(script_width))
690  {
691  script_width = 64;
692  }
693 
694 
695  script_length = stub.script_length;
696  if(!isdefined(script_length))
697  {
698  script_length = 64;
699  }
700 
701  trigger = undefined;
702 
703  origin = stub ‪unitrigger_origin();
704 
705  switch(stub.script_unitrigger_type)
706  {
707  case "unitrigger_radius":
708  trigger = ‪Spawn( "trigger_radius", origin, 0, radius, script_height);
709  break;
710  case "unitrigger_radius_use":
711  trigger = ‪Spawn( "trigger_radius_use", origin, 0, radius, script_height);
712  break;
713  case "unitrigger_box":
714  trigger = ‪Spawn( "trigger_box", origin, 0, script_width, script_length, script_height);
715  break;
716  case "unitrigger_box_use":
717  trigger = ‪Spawn( "trigger_box_use", origin, 0, script_width, script_length, script_height);
718  break;
719  }
720 
721  if(isdefined(trigger))
722  {
723  if(isdefined(stub.angles))
724  {
725  trigger.angles = stub.angles;
726  }
727 
728  if (isdefined(stub.onSpawnFunc))
729  stub [[stub.onSpawnFunc]](trigger);
730 
731  if(isdefined(stub.cursor_hint))
732  {
733  if ( stub.cursor_hint == "HINT_WEAPON" && IsDefined(stub.cursor_hint_weapon) )
734  trigger SetCursorHint(stub.cursor_hint,stub.cursor_hint_weapon);
735  else
736  trigger SetCursorHint(stub.cursor_hint);
737  }
738  trigger TriggerIgnoreTeam();
739 
740  if(‪IS_TRUE(stub.require_look_at))
741  {
742  trigger UseTriggerRequireLookAt();
743  }
744  if(‪IS_TRUE(stub.require_look_toward))
745  {
746  trigger UseTriggerRequireLookToward(true);
747  }
748 
749  if(isdefined(stub.hint_string))
750  {
751  if(isdefined(stub.hint_parm2))
752  {
753  trigger SetHintString(stub.hint_string, stub.hint_parm1, stub.hint_parm2);
754  }
755  else if(isdefined(stub.hint_parm1))
756  {
757  trigger SetHintString(stub.hint_string, stub.hint_parm1);
758  }
759  else if(isdefined(stub.cost) && !‪IS_TRUE( level.weapon_cost_client_filled )) // T7TODO - DEPRECATED
760  {
761  trigger SetHintString(stub.hint_string, stub.cost);
762  }
763  else
764  {
765  trigger SetHintString(stub.hint_string);
766  }
767  }
768 
769  trigger.stub = stub;
770  }
771 
772  ‪copy_zombie_keys_onto_trigger(trigger, stub);
773 
774  if(‪IS_TRUE(stub.trigger_per_player))
775  {
776  if(isdefined(trigger))
777  {
778  trigger setInvisibleToAll();
779  trigger setVisibleToPlayer( player );
780  }
781  if (!isdefined(stub.playertrigger))
782  stub.playertrigger = [];
783  stub.playertrigger[player GetEntityNumber()] = trigger;
784  }
785  else
786  stub.trigger = trigger;
787  trigger.thread_running = false;
788  return trigger;
789 }
790 
792 {
793  // Generic
794  trig.script_noteworthy = stub.script_noteworthy;
795  trig.targetname = stub.targetname;
796  trig.target = stub.target;
797 
798 
799  // Wallbuys
800  trig.weapon = stub.weapon;
801  trig.clientFieldName = stub.clientFieldName;
802 
803  // buildables
804  trig.useTime = stub.useTime;
805 
806 }
807 
808 function ‪trigger_thread(trigger_func) // Wrapper to add kill_trigger endon to all managed trigger threads.
809 {
810  self endon("kill_trigger");
811 
812  if(isdefined(trigger_func))
813  {
814  self [[trigger_func]]();
815  }
816 }
817 
818 function ‪get_closest_unitriggers( org, ‪array, dist = 9999999 )
819 {
820  triggers = [];
821  if( ‪array.size < 1 )
822  {
823  return triggers;
824  }
825  distsq = dist*dist;
826  for( i = 0; i < ‪array.size; i++ )
827  {
828  if (!isdefined(‪array[i]))
829  continue;
830  origin = ‪array[ i ] ‪unitrigger_origin();
831  radius_sq = ‪array[ i ].test_radius_sq;
832 
833  newdistsq = Distance2DSquared( origin, org );
834  if( newdistsq >= radius_sq )
835  {
836  continue;
837  }
838  if ( abs(origin[2]-org[2]) > 42 )
839  continue;
840  ‪array[i].dsquared = newdistsq;
841  j=0;
842  while(j<triggers.size && newdistsq > triggers[j].dsquared)
843  j++;
844  ArrayInsert(triggers,‪array[i],j);
845  }
846 
847  return triggers;
848 }
849 
850 // Utility Function for all maps to use:
851 
852 // self == struct/entity where the unitrigger will be placed
853 function ‪create_unitrigger( str_hint, n_radius = 64, func_prompt_and_visibility = &‪unitrigger_prompt_and_visibility, func_unitrigger_logic = &‪unitrigger_logic, s_trigger_type = "unitrigger_radius_use" )
854 {
855  s_unitrigger = SpawnStruct();
856  s_unitrigger.origin = self.origin;
857  s_unitrigger.angles = self.angles;
858  s_unitrigger.script_unitrigger_type = s_trigger_type;
859  s_unitrigger.cursor_hint = "HINT_NOICON";
860  s_unitrigger.hint_string = str_hint;
861  s_unitrigger.prompt_and_visibility_func = func_prompt_and_visibility;
862  s_unitrigger.related_parent = self;
863  s_unitrigger.radius = n_radius;
864  self.s_unitrigger = s_unitrigger;
865  ‪register_static_unitrigger( s_unitrigger, func_unitrigger_logic );
866 
867  return s_unitrigger;
868 }
869 
870 
871 // self == struct/entity where the unitrigger will be placed
872 function ‪create_dyn_unitrigger( str_hint, n_radius = 64, func_prompt_and_visibility = &‪unitrigger_prompt_and_visibility, func_unitrigger_logic = &‪unitrigger_logic, s_trigger_type = "unitrigger_radius_use" )
873 {
874  s_unitrigger = SpawnStruct();
875  s_unitrigger.origin = self.origin;
876  s_unitrigger.angles = self.angles;
877  s_unitrigger.script_unitrigger_type = s_trigger_type;
878  s_unitrigger.cursor_hint = "HINT_NOICON";
879  s_unitrigger.hint_string = str_hint;
880  s_unitrigger.prompt_and_visibility_func = func_prompt_and_visibility;
881  s_unitrigger.related_parent = self;
882  s_unitrigger.radius = n_radius;
883  self.s_unitrigger = s_unitrigger;
884  ‪register_dyn_unitrigger( s_unitrigger, func_unitrigger_logic );
885 
886  return s_unitrigger;
887 }
888 
889 
890 
891 // self == unitrigger
893 {
894  b_visible = true;
895 
896  return b_visible;
897 }
898 
899 // self == unitrigger
901 {
902  self endon( "death" );
903 
904  while ( true )
905  {
906  self waittill( "trigger", player );
907 
908  if( player ‪zm_utility::in_revive_trigger() ) // revive triggers override trap triggers
909  {
910  continue;
911  }
912 
913  if( ‪IS_DRINKING( player.is_drinking ) )
914  {
915  continue;
916  }
917 
918  if( !‪zm_utility::is_player_valid( player ) ) // ensure valid player
919  {
920  continue;
921  }
922 
923  self.stub.related_parent notify( "trigger_activated", player );
924  }
925 }
926 
927 
‪trigger_thread
‪function trigger_thread(trigger_func)
Definition: _zm_unitrigger.gsc:808
‪get_array
‪function get_array(kvp_value, kvp_key="targetname")
Definition: struct.csc:34
‪unitrigger_trigger
‪function unitrigger_trigger(player)
Definition: _zm_unitrigger.gsc:65
‪delay_delete_contact_ent
‪function delay_delete_contact_ent()
Definition: _zm_unitrigger.gsc:219
‪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
‪copy_zombie_keys_onto_trigger
‪function copy_zombie_keys_onto_trigger(trig, stub)
Definition: _zm_unitrigger.gsc:791
‪is_player_valid
‪function is_player_valid(player, checkIgnoreMeFlag, ignore_laststand_players)
Definition: skeleton.gsc:256
‪register_dyn_unitrigger
‪function register_dyn_unitrigger(unitrigger_stub, trigger_func, recalculate_zone)
Definition: _zm_unitrigger.gsc:287
‪unregister_unitrigger
‪function unregister_unitrigger(unitrigger_stub)
Definition: _zm_unitrigger.gsc:173
‪build_trigger_from_unitrigger_stub
‪function build_trigger_from_unitrigger_stub(stub, player)
Definition: _zm_unitrigger.gsc:665
‪get_closest_unitriggers
‪function get_closest_unitriggers(org, array, dist=9999999)
Definition: _zm_unitrigger.gsc:818
‪assess_and_apply_visibility
‪function assess_and_apply_visibility(trigger, stub, player, default_keep)
Definition: _zm_unitrigger.gsc:335
‪create_dyn_unitrigger
‪function create_dyn_unitrigger(str_hint, n_radius=64, func_prompt_and_visibility=&unitrigger_prompt_and_visibility, func_unitrigger_logic=&unitrigger_logic, s_trigger_type="unitrigger_radius_use")
Definition: _zm_unitrigger.gsc:872
‪register_unitrigger_system_func
‪function register_unitrigger_system_func(system, trigger_func)
Definition: _zm_unitrigger.gsc:53
‪PLAYER_RADIUS
‪#define PLAYER_RADIUS
Definition: _zm_unitrigger.gsc:20
‪debug_unitriggers
‪function debug_unitriggers()
Definition: _zm_unitrigger.gsc:315
‪unitrigger_origin
‪function unitrigger_origin()
Definition: _zm_unitrigger.gsc:77
‪is_player_looking_at
‪function is_player_looking_at(origin, dot, do_trace, ignore_ent)
Definition: util_shared.gsc:1664
‪__init__
‪function __init__()
Definition: _zm_unitrigger.gsc:28
‪UNITRIGGER_MAX_RADIUS
‪#define UNITRIGGER_MAX_RADIUS
Definition: _zm_unitrigger.gsc:22
‪check_and_build_trigger_from_unitrigger_stub
‪function check_and_build_trigger_from_unitrigger_stub(stub, player)
Definition: _zm_unitrigger.gsc:637
‪REGISTER_SYSTEM
‪#define REGISTER_SYSTEM(__sys, __func_init_preload, __reqs)
Definition: shared.gsh:204
‪array
‪function filter array
Definition: array_shared.csc:16
‪run_visibility_function_for_all_triggers
‪function run_visibility_function_for_all_triggers()
Definition: _zm_unitrigger.gsc:599
‪cleanup_trigger
‪function cleanup_trigger(trigger, player)
Definition: _zm_unitrigger.gsc:319
‪Spawn
‪function Spawn(parent, onDeathCallback)
Definition: _flak_drone.gsc:427
‪unitrigger_logic
‪function unitrigger_logic()
Definition: _zm_unitrigger.gsc:900
‪reregister_unitrigger_as_dynamic
‪function reregister_unitrigger_as_dynamic(unitrigger_stub)
Definition: _zm_unitrigger.gsc:308
‪PLAYER_STAND_MAX_Z
‪#define PLAYER_STAND_MAX_Z
Definition: _zm_unitrigger.gsc:21
‪register_unitrigger_internal
‪function register_unitrigger_internal(unitrigger_stub, trigger_func)
Definition: _zm_unitrigger.gsc:86
‪is_same_trigger
‪function is_same_trigger(old_trigger, trigger)
Definition: _zm_unitrigger.gsc:632
‪unregister_unitrigger_internal
‪function unregister_unitrigger_internal(unitrigger_stub)
Definition: _zm_unitrigger.gsc:179
‪unitrigger_force_per_player_triggers
‪function unitrigger_force_per_player_triggers(unitrigger_stub, opt_on_off)
Definition: _zm_unitrigger.gsc:58
‪in_revive_trigger
‪function in_revive_trigger()
Definition: _zm_utility.gsc:1684
‪entity_in_zone
‪function entity_in_zone(zone_name, ignore_enabled_check=false)
Definition: _zm_zonemgr.gsc:214
‪main
‪function main()
Definition: _zm_unitrigger.gsc:364
‪create_unitrigger
‪function create_unitrigger(str_hint, n_radius=64, func_prompt_and_visibility=&unitrigger_prompt_and_visibility, func_unitrigger_logic=&unitrigger_logic, s_trigger_type="unitrigger_radius_use")
Definition: _zm_unitrigger.gsc:853
‪IS_DRINKING
‪#define IS_DRINKING(_is_drinking)
Definition: _zm_utility.gsh:1
‪register_static_unitrigger
‪function register_static_unitrigger(unitrigger_stub, trigger_func, recalculate_zone)
Definition: _zm_unitrigger.gsc:236
‪unitrigger_prompt_and_visibility
‪function unitrigger_prompt_and_visibility(player)
Definition: _zm_unitrigger.gsc:892
‪register_unitrigger
‪function register_unitrigger(unitrigger_stub, trigger_func)
Definition: _zm_unitrigger.gsc:166
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265