File size: 8,309 Bytes
b6a38d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
if Platform.ged then

-- fake prop editor, so that accuracy chart is displayed under Caliber props in InventoryItemTemplate editor
GedPropEditors["accuracy_chart"] = "GedPropAccuracyChart"
DefineClass.GedPropAccuracyChart = {
	__parents = { "GedPropEditor" },
}

function GedPropAccuracyChart:Init()
	XTemplateSpawn("AccuracyChart", self)
end

function GedPropAccuracyChart:UpdateValue()
	local values = self.panel:Obj(self.obj)
	local prop_defs = self.panel:Obj("SelectedObject|props")
	local props_cont = {}
	for i = 1, #prop_defs do
		local id = prop_defs[i].id
		if values[id] ~= nil then
			props_cont[id] = values[id]
		else
			props_cont[id] = prop_defs[i].default
		end
	end
	self.idDrawChart:SetContext(props_cont)
	GedPropEditor.UpdateValue(self)
end


GedPropEditors["directions_set"] = "GedPropDirectionsSet"
DefineClass.GedPropDirectionsSet = {
	__parents = { "GedPropSet" },
	
	items = {
		{text = "N", value = "North"},
		{text = "W", value = "West"},
		{text = "E", value = "East"},
		{text = "S", value = "South"},
	},
}

local h_list_items = {
	["West"] = true,
	["East"] = true,
}

function GedPropDirectionsSet:UpdateValue()
	self.idContainer:DeleteChildren()
	self.idContainer:SetLayoutMethod("VList")
	self.idContainer:SetHAlign("left")

	for _, item in ipairs(self.items) do
		local h_list = h_list_items[item.value]
		if h_list and not self:HasMember("idHListCont") then
			XWindow:new({
				Id = "idHListCont",
				LayoutMethod = "HList",
				LayoutHSpacing = 10,
			}, self.idContainer)
		end
		local button = self:CreateButton(item, h_list and self.idHListCont)
		button:SetHAlign("center")
	end
	
	GedPropEditor.UpdateValue(self)
end

end --Platform.ged


DefineClass.PropertyDefAccuracyChart = {
	__parents = { "PropertyDef" },
	properties = {
		{ category = "Browse", id = "default", name = "Default value", editor = "text", default = "", },
	},
	editor = "accuracy_chart",
	EditorName = "Accuracy chart",
	EditorSubmenu = "Extras",
}

function GetRangeAccuracy_Ref(props_cont, distance, unit, action)
	local effective_range_acc = 100
	local point_blank_acc = 100
	
	local weapon_range
	if unit and action then
		weapon_range = action:GetMaxAimRange(unit, props_cont)
	end
	
	if not weapon_range then
		weapon_range = props_cont.WeaponRange or props_cont:GetProperty("WeaponRange")
	end
	distance = (1.0 * distance) / const.SlabSizeX
	
	local y0 = 1.0 * point_blank_acc
	--local xm, ym = 1.0 * props_cont.EffectiveRange, 1.0 * effective_range_acc
	--local xr = 1.0 * props_cont.ExtremeRange
	local xm, ym = 0.5 * weapon_range, 1.0 * effective_range_acc
	local xr = 1.0 * weapon_range
	local a, b, c = 0, 0, 0
	
	--[[if distance >= xr then
		return 0
	end--]]

--[[	if distance <= 0 then
		return point_blank_acc
	--elseif distance >= xr then
--		return 0
	elseif distance == xm then
		return effective_range_acc
	elseif distance < xm then
		-- first parabola
		a = -(ym - y0) / (xm*xm)
		b = 2 * (ym - y0) / xm
		c = y0	--]]
	if distance <= xm then
		return effective_range_acc
	else
		-- second parabola
		a = -ym / ((xm-xr)*(xm-xr))
		b = -2 * a * xm
		c = -a*xr*xr - b*xr
	end
	
	--return Max(0, round(a * distance * distance + b * distance + c, 1))
	return round(a * distance * distance + b * distance + c, 1)
end

function GetRangeAccuracy(weapon, distance, unit, action)
	local effective_range_acc = 100
	local point_blank_acc = 100
	
	local weapon_range
	if unit and action then
		weapon_range = action:GetMaxAimRange(unit, weapon)
	end
	
	if not weapon_range then
		weapon_range = weapon.WeaponRange or weapon:GetProperty("WeaponRange")
	end
	
	if IsKindOf(unit, "UnitBase") then
		weapon_range = unit:CallReactions_Modify("OnUnitGetWeaponRange", weapon_range, weapon, action)
	end

	local y0 = point_blank_acc
	local xm, ym = weapon_range / 2, effective_range_acc
	local xr = weapon_range
	local a, b, c = 0, 0, 0
	
	if distance / const.SlabSizeX <= xm then
		return effective_range_acc
	else
		-- second parabola
		a = MulDivRound(-ym, const.SlabSizeX, (xm-xr)*(xm-xr))
		b = MulDivRound(-2 * a, xm, const.SlabSizeX)
		c = MulDivRound(-a, xr*xr, const.SlabSizeX) - b*xr
	end
	
	local part = MulDivRound(MulDivRound(a, distance, const.SlabSizeX), distance, const.SlabSizeX*const.SlabSizeX)
	return part + MulDivRound(b, distance, const.SlabSizeX) + c
end

if FirstLoad then
	GedSatSectorSaveModsInProgress = false
end

function GedSatSectorSaveMods()
	if not IsValidThread(GedSatSectorSaveModsInProgress) then
		local thread = CanYield() and CurrentThread()
		GedSatSectorSaveModsInProgress = CreateRealTimeThread(function()
			local mods = {}
			ForEachPresetExtended("CampaignPreset", function(preset, group)
				if preset:IsDirty() then
					for _, satSectorPreset in ipairs(preset.Sectors) do
						local mod_id = satSectorPreset.modId
						if mod_id then
							mods[mod_id] = Mods[mod_id]
						end
					end
				end
			end)
			
			local can_save = true
			for _, mod in pairs(mods) do
				if not mod:CanSaveMod(ged) then
					can_save = false
					break
				end
			end
			if can_save then
				GedSetUiStatus("mod_save", "Saving mods...")
				for _, mod in pairs(mods) do
					mod:SaveWholeMod()
				end
				GedSetUiStatus("mod_save")
			end
			
			GedSatSectorSaveModsInProgress = false
			Wakeup(thread)
		end)
		if thread then WaitWakeup(30000) end
	end
end

function GedCreateXBugReportDlg(summary, descr, files, params)
	local endUserVersion = not not Platform.goldmaster
	if Platform.steam and endUserVersion then
		local steam_beta, steam_branch = g_GedApp:Call("GedGetSteamBetaName")
		endUserVersion = not steam_beta or steam_branch == ""
	end
	
	local minimalVersion = not insideHG() and endUserVersion
	
	params = params or {}
	params.no_priority = not insideHG()
	params.no_platform_tags = not insideHG()
	params.force_save_check = "save as extra_info"
	
	if minimalVersion then
		table.set(params, "no_platform_tags", true)
		table.set(params, "no_game_tags", true)
		table.set(params, "no_header_combos", true)
		table.set(params, "no_attach_auto_save", true)
		table.set(params, "no_api_token",true)
	end
	
	local mod = g_GedApp:Call("GedGetLastEditedMod")
	local modRelated = g_GedApp:Call("GedAreModdingToolsActive")

	table.set(params, "mod", mod)
	table.set(params, "mod_related", modRelated)
	
	return CreateXBugReportDlg(summary, descr, files, params)
end

function OnMsg.GatherModItemDockedActions(obj, actions)
	if IsKindOf(obj, "Preset") or IsKindOf(obj, "ModItemSector") then
		local preset_class = g_Classes[obj.ModdedPresetClass]
		local class = preset_class and (preset_class.PresetClass or preset_class.class)
		local name = IsKindOf(obj, "ModItemSector") and "Satellite sectors editor" or
			preset_class.EditorMenubarName ~= "" and preset_class.EditorMenubarName or (class .. " editor")
			
		actions["PresetEditor"] = {
			name = "Open in " .. name,
			rolloverText = "Open the dedicated editor for this item,\nalongside the rest of the game content.",
			op = "GedOpOpenModItemPresetEditor",
		}
	end
end

function GedOpOpenModItemPresetEditor(socket, obj, selection, a, b, c)
	if IsKindOf(obj, "ModItemSector") then
		obj:POpenGedSatelliteSectorEditor(socket)
	elseif obj and obj.ModdedPresetClass then
		obj:OpenEditor()
	end
end

if Platform.editor then
	function XSelectObjectsTool:PreDeleteConfirmation()
		-- Only in modding mod and when the map is not replaced with a ModItemSector
		if editor.IsModdingEditor() and not mapdata.ModMapPath then
			local display_warn = false
			local sel = editor.GetSel()
			for _, obj in ipairs(sel) do
				if IsKindOf(obj, "GridMarker") or IsKindOf(obj, "Room") or IsKindOf(obj, "TacticalCameraCollider") then
					display_warn = true
					break
				end
			end
			-- Display a warning message to modders that are deleting important game objects from the map
			if display_warn then
				local title = "Warning"
				local question = "You are about to delete objects that are an integral part of the original Jagged Alliance 3 campaign.\nDo you want to proceed?"
				local game_question = StdMessageDialog:new({}, terminal.desktop, { question = true, title = title, text = question, ok_text = "Yes", cancel_text = "No" })
				game_question:Open()
				if game_question:Wait() == "ok" then
					return true -- approve the deletion
				end
				return false
			end
		end
		
		return true
	end
end