-
Notifications
You must be signed in to change notification settings - Fork 0
/
shk_taskmaster.sqf
538 lines (487 loc) · 21.2 KB
/
shk_taskmaster.sqf
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
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
/* == TASKMASTER ===============================================================================
Version 0.31
Author: Shuko (shuko@quakenet, miika@miikajarvinen.fi)
== Creating a briefing =======================================================================
Tasks and notes are given in the init.sqf.
Syntax: [[[Task1Data],[Task2Data]],[[Note1Data],[Note2Data]]] execvm "shk_taskmaster.sqf";
Example:
[[
["Task1","Task1Title","Task1Desc"],
["Task2","Task2Title","Task2Desc",true,["markerTask2",getpos obj2]]
],[
["Note1","Hello West",WEST],
["Note2","Hello East",EAST],
["Credits","<br />Made by: Shuko of LDD Kyllikki<br />Contact: shuko@Quakenet<br />www.kyllikki.fi"]
]] execvm "shk_taskmaster.sqf";
-- Task Data ---------------------------------------------------------------------------------
["TaskName","Title","Description",Condition,[Marker],"State"]
Required parameters:
TaskName string Name used to refer to the task
Title string Task name shown in the in/game task list
Description string Task description, the actual text body
Optional parameters:
Condition boolean/side/faction/unit/group/string Units the task is added to. Default is everyone
Marker array Marker related to the task. It will be created only for the units who have the task. Marker will be hidden after task is completed.
Name string Name of the marker to create.
Position string Position of the marker.
Type string Marker type. Optional, default is "selector_selectedMission".
Color string Marker color. Optional, default is red.
State string Task state of the newly created task. Default is "created".
Destination object/position/marker Place to create task destination (game's built-in waypoint/marker). If an object is given, setSimpleTaskTarget command is used, attaching the destination to it.
- Condition -
It's possible to specify which units (groups, side etc) you want to create the tasks/notes for.
Examples:
[...,WEST] All playable units on BLUFOR (WEST)
[...,"USMC"] Faction USMC
[...,grpMarine1] Units that belong to group named grpMarine1
[...,myDude] Unit named myDude
Then there is the IF syntax, so you can create a condition anyway you want, where _x is the unit (=player).
Examples:
"((group _x == grpScouts) OR (_x == pilot1))" Members of grpScouts and unit named pilot1
"(typeof _x == ""CDF_Soldier_Sniper"")" All CDF snipers
-- Note Data ---------------------------------------------------------------------------------
[NoteTitle,NoteText,Condition]
Required parameters:
NoteTitle string Text shown in the list
NoteText string The actual note text body
Optional parameters:
Condition boolean/side/faction/unit/group/string Units the note is added to. Default is everyone.
== Updating tasks ============================================================================
Task states are updated by calling a function. Possible states are: succeeded/failed/canceled/assigned/created.
Example: ["Task1","succeeded"] call SHK_Taskmaster_upd;
It's possible to set state of one task and set another as assigned using an optional 3rd parameter.
Example: ["Task1","succeeded","Task2"] call SHK_Taskmaster_upd;
This will make task state of task Task1 to succeeded and the state of the task Task2 as assigned.
Another optional 3rd parameter can be used to add a new task after updating another task.
Example: ["Task1","succeeded",["Task2","Title","Desc"]] call SHK_Taskmaster_upd;
This will make task Task1 as succeeded and create a new task Task2. Same set of parameters is used for the
creation as in init.sqf or SHK_Taskmaster_add.
== Creating tasks during a mission ===========================================================
Tasks can be added after briefing with the add function. Same set of parameters is used as in creating a
briefing.
Example: ["Task2","Extraction","Get to teh choppa!"] call SHK_Taskmaster_add;
== Checking task status ======================================================================
SHK_Taskmaster_isCompleted
This function can be used to check if a task is completed. Task is considered completed with states
succeeded, failed and canceled. Function returns a boolean (true/false) value.
Example: "Task1" call SHK_Taskmaster_isCompleted
SHK_Taskmaster_getAssigned
Returns list of tasks which have "assigned" as their state.
Example: call SHK_Taskmaster_getAssigned
Example result: ["Task1","Task4"]
SHK_Taskmaster_getState
Returns the task state (succeeded/failed/canceled/assigned/created).
Example: "Task1" call SHK_Taskmaster_getState
SHK_Taskmaster_hasState
Checks if a task's state matches the given state. Function returns a boolean value.
Example: ["Task1","succeeded"] call SHK_Taskmaster_hasState
SHK_Taskmaster_hasTask
Checks if a task with the given name has been created. Returns boolean.
Example: "Task1" call SHK_Taskmaster_hasTask
SHK_Taskmaster_addNote (client only)
Creates a briefing note. This can only be used on client side, and it's not boardcasted for
other players.
Parameters: ["Title","TextBody",Condition]
Condition is optional.
Example: Example: ["Enemy forces","Oh noes, there will be enemy soldiers in the area of operation."] call SHK_Taskmaster_addNote
== Version history ======================================================================
0.31 Fixed: Change in v0.29 broke task state update for JIPs. States were being overwritten by setcurrenttask command.
0.30 Added: Parameter to create task destination.
0.29 Added: Last task to be added will be made current task automatically.
0.28 Fixed: Markers of completed tasks were not hidden for JIPs.
0.27 Fixed: Attempt to prevent double tasks from being added when the add parameter is used with the update function.
0.26 Added: Script can be called without parameters, just to load the functions for later use.
0.25 Changed: 1.55 patch changed note addition order to same as tasks. Code changed to keep the old way of adding them.
0.24 Changed: Marker handling. Hiding/showing has been removed and replaced with local marker creation.
0.23 Added: Support for Single Player missions. Mainly to enable tasks in the SP mission editor preview.
0.22 Changed: Made add, assign and update functions useable in triggers without getting undefined variable error on clients.
0.21 Changed: Script can now be started with call as well as execvm.
0.20 Added: Support for non-dedicated servers.
0.13 Added: SHK_Taskmaster_initDone variable will be set to true once tasks are processed and functions loaded.
0.12 Fixed: Task updates now wait for player to be alive (after respawn etc).
0.11 Fixed: Missed !isnull player check, which caused problems in marker handling.
*/
DEBUG = false;
/* == COMMON =================================================================================== */
SHK_Taskmaster_initDone = false;
SHK_Taskmaster_add = {
/* Take a task data array, apply default params if needed, save to the task list. Send to clients.
In: array ["Name","Title","Desc",[Marker],"State",Destination]
Out:
*/
if isserver then {
private ["_name","_short","_long","_cond","_marker","_state","_dest"];
_name = _this select 0;
_short = _this select 1;
_long = _this select 2;
if (count _this > 3) then { _cond = _this select 3 } else { _cond = true };
if (count _this > 4) then { _marker = _this select 4 } else { _marker = [] };
if (count _this > 5) then { _state = _this select 5 } else { _state = "created" };
if (count _this > 6) then { _dest = _this select 6 } else { _dest = 0 };
SHK_Taskmaster_Tasks set [count SHK_Taskmaster_Tasks, [_name,_short,_long,_cond,_marker,_state,_dest]];
publicvariable "SHK_Taskmaster_Tasks";
/*
Update for host of the non-dedicated server.
*/
if (!isdedicated && SHK_Taskmaster_initDone) then {
SHK_Taskmaster_Tasks spawn SHK_Taskmaster_handleEvent;
};
};
};
SHK_Taskmaster_addNote = {
/* Creates a briefing note.
In: array ["Title","TextBody",Condition]
Out:
*/
private "_cond";
if (count _this > 2) then { _cond = _this select 2 } else { _cond = true };
{
if ( [_x,_cond] call SHK_Taskmaster_checkCond ) then {
_x creatediaryrecord ["Diary",[_this select 0,_this select 1]];
if (time > 10) then{ hintsilent "Diary note added." };
};
} foreach (if ismultiplayer then {playableunits} else {switchableunits});
};
SHK_Taskmaster_addTask = {
/* Creates the given task for each playableunit and saves the handles.
Adds a task array with name, state and handles to the local task list.
If marker exists, it will be shown or hidden depending if the unit has the task.
In: array ["Name","Title","Desc",[Marker],"State",Destination]
*/
private ["_handle","_handles","_name","_state","_marker","_dest"];
_handles = [];
_name = _this select 0;
_marker = _this select 4;
_state = _this select 5;
_dest = _this select 6;
if DEBUG then { diag_log format ["SHK_Taskmaster> addTask: %1, %2, %3, %4",_name,_marker,_state,_dest]};
{
if ( [_x,(_this select 3)] call SHK_Taskmaster_checkCond ) then {
_handle = _x createsimpletask [_name];
_handle setsimpletaskdescription [(_this select 2),(_this select 1),""];
_handle settaskstate _state;
if (_state in ["created","assigned"]) then {
_x setcurrenttask _handle;
};
switch (toupper(typename _dest)) do {
case "OBJECT": { _handle setsimpletasktarget [_dest,true] };
case "STRING": { _handle setsimpletaskdestination (getmarkerpos _dest) };
case "ARRAY": { _handle setsimpletaskdestination _dest };
};
_handles set [count _handles,_handle];
if (_x == player) then {
if (SHK_Taskmaster_showHints) then { [_handle,_state] call SHK_Taskmaster_showHint };
if (count _marker > 0) then {
if !(_state in ["succeeded","failed","canceled"]) then {
private ["_m","_t","_c"];
_m = createmarkerlocal [(_marker select 0),(_marker select 1)];
_m setmarkershapelocal "ICON";
_t = if (count _marker > 2) then {(_marker select 2)} else {"selector_selectedMission"};
_m setmarkertypelocal _t;
_c = if (count _marker > 3) then {(_marker select 3)} else {"ColorRed"};
_m setmarkercolorlocal _c;
};
};
};
};
} foreach (if ismultiplayer then {playableunits} else {switchableunits});
SHK_Taskmaster_TasksLocal set [count SHK_Taskmaster_TasksLocal,[_name,_state,_handles]];
};
SHK_Taskmaster_assign = {
/* Changes task's state to assigned.
In: string "Name"
Out:
*/
if isserver then {
private "_task";
for "_i" from 0 to (count SHK_Taskmaster_Tasks - 1) do {
if (_this == ((SHK_Taskmaster_Tasks select _i) select 0)) then {
_task =+ SHK_Taskmaster_Tasks select _i;
_task set [5,"assigned"];
SHK_Taskmaster_Tasks set [_i,_task];
};
};
publicvariable "SHK_Taskmaster_Tasks";
/*
Update for host of the non-dedicated server.
*/
if (!isdedicated && SHK_Taskmaster_initDone) then {
SHK_Taskmaster_Tasks spawn SHK_Taskmaster_handleEvent;
};
};
};
SHK_Taskmaster_checkCond = {
/* Checks if given unit fulfills the requirement.
In: array [Unit,Condition]
Out: boolean
*/
private ["_unit","_cond"];
_unit = _this select 0;
_cond = _this select 1;
if (!isNil "_cond") then {
if DEBUG then { diag_log format ["SHK_Taskmaster> typename condition: %1",typename _cond]};
switch (typename _cond) do {
case (typename grpNull): { (_unit in (units _cond)) };
case (typename objNull): { _unit == _cond };
case (typename WEST): { (side _unit == _cond) };
case (typename true): { _cond };
case (typename ""): {
if (_cond in ["USMC","INS","CDF","RU","CIV","GUE","CIV_RU"]) then {
(faction _unit == _cond)
} else {
(call compile format ["%1",_cond])
};
};
default { false };
};
} else { false };
};
SHK_Taskmaster_getAssigned = {
/* Returns list of tasks which have "assigned" as their state.
In:
Out: array ["TaskName","TaskName"]
*/
private "_l";
_l = [];
{
if ((_x select 5) == "assigned") then {
_l set [count _l,(_x select 0)];
};
} foreach SHK_Taskmaster_Tasks;
_l;
};
SHK_Taskmaster_getState = {
/* Returns state of the given task.
In: string "Name"
Out: string "State"
*/
private "_s";
{
if (_this == (_x select 0)) exitwith {
_s = (_x select 5);
};
} foreach SHK_Taskmaster_Tasks;
_s;
};
SHK_Taskmaster_handleEvent = {
/* Takes the pubvar'd task array and determines if a task needs to be added or updated.
In: array SHK_Taskmaster_Tasks from pubvar eventhandler
Out:
*/
waituntil {alive player};
private "_name";
{
_name = _x select 0;
if (_name call SHK_Taskmaster_hasTaskLocal) then {
if ([_name,(_x select 5)] call SHK_Taskmaster_hasStateChanged) then {
if DEBUG then { diag_log format ["SHK_Taskmaster> handleEvent calling updateTask: %1",_name]};
_x call SHK_Taskmaster_updateTask;
};
} else {
if DEBUG then { diag_log format ["SHK_Taskmaster> handleEvent calling addTask: %1",_name]};
_x call SHK_Taskmaster_addTask;
};
} foreach _this;
};
SHK_Taskmaster_hasState = {
/* Checks if given task has a specific state.
In: array ["Name","State"]
Out: boolean
*/
private "_b";
_b = false;
{
if ((_this select 0) == (_x select 0)) then {
if (((_this select 0) call SHK_Taskmaster_getState) == (_this select 1)) then {
_b = true;
};
};
} foreach SHK_Taskmaster_Tasks;
_b;
};
SHK_Taskmaster_hasStateChanged = {
/* Checks if the task state of the given task has changed.
In: array ["TaskName","TaskState"]
Out: boolean
*/
private "_b";
_b = false;
{
if ((_this select 0) == (_x select 0)) then {
if ((_this select 1) != (_x select 1)) exitwith {
_b = true;
};
};
} foreach SHK_Taskmaster_TasksLocal;
_b;
};
SHK_Taskmaster_hasTask = {
/* Checks if task with given name already exists.
In: string Task name
Out: boolean
*/
private "_b";
_b = false;
{
if (_this == (_x select 0)) exitwith { _b = true };
} foreach SHK_Taskmaster_Tasks;
_b;
};
SHK_Taskmaster_hasTaskLocal = {
/* Checks if task with given name already exists.
In: string Task name
Out: boolean
*/
private "_b";
_b = false;
{
if (_this == (_x select 0)) exitwith { _b = true };
} foreach SHK_Taskmaster_TasksLocal;
_b;
};
SHK_Taskmaster_isCompleted = {
private "_b";
_b = false;
{
if (_this == (_x select 0)) then {
if ((_x select 5) in ["succeeded","failed","canceled"]) then {
_b = true;
};
};
} foreach SHK_Taskmaster_Tasks;
_b;
};
SHK_Taskmaster_showHint = {
private "_p";
_p = switch (tolower (_this select 1)) do {
case "created": { [localize "str_taskNew", [1,1,1,1], "taskNew"] };
case "current": { [localize "str_taskSetCurrent", [1,1,1,1], "taskCurrent"] };
case "assigned": { [localize "str_taskSetCurrent", [1,1,1,1], "taskCurrent"] };
case "succeeded": { [localize "str_taskAccomplished", [0.600000,0.839215,0.466666,1.000000], "taskDone"] };
case "failed": { [localize "str_taskFailed", [0.972549,0.121568,0.000000,1.000000], "taskFailed"] };
case "canceled": { [localize "str_taskCancelled", [0.750000,0.750000,0.750000,1.000000], "taskFailed"] };
};
taskHint [format [(_p select 0) + "\n%1", ((taskDescription (_this select 0)) select 1)], (_p select 1), (_p select 2)];
};
SHK_Taskmaster_upd = {
/* Take a task data array, update the task list. Send to clients.
In: array ["Name","Title","Desc",[Marker],"State"]
Out:
*/
if isserver then {
private ["_task","_state"];
_state = (_this select 1);
for "_i" from 0 to (count SHK_Taskmaster_Tasks - 1) do {
_task =+ (SHK_Taskmaster_Tasks select _i);
if ((_task select 0) == (_this select 0)) then {
_task set [5,_state];
};
SHK_Taskmaster_Tasks set [_i,_task];
};
if (count _this > 2) then {
switch (typename (_this select 2)) do {
case (typename ""): { (_this select 2) call SHK_Taskmaster_assign };
case (typename []): { (_this select 2) spawn { sleep 1; _this call SHK_Taskmaster_add} };
};
};
publicvariable "SHK_Taskmaster_Tasks";
/*
Update for host of the non-dedicated server.
*/
if (!isdedicated && SHK_Taskmaster_initDone) then {
SHK_Taskmaster_Tasks spawn SHK_Taskmaster_handleEvent;
};
};
};
SHK_Taskmaster_updateTask = {
/* Updates task state for all playableunits and local task list.
Delete marker of completed task.
In: array ["Name","Title","Desc",[Marker],"State"]
Out:
*/
private ["_task","_name","_state","_handle","_marker"];
for "_i" from 0 to (count SHK_Taskmaster_TasksLocal - 1) do {
_task =+ SHK_Taskmaster_TasksLocal select _i;
_name = _task select 0;
if (_name == (_this select 0)) then {
_marker = _this select 4;
_state = _this select 5;
_task set [1,_state];
SHK_Taskmaster_TasksLocal set [_i,_task];
{
_handle = _x;
{
if (_handle in (simpletasks _x)) then {
_handle settaskstate _state;
if (_x == player) then {
if (SHK_Taskmaster_showHints) then { [_handle,_state] call SHK_Taskmaster_showHint };
if (count _marker > 0) then {
if (_state in ["succeeded","failed","canceled"]) then {
if DEBUG then { diag_log format ["SHK_Taskmaster> updateTask deleting marker: %1, state: %2",_marker,_state]};
deletemarkerlocal (_marker select 0);
};
};
};
};
} foreach (if ismultiplayer then {playableunits} else {switchableunits});
} foreach (_task select 2);
};
};
};
/* == SERVER =================================================================================== */
if isserver then {
SHK_Taskmaster_Tasks = []; // Array member: ["Name","Title","Desc","Marker","State"]
/*
Iterate through the tasks received from init.sqf and add them to an array. Then send it to clients.
*/
if (!isnil "_this") then {
if (count _this > 0) then {
private ["_task","_tasks","_i"];
_tasks = _this select 0;
for [{_i=(count _tasks - 1)},{_i>-1},{_i=_i-1}] do {
(_tasks select _i) call SHK_Taskmaster_add;
};
};
};
publicvariable "SHK_Taskmaster_Tasks";
if DEBUG then {
diag_log "-- SHK_Taskmaster_Tasks --";
diag_log SHK_Taskmaster_Tasks;
};
};
/* == CLIENT =================================================================================== */
if !isdedicated then {
SHK_Taskmaster_showHints = false;
SHK_Taskmaster_TasksLocal = []; // Array member: ["TaskName","TaskState",TaskHandles]
/*
If any notes given in init.sqf, simply add them.
*/
if (!isnil "_this") then {
if (count _this > 1) then {
private ["_notes","_i"];
_notes = _this select 1;
for [{_i=(count _notes - 1)},{_i>-1},{_i=_i-1}] do {
(_notes select _i) call SHK_Taskmaster_addNote;
};
};
};
/*
Initially wait for server to send the task list for briefing. After briefing is created, add
an eventhandler to catch the updated task list server might send.
Wait for briefing tasks to be created before enabling taskhints. This prevents hints from briefing tasks
from being spammed at the start of the mission.
*/
[] spawn {
waituntil {!isnull player};
waituntil {!isnil "SHK_Taskmaster_Tasks"};
if DEBUG then {diag_log format ["SHK_Taskmaster> Tasks received first time: %1",SHK_Taskmaster_Tasks]};
private "_sh";
_sh = SHK_Taskmaster_Tasks spawn SHK_Taskmaster_handleEvent;
waituntil {scriptdone _sh};
SHK_Taskmaster_showHints = true;
SHK_Taskmaster_initDone = true;
"SHK_Taskmaster_Tasks" addpublicvariableeventhandler {
(_this select 1) spawn SHK_Taskmaster_handleEvent;
};
};
};