/*************************************************
 * Decompiled by Serious and Edited by SyndiShanX
 * Script: shared\ai\archetype_human_riotshield.gsc
*************************************************/

#using scripts\shared\ai\archetype_cover_utility;
#using scripts\shared\ai\archetype_human_riotshield_interface;
#using scripts\shared\ai\archetype_locomotion_utility;
#using scripts\shared\ai\archetype_mocomps_utility;
#using scripts\shared\ai\archetype_utility;
#using scripts\shared\ai\systems\ai_interface;
#using scripts\shared\ai\systems\animation_state_machine_mocomp;
#using scripts\shared\ai\systems\animation_state_machine_utility;
#using scripts\shared\ai\systems\behavior_tree_utility;
#using scripts\shared\ai\systems\blackboard;
#using scripts\shared\ai\systems\debug;
#using scripts\shared\ai\systems\gib;
#using scripts\shared\ai\systems\shared;
#using scripts\shared\ai\zombie_utility;
#using scripts\shared\ai_shared;
#using scripts\shared\clientfield_shared;
#using scripts\shared\math_shared;
#using scripts\shared\spawner_shared;
#namespace archetype_human_riotshield;

function autoexec main() {
  spawner::add_archetype_spawn_function("human_riotshield", &humanriotshieldbehavior::archetypehumanriotshieldblackboardinit);
  spawner::add_archetype_spawn_function("human_riotshield", &humanriotshieldserverutils::humanriotshieldspawnsetup);
  humanriotshieldbehavior::registerbehaviorscriptfunctions();
  humanriotshieldinterface::registerhumanriotshieldinterfaceattributes();
}

#namespace humanriotshieldbehavior;

function registerbehaviorscriptfunctions() {
  behaviortreenetworkutility::registerbehaviortreescriptapi("riotshieldShouldTacticalWalk", &riotshieldshouldtacticalwalk);
  behaviortreenetworkutility::registerbehaviortreescriptapi("riotshieldNonCombatLocomotionCondition", &riotshieldnoncombatlocomotioncondition);
  behaviortreenetworkutility::registerbehaviortreescriptapi("unarmedWalkAction", &unarmedwalkactionstart);
  behaviortreenetworkutility::registerbehaviortreescriptapi("riotshieldTacticalWalkStart", &riotshieldtacticalwalkstart);
  behaviortreenetworkutility::registerbehaviortreescriptapi("riotshieldAdvanceOnEnemyService", &riotshieldadvanceonenemyservice);
  behaviortreenetworkutility::registerbehaviortreescriptapi("riotshieldShouldFlinch", &riotshieldshouldflinch);
  behaviortreenetworkutility::registerbehaviortreescriptapi("riotshieldIncrementFlinchCount", &riotshieldincrementflinchcount);
  behaviortreenetworkutility::registerbehaviortreescriptapi("riotshieldClearFlinchCount", &riotshieldclearflinchcount);
  behaviortreenetworkutility::registerbehaviortreescriptapi("riotshieldUnarmedTargetService", &riotshieldunarmedtargetservice);
  behaviortreenetworkutility::registerbehaviortreescriptapi("riotshieldUnarmedAdvanceOnEnemyService", &riotshieldunarmedadvanceonenemyservice);
}

function private archetypehumanriotshieldblackboardinit() {
  entity = self;
  blackboard::createblackboardforentity(entity);
  ai::createinterfaceforentity(entity);
  entity aiutility::registerutilityblackboardattributes();
  self.___archetypeonanimscriptedcallback = &archetypehumanriotshieldonanimscriptedcallback;
  entity finalizetrackedblackboardattributes();
  blackboard::registerblackboardattribute(self, "_move_mode", "normal", &riotshieldmovemode);
  if(isactor(self)) {
    self trackblackboardattribute("");
  }
}

function private archetypehumanriotshieldonanimscriptedcallback(entity) {
  entity.__blackboard = undefined;
  entity archetypehumanriotshieldblackboardinit();
}

function private riotshieldmovemode() {
  entity = self;
  if(entity ai::get_behavior_attribute("phalanx")) {
    return "marching";
  }
  return "normal";
}

function private riotshieldshouldflinch(entity) {
  if(entity haspath() && entity ai::get_behavior_attribute("phalanx")) {
    return true;
  }
  if(entity.damagelocation != "riotshield") {
    return false;
  }
  if(entity.damagelocation == "riotshield" && entity.flinchcount >= 5 && (entity.lastflinchtime + 1500) >= gettime()) {
    return false;
  }
  return true;
}

function private riotshieldincrementflinchcount(entity) {
  entity.flinchcount++;
  entity.lastflinchtime = gettime();
}

function private riotshieldclearflinchcount(entity) {
  entity.lastflinchtime = gettime();
  entity.flinchcount = 0;
}

function private riotshieldshouldtacticalwalk(behaviortreeentity) {
  return true;
}

function private riotshieldnoncombatlocomotioncondition(behaviortreeentity) {
  if(isDefined(behaviortreeentity.enemy)) {
    if(distancesquared(behaviortreeentity.origin, behaviortreeentity lastknownpos(behaviortreeentity.enemy)) > 490000) {
      return true;
    }
  }
  return false;
}

function private riotshieldadvanceonenemyservice(behaviortreeentity) {
  itsbeenawhile = gettime() > behaviortreeentity.nextfindbestcovertime;
  isatscriptgoal = behaviortreeentity isatgoal();
  toolongatnode = 0;
  if(behaviortreeentity ai::get_behavior_attribute("phalanx")) {
    return false;
  }
  if(isDefined(behaviortreeentity.chosennode)) {
    dist_sq = distancesquared(behaviortreeentity.origin, behaviortreeentity.chosennode.origin);
    if(dist_sq < 256) {
      if(!isDefined(behaviortreeentity.timeatchosennode)) {
        behaviortreeentity.timeatchosennode = gettime();
      }
    }
  }
  if(isDefined(behaviortreeentity.timeatchosennode)) {
    if((gettime() - behaviortreeentity.timeatchosennode) > behaviortreeentity.timeatnodemax) {
      toolongatnode = 1;
      behaviortreeentity.timeatchosennode = undefined;
    }
  }
  shouldlookforbettercover = itsbeenawhile || !isatscriptgoal || toolongatnode;
  if(shouldlookforbettercover && isDefined(behaviortreeentity.enemy)) {
    closestrandomnode = undefined;
    closestrandomnodes = behaviortreeentity findbestcovernodes(behaviortreeentity.goalradius, behaviortreeentity.goalpos);
    foreach(node in closestrandomnodes) {
      if(isDefined(behaviortreeentity.chosennode) && behaviortreeentity.chosennode == node) {
        continue;
      }
      if(aiutility::getcovertype(node) == "cover_exposed") {
        closestrandomnode = node;
        break;
      }
    }
    if(!isDefined(closestrandomnode)) {
      closestrandomnode = closestrandomnodes[0];
    }
    if(isDefined(closestrandomnode) && behaviortreeentity findpath(behaviortreeentity.origin, closestrandomnode.origin, 1, 0)) {
      aiutility::releaseclaimnode(behaviortreeentity);
      aiutility::usecovernodewrapper(behaviortreeentity, closestrandomnode);
      behaviortreeentity.chosennode = closestrandomnode;
      behaviortreeentity.timeatnodemax = randomintrange(behaviortreeentity.movedelaymin, behaviortreeentity.movedelaymax);
      behaviortreeentity.timeatchosennode = undefined;
      return true;
    }
  }
  return false;
}

function private riotshieldtacticalwalkstart(behaviortreeentity) {
  aiutility::resetcoverparameters(behaviortreeentity);
  aiutility::setcanbeflanked(behaviortreeentity, 0);
  blackboard::setblackboardattribute(behaviortreeentity, "_stance", "stand");
  behaviortreeentity orientmode("face enemy");
}

function private riotshieldunarmedtargetservice(behaviortreeentity) {
  if(!aiutility::shouldmutexmelee(behaviortreeentity)) {
    return false;
  }
  enemies = [];
  ai = getaiarray();
  foreach(value in ai) {
    if(value.team != behaviortreeentity.team && isactor(value)) {
      enemies[enemies.size] = value;
    }
  }
  if(enemies.size > 0) {
    closestenemy = undefined;
    closestenemydistance = 0;
    for(index = 0; index < enemies.size; index++) {
      enemy = enemies[index];
      enemydistance = distancesquared(behaviortreeentity.origin, enemy.origin);
      checkenemy = 0;
      if(enemydistance > (behaviortreeentity.goalradius * behaviortreeentity.goalradius)) {
        continue;
      }
      if(!isDefined(enemy.targeted_by) || enemy.targeted_by == behaviortreeentity) {
        checkenemy = 1;
      } else {
        targetdistance = distancesquared(enemy.targeted_by.origin, enemy.origin);
        if(enemydistance < targetdistance) {
          checkenemy = 1;
        }
      }
      if(checkenemy) {
        if(!isDefined(closestenemy) || enemydistance < closestenemydistance) {
          closestenemydistance = enemydistance;
          closestenemy = enemy;
        }
      }
    }
    if(isDefined(behaviortreeentity.favoriteenemy)) {
      behaviortreeentity.favoriteenemy.targeted_by = undefined;
    }
    behaviortreeentity.favoriteenemy = closestenemy;
    if(isDefined(behaviortreeentity.favoriteenemy)) {
      behaviortreeentity.favoriteenemy.targeted_by = behaviortreeentity;
    }
    return true;
  }
  return false;
}

function private riotshieldunarmedadvanceonenemyservice(behaviortreeentity) {
  if(gettime() < behaviortreeentity.nextfindbestcovertime) {
    return false;
  }
  if(isDefined(behaviortreeentity.favoriteenemy)) {
    recordline(behaviortreeentity.favoriteenemy.origin, behaviortreeentity.origin, (1, 0.5, 0), "", behaviortreeentity);
    enemydistance = distancesquared(behaviortreeentity.favoriteenemy.origin, behaviortreeentity.origin);
    if(enemydistance < (behaviortreeentity.goalradius * behaviortreeentity.goalradius)) {
      behaviortreeentity useposition(behaviortreeentity.favoriteenemy.origin);
      return true;
    }
  }
  behaviortreeentity clearuseposition();
  return false;
}

function private unarmedwalkactionstart(behaviortreeentity) {
  blackboard::setblackboardattribute(behaviortreeentity, "_stance", "stand");
  behaviortreeentity orientmode("face enemy");
}

function private riotshieldkilledoverride(inflictor, attacker, damage, meansofdeath, weapon, dir, hitloc, offsettime) {
  entity = self;
  aiutility::dropriotshield(entity);
  return damage;
}

function private riotshielddamageoverride(einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex, modelindex) {
  entity = self;
  if(shitloc == "riotshield") {
    riotshieldincrementflinchcount(entity);
    entity.health = entity.health + 1;
    return 1;
  }
  if(sweapon.name == "incendiary_grenade") {
    idamage = entity.health;
  }
  return idamage;
}

#namespace humanriotshieldserverutils;

function humanriotshieldspawnsetup() {
  entity = self;
  aiutility::attachriotshield(entity, getweapon("riotshield"), "wpn_t7_shield_riot_world_lh", "tag_weapon_left");
  entity.movedelaymin = 2500;
  entity.movedelaymax = 5000;
  entity.ignorerunandgundist = 1;
  aiutility::addaioverridedamagecallback(entity, &humanriotshieldbehavior::riotshielddamageoverride);
  aiutility::addaioverridekilledcallback(entity, &humanriotshieldbehavior::riotshieldkilledoverride);
  humanriotshieldbehavior::riotshieldclearflinchcount(entity);
}