File: sexp.h

package info (click to toggle)
freespace2 24.2.0%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,716 kB
  • sloc: cpp: 595,001; ansic: 21,741; python: 1,174; sh: 457; makefile: 248; xml: 181
file content (1649 lines) | stat: -rw-r--r-- 55,486 bytes parent folder | download
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
/*
 * Copyright (C) Volition, Inc. 1999.  All rights reserved.
 *
 * All source code herein is the property of Volition, Inc. You may not sell 
 * or otherwise commercially exploit the source or things you created based on the 
 * source.
 *
*/

#ifndef _SEXP_H
#define _SEXP_H

#include "globalincs/globals.h"
#include "globalincs/pstypes.h"	// for NULL
#include "object/object_flags.h"
#include "ship/ship_flags.h"
#include "mission/mission_flags.h"
#include "ai/ai_flags.h"

class ship_subsys;
class ship;
class waypoint_list;
class object;
class waypoint;
class p_object;
struct ship_obj;

// bumped to 30 by Goober5000
#define	OPERATOR_LENGTH	30  // if this ever exceeds TOKEN_LENGTH, let JasonH know!

#define MAX_SEXP_VARIABLES 250

// Operator argument formats (data types of an argument)
enum sexp_opf_t : int {
	OPF_UNUSED,						// argument types need to start at 1 instead of 0
	OPF_NONE,						// argument cannot exist at this position if it's this
	OPF_NULL,						// no value.  Can still be used for type matching, however
	OPF_BOOL,
	OPF_NUMBER,
	OPF_SHIP,
	OPF_WING,
	OPF_SUBSYSTEM,
	OPF_POINT,						// either a 3d point in space, or a waypoint name
	OPF_IFF,
	OPF_AI_GOAL,					// special to match ai goals
	OPF_DOCKER_POINT,				// docking point on docker ship
	OPF_DOCKEE_POINT,				// docking point on dockee ship
	OPF_MESSAGE,					// the name (id) of a message in Messages[] array
	OPF_WHO_FROM,					// who sent the message -- doesn't necessarily have to be a ship!!!
	OPF_PRIORITY,					// priority for messages
	OPF_WAYPOINT_PATH,				// name of a waypoint
	OPF_POSITIVE,					// positive number or zero
	OPF_MISSION_NAME,				// name of a mission for various mission related things
	OPF_SHIP_POINT,					// a waypoint or a ship
	OPF_GOAL_NAME,					// name of goal (or maybe event?) from a mission
	OPF_SHIP_WING,					// either a ship or wing name (they don't conflict)
	OPF_SHIP_WING_WHOLETEAM,		// Karajorma - Ship, wing or an entire team's worth of ships
	OPF_SHIP_WING_SHIPONTEAM_POINT,	// name of a ship, wing, any ship on a team, or a point
	OPF_SHIP_WING_POINT,
	OPF_SHIP_WING_POINT_OR_NONE,	// WMC - Ship, wing, point or none
	OPF_SHIP_TYPE,					// type of ship (fighter/bomber/etc)
	OPF_KEYPRESS,					// a default key
	OPF_EVENT_NAME,					// name of an event
	OPF_AI_ORDER,					// a squadmsg order player can give to a ship
	OPF_SKILL_LEVEL,				// current skill level of the game
	OPF_MEDAL_NAME,					// name of medals
	OPF_WEAPON_NAME,				// name of a weapon
	OPF_SHIP_CLASS_NAME,			// name of a ship class
	OPF_CUSTOM_HUD_GAUGE,			// name of custom HUD gauge
	OPF_HUGE_WEAPON,				// name of a secondary bomb type weapon
	OPF_SHIP_NOT_PLAYER,			// a ship, but not a player ship
	OPF_JUMP_NODE_NAME,				// name of a jump node
	OPF_VARIABLE_NAME,				// variable name
	OPF_AMBIGUOUS,					// type used with variable
	OPF_AWACS_SUBSYSTEM,			// an awacs subsystem
	OPF_CARGO,						// Goober5000 - a cargo string (currently used for set-cargo and is-cargo)
	OPF_AI_CLASS,					// Goober5000 - an AI class
	OPF_SUPPORT_SHIP_CLASS,			// Goober5000 - a support ship class
	OPF_ARRIVAL_LOCATION,			// Goober5000 - a ship arrival location
	OPF_ARRIVAL_ANCHOR_ALL,			// Goober5000 - all of a ship's possible arrival anchors
	OPF_DEPARTURE_LOCATION,			// Goober5000 - a ship departure location
	OPF_SHIP_WITH_BAY,				// Goober5000 - a ship with a fighter bay
	OPF_SOUNDTRACK_NAME,			// Goober5000 - the name of a music soundtrack
	OPF_INTEL_NAME,					// Goober5000 - the name of an intel entry in species.tbl
	OPF_STRING,						// Goober5000 - any old string
	OPF_ROTATING_SUBSYSTEM,			// Goober5000 - a rotating subsystem
	OPF_NAV_POINT,					// Kazan	  - a Nav Point name
	OPF_SSM_CLASS,					// Goober5000 - an SSM class
	OPF_FLEXIBLE_ARGUMENT,			// Goober5000 - special to match for when-argument
	OPF_ANYTHING,					// Goober5000 - anything goes, except containers
	OPF_SKYBOX_MODEL_NAME,			// taylor - changing skybox model
	OPF_SHIP_OR_NONE,				// Goober5000 - an "optional" ship argument
	OPF_BACKGROUND_BITMAP,			// phreak - name of a background bitmap
	OPF_SUN_BITMAP,					// phreak - name of a background bitmap
	OPF_NEBULA_STORM_TYPE,			// phreak - name a nebula storm
	OPF_NEBULA_POOF,				// phreak - name of a nebula poof
	OPF_TURRET_TARGET_ORDER,		// WMC - name of a turret target type (see aiturret.cpp)
	OPF_SUBSYSTEM_OR_NONE,			// Goober5000 - an "optional" subsystem argument
	OPF_PERSONA,					// Karajorma - name of a persona
	OPF_SUBSYS_OR_GENERIC,			// Karajorma - a subsystem or a generic name (like engine) which covers all subsystems of that type
	OPF_ORDER_RECIPIENT,			// Karajorma - since orders can go to All Fighters as well as a ship or wing
	OPF_SUBSYSTEM_TYPE,				// Goober5000 - a generic subsystem type (navigation, engines, etc.) rather than a specific subsystem
	OPF_POST_EFFECT,				// Hery - type of post-processing effect
	OPF_TARGET_PRIORITIES,			// FUBAR - Target priority groups
	OPF_ARMOR_TYPE,					// FUBAR - Armor type or <none>
	OPF_FONT,						// Goober5000 - a FreeSpace font
	OPF_HUD_ELEMENT,				// A magic name of a specific HUD element
	OPF_SOUND_ENVIRONMENT,			// Goober5000 - one of EFX_presets, per Taylor
	OPF_SOUND_ENVIRONMENT_OPTION,	// Goober5000 - one of Taylor's options
	OPF_EXPLOSION_OPTION,			// Goober5000
	OPF_AUDIO_VOLUME_OPTION,		// The E
	OPF_WEAPON_BANK_NUMBER,			// Karajorma - The number of a primary/secondary/tertiary weapon bank or all of them
	OPF_MESSAGE_OR_STRING,			// Goober5000 - provides a list of messages like OPF_MESSAGE, but also allows entering arbitrary strings
	OPF_BUILTIN_HUD_GAUGE,			// The E
	OPF_DAMAGE_TYPE,				// FUBAR - Damage type or <none>
	OPF_SHIP_EFFECT,				// The E - per-ship effects, as defined in post-processing.tbl
	OPF_ANIMATION_TYPE,				// Goober5000 - as defined in modelanim.h
	OPF_MISSION_MOOD,				// Karajorma - Moods determine which builtin messages will be sent
	OPF_SHIP_FLAG,					// Karajorma - The name of a ship flag
	OPF_TEAM_COLOR,					// The E - Color settings as defined in Colors.tbl
	OPF_NEBULA_PATTERN,				// Axem - Full Nebula Background Patterns, as defined in nebula.tbl
	OPF_SKYBOX_FLAGS,				// niffiwan - valid skybox flags
	OPF_GAME_SND,					// m!m - A game sound
	OPF_FIREBALL,					// Goober5000 - an entry in fireball.tbl
	OPF_SPECIES,					// Goober5000
	OPF_LANGUAGE,					// Goober5000
	OPF_FUNCTIONAL_WHEN_EVAL_TYPE,	// Goober5000
	OPF_CONTAINER_NAME,				// Karajorma/jg18 - The name of a SEXP container
	OPF_LIST_CONTAINER_NAME,		// Karajorma/jg18 - The name of a SEXP list container
	OPF_MAP_CONTAINER_NAME,			// Karajorma/jg18 - The name of a SEXP map container
	OPF_ANIMATION_NAME,				// Lafiel
	OPF_CONTAINER_VALUE,			// jg18 - Container data and map container keys
	OPF_DATA_OR_STR_CONTAINER,		// jg18 - any data, or a container that is accessed via strings
	OPF_TRANSLATING_SUBSYSTEM,		// Goober5000 - a translating subsystem
	OPF_ANY_HUD_GAUGE,				// Goober5000 - both custom and builtin
	OPF_WING_FLAG,					// Goober5000 - The name of a wing flag
	OPF_ASTEROID_TYPES,				// MjnMixael - Asteroids from asteroids.tbl, asteroid types only
	OPF_DEBRIS_TYPES,				// MjnMixael - Asteroids from asteroids.tbl, debris types only
	OPF_WING_FORMATION,				// Goober5000 - as defined in ships.tbl
	OPF_MOTION_DEBRIS,				// MjnMixael - Motion debris types as defined in stars.tbl
	OPF_TURRET_TYPE,				// MjnMixael - Turret types as defined in aiturret.cpp
	OPF_BOLT_TYPE,					// MjnMixael - Lightning bolt types as defined in lightning.tbl
	OPF_TRAITOR_OVERRIDE,			// MjnMixael - Traitor overrides as defined in traitor.tbl
	OPF_LUA_GENERAL_ORDER,          // MjnMixael - General orders as defined in sexps.tbl
	OPF_CHILD_LUA_ENUM,			    // MjnMixael - Used to let Lua Enums reference Enums
	OPF_MISSION_CUSTOM_STRING,      // MjnMixael - The custom strings as defined in FRED
	OPF_MESSAGE_TYPE,      // naomimyselfandi - A message type (Attack Target et al.)

	//Must always be at the end of the list
	First_available_opf_id
};

struct dynamic_sexp_enum_list {
	SCP_string name;
	SCP_vector<SCP_string> list;
};

extern SCP_vector<dynamic_sexp_enum_list> Dynamic_enums;

struct dynamic_sexp_parameter_list {
	SCP_string operator_name;
	SCP_vector<std::pair<int, int>> parameter_map;
};

extern SCP_vector<dynamic_sexp_parameter_list> Dynamic_parameters;

struct dynamic_sexp_child_enum_suffixes {
	SCP_string operator_name;
	int param_index;
	SCP_string suffix;
};

extern SCP_vector<dynamic_sexp_child_enum_suffixes> Dynamic_enum_suffixes;

int get_dynamic_parameter_index(const SCP_string &op_name, int param);

int get_dynamic_enum_position(const SCP_string &enum_name);

SCP_string get_child_enum_suffix(const SCP_string& op_name, int param_index);

// Operand return types
enum sexp_opr_t : int {
	OPR_NONE,
	OPR_NUMBER,             // returns number
	OPR_BOOL,               // returns true/false value
	OPR_NULL,               // doesn't return a value
	OPR_AI_GOAL,	        // is an ai operator (doesn't really return a value, but used for type matching)
	OPR_POSITIVE,	        // returns a non-negative number
	OPR_STRING,             // not really a return type, but used for type matching.
	OPR_AMBIGUOUS,          // not really a return type, but used for type matching.
	OPR_FLEXIBLE_ARGUMENT,  // Goober5000 - is an argument operator (doesn't really return a value, but used for type matching)
};

#define	OP_INSERT_FLAG			0x8000
#define	OP_REPLACE_FLAG			0x4000

// if we ever have more than 1024 (!)
// total sexps, we're going to have to
// figure out a different way of
// distinguishing between sexp identifier
// and sexp array index
#define	FIRST_OP				0x0400

enum : int {
	OP_CATEGORY_NONE,
	OP_CATEGORY_OBJECTIVE,
	OP_CATEGORY_TIME,
	OP_CATEGORY_LOGICAL,
	OP_CATEGORY_ARITHMETIC,
	OP_CATEGORY_STATUS,
	OP_CATEGORY_CHANGE,
	OP_CATEGORY_CONDITIONAL,
	OP_CATEGORY_AI,
	OP_CATEGORY_TRAINING,
	OP_CATEGORY_UNLISTED,
	OP_CATEGORY_GOAL_EVENT,
	// this should come after every category
	First_available_category_id
};

// New subcategories! :) -- Goober5000
// Adding more subcategories is possible with the new code.  All that needs to be done is
// to add a line here, some appropriate case statements in get_subcategory() and
// category_from_subcategory(), and the submenu name in the op_submenu[] array in sexp.cpp.
enum : int {
	OP_SUBCATEGORY_NONE,
	CHANGE_SUBCATEGORY_MESSAGING,
	CHANGE_SUBCATEGORY_AI_CONTROL,
	CHANGE_SUBCATEGORY_SHIP_STATUS,
	CHANGE_SUBCATEGORY_SHIELDS_ENGINES_AND_WEAPONS,
	CHANGE_SUBCATEGORY_SUBSYSTEMS,
	CHANGE_SUBCATEGORY_CARGO,
	CHANGE_SUBCATEGORY_ARMOR_AND_DAMAGE_TYPES,
	CHANGE_SUBCATEGORY_BEAMS_AND_TURRETS,
	CHANGE_SUBCATEGORY_MODELS_AND_TEXTURES,
	CHANGE_SUBCATEGORY_COORDINATE_MANIPULATION,
	CHANGE_SUBCATEGORY_MISSION_AND_CAMPAIGN,
	CHANGE_SUBCATEGORY_MUSIC_AND_SOUND,
	CHANGE_SUBCATEGORY_HUD,
	CHANGE_SUBCATEGORY_NAV,
	CHANGE_SUBCATEGORY_CUTSCENES,
	CHANGE_SUBCATEGORY_BACKGROUND_AND_NEBULA,
	CHANGE_SUBCATEGORY_JUMP_NODES,
	CHANGE_SUBCATEGORY_SPECIAL_EFFECTS,
	CHANGE_SUBCATEGORY_VARIABLES,
	CHANGE_SUBCATEGORY_CONTAINERS,
	CHANGE_SUBCATEGORY_OTHER,
	STATUS_SUBCATEGORY_MISSION,
	STATUS_SUBCATEGORY_PLAYER,
	STATUS_SUBCATEGORY_MULTIPLAYER,
	STATUS_SUBCATEGORY_SHIP_STATUS,
	STATUS_SUBCATEGORY_SHIELDS_ENGINES_AND_WEAPONS,
	STATUS_SUBCATEGORY_CARGO,
	STATUS_SUBCATEGORY_DAMAGE,
	STATUS_SUBCATEGORY_DISTANCE_AND_COORDINATES,
	STATUS_SUBCATEGORY_VARIABLES,
	STATUS_SUBCATEGORY_CONTAINERS,
	STATUS_SUBCATEGORY_OTHER,
	// this should come after every subcategory
	First_available_subcategory_id
};

enum : int {
	//an operator value of 0 represents a non-operator.
	//Because of this, OP_NOT_AN_OP must NEVER be changed to a different value and must always be assigned 0
	OP_NOT_AN_OP = 0, 

	// OP_CATEGORY_ARITHMETIC

	OP_PLUS = FIRST_OP,
	OP_MINUS,
	OP_MOD,
	OP_MUL,
	OP_DIV,
	OP_RAND,
	OP_ABS,	// Goober5000
	OP_MIN,	// Goober5000
	OP_MAX,	// Goober5000
	OP_AVG,	// Goober5000
	OP_RAND_MULTIPLE,	// Goober5000
	OP_POW,	// Goober5000
	OP_BITWISE_AND,	// Goober5000
	OP_BITWISE_OR,	// Goober5000
	OP_BITWISE_NOT,	// Goober5000
	OP_BITWISE_XOR,	// Goober5000

	OP_SET_BIT,	// Goober5000
	OP_UNSET_BIT,	// Goober5000
	OP_IS_BIT_SET,	// Goober5000
	OP_SIGNUM,	// Goober5000
	OP_IS_NAN,	// Goober5000
	OP_NAN_TO_NUMBER,	// Goober5000
	OP_ANGLE_VECTORS,	// Lafiel

	// OP_CATEGORY_LOGICAL

	OP_TRUE,
	OP_FALSE,
	OP_AND,
	OP_AND_IN_SEQUENCE,
	OP_OR,
	OP_EQUALS,
	OP_GREATER_THAN,
	OP_LESS_THAN,
	OP_HAS_TIME_ELAPSED,
	OP_NOT,
	OP_STRING_EQUALS,
	OP_STRING_GREATER_THAN,
	OP_STRING_LESS_THAN,
	OP_NOT_EQUAL,	// Goober5000
	OP_GREATER_OR_EQUAL,	// Goober5000
	OP_LESS_OR_EQUAL,	// Goober5000

	OP_XOR,	// Goober5000
	OP_PERFORM_ACTIONS_BOOL_FIRST,	// Goober5000
	OP_PERFORM_ACTIONS_BOOL_LAST,	// Goober5000
	OP_HAS_TIME_ELAPSED_MSECS,	// Goober5000

	// OP_CATEGORY_GOAL_EVENT
	
	OP_GOAL_INCOMPLETE,
	OP_GOAL_TRUE_DELAY,
	OP_GOAL_FALSE_DELAY,
	OP_EVENT_INCOMPLETE,
	OP_EVENT_TRUE_DELAY,
	OP_EVENT_FALSE_DELAY,
	OP_PREVIOUS_EVENT_TRUE,
	OP_PREVIOUS_EVENT_FALSE,
	OP_PREVIOUS_GOAL_TRUE,
	OP_PREVIOUS_GOAL_FALSE,
	OP_EVENT_TRUE_MSECS_DELAY,
	OP_EVENT_FALSE_MSECS_DELAY,
	OP_RESET_EVENT,
	OP_RESET_GOAL,

	// OP_CATEGORY_OBJECTIVE
	
	OP_IS_DESTROYED_DELAY,
	OP_IS_SUBSYSTEM_DESTROYED_DELAY,
	OP_IS_DISABLED_DELAY,
	OP_IS_DISARMED_DELAY,
	OP_HAS_DOCKED_DELAY,
	OP_HAS_UNDOCKED_DELAY,
	OP_HAS_ARRIVED_DELAY,
	OP_HAS_DEPARTED_DELAY,
	OP_WAYPOINTS_DONE_DELAY,
	OP_SHIP_TYPE_DESTROYED,
	OP_PERCENT_SHIPS_DEPARTED,
	OP_PERCENT_SHIPS_DESTROYED,
	OP_DEPART_NODE_DELAY,
	OP_DESTROYED_DEPARTED_DELAY,
	OP_PERCENT_SHIPS_DISARMED,	// Goober5000
	OP_PERCENT_SHIPS_DISABLED,	// Goober5000

	OP_PERCENT_SHIPS_ARRIVED,	// FUBAR-BDHR
	OP_NAV_IS_VISITED,	// Kazan
	OP_WAS_DESTROYED_BY_DELAY,	// WCS
	OP_PERCENT_SHIPS_SCANNED,	// Goober5000
	
	// OP_CATEGORY_TIME
	
	OP_TIME_SHIP_DESTROYED,
	OP_TIME_SHIP_ARRIVED,
	OP_TIME_SHIP_DEPARTED,
	OP_TIME_WING_DESTROYED,
	OP_TIME_WING_ARRIVED,
	OP_TIME_WING_DEPARTED,
	OP_MISSION_TIME,
	OP_MISSION_TIME_MSECS,	// Goober5000
	OP_TIME_DOCKED,
	OP_TIME_UNDOCKED,
	OP_TIME_TO_GOAL, // tcrayford
	OP_SET_HUD_TIME_PAD, // MjnMixael
	
	// OP_CATEGORY_STATUS
	
	OP_SHIELDS_LEFT,
	OP_HITS_LEFT,
	OP_HITS_LEFT_SUBSYSTEM,	// deprecated
	OP_SIM_HITS_LEFT,
	OP_DISTANCE,
	OP_DISTANCE_CENTER_SUBSYSTEM,	// Goober5000
	OP_LAST_ORDER_TIME,
	OP_NUM_PLAYERS,
	OP_SKILL_LEVEL_AT_LEAST,
	OP_WAS_PROMOTION_GRANTED,
	OP_WAS_MEDAL_GRANTED,
	OP_CARGO_KNOWN_DELAY,
	OP_CAP_SUBSYS_CARGO_KNOWN_DELAY,
	OP_HAS_BEEN_TAGGED_DELAY,
	OP_IS_TAGGED,
	OP_NUM_KILLS,
	
	OP_NUM_TYPE_KILLS,
	OP_NUM_CLASS_KILLS,
	OP_SHIELD_RECHARGE_PCT,
	OP_ENGINE_RECHARGE_PCT,
	OP_WEAPON_RECHARGE_PCT,
	OP_SHIELD_QUAD_LOW,
	OP_SECONDARY_AMMO_PCT,
	OP_IS_SECONDARY_SELECTED,
	OP_IS_PRIMARY_SELECTED,
	OP_SPECIAL_WARP_DISTANCE,
	OP_IS_SHIP_VISIBLE,
	OP_TEAM_SCORE,
	OP_PRIMARY_AMMO_PCT,	// Goober5000
	OP_IS_SHIP_STEALTHY,	// Goober5000
	OP_IS_CARGO,	// Goober5000
	OP_IS_FRIENDLY_STEALTH_VISIBLE,	// Goober5000
	
	OP_GET_OBJECT_X,	// Goober5000
	OP_GET_OBJECT_Y,	// Goober5000
	OP_GET_OBJECT_Z,	// Goober5000
	OP_IS_AI_CLASS,	// Goober5000
	OP_IS_SHIP_TYPE,	// Goober5000
	OP_IS_SHIP_CLASS,	// Goober5000
	OP_NUM_SHIPS_IN_BATTLE,	// phreak
	OP_CURRENT_SPEED, // WMCoolmon
	OP_IS_IFF,	// Goober5000
	OP_IS_SPECIES,	// Goober5000
	OP_NUM_WITHIN_BOX,	// WMCoolmon
	OP_SCRIPT_EVAL_NUM, // WMCoolmon
	OP_SCRIPT_EVAL_STRING, // WMCoolmon
	OP_NUM_SHIPS_IN_WING,	// Karajorma
	OP_GET_PRIMARY_AMMO, // Karajorma
	OP_GET_SECONDARY_AMMO, // Karajorma

	OP_NUM_ASSISTS, // Karajorma
	OP_SHIP_SCORE, // Karajorma
	OP_SHIP_DEATHS, // Karajorma
	OP_RESPAWNS_LEFT, // Karajorma
	OP_IS_PLAYER, // Karajorma
	OP_GET_DAMAGE_CAUSED, // Karajorma
	OP_AFTERBURNER_LEFT, // Karajorma
	OP_WEAPON_ENERGY_LEFT, // Karajorma
	OP_PRIMARY_FIRED_SINCE, // Karajorma
	OP_SECONDARY_FIRED_SINCE, // Karajorma
	OP_CUTSCENES_GET_FOV, // Echelon9
	OP_HITS_LEFT_SUBSYSTEM_GENERIC, // Goober5000
	OP_HITS_LEFT_SUBSYSTEM_SPECIFIC, // Goober5000
	OP_GET_OBJECT_PITCH,	// Goober5000
	OP_GET_OBJECT_BANK,	// Goober5000
	OP_GET_OBJECT_HEADING,	// Goober5000
	
	OP_HAS_PRIMARY_WEAPON, // Karajorma
	OP_HAS_SECONDARY_WEAPON, // Karajorma
	OP_STRING_TO_INT, // Karajorma
	OP_STRING_GET_LENGTH, // Goober5000
	OP_GET_OBJECT_SPEED_X,
	OP_GET_OBJECT_SPEED_Y,
	OP_GET_OBJECT_SPEED_Z,
	OP_NAV_DISTANCE, // Kazan
	OP_NAV_ISLINKED, // Kazan
	OP_IS_FACING, // The E
	OP_DIRECTIVE_VALUE, // Karajorma
	OP_GET_NUM_COUNTERMEASURES, // Karajorma
	OP_IS_IN_BOX, // Sushi
	OP_IS_IN_MISSION, // Goober5000
	OP_ARE_SHIP_FLAGS_SET, // Karajorma
	OP_ARE_WING_FLAGS_SET, // Goober5000

	OP_GET_THROTTLE_SPEED, // Karajorma
	OP_HAS_ARMOR_TYPE, // MjnMixael
	OP_TURRET_GET_PRIMARY_AMMO, // DahBlount, part of the turret ammo code
	OP_TURRET_GET_SECONDARY_AMMO,	// DahBlount, part of the turret ammo code
	OP_TURRET_HAS_PRIMARY_WEAPON,      // MjnMixael
	OP_TURRET_HAS_SECONDARY_WEAPON, // MjnMixael
	OP_IS_DOCKED,	// Goober5000
	OP_IS_IN_TURRET_FOV,	// Goober5000
	OP_GET_HOTKEY, // wookieejedi
	OP_DISTANCE_CENTER, // Goober5000
	OP_DISTANCE_BBOX, // Goober5000
	OP_DISTANCE_BBOX_SUBSYSTEM, // Goober5000
	OP_IS_LANGUAGE,						// Goober5000
	OP_SCRIPT_EVAL_BOOL, // Goober5000
	OP_IS_CONTAINER_EMPTY,	// Karajorma/jg18
	OP_GET_CONTAINER_SIZE,	// Karajorma/jg18

	OP_LIST_HAS_DATA,	// Karajorma/jg18
	OP_LIST_DATA_INDEX,	// Karajorma/jg18
	OP_MAP_HAS_KEY,	// Karajorma/jg18
	OP_MAP_HAS_DATA_ITEM,	// Karajorma/jg18
	OP_ANGLE_FVEC_TARGET, // Lafiel
	OP_IS_SHIP_EMP_ACTIVE,	// MjnMixael
	OP_PLAYER_IS_CHEATING_BASTARD,	// The E
	OP_TURRET_FIRED_SINCE,	// Asteroth
	
	// OP_CATEGORY_CONDITIONAL
	// conditional sexpressions
	
	OP_WHEN,
	OP_WHEN_ARGUMENT,	// Goober5000
	OP_EVERY_TIME,	// Goober5000
	OP_EVERY_TIME_ARGUMENT,	// Goober5000
	OP_ANY_OF,	// Goober5000
	OP_EVERY_OF,	// Goober5000
	OP_RANDOM_OF,	// Goober5000
	OP_NUMBER_OF,	// Goober5000
	OP_INVALIDATE_ARGUMENT,	// Goober5000
	OP_RANDOM_MULTIPLE_OF,	// Karajorma
	OP_IN_SEQUENCE,	// Karajorma
	OP_VALIDATE_ARGUMENT,	// Karajorma
	OP_DO_FOR_VALID_ARGUMENTS,	// Karajorma
	OP_INVALIDATE_ALL_ARGUMENTS,	// Karajorma
	OP_VALIDATE_ALL_ARGUMENTS,	// Karajorma
	OP_FOR_COUNTER,	// Goober5000
	
	OP_IF_THEN_ELSE,	// Goober5000
	OP_NUM_VALID_ARGUMENTS,	// Karajorma
	OP_FUNCTIONAL_IF_THEN_ELSE,	// Goober5000
	OP_FOR_SHIP_CLASS,	// Goober5000
	OP_FOR_SHIP_TYPE,	// Goober5000
	OP_FOR_SHIP_TEAM,	// Goober5000
	OP_FOR_SHIP_SPECIES,	// Goober5000
	OP_FOR_PLAYERS,	// Goober5000
	OP_FIRST_OF,	// MageKing17
	OP_SWITCH,	// Goober5000
	OP_FUNCTIONAL_SWITCH,	// Goober5000
	OP_FUNCTIONAL_WHEN,	// Goober5000
	OP_FOR_CONTAINER_DATA,	// jg18
	OP_FOR_MAP_CONTAINER_KEYS,	// jg18
	OP_ON_MISSION_SKIP,	// Goober5000
	OP_FOR_SUBSYSTEMS,	// Goober5000

	// OP_CATEGORY_CHANGE
	// sexpressions with side-effects
	
	OP_CHANGE_IFF,
	OP_REPAIR_SUBSYSTEM,
	OP_SABOTAGE_SUBSYSTEM,
	OP_SET_SUBSYSTEM_STRNGTH,
	OP_PROTECT_SHIP,
	OP_SEND_MESSAGE,
	OP_SEND_BUILTIN_MESSAGE,
	OP_SELF_DESTRUCT,
	OP_CLEAR_GOALS,
	OP_ADD_GOAL,
	OP_REMOVE_GOAL,	// Goober5000
	OP_INVALIDATE_GOAL,
	OP_VALIDATE_GOAL,
	OP_SEND_RANDOM_MESSAGE,
	OP_TRANSFER_CARGO,
	OP_EXCHANGE_CARGO,
	OP_UNPROTECT_SHIP,
	
	OP_GOOD_REARM_TIME,
	OP_BAD_REARM_TIME,
	OP_GRANT_PROMOTION,
	OP_GRANT_MEDAL,
	OP_ALLOW_SHIP,
	OP_ALLOW_WEAPON,
	OP_GOOD_SECONDARY_TIME,
	OP_WARP_BROKEN,
	OP_WARP_NOT_BROKEN,
	OP_WARP_NEVER,
	OP_WARP_ALLOWED,
	OP_SHIP_INVISIBLE,
	OP_SHIP_VISIBLE,
	OP_SHIP_INVULNERABLE,
	OP_SHIP_VULNERABLE,
	OP_RED_ALERT,
	
	OP_TECH_ADD_SHIP,
	OP_TECH_ADD_WEAPON,
	OP_END_CAMPAIGN,
	OP_JETTISON_CARGO_DELAY,
	OP_MODIFY_VARIABLE,
	OP_NOP,
	OP_BEAM_FIRE,
	OP_BEAM_FREE,
	OP_BEAM_FREE_ALL,
	OP_BEAM_LOCK,
	OP_BEAM_LOCK_ALL,
	OP_BEAM_PROTECT_SHIP,
	OP_BEAM_UNPROTECT_SHIP,
	OP_TURRET_FREE,
	OP_TURRET_FREE_ALL,
	OP_TURRET_LOCK,
	
	OP_TURRET_LOCK_ALL,
	OP_ADD_REMOVE_ESCORT,
	OP_AWACS_SET_RADIUS,
	OP_SEND_MESSAGE_LIST,
	OP_CAP_WAYPOINT_SPEED,
	OP_SHIP_GUARDIAN,
	OP_SHIP_NO_GUARDIAN,
	OP_TURRET_TAGGED_ONLY_ALL,
	OP_TURRET_TAGGED_CLEAR_ALL,
	OP_SUBSYS_SET_RANDOM,
	OP_SUPERNOVA_START,
	OP_CARGO_NO_DEPLETE,
	OP_SET_SPECIAL_WARPOUT_NAME,
	OP_SHIP_VANISH,
	OP_SHIELDS_ON,	//-Sesquipedalian
	OP_SHIELDS_OFF,	//-Sesquipedalian
	
	OP_CHANGE_AI_LEVEL,	//-Sesquipedalian
	OP_END_MISSION, //-Sesquipedalian. replaces end-mission-delay, which did nothing
	OP_SET_SCANNED,	// Goober5000
	OP_SET_UNSCANNED,	// Goober5000
	OP_SHIP_STEALTHY,	// Goober5000
	OP_SHIP_UNSTEALTHY,	// Goober5000
	OP_SET_CARGO,	// Goober5000
	OP_CHANGE_AI_CLASS,	// Goober5000
	OP_FRIENDLY_STEALTH_INVISIBLE,	// Goober5000
	OP_FRIENDLY_STEALTH_VISIBLE,	// Goober5000
	OP_DAMAGED_ESCORT_LIST, //phreak
	OP_DAMAGED_ESCORT_LIST_ALL,	// Goober5000
	OP_SHIP_VAPORIZE,	// Goober5000
	OP_SHIP_NO_VAPORIZE,	// Goober5000
	OP_COLLIDE_INVISIBLE,	// Goober5000
	OP_DONT_COLLIDE_INVISIBLE,	// Goober5000
	
	OP_PRIMITIVE_SENSORS_SET_RANGE,	// Goober5000
	OP_CHANGE_SHIP_CLASS,	// Goober5000
	OP_SCRIPT_EVAL, //WMC
	OP_SET_SUPPORT_SHIP,	// Goober5000
	OP_DEACTIVATE_GLOW_POINTS,	//-Bobboau
	OP_ACTIVATE_GLOW_POINTS,	//-Bobboau
	OP_DEACTIVATE_GLOW_MAPS,	//-Bobboau
	OP_ACTIVATE_GLOW_MAPS,	//-Bobboau
	OP_DEACTIVATE_GLOW_POINT_BANK,	//-Bobboau
	OP_ACTIVATE_GLOW_POINT_BANK,	//-Bobboau
	OP_CHANGE_SOUNDTRACK,	// Goober5000
	OP_TECH_ADD_INTEL,	// Goober5000
	OP_TECH_RESET_TO_DEFAULT,	// Goober5000
	OP_CREATE_BOLT,		//MjnMixael
	OP_EXPLOSION_EFFECT,	// Goober5000
	OP_WARP_EFFECT,	// Goober5000
	OP_SET_OBJECT_FACING,	// Goober5000
	
	OP_SET_OBJECT_FACING_OBJECT,	// Goober5000
	OP_SET_OBJECT_POSITION,	// Goober5000
	OP_PLAY_SOUND_FROM_TABLE,	// Goober5000
	OP_PLAY_SOUND_FROM_FILE,	// Goober5000
	OP_CLOSE_SOUND_FROM_FILE,	// Goober5000
	OP_HUD_DISABLE,	// Goober5000
	OP_KAMIKAZE,	//-Sesquipedalian
	OP_MISSION_SET_SUBSPACE,
	OP_TURRET_TAGGED_SPECIFIC, //phreak
	OP_TURRET_TAGGED_CLEAR_SPECIFIC, //phreak
	OP_LOCK_ROTATING_SUBSYSTEM,	// Goober5000
	OP_FREE_ROTATING_SUBSYSTEM,	// Goober5000
	OP_REVERSE_ROTATING_SUBSYSTEM,	// Goober5000
	OP_ROTATING_SUBSYS_SET_TURN_TIME,	// Goober5000
	OP_PLAYER_USE_AI,	// Goober5000
	OP_PLAYER_NOT_USE_AI,	// Goober5000
	
	OP_HUD_DISABLE_EXCEPT_MESSAGES,	// Goober5000
	OP_FORCE_JUMP,	// Goober5000
	OP_HUD_SET_TEXT, //WMC
	OP_HUD_SET_TEXT_NUM, //WMC
	OP_HUD_SET_COORDS, //WMC
	OP_HUD_SET_FRAME, //WMC
	OP_HUD_SET_COLOR, //WMC
	OP_HUD_SET_MAX_TARGETING_RANGE, // Goober5000
	OP_SHIP_TAG, // Goober5000
	OP_SHIP_UNTAG, // Goober5000
	OP_SHIP_CHANGE_ALT_NAME,	// Goober5000
	OP_SCRAMBLE_MESSAGES,	// phreak
	OP_UNSCRAMBLE_MESSAGES,	// phreak
	OP_CUTSCENES_SET_CUTSCENE_BARS,	// WMC
	OP_CUTSCENES_UNSET_CUTSCENE_BARS,	// WMC
	OP_CUTSCENES_FADE_IN,	// WMC
	
	OP_CUTSCENES_FADE_OUT,	// WMC
	OP_CUTSCENES_SET_CAMERA_POSITION,	// WMC
	OP_CUTSCENES_SET_CAMERA_FACING,	// WMC
	OP_CUTSCENES_SET_CAMERA_FACING_OBJECT,	// WMC
	OP_CUTSCENES_SET_CAMERA_ROTATION,	// WMC
	OP_CUTSCENES_SET_FOV,	// WMC
	OP_CUTSCENES_RESET_FOV,	// WMC
	OP_CUTSCENES_RESET_CAMERA,	// WMC
	OP_CUTSCENES_SHOW_SUBTITLE,	// WMC / deprecated
	OP_CUTSCENES_SET_TIME_COMPRESSION,	// WMC
	OP_CUTSCENES_RESET_TIME_COMPRESSION,	// WMC
	OP_CUTSCENES_FORCE_PERSPECTIVE,	// WMC
	OP_JUMP_NODE_SET_JUMPNODE_NAME,	// CommanderDJ
	OP_JUMP_NODE_SET_JUMPNODE_DISPLAY_NAME,
	OP_JUMP_NODE_SET_JUMPNODE_COLOR,	// WMC
	OP_JUMP_NODE_SET_JUMPNODE_MODEL,	// WMC
	OP_JUMP_NODE_SHOW_JUMPNODE,	// WMC
	
	OP_JUMP_NODE_HIDE_JUMPNODE,	// WMC
	OP_SHIP_GUARDIAN_THRESHOLD,	// Goober5000
	OP_SHIP_SUBSYS_GUARDIAN_THRESHOLD,	// Goober5000
	OP_SET_SKYBOX_MODEL, // taylor
	OP_SHIP_CREATE,
	OP_WEAPON_CREATE,	// Goober5000
	OP_SET_OBJECT_SPEED_X, // Deprecated by wookieejedi
	OP_SET_OBJECT_SPEED_Y, // Deprecated by wookieejedi
	OP_SET_OBJECT_SPEED_Z, // Deprecated by wookieejedi
	OP_MISSION_SET_NEBULA,
	OP_ADD_BACKGROUND_BITMAP,
	OP_REMOVE_BACKGROUND_BITMAP,
	OP_ADD_SUN_BITMAP,
	OP_REMOVE_SUN_BITMAP,
	OP_NEBULA_CHANGE_STORM,
	OP_NEBULA_TOGGLE_POOF,
	OP_NEBULA_FADE_POOF,
	OP_VOLUMETRICS_TOGGLE,
	
	OP_TURRET_CHANGE_WEAPON,
	OP_TURRET_SET_TARGET_ORDER,
	OP_SHIP_TURRET_TARGET_ORDER,
	OP_SET_PRIMARY_AMMO, // Karajorma
	OP_SET_SECONDARY_AMMO, // Karajorma
	OP_SHIP_BOMB_TARGETABLE,	//WMC
	OP_SHIP_BOMB_UNTARGETABLE,	//WMC
	OP_SHIP_SUBSYS_TARGETABLE,	// Goober5000
	OP_SHIP_SUBSYS_UNTARGETABLE,	// Goober5000
	OP_SET_DEATH_MESSAGE,	// Goober5000
	OP_SET_PRIMARY_WEAPON, // Karajorma
	OP_SET_SECONDARY_WEAPON, // Karajorma
	OP_DISABLE_BUILTIN_MESSAGES, // Karajorma
	OP_ENABLE_BUILTIN_MESSAGES, // Karajorma
	OP_LOCK_PRIMARY_WEAPON, // Karajorma
	OP_UNLOCK_PRIMARY_WEAPON, // Karajorma
	
	OP_LOCK_SECONDARY_WEAPON, // Karajorma
	OP_UNLOCK_SECONDARY_WEAPON, // Karajorma
	OP_SET_CAMERA_SHUDDER,	// Goober5000
	OP_SET_FRIENDLY_DAMAGE_CAPS, // Kestrellius
	OP_ALLOW_TREASON, // Karajorma
	OP_SHIP_COPY_DAMAGE,	// Goober5000
	OP_CHANGE_SUBSYSTEM_NAME,	// Karajorma
	OP_SET_PERSONA, // Karajorma
	OP_CHANGE_PLAYER_SCORE, // Karajorma
	OP_CHANGE_TEAM_SCORE, // Karajorma
	OP_CUTSCENES_SET_CAMERA_FOV,	// WMC
	OP_CUTSCENES_SET_CAMERA, // WMC
	OP_CUTSCENES_SET_CAMERA_HOST, // WMC
	OP_CUTSCENES_SET_CAMERA_TARGET, // WMC
	OP_LOCK_AFTERBURNER, // KeldorKatarn
	OP_UNLOCK_AFTERBURNER, // KeldorKatarn
	OP_SHIP_CHANGE_CALLSIGN,	// FUBAR
	
	OP_SET_RESPAWNS, // Karajorma
	OP_SET_AFTERBURNER_ENERGY, // Karajorma
	OP_SET_WEAPON_ENERGY, // Karajorma
	OP_SET_SHIELD_ENERGY, // Karajorma
	OP_SET_AMBIENT_LIGHT, // Karajorma
	OP_CHANGE_IFF_COLOR, // Wanderer
	OP_TURRET_SUBSYS_TARGET_DISABLE, // Wanderer
	OP_TURRET_SUBSYS_TARGET_ENABLE, // Wanderer
	OP_CLEAR_WEAPONS, // Wanderer
	OP_SHIP_MANEUVER, // Wanderer 
	OP_SHIP_ROT_MANEUVER, // Wanderer
	OP_SHIP_LAT_MANEUVER, // Wanderer
	OP_GET_VARIABLE_BY_INDEX, // Goober5000
	OP_SET_VARIABLE_BY_INDEX, // Goober5000
	OP_SET_POST_EFFECT, // Hery
	OP_TURRET_SET_OPTIMUM_RANGE, // FUBAR
	
	OP_TURRET_SET_DIRECTION_PREFERENCE, // FUBAR
	OP_TURRET_SET_TARGET_PRIORITIES, // FUBAR
	OP_SET_ARMOR_TYPE, // FUBAR
	OP_CUTSCENES_SHOW_SUBTITLE_TEXT,	// Goober5000
	OP_CUTSCENES_SHOW_SUBTITLE_IMAGE,	// Goober5000
	OP_HUD_DISPLAY_GAUGE,
	OP_SET_SOUND_ENVIRONMENT,	// Taylor
	OP_UPDATE_SOUND_ENVIRONMENT,	// Taylor
	OP_SET_EXPLOSION_OPTION,	// Goober5000
	OP_ADJUST_AUDIO_VOLUME, // The E
	OP_FORCE_GLIDE, // The E
	OP_TURRET_SET_RATE_OF_FIRE, // FUBAR
	OP_HUD_SET_MESSAGE, // The E
	OP_SHIP_SUBSYS_NO_REPLACE, // FUBAR
	OP_SET_IMMOBILE,	// Goober5000
	OP_SET_MOBILE,	// Goober5000
	
	OP_SHIP_SUBSYS_NO_LIVE_DEBRIS, // FUBAR
	OP_SHIP_SUBSYS_VANISHED, // FUBAR
	OP_SHIP_SUBSYS_IGNORE_IF_DEAD, // FUBAR
	OP_HUD_SET_DIRECTIVE, // The E
	OP_HUD_GAUGE_SET_ACTIVE, // The E - slightly deprecated
	OP_HUD_ACTIVATE_GAUGE_TYPE, // The E - slightly deprecated
	OP_SET_OBJECT_ORIENTATION,	// Goober5000
	OP_STRING_CONCATENATE,	// Goober5000
	OP_INT_TO_STRING, // Goober5000
	OP_WEAPON_SET_DAMAGE_TYPE, // FUBAR
	OP_SHIP_SET_DAMAGE_TYPE, // FUBAR
	OP_SHIP_SHOCKWAVE_SET_DAMAGE_TYPE, // FUBAR
	OP_FIELD_SET_DAMAGE_TYPE, // FUBAR
	OP_TURRET_PROTECT_SHIP,	// Goober5000
	OP_TURRET_UNPROTECT_SHIP,	// Goober5000
	OP_DISABLE_ETS, // The E
	
	OP_ENABLE_ETS, // The E
	OP_NAV_ADD_WAYPOINT,	// Kazan
	OP_NAV_ADD_SHIP,	// Kazan
	OP_NAV_DEL,	// Kazan
	OP_NAV_HIDE,	// Kazan
	OP_NAV_RESTRICT,	// Kazan
	OP_NAV_UNHIDE,	// Kazan
	OP_NAV_UNRESTRICT,	// Kazan
	OP_NAV_SET_VISITED,	// Kazan
	OP_NAV_SET_CARRY,	// Kazan
	OP_NAV_UNSET_CARRY,	// Kazan
	OP_NAV_UNSET_VISITED,	// Kazan
	OP_NAV_SET_NEEDSLINK,	// Kazan
	OP_NAV_UNSET_NEEDSLINK,	// Kazan
	OP_NAV_USECINEMATICS,	// Kazan
	OP_NAV_USEAP,	// Kazan
	
	// OP_CATEGORY_CHANGE2
	
	OP_STRING_GET_SUBSTRING,	// Goober5000
	OP_STRING_SET_SUBSTRING,	// Goober5000
	OP_SET_NUM_COUNTERMEASURES, // Karajorma
	OP_ADD_TO_COLGROUP, // The E
	OP_REMOVE_FROM_COLGROUP, // The E
	OP_GET_COLGROUP_ID, // The E
	OP_SHIP_EFFECT, // Valathil
	OP_CLEAR_SUBTITLES, // The E
	OP_BEAM_FIRE_COORDS,	// Goober5000
	OP_SET_DOCKED, // Sushi
	OP_SET_THRUSTERS, // The E
	OP_TRIGGER_SUBMODEL_ANIMATION,	// Goober5000
	OP_HUD_CLEAR_MESSAGES, // Swifty
	OP_SET_PLAYER_ORDERS,	// Karajorma
	OP_SUPERNOVA_STOP, //CommanderDJ
	OP_SET_PLAYER_THROTTLE_SPEED, //CommanderDJ
	
	OP_SET_DEBRIEFING_TOGGLED,	// Goober5000
	OP_SET_SUBSPACE_DRIVE,	// Goober5000
	OP_SET_ARRIVAL_INFO,	// Goober5000
	OP_SET_DEPARTURE_INFO,	// Goober5000
	OP_SET_SKYBOX_ORIENT,	// Goober5000
	OP_DESTROY_INSTANTLY,	// Admiral MS
	OP_DESTROY_SUBSYS_INSTANTLY,	// Admiral MS
	OP_DEBUG,	// Karajorma
	OP_SET_MISSION_MOOD,	// Karajorma
	OP_NAV_SELECT, 	// Talon1024
	OP_NAV_UNSELECT, 	// Talon1024
	OP_ALTER_SHIP_FLAG,	// Karajorma
	OP_CHANGE_TEAM_COLOR,	// The E
	OP_NEBULA_CHANGE_PATTERN,	// Axem
	OP_SET_WING_FORMATION,	// Goober5000
	OP_TECH_ADD_INTEL_XSTR,	// Goober5000
	
	OP_COPY_VARIABLE_FROM_INDEX, // Goober5000
	OP_COPY_VARIABLE_BETWEEN_INDEXES, // Goober5000
	OP_GET_ETS_VALUE,	// niffiwan
	OP_SET_ETS_VALUES,	// niffiwan
	OP_CALL_SSM_STRIKE, // X3N0-Life-Form
	OP_OVERRIDE_MOTION_DEBRIS,    // The E
	OP_HUD_SET_CUSTOM_GAUGE_ACTIVE, 	// The E, just revamped a bit by Axem
	OP_HUD_SET_BUILTIN_GAUGE_ACTIVE, 	// The E, just revamped a bit by Axem
	OP_SCRIPT_EVAL_MULTI,	// Karajorma
	OP_PAUSE_SOUND_FROM_FILE,	// Goober5000
	OP_SCRIPT_EVAL_BLOCK, // niffiwan
	OP_BEAM_FLOATING_FIRE,	// MageKing17
	OP_TURRET_SET_PRIMARY_AMMO,	// DahBlount, part of the turret ammo changes
	OP_TURRET_SET_SECONDARY_AMMO,	// DahBlount, part of the turret ammo changes
	OP_JETTISON_CARGO_NEW,	// Goober5000
	OP_STRING_CONCATENATE_BLOCK,	// Goober5000
	
	OP_MODIFY_VARIABLE_XSTR,	// m!m
	OP_RESET_POST_EFFECTS,	// Goober5000
	OP_ADD_REMOVE_HOTKEY,    // wookieejedi
	OP_TECH_REMOVE_INTEL_XSTR,    // wookieejedi
	OP_TECH_REMOVE_INTEL,   // wookieejedi
	OP_CHANGE_BACKGROUND,	// Goober5000
	OP_CLEAR_DEBRIS,	// Goober5000
	OP_SET_DEBRIEFING_PERSONA,	// Goober5000
	OP_SET_TRAITOR_OVERRIDE,	//MjnMixael
	OP_ADD_TO_COLGROUP_NEW,	// Goober5000
	OP_REMOVE_FROM_COLGROUP_NEW,	// Goober5000
	OP_GET_POWER_OUTPUT,	// The E
	OP_TURRET_SET_FORCED_TARGET,	// Asteroth
	OP_TURRET_SET_FORCED_SUBSYS_TARGET,	// Asteroth
	OP_TURRET_CLEAR_FORCED_TARGET,	// Asteroth
	OP_SEND_MESSAGE_CHAIN,	// Goober5000
	OP_TURRET_SET_INACCURACY,	// Asteroth
	
	OP_REPLACE_TEXTURE,	// Lafiel
	OP_REPLACE_TEXTURE_SKYBOX,	// Lafiel
	OP_NEBULA_CHANGE_FOG_COLOR,	// Asteroth
	OP_SET_ALPHA_MULT,	// Lafiel
	OP_DESTROY_INSTANTLY_WITH_DEBRIS,	// Asteroth
	OP_TRIGGER_ANIMATION_NEW,	// Lafiel
	OP_UPDATE_MOVEABLE,	// Lafiel
	OP_NAV_SET_COLOR, 	// Goober5000
	OP_NAV_SET_VISITED_COLOR, 	// Goober5000
	OP_CONTAINER_ADD_TO_LIST,	// Karajorma/jg18
	OP_CONTAINER_REMOVE_FROM_LIST,	// Karajorma/jg18
	OP_CONTAINER_ADD_TO_MAP,	// Karajorma/jg18
	OP_CONTAINER_REMOVE_FROM_MAP,	// Karajorma/jg18
	OP_CONTAINER_GET_MAP_KEYS,	// Karajorma/jg18
	OP_CLEAR_CONTAINER,	// Karajorma/jg18
	OP_ADD_BACKGROUND_BITMAP_NEW,	// Goober5000
	OP_ADD_SUN_BITMAP_NEW,	// Goober5000
	
	OP_CANCEL_FUTURE_WAVES,	// naomimyselfandi
	OP_COPY_CONTAINER,	// jg18
	OP_APPLY_CONTAINER_FILTER,	// jg18
	OP_STOP_LOOPING_ANIMATION,	// Lafiel
	OP_LOCK_TRANSLATING_SUBSYSTEM,	// Goober5000
	OP_FREE_TRANSLATING_SUBSYSTEM,	// Goober5000
	OP_REVERSE_TRANSLATING_SUBSYSTEM,	// Goober5000
	OP_TRANSLATING_SUBSYS_SET_SPEED,	// Goober5000
	OP_ALTER_WING_FLAG,	// Goober5000
	OP_TOGGLE_ASTEROID_FIELD,	// MjnMixael
	OP_HUD_FORCE_SENSOR_STATIC,	// MjnMixael
	OP_HUD_FORCE_EMP_EFFECT, // MjnMixael
	OP_SET_GRAVITY_ACCEL,	// Asteroth
	OP_FORCE_REARM,	 // MjnMixael
	OP_ABORT_REARM,  // MjnMixael
	OP_SET_ORDER_ALLOWED_TARGET,	// MjnMixael
	OP_ENABLE_GENERAL_ORDERS,	// MjnMixael
	OP_VALIDATE_GENERAL_ORDERS,		// MjnMixael
	OP_USED_CHEAT,	// Kiloku
	OP_SET_ASTEROID_FIELD,	// MjnMixael
	OP_SET_DEBRIS_FIELD,	// MjnMixael
	OP_CONFIG_ASTEROID_FIELD,  // MjnMixael
	OP_CONFIG_DEBRIS_FIELD,  // MjnMixael
	OP_CONFIG_FIELD_TARGETS,  // MjnMixael
	OP_SET_MOTION_DEBRIS,   // MjnMixael
	OP_GOOD_PRIMARY_TIME,	// plieblang
	OP_SET_SKYBOX_ALPHA,	// Goober5000
	
	// OP_CATEGORY_AI
	// defined for AI goals
	
	OP_AI_CHASE,
	OP_AI_DOCK,
	OP_AI_UNDOCK,
	OP_AI_WARP_OUT,
	OP_AI_WAYPOINTS,
	OP_AI_WAYPOINTS_ONCE,
	OP_AI_DESTROY_SUBSYS,
	OP_AI_DISABLE_SHIP,
	OP_AI_DISARM_SHIP,
	OP_AI_GUARD,
	OP_AI_CHASE_ANY,
	OP_AI_EVADE_SHIP,
	OP_AI_STAY_NEAR_SHIP,
	OP_AI_KEEP_SAFE_DISTANCE,
	OP_AI_IGNORE,
	OP_AI_STAY_STILL,
	OP_AI_PLAY_DEAD,
	OP_AI_IGNORE_NEW,	// Goober5000
	OP_AI_FORM_ON_WING, // The E
	OP_AI_CHASE_SHIP_CLASS,	// Goober5000
	OP_AI_PLAY_DEAD_PERSISTENT,	// Goober5000
	OP_AI_FLY_TO_SHIP,	// Goober5000
	OP_AI_REARM_REPAIR,	// Goober5000
	OP_AI_DISABLE_SHIP_TACTICAL,	// Goober5000
	OP_AI_DISARM_SHIP_TACTICAL,	// Goober5000

	// OP_CATEGORY_UNLISTED
	
	OP_GOALS_ID,
	OP_NEXT_MISSION,		// used in campaign files for branching
	OP_IS_DESTROYED,
	OP_IS_SUBSYSTEM_DESTROYED,
	OP_IS_DISABLED,
	OP_IS_DISARMED,
	OP_HAS_DOCKED,
	OP_HAS_UNDOCKED,
	OP_HAS_ARRIVED,
	OP_HAS_DEPARTED,
	OP_WAYPOINTS_DONE,
	OP_ADD_SHIP_GOAL,
	OP_CLEAR_SHIP_GOALS,
	OP_ADD_WING_GOAL,
	OP_CLEAR_WING_GOALS,
	OP_AI_CHASE_WING,
	OP_AI_GUARD_WING,
	OP_EVENT_TRUE,
	OP_EVENT_FALSE,
	OP_PREVIOUS_GOAL_INCOMPLETE,
	OP_PREVIOUS_EVENT_INCOMPLETE,
	OP_AI_WARP,
	OP_IS_CARGO_KNOWN,
	OP_COND,
	OP_END_OF_CAMPAIGN,
	
	// OP_CATEGORY_TRAINING
	// training sexps
	
	OP_KEY_PRESSED,
	OP_KEY_RESET,
	OP_TARGETED,
	OP_SPEED,
	OP_FACING,
	OP_ORDER,
	OP_WAYPOINT_MISSED,
	OP_PATH_FLOWN,
	OP_WAYPOINT_TWICE,
	OP_TRAINING_MSG,
	OP_FLASH_HUD_GAUGE,
	OP_SPECIAL_CHECK,
	OP_SECONDARIES_DEPLETED,
	OP_FACING2,
	OP_PRIMARIES_DEPLETED,	// Goober5000
	OP_MISSILE_LOCKED,	// Sesquipedalian
	OP_SET_TRAINING_CONTEXT_FLY_PATH,
	OP_SET_TRAINING_CONTEXT_SPEED,
	OP_KEY_RESET_MULTIPLE,	// Goober5000
	OP_RESET_ORDERS, // Karajorma
	OP_QUERY_ORDERS, // Karajorma
	OP_NODE_TARGETED, // FUBAR
	OP_IGNORE_KEY, // Karajorma
	
	// this should come after every operator
	First_available_operator_id
};

// defines for string constants
#define SEXP_HULL_STRING			"Hull"
#define SEXP_SIM_HULL_STRING		"Simulated Hull"
#define SEXP_SHIELD_STRING			"Shields"
#define SEXP_ALL_ENGINES_STRING		"<all engines>"
#define SEXP_ALL_TURRETS_STRING		"<all turrets>"
#define SEXP_ARGUMENT_STRING		"<argument>"
#define SEXP_NONE_STRING			"<none>"
#define SEXP_ANY_STRING				"<any string>"
#define SEXP_ALL_BANKS_STRING		"<all weapon banks>"

// macros for accessing sexpression atoms
/**
 * @brief Returns the first element of a SEXP list
 *
 * The name CAR originates from the original LISP language where it was a function which retrieved the first element of
 * a list.
 *
 * @see https://en.wikipedia.org/wiki/CAR_and_CDR
 */
#define CAR(n)		((n < 0) ? -1 : Sexp_nodes[n].first)
/**
 * @brief Returns the rest of a SEXP list. The rest is everything starting from the second element.
 *
 * The name CDR originates from the original LISP language where it was a function which retrieved the "rest" of a list.
 *
 * @see https://en.wikipedia.org/wiki/CAR_and_CDR
 */
#define CDR(n)		((n < 0) ? -1 : Sexp_nodes[n].rest)
#define CADR(n)		CAR(CDR(n))
// #define CTEXT(n)	(Sexp_nodes[n].text)
const char *CTEXT(int n);

// added by Goober5000
#define CDDR(n)		CDR(CDR(n))
#define CDDDR(n)	CDR(CDDR(n))
#define CDDDDR(n)	CDR(CDDDR(n))
#define CDDDDDR(n)	CDR(CDDDDR(n))
#define CADDR(n)	CAR(CDDR(n))
#define CADDDR(n)	CAR(CDDDR(n))
#define CADDDDR(n)	CAR(CDDDDR(n))
#define CADDDDDR(n)	CAR(CDDDDDR(n))

enum class sexp_ref_type
{
	SHIP = 1,
	WING,
	PLAYER,
	WAYPOINT,
	WAYPOINT_PATH
};

enum class sexp_src
{
	NONE = 0,
	SHIP_ARRIVAL,
	SHIP_DEPARTURE,
	WING_ARRIVAL,
	WING_DEPARTURE,
	EVENT,
	MISSION_GOAL,
	MISSION_CUTSCENE,
	SHIP_ORDER,
	WING_ORDER,
	DEBRIEFING,
	BRIEFING,
	UNKNOWN
};

enum class sexp_mode
{
	GENERAL = 0,
	CAMPAIGN
};

// defines for type field of sexp nodes.  The actual type of the node will be stored in the lower
// two bytes of the field.  The upper two bytes will be used for flags (bleah...)
// Be sure not to conflict with type field of sexp_variable
#define SEXP_NOT_USED		0
#define SEXP_LIST				1
#define SEXP_ATOM				2

// flags for sexpressions -- masked onto the end of the type field
#define SEXP_FLAG_PERSISTENT				(1<<31)		// should this sexp node be persistant across missions
#define SEXP_FLAG_VARIABLE					(1<<30)

// sexp variable definitions
#define SEXP_VARIABLE_CHAR					('@')
// defines for type field of sexp_variable.  Be sure not to conflict with type field of sexp_node
#define SEXP_VARIABLE_NUMBER				(1<<4)	//	(0x0010)
#define SEXP_VARIABLE_STRING				(1<<5)	//	(0x0020)
#define SEXP_VARIABLE_UNKNOWN				(1<<6)	//	(0x0040)
#define SEXP_VARIABLE_NOT_USED				(1<<7)	//	(0x0080)

#define SEXP_VARIABLE_BLOCK					(1<<0)	//	(0x0001)
/*
#define SEXP_VARIABLE_BLOCK_EXP				(1<<1)	//	(0x0002)
#define SEXP_VARIABLE_BLOCK_HIT				(1<<2)	//	(0x0004)
*/
#define SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE		(1<<3)	//	(0x0008)

// Goober5000 - hopefully this should work and not conflict with anything
#define SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS	(1<<29)	//	(0x0100)
//Karajorma
#define SEXP_VARIABLE_NETWORK				(1<<28)
#define SEXP_VARIABLE_SAVE_TO_PLAYER_FILE	(1<<27)

#define SEXP_VARIABLE_IS_PERSISTENT (SEXP_VARIABLE_SAVE_ON_MISSION_PROGRESS|SEXP_VARIABLE_SAVE_ON_MISSION_CLOSE)

#define BLOCK_EXP_SIZE					6
#define INNER_RAD							0
#define OUTER_RAD							1
#define DAMAGE								2
#define BLAST								3
#define PROPAGATE							4
#define SHOCK_SPEED						5

#define BLOCK_HIT_SIZE					2
#define SHIELD_STRENGTH					0
#define HULL_STRENGTH					1


#define SEXP_VARIABLE_SET				(0x0100)
#define SEXP_VARIABLE_MODIFIED		(0x0200)

#define SEXP_TYPE_MASK(t)	(t & 0x00ff)
#define SEXP_NODE_TYPE(n)	(Sexp_nodes[n].type & 0x00ff)

// defines for subtypes of atoms
#define SEXP_ATOM_LIST				0
#define SEXP_ATOM_OPERATOR			1
#define SEXP_ATOM_NUMBER			2
#define SEXP_ATOM_STRING			3
#define SEXP_ATOM_CONTAINER_NAME	4
#define SEXP_ATOM_CONTAINER_DATA	5

// defines to short circuit evaluation when possible. Also used when goals can't
// be satisfied yet because ship (or wing) hasn't been created yet.

#define SEXP_TRUE			1
#define SEXP_FALSE			0

// Goober5000: changed these to unlikely values, because now we have sexps using negative numbers
#define SEXP_KNOWN_FALSE	(INT_MIN+10)
#define SEXP_KNOWN_TRUE		(INT_MIN+11)
#define SEXP_UNKNOWN		(INT_MIN+12)
#define SEXP_NAN			(INT_MIN+13)	// not a number -- used when ships/wing part of boolean and haven't arrived yet
#define SEXP_NAN_FOREVER	(INT_MIN+14)	// not a number and will never change -- used to falsify boolean sexpressions
#define SEXP_CANT_EVAL		(INT_MIN+15)	// can't evaluate yet for whatever reason (acts like false)
#define SEXP_NUM_EVAL		(INT_MIN+16)	// already completed an arithmetic operation and result is stored
// in case we want to test for any of the above
#define SEXP_UNLIKELY_RETURN_VALUE_BOUND		(INT_MIN+17)

// defines for check_sexp_syntax
enum sexp_error_check
{
	SEXP_CHECK_NO_ERROR = 0,

	SEXP_CHECK_NONOP_ARGS,              // non-operator has arguments
	SEXP_CHECK_OP_EXPECTED,             // operator expected, but found data instead
	SEXP_CHECK_UNKNOWN_OP,              // unrecognized operator
	SEXP_CHECK_TYPE_MISMATCH,           // return type or data type mismatch
	SEXP_CHECK_BAD_ARG_COUNT,           // argument count in incorrect
	SEXP_CHECK_UNKNOWN_TYPE,            // unrecognized return type of data type

	SEXP_CHECK_INVALID_NUM = 101,       // number is not valid
	SEXP_CHECK_INVALID_SHIP,            // invalid ship name
	SEXP_CHECK_INVALID_WING,            // invalid wing name
	SEXP_CHECK_INVALID_SUBSYS,          // invalid subsystem
	SEXP_CHECK_INVALID_IFF,             // invalid iff string
	SEXP_CHECK_INVALID_POINT,           // invalid point
	SEXP_CHECK_NEGATIVE_NUM,            // negative number wasn't allowed
	SEXP_CHECK_INVALID_SHIP_WING,       // invalid ship/wing
	SEXP_CHECK_INVALID_SHIP_TYPE,       // invalid ship type
	SEXP_CHECK_UNKNOWN_MESSAGE,         // invalid message
	SEXP_CHECK_INVALID_PRIORITY,        // invalid priority for a message
	SEXP_CHECK_INVALID_MISSION_NAME,    // invalid mission name
	SEXP_CHECK_INVALID_GOAL_NAME,       // invalid goal name
	SEXP_CHECK_INVALID_LEVEL,           // mission level too high in campaign
	SEXP_CHECK_INVALID_MSG_SOURCE,      // invalid 'who-from' for a message being sent
	SEXP_CHECK_INVALID_DOCKER_POINT,
	SEXP_CHECK_INVALID_DOCKEE_POINT,
	SEXP_CHECK_ORDER_NOT_ALLOWED,       // ship goal (order) isn't allowed for given ship
	SEXP_CHECK_DOCKING_NOT_ALLOWED,
	SEXP_CHECK_NUM_RANGE_INVALID,
	SEXP_CHECK_INVALID_EVENT_NAME,
	SEXP_CHECK_INVALID_SKILL_LEVEL,
	SEXP_CHECK_INVALID_MEDAL_NAME,
	SEXP_CHECK_INVALID_WEAPON_NAME,
	SEXP_CHECK_INVALID_SHIP_CLASS_NAME,
	SEXP_CHECK_INVALID_CUSTOM_HUD_GAUGE,
	SEXP_CHECK_INVALID_JUMP_NODE,
	SEXP_CHECK_INVALID_VARIABLE,
	SEXP_CHECK_INVALID_AI_CLASS,
	SEXP_CHECK_UNKNOWN_ERROR,
	SEXP_CHECK_INVALID_SUPPORT_SHIP_CLASS,
	SEXP_CHECK_INVALID_SHIP_WITH_BAY,
	SEXP_CHECK_INVALID_ARRIVAL_LOCATION,
	SEXP_CHECK_INVALID_DEPARTURE_LOCATION,
	SEXP_CHECK_INVALID_ARRIVAL_ANCHOR_ALL,
	SEXP_CHECK_INVALID_SOUNDTRACK_NAME,
	SEXP_CHECK_INVALID_INTEL_NAME,
	SEXP_CHECK_INVALID_SKYBOX_NAME,
	SEXP_CHECK_INVALID_PERSONA_NAME,
	SEXP_CHECK_INVALID_VARIABLE_TYPE,
	SEXP_CHECK_INVALID_SUBSYS_TYPE,
	SEXP_CHECK_INVALID_FONT,
	SEXP_CHECK_INVALID_HUD_ELEMENT,
	SEXP_CHECK_INVALID_SOUND_ENVIRONMENT,
	SEXP_CHECK_INVALID_SOUND_ENVIRONMENT_OPTION,
	SEXP_CHECK_INVALID_EXPLOSION_OPTION,
	SEXP_CHECK_INVALID_SHIP_EFFECT,
	SEXP_CHECK_INVALID_TURRET_TARGET_ORDER,
	SEXP_CHECK_INVALID_TURRET_TYPE,
	SEXP_CHECK_INVALID_ARMOR_TYPE,
	SEXP_CHECK_INVALID_DAMAGE_TYPE,
	SEXP_CHECK_INVALID_TARGET_PRIORITIES,
	SEXP_CHECK_INVALID_AUDIO_VOLUME_OPTION,
	SEXP_CHECK_INVALID_BUILTIN_HUD_GAUGE,
	SEXP_CHECK_INVALID_ANIMATION_TYPE,
	SEXP_CHECK_INVALID_MISSION_MOOD,
	SEXP_CHECK_INVALID_SHIP_FLAG,
	SEXP_CHECK_INVALID_TEAM_COLOR,
	SEXP_CHECK_INVALID_SKYBOX_FLAG,
	SEXP_CHECK_INVALID_GAME_SND,
	SEXP_CHECK_INVALID_SSM_CLASS,
	SEXP_CHECK_INVALID_FIREBALL,
	SEXP_CHECK_INVALID_SPECIES,
	SEXP_CHECK_INVALID_FUNCTIONAL_WHEN_EVAL_TYPE,
	SEXP_CHECK_MISPLACED_SPECIAL_ARGUMENT,
	SEXP_CHECK_AMBIGUOUS_GOAL_NAME,
	SEXP_CHECK_AMBIGUOUS_EVENT_NAME,
	SEXP_CHECK_INVALID_CONTAINER,
	SEXP_CHECK_MISSING_CONTAINER_MODIFIER,
	SEXP_CHECK_INVALID_LIST_MODIFIER,
	SEXP_CHECK_WRONG_MAP_KEY_TYPE,
	SEXP_CHECK_WRONG_CONTAINER_TYPE,
	SEXP_CHECK_INVALID_ANIMATION,
	SEXP_CHECK_WRONG_CONTAINER_DATA_TYPE,
	SEXP_CHECK_INVALID_SPECIAL_ARG_TYPE,
	SEXP_CHECK_INVALID_AWACS_SUBSYS,
	SEXP_CHECK_INVALID_ROTATING_SUBSYS,
	SEXP_CHECK_INVALID_TRANSLATING_SUBSYS,
	SEXP_CHECK_INVALID_ANY_HUD_GAUGE,
	SEXP_CHECK_INVALID_WING_FLAG,
	SEXP_CHECK_INVALID_WING_FORMATION,
	SEXP_CHECK_INVALID_ASTEROID,
	SEXP_CHECK_INVALID_MOTION_DEBRIS,
	SEXP_CHECK_INVALID_BOLT_TYPE,
	SEXP_CHECK_INVALID_TRAITOR_OVERRIDE,
	SEXP_CHECK_INVALID_LUA_GENERAL_ORDER,
	SEXP_CHECK_INVALID_SHIP_POINT,
	SEXP_CHECK_INVALID_SHIP_WING_SHIPONTEAM_POINT,
	SEXP_CHECK_INVALID_SHIP_WING_POINT,
	SEXP_CHECK_INVALID_ORDER_RECIPIENT,
	SEXP_CHECK_INVALID_SHIP_WING_WHOLETEAM,
	SEXP_CHECK_MUST_BE_INTEGER,
	SEXP_CHECK_INVALID_CUSTOM_STRING,
	SEXP_CHECK_INVALID_MESSAGE_TYPE,
	SEXP_CHECK_POTENTIAL_ISSUE,
};


#define TRAINING_CONTEXT_SPEED		(1<<0)
#define TRAINING_CONTEXT_FLY_PATH	(1<<1)

// numbers used in special_training_check() function
#define SPECIAL_CHECK_TRAINING_FAILURE	2000

typedef struct sexp_ai_goal_link {
	int ai_goal;
	int op_code;
} sexp_ai_goal_link;


enum class sexp_oper_type
{
	NONE = 0,
	CONDITIONAL,
	ARGUMENT,
	ACTION,
	ARITHMETIC,
	BOOLEAN,
	INTEGER,
	GOAL
};

typedef struct sexp_oper {
	SCP_string text;
	int	value;
	int	min, max;
	sexp_oper_type type;
} sexp_oper;

// Goober5000
struct sexp_cached_data
{
	int sexp_node_data_type = OPF_NONE;		// an OPF_ #define
	int numeric_literal = 0;				// i.e. a number
	int ship_registry_index = -1;			// because ship status is pretty common
	int other_index = -1;					// could be an IFF, a wing, a goal, or other index
	// jg18 - used to store result from sexp_container_CTEXT()
	char container_CTEXT_result[TOKEN_LENGTH] = "";

	sexp_cached_data() = default;

	sexp_cached_data(int _sexp_node_data_type)
		: sexp_node_data_type(_sexp_node_data_type)
	{}

	sexp_cached_data(int _sexp_node_data_type, int _other_index)
		: sexp_node_data_type(_sexp_node_data_type), other_index(_other_index)
	{}

	sexp_cached_data(int _sexp_node_data_type, int _numeric_literal, int _ship_registry_index)
		: sexp_node_data_type(_sexp_node_data_type), numeric_literal(_numeric_literal), ship_registry_index(_ship_registry_index)
	{}

	sexp_cached_data(int _sexp_node_data_type, const SCP_string &_container_CTEXT_result)
		: sexp_node_data_type(_sexp_node_data_type)
	{
		update_container_CTEXT_result(_container_CTEXT_result);
	}

	void update_container_CTEXT_result(const SCP_string &_container_CTEXT_result)
	{
		if (_container_CTEXT_result.empty()) {
			Warning(LOCATION, "assigning empty string to SEXP node text");
		} else if (_container_CTEXT_result.length() >= sizeof(container_CTEXT_result)) {
			Warning(LOCATION,
				"attempt to assign CTEXT() result %s which is too long (limit %d)",
				_container_CTEXT_result.c_str(),
				(int)(sizeof(container_CTEXT_result) - 1));
		}

		const auto length = _container_CTEXT_result.copy(container_CTEXT_result, sizeof(container_CTEXT_result) - 1);
		container_CTEXT_result[length] = 0;
	}
};

typedef struct sexp_node {
	char	text[TOKEN_LENGTH];
	int op_index;				// the index in the Operators array for the operator at this node (or -1 if not an operator)
	int	type;						// atom, list, or not used
	int	subtype;					// type of atom or list?
	int	first;					// if first parameter is sexp, index into Sexp_nodes
	int	rest;						// index into Sexp_nodes of rest of parameters
	int	value;					// known to be true, known to be false, or not known
	int flags;					// Goober5000

	sexp_cached_data *cache;	// Goober5000
	int cached_variable_index;	// Goober5000
} sexp_node;

// Goober5000
#define SNF_ARGUMENT_VALID			(1<<0)
#define SNF_ARGUMENT_SELECT			(1<<1)
#define SNF_SPECIAL_ARG_IN_NODE		(1<<2)
#define SNF_SPECIAL_ARG_IN_TREE		(1<<3)
#define SNF_SPECIAL_ARG_NOT_IN_TREE	(1<<4)
#define SNF_CHECKED_ARG_FOR_VAR		(1<<5)
#define SNF_CHECKED_NODE_FOR_OPF_POSITIVE	(1<<6)
#define SNF_NODE_IS_OPF_POSITIVE	(1<<7)
#define SNF_DESCENDANT_OF_WHEN_ARG_OP		(1<<8)
#define SNF_NOT_DESCENDANT_OF_WHEN_ARG_OP	(1<<9)
#define SNF_DEFAULT_VALUE			SNF_ARGUMENT_VALID

typedef struct sexp_variable {
	int		type;
	char	text[TOKEN_LENGTH];
	char	variable_name[TOKEN_LENGTH];
} sexp_variable;

// next define used to eventually mark a directive as satisfied even though there may be more
// waves for a wing.  bascially a hack for the directives display.
#define DIRECTIVE_WING_ZERO		-999

// Goober5000 - it's dynamic now
//extern sexp_node Sexp_nodes[MAX_SEXP_NODES];

extern int Num_sexp_nodes;
extern sexp_node *Sexp_nodes;

extern sexp_variable Sexp_variables[MAX_SEXP_VARIABLES];
extern sexp_variable Block_variables[MAX_SEXP_VARIABLES];

extern SCP_vector<sexp_oper> Operators;
extern SCP_vector<int> Sorted_operator_indexes;
extern size_t Max_operator_length;

extern int Locked_sexp_true, Locked_sexp_false;
extern int Directive_count;
extern int Sexp_useful_number;  // a variable to pass useful info in from external modules
extern bool Assume_event_is_current;
extern int Sexp_clipboard;  // used by Fred

extern SCP_vector<int> Current_sexp_operator;


// event log stuff
extern SCP_vector<SCP_string> *Current_event_log_buffer;
extern SCP_vector<SCP_string> *Current_event_log_variable_buffer;
extern SCP_vector<SCP_string> *Current_event_log_container_buffer;
extern SCP_vector<SCP_string> *Current_event_log_argument_buffer;

extern void init_sexp();
extern void sexp_startup();
extern void sexp_shutdown();
extern int alloc_sexp(const char *text, int type, int subtype, int first, int rest);
extern int find_free_sexp();
extern int free_one_sexp(int num);
extern int free_sexp(int num, int calling_node = -1);
extern int free_sexp2(int num, int calling_node = -1);
extern int dup_sexp_chain(int node);
extern int cmp_sexp_chains(int node1, int node2);
extern int find_sexp_list(int num);
extern int find_parent_operator(int num);
extern int is_sexp_top_level( int node );

// Goober5000 - renamed these to be more clear, to prevent bugs :p
extern int get_operator_index(const char *token);
extern int get_operator_index(int node);
extern int get_operator_const(const char *token);
extern int get_operator_const(int node);
extern int find_operator_index(int op_const);

extern int check_sexp_syntax(int node, int return_type = OPR_BOOL, int recursive = 0, int *bad_node = 0 /*NULL*/, sexp_mode mode = sexp_mode::GENERAL);
extern int check_sexp_potential_issues(int node, int *bad_node, SCP_string &issue_msg);
extern int get_sexp_main(void);	//	Returns start node
extern int run_sexp(const char* sexpression, bool run_eval_num = false, bool *is_nan_or_nan_forever = nullptr); // debug and lua sexps
extern int stuff_sexp_variable_list();
extern int eval_sexp(int cur_node, int referenced_node = -1);
extern int eval_num(int n, bool &is_nan, bool &is_nan_forever);
extern bool is_sexp_true(int cur_node, int referenced_node = -1);
extern bool map_opf_to_opr(sexp_opf_t opf_type, sexp_opr_t &opr_type);
const char *opr_type_name(sexp_opr_t opr_type);
extern int query_operator_return_type(int op);
extern int query_operator_argument_type(int op, int argnum);
extern void update_sexp_references(const char *old_name, const char *new_name);
extern void update_sexp_references(const char *old_name, const char *new_name, int format);
extern std::pair<int, sexp_src> query_referenced_in_sexp(sexp_ref_type type, const char *name, int &node);
extern void stuff_sexp_text_string(SCP_string &dest, int node, int mode);
extern int build_sexp_string(SCP_string &accumulator, int cur_node, int level, int mode);
extern bool sexp_query_type_match(int opf, int opr);
extern int sexp_match_closest_operator(const SCP_string &str, int opf);
extern bool sexp_recoverable_error(int num);
extern const char *sexp_error_message(int num);
extern int count_free_sexp_nodes();


struct ship_registry_entry;
struct wing;

// Goober5000 - stuff with caching
// (included in the header file because Lua uses the first three)
extern const ship_registry_entry *eval_ship(int node);
extern wing *eval_wing(int node);
extern int sexp_get_variable_index(int node);
extern int sexp_atoi(int node);
extern bool sexp_can_construe_as_integer(int node);

// Goober5000 - for special-arg SEXPs
extern bool is_when_argument_op(int op_const);
extern bool is_argument_provider_op(int op_const);
extern bool is_implicit_argument_provider_op(int op_const); // jg18
extern int find_argument_provider(int node);

// functions to change the attributes of an sexpression tree to persistent or not persistent
extern void sexp_unmark_persistent( int n );
extern void sexp_mark_persistent( int n );
extern int verify_sexp_tree(int node);
extern int query_sexp_ai_goal_valid(int sexp_ai_goal, int ship);
int query_node_in_sexp(int node, int sexp);
void flush_sexp_tree(int node);

// sexp_variable
void sexp_modify_variable(const char *text, int index, bool sexp_callback = true);
int get_index_sexp_variable_name(const char *text);
int get_index_sexp_variable_name(SCP_string &text);	// Goober5000
int get_index_sexp_variable_name_special(const char *text);	// Goober5000
int get_index_sexp_variable_name_special(SCP_string &text, size_t startpos);	// Goober5000
bool sexp_replace_variable_names_with_values(char *text, int max_len);	// Goober5000
bool sexp_replace_variable_names_with_values(SCP_string &text);	// Goober5000
int get_nth_variable_index(int nth, int variable_type);	// Karajorma
int sexp_variable_count();
int sexp_campaign_file_variable_count();	// Goober5000
int sexp_variable_typed_count(int sexp_variables_index, int variable_type); // Karajorma
void sexp_variable_delete(int index);
void sexp_variable_sort();
void sexp_fred_modify_variable(const char *text, const char *var_name, int index, int type);
int sexp_add_variable(const char *text, const char *var_name, int type, int index=-1);
bool generate_special_explosion_block_variables();
int num_block_variables();
bool has_special_explosion_block_index(ship *shipp, int *index);

extern bool usable_in_campaign(int op_id);
extern int get_category(int op_id);
extern int category_of_subcategory(int subcategory_id);
extern int get_subcategory(int op_id);
extern const char *get_category_name(int category_id);

// Goober5000
extern void sexp_music_close();

//WMC - moved here from FRED
typedef struct sexp_help_struct {
	int id;
	SCP_string help;
} sexp_help_struct;

extern SCP_vector<sexp_help_struct> Sexp_help;

typedef struct op_menu_struct {
	SCP_string name;
	int id;
} op_menu_struct;

extern SCP_vector<op_menu_struct> op_menu;
extern SCP_vector<op_menu_struct> op_submenu;

//WMC
//Outputs sexp.html file
bool output_sexps(const char *filepath);

void multi_sexp_eval();

// Goober5000/Taylor
extern int Num_sound_environment_options;
extern const char *Sound_environment_option[];

// Goober5000
extern int Num_explosion_options;
extern const char *Explosion_option[];

extern int Num_functional_when_eval_types;
extern const char *Functional_when_eval_type[];

//The E
extern int Num_adjust_audio_options;
extern const char *Adjust_audio_options[];

extern int Num_skybox_flags;
extern const char *Skybox_flags[];

/** Global state variables for the hud-display-gauge sexp.
They all should be named Sexp_hud_display_*;
They all should follow the following symantics for the value of the
variable:
=0	don't show
=1	show until canceled
>1	timestamp when gauge should stop showing (set zero when expired)
\sa sexp_hud_display_warpout
*/
extern int Sexp_hud_display_warpout;

//Needed for scripting access to ship effects
int get_effect_from_name(const char* name);

void maybe_write_to_event_log(int result);

//OSWPT Stuff

enum class oswpt_type : uint8_t
{
	NONE = 0,
	SHIP,
	WING,
	WAYPOINT,
	SHIP_ON_TEAM,		// e.g. <any friendly>
	WHOLE_TEAM,			// e.g. Friendly
	PARSE_OBJECT,		// a "ship" that hasn't arrived yet
	EXITED,
	WING_NOT_PRESENT	// a wing that hasn't arrived yet or is between waves
};

namespace scripting {
	class ade_table_entry;
}
namespace luacpp {
	class LuaValue;
}
struct lua_State;

// Goober5000
struct object_ship_wing_point_team
{
	char object_name[NAME_LENGTH] = { 0 };
	oswpt_type type = oswpt_type::NONE;

	int ship_registry_index = -1;
	int objnum = -1;
	int wingnum = -1;
	int wp_list = -1;
	int wp_index = -1;
	int team = -1;

	object_ship_wing_point_team() = default;
	object_ship_wing_point_team(ship* sp);
	object_ship_wing_point_team(p_object* pop);
	object_ship_wing_point_team(ship_obj* sop);
	object_ship_wing_point_team(wing* wp);

	inline bool has_ship_entry() const { return ship_registry_index >= 0; }
	inline bool has_objp() const { return objnum >= 0; }
	inline bool has_wingp() const { return wingnum >= 0; }
	inline bool has_waypointp() const { return wp_list >= 0 && wp_index >= 0; }

	const ship_registry_entry* ship_entry() const;
	object* objp() const;
	wing* wingp() const;
	waypoint* waypointp() const;

	const ship_registry_entry* ship_entry_or_null() const;
	object* objp_or_null() const;
	wing* wingp_or_null() const;
	waypoint* waypointp_or_null() const;

	bool has_p_objp() const;
	bool has_shipp() const;

	p_object* p_objp() const;
	ship* shipp() const;

	p_object* p_objp_or_null() const;
	ship* shipp_or_null() const;

	bool matches(const ship* shipp) const;
	void clear();

	bool operator==(const object_ship_wing_point_team &other) const;
	bool operator!=(const object_ship_wing_point_team &other) const;
};

void eval_object_ship_wing_point_team(object_ship_wing_point_team* oswpt, int node, const char* ctext_override = nullptr);

bool sexp_check_flag_arrays(const char *flag_name, Object::Object_Flags &object_flag, Ship::Ship_Flags &ship_flag, Mission::Parse_Object_Flags &parse_obj_flag, AI::AI_Flags &ai_flag);
bool sexp_check_flag_array(const char* flag_name, Ship::Wing_Flags& wing_flag);

#endif