Skip to content

Commit 5366f23

Browse files
committed
Allow custom Lua Enums
1 parent 49b486a commit 5366f23

File tree

7 files changed

+96
-112
lines changed

7 files changed

+96
-112
lines changed

code/parse/sexp.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,8 @@ sexp_ai_goal_link Sexp_ai_goal_links[] = {
889889
{ AI_GOAL_REARM_REPAIR, OP_AI_REARM_REPAIR },
890890
};
891891

892+
SCP_vector<enum_list> Enums;
893+
892894
void sexp_set_skybox_model_preload(const char *name); // taylor
893895
int Num_skybox_flags = 6;
894896
const char *Skybox_flags[] = {
@@ -3948,7 +3950,17 @@ int check_sexp_syntax(int node, int return_type, int recursive, int *bad_node, i
39483950
break;
39493951

39503952
default:
3951-
Error(LOCATION, "Unhandled argument format");
3953+
if (Enums.size() > 0) {
3954+
if ((type - First_available_list_id) < (int)Enums.size()) {
3955+
if (type2 != SEXP_ATOM_STRING)
3956+
return SEXP_CHECK_TYPE_MISMATCH;
3957+
} else {
3958+
Error(LOCATION, "Unhandled argument format");
3959+
}
3960+
} else {
3961+
Error(LOCATION, "Unhandled argument format");
3962+
}
3963+
39523964
}
39533965

39543966
node = Sexp_nodes[node].rest;

code/parse/sexp.h

Lines changed: 6 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -135,110 +135,12 @@ enum : int {
135135
First_available_list_id
136136
};
137137

138-
// Operator argument formats (data types of an argument)
139-
/*#define OPF_NONE 1 // argument cannot exist at this position if it's this
140-
#define OPF_NULL 2 // no value. Can still be used for type matching, however
141-
#define OPF_BOOL 3
142-
#define OPF_NUMBER 4
143-
#define OPF_SHIP 5
144-
#define OPF_WING 6
145-
#define OPF_SUBSYSTEM 7
146-
#define OPF_POINT 8 // either a 3d point in space, or a waypoint name
147-
#define OPF_IFF 9
148-
#define OPF_AI_GOAL 10 // special to match ai goals
149-
#define OPF_DOCKER_POINT 11 // docking point on docker ship
150-
#define OPF_DOCKEE_POINT 12 // docking point on dockee ship
151-
#define OPF_MESSAGE 13 // the name (id) of a message in Messages[] array
152-
#define OPF_WHO_FROM 14 // who sent the message -- doesn't necessarily have to be a ship!!!
153-
#define OPF_PRIORITY 15 // priority for messages
154-
#define OPF_WAYPOINT_PATH 16 // name of a waypoint
155-
#define OPF_POSITIVE 17 // positive number or zero
156-
#define OPF_MISSION_NAME 18 // name of a mission for various mission related things
157-
#define OPF_SHIP_POINT 19 // a waypoint or a ship
158-
#define OPF_GOAL_NAME 20 // name of goal (or maybe event?) from a mission
159-
#define OPF_SHIP_WING 21 // either a ship or wing name (they don't conflict)
160-
#define OPF_SHIP_WING_WHOLETEAM 22 // Karajorma - Ship, wing or an entire team's worth of ships
161-
#define OPF_SHIP_WING_SHIPONTEAM_POINT 23 // name of a ship, wing, any ship on a team, or a point
162-
#define OPF_SHIP_WING_POINT 24
163-
#define OPF_SHIP_WING_POINT_OR_NONE 25 // WMC - Ship, wing, point or none
164-
#define OPF_SHIP_TYPE 26 // type of ship (fighter/bomber/etc)
165-
#define OPF_KEYPRESS 27 // a default key
166-
#define OPF_EVENT_NAME 28 // name of an event
167-
#define OPF_AI_ORDER 29 // a squadmsg order player can give to a ship
168-
#define OPF_SKILL_LEVEL 30 // current skill level of the game
169-
#define OPF_MEDAL_NAME 31 // name of medals
170-
#define OPF_WEAPON_NAME 32 // name of a weapon
171-
#define OPF_SHIP_CLASS_NAME 33 // name of a ship class
172-
#define OPF_CUSTOM_HUD_GAUGE 34 // name of custom HUD gauge
173-
#define OPF_HUGE_WEAPON 35 // name of a secondary bomb type weapon
174-
#define OPF_SHIP_NOT_PLAYER 36 // a ship, but not a player ship
175-
#define OPF_JUMP_NODE_NAME 37 // name of a jump node
176-
#define OPF_VARIABLE_NAME 38 // variable name
177-
#define OPF_AMBIGUOUS 39 // type used with variable
178-
#define OPF_AWACS_SUBSYSTEM 40 // an awacs subsystem
179-
#define OPF_CARGO 41 // Goober5000 - a cargo string (currently used for set-cargo and is-cargo)
180-
#define OPF_AI_CLASS 42 // Goober5000 - an AI class
181-
#define OPF_SUPPORT_SHIP_CLASS 43 // Goober5000 - a support ship class
182-
#define OPF_ARRIVAL_LOCATION 44 // Goober5000 - a ship arrival location
183-
#define OPF_ARRIVAL_ANCHOR_ALL 45 // Goober5000 - all of a ship's possible arrival anchors
184-
#define OPF_DEPARTURE_LOCATION 46 // Goober5000 - a ship departure location
185-
#define OPF_SHIP_WITH_BAY 47 // Goober5000 - a ship with a fighter bay
186-
#define OPF_SOUNDTRACK_NAME 48 // Goober5000 - the name of a music soundtrack
187-
#define OPF_INTEL_NAME 49 // Goober5000 - the name of an intel entry in species.tbl
188-
#define OPF_STRING 50 // Goober5000 - any old string
189-
#define OPF_ROTATING_SUBSYSTEM 51 // Goober5000 - a rotating subsystem
190-
#define OPF_NAV_POINT 52 // Kazan - a Nav Point name
191-
#define OPF_SSM_CLASS 53 // Goober5000 - an SSM class
192-
#define OPF_FLEXIBLE_ARGUMENT 54 // Goober5000 - special to match for when-argument
193-
#define OPF_ANYTHING 55 // Goober5000 - anything goes, except containers
194-
#define OPF_SKYBOX_MODEL_NAME 56 // taylor - changing skybox model
195-
#define OPF_SHIP_OR_NONE 57 // Goober5000 - an "optional" ship argument
196-
#define OPF_BACKGROUND_BITMAP 58 // phreak - name of a background bitmap
197-
#define OPF_SUN_BITMAP 59 // phreak - name of a background bitmap
198-
#define OPF_NEBULA_STORM_TYPE 60 // phreak - name a nebula storm
199-
#define OPF_NEBULA_POOF 61 // phreak - name of a nebula poof
200-
#define OPF_TURRET_TARGET_ORDER 62 // WMC - name of a turret target type (see aiturret.cpp)
201-
#define OPF_SUBSYSTEM_OR_NONE 63 // Goober5000 - an "optional" subsystem argument
202-
#define OPF_PERSONA 64 // Karajorma - name of a persona
203-
#define OPF_SUBSYS_OR_GENERIC 65 // Karajorma - a subsystem or a generic name (like engine) which covers all subsystems of that type
204-
#define OPF_ORDER_RECIPIENT 66 // Karajorma - since orders can go to All Fighters as well as a ship or wing
205-
#define OPF_SUBSYSTEM_TYPE 67 // Goober5000 - a generic subsystem type (navigation, engines, etc.) rather than a specific subsystem
206-
#define OPF_POST_EFFECT 68 // Hery - type of post-processing effect
207-
#define OPF_TARGET_PRIORITIES 69 // FUBAR - Target priority groups
208-
#define OPF_ARMOR_TYPE 70 // FUBAR - Armor type or <none>
209-
#define OPF_FONT 71 // Goober5000 - a FreeSpace font
210-
#define OPF_HUD_ELEMENT 72 // A magic name of a specific HUD element
211-
#define OPF_SOUND_ENVIRONMENT 73 // Goober5000 - one of EFX_presets, per Taylor
212-
#define OPF_SOUND_ENVIRONMENT_OPTION 74 // Goober5000 - one of Taylor's options
213-
#define OPF_EXPLOSION_OPTION 75 // Goober5000
214-
#define OPF_AUDIO_VOLUME_OPTION 76 // The E
215-
#define OPF_WEAPON_BANK_NUMBER 77 // Karajorma - The number of a primary/secondary/tertiary weapon bank or all of them
216-
#define OPF_MESSAGE_OR_STRING 78 // Goober5000 - provides a list of messages like OPF_MESSAGE, but also allows entering arbitrary strings
217-
#define OPF_BUILTIN_HUD_GAUGE 79 // The E
218-
#define OPF_DAMAGE_TYPE 80 // FUBAR - Damage type or <none>
219-
#define OPF_SHIP_EFFECT 81 // The E - per-ship effects, as defined in post-processing.tbl
220-
#define OPF_ANIMATION_TYPE 82 // Goober5000 - as defined in modelanim.h
221-
#define OPF_MISSION_MOOD 83 // Karajorma - Moods determine which builtin messages will be sent
222-
#define OPF_SHIP_FLAG 84 // Karajorma - The name of a ship flag
223-
#define OPF_TEAM_COLOR 85 // The E - Color settings as defined in Colors.tbl
224-
#define OPF_NEBULA_PATTERN 86 // Axem - Full Nebula Background Patterns, as defined in nebula.tbl
225-
#define OPF_SKYBOX_FLAGS 87 // niffiwan - valid skybox flags
226-
#define OPF_GAME_SND 88 // m!m - A game sound
227-
#define OPF_FIREBALL 89 // Goober5000 - an entry in fireball.tbl
228-
#define OPF_SPECIES 90 // Goober5000
229-
#define OPF_LANGUAGE 91 // Goober5000
230-
#define OPF_FUNCTIONAL_WHEN_EVAL_TYPE 92 // Goober5000
231-
#define OPF_CONTAINER_NAME 93 // Karajorma/jg18 - The name of a SEXP container
232-
#define OPF_LIST_CONTAINER_NAME 94 // Karajorma/jg18 - The name of a SEXP list container
233-
#define OPF_MAP_CONTAINER_NAME 95 // Karajorma/jg18 - The name of a SEXP map container
234-
#define OPF_ANIMATION_NAME 96 // Lafiel
235-
#define OPF_CONTAINER_VALUE 97 // jg18 - Container data and map container keys
236-
#define OPF_DATA_OR_STR_CONTAINER 98 // jg18 - any data, or a container that is accessed via strings
237-
#define OPF_TRANSLATING_SUBSYSTEM 99 // Goober5000 - a translating subsystem
238-
#define OPF_ANY_HUD_GAUGE 100 // Goober5000 - both custom and builtin
239-
#define OPF_WING_FLAG 101 // Goober5000 - The name of a wing flag
240-
#define OPF_ASTEROID_DEBRIS 102 // MjnMixael - Debris types as defined in asteroids.tbl
241-
#define OPF_WING_FORMATION 103 // Goober5000 - as defined in ships.tbl*/
138+
typedef struct enum_list {
139+
SCP_string name;
140+
SCP_vector<SCP_string> list;
141+
}enum_list;
142+
143+
extern SCP_vector<enum_list> Enums;
242144

243145
// Operand return types
244146
#define OPR_NUMBER 1 // returns number

code/parse/sexp/LuaSEXP.cpp

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ static SCP_unordered_map<SCP_string, int> parameter_type_mapping{{ "boolean",
4545
{ "ship+wing+team", OPF_SHIP_WING_WHOLETEAM },
4646
{ "ship+wing+ship_on_team+waypoint", OPF_SHIP_WING_SHIPONTEAM_POINT },
4747
{ "ship+wing+waypoint", OPF_SHIP_WING_POINT },
48-
{ "ship+wing+waypoint+none", OPF_SHIP_WING_POINT_OR_NONE }, };
48+
{ "ship+wing+waypoint+none", OPF_SHIP_WING_POINT_OR_NONE },
49+
{ "enum", First_available_list_id } };
4950

5051
std::pair<SCP_string, int> LuaSEXP::get_parameter_type(const SCP_string& name)
5152
{
@@ -245,8 +246,14 @@ luacpp::LuaValue LuaSEXP::sexpToLua(int node, int argnum) const {
245246
return LuaValue::createValue(_action.getLuaState(), l_OSWPT.Set(oswpt));
246247
}
247248
default:
248-
UNREACHABLE("Unhandled argument type! Someone added an argument type but didn't add handling code to execute().");
249-
return LuaValue::createNil(_action.getLuaState());
249+
if ((strcmp(argtype.first.c_str(), "enum")) == 0) {
250+
auto text = CTEXT(node);
251+
return LuaValue::createValue(_action.getLuaState(), text);
252+
} else {
253+
UNREACHABLE(
254+
"Unhandled argument type! Someone added an argument type but didn't add handling code to execute().");
255+
return LuaValue::createNil(_action.getLuaState());
256+
}
250257
}
251258
}
252259
int LuaSEXP::getSexpReturnValue(const LuaValueList& retVals) const {
@@ -518,6 +525,33 @@ void LuaSEXP::parseTable() {
518525
type = get_parameter_type("string");
519526
}
520527

528+
if ((strcmp(type.first.c_str(), "enum")) == 0) {
529+
type.second = increment_list_id();
530+
required_string("+Enum Name:");
531+
532+
SCP_string enum_name;
533+
stuff_string(enum_name, F_NAME);
534+
535+
enum_list thisList;
536+
thisList.name = enum_name;
537+
538+
SCP_vector<SCP_string> list_items;
539+
while (optional_string("+Enum:")) {
540+
SCP_string item;
541+
stuff_string(item, F_NAME);
542+
list_items.push_back(item);
543+
}
544+
545+
if ((int)list_items.size() > 0) {
546+
thisList.list = list_items;
547+
} else {
548+
thisList.list.push_back("<none>");
549+
}
550+
551+
Enums.push_back(thisList);
552+
553+
}
554+
521555
if (variable_arg_part) {
522556
_varargs_type_pattern.push_back(type);
523557
} else {

code/parse/sexp/sexp_lookup.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,13 @@ DynamicSEXP* get_dynamic_sexp(int operator_const)
199199

200200
return iter->second.get();
201201
}
202-
int get_category_of_subcategory(int subcategory_id)
202+
int increment_list_id()
203203
{
204+
auto& global = globals();
205+
return global.next_free_list_id++;
206+
}
207+
int get_category_of_subcategory(int subcategory_id)
208+
{
204209
const auto& global = globals();
205210

206211
auto iter = global.subcategory_to_category.find(subcategory_id);

code/parse/sexp/sexp_lookup.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ int get_category_of_subcategory(int subcategory_id);
4444
*/
4545
int add_category(const SCP_string& name);
4646

47+
int increment_list_id();
48+
4749
/**
4850
* @brief Dynamically add a new subcategory to the SEXP system
4951
*

fred2/sexp_tree.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3499,7 +3499,15 @@ int sexp_tree::query_default_argument_available(int op, int i)
34993499
return 0;
35003500

35013501
default:
3502-
Int3();
3502+
if (Enums.size() > 0) {
3503+
if ((type - First_available_list_id) < (int)Enums.size()) {
3504+
return 1;
3505+
} else {
3506+
UNREACHABLE("Unhandled SEXP argument type!");
3507+
}
3508+
} else {
3509+
UNREACHABLE("Unhandled SEXP argument type!");
3510+
}
35033511

35043512
}
35053513

@@ -5438,8 +5446,8 @@ sexp_list_item *sexp_tree::get_listing_opf(int opf, int parent_node, int arg_ind
54385446
break;
54395447

54405448
default:
5441-
Int3(); // unknown OPF code
5442-
list = NULL;
5449+
//We're at the end of the list so check for any dynamic enums
5450+
list = check_for_dynamic_sexp_enum(opf);
54435451
break;
54445452
}
54455453

@@ -7348,6 +7356,26 @@ sexp_list_item *sexp_tree::get_container_multidim_modifiers(int con_data_node) c
73487356
return head.next;
73497357
}
73507358

7359+
sexp_list_item* sexp_tree::check_for_dynamic_sexp_enum(int opf)
7360+
{
7361+
sexp_list_item head;
7362+
7363+
int item = opf - First_available_list_id;
7364+
7365+
if (item <= (int)Enums.size()) {
7366+
7367+
for (int i = 0; i < (int)Enums[item].list.size(); i++) {
7368+
mprintf(("ENUMS adding item %s\n", Enums[item].list[i].c_str()));
7369+
head.add_data(Enums[item].list[i].c_str());
7370+
}
7371+
return head.next;
7372+
} else {
7373+
// else if opf is invalid do this
7374+
UNREACHABLE("Unhandled SEXP argument type!"); // unknown OPF code
7375+
return NULL;
7376+
}
7377+
}
7378+
73517379
// given a node's parent, check if node is eligible for being used with the special argument
73527380
bool sexp_tree::is_node_eligible_for_special_argument(int parent_node) const
73537381
{

fred2/sexp_tree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ class sexp_tree : public CTreeCtrl
304304
sexp_list_item *get_listing_opf_animation_name(int parent_node);
305305
sexp_list_item *get_listing_opf_sexp_containers(ContainerType con_type);
306306
sexp_list_item *get_listing_opf_wing_formation();
307+
sexp_list_item* check_for_dynamic_sexp_enum(int opf);
307308

308309
// container modifier options for container data nodes
309310
sexp_list_item *get_container_modifiers(int con_data_node) const;

0 commit comments

Comments
 (0)