-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathParkVehicleSystem.lua
More file actions
247 lines (211 loc) · 7.74 KB
/
Copy pathParkVehicleSystem.lua
File metadata and controls
247 lines (211 loc) · 7.74 KB
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
--- Global instance of park vehicle.
---@class ParkVehicleSystem
---@field modName string
---@field modDir string
---@field inputManager InputBinding
---@field debug boolean
---@field instances table<integer, ParkVehicle>
---@field counter integer Increased if an instance is registered, used as key within the table
ParkVehicleSystem = {}
local ParkVehicleSystem_mt = Class(ParkVehicleSystem)
---
---@param modName string
---@param modDir string
---@param inputManager InputBinding
---@param debug boolean
---@return ParkVehicleSystem
function ParkVehicleSystem:new(modName, modDir, inputManager, debug)
local self = {}
setmetatable(self, ParkVehicleSystem_mt)
self.modName = modName
self.modDir = modDir
self.debug = debug
self.inputManager = inputManager
self.instances = {}
self.counter = 0
self.controlledVehicle = nil
self.autoUnparkEnabled = true
self.uniqueUserId = nil
self:loadSettings()
return self
end
--- Single owner of modSettings/parkVehicle.xml: both the per-installation
--- uniqueUserId and the autoUnparkEnabled preference live in this one file,
--- read/written only from here (ParkVehicle.lua just asks for the values).
function ParkVehicleSystem:getSettingsFilePath()
return getUserProfileAppPath() .. "modSettings/parkVehicle.xml"
end
function ParkVehicleSystem:loadSettings()
if g_dedicatedServerInfo ~= nil then
return
end
local filePath = self:getSettingsFilePath()
if not fileExists(filePath) then
return
end
local xml = loadXMLFile("ParkVehicle", filePath)
if hasXMLProperty(xml, "ParkVehicle#autoUnparkEnabled") then
self.autoUnparkEnabled = Utils.getNoNil(getXMLBool(xml, "ParkVehicle#autoUnparkEnabled"), true)
end
self.uniqueUserId = getXMLString(xml, "ParkVehicle#uniqueUserId")
delete(xml)
end
function ParkVehicleSystem:saveSettings()
if g_dedicatedServerInfo ~= nil then
return
end
local filePath = self:getSettingsFilePath()
local xml
if fileExists(filePath) then
xml = loadXMLFile("ParkVehicle", filePath)
else
createFolder(getUserProfileAppPath() .. "modSettings")
xml = createXMLFile("ParkVehicle", filePath, "ParkVehicle")
end
setXMLBool(xml, "ParkVehicle#autoUnparkEnabled", self.autoUnparkEnabled)
if self.uniqueUserId ~= nil then
setXMLString(xml, "ParkVehicle#uniqueUserId", self.uniqueUserId)
end
saveXMLFile(xml)
delete(xml)
end
---@param enabled boolean
function ParkVehicleSystem:setAutoUnparkEnabled(enabled)
self.autoUnparkEnabled = enabled
self:saveSettings()
end
--- Per-player id used to key each vehicle's parked state, so multiple
--- players in the same MP session each have their own independent parking
--- preference for the same vehicle. Generated once and persisted; memoized
--- here so only the first vehicle that needs it triggers any file I/O.
---@return string
function ParkVehicleSystem:getUniqueUserId()
if self.uniqueUserId == nil then
if g_dedicatedServerInfo ~= nil then
self.uniqueUserId = "dedi"
else
self.uniqueUserId = g_currentMission.playerNickname or ParkVehicleSystem.randomString(25)
self:saveSettings()
end
end
return self.uniqueUserId
end
function ParkVehicleSystem.randomString(length)
local charset = {} -- [0-9a-zA-Z]
for c = 48, 57 do
table.insert(charset, string.char(c))
end
for c = 65, 90 do
table.insert(charset, string.char(c))
end
for c = 97, 122 do
table.insert(charset, string.char(c))
end
local function randomString(len)
if not len or len <= 0 then
return ""
end
return randomString(len - 1) .. charset[math.random(1, #charset)]
end
return randomString(length)
end
function ParkVehicleSystem:onMissionLoaded(mission)
-- hook into function, which is called only if the HUD is really visible for a vehicle
mission.hud.drawControlledEntityHUD = Utils.appendedFunction(mission.hud.drawControlledEntityHUD,
function(self)
if self.isVisible then
ParkVehicleSystem:renderHud()
end
end)
-- hook into function, which sets the vehicle for HUD display
mission.hud.setControlledVehicle = Utils.appendedFunction(mission.hud.setControlledVehicle,
function(self, vehicle)
ParkVehicleSystem:setVehicle(vehicle)
end)
end
---@param typeManager TypeManager
---@param specManager SpecializationManager
function ParkVehicleSystem:installSpecialization(typeManager, specManager)
-- register spec
specManager:addSpecialization("parkVehicle", "ParkVehicle", Utils.getFilename("ParkVehicle.lua", self.modDir), nil)
-- add spec to vehicle types
local totalCount = 0
local modified = 0
for typeName, typeEntry in pairs(typeManager:getTypes()) do
totalCount = totalCount + 1
if SpecializationUtil.hasSpecialization(Enterable, typeEntry.specializations) and
not SpecializationUtil.hasSpecialization(Rideable, typeEntry.specializations) and
not SpecializationUtil.hasSpecialization(ParkVehicle, typeEntry.specializations) then
typeManager:addSpecialization(typeName, self.modName .. ".parkVehicle")
modified = modified + 1
if (self.debug) then
print("Adding park vehicle to " .. typeName)
end
else
if (self.debug) then
print("Not adding park vehicle to " .. typeName)
end
end
end
print(string.format("Inserted Park Vehicle into %i of %i vehicle types", modified, totalCount))
end
function ParkVehicleSystem:registerActionEvents()
local _, eventId = self.inputManager:registerActionEvent(InputAction.PARKVEHICLE_UNPARK_ALL, self, self.unparkAll, false, true, false, true)
self.inputManager:setActionEventTextPriority(eventId, GS_PRIO_VERY_HIGH)
end
function ParkVehicleSystem:unregisterActionEvents()
self.inputManager:removeActionEventsByTarget(self)
end
---@param instance ParkVehicle
---@return integer the key to unregister this instance
function ParkVehicleSystem:registerInstance(instance)
local key = self.counter
self.instances[key] = instance
self.counter = self.counter + 1
return key
end
---@param key integer
function ParkVehicleSystem:unregisterInstance(key)
self.instances[key] = nil
end
function ParkVehicleSystem:unparkAll()
for _, value in pairs(self.instances) do
value:setParkVehicleState(false)
end
end
---@return ParkVehicle[] currently parked vehicle instances, in registration order
function ParkVehicleSystem:getParkedVehicles()
local vehicles = {}
for i = 0, self.counter - 1 do
local instance = self.instances[i]
if instance ~= nil and instance:getParkVehicleState() then
table.insert(vehicles, instance)
end
end
return vehicles
end
-- Bypasses the normal Tab restriction: cycles only through vehicles that are
-- currently parked, so you can reach them without unparking first.
function ParkVehicleSystem:cycleParkedVehicles()
local vehicles = self:getParkedVehicles()
if #vehicles == 0 then
return
end
local currentVehicle = g_localPlayer:getCurrentVehicle()
local index = 1
for i, vehicle in ipairs(vehicles) do
if vehicle == currentVehicle then
index = (i % #vehicles) + 1
break
end
end
g_localPlayer:requestToEnterVehicle(vehicles[index])
end
function ParkVehicleSystem:setVehicle(vehicle)
self.controlledVehicle = vehicle
end
function ParkVehicleSystem:renderHud()
if self.controlledVehicle ~= nil and self.controlledVehicle.parkVehicleRender ~= nil then
self.controlledVehicle:parkVehicleRender()
end
end