/*************************************************
 * Decompiled by Serious and Edited by SyndiShanX
 * Script: zm\_zm_unitrigger.gsc
*************************************************/

#using scripts\codescripts\struct;
#using scripts\shared\system_shared;
#using scripts\zm\_zm_utility;
#using scripts\zm\_zm_zonemgr;
#namespace zm_unitrigger;

function autoexec __init__sytem__() {
  system::register("zm_unitrigger", &__init__, undefined, undefined);
}

function __init__() {
  level._unitriggers = spawnStruct();
  level._unitriggers._deferredinitlist = [];
  level._unitriggers.trigger_pool = [];
  level._unitriggers.trigger_stubs = [];
  level._unitriggers.dynamic_stubs = [];
  level._unitriggers.system_trigger_funcs = [];
  level._unitriggers.largest_radius = 64;
  stubs_keys = array("unitrigger_radius", "unitrigger_radius_use", "unitrigger_box", "unitrigger_box_use");
  stubs = [];
  for(i = 0; i < stubs_keys.size; i++) {
    stubs = arraycombine(stubs, struct::get_array(stubs_keys[i], "script_unitrigger_type"), 1, 0);
  }
  for(i = 0; i < stubs.size; i++) {
    register_unitrigger(stubs[i]);
  }
}

function register_unitrigger_system_func(system, trigger_func) {
  level._unitriggers.system_trigger_funcs[system] = trigger_func;
}

function unitrigger_force_per_player_triggers(unitrigger_stub, opt_on_off = 1) {
  unitrigger_stub.trigger_per_player = opt_on_off;
}

function unitrigger_trigger(player) {
  if(self.trigger_per_player) {
    return self.playertrigger[player getentitynumber()];
  }
  return self.trigger;
}

function unitrigger_origin() {
  if(isDefined(self.originfunc)) {
    origin = self[[self.originfunc]]();
  } else {
    origin = self.origin;
  }
  return origin;
}

function register_unitrigger_internal(unitrigger_stub, trigger_func) {
  if(!isDefined(unitrigger_stub.script_unitrigger_type)) {
    println("");
    return;
  }
  if(isDefined(trigger_func)) {
    unitrigger_stub.trigger_func = trigger_func;
  } else if(isDefined(unitrigger_stub.unitrigger_system) && isDefined(level._unitriggers.system_trigger_funcs[unitrigger_stub.unitrigger_system])) {
    unitrigger_stub.trigger_func = level._unitriggers.system_trigger_funcs[unitrigger_stub.unitrigger_system];
  }
  switch (unitrigger_stub.script_unitrigger_type) {
    case "unitrigger_radius":
    case "unitrigger_radius_use": {
      if(!isDefined(unitrigger_stub.radius)) {
        unitrigger_stub.radius = 32;
      }
      if(!isDefined(unitrigger_stub.script_height)) {
        unitrigger_stub.script_height = 64;
      }
      unitrigger_stub.test_radius_sq = (unitrigger_stub.radius + 15) * (unitrigger_stub.radius + 15);
      break;
    }
    case "unitrigger_box":
    case "unitrigger_box_use": {
      if(!isDefined(unitrigger_stub.script_width)) {
        unitrigger_stub.script_width = 64;
      }
      if(!isDefined(unitrigger_stub.script_height)) {
        unitrigger_stub.script_height = 64;
      }
      if(!isDefined(unitrigger_stub.script_length)) {
        unitrigger_stub.script_length = 64;
      }
      box_radius = length((unitrigger_stub.script_width / 2, unitrigger_stub.script_length / 2, unitrigger_stub.script_height / 2));
      if(!isDefined(unitrigger_stub.radius) || unitrigger_stub.radius < box_radius) {
        unitrigger_stub.radius = box_radius;
      }
      unitrigger_stub.test_radius_sq = (box_radius + 15) * (box_radius + 15);
      break;
    }
    default: {
      println(("" + unitrigger_stub.targetname) + "");
      return;
    }
  }
  if(unitrigger_stub.radius > level._unitriggers.largest_radius) {
    level._unitriggers.largest_radius = min(113, unitrigger_stub.radius);
    if(isDefined(level.fixed_max_player_use_radius)) {
      if(level.fixed_max_player_use_radius > getdvarfloat("player_useRadius_zm")) {
        setDvar("player_useRadius_zm", level.fixed_max_player_use_radius);
      }
    } else if(level._unitriggers.largest_radius > getdvarfloat("player_useRadius_zm")) {
      setDvar("player_useRadius_zm", level._unitriggers.largest_radius);
    }
  }
  level._unitriggers.trigger_stubs[level._unitriggers.trigger_stubs.size] = unitrigger_stub;
  unitrigger_stub.registered = 1;
}

function register_unitrigger(unitrigger_stub, trigger_func) {
  register_unitrigger_internal(unitrigger_stub, trigger_func);
  level._unitriggers.dynamic_stubs[level._unitriggers.dynamic_stubs.size] = unitrigger_stub;
}

function unregister_unitrigger(unitrigger_stub) {
  thread unregister_unitrigger_internal(unitrigger_stub);
}

function unregister_unitrigger_internal(unitrigger_stub) {
  if(!isDefined(unitrigger_stub)) {
    return;
  }
  unitrigger_stub.registered = 0;
  if(isDefined(unitrigger_stub.trigger_per_player) && unitrigger_stub.trigger_per_player) {
    if(isDefined(unitrigger_stub.playertrigger) && unitrigger_stub.playertrigger.size > 0) {
      keys = getarraykeys(unitrigger_stub.playertrigger);
      foreach(key in keys) {
        trigger = unitrigger_stub.playertrigger[key];
        trigger notify("kill_trigger");
        if(isDefined(trigger)) {
          trigger delete();
        }
      }
      unitrigger_stub.playertrigger = [];
    }
  } else if(isDefined(unitrigger_stub.trigger)) {
    trigger = unitrigger_stub.trigger;
    trigger notify("kill_trigger");
    trigger.stub.trigger = undefined;
    trigger delete();
  }
  if(isDefined(unitrigger_stub.in_zone)) {
    arrayremovevalue(level.zones[unitrigger_stub.in_zone].unitrigger_stubs, unitrigger_stub);
    unitrigger_stub.in_zone = undefined;
  }
  arrayremovevalue(level._unitriggers.trigger_stubs, unitrigger_stub);
  arrayremovevalue(level._unitriggers.dynamic_stubs, unitrigger_stub);
}

function delay_delete_contact_ent() {
  self.last_used_time = 0;
  while(true) {
    wait(1);
    if((gettime() - self.last_used_time) > 1000) {
      self delete();
      level._unitriggers.contact_ent = undefined;
      return;
    }
  }
}

function register_static_unitrigger(unitrigger_stub, trigger_func, recalculate_zone) {
  if(level.zones.size == 0) {
    unitrigger_stub.trigger_func = trigger_func;
    level._unitriggers._deferredinitlist[level._unitriggers._deferredinitlist.size] = unitrigger_stub;
    return;
  }
  if(!isDefined(level._unitriggers.contact_ent)) {
    level._unitriggers.contact_ent = spawn("script_origin", (0, 0, 0));
    level._unitriggers.contact_ent thread delay_delete_contact_ent();
  }
  register_unitrigger_internal(unitrigger_stub, trigger_func);
  if(!isDefined(level._no_static_unitriggers)) {
    level._unitriggers.contact_ent.last_used_time = gettime();
    level._unitriggers.contact_ent.origin = unitrigger_stub.origin;
    if(isDefined(unitrigger_stub.in_zone) && !isDefined(recalculate_zone)) {
      level.zones[unitrigger_stub.in_zone].unitrigger_stubs[level.zones[unitrigger_stub.in_zone].unitrigger_stubs.size] = unitrigger_stub;
      return;
    }
    keys = getarraykeys(level.zones);
    for(i = 0; i < keys.size; i++) {
      if(level._unitriggers.contact_ent zm_zonemgr::entity_in_zone(keys[i], 1)) {
        if(!isDefined(level.zones[keys[i]].unitrigger_stubs)) {
          level.zones[keys[i]].unitrigger_stubs = [];
        }
        level.zones[keys[i]].unitrigger_stubs[level.zones[keys[i]].unitrigger_stubs.size] = unitrigger_stub;
        unitrigger_stub.in_zone = keys[i];
        return;
      }
    }
  }
  level._unitriggers.dynamic_stubs[level._unitriggers.dynamic_stubs.size] = unitrigger_stub;
  unitrigger_stub.registered = 1;
}

function register_dyn_unitrigger(unitrigger_stub, trigger_func, recalculate_zone) {
  if(level.zones.size == 0) {
    unitrigger_stub.trigger_func = trigger_func;
    level._unitriggers._deferredinitlist[level._unitriggers._deferredinitlist.size] = unitrigger_stub;
    return;
  }
  if(!isDefined(level._unitriggers.contact_ent)) {
    level._unitriggers.contact_ent = spawn("script_origin", (0, 0, 0));
    level._unitriggers.contact_ent thread delay_delete_contact_ent();
  }
  register_unitrigger_internal(unitrigger_stub, trigger_func);
  level._unitriggers.dynamic_stubs[level._unitriggers.dynamic_stubs.size] = unitrigger_stub;
  unitrigger_stub.registered = 1;
}

function reregister_unitrigger_as_dynamic(unitrigger_stub) {
  unregister_unitrigger_internal(unitrigger_stub);
  register_unitrigger(unitrigger_stub, unitrigger_stub.trigger_func);
}

function debug_unitriggers() {
  while(true) {
    if(getdvarint("") > 0) {
      for(i = 0; i < level._unitriggers.trigger_stubs.size; i++) {
        triggerstub = level._unitriggers.trigger_stubs[i];
        color = vectorscale((1, 0, 0), 0.75);
        if(!isDefined(triggerstub.in_zone)) {
          color = vectorscale((1, 1, 0), 0.65);
        } else if(level.zones[triggerstub.in_zone].is_active) {
          color = (1, 1, 0);
        }
        if(isDefined(triggerstub.trigger) || (isDefined(triggerstub.playertrigger) && triggerstub.playertrigger.size > 0)) {
          color = (0, 1, 0);
          if(isDefined(triggerstub.playertrigger) && triggerstub.playertrigger.size > 0) {
            print3d(triggerstub.origin, triggerstub.playertrigger.size, color, 1, 1, 1);
          }
        }
        origin = triggerstub unitrigger_origin();
        switch (triggerstub.script_unitrigger_type) {
          case "":
          case "": {
            if(triggerstub.radius) {
              circle(origin, triggerstub.radius, color, 0, 0, 1);
            }
            if(triggerstub.script_height) {
              line(origin, origin + (0, 0, triggerstub.script_height), color, 0, 1);
            }
            break;
          }
          case "":
          case "": {
            vec = (triggerstub.script_width / 2, triggerstub.script_length / 2, triggerstub.script_height / 2);
            box(origin, vec * -1, vec, triggerstub.angles[1], color, 1, 0, 1);
            break;
          }
        }
      }
    }
    wait(0.05);
  }
}

function cleanup_trigger(trigger, player) {
  trigger notify("kill_trigger");
  if(isDefined(trigger.stub.trigger_per_player) && trigger.stub.trigger_per_player) {
    trigger.stub.playertrigger[player getentitynumber()] = undefined;
  } else {
    trigger.stub.trigger = undefined;
  }
  trigger delete();
  level._unitriggers.trigger_pool[player getentitynumber()] = undefined;
}

function assess_and_apply_visibility(trigger, stub, player, default_keep) {
  if(!isDefined(trigger) || !isDefined(stub)) {
    return 0;
  }
  keep_thread = default_keep;
  if(!isDefined(stub.prompt_and_visibility_func) || trigger[[stub.prompt_and_visibility_func]](player)) {
    keep_thread = 1;
    if(!(isDefined(trigger.thread_running) && trigger.thread_running)) {
      trigger thread trigger_thread(trigger.stub.trigger_func);
    }
    trigger.thread_running = 1;
    if(isDefined(trigger.reassess_time) && trigger.reassess_time <= 0) {
      trigger.reassess_time = undefined;
    }
  } else {
    if(isDefined(trigger.thread_running) && trigger.thread_running) {
      keep_thread = 0;
    }
    trigger.thread_running = 0;
    if(isDefined(stub.inactive_reassess_time)) {
      trigger.reassess_time = stub.inactive_reassess_time;
    } else {
      trigger.reassess_time = 1;
    }
  }
  return keep_thread;
}

function main() {
  level thread debug_unitriggers();
  if(level._unitriggers._deferredinitlist.size) {
    for(i = 0; i < level._unitriggers._deferredinitlist.size; i++) {
      register_static_unitrigger(level._unitriggers._deferredinitlist[i], level._unitriggers._deferredinitlist[i].trigger_func);
    }
    for(i = 0; i < level._unitriggers._deferredinitlist.size; i++) {
      level._unitriggers._deferredinitlist[i] = undefined;
    }
    level._unitriggers._deferredinitlist = undefined;
  }
  valid_range = level._unitriggers.largest_radius + 15;
  valid_range_sq = valid_range * valid_range;
  while(!isDefined(level.active_zone_names)) {
    wait(0.1);
  }
  while(true) {
    waited = 0;
    active_zone_names = level.active_zone_names;
    candidate_list = [];
    for(j = 0; j < active_zone_names.size; j++) {
      if(isDefined(level.zones[active_zone_names[j]].unitrigger_stubs)) {
        candidate_list = arraycombine(candidate_list, level.zones[active_zone_names[j]].unitrigger_stubs, 1, 0);
      }
    }
    candidate_list = arraycombine(candidate_list, level._unitriggers.dynamic_stubs, 1, 0);
    players = getplayers();
    for(i = 0; i < players.size; i++) {
      player = players[i];
      if(!isDefined(player)) {
        continue;
      }
      player_origin = player.origin + vectorscale((0, 0, 1), 35);
      trigger = level._unitriggers.trigger_pool[player getentitynumber()];
      old_trigger = undefined;
      closest = [];
      if(isDefined(trigger)) {
        dst = valid_range_sq;
        origin = trigger unitrigger_origin();
        dst = trigger.stub.test_radius_sq;
        time_to_ressess = 0;
        trigger_still_valid = 0;
        if(distance2dsquared(player_origin, origin) < dst) {
          if(isDefined(trigger.reassess_time)) {
            trigger.reassess_time = trigger.reassess_time - 0.05;
            if(trigger.reassess_time > 0) {
              continue;
            }
            time_to_ressess = 1;
          }
          trigger_still_valid = 1;
        }
        closest = get_closest_unitriggers(player_origin, candidate_list, valid_range);
        if(isDefined(trigger) && time_to_ressess && (closest.size < 2 || (isDefined(trigger.thread_running) && trigger.thread_running))) {
          if(assess_and_apply_visibility(trigger, trigger.stub, player, 1)) {
            continue;
          }
        }
        if(trigger_still_valid && closest.size < 2) {
          if(assess_and_apply_visibility(trigger, trigger.stub, player, 1)) {
            continue;
          }
        }
        if(trigger_still_valid) {
          old_trigger = trigger;
          trigger = undefined;
          level._unitriggers.trigger_pool[player getentitynumber()] = undefined;
        } else if(isDefined(trigger)) {
          cleanup_trigger(trigger, player);
        }
      } else {
        closest = get_closest_unitriggers(player_origin, candidate_list, valid_range);
      }
      index = 0;
      first_usable = undefined;
      first_visible = undefined;
      trigger_found = 0;
      while(index < closest.size) {
        if(!zm_utility::is_player_valid(player) && (!(isDefined(closest[index].ignore_player_valid) && closest[index].ignore_player_valid))) {
          index++;
          continue;
        }
        if(!(isDefined(closest[index].registered) && closest[index].registered)) {
          index++;
          continue;
        }
        trigger = check_and_build_trigger_from_unitrigger_stub(closest[index], player);
        if(isDefined(trigger)) {
          trigger.parent_player = player;
          if(assess_and_apply_visibility(trigger, closest[index], player, 0)) {
            if(player zm_utility::is_player_looking_at(closest[index].origin, 0.9, 0)) {
              if(!is_same_trigger(old_trigger, trigger) && isDefined(old_trigger)) {
                cleanup_trigger(old_trigger, player);
              }
              level._unitriggers.trigger_pool[player getentitynumber()] = trigger;
              trigger_found = 1;
              break;
            }
            if(!isDefined(first_usable)) {
              first_usable = index;
            }
          }
          if(!isDefined(first_visible)) {
            first_visible = index;
          }
          if(isDefined(trigger)) {
            if(is_same_trigger(old_trigger, trigger)) {
              level._unitriggers.trigger_pool[player getentitynumber()] = undefined;
            } else {
              cleanup_trigger(trigger, player);
            }
          }
          last_trigger = trigger;
        }
        index++;
        waited = 1;
        wait(0.05);
      }
      if(!isDefined(player)) {
        continue;
      }
      if(trigger_found) {
        continue;
      }
      if(isDefined(first_usable)) {
        index = first_usable;
      } else if(isDefined(first_visible)) {
        index = first_visible;
      }
      trigger = check_and_build_trigger_from_unitrigger_stub(closest[index], player);
      if(isDefined(trigger)) {
        trigger.parent_player = player;
        level._unitriggers.trigger_pool[player getentitynumber()] = trigger;
        if(is_same_trigger(old_trigger, trigger)) {
          continue;
        }
        if(isDefined(old_trigger)) {
          cleanup_trigger(old_trigger, player);
        }
        if(isDefined(trigger)) {
          assess_and_apply_visibility(trigger, trigger.stub, player, 0);
        }
      }
    }
    if(!waited) {
      wait(0.05);
    }
  }
}

function run_visibility_function_for_all_triggers() {
  if(!isDefined(self.prompt_and_visibility_func)) {
    return;
  }
  if(isDefined(self.trigger_per_player) && self.trigger_per_player) {
    if(!isDefined(self.playertrigger)) {
      return;
    }
    players = getplayers();
    for(i = 0; i < players.size; i++) {
      if(isDefined(self.playertrigger[players[i] getentitynumber()])) {
        self.playertrigger[players[i] getentitynumber()][[self.prompt_and_visibility_func]](players[i]);
      }
    }
  } else if(isDefined(self.trigger)) {
    self.trigger[[self.prompt_and_visibility_func]](getplayers()[0]);
  }
}

function is_same_trigger(old_trigger, trigger) {
  return isDefined(old_trigger) && old_trigger == trigger && trigger.parent_player == old_trigger.parent_player;
}

function check_and_build_trigger_from_unitrigger_stub(stub, player) {
  if(!isDefined(stub)) {
    return undefined;
  }
  if(isDefined(stub.trigger_per_player) && stub.trigger_per_player) {
    if(!isDefined(stub.playertrigger)) {
      stub.playertrigger = [];
    }
    if(!isDefined(stub.playertrigger[player getentitynumber()])) {
      trigger = build_trigger_from_unitrigger_stub(stub, player);
      level._unitriggers.trigger_pool[player getentitynumber()] = trigger;
    } else {
      trigger = stub.playertrigger[player getentitynumber()];
    }
  } else {
    if(!isDefined(stub.trigger)) {
      trigger = build_trigger_from_unitrigger_stub(stub, player);
      level._unitriggers.trigger_pool[player getentitynumber()] = trigger;
    } else {
      trigger = stub.trigger;
    }
  }
  return trigger;
}

function build_trigger_from_unitrigger_stub(stub, player) {
  if(isDefined(level._zm_build_trigger_from_unitrigger_stub_override)) {
    if(stub[[level._zm_build_trigger_from_unitrigger_stub_override]](player)) {
      return;
    }
  }
  radius = stub.radius;
  if(!isDefined(radius)) {
    radius = 64;
  }
  script_height = stub.script_height;
  if(!isDefined(script_height)) {
    script_height = 64;
  }
  script_width = stub.script_width;
  if(!isDefined(script_width)) {
    script_width = 64;
  }
  script_length = stub.script_length;
  if(!isDefined(script_length)) {
    script_length = 64;
  }
  trigger = undefined;
  origin = stub unitrigger_origin();
  switch (stub.script_unitrigger_type) {
    case "unitrigger_radius": {
      trigger = spawn("trigger_radius", origin, 0, radius, script_height);
      break;
    }
    case "unitrigger_radius_use": {
      trigger = spawn("trigger_radius_use", origin, 0, radius, script_height);
      break;
    }
    case "unitrigger_box": {
      trigger = spawn("trigger_box", origin, 0, script_width, script_length, script_height);
      break;
    }
    case "unitrigger_box_use": {
      trigger = spawn("trigger_box_use", origin, 0, script_width, script_length, script_height);
      break;
    }
  }
  if(isDefined(trigger)) {
    if(isDefined(stub.angles)) {
      trigger.angles = stub.angles;
    }
    if(isDefined(stub.onspawnfunc)) {
      stub[[stub.onspawnfunc]](trigger);
    }
    if(isDefined(stub.cursor_hint)) {
      if(stub.cursor_hint == "HINT_WEAPON" && isDefined(stub.cursor_hint_weapon)) {
        trigger setcursorhint(stub.cursor_hint, stub.cursor_hint_weapon);
      } else {
        trigger setcursorhint(stub.cursor_hint);
      }
    }
    trigger triggerignoreteam();
    if(isDefined(stub.require_look_at) && stub.require_look_at) {
      trigger usetriggerrequirelookat();
    }
    if(isDefined(stub.require_look_toward) && stub.require_look_toward) {
      trigger usetriggerrequirelooktoward(1);
    }
    if(isDefined(stub.hint_string)) {
      if(isDefined(stub.hint_parm2)) {
        trigger sethintstring(stub.hint_string, stub.hint_parm1, stub.hint_parm2);
      } else {
        if(isDefined(stub.hint_parm1)) {
          trigger sethintstring(stub.hint_string, stub.hint_parm1);
        } else {
          if(isDefined(stub.cost) && (!(isDefined(level.weapon_cost_client_filled) && level.weapon_cost_client_filled))) {
            trigger sethintstring(stub.hint_string, stub.cost);
          } else {
            trigger sethintstring(stub.hint_string);
          }
        }
      }
    }
    trigger.stub = stub;
  }
  copy_zombie_keys_onto_trigger(trigger, stub);
  if(isDefined(stub.trigger_per_player) && stub.trigger_per_player) {
    if(isDefined(trigger)) {
      trigger setinvisibletoall();
      trigger setvisibletoplayer(player);
    }
    if(!isDefined(stub.playertrigger)) {
      stub.playertrigger = [];
    }
    stub.playertrigger[player getentitynumber()] = trigger;
  } else {
    stub.trigger = trigger;
  }
  trigger.thread_running = 0;
  return trigger;
}

function copy_zombie_keys_onto_trigger(trig, stub) {
  trig.script_noteworthy = stub.script_noteworthy;
  trig.targetname = stub.targetname;
  trig.target = stub.target;
  trig.weapon = stub.weapon;
  trig.clientfieldname = stub.clientfieldname;
  trig.usetime = stub.usetime;
}

function trigger_thread(trigger_func) {
  self endon("kill_trigger");
  if(isDefined(trigger_func)) {
    self[[trigger_func]]();
  }
}

function get_closest_unitriggers(org, array, dist = 9999999) {
  triggers = [];
  if(array.size < 1) {
    return triggers;
  }
  distsq = dist * dist;
  for(i = 0; i < array.size; i++) {
    if(!isDefined(array[i])) {
      continue;
    }
    origin = array[i] unitrigger_origin();
    radius_sq = array[i].test_radius_sq;
    newdistsq = distance2dsquared(origin, org);
    if(newdistsq >= radius_sq) {
      continue;
    }
    if((abs(origin[2] - org[2])) > 42) {
      continue;
    }
    array[i].dsquared = newdistsq;
    for(j = 0; j < triggers.size && newdistsq > triggers[j].dsquared; j++) {}
    arrayinsert(triggers, array[i], j);
  }
  return triggers;
}

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") {
  s_unitrigger = spawnStruct();
  s_unitrigger.origin = self.origin;
  s_unitrigger.angles = self.angles;
  s_unitrigger.script_unitrigger_type = s_trigger_type;
  s_unitrigger.cursor_hint = "HINT_NOICON";
  s_unitrigger.hint_string = str_hint;
  s_unitrigger.prompt_and_visibility_func = func_prompt_and_visibility;
  s_unitrigger.related_parent = self;
  s_unitrigger.radius = n_radius;
  self.s_unitrigger = s_unitrigger;
  register_static_unitrigger(s_unitrigger, func_unitrigger_logic);
  return s_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") {
  s_unitrigger = spawnStruct();
  s_unitrigger.origin = self.origin;
  s_unitrigger.angles = self.angles;
  s_unitrigger.script_unitrigger_type = s_trigger_type;
  s_unitrigger.cursor_hint = "HINT_NOICON";
  s_unitrigger.hint_string = str_hint;
  s_unitrigger.prompt_and_visibility_func = func_prompt_and_visibility;
  s_unitrigger.related_parent = self;
  s_unitrigger.radius = n_radius;
  self.s_unitrigger = s_unitrigger;
  register_dyn_unitrigger(s_unitrigger, func_unitrigger_logic);
  return s_unitrigger;
}

function unitrigger_prompt_and_visibility(player) {
  b_visible = 1;
  return b_visible;
}

function unitrigger_logic() {
  self endon("death");
  while(true) {
    self waittill("trigger", player);
    if(player zm_utility::in_revive_trigger()) {
      continue;
    }
    if(player.is_drinking > 0) {
      continue;
    }
    if(!zm_utility::is_player_valid(player)) {
      continue;
    }
    self.stub.related_parent notify("trigger_activated", player);
  }
}