Get SaintAxe&Ror SpeechMaker Now And build your conversations easily ! |
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
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
