Author Topic: Strict Typing For Variables (Somewhat Alpha)  (Read 1946 times)

0 Members and 1 Guest are viewing this topic.

Offline karajorma

  • King Louie - Jungle VIP
  • Administrator
  • 214
    • Karajorma's Freespace FAQ
Strict Typing For Variables (Somewhat Alpha)
This is something of a spin-off from my work on SEXP Containers (where it will be much more useful) but here's a set of builds that allow you to strictly typecast your SEXP Variables. What does that mean? Well instead of simply declaring String or Number variables, this build allows you to set a second option which says that your string variable must be the name of a ship, or a persona, or any other type of option that is defined in sexp.h as an OPF type.

Why would you want to do this? Well one advantage is that it should cut down on stupid errors like telling the game to set a variable to "Gama 1" Another advantage is that the game should generate proper popup menu lists of all the things of that type when you right-click on the entry. Simple add a modify-variable SEXP, choose a strictly typed variable and when you right click on the <any data> you can simply choose from the Replace Data option like you would for normal SEXP.

Since things are still somewhat alpha, I added all the OPF types including those which make no sense (adding Any String is exactly the same as not having a strictly typed string variable for instance). I'll trim things down to only the useful ones later.


The feature needs some testing of course so you can find the builds here. I'd advise using a copy of your missions for any testing as things may change when I start adding the same feature to the SEXP Containers. That said, I'd suggest that people select a fairly advanced mission and try setting a strict type on all their variables so that I can deal with any bugs found. Changes to the mission are pretty minimal anyway

Code: [Select]
$Variables:
(
0 "Simple_String" "Simple value" "string"
1 "Strict_String" "Beta 2" "string" "strict-type" 5

this type for instance will only allow you to use modify-variable with a ship that is actually in the mission and will pop up an error message if the string is not a ship name.

I suspect strong typing for arguments would be more difficult to do but if there is interest (or someone like Goober has a good idea on how to do it easily) I might give them a try too because after starting a when-argument SEXP I tend to find it annoying to have to add strings from the menu and then change them manually to something useful.

Here's the code

Code: [Select]
Index: code/fred2/addvariabledlg.cpp
===================================================================
--- code/fred2/addvariabledlg.cpp (revision 11138)
+++ code/fred2/addvariabledlg.cpp (working copy)
@@ -56,6 +56,7 @@
  ON_BN_CLICKED(IDC_TYPE_CAMPAIGN_PERSISTENT, OnTypeCampaignPersistent)
  ON_BN_CLICKED(IDC_TYPE_PLAYER_PERSISTENT, OnTypePlayerPersistent)
  ON_BN_CLICKED(IDC_TYPE_NETWORK_VARIABLE, OnTypeNetworkVariable)
+ ON_CBN_SELCHANGE(IDC_RETURN_TYPE, OnSelchangeAddVariableReturnType)
  //}}AFX_MSG_MAP
 END_MESSAGE_MAP()
 
@@ -106,6 +107,8 @@
 BOOL CAddVariableDlg::OnInitDialog()
 {
  CDialog::OnInitDialog();
+
+ int i;
 
  // TODO: Add extra initialization here
  m_variable_name = "<Variable Name>";
@@ -122,6 +125,16 @@
  m_data_validated = false;
  m_create = false;
 
+ m_return_type = -1;
+
+ CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_RETURN_TYPE);
+
+ for (i = 0; i < NUM_OPERATOR_AGRUMENT_FORMATS; i++) {
+ cbox->AddString(Operator_Types[i].description);
+ }
+
+ cbox->SetCurSel(0);
+
  // Send default name and values into dialog box
  UpdateData(FALSE);
 
@@ -285,3 +298,8 @@
  ((CButton *) GetDlgItem(IDC_TYPE_PLAYER_PERSISTENT))->SetCheck(m_type_player_persistent);
  ((CButton *) GetDlgItem(IDC_TYPE_NETWORK_VARIABLE))->SetCheck(m_type_network_variable);
 }
+
+void CAddVariableDlg::OnSelchangeAddVariableReturnType()
+{
+ m_return_type = ((CComboBox *) GetDlgItem(IDC_RETURN_TYPE))->GetCurSel();
+}
\ No newline at end of file
Index: code/fred2/addvariabledlg.h
===================================================================
--- code/fred2/addvariabledlg.h (revision 11138)
+++ code/fred2/addvariabledlg.h (working copy)
@@ -38,7 +38,8 @@
  bool m_type_player_persistent;
  bool m_type_network_variable;
  bool m_create;
- int m_sexp_var_index;
+ int m_sexp_var_index;
+ int m_return_type;
  //}}AFX_DATA
 
 
@@ -64,6 +65,7 @@
  afx_msg void OnTypeCampaignPersistent();
  afx_msg void OnTypeNetworkVariable();
  afx_msg void set_variable_type();
+ afx_msg void OnSelchangeAddVariableReturnType();
  //}}AFX_MSG
  DECLARE_MESSAGE_MAP()
 };
Index: code/fred2/fred.rc
===================================================================
--- code/fred2/fred.rc (revision 11138)
+++ code/fred2/fred.rc (working copy)
@@ -1834,16 +1834,16 @@
     CONTROL         "Laser Protect Ship",IDC_LASER_PROTECT_SHIP,"Button",BS_3STATE | WS_TABSTOP,12,110,80,8
     CONTROL         "Missile Protect Ship",IDC_MISSILE_PROTECT_SHIP,"Button",BS_3STATE | WS_TABSTOP,12,118,80,8
     GROUPBOX        "Turret Threats",IDC_STATIC,7,83,102,48
-    CONTROL         "Does Not Move",IDC_IMMOBILE,"Button",BS_3STATE | WS_TABSTOP,7,274,66,10
-    CONTROL         "Cloaked",IDC_CLOAKED,"Button",BS_3STATE | WS_TABSTOP,165,167,42,10
-    CONTROL         "Scramble Messages",IDC_SCRAMBLE_MESSAGES,"Button",BS_3STATE | WS_TABSTOP,165,177,79,10
-    CONTROL         "No Collisions",IDC_NO_COLLIDE,"Button",BS_3STATE | WS_TABSTOP,165,188,66,10
-END
-
-IDD_ADD_VARIABLE DIALOG  0, 0, 422, 102
+    CONTROL         "Does Not Move",IDC_IMMOBILE,"Button",BS_3STATE | WS_TABSTOP,7,274,66,10
+    CONTROL         "Cloaked",IDC_CLOAKED,"Button",BS_3STATE | WS_TABSTOP,165,167,42,10
+    CONTROL         "Scramble Messages",IDC_SCRAMBLE_MESSAGES,"Button",BS_3STATE | WS_TABSTOP,165,177,79,10
+    CONTROL         "No Collisions",IDC_NO_COLLIDE,"Button",BS_3STATE | WS_TABSTOP,165,188,66,10
+END
+
+IDD_ADD_VARIABLE DIALOGEX 0, 0, 422, 102
 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Add Variable"
-FONT 8, "MS Sans Serif"
+FONT 8, "MS Sans Serif", 0, 0, 0x0
 BEGIN
     CONTROL         "String",IDC_TYPE_STRING,"Button",BS_AUTORADIOBUTTON,21,19,34,10
     CONTROL         "Number",IDC_TYPE_NUMBER,"Button",BS_AUTORADIOBUTTON,21,32,41,10
@@ -1858,12 +1858,14 @@
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,137,47,84,11
     CONTROL         "Player-Persistent",IDC_TYPE_PLAYER_PERSISTENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,137,59,84,11
     CONTROL         "Network-Variable",IDC_TYPE_NETWORK_VARIABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,137,71,84,11
+    COMBOBOX        IDC_RETURN_TYPE,251,54,156,143,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+    LTEXT           "Strict Type",IDC_STATIC,251,42,35,8
 END
 
-IDD_MODIFY_VARIABLE DIALOG  0, 0, 422, 102
+IDD_MODIFY_VARIABLE DIALOGEX 0, 0, 422, 102
 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Modify Variable"
-FONT 8, "MS Sans Serif"
+FONT 8, "MS Sans Serif", 0, 0, 0x0
 BEGIN
     CONTROL         "String",IDC_TYPE_STRING,"Button",BS_AUTORADIOBUTTON,21,19,34,10
     CONTROL         "Number",IDC_TYPE_NUMBER,"Button",BS_AUTORADIOBUTTON,21,32,41,10
@@ -1880,6 +1882,8 @@
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,138,47,84,11
     CONTROL         "Player-Persistent",IDC_TYPE_PLAYER_PERSISTENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,138,59,84,11
     CONTROL         "Network-Variable",IDC_TYPE_NETWORK_VARIABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,138,72,84,11
+    COMBOBOX        IDC_MODIFY_RETURN_TYPE,251,56,155,91,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+    LTEXT           "Strict Type",IDC_STATIC,251,40,35,8
 END
 
 IDD_SPECIAL_DAMAGE DIALOG  0, 0, 234, 129
@@ -2103,8 +2107,8 @@
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 3,7,1,000000
- PRODUCTVERSION 3,7,1,000000
+ FILEVERSION 3,7,1,0
+ PRODUCTVERSION 3,7,1,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -2662,6 +2666,8 @@
 BEGIN
     IDC_MODIFY_VARIABLE_NAME, 0x403, 1, 0
 "\000"
+    IDC_MODIFY_RETURN_TYPE, 0x403, 1, 0
+"\000"
     0
 END
 
Index: code/fred2/missionsave.cpp
===================================================================
--- code/fred2/missionsave.cpp (revision 11138)
+++ code/fred2/missionsave.cpp (working copy)
@@ -1145,6 +1145,11 @@
  // persistent and network variables
  if (Format_fs2_open != FSO_FORMAT_RETAIL)
  {
+ // Strict Type
+ if (Sexp_variables[i].strict_type != 0) {
+ fout("\t\t\"%s\"\t%d", "strict-type", Sexp_variables[i].strict_type);
+ }
+
  // Network variable - Karajorma
  if (Sexp_variables[i].type & SEXP_VARIABLE_NETWORK) {
  fout("\t\t\"%s\"", "network-variable");
Index: code/fred2/modifyvariabledlg.cpp
===================================================================
--- code/fred2/modifyvariabledlg.cpp (revision 11138)
+++ code/fred2/modifyvariabledlg.cpp (working copy)
@@ -61,6 +61,7 @@
  ON_CBN_EDITCHANGE(IDC_MODIFY_VARIABLE_NAME, OnEditchangeModifyVariableName)
  ON_EN_KILLFOCUS(IDC_MODIFY_DEFAULT_VALUE, OnKillfocusModifyDefaultValue)
  ON_CBN_DROPDOWN(IDC_MODIFY_VARIABLE_NAME, OnDropdownModifyVariableName)
+ ON_CBN_SELCHANGE(IDC_MODIFY_RETURN_TYPE, OnSelchangeModifyVariableReturnType)
  //}}AFX_MSG_MAP
 END_MESSAGE_MAP()
 
@@ -225,7 +226,7 @@
  }
 
  // check if another has been modified
- if (m_modified_type || m_modified_persistence || m_modified_name || m_modified_value) {
+ if (m_modified_type || m_modified_persistence || m_modified_name || m_modified_value || m_modified_return_type ) {
 
  // Don't send message if changing to self
  if (index != m_combo_last_modified_index) {
@@ -247,6 +248,7 @@
  m_type_campaign_persistent = ((Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_CAMPAIGN_PERSISTENT) != 0) ? true : false;
  m_type_player_persistent = ((Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_PLAYER_PERSISTENT) != 0) ? true : false;
  m_type_network_variable = ((Sexp_variables[sexp_variable_index].type & SEXP_VARIABLE_NETWORK) != 0) ? true : false;
+ m_return_type = Sexp_variables[sexp_variable_index].strict_type;
  set_variable_type();
 
  // Set new default value for selection
@@ -325,6 +327,16 @@
  edit->SetWindowText(Sexp_variables[m_translate_combo_to_sexp[last_modified]].text);
  }
 
+
+ cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_RETURN_TYPE);
+ cbox->ResetContent();
+
+ for (i = 0; i < NUM_OPERATOR_AGRUMENT_FORMATS; i++) {
+ cbox->AddString(Operator_Types[i].description);
+ }
+
+ cbox->SetCurSel(Sexp_variables[m_translate_combo_to_sexp[last_modified]].strict_type);
+
  // Set old variable name
  m_old_var_name = Sexp_variables[m_translate_combo_to_sexp[last_modified]].variable_name;
 
@@ -340,6 +352,7 @@
  m_modified_value = false;
  m_modified_type  = false;
  m_modified_persistence = false;
+ m_modified_return_type = false;
  m_deleted   = false;
  m_do_modify   = false;
 
@@ -364,6 +377,10 @@
  ((CButton *) GetDlgItem(IDC_TYPE_CAMPAIGN_PERSISTENT))->SetCheck(m_type_campaign_persistent);
  ((CButton *) GetDlgItem(IDC_TYPE_PLAYER_PERSISTENT))->SetCheck(m_type_player_persistent);
  ((CButton *) GetDlgItem(IDC_TYPE_NETWORK_VARIABLE))->SetCheck(m_type_network_variable);
+
+ CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_RETURN_TYPE);
+
+ cbox->SetCurSel(m_return_type);
 }
 
 void CModifyVariableDlg::OnOK()
@@ -389,7 +406,7 @@
  if (m_var_name_validated) {
 
  // maybe set m_do_modify -- this is needed. compare with OnCancel()
- if (m_modified_name || m_modified_persistence || m_modified_value || m_modified_type) {
+ if (m_modified_name || m_modified_persistence || m_modified_value || m_modified_type || m_modified_return_type ) {
  m_do_modify = true;
  }
  CDialog::OnOK();
@@ -545,3 +562,20 @@
 
  cbox->SetCurSel(m_combo_last_modified_index);
 }
+
+void CModifyVariableDlg::OnSelchangeModifyVariableReturnType()
+{
+ CComboBox *cbox = (CComboBox *) GetDlgItem(IDC_MODIFY_RETURN_TYPE);
+
+ // get index of current selection
+ int index = cbox->GetCurSel();
+
+ // check an item was actually selected, and not outside the box
+ if (index == CB_ERR) {
+ return;
+ }
+
+ m_return_type = index;
+ m_modified_return_type = true;
+
+}
\ No newline at end of file
Index: code/fred2/modifyvariabledlg.h
===================================================================
--- code/fred2/modifyvariabledlg.h (revision 11138)
+++ code/fred2/modifyvariabledlg.h (working copy)
@@ -45,9 +45,11 @@
  bool m_data_validated;
  bool m_var_name_validated;
  bool m_do_modify;
+ bool m_modified_return_type;
  int m_combo_last_modified_index;
  int m_translate_combo_to_sexp[MAX_SEXP_VARIABLES];
  int m_start_index; // index of sexp_variables which is right clicked to get this menu
+ int m_return_type;
  sexp_tree *m_p_sexp_tree;
  //}}AFX_DATA
 
@@ -76,8 +78,8 @@
  afx_msg void OnTypeNetworkVariable();
  afx_msg void OnSelchangeModifyVariableName();
  afx_msg void OnEditchangeModifyVariableName();
- virtual BOOL OnInitDialog();
- virtual void OnOK();
+ BOOL OnInitDialog();
+ void OnOK();
  afx_msg void OnKillfocusModifyDefaultValue();
  afx_msg void set_variable_type();
  afx_msg void validate_data(CString &temp_data, int set_focus);
@@ -84,6 +86,7 @@
  afx_msg void validate_var_name(int set_focus);
  afx_msg int get_sexp_var_index();
  afx_msg void OnDropdownModifyVariableName();
+ afx_msg void OnSelchangeModifyVariableReturnType();
  //}}AFX_MSG
  DECLARE_MESSAGE_MAP()
 };
Index: code/fred2/resource.h
===================================================================
--- code/fred2/resource.h (revision 11138)
+++ code/fred2/resource.h (working copy)
@@ -533,11 +533,14 @@
 #define IDC_SHIP_VARIABLES_COMBO        1188
 #define IDC_SUFFIX                      1188
 #define IDC_SOUND_ENVIRONMENT           1188
+#define IDC_RETURN_TYPE                 1188
 #define IDC_CREATED                     1189
 #define IDC_DEPARTURE_TARGET            1189
 #define IDC_SBITMAP                     1189
 #define IDC_ASCT1_VARIABLES_COMBO1      1189
 #define IDC_WEAPON_VARIABLES_COMBO      1189
+#define DC_RETURN_TYPE                  1189
+#define IDC_MODIFY_RETURN_TYPE          1189
 #define IDC_ASCT1_CLASS_COMBO2          1190
 #define IDC_BACKGROUND_NUM              1190
 #define IDC_WING_DISPLAY_FILTER         1191
Index: code/fred2/sexp_tree.cpp
===================================================================
--- code/fred2/sexp_tree.cpp (revision 11138)
+++ code/fred2/sexp_tree.cpp (working copy)
@@ -1063,7 +1063,7 @@
 
  // special case reset type for ambiguous
  if (type == OPF_AMBIGUOUS) {
- type = get_modify_variable_type(parent);
+ type = get_modify_variable_type(parent, true);
  }
 
  list = get_listing_opf(type, parent, Replace_count);
@@ -1591,8 +1591,10 @@
  type |= SEXP_VARIABLE_PLAYER_PERSISTENT;
  }
 
+ int strict_type = Operator_Types[dlg.m_return_type].type;
+
  // add variable
- sexp_add_variable(dlg.m_default_value, dlg.m_variable_name, type);
+ sexp_add_variable(dlg.m_default_value, dlg.m_variable_name, type, strict_type);
 
  // sort variable
  sexp_variable_sort();
@@ -1660,8 +1662,10 @@
  type |= SEXP_VARIABLE_PLAYER_PERSISTENT;
  }
 
+ int strict_type = Operator_Types[dlg.m_return_type].type;
+
  // update sexp_variable
- sexp_fred_modify_variable(dlg.m_default_value, dlg.m_cur_variable_name, sexp_var_index, type);
+ sexp_fred_modify_variable(dlg.m_default_value, dlg.m_cur_variable_name, sexp_var_index, type, strict_type);
 
  // modify sexp_tree
  modify_sexp_tree_variable(old_name, sexp_var_index);
@@ -1750,6 +1754,9 @@
  Assert(op >= 0);
 
  type = query_operator_argument_type(op, Replace_count); // check argument type at this position
+ if (type == OPF_AMBIGUOUS) {
+ type = get_modify_variable_type(tree_nodes[item_index].parent, true);
+ }
  list = get_listing_opf(type, tree_nodes[item_index].parent, Replace_count);
  Assert(list);
 
@@ -3185,7 +3192,7 @@
  var_name[length] = '\0';
 }
 
-int sexp_tree::get_modify_variable_type(int parent)
+int sexp_tree::get_modify_variable_type(int parent, bool allow_strict_typing)
 {
  int sexp_var_index = -1;
 
@@ -3218,7 +3225,12 @@
  } else if (Sexp_variables[sexp_var_index].type & SEXP_VARIABLE_NUMBER) {
  return OPF_NUMBER;
  } else if (Sexp_variables[sexp_var_index].type & SEXP_VARIABLE_STRING) {
- return OPF_AMBIGUOUS;
+ if ( (Sexp_variables[sexp_var_index].strict_type != 0) && allow_strict_typing ) {
+ return Sexp_variables[sexp_var_index].strict_type;
+ }
+ else {
+ return OPF_AMBIGUOUS;
+ }
  } else {
  Int3();
  return 0;
Index: code/fred2/sexp_tree.h
===================================================================
--- code/fred2/sexp_tree.h (revision 11138)
+++ code/fred2/sexp_tree.h (working copy)
@@ -180,7 +180,7 @@
  void modify_sexp_tree_variable(const char *old_name, int sexp_var_index);
  int get_item_index_to_var_index();
  int get_tree_name_to_sexp_variable_index(const char *tree_name);
- int get_modify_variable_type(int parent);
+ int get_modify_variable_type(int parent, bool allow_strict_typing = false);
  int get_variable_count(const char *var_name);
  int get_loadout_variable_count(int var_index);
 
Index: code/parse/sexp.cpp
===================================================================
--- code/parse/sexp.cpp (revision 11138)
+++ code/parse/sexp.cpp (working copy)
@@ -738,6 +738,98 @@
  { "set-training-context-speed", OP_SET_TRAINING_CONTEXT_SPEED, 2, 2, SEXP_ACTION_OPERATOR, },
 };
 
+operator_type Operator_Types[] = {
+ { "None", 0 },
+ { "Illegal", OPF_NONE },
+ { "NULL", OPF_NULL },
+ { "Boolean (True/False)", OPF_BOOL },
+ { "Number", OPF_NUMBER },
+ { "Ship Name", OPF_SHIP },
+ { "Wing Name", OPF_WING },
+ { "Subsystem Name", OPF_SUBSYSTEM },
+ { "A point in 3D space or Waypoint name", OPF_POINT },
+ { "IFF", OPF_IFF },
+ { "AI Goal", OPF_AI_GOAL },
+ { "Docking Point On Docker Ship", OPF_DOCKER_POINT },
+ { "Docking Point On Dockee Ship", OPF_DOCKEE_POINT },
+ { "Message Name", OPF_MESSAGE },
+ { "Sender Of A Message", OPF_WHO_FROM },
+ { "Message Priority", OPF_PRIORITY },
+ { "Waypoint Name", OPF_WAYPOINT_PATH },
+ { "Positive Number", OPF_POSITIVE },
+ { "Mission Name", OPF_MISSION_NAME },
+ { "Waypoint Or Ship Name", OPF_SHIP_POINT },
+ { "Goal Name", OPF_GOAL_NAME }, 
+ { "Ship Or Wing Name",   OPF_SHIP_WING }, 
+ { "Ship, Wing Or An Entire Team", OPF_SHIP_WING_WHOLETEAM },
+ { "Ship, Wing, Team Or Waypoint",   OPF_SHIP_WING_SHIPONTEAM_POINT },
+ { "Ship, Wing Or Waypoint", OPF_SHIP_WING_POINT },
+ { "Ship, Wing, Waypoint Or Nothing", OPF_SHIP_WING_POINT_OR_NONE },
+ { "Ship Type",  OPF_SHIP_TYPE },
+ { "Keypress",  OPF_KEYPRESS }, 
+ { "Event Name",  OPF_EVENT_NAME }, 
+ { "An Order A Player Can Give",  OPF_AI_ORDER }, 
+ { "Skill Levels",  OPF_SKILL_LEVEL }, 
+ { "Medal Name",  OPF_MEDAL_NAME }, 
+ { "Weapon Name",  OPF_WEAPON_NAME }, 
+ { "Ship Class Name",  OPF_SHIP_CLASS_NAME }, 
+ { "HUD Gauge Name",  OPF_HUD_GAUGE_NAME },
+ { "Secondary Bomb Name",  OPF_HUGE_WEAPON }, 
+ { "Ship Name Other Than The Player",  OPF_SHIP_NOT_PLAYER }, 
+ { "Jump Node Name",  OPF_JUMP_NODE_NAME }, 
+ { "Variable Name",  OPF_VARIABLE_NAME }, 
+ { "Any String (Used With Variables)",  OPF_AMBIGUOUS }, 
+ { "AWACS Subsystem",  OPF_AWACS_SUBSYSTEM }, 
+ { "Cargo Type", OPF_CARGO }, 
+ { "AI Class", OPF_AI_CLASS }, 
+ { "Support Ship Class", OPF_SUPPORT_SHIP_CLASS },
+ { "Ship Arrival Location", OPF_ARRIVAL_LOCATION },
+ { "Ship Arrival Anchor", OPF_ARRIVAL_ANCHOR_ALL }, 
+ { "Ship Departure Location", OPF_DEPARTURE_LOCATION },
+ { "Ship With Fighter Bay", OPF_SHIP_WITH_BAY },
+ { "Soundtrack Name", OPF_SOUNDTRACK_NAME }, 
+ { "Species.tbl Entry", OPF_INTEL_NAME }, 
+ { "Any String", OPF_STRING },
+ { "Rotating Subsystem", OPF_ROTATING_SUBSYSTEM }, 
+ { "Nav Point Name", OPF_NAV_POINT }, 
+ { "SSM Class", OPF_SSM_CLASS },
+ { "Any String (Used With When Argument)",   OPF_FLEXIBLE_ARGUMENT }, 
+ { "Anything At All", OPF_ANYTHING }, 
+ { "Skybox Name", OPF_SKYBOX_MODEL_NAME },
+ { "Ship Name (Or None)", OPF_SHIP_OR_NONE }, 
+ { "Background Bitmap Name", OPF_BACKGROUND_BITMAP },
+ { "Sun Bitmap Name", OPF_SUN_BITMAP }, 
+ { "Nebula Storm Name", OPF_NEBULA_STORM_TYPE }, 
+ { "Nebula Poof Name", OPF_NEBULA_POOF }, 
+ { "Turret Target Type Name", OPF_TURRET_TARGET_ORDER },
+ { "Subsystem Name (Or None)", OPF_SUBSYSTEM_OR_NONE }, 
+ { "Persona Name", OPF_PERSONA },
+ { "Subsystem Name (Including Generics)", OPF_SUBSYS_OR_GENERIC }, 
+ { "Any Ship Which Can Recieve Orders", OPF_ORDER_RECIPIENT }, 
+ { "Generic Subsystem Type", OPF_SUBSYSTEM_TYPE },
+ { "Post Processing Effect Type", OPF_POST_EFFECT }, 
+ { "Target Priority", OPF_TARGET_PRIORITIES }, 
+ { "Armor Type (Or None)", OPF_ARMOR_TYPE }, 
+ { "Font Name", OPF_FONT }, 
+ { "HUD Element", OPF_HUD_ELEMENT }, 
+ { "Sound EFX Preset", OPF_SOUND_ENVIRONMENT }, 
+ { "Sound Environment Option", OPF_SOUND_ENVIRONMENT_OPTION }, 
+ { "Explosion Option", OPF_EXPLOSION_OPTION }, 
+ { "Audio Volume Option", OPF_AUDIO_VOLUME_OPTION }, 
+ { "Weapon Bank Number", OPF_WEAPON_BANK_NUMBER }, 
+ { "Message Name (Or String)", OPF_MESSAGE_OR_STRING }, 
+ { "HUD Gauge Name", OPF_HUD_GAUGE }, 
+ { "Damage Type", OPF_DAMAGE_TYPE }, 
+ { "Post-processing.tbl Ship Effect", OPF_SHIP_EFFECT }, 
+ { "Animation Type", OPF_ANIMATION_TYPE }, 
+ { "Mission Mood Name", OPF_MISSION_MOOD }, 
+ { "Name Of A Ship Flag", OPF_SHIP_FLAG }, 
+ { "Team Colour Settings", OPF_TEAM_COLOR }, 
+ { "Nebula Background Patterns", OPF_NEBULA_PATTERN }, 
+ { "Skybox Flags", OPF_SKYBOX_FLAGS }, 
+ { "A Game Sound", OPF_GAME_SND },
+};
+
 sexp_ai_goal_link Sexp_ai_goal_links[] = {
  { AI_GOAL_CHASE, OP_AI_CHASE },
  { AI_GOAL_CHASE_WING, OP_AI_CHASE_WING },
@@ -1837,6 +1929,28 @@
  continue;
  }
 
+ // Check for strict typing
+ if (type == OPF_AMBIGUOUS) {
+ if ((Operators[op].value == OP_MODIFY_VARIABLE) || (Operators[op].value == OP_SET_VARIABLE_BY_INDEX)) {
+ // Get the variable
+ if (Operators[op].value == OP_MODIFY_VARIABLE) {
+ int variable_node = CDR(find_parent_operator(node));
+ var_index = get_index_sexp_variable_from_node(variable_node);
+ }
+ else if (Operators[op].value == OP_SET_VARIABLE_BY_INDEX) {
+ int variable_node = CDR(find_parent_operator(node));
+ var_index = atoi(CTEXT(variable_node));
+ }
+
+ Assertion (var_index != -1, "Invalid variable index found in mission");
+ if (var_index != -1) {
+ if (Sexp_variables[var_index].strict_type) {
+ type = Sexp_variables[var_index].strict_type;
+ }
+ }
+ }
+ }
+
  switch (type) {
  case OPF_NAV_POINT:
  if (type2 != SEXP_ATOM_STRING){
@@ -3549,8 +3663,11 @@
  char str_type[TOKEN_LENGTH];
  char persistent[TOKEN_LENGTH];
  char network[TOKEN_LENGTH];
+ char strict_type_string[TOKEN_LENGTH];
  int index;
  int type;
+
+ int strict_type = 0;
 
  count = 0;
  required_string("$Variables:");
@@ -3600,6 +3717,16 @@
  }
 
  // possibly get network-variable
+ if (check_for_string("\"strict-type\"")) {
+
+ get_string(strict_type_string);
+ ignore_white_space();
+ // eat it
+ stuff_int(&strict_type);
+ ignore_white_space();
+ }
+
+ // possibly get network-variable
  if (check_for_string("\"network-variable\"")) {
  // eat it
  get_string(network);
@@ -3645,7 +3772,7 @@
  }
  else {
  count++;
- sexp_add_variable(default_value, var_name, type, index);
+ sexp_add_variable(default_value, var_name, type, strict_type, index);
  }
  }
 
@@ -28300,7 +28427,7 @@
  *
  * This should be called from within mission parse.
  */
-int sexp_add_variable(const char *text, const char *var_name, int type, int index)
+int sexp_add_variable(const char *text, const char *var_name, int type, int strict_type, int index)
 {
  // if index == -1, find next open slot
  if (index == -1) {
@@ -28319,6 +28446,7 @@
  strcpy_s(Sexp_variables[index].variable_name, var_name);
  Sexp_variables[index].type &= ~SEXP_VARIABLE_NOT_USED;
  Sexp_variables[index].type = (type | SEXP_VARIABLE_SET);
+ Sexp_variables[index].strict_type = strict_type;
  }
 
  return index;
@@ -28660,7 +28788,7 @@
 }
 
 // Different type needed for Fred (1) allow modification of type (2) no callback required
-void sexp_fred_modify_variable(const char *text, const char *var_name, int index, int type)
+void sexp_fred_modify_variable(const char *text, const char *var_name, int index, int type, int strict_type)
 {
  Assert(index >= 0 && index < MAX_SEXP_VARIABLES);
  Assert(Sexp_variables[index].type & SEXP_VARIABLE_SET);
@@ -28669,6 +28797,11 @@
  strcpy_s(Sexp_variables[index].text, text);
  strcpy_s(Sexp_variables[index].variable_name, var_name);
  Sexp_variables[index].type = (SEXP_VARIABLE_SET | SEXP_VARIABLE_MODIFIED | type);
+
+ // maybe change the strict type
+ if (strict_type != -1) {
+ Sexp_variables[index].strict_type = strict_type;
+ }
 }
 
 /**
Index: code/parse/sexp.h
===================================================================
--- code/parse/sexp.h (revision 11138)
+++ code/parse/sexp.h (working copy)
@@ -114,6 +114,8 @@
 #define OPF_SKYBOX_FLAGS 87 // niffiwan - valid skybox flags
 #define OPF_GAME_SND 88 // m!m - A game sound
 
+#define NUM_OPERATOR_AGRUMENT_FORMATS 88
+
 // Operand return types
 #define OPR_NUMBER 1 // returns number
 #define OPR_BOOL 2 // returns true/false value
@@ -1008,6 +1010,11 @@
 
 #define SEXP_TRIGGER_OPERATOR ( SEXP_ARITHMETIC_OPERATOR | SEXP_BOOLEAN_OPERATOR | SEXP_INTEGER_OPERATOR )
 
+typedef struct operator_type {
+ char description[256];
+ int type;
+} operator_type;
+
 typedef struct sexp_oper {
  char *text;
  int value;
@@ -1035,6 +1042,7 @@
  int type;
  char text[TOKEN_LENGTH];
  char variable_name[TOKEN_LENGTH];
+ int strict_type;
 } sexp_variable;
 
 
@@ -1074,6 +1082,7 @@
 extern sexp_variable Block_variables[MAX_SEXP_VARIABLES];
 
 extern sexp_oper Operators[];
+extern operator_type Operator_Types[];
 extern int Num_operators;
 extern int Locked_sexp_true, Locked_sexp_false;
 extern int Directive_count;
@@ -1165,8 +1174,8 @@
 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);
+void sexp_fred_modify_variable(const char *text, const char *var_name, int index, int type, int strict_type = -1);
+int sexp_add_variable(const char *text, const char *var_name, int type, int strict_type = 0, int index = -1);
 bool generate_special_explosion_block_variables();
 int num_block_variables();
 bool has_special_explosion_block_index(ship *shipp, int *index);





[attachment kidnapped by pirates]
« Last Edit: October 18, 2014, 05:16:07 am by karajorma »
Karajorma's Freespace FAQ. It's almost like asking me yourself.

[ Diaspora ] - [ Seeds Of Rebellion ] - [ Mind Games ]