--cover script by smallg --change (increase) values here to make the enemies move further when moving around cover (when player is flanking) local xoffset = 80 local zoffset = 80 local state = {} local nearest_cover = {} local cover = {} local health = {} local character_stood = {} local destx = {} local destz = {} function ai_init(e) CharacterControlUnarmed(e) state[e] = "alert" nearest_cover[e] = 9999 cover[e] = -1 health[e] = 0 character_stood[e] = 1 destx[e] = 0 destz[e] = 0 end function ai_main(e) local ent = g_Entity[e]['obj'] if state[e] == "find_cover" then --cycle through all available cover and find nearest 1 (except one already at so if we get hit we can find new cover) for a = 1, 2999 do if cover_true[a] == 1 then --range within which to ignore cover (so we actually move) if GetDistance(e,a) > 150 then --check new cover is closer then others if GetDistance(e,a) < nearest_cover[e] then --first run this will be -1 as we dont have any current cover so need this to stop entity error if cover[e] ~= -1 then --this checks for player position (so we wont move closer to the player - hopefully making us harder targets while moving) if GetPlayerDistance(a) > GetPlayerDistance(cover[e]) then --we have found new cover so update the nearest distance nearest_cover[e] = GetDistance(e,a) --set the entity number of the cover cover[e] = a CharacterControlStand(e) SetCharacterToRun(e) end else nearest_cover[e] = GetDistance(e,a) cover[e] = a end end end end end destx[e] = coverx[cover[e]] destz[e] = coverz[cover[e]] --move the enemy to the new cover AIEntityGoToPosition(ent,destx[e],destz[e]) state[e] = "moving to new cover" elseif state[e] == "moving to new cover" then --range at which we are in cover and can start checking for combat / damage if GetDistance(e,cover[e]) <= 250 then nearest_cover[e] = 9999 state[e] = "combat" --store our current health so we can detect any damage taken while in this cover health[e] = g_Entity[e]['health'] end --inital state (currently only rotates to face player and moves to cover when we can see the player) elseif state[e] == "alert" then CharacterControlArmed(e) SetCharacterToRun(e) RotateToPlayerSlowly(e,4) if g_Entity[e]['plrvisible'] == 1 then state[e] = "find_cover" end elseif state[e] == "combat" then --check player position again and update as needed (so we can try stay on the correct side of the cover if he flanks us) if g_PlayerPosX < coverx[cover[e]] and g_Entity[e]['x'] < coverx[cover[e]] then destx[e] = coverx[cover[e]] + xoffset elseif g_PlayerPosX > coverx[cover[e]] and g_Entity[e]['x'] > coverx[cover[e]] then destx[e] = coverx[cover[e]] - xoffset end if g_PlayerPosZ < coverz[cover[e]] and g_Entity[e]['z'] < coverz[cover[e]] then destz[e] = coverz[cover[e]] + zoffset elseif g_PlayerPosZ > coverz[cover[e]] and g_Entity[e]['z'] > coverz[cover[e]] then destz[e] = coverz[cover[e]] - zoffset end AIEntityGoToPosition(ent,destx[e],destz[e]) --look at and fire at the player LookAtPlayer(e) FireWeapon(e) --if we can duck and still see the player we will do so (for better cover) if character_stood[e] == 1 then CharacterControlDucked(e) character_stood[e] = 0 end --if we cant see the player try standing up if g_Entity[e]['plrvisible'] == 0 then if character_stood[e] == 0 then CharacterControlStand(e) character_stood[e] = 1 --if still cant see the player then we'll go back to alert state -- assumes player moved out of range else state[e] = "alert" end end --if we are hit while in cover we should try move to new cover if g_Entity[e]['health'] < health[e] then state[e] = "find_cover" end end Prompt(state[e]) end --main --function called by script to compare 2 entity distances 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