27 | function FieldDefinition:new(name) |
28 | local self = {}; |
29 | setmetatable(self, FieldDefinition_mt); |
30 | |
31 | self.isInit = false; |
32 | self.numberOfFields = getNumOfChildren(name); |
33 | self.fieldDefs = {}; |
34 | self.fieldDefsByFieldNumber = {}; |
35 | self.unownedFields = {}; |
36 | |
37 | for i = 1, self.numberOfFields do |
38 | local currentFieldDef = getChildAt(name, i - 1); |
39 | local fieldDef = {}; |
40 | fieldDef.rootNode = currentFieldDef; |
41 | fieldDef.fieldNumber = i; |
42 | fieldDef.fieldName = Utils.getNoNil(getUserAttribute(currentFieldDef, "fieldName"), ""); |
43 | fieldDef.fieldArea = Utils.getNoNil(getUserAttribute(currentFieldDef, "fieldArea"), 2.5); |
44 | local angleRad = math.rad(Utils.getNoNil(tonumber(getUserAttribute(currentFieldDef, "fieldAngle")), 0)); |
45 | fieldDef.fieldAngle = Utils.convertToDensityMapAngle(angleRad, g_currentMission.terrainDetailAngleMaxValue); |
46 | local fieldPriceScale = Utils.getNoNil(getUserAttribute(currentFieldDef, "fieldPriceScale"), 1); |
47 | fieldDef.fieldPriceFactor = Utils.getNoNil(getUserAttribute(currentFieldDef, "fieldPriceFactor"), fieldPriceScale); |
48 | fieldDef.fieldPrice = FieldDefinition.getFieldPrice(fieldDef.fieldArea) * fieldDef.fieldPriceFactor |
49 | fieldDef.fieldPriceInitial = fieldDef.fieldPrice; |
50 | |
51 | fieldDef.fieldJobUsageAllowed = Utils.getNoNil(getUserAttribute(currentFieldDef, "fieldJobUsageAllowed"), true); |
52 | fieldDef.fieldJobVehicleSpawnDirection = tonumber( Utils.getNoNil(getUserAttribute(currentFieldDef, "fieldJobVehicleSpawnDirection"), 1.0) ); |
53 | |
54 | local npcIndex = getUserAttribute(currentFieldDef, "npcIndex") |
55 | if npcIndex == nil then |
56 | npcIndex = NPCUtil.getRandomNPCIndex() |
57 | end |
58 | fieldDef.npcIndex = npcIndex |
59 | fieldDef.fieldBuyTrigger = getChildAt(currentFieldDef, 0); |
60 | fieldDef.fieldBuySymbol = getChildAt(fieldDef.fieldBuyTrigger, 0); |
61 | fieldDef.fieldDimensions = getChildAt(currentFieldDef, 1); -- this transformgroup's children define the field's location and dimensions |
62 | fieldDef.fieldMapIndicator = getChildAt(currentFieldDef, 2); -- this is where the field number appears on the ingamemap |
63 | |
64 | -- add field number to ingamemap |
65 | local x, _, z = getWorldTranslation(fieldDef.fieldMapIndicator); |
66 | local _, textSize = getNormalizedScreenValues(0, 6); |
67 | local _, textOffsetY = getNormalizedScreenValues(0, 6); |
68 | |
69 | local fieldName = tostring(fieldDef.fieldNumber) |
70 | -- field name overrides field number as the hotspot's displayed name |
71 | if fieldDef.fieldName ~= "" then |
72 | -- if field name is not in i18n, just take the name given via user attribute |
73 | fieldName = fieldDef.fieldName; |
74 | local i18n = g_i18n; |
75 | if g_currentMission.missionInfo.customEnvironment ~= nil then |
76 | i18n = _G[g_currentMission.missionInfo.customEnvironment].g_i18n; |
77 | end |
78 | if i18n:hasText(fieldName) then |
79 | fieldName = i18n:getText(fieldName) |
80 | end; |
81 | end; |
82 | |
83 | fieldDef.fieldMapHotspot = g_currentMission.ingameMap:createMapHotspot("fieldDefinition", fieldName, nil, nil, nil, x, z, 0, 0, false, false, true, 0, nil, MapHotspot.CATEGORY_FIELD_DEFINITION, textSize, textOffsetY); |
84 | |
85 | -- commented out: displaying field areas makes map too crowded |
86 | -- fieldDef.fieldMapHotspot.fullViewName = string.format("%d\n(%1.2f " .. g_i18n:getText("unit_areaShort") .. ")", fieldDef.fieldNumber, fieldDef.fieldArea); |
87 | |
88 | table.insert(self.fieldDefs, fieldDef); |
89 | self.fieldDefsByFieldNumber[i] = fieldDef; -- for convenience |
90 | |
91 | fieldDef.ownedByPlayer = nil; |
92 | local isOwned = g_currentMission:getIsServer() and Utils.getNoNil(getUserAttribute(currentFieldDef, "ownedByPlayer"), false); |
93 | |
94 | if g_isPresentationVersion then |
95 | isOwned = (i == 4 or |
96 | i == 7 or |
97 | i == 12 or |
98 | i == 14 or |
99 | i == 15 or |
100 | i == 23 or |
101 | i == 25 or |
102 | i == 27 or |
103 | i == 28); |
104 | end |
105 | self:setFieldOwnedByPlayer(fieldDef, isOwned); |
106 | |
107 | -- |
108 | fieldDef.getFieldStatusPartitions = {}; |
109 | fieldDef.setFieldStatusPartitions = {}; |
110 | fieldDef.maxFieldStatusPartitions = {}; |
111 | |
112 | self:updateFieldPartitions(fieldDef, fieldDef.getFieldStatusPartitions, 900); |
113 | self:updateFieldPartitions(fieldDef, fieldDef.setFieldStatusPartitions, 400); |
114 | self:updateFieldPartitions(fieldDef, fieldDef.maxFieldStatusPartitions, 10000000); |
115 | |
116 | --print(" fieldNumber: "..tostring(fieldDef.fieldNumber).." :: get set max -> "..tostring(table.getn(fieldDef.getFieldStatusPartitions)).." // "..tostring(table.getn(fieldDef.setFieldStatusPartitions)).." // "..tostring(table.getn(fieldDef.maxFieldStatusPartitions)) ); |
117 | end; |
118 | |
119 | self.currentField = nil; -- this points to the field def whose trigger the player is currently standing in |
120 | |
121 | self.activateText = g_i18n:getText("action_purchaseOrFarmField"); |
122 | |
123 | self.isEnabled = true; |
124 | self.objectActivated = false; |
125 | |
126 | return self; |
127 | end; |
155 | function FieldDefinition:setFieldOwnedByPlayer(fieldDef, isOwned) |
156 | if fieldDef.ownedByPlayer ~= isOwned then |
157 | fieldDef.ownedByPlayer = isOwned; |
158 | |
159 | if isOwned then |
160 | for i,unownedField in ipairs(self.unownedFields) do |
161 | if unownedField == fieldDef then |
162 | table.remove(self.unownedFields, i); |
163 | break; |
164 | end |
165 | end |
166 | |
167 | if fieldDef.fieldJobHotspot ~= nil then |
168 | g_currentMission.ingameMap:deleteMapHotspot(fieldDef.fieldJobHotspot) |
169 | end |
170 | setVisibility(fieldDef.fieldBuySymbol, false); |
171 | removeTrigger(fieldDef.fieldBuyTrigger); |
172 | |
173 | if self.objectActivated and self.currentField == fieldDef then |
174 | self.objectActivated = false; |
175 | g_currentMission:removeActivatableObject(self); |
176 | end |
177 | |
178 | fieldDef.fieldMapHotspot.textColor = {0.25, 1, 0.25, 1}; |
179 | fieldDef.fieldMapHotspot.textBold = true |
180 | fieldDef.fieldMapHotspot.textSize = fieldDef.fieldMapHotspot.defaultTextSize*1.3 |
181 | |
182 | -- throw player out of field dialog if he's currently got it open |
183 | if g_gui:getIsGuiVisible() and g_gui.currentGuiName == "FieldJobMissionScreen" and g_gui.currentGui.target.currentField == fieldDef then |
184 | g_gui.currentGui.target:onClickBack(); |
185 | end; |
186 | |
187 | self.currentField = nil; |
188 | |
189 | else |
190 | setVisibility(fieldDef.fieldBuySymbol, true); |
191 | addTrigger(fieldDef.fieldBuyTrigger, "triggerCallback", self); |
192 | table.insert(self.unownedFields, fieldDef); |
193 | fieldDef.fieldMapHotspot.textColor = {1, 1, 1, 1}; |
194 | fieldDef.fieldMapHotspot.textBold = false |
195 | fieldDef.fieldMapHotspot.textSize = fieldDef.fieldMapHotspot.defaultTextSize |
196 | |
197 | local x,_,z = getWorldTranslation(fieldDef.fieldBuyTrigger) |
198 | local width, height = getNormalizedScreenValues(6, 6) |
199 | |
200 | local text = string.format(g_i18n:getText("fieldJob_number"), fieldDef.fieldNumber) |
201 | fieldDef.fieldJobHotspot = g_currentMission.ingameMap:createMapHotspot("fieldJob", text, nil, getNormalizedUVs({520, 776, 240, 240}), {0.0742, 0.4341, 0.6939, 1}, x, z, width, height, false, false, false, 0, nil, MapHotspot.CATEGORY_FIELD_JOB, nil, nil, nil, nil, getNormalizedUVs({776, 776, 240, 240}), Overlay.ALIGN_VERTICAL_MIDDLE, 1); |
202 | end |
203 | |
204 | self:updateFieldOwnedData(fieldDef); |
205 | end |
206 | end |
249 | function FieldDefinition:onActivateObject() |
250 | -- check if new job is available |
251 | local fieldJob; |
252 | if g_currentMission.fieldJobManager ~= nil and self.currentField ~= nil then |
253 | if not g_currentMission.fieldJobManager:isFieldJobActive() then |
254 | if self.currentField.fieldJobUsageAllowed then |
255 | fieldJob = g_currentMission.fieldJobManager:createNewFieldJob(self.currentField); |
256 | end |
257 | end |
258 | end |
259 | |
260 | if self.currentField ~= nil then |
261 | |
262 | g_fieldJobMissionScreen:setStartCallback(self.startCallback, self); |
263 | g_fieldJobMissionScreen:setCancelCallback(self.cancelCallback, self); |
264 | |
265 | local fieldDef = self.currentField; |
266 | |
267 | local mapName = ""; |
268 | if g_currentMission.missionInfo ~= nil then |
269 | mapName = tostring(g_currentMission.missionInfo.name); |
270 | local map = MapsUtil.getMapById(g_currentMission.missionInfo.mapId); |
271 | if map ~= nil then |
272 | if g_currentMission.missionInfo:isa(FSCareerMissionInfo) then |
273 | mapName = map.title |
274 | end; |
275 | end |
276 | end; |
277 | |
278 | local actualFieldPriceFactor = 1.0 - (0.2 * Utils.clamp(NPCUtil.npcIndexToDesc[fieldDef.npcIndex].finishedMissions / FieldJob.THRESHOLD_NPC_IS_HAPPY, 0, 1)); |
279 | fieldDef.fieldPrice = fieldDef.fieldPriceInitial * actualFieldPriceFactor; |
280 | |
281 | if fieldJob == nil then |
282 | g_fieldJobMissionScreen:setData(fieldDef.npcIndex, fieldDef.fieldNumber, mapName, fieldDef.fieldArea, fieldDef.fieldPrice); |
283 | else |
284 | if fieldJob == -1 then |
285 | g_fieldJobMissionScreen:setData(fieldDef.npcIndex, fieldDef.fieldNumber, mapName, fieldDef.fieldArea, fieldDef.fieldPrice, nil, nil, g_i18n:getText("warning_noFreeMissionSpace")); |
286 | else |
287 | local jobReward, jobTitle, jobDesc, jobVehicles, jobTime = fieldJob:getFieldJobData(); |
288 | g_fieldJobMissionScreen:setData(fieldDef.npcIndex, fieldDef.fieldNumber, mapName, fieldDef.fieldArea, fieldDef.fieldPrice, jobReward, jobTitle, jobDesc, jobVehicles, jobTime); |
289 | end |
290 | end |
291 | g_gui:showGui("FieldJobMissionScreen"); |
292 | else |
293 | print("ERROR: current field def is nil"); |
294 | end; |
295 | self.objectActivated = true; |
296 | g_currentMission:addActivatableObject(self); |
297 | end; |