require('scriptbank/ai_soldier') local ai = {} g_name = {} state = {} forward_speed = {} local grenades = {} local max_grenades = {} local thrown = {} grenade = {} --max range at which we can throw a grenade from (will swap to gun if player comes within 33% of this so we are less likely to blow ourselves up) throw_range = 800 --time until we can throw another grenade (for animation and so we dont throw them all at once) local throw_delay = 1100 --range grenade will travel before it blows up (if it misses) *& also grenade speed can effect when it will blow up* max_distance = throw_range * 1.25 bounce_speed = {} local set = {} function ai_grenade_init_name(e,name) g_name[e] = name state[e] = "wait" grenades[e] = 0 thrown[e] = 0 ai_soldier_init(e) ai[e] = {} CharacterControlManual(e) ai_soldier_pathindex[e] = -1 end function ai_grenade_main(e) --find and assign grenades if set[e] == nil then set[e] = -1 return elseif set[e] == -1 then for a = 1,9999 do if g_Entity[a] ~= nil and a ~= e then if g_name[a] ~= nil then if g_name[a] == "grenade"..g_name[e] then --if GetDistance(e,a) < 80 then grenades[e] = grenades[e] + 1 ai[e][grenades[e]] = a --ai[grenades[e]] = a grenade[a] = e max_grenades[e] = grenades[e] set[e] = 1 --end end end end end set[e] = 0 else EntObjNo = g_Entity[e]['obj']; --patrol state - follow waypoints or stand guard if state[e] == "wait" then -- 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) ai_path_point_direction[e] = 1 ai_path_point_max[e] = AIGetPathCountPoints(ai_soldier_pathindex[e]) end end -- If set to head home, lets go there if ai_returning_home[e] == 1 then tDistX = g_Entity[e]['x'] - ai_start_x[e]; tDistZ = g_Entity[e]['z'] - ai_start_z[e]; DistToStart = math.sqrt(math.abs(tDistX*tDistX)+math.abs(tDistZ*tDistZ)) if DistToStart < 200 or GetTimer(e) > ai_combat_state_delay[e] then ai_soldier_pathindex[e] = -1 AIEntityStop(EntObjNo); ModulateSpeed(e,1.0) ai_returning_home[e] = 0 ai_soldier_state[e] = "alerted" ai_alerted_mode[e] = 0 else AIEntityGoToPosition(EntObjNo,ai_start_x[e],ai_start_z[e]) if g_Entity[e]['animating'] ~= 2 then SetAnimation(1) LoopAnimation(e) g_Entity[e]['animating'] = 2 end MoveForward(e,AIGetEntitySpeed(g_Entity[e]['obj'])) SetRotation(e,0,AIGetEntityAngleY(g_Entity[e]['obj']),0) AISetEntityPosition(g_Entity[e]['obj'],GetEntityPositionX(e),GetEntityPositionY(e),GetEntityPositionZ(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]) if g_Entity[e]['animating'] ~= 2 then SetAnimation(1) LoopAnimation(e) g_Entity[e]['animating'] = 2 end MoveForward(e,AIGetEntitySpeed(g_Entity[e]['obj'])) SetRotation(e,0,AIGetEntityAngleY(g_Entity[e]['obj']),0) AISetEntityPosition(g_Entity[e]['obj'],GetEntityPositionX(e),GetEntityPositionY(e),GetEntityPositionZ(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 if g_Entity[e]['animating'] == 0 then SetAnimation(0) PlayAnimation(e) g_Entity[e]['animating'] = 1 end end --player detected if g_Entity[e]['plrvisible'] == 1 or AIGetEntityHeardSound(EntObjNo) == 1 then state[e] = "alert" AIEntityGoToPosition(g_Entity[e]['obj'],g_Entity[e]['x'],g_Entity[e]['z']) AIEntityStop(e) end --combat state elseif state[e] == "alert" then --player too close, stop throwing grenades and use gun if GetPlayerDistance(e) < throw_range / 3 then StopAnimation(e) SwitchScript(e,"ai_soldier") else --player in throw range if GetPlayerDistance(e) < throw_range then --we can see the player so stop moving if g_Entity[e]['plrvisible'] == 1 then AIEntityGoToPosition(g_Entity[e]['obj'],g_Entity[e]['x'],g_Entity[e]['z']) AIEntityStop(e) RotateToPlayer(e) --throw grenade if we have 1 and havent thrown one recently if GetTimer(e) > throw_delay then if thrown[e] == 0 then if grenades[e] > 0 then SetAnimationFrames(2390,2444) PlayAnimation(e) g_Entity[e]['animating'] = 9 if ai[e][grenades[e]] ~= nil then PlaySoundIfSilent(ai[e][grenades[e]],0) SetPosition(ai[e][grenades[e]],g_Entity[e]['x'],g_Entity[e]['y']+60,g_Entity[e]['z']) --update grenade state so it can run it's script state[ai[e][grenades[e]]] = "thrown" -- end grenades[e] = grenades[e] - 1 thrown[e] = 1 --no grenades so swap to gun else SwitchScript(e,"ai_soldier") end else thrown[e] = 0 end StartTimer(e) end --cant see player so lets move closer to try find him else AIEntityGoToPosition(g_Entity[e]['obj'],g_PlayerPosX,g_PlayerPosZ) if g_Entity[e]['animating'] ~= 3 then SetAnimation(1) LoopAnimation(e) g_Entity[e]['animating'] = 3 end MoveForward(e,AIGetEntitySpeed(g_Entity[e]['obj'])) SetRotation(e,0,AIGetEntityAngleY(g_Entity[e]['obj']),0) AISetEntityPosition(g_Entity[e]['obj'],GetEntityPositionX(e),GetEntityPositionY(e),GetEntityPositionZ(e)) end --player not in throw range so lets move closer else if GetPlayerDistance(e) > throw_range and g_Entity[e]['animating'] ~= 9 then LookAtPlayer(e) AIEntityGoToPosition(g_Entity[e]['obj'],g_PlayerPosX,g_PlayerPosZ) if g_Entity[e]['animating'] ~= 3 then SetAnimation(1) LoopAnimation(e) g_Entity[e]['animating'] = 3 end MoveForward(e,AIGetEntitySpeed(g_Entity[e]['obj'])) SetRotation(e,0,AIGetEntityAngleY(g_Entity[e]['obj']),0) AISetEntityPosition(g_Entity[e]['obj'],GetEntityPositionX(e),GetEntityPositionY(e),GetEntityPositionZ(e)) end end end --player dead or far out of range so lets go back to patrol if g_PlayerHealth < 1 or GetPlayerDistance(e) > throw_range * 2.5 then AIEntityGoToPosition(g_Entity[e]['obj'],g_Entity[e]['x'],g_Entity[e]['z']) AIEntityStop(e) state[e] = "wait" end end --state end --ai set --Prompt(grenades[2].." "..grenades[4].." "..grenades[6].." "..grenades[8]) end --main function ai_grenade_exit(e) end