File size: 4,859 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
ColorModifierReasons = {
	--override this in your project
	--{id = "reason_name", weight = default reason weight number, color = default reason color},
}

MapVar("ColorModifierReasonsData", false)
local table_find = table.find
local SetColorModifier = CObject.SetColorModifier
local GetColorModifier = CObject.GetColorModifier
local clrNoModifier = const.clrNoModifier
local default_color_modifier = RGBA(100, 100, 100, 0)

function SetColorModifierReason(obj, reason, color, weight, blend, skip_attaches)
	assert(reason)
	if not reason then
		return
	end
	local color_value = color
	
	if obj:GetRadius() > 0 then
		local data = ColorModifierReasonsData
		if not data then
			data = {}
			ColorModifierReasonsData = data 
		end
		local mrt = data[obj]
		local orig_color
		if not mrt then
			orig_color = GetColorModifier(obj)
			mrt = { orig_color = orig_color }
			data[obj] = mrt
		end
		
		local rt = ColorModifierReasons
		local idx = table_find(rt, "id", reason)
		local rdata = idx and rt[idx] or false
		
		color = color or rdata and rdata.color or nil
		if not color then
			printf("[WARNING] SetColorModifierReason no color! reason %s, color %s, weight %s", reason, tostring(color), tostring(weight))
			return
		end
		weight = weight or rdata and rdata.weight or const.DefaultColorModWeight
		if not weight then
			printf("[WARNING] SetColorModifierReason no weight! reason %s, color %s, weight %s", reason, tostring(color), tostring(weight))
			return
		end
		
		if blend then
			orig_color = orig_color or mrt.orig_color
			if orig_color ~= clrNoModifier then
				color = InterpolateRGB(orig_color, color, blend, 100)
			end
		end
		local idx = table_find(mrt, "reason", reason)
		local entry = idx and mrt[idx]
		if entry then
			entry.weight = weight
			entry.color = color
		else
			entry = { reason = reason, weight = weight, color = color }
			table.insert(mrt, entry)
		end
		table.stable_sort(mrt, function(a, b)
			return a.weight < b.weight
		end)
		SetColorModifier(obj, mrt[#mrt].color)
	end
	if skip_attaches then
		return
	end
	obj:ForEachAttach(SetColorModifierReason, reason, color_value, weight, blend)
end

function SetOrigColorModifier(obj, color, skip_attaches)
	local data = ColorModifierReasonsData
	local mrt = data and data[obj]
	if not mrt then
		SetColorModifier(obj, color)
	else
		mrt.orig_color = color
	end
	if skip_attaches then return end
	obj:ForEachAttach(SetOrigColorModifier, color)
end

function GetOrigColorModifier(obj)
	local modifier = GetColorModifier(obj)
	return modifier == default_color_modifier and table.get(ColorModifierReasonsData, obj, "orig_color") or modifier
end

function ValidateColorReasons()
	table.validate_map(ColorModifierReasonsData)
end

function ClearColorModifierReason(obj, reason, skip_color_change, skip_attaches)	
	assert(reason)
	if not reason then
		return
	end
	local data = ColorModifierReasonsData
	local mrt = data and data[obj]
	if mrt then
		if not IsValid(obj) then
			data[obj] = nil
			return
		end
		local idx = table_find(mrt, "reason", reason)
		if not idx then
			return
		end
		local update = idx == #mrt
		table.remove(mrt, idx)
		if #mrt == 0 then
			data[obj] = nil
			DelayedCall(1000, ValidateColorReasons)
			if not next(data) then
				ColorModifierReasonsData = false
			end
		end
		if update and not skip_color_change then
			local active = mrt[#mrt]
			local color = active and active.color or mrt.orig_color or const.clrNoModifier
			SetColorModifier(obj, color)
		end
	end
	if skip_attaches then
		return
	end
	obj:ForEachAttach(ClearColorModifierReason, reason, skip_color_change)
end

function ClearColorModifierReasons(obj)
	local data = ColorModifierReasonsData
	local mrt = data and data[obj]
	if not mrt then
		return
	end
	if IsValid(obj) then
		SetColorModifier(obj, mrt.orig_color or const.clrNoModifier)
		obj:ForEachAttach(ClearColorModifierReasons)
	end
	data[obj] = nil
end

OnMsg.StartSaveGame = ValidateColorReasons
	
----

MapVar("InvisibleReasons", {}, weak_keys_meta)

local efVisible = const.efVisible

function SetInvisibleReason(obj, reason)
	local invisible_reasons = InvisibleReasons
	local obj_reasons = invisible_reasons[obj]
	if obj_reasons then
		obj_reasons[reason] = true
		return
	end
	invisible_reasons[obj] = { [reason] = true }
	obj:ClearHierarchyEnumFlags(efVisible)
end

function ClearInvisibleReason(obj, reason)
	local invisible_reasons = InvisibleReasons
	local obj_reasons = invisible_reasons[obj]
	if not obj_reasons or not obj_reasons[reason] then
		return
	end
	obj_reasons[reason] = nil
	if next(obj_reasons) then
		return
	end
	invisible_reasons[obj] = nil
	obj:SetHierarchyEnumFlags(efVisible)
end

function ClearInvisibleReasons(obj)
	local invisible_reasons = InvisibleReasons
	if not invisible_reasons[obj] then
		return
	end
	invisible_reasons[obj] = nil
	obj:SetHierarchyEnumFlags(efVisible)
end

----