local headshots_on = 1 --set to 0 if you dont want characters to instantly die from a headshot local headshot_damage = 50 --set how much damage to apply for a headshot (if headshots are set to on/1) local lose_interest_delay = 4000 --how long before we go back to patrol state if player moves out of range/sight local max_move = 500 --how far away from the path the character can move if aggro/attacking local min_attack_range = 750 --wont move towards player if within this range local alert_range = 400 --cant see player but we can "detect" him (sneaking behind character?) local startx = {} local startz = {} function ai_on_path_init(e) ai_soldier_state[e] = "patrol" ai_soldier_pathindex[e] = -1 end function ai_on_path_main(e) EntObjNo = g_Entity[e]['obj'] -- Patrol Mode if ai_soldier_state[e] == "patrol" then CharacterControlUnarmed(e) -- Try and find a close path to patrol, just check once for it if ai_soldier_pathindex[e] == -1 then ai_soldier_pathindex[e] = -2 -- find initial waypoint path to follow PathIndex = -1; pClosest = 99999; for pa = 1, AIGetTotalPaths(), 1 do for po = 1 , AIGetPathCountPoints(pa), 1 do pDX = g_Entity[e]['x'] - AIPathGetPointX(pa,po); pDZ = g_Entity[e]['z'] - AIPathGetPointZ(pa,po); pDist = math.sqrt(math.abs(pDX*pDX)+math.abs(pDZ*pDZ)); if pDist < pClosest and pDist < 200 then pClosest = pDist; PathIndex = pa; end end -- po end -- pa -- follow found path if PathIndex > -1 then ai_soldier_pathindex[e] = PathIndex; ai_path_point_index[e] = 2 ModulateSpeed(e,1.0) SetCharacterToWalk(e) ai_path_point_direction[e] = 1 ai_path_point_max[e] = AIGetPathCountPoints(ai_soldier_pathindex[e]) end -- If we have a path then lets patrol it elseif ai_soldier_pathindex[e] > -1 then ai_patrol_x[e] = AIPathGetPointX(ai_soldier_pathindex[e],ai_path_point_index[e]) ai_patrol_z[e] = AIPathGetPointZ(ai_soldier_pathindex[e],ai_path_point_index[e]) AIEntityGoToPosition(EntObjNo,ai_patrol_x[e],ai_patrol_z[e]) tDistX = g_Entity[e]['x'] - ai_patrol_x[e] tDistZ = g_Entity[e]['z'] - ai_patrol_z[e] DistFromPath = math.sqrt(math.abs(tDistX*tDistX)+math.abs(tDistZ*tDistZ)) if DistFromPath < 50 then if ai_path_point_direction[e] == 1 then ai_path_point_index[e] = ai_path_point_index[e] + 1 if ( ai_path_point_index[e] > ai_path_point_max[e] ) then ai_path_point_index[e] = ai_path_point_max[e] -1 ai_path_point_direction[e] = 0 end else ai_path_point_index[e] = ai_path_point_index[e] - 1 if ( ai_path_point_index[e] < 1 ) then ai_path_point_index[e] = 2 ai_path_point_direction[e] = 1 end end end else CharacterControlFidget(e) end if (g_Entity[e]['plrvisible'] == 1 and GetPlayerDistance(e) < 1500+max_move) or AIGetEntityHeardSound(EntObjNo) == 1 or GetPlayerDistance(e) < alert_range then AIEntityGoToPosition(EntObjNo,g_Entity[e]['x'],g_Entity[e]['z']) startx[e] = g_Entity[e]['x'] startz[e] = g_Entity[e]['z'] StartTimer(e) ai_soldier_state[e] = "attack" end elseif ai_soldier_state[e] == "attack" then CharacterControlArmed(e) RotateToPlayer(e) if (GetPlayerDistance(e) > min_attack_range or g_Entity[e]['plrvisible'] == 0) and GetDistanceToPoint(e,startx[e],startz[e]) < max_move then AIEntityGoToPosition(EntObjNo,g_PlayerPosX,g_PlayerPosZ) else AIEntityGoToPosition(EntObjNo,g_Entity[e]['x'],g_Entity[e]['z']) end if g_Entity[e]['plrvisible'] == 1 and GetPlayerDistance(e) < 1500 then StartTimer(e) FireWeapon(e) else if GetTimer(e) > lose_interest_delay then ai_soldier_state[e] = "patrol" end end end --state if headshots_on == 1 then if ai_soldier_state[e] ~= "deathanim" then if string.find(string.lower(g_Entity[e]['limbhit']), "head") ~= nil then ai_soldier_state[e] = "deathanim" PlayCharacterSound(e,"onDeath") StartTimer(e) CharacterControlLimbo(e) BulletRayDX = g_Entity[e]['x'] - g_PlayerPosX; BulletRayDY = g_Entity[e]['y'] - g_PlayerPosY; BulletRayDZ = g_Entity[e]['z'] - g_PlayerPosZ; BulletAngle = (math.atan2(BulletRayDX,BulletRayDZ)/6.28)*360 BulletAngle = BulletAngle + g_Entity[e]['angley'] if BulletAngle < 0 then BulletAngle = BulletAngle + 360 end if BulletAngle >= 360 then BulletAngle = BulletAngle - 360 end if BulletAngle >= 360 then BulletAngle = BulletAngle - 360 end if BulletAngle >= 360-45 or BulletAngle <= 0+45 then SetAnimationFrames(5031,5050) SetAnimationFrame(e,5031) end if BulletAngle >= 180-45 and BulletAngle <= 180+45 then SetAnimationFrames(4972,5002) SetAnimationFrame(e,4972) end if BulletAngle >= 90-45 and BulletAngle <= 90+45 then -- side hit animations not aligned for this technique (yet) SetAnimationFrames(4972,5002) SetAnimationFrame(e,4972) end if BulletAngle >= 270-45 and BulletAngle <= 270+45 then -- side hit animations not aligned for this technique (yet) SetAnimationFrames(4972,5002) SetAnimationFrame(e,4972) end PlayAnimation(e) ModulateSpeed(e,1.0) SetAnimationSpeed(e,1.5) end else --DeathAnim Else -- wait until death anim mostly over, then switch to ragdoll if GetTimer(e)>200 then SetEntityHealth(e,g_Entity[e]['health']-headshot_damage) BulletRayDX = g_Entity[e]['x'] - g_PlayerPosX; BulletRayDY = g_Entity[e]['y'] - g_PlayerPosY; BulletRayDZ = g_Entity[e]['z'] - g_PlayerPosZ; SetEntityRagdollForce(e,g_Entity[e]['limbhitindex'],BulletRayDX,BulletRayDY,BulletRayDZ,750) ResetLimbHit(e) end end --DeathAnim Endif end end --main function ai_on_path_exit(e) if ai_soldier_state[e] ~= "deathanim" then PlayCharacterSound(e,"onDeath") end end function GetDistanceToPoint(e,x,z) if g_Entity[e] ~= nil and g_Entity[e] ~= 0 then local disx = g_Entity[e]['x'] - x local disz = g_Entity[e]['z'] - z return math.sqrt(disx^2 + disz^2) end end