forked from FAForever/fa
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimInit.lua
355 lines (301 loc) · 13.2 KB
/
simInit.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
-- ==========================================================================================
-- * File : lua/simInit.lua
-- * Authors : Gas Powered Games, FAF Community, HUSSAR
-- * Summary : This is the sim-specific top-level lua initialization file. It is run at initialization time to set up all lua state for the sim.
-- * Copyright © 2005 Gas Powered Games, Inc. All rights reserved.
-- ==========================================================================================
-- Initialization order within the sim:
-- 1. __blueprints is filled in from preloaded data
-- 2. simInit.lua [this file] runs. It sets up infrastructure necessary to make Lua classes work etc.
-- if starting a new session:
-- 3a. ScenarioInfo is setup with info about the scenario
-- 4a. SetupSession() is called
-- 5a. Armies, brains, recon databases, and other underlying game facilities are created
-- 6a. BeginSession() is called, which loads the actual scenario data and starts the game
-- otherwise (loading a old session):
-- 3b. The saved lua state is deserialized
-- ==========================================================================================
-- Do global initialization and set up common global functions
doscript '/lua/globalInit.lua'
WaitTicks = coroutine.yield
function WaitSeconds(n)
local ticks = math.max(1, n * 10)
if ticks > 1 then
ticks = ticks + 1
end
WaitTicks(ticks)
end
-- Set up the sync table and some globals for use by scenario functions
doscript '/lua/SimSync.lua'
local syncStartPositions = false -- This is held here because the Sync table is cleared between SetupSession() and BeginSession()
function ShuffleStartPositions(syncNewPositions)
local markers = ScenarioInfo.Env.Scenario.MasterChain._MASTERCHAIN_.Markers
local positionGroups = ScenarioInfo.Options.RandomPositionGroups
local positions = {}
if not positionGroups then
return
end
for _, group in positionGroups do
for _, num in group do
local name = 'ARMY_' .. num
local marker = markers[name]
if marker and marker.position then
positions[num] = {pos = marker.position, name = name}
end
end
local shuffledGroup = table.shuffle(group)
for i = 1, table.getn(group) do
local pos = positions[shuffledGroup[i]].pos
local name = positions[group[i]].name
if pos and markers[name] then
markers[name].position = pos
if syncNewPositions then
syncStartPositions[name] = pos
end
end
end
end
end
--SetupSession will be called by the engine after ScenarioInfo is set
--but before any armies are created.
function SetupSession()
-- LOG('SetupSession: ', repr(ScenarioInfo))
ArmyBrains = {}
-- ScenarioInfo is a table filled in by the engine with fields from the _scenario.lua
-- file we're using for this game. We use it to store additional global information
-- needed by our scenario.
ScenarioInfo.PlatoonHandles = {}
ScenarioInfo.UnitGroups = {}
ScenarioInfo.UnitNames = {}
ScenarioInfo.VarTable = {}
ScenarioInfo.OSPlatoonCounter = {}
ScenarioInfo.BuilderTable = { Air = {}, Land = {}, Sea = {}, Gate = {} }
ScenarioInfo.BuilderTable.AddedPlans = {}
ScenarioInfo.MapData = { PathingTable = { Amphibious = {}, Water = {}, Land = {}, }, IslandData = {} }
-- ScenarioInfo.Env is the environment that the save file and scenario script file
-- are loaded into. We set it up here with some default functions that can be accessed
-- from the scenario script.
ScenarioInfo.Env = import('/lua/scenarioEnvironment.lua')
--Check if ShareOption is valid, and if not then set it to ShareUntilDeath
local shareOption = ScenarioInfo.Options.Share
local globalOptions = import('/lua/ui/lobby/lobbyOptions.lua').globalOpts
local shareOptions = {}
for _,globalOption in globalOptions do
if globalOption.key == 'Share' then
for _,value in globalOption.values do
shareOptions[value.key] = true
end
break
end
end
if not shareOptions[shareOption] then
ScenarioInfo.Options.Share = 'ShareUntilDeath'
end
-- if build/enhancement restrictions chosen, set them up
local buildRestrictions, enhRestrictions = nil, {}
local restrictions = ScenarioInfo.Options.RestrictedCategories
if restrictions then
table.print(restrictions, 'RestrictedCategories')
local presets = import('/lua/ui/lobby/UnitsRestrictions.lua').GetPresetsData()
for index, restriction in restrictions do
local preset = presets[restriction]
if not preset then -- custom restriction
LOG('restriction.custom: "'.. restriction ..'"')
-- using hash table because it is faster to check for restrictions later in game
enhRestrictions[restriction] = true
if buildRestrictions then
buildRestrictions = buildRestrictions .. " + (" .. restriction .. ")"
else
buildRestrictions = "(" .. restriction .. ")"
end
else -- preset restriction
if preset.categories then
LOG('restriction.preset "'.. preset.categories .. '"')
if buildRestrictions then
buildRestrictions = buildRestrictions .. " + (" .. preset.categories .. ")"
else
buildRestrictions = "(" .. preset.categories .. ")"
end
end
if preset.enhancements then
LOG('restriction.enhancement "'.. restriction .. '"')
table.print(preset.enhancements, 'restriction.enhancements ')
for _, enhancement in preset.enhancements do
enhRestrictions[enhancement] = true
end
end
end
end
end
if buildRestrictions then
LOG('restriction.build '.. buildRestrictions)
buildRestrictions = import('/lua/sim/Categoryutils.lua').ParseEntityCategoryProperly(buildRestrictions)
-- add global build restrictions for all armies
import('/lua/game.lua').AddRestriction(buildRestrictions)
ScenarioInfo.BuildRestrictions = buildRestrictions
end
if table.getsize(enhRestrictions) > 0 then
--table.print(enhRestrictions, 'enhRestrictions ')
import('/lua/enhancementcommon.lua').RestrictList(enhRestrictions)
end
-- Loads the scenario saves and script files
-- The save file creates a table named "Scenario" in ScenarioInfo.Env,
-- containing most of the save data. We'll copy it up to a top-level global.
LOG('Loading save file: ',ScenarioInfo.save)
doscript('/lua/dataInit.lua')
doscript(ScenarioInfo.save, ScenarioInfo.Env)
Scenario = ScenarioInfo.Env.Scenario
local spawn = ScenarioInfo.Options.TeamSpawn
if spawn and table.find({'random_reveal', 'balanced_reveal', 'balanced_flex_reveal'}, spawn) then
-- Shuffles positions like normal but syncs the new positions to the UI
syncStartPositions = {}
ShuffleStartPositions(true)
elseif spawn and table.find({'random', 'balanced', 'balanced_flex'}, spawn) then
-- Prevents players from knowing start positions at start
ShuffleStartPositions(false)
end
LOG('Loading script file: ', ScenarioInfo.script)
doscript(ScenarioInfo.script, ScenarioInfo.Env)
-- Preloads AI templates from AI mods
AIModTemplatesPreloader()
ResetSyncTable()
end
-- OnCreateArmyBrain() is called by then engine as the brains are created, and we
-- use it to store off various useful bits of info.
-- The global variable "ArmyBrains" contains an array of AI brains, one for each army.
function OnCreateArmyBrain(index, brain, name, nickname)
--LOG(string.format("OnCreateArmyBrain %d %s %s",index,name,nickname))
ArmyBrains[index] = brain
ArmyBrains[index].Name = name
ArmyBrains[index].Nickname = nickname
ScenarioInfo.PlatoonHandles[index] = {}
ScenarioInfo.UnitGroups[index] = {}
ScenarioInfo.UnitNames[index] = {}
InitializeArmyAI(name)
-- Add build restrictions to the army, if any are configured.
if ScenarioInfo.BuildRestrictions then
AddBuildRestriction(index, ScenarioInfo.BuildRestrictions)
end
--brain:InitializePlatoonBuildManager()
--ScenarioUtils.LoadArmyPBMBuilders(name)
--LOG('*SCENARIO DEBUG: ON POP, ARMY BRAINS = ', repr(ArmyBrains))
end
function InitializePrebuiltUnits(name)
ArmyInitializePrebuiltUnits(name)
end
-- BeginSession will be called by the engine after the armies are created (but without
-- any units yet) and we're ready to start the game. It's responsible for setting up
-- the initial units and any other gameplay state we need.
function BeginSession()
LOG('BeginSession...')
SPEW('Active mods in sim: ', repr(__active_mods))
ForkThread(GameTimeLogger)
local focusarmy = GetFocusArmy()
if focusarmy>=0 and ArmyBrains[focusarmy] then
LocGlobals.PlayerName = ArmyBrains[focusarmy].Nickname
end
-- Pass ScenarioInfo into OnPopulate() and OnStart() for backwards compatibility
ScenarioInfo.Env.OnPopulate(ScenarioInfo)
ScenarioInfo.Env.OnStart(ScenarioInfo)
-- Look for teams
local teams = {}
for name,army in ScenarioInfo.ArmySetup do
if army.Team > 1 then
if not teams[army.Team] then
teams[army.Team] = {}
end
table.insert(teams[army.Team],army.ArmyIndex)
end
end
if ScenarioInfo.Options.TeamLock == 'locked' then
-- Specify that the teams are locked. Parts of the diplomacy dialog will
-- be disabled.
ScenarioInfo.TeamGame = true
Sync.LockTeams = true
end
-- Set up the teams we found
for team,armyIndices in teams do
for k,index in armyIndices do
for k2,index2 in armyIndices do
SetAlliance(index,index2,"Ally")
end
ArmyBrains[index].RequestingAlliedVictory = true
end
end
-- Create any effect markers on map
local markers = import('/lua/sim/ScenarioUtilities.lua').GetMarkers()
local Entity = import('/lua/sim/Entity.lua').Entity
local EffectTemplate = import ('/lua/EffectTemplates.lua')
if markers then
for k, v in markers do
if v.type == 'Effect' then
local EffectMarkerEntity = Entity()
Warp(EffectMarkerEntity, v.position)
EffectMarkerEntity:SetOrientation(OrientFromDir(v.orientation), true)
for k, v in EffectTemplate [v.EffectTemplate] do
CreateEmitterAtBone(EffectMarkerEntity,-2,-1,v):ScaleEmitter(v.scale or 1):OffsetEmitter(v.offset.x or 0, v.offset.y or 0, v.offset.z or 0)
end
end
end
end
Sync.EnhanceRestrict = import('/lua/enhancementcommon.lua').GetRestricted()
Sync.Restrictions = import('/lua/game.lua').GetRestrictions()
--for off-map prevention
OnStartOffMapPreventionThread()
if syncStartPositions then
Sync.StartPositions = syncStartPositions
end
end
function GameTimeLogger()
local time
while true do
GTS = GetGameTimeSeconds()
hours = math.floor(GTS / 3600);
minutes = math.floor((GTS - (hours * 3600)) / 60);
seconds = GTS - (hours * 3600) - (minutes * 60);
SPEW(string.format('Current gametime: %02d:%02d:%02d', hours, minutes, seconds))
WaitSeconds(30)
end
end
-- forks a thread that performs off-map prevention
function OnStartOffMapPreventionThread()
OffMappingPreventThread = ForkThread(import('/lua/ScenarioFramework.lua').AntiOffMapMainThread)
ScenarioInfo.OffMapPreventionThreadAllowed = true
--WARN('success')
end
-- OnPostLoad called after loading a saved game
function OnPostLoad()
end
-- Set up list of files to prefetch
Prefetcher = CreatePrefetchSet()
function DefaultPrefetchSet()
local set = { models = {}, anims = {}, d3d_textures = {} }
-- for k,file in DiskFindFiles('/units/', '*.scm') do
-- table.insert(set.models,file)
-- end
-- for k,file in DiskFindFiles('/units/', '*.sca') do
-- table.insert(set.anims,file)
-- end
-- for k,file in DiskFindFiles('/units/', '*.dds') do
-- table.insert(set.d3d_textures,file)
-- end
return set
end
Prefetcher:Update(DefaultPrefetchSet())
function AIModTemplatesPreloader()
local simMods = __active_mods or {}
for Index, ModData in simMods do
ModAIFiles = DiskFindFiles(ModData.location..'/lua/AI/CustomAIs_v2', '*.lua')
if ModAIFiles[1] then
for k,file in DiskFindFiles(ModData.location..'/lua/AI/PlatoonTemplates', '*.lua') do
import(file)
end
for k,file in DiskFindFiles(ModData.location..'/lua/AI/AIBuilders', '*.lua') do
import(file)
end
for k,file in DiskFindFiles(ModData.location..'/lua/AI/AIBaseTemplates', '*.lua') do
import(file)
end
end
end
end