Get SaintAxe&Ror SpeechMaker Now
And build your conversations easily !
 
Using OFDR Mission Editor - How-To
 

This is a page that displays some short How-To to help using OFDR Mission Editor for basic mission editing.
These How-To are not the "best way" or are not endorsed by CodeMasters in any way. They are just the result of the long time I spent coding a lot of Single Player / Coop missions with simple and complex scripting (+ 115) .

Link : Official LUA Documentation

 
 
Back to summary
 

HOWTO 4 : Random Spawning

This is a very simple mission that shows you how to spawn an entityset at a random location.

The scenario is :
A random amount of PLA is set at the begining of the mission. The player must kill the PLA unit that is spawned at a variable location. When all are killed, the objective is completed. End of the story.

Here is the complete level.lua :

-- -------------------------------------------------------- --
--    __       _       _     _              __              --
--   / _\ __ _(_)_ __ | |_  /_\ __  _____  /__\ ___  _ __   --
--   \ \ / _` | | '_ \| __|//_\\\ \/ / _ \/ \/// _ \| '__|  --
--   _\ \ (_| | | | | | |_/  _  \>  <  __/ _  \ (_) | |     --
--   \__/\__,_|_|_| |_|\__\_/ \_/_/\_\___\/ \_/\___/|_|     --
--                                                          --
-- -------------------------------------------------------- --


-- OFP Dragon Rising
-- HOWTO 4 : Random Spawning
-- Author : Thierry Godin (SaintAxe&Ror)
-- Web : http://sar.n1bus.eu
-- Date de creation : 06/01/2012

function onMissionStart()
math.randomseed(os.time())

curUnit = ""
nbKilled = 0
tabStance = {"ESTANDING", "ECROUCHING", "EPRONE"}
curWp = ""
groupWp = "grpSpawnWp"
	
	OFP:displaySystemMessage("HOWTO 4 : Random Spawning 1.0.0")
	OFP:displaySystemMessage("Thanks for playing SaintAxe&Ror mission")
	OFP:displaySystemMessage("Other stuff here = http://sar.n1bus.eu")
	OFP:displaySystemMessage("Have fun !")  
	
	OFP:setObjectiveState("objKillEmAll", "IN_PROGRESS")
	OFP:setObjectiveVisibility("objKillEmAll", true)
	
	OFP:setInvulnerable("echSAR", true)	
	
	nbToKill = math.random(5, 10)
	OFP:displaySystemMessage("Kill " .. nbToKill .. " PLA to complete the objective")
	OFP:addTimer("timerSpawn", 5000)
end

-- ---------------------------------------------------------------
-- SPAWN
-- ---------------------------------------------------------------
function onTimer_timerSpawn()
	if nbKilled ~= nbToKill then
	
		local maxWp = OFP:getGroupSize(groupWp)
		
		local grpNb = maxWp - 1
		local grpIndex = math.random(0, grpNb)
	
		local spawnWp = OFP:getGroupMember(groupWp, grpIndex)
		
		if spawnWp ~= curWp then
			local x, y, z = OFP:getPosition(spawnWp)
			spawnUnitID = OFP:spawnEntitySetAtLocation("enemySet", x, y, z)
			curWp =  spawnWp
		else
			OFP:setTimer("timerSpawn", 200)
		end
	end
end

function onSpawnedReady( setName, setID, tableOfEntities, errorCode )
	if setID == spawnUnitID then
		for i = 1, #tableOfEntities do
			if OFP:isUnit(tableOfEntities[i]) then
				curUnit = tableOfEntities[i]
				
				local y = math.random(1, #tabStance)
				OFP:setStance(curUnit, tabStance[y], "ADDTOEND")
				OFP:setMood(curUnit, "EMoodCautious", "ADDTOEND")
			
				OFP:displaySystemMessage("Unit Spawned : " .. curUnit .. " / " .. tabStance[y])
			end
		end
	end
end
-- -------------------------------

-- ---------------------------------------------------------------
-- KILL
-- ---------------------------------------------------------------
function onDeath(victim, killer)
	if victim == curUnit then 
		nbKilled = nbKilled + 1
		local str = "You killed : " .. victim .. " (" .. nbKilled .. "/" .. nbToKill .. ")"
		OFP:displaySystemMessage(str)
		
		if nbKilled ~= nbToKill then
			OFP:setTimer("timerSpawn", 200)
		else
			OFP:removeTimer("timerSpawn")
			OFP:setObjectiveState("objKillEmAll", "COMPLETED")
			OFP:displaySystemMessage("Congrats ! You killed : " .. nbKilled .. " units")
			OFP:addTimer("timerEnd", 8000)
		end
	end
end
-- -------------------------------


function onTimer_timerEnd()
	if OFP:getObjectiveState("objKillEmAll") == "COMPLETED"	then
		OFP:missionCompleted()
	else
		OFP:missionFailed()
	end
end

function onAllPlayersDead()
	OFP:missionFailedKIA();
end
 



1. Preparing the mission :
In the onMissionStart() event, we initialize the randomization function with

math.randomseed(os.time())  -- initialize the randomization function
 


Then, we set several variables :

curUnit = ""  -- this is the current name of the spawned unit
nbKilled = 0  -- this is the number of PLA unit we have killed
tabStance = {"ESTANDING", "ECROUCHING", "EPRONE"}  -- this is a table of stances that will be applied when spawning PLA unit
curWp = ""  -- this is the current name of the waypoint where unit is spawned
groupWp = "grpSpawnWp"  -- we put 4 waypoints in a group
 


Then we set the amount of PLA unit to kill (randomly) and we start spawning the first unit.

nbToKill = math.random(5, 10)  -- amount of PLA to kill (between 5 and 10)
OFP:displaySystemMessage("Kill " .. nbToKill .. " PLA to complete the objective")
OFP:addTimer("timerSpawn", 5000)
 



2. spawning PLA Unit :
Each time timer timerSpawn is fired, we try to spawn the entityset.

function onTimer_timerSpawn()
	if nbKilled ~= nbToKill then  -- if we have not killed all PLA unit
	
		local maxWp = OFP:getGroupSize(groupWp)  -- count the amount of waypoints in the group
		
		local grpNb = maxWp - 1
		local grpIndex = math.random(0, grpNb) -- define a random index
	
		local spawnWp = OFP:getGroupMember(groupWp, grpIndex) -- define a random waypoint
		
                -- we do not want to spawn a unit at the same place.
                -- so we check if the new waypoint is not at the same place that has been set last time
		if spawnWp ~= curWp then 
                        -- if it's ok, we can spawn the entityset at the new waypoint
			local x, y, z = OFP:getPosition(spawnWp)
			spawnUnitID = OFP:spawnEntitySetAtLocation("enemySet", x, y, z)
			curWp =  spawnWp  -- we store the name of the waypoint for next spawn
		else
                        -- if it's not ok, we recall the function
			OFP:setTimer("timerSpawn", 200)
		end
	end
end
 


And once the entityset is spawned we make some adjustments :

function onSpawnedReady( setName, setID, tableOfEntities, errorCode )
	if setID == spawnUnitID then
		for i = 1, #tableOfEntities do
			if OFP:isUnit(tableOfEntities[i]) then
                                -- if this is a unit (PLA) we store its name for onDeath() event
				curUnit = tableOfEntities[i] 	
			
                                -- now we set the stance of the unit randomly (for fun)
				local y = math.random(1, #tabStance)
				OFP:setStance(curUnit, tabStance[y], "ADDTOEND")
				OFP:setMood(curUnit, "EMoodCautious", "ADDTOEND")
			
                                -- and we display its name/stance
				OFP:displaySystemMessage("Unit Spawned : " .. curUnit .. " / " .. tabStance[y])
			end
		end
	end
end
 



3. Detect when the PLA unit has been killed:
Each time the PLA unit is killed, we will respawn another one until we have killed the total amount that has been defined at startup.

function onDeath(victim, killer)
        -- if the victim has same name as the one we stored = it's our PLA unit !
	if victim == curUnit then 
		nbKilled = nbKilled + 1  -- we count the killed unit
		local str = "You killed : " .. victim .. " (" .. nbKilled .. "/" .. nbToKill .. ")"
		OFP:displaySystemMessage(str)
		
		if nbKilled ~= nbToKill then  -- if we do not have killed the needed amount
                        -- we respawn the entityset
			OFP:setTimer("timerSpawn", 200)
		else
                        -- otherwise we have killed all the enemy
                        -- game is completed
			OFP:removeTimer("timerSpawn")
			OFP:setObjectiveState("objKillEmAll", "COMPLETED")
			OFP:displaySystemMessage("Congrats ! You killed : " .. nbKilled .. " units")
			OFP:addTimer("timerEnd", 8000)
		end
	end
end
 

Download

Download MSSN file : SAR_HT4_Spawn1.zip

 
Back to summary