File: Script.c

package info (click to toggle)
openclonk 8.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 169,500 kB
  • sloc: cpp: 180,478; ansic: 108,988; xml: 31,371; python: 1,223; php: 767; makefile: 139; sh: 101; javascript: 34
file content (315 lines) | stat: -rw-r--r-- 7,907 bytes parent folder | download | duplicates (5)
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
/**
	ControllerActionBar

	Shows a small preview next to the crew portraits of what happens on CON_Interact.

	@authors Zapper, Clonkonaut
*/

// HUD margin and size in tenths of em.
// !!! Does also use the following constants from ControllerCrewBar.ocd:
// GUI_Controller_CrewBar_IconSize
// GUI_Controller_CrewBar_IconMargin
// GUI_Controller_CrewBar_CursorSize
// GUI_Controller_CrewBar_CursorMargin

// !!! Does also use all the ACTIONTYPE_* constants from ClonkControl.ocd

local current_interaction;

local actionbar_gui_menu;
local actionbar_gui_id;

/* GUI creation */

// For custom HUD graphics overload the following function as deemed fit.

func AssembleActionBar()
{
	// Calculate margin + width of crew portraits
	var icon_margin = GUI_Controller_CrewBar_CursorMargin +
	                  GUI_Controller_CrewBar_CursorSize +
	                  GUI_Controller_CrewBar_IconMargin +
	                  GUI_Controller_CrewBar_IconSize +
	                  GUI_Controller_CrewBar_IconMargin;
	var icon_size = icon_margin + GUI_Controller_CrewBar_IconSize;

	return
	{
		Target = this,
		Player = NO_OWNER, // will be shown only if there is an interaction possible, e.g. standing in front of a vehicle
		Style = GUI_Multiple | GUI_NoCrop | GUI_IgnoreMouse,
		Left = ToEmString(icon_margin),
		Right = ToEmString(icon_size),
		Top = ToEmString(GUI_Controller_CrewBar_IconMargin),
		Bottom = ToEmString(GUI_Controller_CrewBar_IconMargin + GUI_Controller_CrewBar_IconSize),
		Symbol = Icon_Menu_RectangleRounded,
		Priority = 1,
		key =// the interaction key
		{
			Target = this,
			Style = GUI_NoCrop | GUI_TextHCenter | GUI_TextBottom,
			Left = "-50%",
			Right = "150%",
			Top = ToEmString(-6),
			Bottom = ToEmString(4),
			Text = Format("<c dddd00>[%s]</c>", GetPlayerControlAssignment(GetOwner(), CON_Interact, true)),
			Priority = 2
		},
		symbol =// the object to interact with
		{
			Target = this,
			Symbol = nil,
			Priority = 3
		},
		icon =// small icon visualising the action
		{
			Target = this,
			Style = GUI_NoCrop,
			Left = "50%",
			Top = "50%",
			Symbol = nil,
			Priority = 4
		},
		text =// interaction description
		{
			Target = this,
			Style = GUI_NoCrop | GUI_TextHCenter,
			Left = "-50%",
			Right = "150%",
			Top = ToEmString(GUI_Controller_CrewBar_IconSize - 5),
			Bottom = ToEmString(GUI_Controller_CrewBar_IconMargin + GUI_Controller_CrewBar_IconSize + 15),
			Text = "",
			Priority = 5
		},
		plus =// shown if there are multiple interactions
		{
			Target = this,
			Player = NO_OWNER,
			ID = 1,
			Style = GUI_NoCrop,
			Left = ToEmString(GUI_Controller_CrewBar_IconSize / 2),
			Right = ToEmString(GUI_Controller_CrewBar_IconSize * 3 / 2),
			Bottom = ToEmString(GUI_Controller_CrewBar_IconSize / 2),
			Symbol = Icon_Number,
			GraphicsName = "PlusGreen",
			Priority = 6
		}
	};
}

/* Creation / Destruction */

private func Construction()
{

	actionbar_gui_menu = AssembleActionBar();

	actionbar_gui_id = GuiOpen(actionbar_gui_menu);

	EnableInteractionUpdating(true);
	return _inherited(...);
}

private func Destruction()
{
	GuiClose(actionbar_gui_id);
	EnableInteractionUpdating(false);
	current_interaction = nil;
	_inherited(...);
}

public func SetCurrentInteraction(proplist interaction)
{
	// Already showing?
	if (DeepEqual(interaction, current_interaction)) return;
	
	if (interaction == nil)
	{
		HideInteraction();
		return;
	}
	
	// Display that information
	current_interaction = interaction;
	actionbar_gui_menu.Player = GetOwner();
	// We can assert that we have a cursor here.
	var cursor = GetCursor(GetOwner());
	var help = GetInteractionHelp(current_interaction, cursor);
	
	var update = {
		Player = GetOwner(),
		symbol =
		{
			Symbol = current_interaction.interaction_object
		},
		icon =
		{
			Symbol = help.help_icon,
			GraphicsName = help.help_icon_graphics
		},
		text =
		{
			Text = help.help_text
		}
	};

	GuiUpdate(update, actionbar_gui_id);
	
	return help;
}

public func GetCurrentInteraction()
{
	return current_interaction;
}

/* Timer */

public func EnableInteractionUpdating(bool enable)
{
	var fx = GetEffect("IntUpdateInteraction", this);
	if (fx && !enable)
		RemoveEffect(nil, nil, fx);
	else if (!fx && enable)
		AddEffect("IntUpdateInteraction", this, 1, 10, this);
}

/*
	Searched for interactable objects and updates the display.
*/
public func UpdateInteractionObject()
{
	var cursor = GetCursor(GetOwner());
	if (!cursor || !cursor->GetCrewEnabled())
	{
		HideInteraction();
		return;
	}

	var interactables = cursor->~GetInteractableObjects();
	if (!interactables || !GetLength(interactables))
	{
		HideInteraction();
		return;
	}

	// Get the interaction with the highest priority
	var high_prio = nil;
	for (var interactable in interactables)
		if (high_prio == nil || (interactable.priority < high_prio.priority)) high_prio = interactable;

	// If there are multiple interactions, show plus sign
	if (GetLength(interactables) > 1)
	{
		if (actionbar_gui_menu.plus.Player != GetOwner())
		{
			actionbar_gui_menu.plus.Player = GetOwner();
			GuiUpdate({ Player = GetOwner() }, actionbar_gui_id, 1, this);
		}
	}
	else
	{
		if (actionbar_gui_menu.plus.Player == GetOwner())
		{
			actionbar_gui_menu.plus.Player = NO_OWNER;
			GuiUpdate({ Player = NO_OWNER }, actionbar_gui_id, 1, this);
		}
	}
	
	SetCurrentInteraction(high_prio);
}

// Runs every 10 frames to look for possible interactable objects and shows the interaction icon if applicable
private func FxIntUpdateInteractionTimer()
{
	UpdateInteractionObject();
	return FX_OK;
}

// Does hide the interaction icon
private func HideInteraction()
{
	// Already hidden, do nothing
	if (actionbar_gui_menu.Player == NO_OWNER) return;

	actionbar_gui_menu.Player = NO_OWNER;
	current_interaction = nil;
	GuiUpdate({ Player = NO_OWNER }, actionbar_gui_id);
}

/* Returns a proplist with the following properties to display:
help_text: A text describing the interaction or ""
help_icon: A pictographic icon definition symbolising the interaction or nil
help_icon_graphics: The graphics of the icon definition to use or ""
*/
private func GetInteractionHelp(proplist interaction, object clonk)
{
	var actiontype = interaction.actiontype;
	var to_interact = interaction.interaction_object;
	var interaction_index = interaction.interaction_index;
	
	var ret =
	{
		help_text = "",
		help_icon = nil,
		help_icon_graphics = ""
	};

	// Help text: Grabbing / Ungrabbing / Pushing out
	if (actiontype == ACTIONTYPE_VEHICLE)
	{
		if (clonk->Contained() && to_interact->Contained() == clonk->Contained())
		{
			ret.help_text = Format("$TxtPushOut$", to_interact->GetName());
			ret.help_icon = Icon_Exit;
		}
		else if (clonk->GetProcedure() == "PUSH" && clonk->GetActionTarget() == to_interact)
		{
			ret.help_text = Format("$TxtUnGrab$", to_interact->GetName());
			ret.help_icon = Icon_LetGo;
		}
		else
		{
			ret.help_text = Format("$TxtGrab$", to_interact->GetName());
			ret.help_icon = Icon_Grab;
		}
	}

	// Help text: Enter / Exit
	if (actiontype == ACTIONTYPE_STRUCTURE)
	{
		if (clonk->Contained() && clonk->Contained() == to_interact)
		{
			ret.help_text = Format("$TxtExit$", to_interact->GetName());
			ret.help_icon = Icon_Exit;
		}
		else
		{
			ret.help_text = Format("$TxtEnter$", to_interact->GetName());
			ret.help_icon = Icon_Enter;
		}
	}

	// Help text: Script Interaction
	if (actiontype == ACTIONTYPE_SCRIPT)
	{
		var metainfo = to_interact->~GetInteractionMetaInfo(clonk, interaction_index);
		if (metainfo)
		{
			ret.help_text = metainfo.Description;
			ret.help_icon = metainfo.IconID;
			ret.help_icon_graphics = metainfo.IconName;
		}
	}

	// Help text: Extra Interaction (already in proplist)
	if (actiontype == ACTIONTYPE_EXTRA)
	{
		ret.help_text = interaction.extra_data.Description;
		ret.help_icon = interaction.extra_data.IconID;
		ret.help_icon_graphics = interaction.extra_data.IconName;
	}

	return ret;
}