Cowardly Ships

From FreeSpace Wiki
Jump to: navigation, search

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