fa
fa copied to clipboard
Refactor Scenario Framework part 1
Covers [a bit more than its fair share of] the first third of annotating the scenario framework. Incidentally, these functions are basically pulled from scenariotriggers.lua
, so I also ended up annotating those copied functions as well. And when I say "annotate" I kinda mean "refactor"--but don't worry, its mostly just variable renaming. This one definitely became larger than I thought it was going to be, even breaking it into chunks... I'll reevaluate my methods.
@speed2CZ could you find the time to look over these changes too?
The IDE is really good about letting you about problems with annotations--are you talking about making sure I renamed parameters correctly or the small logical equivalences I did?
The logic changes, it needs debugging. Ideally to test it on couple of missions.
Hhm, ~~FAF is currently completely broken as to anything to do with the campaign, so it can't be properly tested~~ I have recently been informed about the fa-coop project. I've summarized the kinds of logical changes here if you'd like to review them manually. Would you prefer that I revert them instead?
- function PlatoonMoveRoute(platoon, route, squad)
- for _, v in route do
- if type(v) == 'string' then
- if squad then
- platoon:MoveToLocation(ScenarioUtils.MarkerToPosition(v), false, squad)
- else
- platoon:MoveToLocation(ScenarioUtils.MarkerToPosition(v), false)
- end
- else
- if squad then
- platoon:MoveToLocation(v, false, squad)
- else
- platoon:MoveToLocation(v, false)
- end
- end
- end
- end
+ function PlatoonMoveRoute(platoon, route, squad)
+ for _, node in route do
+ if type(node) == 'string' then
+ node = ScenarioUtils.MarkerToPosition(node)
+ end
+ if squad then
+ platoon:MoveToLocation(v, false, squad)
+ else
+ platoon:MoveToLocation(v, false)
+ end
+ end
+ end
- function GroupProgressTimerThread(group, time)
- ...
- v:SetWorkProgress(currTime/time)
- ...
- end
+ function GroupProgressTimerThread(units, time)
+ ...
+ local prog = currTime / time
+ ...
+ unit:SetWorkProgress(prog)
+ ...
+ end
- function Dialogue(dialogueTable, callback, critical, speaker)
- local canSpeak = true
- if speaker and speaker.Dead then
- canSpeak = false
- end
-
- if canSpeak then
- ...
- end
- end
+ function Dialogue(dialogueTable, callback, critical, speaker)
+ if not (speaker and speaker.Dead) then
+ ...
+ end
+ end
- SetupMFDSync(movieTable, text)
- ...
- local timeSecs = GetGameTimeSeconds()
- tempData.time = string.format("%02d:%02d:%02d", math.floor(timeSecs/360), math.floor(timeSecs/60), math.mod(timeSecs, 60))
- tempData.color = 'ffffffff'
- if movieTable[4] == 'UEF' then
- ...
- end
- ...
- end
+ SetupMFDSync(movieTable, text)
+ ...
+ local time = GetGameTimeSeconds()
+ local hours = math.floor(time / 3600)
+ local minutes = math.mod(time, math.floor(time / 60), 60)
+ local seconds = math.mod(time, 60)
+ tempData.time = string.format("%02d:%02d:%02d", hours, minutes, seconds)
+ if movieTable[4] == 'UEF' then
+ ...
+ else
+ tempData.color = 'ffffffff'
+ end
+ ...
+ end
*variable storage changes not included
- function PlayDialogue()
- ...
- if v.text and not v.vid then
- if not v.vid then
- DisplayMissionText(v.text)
- end
- end
- ...
- local vidText = ''
- if v.text then
- vidText = v.text
- end
- ...
- SetupMFDSync(movieData, vidText)
- ...
- end
+ function PlayDialogue()
+ ...
+ if text and not vid then
+ DisplayMissionText(text)
+ end
+ ...
+ text = text or ""
+ ...
+ SetupMFDSync(movieData, text)
+ ...
+ end
- function AreaTriggerThread(callbackFunction, rectangleTable, category, onceOnly, invert, aiBrain, number, requireBuilt, name)
- ...
- for _, v in rectangleTable do
- table.insert(recTable, ...)
- end
-
- ...
- for _, v in recTable do
- ...
- totalEntities[table.getn(totalEntities) + 1] = ve
- ...
- end
- ...
- local numEntities = table.getn(totalEntities)
- if numEntities > 0 then
- ...
- if number and ((amount >= number and not invert) or (amount < number and invert)) then
- ...
- if (triggered and not invert and not number) or (not triggered and invert and not number) or (triggered and number) then
- ...
- end
+ function AreaTriggerThread(callback, rectangles, category, onceOnly, invert, aiBrain, unitCount, requireBuilt, name)
+ ...
+ for i, rect in rectangles do
+ recTable[i] = ...
+ end
+
+ ...
+ local totalEntityCount = 0
+ for _, rect in recTable do
+ ...
+ totalEntityCount = totalEntityCount + 1
+ totalEntities[totalEntityCount] = entity
+ ...
+ end
+ ...
+ if totalEntityCount > 0 then
+ ...
+ if unitCount and ((amount >= unitCount) ~= invert) then
+ ...
+ if (not unitCount and (triggered ~= invert)) or (triggered and unitCount) then
+ ...
+ end
- function ThreatTriggerAroundUnitThread(callbackFunction, aiBrain, unit, rings, onceOnly, value, greater, name)
- ...
- if greater and threat >= value then
- -- stuff
- elseif not greater and threat <= value then
- -- same stuff
- end
- ...
- end
+ function ThreatTriggerAroundUnitThread(callback, aiBrain, unit, rings, onceOnly, value, greater, name)
+ ...
+ if (greater and threat >= value) or (not greater and threat <= value) then
+ -- that stuff
+ end
+ ...
+ end
- function TimerTriggerThread(callbackFunction, seconds, name, displayBool, onTickFunc)
- ...
- local ticking = true
- local targetTime = math.floor(GetGameTimeSeconds()) + seconds
-
- while ticking do
- onTickFunc(targetTime - math.floor(GetGameTimeSeconds()))
-
- if targetTime - math.floor(GetGameTimeSeconds()) < 0 then
- ticking = false
- end
-
- WaitSeconds(1)
- end
- ...
- end
+ function TimerTriggerThread(callback, seconds, name, display, onTickSecond)
+ ...
+ local targetTime = math.floor(GetGameTimeSeconds()) + seconds
+ onTickSecond(seconds)
+
+ while true do
+ WaitSeconds(1)
+ local time = targetTime - math.floor(GetGameTimeSeconds())
+ onTickSecond(time)
+ if time < 0 then
+ break
+ end
+ end
+ ...
+ end
- function CreateArmyStatTrigger(callbackFunction, aiBrain, name, triggerTable)
- ...
- if string.find (triggerData.StatType, "Economy_") then
- aiBrain:GetArmyStat(triggerData.StatType, 0.0)
- else
- aiBrain:GetArmyStat(triggerData.StatType, 0)
- end
- ...
- end
+ function CreateArmyStatTrigger(callbackFunction, aiBrain, name, triggerTable)
+ ...
+ aiBrain:GetArmyStat(trigger.StatType, 0)
+ ...
+ end
- function UnitToPositionDistanceTriggerThread(cb, unit, marker, distance, name)
- ...
- local fired = false
- while not fired do
- ...
- fired = true
- if name then
- cb(TriggerManager, name, unit)
- return
- else
- cb(unit)
- return
- end
- ...
- end
- end
+ function UnitToPositionDistanceTriggerThread(callback, unit, marker, distance, name)
+ ...
+ while true do
+ ...
+ if name then
+ callback(TriggerManager, name, unit)
+ else
+ callback(unit)
+ end
+ return
+ end
+ end
- function CreateUnitCapturedTrigger(cbOldUnit, cbNewUnit, unit)
- if cbOldUnit then
- unit:AddUnitCallback(cbOldUnit, 'OnCaptured')
- end
- if cbNewUnit then
- unit:AddUnitCallback(cbNewUnit, 'OnCapturedNewUnit')
- end
- end
+ function CreateUnitCapturedTrigger(cbOldUnit, cbNewUnit, unit)
+ unit:AddOnCapturedCallback(cbOldUnit, cbNewUnit)
+ end
- function VariableBoolCheckThread(cb, varName, value, name)
- if value then
- ...
- cb(TriggerManager, name)
- else
- ...
- cb(TriggerManager, name)
- end
- end
+ function VariableBoolCheckThread(callback, varName, invert, name)
+ if invert then
+ ...
+ else
+ ...
+ end
+ callback(TriggerManager, name)
+ end
- function MissionNumberTriggerThread(cb, value, name)
- ...
- while not ScenarioInfo.VarTable['Mission Number'] == value do
- ...
- end
+ function MissionNumberTriggerThread(callback, value, name)
+ ...
+ while ScenarioInfo.VarTable['Mission Number'] ~= value do
+ ...
+ end
- function CreateUnitGivenTrigger(cb, unit)
- TriggerFile.CreateUnitGivenTrigger(cb, unit)
- end
+ CreateUnitGivenTrigger = TriggerFile.CreateUnitGivenTrigger
- function CreateThreatTriggerAroundUnit(callbackFunction, aiBrain, unit, rings, onceOnly, value, greater)
- return ForkThread(ThreatTriggerAroundUnitThread, callbackFunction, aiBrain, unit, rings, onceOnly, value, greater)
- end
+ function CreateThreatTriggerAroundUnit(callbackFunction, aiBrain, unit, rings, onceOnly, value, greater, name)
+ return ForkThread(ThreatTriggerAroundUnitThread, callbackFunction, aiBrain, unit, rings, onceOnly, value, greater, name)
+ end
- function CreateTimerTrigger(cb, seconds, displayBool)
- timerThread = TriggerFile.CreateTimerTrigger(cb, seconds, displayBool)
- return timerThread
- end
+ function CreateTimerTrigger(callback, seconds, name, display, onTickSecond)
+ timerThread = TriggerFile.CreateTimerTrigger(callback, seconds, name, display, onTickSecond)
+ return timerThread
+ end
The only API "breaking" changes are the last three
-
ScenarioFramework.lua
no longer directly callsscenariotriggers.lua
functions, so changing functions inscenariotrigger.lua
instead ofScenarioFramework.lua
won't update them - adding support for the previously unused
name
parameter in all of the trigger functions means that any calls to these that derive their last argument from unadjusted multiple-return function calls will result in the callback function being called using the triggermanager + trailing name argument version - fixing the parameters in
CreateTimerTrigger
might mean that mods that, for some bizzare reason, rely on it being wrong need to be updated
Alright, I've done some testing and ~~none of the errors are mine~~ the coop branch is a lot more finicky than I thought and there are lots of errors
Can you copy some of the errors you encountered?
Oooh, rats, I already moved back to fafdevelop. I can test a campaign map again the morning if you'd like.
Sorry about all that @speed2CZ , I was still figuring out how to use the campaign branch. Everything's good now!
Looks like all the reviews are resolved and this has become inactive--I'll merge soon.
Hold up - allow me to run it over one more time tonight 😄
@Garanas How'd it go?
Lets merge it after the release is stable