-
-
Notifications
You must be signed in to change notification settings - Fork 517
/
wzapi.h
1126 lines (993 loc) · 43.6 KB
/
wzapi.h
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
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
This file is part of Warzone 2100.
Copyright (C) 2011-2020 Warzone 2100 Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __INCLUDED_WZAPI_H__
#define __INCLUDED_WZAPI_H__
// Documentation stuff follows. The build system will parse the comment prefixes
// and sort the comments into the appropriate Markdown documentation files.
//== # Globals
//==
//== This section describes global variables (or 'globals' for short) that are
//== available from all scripts. You typically cannot write to these variables,
//== they are read-only.
//==
//__ # Events
//__
//__ This section describes event callbacks (or 'events' for short) that are
//__ called from the game when something specific happens. Which scripts
//__ receive them is usually filtered by player. Call ```receiveAllEvents(true)```
//__ to start receiving all events unfiltered.
//__
//-- # Functions
//--
//-- This section describes functions that can be called from scripts to make
//-- things happen in the game (usually called our script 'API').
//--
//;; # Game objects
//;;
//;; This section describes various **game objects** defined by the script interface,
//;; and which are both accepted by functions and returned by them. Changing the
//;; fields of a **game object** has no effect on the game before it is passed to a
//;; function that does something with the **game object**.
//;;
#include "lib/framework/frame.h"
#include <nonstd/optional.hpp>
#include "basedef.h"
#include "structuredef.h"
#include "featuredef.h"
#include "lib/framework/wzconfig.h"
#include "hci.h"
#include "gateway.h"
using nonstd::optional;
using nonstd::nullopt;
#include <string>
#include <vector>
#include <memory>
#include <functional>
typedef uint64_t uniqueTimerID;
class timerAdditionalData
{
public:
virtual ~timerAdditionalData() { }
public:
virtual void onTimerDelete(uniqueTimerID, BASE_OBJECT*) { };
};
typedef std::function<void (uniqueTimerID, BASE_OBJECT*, timerAdditionalData *)> TimerFunc;
// NOTES:
// - All position value types (scr_position, scr_area, etc) passed to/from scripts expect map coordinates
enum timerType
{
TIMER_REPEAT, TIMER_ONESHOT_READY, TIMER_ONESHOT_DONE, TIMER_REMOVED
};
struct scr_radius
{
int32_t x; int32_t y; int32_t radius;
};
struct scr_area
{
int32_t x1; int32_t y1; int32_t x2; int32_t y2;
};
struct scr_position
{
int32_t x; int32_t y;
};
// Utility conversion functions
BASE_OBJECT *IdToObject(OBJECT_TYPE type, int id, int player);
// MARK: - wzapi
namespace wzapi
{
#define WZAPI_NO_PARAMS_NO_CONTEXT
#define WZAPI_NO_PARAMS const wzapi::execution_context& context
#define WZAPI_PARAMS(...) const wzapi::execution_context& context, __VA_ARGS__
#define WZAPI_BASE_PARAMS(...) const wzapi::execution_context_base& context, __VA_ARGS__
#define SCRIPTING_EVENT_NON_REQUIRED { return false; }
struct researchResult; // forward-declare
template<typename T>
struct event_nullable_ptr
{
private:
using TYPE_POINTER = T*;
TYPE_POINTER pt;
public:
event_nullable_ptr(TYPE_POINTER _pt)
: pt(_pt)
{ }
event_nullable_ptr()
: pt(nullptr)
{ }
operator TYPE_POINTER&()
{
return pt;
}
operator TYPE_POINTER() const
{
return pt;
}
explicit operator bool() const noexcept
{
return pt != nullptr;
}
};
class scripting_event_handling_interface
{
public:
virtual ~scripting_event_handling_interface() { };
public:
// MARK: General events
//__ ## eventGameInit()
//__
//__ An event that is run once as the game is initialized. Not all game state may have been
//__ properly initialized by this time, so use this only to initialize script state.
//__
virtual bool handle_eventGameInit() = 0;
//__ ## eventStartLevel()
//__
//__ An event that is run once the game has started and all game data has been loaded.
//__
virtual bool handle_eventStartLevel() = 0;
//__ ## eventMissionTimeout()
//__
//__ An event that is run when the mission timer has run out.
//__
virtual bool handle_eventMissionTimeout() SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventVideoDone()
//__
//__ An event that is run when a video show stopped playing.
//__
virtual bool handle_eventVideoDone() SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventGameLoaded()
//__
//__ An event that is run when game is loaded from a saved game. There is usually no need to use this event.
//__
virtual bool handle_eventGameLoaded() SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventGameSaving()
//__
//__ An event that is run before game is saved. There is usually no need to use this event.
//__
virtual bool handle_eventGameSaving() SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventGameSaved()
//__
//__ An event that is run after game is saved. There is usually no need to use this event.
//__
virtual bool handle_eventGameSaved() SCRIPTING_EVENT_NON_REQUIRED
public:
// MARK: Transporter events
//__ ## eventTransporterLaunch(transport)
//__
//__ An event that is run when the mission transporter has been ordered to fly off.
//__
virtual bool handle_eventLaunchTransporter() SCRIPTING_EVENT_NON_REQUIRED // DEPRECATED!
virtual bool handle_eventTransporterLaunch(const BASE_OBJECT *psTransport) SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventTransporterArrived(transport)
//__
//__ An event that is run when the mission transporter has arrived at the map edge with reinforcements.
//__
virtual bool handle_eventReinforcementsArrived() SCRIPTING_EVENT_NON_REQUIRED // DEPRECATED!
virtual bool handle_eventTransporterArrived(const BASE_OBJECT *psTransport) SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventTransporterExit(transport)
//__
//__ An event that is run when the mission transporter has left the map.
//__
virtual bool handle_eventTransporterExit(const BASE_OBJECT *psObj) SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventTransporterDone(transport)
//__
//__ An event that is run when the mission transporter has no more reinforcements to deliver.
//__
virtual bool handle_eventTransporterDone(const BASE_OBJECT *psTransport) SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventTransporterLanded(transport)
//__
//__ An event that is run when the mission transporter has landed with reinforcements.
//__
virtual bool handle_eventTransporterLanded(const BASE_OBJECT *psTransport) SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventTransporterEmbarked(transport)
//__
//__ An event that is run when a unit embarks into a transporter.
//__
virtual bool handle_eventTransporterEmbarked(const BASE_OBJECT *psTransport) SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventTransporterDisembarked(transport)
//__
//__ An event that is run when a unit disembarks from a transporter.
//__
virtual bool handle_eventTransporterDisembarked(const BASE_OBJECT *psTransport) SCRIPTING_EVENT_NON_REQUIRED
public:
// MARK: UI-related events (intended for the tutorial)
//__ ## eventDeliveryPointMoving()
//__
//__ An event that is run when the current player starts to move a delivery point.
//__
virtual bool handle_eventDeliveryPointMoving(const BASE_OBJECT *psStruct) SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventDeliveryPointMoved()
//__
//__ An event that is run after the current player has moved a delivery point.
//__
virtual bool handle_eventDeliveryPointMoved(const BASE_OBJECT *psStruct) SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventDesignBody()
//__
//__ An event that is run when current user picks a body in the design menu.
//__
virtual bool handle_eventDesignBody() SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventDesignPropulsion()
//__
//__ An event that is run when current user picks a propulsion in the design menu.
//__
virtual bool handle_eventDesignPropulsion() SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventDesignWeapon()
//__
//__ An event that is run when current user picks a weapon in the design menu.
//__
virtual bool handle_eventDesignWeapon() SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventDesignCommand()
//__
//__ An event that is run when current user picks a command turret in the design menu.
//__
virtual bool handle_eventDesignCommand() SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventDesignSystem()
//__
//__ An event that is run when current user picks a system other than command turret in the design menu.
//__
virtual bool handle_eventDesignSystem() SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventDesignQuit()
//__
//__ An event that is run when current user leaves the design menu.
//__
virtual bool handle_eventDesignQuit() SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventMenuBuildSelected()
//__
//__ An event that is run when current user picks something new in the build menu.
//__
virtual bool handle_eventMenuBuildSelected(/*BASE_OBJECT *psObj*/) SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventMenuResearchSelected()
//__
//__ An event that is run when current user picks something new in the research menu.
//__
virtual bool handle_eventMenuResearchSelected(/*BASE_OBJECT *psObj*/) SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventMenuBuild()
//__
//__ An event that is run when current user opens the build menu.
//__
virtual bool handle_eventMenuBuild() SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventMenuResearch()
//__
//__ An event that is run when current user opens the research menu.
//__
virtual bool handle_eventMenuResearch() SCRIPTING_EVENT_NON_REQUIRED
virtual bool handle_eventMenuDesign() SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventMenuManufacture()
//__
//__ An event that is run when current user opens the manufacture menu.
//__
virtual bool handle_eventMenuManufacture() SCRIPTING_EVENT_NON_REQUIRED
//__ ## eventSelectionChanged(objects)
//__
//__ An event that is triggered whenever the host player selects one or more game objects.
//__ The ```objects``` parameter contains an array of the currently selected game objects.
//__ Keep in mind that the player may drag and drop select many units at once, select one
//__ unit specifically, or even add more selections to a current selection one at a time.
//__ This event will trigger once for each user action, not once for each selected or
//__ deselected object. If all selected game objects are deselected, ```objects``` will
//__ be empty.
//__
virtual bool handle_eventSelectionChanged(const std::vector<const BASE_OBJECT *>& objects) SCRIPTING_EVENT_NON_REQUIRED
public:
// MARK: Game state-change events
//__ ## eventObjectRecycled()
//__
//__ An event that is run when an object (ex. droid, structure) is recycled.
//__
virtual bool handle_eventObjectRecycled(const BASE_OBJECT *psObj) = 0;
//__ ## eventPlayerLeft(player)
//__
//__ An event that is run after a player has left the game.
//__
virtual bool handle_eventPlayerLeft(int player) = 0;
//__ ## eventCheatMode(entered)
//__
//__ Game entered or left cheat/debug mode.
//__ The entered parameter is true if cheat mode entered, false otherwise.
//__
virtual bool handle_eventCheatMode(bool entered) = 0;
//__ ## eventDroidIdle(droid)
//__
//__ A droid should be given new orders.
//__
virtual bool handle_eventDroidIdle(const DROID *psDroid) = 0;
//__ ## eventDroidBuilt(droid[, structure])
//__
//__ An event that is run every time a droid is built. The structure parameter is set
//__ if the droid was produced in a factory. It is not triggered for droid theft or
//__ gift (check ```eventObjectTransfer``` for that).
//__
virtual bool handle_eventDroidBuilt(const DROID *psDroid, optional<const STRUCTURE *> psFactory) = 0;
//__ ## eventStructureBuilt(structure[, droid])
//__
//__ An event that is run every time a structure is produced. The droid parameter is set
//__ if the structure was built by a droid. It is not triggered for building theft
//__ (check ```eventObjectTransfer``` for that).
//__
virtual bool handle_eventStructureBuilt(const STRUCTURE *psStruct, optional<const DROID *> psDroid) = 0;
//__ ## eventStructureDemolish(structure[, droid])
//__
//__ An event that is run every time a structure begins to be demolished. This does
//__ not trigger again if the structure is partially demolished.
//__
virtual bool handle_eventStructureDemolish(const STRUCTURE *psStruct, optional<const DROID *> psDroid) = 0;
//__ ## eventStructureReady(structure)
//__
//__ An event that is run every time a structure is ready to perform some
//__ special ability. It will only fire once, so if the time is not right,
//__ register your own timer to keep checking.
//__
virtual bool handle_eventStructureReady(const STRUCTURE *psStruct) = 0;
//__ ## eventStructureUpgradeStarted(structure)
//__
//__ An event that is run every time a structure starts to be upgraded.
//__
virtual bool handle_eventStructureUpgradeStarted(const STRUCTURE *psStruct) = 0;
//__ ## eventAttacked(victim, attacker)
//__
//__ An event that is run when an object belonging to the script's controlling player is
//__ attacked. The attacker parameter may be either a structure or a droid.
//__
virtual bool handle_eventAttacked(const BASE_OBJECT *psVictim, const BASE_OBJECT *psAttacker) = 0;
//__ ## eventResearched(research, structure, player)
//__
//__ An event that is run whenever a new research is available. The structure
//__ parameter is set if the research comes from a research lab owned by the
//__ current player. If an ally does the research, the structure parameter will
//__ be set to null. The player parameter gives the player it is called for.
//__
virtual bool handle_eventResearched(const researchResult& research, event_nullable_ptr<const STRUCTURE> psStruct, int player) = 0;
//__ ## eventDestroyed(object)
//__
//__ An event that is run whenever an object is destroyed. Careful passing
//__ the parameter object around, since it is about to vanish!
//__
virtual bool handle_eventDestroyed(const BASE_OBJECT *psVictim) = 0;
//__ ## eventPickup(feature, droid)
//__
//__ An event that is run whenever a feature is picked up. It is called for
//__ all players / scripts.
//__ Careful passing the parameter object around, since it is about to vanish! (3.2+ only)
//__
virtual bool handle_eventPickup(const FEATURE *psFeat, const DROID *psDroid) = 0;
//__ ## eventObjectSeen(viewer, seen)
//__
//__ An event that is run sometimes when an object, which was marked by an object label,
//__ which was reset through resetLabel() to subscribe for events, goes from not seen to seen.
//__ An event that is run sometimes when an objectm goes from not seen to seen.
//__ First parameter is **game object** doing the seeing, the next the game
//__ object being seen.
virtual bool handle_eventObjectSeen(const BASE_OBJECT *psViewer, const BASE_OBJECT *psSeen) = 0;
//__
//__ ## eventGroupSeen(viewer, group)
//__
//__ An event that is run sometimes when a member of a group, which was marked by a group label,
//__ which was reset through resetLabel() to subscribe for events, goes from not seen to seen.
//__ First parameter is **game object** doing the seeing, the next the id of the group
//__ being seen.
//__
virtual bool handle_eventGroupSeen(const BASE_OBJECT *psViewer, int groupId) = 0;
//__ ## eventObjectTransfer(object, from)
//__
//__ An event that is run whenever an object is transferred between players,
//__ for example due to a Nexus Link weapon. The event is called after the
//__ object has been transferred, so the target player is in object.player.
//__ The event is called for both players.
//__
virtual bool handle_eventObjectTransfer(const BASE_OBJECT *psObj, int from) = 0;
//__ ## eventChat(from, to, message)
//__
//__ An event that is run whenever a chat message is received. The ```from``` parameter is the
//__ player sending the chat message. For the moment, the ```to``` parameter is always the script
//__ player.
//__
virtual bool handle_eventChat(int from, int to, const char *message) = 0;
//__ ## eventBeacon(x, y, from, to[, message])
//__
//__ An event that is run whenever a beacon message is received. The ```from``` parameter is the
//__ player sending the beacon. For the moment, the ```to``` parameter is always the script player.
//__ Message may be undefined.
//__
virtual bool handle_eventBeacon(int x, int y, int from, int to, optional<const char *> message) = 0;
//__ ## eventBeaconRemoved(from, to)
//__
//__ An event that is run whenever a beacon message is removed. The ```from``` parameter is the
//__ player sending the beacon. For the moment, the ```to``` parameter is always the script player.
//__
virtual bool handle_eventBeaconRemoved(int from, int to) = 0;
//__ ## eventGroupLoss(gameObject, groupId, newSize)
//__
//__ An event that is run whenever a group becomes empty. Input parameter
//__ is the about to be killed object, the group's id, and the new group size.
//__
// // Since groups are entities local to one context, we do not iterate over them here.
virtual bool handle_eventGroupLoss(const BASE_OBJECT *psObj, int group, int size) = 0;
//__ ## eventArea<label>(droid)
//__
//__ An event that is run whenever a droid enters an area label. The area is then
//__ deactived. Call resetArea() to reactivate it. The name of the event is
//__ `eventArea${label}`.
//__
virtual bool handle_eventArea(const std::string& label, const DROID *psDroid) = 0;
//__ ## eventDesignCreated(template)
//__
//__ An event that is run whenever a new droid template is created. It is only
//__ run on the client of the player designing the template.
//__
virtual bool handle_eventDesignCreated(const DROID_TEMPLATE *psTemplate) = 0;
//__ ## eventAllianceOffer(from, to)
//__
//__ An event that is called whenever an alliance offer is requested.
//__
virtual bool handle_eventAllianceOffer(uint8_t from, uint8_t to) = 0;
//__ ## eventAllianceAccepted(from, to)
//__
//__ An event that is called whenever an alliance is accepted.
//__
virtual bool handle_eventAllianceAccepted(uint8_t from, uint8_t to) = 0;
//__ ## eventAllianceBroken(from, to)
//__
//__ An event that is called whenever an alliance is broken.
//__
virtual bool handle_eventAllianceBroken(uint8_t from, uint8_t to) = 0;
public:
// MARK: Special input events
//__ ## eventSyncRequest(req_id, x, y, obj_id, obj_id2)
//__
//__ An event that is called from a script and synchronized with all other scripts and hosts
//__ to prevent desync from happening. Sync requests must be carefully validated to prevent
//__ cheating!
//__
virtual bool handle_eventSyncRequest(int from, int req_id, int x, int y, const BASE_OBJECT *psObj, const BASE_OBJECT *psObj2) = 0;
//__ ## eventKeyPressed(meta, key)
//__
//__ An event that is called whenever user presses a key in the game, not counting chat
//__ or other pop-up user interfaces. The key values are currently undocumented.
virtual bool handle_eventKeyPressed(int meta, int key) SCRIPTING_EVENT_NON_REQUIRED
};
enum class GlobalVariableFlags
{
None = 0,
ReadOnly = 1 << 0, // binary 0001
ReadOnlyUpdatedFromApp = 1 << 1, // binary 0010
DoNotSave = 1 << 2, // binary 0100
};
inline GlobalVariableFlags operator | (GlobalVariableFlags lhs, GlobalVariableFlags rhs)
{
using T = std::underlying_type<GlobalVariableFlags>::type;
return static_cast<GlobalVariableFlags>(static_cast<T>(lhs) | static_cast<T>(rhs));
}
inline GlobalVariableFlags& operator |= (GlobalVariableFlags& lhs, GlobalVariableFlags rhs)
{
lhs = lhs | rhs;
return lhs;
}
inline GlobalVariableFlags operator& (GlobalVariableFlags lhs, GlobalVariableFlags rhs)
{
using T = std::underlying_type<GlobalVariableFlags>::type;
return static_cast<GlobalVariableFlags>(static_cast<T>(lhs) & static_cast<T>(rhs));
}
inline GlobalVariableFlags& operator&= (GlobalVariableFlags& lhs, GlobalVariableFlags rhs)
{
lhs = lhs & rhs;
return lhs;
}
class scripting_instance : public scripting_event_handling_interface
{
public:
scripting_instance(int player, const std::string& scriptName, const std::string& scriptPath);
virtual ~scripting_instance();
public:
virtual bool readyInstanceForExecution() = 0;
public:
const std::string& scriptName() const { return m_scriptName; }
const std::string& scriptPath() const { return m_scriptPath; }
int player() const { return m_player; }
bool isHostAI() const;
public:
inline void setReceiveAllEvents(bool value) { m_isReceivingAllEvents = value; }
inline bool isReceivingAllEvents() const { return m_isReceivingAllEvents; }
public:
// Helpers for loading a file from the "context" of a scripting_instance
class LoadFileSearchOptions
{
public:
static const uint32_t ScriptPath_FileNameOnlyBackwardsCompat = 0x00000001;
static const uint32_t ScriptPath = 0x00000002;
static const uint32_t DataDir = 0x00000004;
static const uint32_t ConfigScriptDir = 0x00000008;
static const uint32_t All = ScriptPath | DataDir | ConfigScriptDir;
static const uint32_t All_BackwardsCompat = ScriptPath_FileNameOnlyBackwardsCompat | All;
};
// Loads a file.
// (Intended for use from implementations of things like "include" functions.)
//
// Lookup order is as follows (based on the value of `searchFlags`):
// - 1.) The filePath is checked relative to the read-only data dir search paths (LoadFileSearchOptions::DataDir)
// - 2.) The filePath is checked relative to "<user's config dir>/script/" (LoadFileSearchOptions::ConfigScriptDir)
// - 3.) The filename *only* is checked relative to the main scriptPath (LoadFileSearchOptions::ScriptPath_FileNameOnlyBackwardsCompat) - for backwards-compat only
// - 4.) The filePath is checked relative to the main scriptPath (LoadFileSearchOptions::ScriptPath)
bool loadFileForInclude(const std::string& filePath, std::string& loadedFilePath, char **ppFileData, UDWORD *pFileSize, uint32_t searchFlags = LoadFileSearchOptions::All);
public:
// event handling
// - see `scripting_event_handling_interface`
public:
// save / restore state
virtual bool saveScriptGlobals(nlohmann::json &result) = 0;
virtual bool loadScriptGlobals(const nlohmann::json &result) = 0;
virtual nlohmann::json saveTimerFunction(uniqueTimerID timerID, std::string timerName, const timerAdditionalData* additionalParam) = 0;
// recreates timer functions (and additional userdata) based on the information saved by the saveTimerFunction() method
virtual std::tuple<TimerFunc, std::unique_ptr<timerAdditionalData>> restoreTimerFunction(const nlohmann::json& savedTimerFuncData) = 0;
public:
// get state for debugging
virtual nlohmann::json debugGetAllScriptGlobals() = 0;
enum class DebugSpecialStringType {
TYPE_DESCRIPTION
};
virtual std::unordered_map<std::string, DebugSpecialStringType> debugGetScriptGlobalSpecialStringValues();
virtual bool debugEvaluateCommand(const std::string &text) = 0;
public:
// output to debug log file
void dumpScriptLog(const std::string &info);
void dumpScriptLog(const std::string &info, int me);
public:
virtual void updateGameTime(uint32_t gameTime) = 0;
virtual void updateGroupSizes(int group, int size) = 0;
// set "global" variables
//
// expects: a json object (keys ("variable names") -> values)
//
// as appropriate for this scripting_instance, modifies "global variables" that scripts can access
// for each key in the json object, it sets the appropriate "global variable" to the associated value
//
// only modifies global variables for keys in the json object - if other global variables already exist
// in this scripting_instance (ex. from a prior call to this function), they are maintained
//
// flags: - GlobalVariableFlags::ReadOnly - if supported by the scripting instance, should set constant / read-only variables
// that the script(s) themselves cannot modify (but may be updated by WZ via future calls to this function)
// - GlobalVariableFlags::DoNotSave - indicates that the global variable(s) should not be saved by saveScriptGlobals()
virtual void setSpecifiedGlobalVariables(const nlohmann::json& variables, GlobalVariableFlags flags = GlobalVariableFlags::ReadOnly | GlobalVariableFlags::DoNotSave) = 0;
virtual void setSpecifiedGlobalVariable(const std::string& name, const nlohmann::json& value, GlobalVariableFlags flags = GlobalVariableFlags::ReadOnly | GlobalVariableFlags::DoNotSave) = 0;
private:
int m_player;
std::string m_scriptName;
std::string m_scriptPath;
bool m_isReceivingAllEvents = false;
};
class execution_context_base
{
public:
virtual ~execution_context_base();
public:
virtual void throwError(const char *expr, int line, const char *function) const = 0;
};
class execution_context : public execution_context_base
{
public:
virtual ~execution_context();
public:
virtual wzapi::scripting_instance* currentInstance() const = 0;
int player() const;
void set_isReceivingAllEvents(bool value) const;
bool get_isReceivingAllEvents() const;
virtual playerCallbackFunc getNamedScriptCallback(const WzString& func) const = 0;
virtual void doNotSaveGlobal(const std::string &global) const = 0;
};
struct game_object_identifier
{
game_object_identifier() { }
game_object_identifier(const BASE_OBJECT* psObj)
: type(psObj->type)
, id(psObj->id)
, player(psObj->player)
{ }
int type;
int id = -1;
int player = -1;
};
struct droid_id_player
{
int id = -1;
int player = -1;
};
struct reservedParam
{ };
struct string_or_string_list
{
std::vector<std::string> strings;
};
struct va_list_treat_as_strings
{
std::vector<std::string> strings;
};
template<typename ContainedType>
struct va_list
{
std::vector<ContainedType> va_list;
};
struct optional_position
{
bool valid;
int x;
int y;
};
struct specified_player
{
int player = -1;
};
struct STRUCTURE_TYPE_or_statsName_string
{
STRUCTURE_TYPE type = NUM_DIFF_BUILDINGS;
std::string statsName;
};
struct object_request
{
public:
object_request();
object_request(const std::string& label);
object_request(int x, int y);
object_request(OBJECT_TYPE type, int player, int id);
public:
enum class RequestType
{
INVALID_REQUEST,
LABEL_REQUEST,
MAPPOS_REQUEST,
OBJECTID_REQUEST
};
public:
const std::string& getLabel() const;
scr_position getMapPosition() const;
std::tuple<OBJECT_TYPE, int, int> getObjectIDRequest() const;
public:
const RequestType requestType;
private:
const std::string str;
const int val1 = -1;
const int val2 = -1;
const int val3 = -1;
};
struct label_or_position_values
{
private:
const int VERY_LOW_INVALID_POS_VALUE = -2;
public:
label_or_position_values() { }
label_or_position_values(const std::string &label)
: type(Type::Label_Request)
, label(label)
{ }
label_or_position_values(int32_t x1, int32_t y1, optional<int32_t> x2 = nullopt, optional<int32_t> y2 = nullopt)
: type(Type::Position_Values_Request)
, x1(x1), y1(y1), x2(x2), y2(y2)
{ }
public:
inline bool isValid() { return type != Type::Invalid_Request; }
inline bool isLabel() { return type == Type::Label_Request; }
inline bool isPositionValues() { return type == Type::Position_Values_Request; }
public:
enum Type
{
Invalid_Request,
Label_Request,
Position_Values_Request
};
Type type = Invalid_Request;
int32_t x1 = VERY_LOW_INVALID_POS_VALUE;
int32_t y1 = VERY_LOW_INVALID_POS_VALUE;
optional<int32_t> x2;
optional<int32_t> y2;
std::string label;
};
// retVals
struct no_return_value
{ };
struct researchResult
{
researchResult() { }
researchResult(const RESEARCH * psResearch, int player)
: psResearch(psResearch)
, player(player)
{ }
const RESEARCH * psResearch = nullptr;
int player;
};
struct researchResults
{
std::vector<const RESEARCH *> resList;
int player;
};
template<typename T>
struct returned_nullable_ptr
{
private:
using TYPE_POINTER = T*;
TYPE_POINTER pt;
public:
returned_nullable_ptr(TYPE_POINTER _pt)
: pt(_pt)
{ }
returned_nullable_ptr()
: pt(nullptr)
{ }
operator TYPE_POINTER&()
{
return pt;
}
operator TYPE_POINTER() const
{
return pt;
}
explicit operator bool() const noexcept
{
return pt != nullptr;
}
};
class GameEntityRules
{
public:
typedef std::map<std::string, int> NameToTypeMap;
GameEntityRules(int player, unsigned index, const NameToTypeMap& nameToTypeMap)
: player(player)
, index(index)
, propertyNameToTypeMap(nameToTypeMap)
{ }
public:
using value_type = nlohmann::json;
value_type getPropertyValue(const wzapi::execution_context_base& context, const std::string& name) const;
value_type setPropertyValue(const wzapi::execution_context_base& context, const std::string& name, const value_type& newValue);
public:
inline NameToTypeMap::const_iterator begin() const
{
return propertyNameToTypeMap.cbegin();
}
inline NameToTypeMap::const_iterator end() const
{
return propertyNameToTypeMap.cend();
}
inline int getPlayer() const { return player; }
inline int getIndex() const { return index; }
private:
// context
int player = -1;
unsigned index = 0;
NameToTypeMap propertyNameToTypeMap;
};
class GameEntityRuleContainer
{
public:
typedef std::string GameEntityName;
typedef std::pair<GameEntityName, GameEntityRules> GameEntityRulesPair;
public:
GameEntityRuleContainer()
{ }
inline void addRules(const GameEntityName& statsName, GameEntityRules&& entityRules)
{
rules.emplace_back(GameEntityRulesPair{statsName, std::move(entityRules)});
lookup_table[statsName] = rules.size() - 1;
}
public:
inline GameEntityRules& operator[](const GameEntityName& statsName)
{
return rules.at(lookup_table.at(statsName)).second;
}
inline std::vector<GameEntityRulesPair>::const_iterator begin() const
{
return rules.cbegin();
}
inline std::vector<GameEntityRulesPair>::const_iterator end() const
{
return rules.cend();
}
private:
std::vector<GameEntityRulesPair> rules;
std::unordered_map<GameEntityName, size_t> lookup_table;
};
class PerPlayerUpgrades
{
public:
typedef std::string GameEntityClass;
public:
PerPlayerUpgrades(int player)
: player(player)
{ }
inline void addGameEntity(const GameEntityClass& entityClass, GameEntityRuleContainer&& rulesContainer)
{
upgrades.emplace(entityClass, std::move(rulesContainer));
}
public:
inline GameEntityRuleContainer& operator[](const GameEntityClass& entityClass)
{
return upgrades[entityClass];
}
inline const GameEntityRuleContainer* find(const GameEntityClass& entityClass) const
{
auto it = upgrades.find(entityClass);
if (it == upgrades.end())
{
return nullptr;
}
return &(it->second);
}
inline int getPlayer() const { return player; }
inline std::map<GameEntityClass, GameEntityRuleContainer>::const_iterator begin() const
{
return upgrades.cbegin();
}
inline std::map<GameEntityClass, GameEntityRuleContainer>::const_iterator end() const
{
return upgrades.cend();
}
private:
std::map<GameEntityClass, GameEntityRuleContainer> upgrades;
int player = 0;
};
#define MULTIPLAY_SYNCREQUEST_REQUIRED
#define MUTLIPLAY_UNSAFE
#define WZAPI_DEPRECATED
#define WZAPI_AI_UNSAFE
std::string translate(WZAPI_PARAMS(std::string str));
int32_t syncRandom(WZAPI_PARAMS(uint32_t limit));
bool setAlliance(WZAPI_PARAMS(int player1, int player2, bool areAllies));
no_return_value sendAllianceRequest(WZAPI_PARAMS(int player2));
bool orderDroid(WZAPI_PARAMS(DROID* psDroid, int order));
bool orderDroidBuild(WZAPI_PARAMS(DROID* psDroid, int order, std::string structureName, int x, int y, optional<float> direction));
bool setAssemblyPoint(WZAPI_PARAMS(STRUCTURE *psStruct, int x, int y));
bool setSunPosition(WZAPI_PARAMS(float x, float y, float z));
bool setSunIntensity(WZAPI_PARAMS(float ambient_r, float ambient_g, float ambient_b, float diffuse_r, float diffuse_g, float diffuse_b, float specular_r, float specular_g, float specular_b));
bool setFogColour(WZAPI_PARAMS(int r, int g, int b));
bool setWeather(WZAPI_PARAMS(int weatherType));
bool setSky(WZAPI_PARAMS(std::string textureFilename, float windSpeed, float scale));
bool cameraSlide(WZAPI_PARAMS(float x, float y));
bool cameraZoom(WZAPI_PARAMS(float viewDistance, float speed));
bool cameraTrack(WZAPI_PARAMS(optional<DROID *> _droid));
uint32_t addSpotter(WZAPI_PARAMS(int x, int y, int player, int range, bool radar, uint32_t expiry));
bool removeSpotter(WZAPI_PARAMS(uint32_t spotterId));
bool syncRequest(WZAPI_PARAMS(int32_t req_id, int32_t x, int32_t y, optional<const BASE_OBJECT *> _psObj, optional<const BASE_OBJECT *> _psObj2));
bool replaceTexture(WZAPI_PARAMS(std::string oldFilename, std::string newFilename));
bool changePlayerColour(WZAPI_PARAMS(int player, int colour));
bool setHealth(WZAPI_PARAMS(BASE_OBJECT* psObject, int health)); MULTIPLAY_SYNCREQUEST_REQUIRED
bool useSafetyTransport(WZAPI_PARAMS(bool flag));
bool restoreLimboMissionData(WZAPI_NO_PARAMS);
uint32_t getMultiTechLevel(WZAPI_NO_PARAMS);
bool setCampaignNumber(WZAPI_PARAMS(int campaignNumber));
int32_t getMissionType(WZAPI_NO_PARAMS);
bool getRevealStatus(WZAPI_NO_PARAMS);
bool setRevealStatus(WZAPI_PARAMS(bool status));
bool autoSave(WZAPI_NO_PARAMS);
// horrible hacks follow -- do not rely on these being present!
no_return_value hackNetOff(WZAPI_NO_PARAMS);
no_return_value hackNetOn(WZAPI_NO_PARAMS);
no_return_value hackAddMessage(WZAPI_PARAMS(std::string message, int messageType, int player, bool immediate));