Cowardly Ships
From FreeSpace Wiki
I found a need to have ships evade their attackers rather than fly on without responding to incoming fire. Probably an edge case! Could be useful for making escape pods harder to shoot down (or conversely easier to escort?)
NOTE: I need to fix this by removing the for-loop searches for the ship name and replace with mn.Ships[NAME] & isValid() check (where it doesn't already exist).
#Conditional Hooks
$Application: FS2_Open
$On Game Init:
[
OD = {}
function OD:Init()
--[[
allow sexps to set order state; i.e. evade to start with
if ship has state set; and was hit/attacked
set goal (e.g. ai-evade-ship its attacker)
after goal Duration has elapsed, remove goal
]]--
self.ShipList = {}
self.Duration = 9
self.CheckInterval = 1
self.LastRun = 0
self.addKey = "9"
self.delKey = "0"
self.DEBUG = true
end
function OD:wasAttacked(ship,weapon)
if ship:isValid() then
local numShips = #self.ShipList
for i=1, numShips do
if ship.Name == self.ShipList[i].Name then
curTime = mn.getMissionTime()
if self.ShipList[i].Time < curTime then
self.ShipList[i].Time = curTime + OD.Duration
if self.DEBUG then
local numOrders = #ship.Orders
for i=1, numOrders do
ba.warning(tostring(ship.Orders[i]:getType()))
ba.warning(ship.Orders[i].Priority)
end
end
if weapon.Parent:isValid() then
ship:giveOrder(ORDER_EVADE,weapon.Parent,nil,1.0)
end
end
end
end
end
end
function OD:evalRemove()
now = mn.getMissionTime()
if self.LastRun + self.CheckInterval < now then
self.LastRun = now
local numShips = #self.ShipList
for i=1, numShips do
if self.ShipList[i].Time < now then
OD:removeOrder(self.ShipList[i])
end
end
end
end
function OD:removeOrder(item)
local ship = mn.getObjectFromSignature(item.sig)
if not ship:isValid() then return end
if not ship.Orders:isValid() then return end
local numOrders = #ship.Orders
for i=1, numOrders do
if tostring(ship.Orders[i]:getType()) == item.Order then
ship.Orders[i]:remove()
end
end
end
function OD:as(shipname,order)
-- addShip to ShipList
local allships = #mn.Ships
for i=1, allships do
if mn.Ships[i].Name == shipname then
local tmp = {}
tmp.Name = mn.Ships[i].Name
tmp.sig = mn.Ships[i]:getSignature()
tmp.Time = 0
tmp.Order = OD:OrderLookup(order)
self.ShipList[#self.ShipList+1] = tmp
break
end
end
if self.DEBUG then ba.warning('ran OD:as') end
end
function OD:ds(shipname,order)
-- deleteShip from ShipList
-- also remove the order if its active
local ships = #self.ShipList
for i=1, ships do
if self.ShipList[i].Name == shipname then
if self.ShipList[i].Order == OD:OrderLookup(order) then
OD:removeOrder(self.ShipList[i])
table.remove(self.ShipList,i)
break
end
end
end
if self.DEBUG then ba.warning('ran OD:ds') end
end
function OD:OrderLookup(order)
if order == 'evade' then
return 'ORDER_EVADE'
else
return 'UNKNOWN'
end
end
]
$On Gameplay Start:
[
OD:Init()
]
$Object Type: Weapon
$On Ship Collision:
[
-- do not treat ramming as an attack
OD:wasAttacked(hv.Object,hv.Weapon)
]
$State: GS_STATE_GAME_PLAY
$On Key Released:
[
if OD.DEBUG then
local shipname = "Glich" -- testing only
local order = 'evade'
if hv.Key == OD.addKey then
OD:as(shipname,order)
elseif hv.Key == OD.delKey then
OD:ds(shipname,order)
end
end
]
$State: GS_STATE_GAME_PLAY
$On Frame:
[
OD:evalRemove()
]
#End