team = {} local nearest_enemy_dist = {} local target_enemy = {} local attack_range = 1000 local attack_delay = 1200 local attack_damage = 25 local shout_range = 900 local direction = {} local bullets = {} local max_bullets = {} local reload_time = {} local pos_x = {} local pos_z = {} local new_y = {} shouting = 0 function team_ai_init_name(e,name) team[e] = name ai_soldier_state[e] = "patrol" ai_soldier_pathindex[e] = -1 max_enemies = e if first_enemy == nil then first_enemy = e team["player"] = name end max_bullets[e] = 8 bullets[e] = max_bullets[e] reload_time[e] = 1500 direction[e] = 0 end function team_ai_main(e) if ai_soldier_state[e] == "patrol" then pos_x[e] = g_Entity[e]['x'] pos_z[e] = g_Entity[e]['z'] -- 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 CharacterControlArmed(e) -- 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]) CharacterControlUnarmed(e) SetCharacterToWalk(e) AIEntityGoToPosition(g_Entity[e]['obj'],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 AIEntityStop(g_Entity[e]['obj']) CharacterControlFidget(e) end nearest_enemy_dist[e] = attack_range target_enemy[e] = nil for a = first_enemy, max_enemies do if g_Entity[a] ~= nil then if team[a] ~= nil then if team[a] ~= team[e] then if GetDistance(e,a) < nearest_enemy_dist[e] then if g_Entity[a]['health'] > 0 then if AICouldSee(g_Entity[e]['obj'],g_Entity[a]['x'],g_Entity[a]['y'],g_Entity[a]['z']) == 1 then nearest_enemy_dist[e] = GetDistance(e,a) target_enemy[e] = a end end end end end end end if team[e] ~= team["player"] then if GetPlayerDistance(e) < nearest_enemy_dist[e] then if AICouldSee(g_Entity[e]['obj'],g_PlayerPosX,g_PlayerPosY,g_PlayerPosZ) == 1 then nearest_enemy_dist[e] = GetPlayerDistance(e) target_enemy[e] = "player" end end end if g_KeyPressE == 1 then if team[e] == team["player"] then if shouting < 10 then shouting = shouting + 1 PromptDuration("Guys, Help over here!",2000) if GetPlayerDistance(e) < shout_range then PromptLocal(e,"yes sir") nearest_enemy_dist[e] = attack_range for a = first_enemy, max_enemies do if g_Entity[a] ~= nil then if team[a] ~= nil then if team[a] ~= team[e] then if GetPlayerDistance(a) < nearest_enemy_dist[e] then if g_Entity[a]['health'] > 0 then if AICouldSee(g_Entity[e]['obj'],g_Entity[a]['x'],g_Entity[a]['y'],g_Entity[a]['z']) == 1 then nearest_enemy_dist[e] = GetDistance(e,a) target_enemy[e] = a end end end end end end end end else if target_enemy[e] == nil then ai_soldier_state[e] = "toplayer" end end end else shouting = 0 end if target_enemy[e] ~= nil then StartTimer(e) ai_soldier_state[e] = "move" return end elseif ai_soldier_state[e] == "move" then direction[e] = math.random(0,1) if target_enemy[e] ~= "player" then if GetDistance(e,target_enemy[e]) < attack_range then ai_soldier_state[e] = "attack" else SetCharacterToRun(e) AIEntityGoToPosition(g_Entity[e]['obj'],g_Entity[target_enemy[e]]['x'],g_Entity[target_enemy[e]]['z']) end else if GetPlayerDistance(e) < attack_range then ai_soldier_state[e] = "attack" else SetCharacterToRun(e) AIEntityGoToPosition(g_Entity[e]['obj'],g_PlayerPosX,g_PlayerPosZ) end end elseif ai_soldier_state[e] == "attack" then SetCharacterToRun(e) if target_enemy[e] ~= "player" then if GetDistance(e,target_enemy[e]) < attack_range then --AIEntityStop(g_Entity[e]['obj']) if GetDistanceToPoint(e,pos_x[e],pos_z[e]) < 200 then RotateToPoint(e,g_Entity[target_enemy[e]]['x'],g_Entity[target_enemy[e]]['z']) end if GetDistanceToPoint(e,pos_x[e],pos_z[e]) < 100 then if direction[e] == 1 then pos_mod = -attack_range/2 new_y[e] = math.random(-15,15)+AngleToPoint(e,g_Entity[target_enemy[e]]['x'],g_Entity[target_enemy[e]]['z']) pos_x[e] = g_Entity[target_enemy[e]]['x'] + (math.sin(new_y[e]) * pos_mod) pos_z[e] = g_Entity[target_enemy[e]]['z'] + (math.cos(new_y[e]) * pos_mod) else pos_mod = attack_range/2 new_y[e] = math.random(-15,15)+AngleToPoint(e,g_Entity[target_enemy[e]]['x'],g_Entity[target_enemy[e]]['z']) pos_x[e] = g_Entity[target_enemy[e]]['x'] + (math.sin(new_y[e]) * pos_mod) pos_z[e] = g_Entity[target_enemy[e]]['z'] + (math.cos(new_y[e]) * pos_mod) end else AIEntityGoToPosition(g_Entity[e]['obj'],pos_x[e],pos_z[e]) end if GetTimer(e) > attack_delay then if EntityLooking(e,target_enemy[e],attack_range,35) == 1 and AICouldSee(g_Entity[e]['obj'],g_Entity[target_enemy[e]]['x'],g_Entity[target_enemy[e]]['y'],g_Entity[target_enemy[e]]['z']) == 1 then StartTimer(e) PlaySound(e,1) SetEntityHealth(target_enemy[e],g_Entity[target_enemy[e]]['health']-attack_damage) bullets[e] = bullets[e] - 1 end end else ai_soldier_state[e] = "move" end else if GetPlayerDistance(e) < attack_range then --AIEntityStop(g_Entity[e]['obj']) if GetDistanceToPoint(e,pos_x[e],pos_z[e]) < 200 then RotateToPoint(e,g_PlayerPosX,g_PlayerPosZ) end if GetDistanceToPoint(e,pos_x[e],pos_z[e]) < 100 then if direction[e] == 1 then pos_mod = -attack_range/2 new_y[e] = math.random(-15,15)+AngleToPoint(e,g_PlayerPosX,g_PlayerPosZ) pos_x[e] = g_PlayerPosX + (math.sin(new_y[e]) * pos_mod) pos_z[e] = g_PlayerPosZ + (math.cos(new_y[e]) * pos_mod) else pos_mod = attack_range/2 new_y[e] = math.random(-15,15)+AngleToPoint(e,g_PlayerPosX,g_PlayerPosZ) pos_x[e] = g_PlayerPosX + (math.sin(new_y[e]) * pos_mod) pos_z[e] = g_PlayerPosZ + (math.cos(new_y[e]) * pos_mod) end else AIEntityGoToPosition(g_Entity[e]['obj'],pos_x[e],pos_z[e]) end if GetTimer(e) > attack_delay then if EntityLookingAtPlayer(e,attack_range,35) == 1 and AICouldSee(g_Entity[e]['obj'],g_PlayerPosX,g_PlayerPosY,g_PlayerPosZ) == 1 then StartTimer(e) PlaySound(e,1) HurtPlayer(e,attack_damage) bullets[e] = bullets[e] - 1 end end else ai_soldier_state[e] = "move" end end elseif ai_soldier_state[e] == "toplayer" then if GetPlayerDistance(e) > 100 then SetCharacterToRun(e) AIEntityGoToPosition(g_Entity[e]['obj'],g_PlayerPosX,g_PlayerPosZ) else ai_soldier_state[e] = "patrol" end end --state ----- if target_enemy[e] ~= nil then if target_enemy[e] ~= "player" then if g_Entity[target_enemy[e]] == nil or g_Entity[target_enemy[e]]['health'] < 1 or GetTimer(e) > attack_delay * 6 then StartTimer(e) target_enemy[e] = nil AIEntityStop(g_Entity[e]['obj']) ai_soldier_state[e] = "patrol" end else if g_PlayerHealth < 1 or GetTimer(e) > attack_delay * 6 then StartTimer(e) target_enemy[e] = nil AIEntityStop(g_Entity[e]['obj']) ai_soldier_state[e] = "patrol" end end end if bullets[e] < 1 then if ai_soldier_state[e] ~= "reload" then StartTimer(e) AIEntityStop(g_Entity[e]['obj']) CharacterControlLimbo(e) ai_soldier_state[e] = "reload" else if GetTimer(e) < reload_time[e] then if g_Entity[e]['animating'] == 0 then SetAnimationFrames(515,605) PlayAnimation(e) g_Entity[e]['animating'] = 1 end else StopAnimation(e) CharacterControlArmed(e) bullets[e] = max_bullets[e] StartTimer(e) target_enemy[e] = nil AIEntityStop(g_Entity[e]['obj']) ai_soldier_state[e] = "patrol" end end end end --main(e) function team_exit(e) end function RotateToEntity(e,v) if g_Entity[e] ~= nil and g_Entity[e] ~= 0 and g_Entity[v] ~= nil and g_Entity[v] ~= 0 then local x = g_Entity[v]['x'] - g_Entity[e]['x'] local z = g_Entity[v]['z'] - g_Entity[e]['z'] local angle = math.atan2(x,z) angle = angle * (180.0 / math.pi) if angle < 0 then angle = 360 + angle elseif angle > 360 then angle = angle - 360 end SetRotation(e,0,angle,0) return angle end end function PlayerAngleToPoint(x,z) local destx = x - g_PlayerPosX local destz = z - g_PlayerPosZ local angle = math.atan2(destx,destz) angle = angle * (180.0 / math.pi) if angle < 0 then angle = 360 + angle elseif angle > 360 then angle = angle - 360 end --SetRotation(e,0,angle,0) return angle end function RotateToPoint(e,x,z) if g_Entity[e] ~= nil and x > 0 and z > 0 then local destx = x - g_Entity[e]['x'] local destz = z - g_Entity[e]['z'] local angle = math.atan2(destx,destz) angle = angle * (180.0 / math.pi) if angle < 0 then angle = 360 + angle elseif angle > 360 then angle = angle - 360 end SetRotation(e,0,angle,0) return angle end end function RotateToPointSlowly(e,x,z,v) if g_Entity[e] ~= nil and x > 0 and z > 0 then if v == nil then v = 1 end local destx = x - g_Entity[e]['x'] local destz = z - g_Entity[e]['z'] local angleneeded = math.atan2(destx,destz) angleneeded = angleneeded * (180.0 / math.pi) if angleneeded < 0 then angleneeded = 360 + angleneeded elseif angleneeded > 360 then angleneeded = angleneeded - 360 end local current_angy = g_Entity[e]['angley'] while current_angy < 0 or current_angy > 360 do if current_angy <= 0 then current_angy = 360 + current_angy elseif current_angy > 360 then current_angy = current_angy - 360 end end local L = angleneeded - v local R = angleneeded + v if L <= 0 then L = 360 + L elseif L > 360 then L = L - 360 end if R <= 0 then R = 360 + R elseif R > 360 then R = R - 360 end --if not already facing the target direction (+/- the rotation speed) if current_angy < L or current_angy > R then --do it in 2 halfs so we can account for 0/360 wrap if current_angy > 180 then if angleneeded > current_angy - 180 and angleneeded < current_angy then current_angy = current_angy - v else current_angy = current_angy + v end else if angleneeded < current_angy + 180 and angleneeded > current_angy then current_angy = current_angy + v else current_angy = current_angy - v end end SetRotation(e,0,current_angy,0) return current_angy end end end function AngleToPoint(e,x,z) if g_Entity[e] ~= nil and x > 0 and z > 0 then local destx = x - g_Entity[e]['x'] local destz = z - g_Entity[e]['z'] local angle = math.atan2(destx,destz) angle = angle * (180.0 / math.pi) if angle < 0 then angle = 360 + angle elseif angle > 360 then angle = angle - 360 end --SetRotation(e,0,angle,0) return angle end end function GetDistance(e,v) if g_Entity[e] ~= nil and g_Entity[e] ~= 0 and g_Entity[v] ~= nil and g_Entity[v] ~= 0 then local disx = g_Entity[e]['x'] - g_Entity[v]['x'] local disz = g_Entity[e]['z'] - g_Entity[v]['z'] local disy = g_Entity[e]['y'] - g_Entity[v]['y'] return math.sqrt(disx^2 + disz^2 + disy^2) 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 function PlayerDistanceToPoint(x,z) local disx = g_PlayerPosX - x local disz = g_PlayerPosZ - z return math.sqrt(disx^2 + disz^2) end function GetFlatDistance(e,v) if g_Entity[e] ~= nil and g_Entity[v] ~= nil then local distDX = g_Entity[e]['x'] - g_Entity[v]['x'] local distDZ = g_Entity[e]['z'] - g_Entity[v]['z'] return math.sqrt((distDX*distDX)+(distDZ*distDZ)); end end function GetPlayerDistance(e) tPlayerDX = (g_Entity[e]['x'] - g_PlayerPosX) tPlayerDY = (g_Entity[e]['y'] - g_PlayerPosY) tPlayerDZ = (g_Entity[e]['z'] - g_PlayerPosZ) if math.abs(tPlayerDY) > 100 then tPlayerDY = tPlayerDY * 4 end return math.sqrt(math.abs(tPlayerDX*tPlayerDX)+math.abs(tPlayerDY*tPlayerDY)+math.abs(tPlayerDZ*tPlayerDZ)); end function GetPlayerFlatDistance(e) tPlayerDX = (g_Entity[e]['x'] - g_PlayerPosX) tPlayerDZ = (g_Entity[e]['z'] - g_PlayerPosZ) return math.sqrt(math.abs(tPlayerDX*tPlayerDX)+math.abs(tPlayerDZ*tPlayerDZ)); end function PlayerLooking(e,dis,v) if g_Entity[e] ~= nil then if dis == nil then dis = 3000 end if v == nil then v = 0.5 end if GetPlayerDistance(e) <= dis then local destx = g_Entity[e]['x'] - g_PlayerPosX local destz = g_Entity[e]['z'] - g_PlayerPosZ local angle = math.atan2(destx,destz) angle = angle * (180.0 / math.pi) if angle <= 0 then angle = 360 + angle elseif angle > 360 then angle = angle - 360 end while g_PlayerAngY < 0 or g_PlayerAngY > 360 do if g_PlayerAngY <= 0 then g_PlayerAngY = 360 + g_PlayerAngY elseif g_PlayerAngY > 360 then g_PlayerAngY = g_PlayerAngY - 360 end end local L = angle - v local R = angle + v if L <= 0 then L = 360 + L elseif L > 360 then L = L - 360 end if R <= 0 then R = 360 + R elseif R > 360 then R = R - 360 end if (L < R and math.abs(g_PlayerAngY) > L and math.abs(g_PlayerAngY) < R) then return 1 elseif (L > R and (math.abs(g_PlayerAngY) > L or math.abs(g_PlayerAngY) < R)) then return 1 else return 0 end else return 0 end end end function EntityLooking(e,t,dis,v) if g_Entity[e] ~= nil and g_Entity[t] ~= nil then if dis == nil then dis = 3000 end if v == nil then v = 0.5 end local destx = g_Entity[t]['x'] - g_Entity[e]['x'] local destz = g_Entity[t]['z'] - g_Entity[e]['z'] if math.sqrt((destx*destx)+(destz*destz)) <= dis then local angle = math.atan2(destx,destz) angle = angle * (180.0 / math.pi) if angle <= 0 then angle = 360 + angle elseif angle > 360 then angle = angle - 360 end while g_Entity[e]['angley'] < 0 or g_Entity[e]['angley'] > 360 do if g_Entity[e]['angley'] <= 0 then g_Entity[e]['angley'] = 360 + g_Entity[e]['angley'] elseif g_Entity[e]['angley'] > 360 then g_Entity[e]['angley'] = g_Entity[e]['angley'] - 360 end end local L = angle - v local R = angle + v if L <= 0 then L = 360 + L elseif L > 360 then L = L - 360 end if R <= 0 then R = 360 + R elseif R > 360 then R = R - 360 end if (L < R and math.abs(g_Entity[e]['angley']) > L and math.abs(g_Entity[e]['angley']) < R) then return 1 elseif (L > R and (math.abs(g_Entity[e]['angley']) > L or math.abs(g_Entity[e]['angley']) < R)) then return 1 else return 0 end else return 0 end end end function EntityLookingAtPlayer(e,dis,v) if g_Entity[e] ~= nil then if dis == nil then dis = 3000 end if v == nil then v = 0.5 end local destx = g_PlayerPosX - g_Entity[e]['x'] local destz = g_PlayerPosZ - g_Entity[e]['z'] if math.sqrt((destx*destx)+(destz*destz)) <= dis then local angle = math.atan2(destx,destz) angle = angle * (180.0 / math.pi) if angle <= 0 then angle = 360 + angle elseif angle > 360 then angle = angle - 360 end while g_Entity[e]['angley'] < 0 or g_Entity[e]['angley'] > 360 do if g_Entity[e]['angley'] <= 0 then g_Entity[e]['angley'] = 360 + g_Entity[e]['angley'] elseif g_Entity[e]['angley'] > 360 then g_Entity[e]['angley'] = g_Entity[e]['angley'] - 360 end end local L = angle - v local R = angle + v if L <= 0 then L = 360 + L elseif L > 360 then L = L - 360 end if R <= 0 then R = 360 + R elseif R > 360 then R = R - 360 end if (L < R and math.abs(g_Entity[e]['angley']) > L and math.abs(g_Entity[e]['angley']) < R) then return 1 elseif (L > R and (math.abs(g_Entity[e]['angley']) > L or math.abs(g_Entity[e]['angley']) < R)) then return 1 else return 0 end else return 0 end end end