Subject: Pass desired script type as the subtype for a new script.

From: Rider Linden <[email-masked]>
Date: Tue, 3 Mar 2026 11:11:02 -0800

---
 indra/llinventory/llinventory.h            |  8 ++++----
 indra/llinventory/llinventorydefines.h     |  5 +----
 indra/llinventory/llinventorytype.h        |  7 +++++++
 indra/newview/llpanelcontents.cpp          |  8 ++++----
 indra/newview/lltooldraganddrop.cpp        |  2 +-
 indra/newview/llviewerinventory.cpp        |  2 +-
 indra/newview/llviewerinventory.h          |  2 --
 indra/newview/llviewerobject.cpp           | 11 ++++++-----
 indra/newview/llviewerobject.h             |  6 +++---
 scripts/messages/message_template.msg      |  1 -
 scripts/messages/message_template.msg.sha1 |  2 +-
 11 files changed, 28 insertions(+), 26 deletions(-)

(limited to 'scripts/messages/message_template.msg')

diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 181c46226c..58dea83617 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -24,11 +24,11 @@
  * $/LicenseInfo$
  */
 
-#ifndef LL_LLINVENTORY_H
-#define LL_LLINVENTORY_H
+#pragma once
 
 #include "llfoldertype.h"
 #include "llinventorytype.h"
+#include "llinventorydefines.h"
 #include "llpermissions.h"
 #include "llrefcount.h"
 #include "llsaleinfo.h"
@@ -166,6 +166,7 @@ public:
     virtual const std::string& getActualDescription() const; // Does not follow links
     virtual const LLSaleInfo& getSaleInfo() const;
     virtual LLInventoryType::EType getInventoryType() const;
+    virtual U8 getInventorySubType() const { return getFlags() & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK; }
     virtual U32 getFlags() const;
     virtual time_t getCreationDate() const;
     virtual U32 getCRC32() const; // really more of a checksum.
@@ -182,6 +183,7 @@ public:
     void setSaleInfo(const LLSaleInfo& sale_info);
     void setPermissions(const LLPermissions& perm);
     void setInventoryType(LLInventoryType::EType inv_type);
+    void setInventorySubType(U8 sub_type)  { setFlags((getFlags() & ~LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK) | (sub_type & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK)); }
     void setFlags(U32 flags);
     void setCreator(const LLUUID& creator); // only used for calling cards
 
@@ -294,5 +296,3 @@ protected:
 LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item);
 LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat);
 LLPointer<LLInventoryCategory> ll_create_category_from_sd(const LLSD& sd_cat);
-
-#endif // LL_LLINVENTORY_H
diff --git a/indra/llinventory/llinventorydefines.h b/indra/llinventory/llinventorydefines.h
index 8e7bd87ac4..9088d172d9 100644
--- a/indra/llinventory/llinventorydefines.h
+++ b/indra/llinventory/llinventorydefines.h
@@ -24,8 +24,7 @@
  * $/LicenseInfo$
  */
 
-#ifndef LL_LLINVENTORYDEFINES_H
-#define LL_LLINVENTORYDEFINES_H
+#pragma once
 
 // Consts for "key" field in the task inventory update message
 extern const U8 TASK_INVENTORY_ITEM_KEY;
@@ -97,5 +96,3 @@ public:
             // on a pre-existing inventory item (DEV-28098 and DEV-30997)
     };
 };
-
-#endif // LL_LLINVENTORYDEFINES_H
diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h
index c90f8aa107..0627b8df3c 100644
--- a/indra/llinventory/llinventorytype.h
+++ b/indra/llinventory/llinventorytype.h
@@ -150,6 +150,13 @@ private:
     ~LLInventoryType( void );
 };
 
+// Subtypes for scripts, (inventory type IT_LSL).
+enum ScriptSubtype_t
+{
+    SST_LSL = 0,
+    SST_LUA = 1
+};
+
 // helper function that returns true if inventory type and asset type
 // are potentially compatible. For example, an attachment must be an
 // object, but a wearable can be a bodypart or clothing asset.
diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp
index 2f060ac2e6..2e4dc88217 100644
--- a/indra/newview/llpanelcontents.cpp
+++ b/indra/newview/llpanelcontents.cpp
@@ -241,7 +241,7 @@ void LLPanelContents::onClickNewScript(void *userdata)
         std::string desc;
         LLViewerAssetType::generateDescriptionFor(LLAssetType::AT_LSL_TEXT, desc);
 
-        U8 script_language = LANG_ID_LSL;
+        U8 script_language = SST_LSL;
         LLUUID template_id;
 
         LLViewerRegion* region = object->getRegion();
@@ -251,7 +251,7 @@ void LLPanelContents::onClickNewScript(void *userdata)
             region->getSimulatorFeatures(simulatorFeatures);
             if (simulatorFeatures["LuaScriptsEnabled"].asBoolean())
             {
-                script_language = LANG_ID_LUA;
+                script_language = SST_LUA;
             }
         }
         // *TODO* Get a template ID and script_language based on user preferences.  Template ID is the inventory item UUID of a script
@@ -268,9 +268,9 @@ void LLPanelContents::onClickNewScript(void *userdata)
                 "New Script",
                 desc,
                 LLSaleInfo::DEFAULT,
-                LLInventoryItemFlags::II_FLAGS_NONE,
+                LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK & script_language,
                 time_corrected());
-        object->saveScript(new_item, true, true, script_language, template_id);
+        object->saveScript(new_item, true, true, template_id);
 
         std::string name = new_item->getName();
 
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index bca4743c19..eb8ace339e 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -1828,7 +1828,7 @@ void LLToolDragAndDrop::dropScript(LLViewerObject* hit_obj,
                 }
             }
         }
-        hit_obj->saveScript(new_script, active, true, LANG_ID_LSL, LLUUID::null);
+        hit_obj->saveScript(new_script, active, true, LLUUID::null);
         if (gFloaterTools)
         {
             gFloaterTools->dirty();
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index f5fd234da7..53d87e2869 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1739,7 +1739,7 @@ void create_new_item(const std::string& name,
                 region->getSimulatorFeatures(simulatorFeatures);
                 if (simulatorFeatures["LuaScriptsEnabled"].asBoolean())
                 {
-                    subtype = LANG_ID_LUA;
+                    subtype = SST_LUA;
                 }
             }
             break;
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 4147efe3a9..23f85663e8 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -43,8 +43,6 @@ class LLInventoryCallback;
 class LLAvatarName;
 
 constexpr U8 NO_INV_SUBTYPE{ 0 };
-constexpr U8 LANG_ID_LSL = 0;
-constexpr U8 LANG_ID_LUA = 1;
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLViewerInventoryItem
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index ca5281b3c7..d280f74fc7 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -2767,9 +2767,10 @@ void LLViewerObject::doUpdateInventory(
 // If a template_id is provided, the new script will be a copy of that item.
 //
 // *IMPORTANT* If template_id is provided, it must be the ITEM ID of a
-// copy/mod-able script in the user's inventory.
+// copy/mod-able script in the user's inventory. The simulator will verify
+// permissions.
 void LLViewerObject::saveScript(const LLViewerInventoryItem* item,
-    bool active, bool is_new, U8 script_language, const LLUUID& template_id)
+    bool active, bool is_new, const LLUUID& template_id)
 {
     /*
      * XXXPAM Investigate not making this copy.  Seems unecessary, but I'm unsure about the
@@ -2799,11 +2800,11 @@ void LLViewerObject::saveScript(const LLViewerInventoryItem* item,
     msg->nextBlockFast(_PREHASH_InventoryBlock);
     task_item->packMessage(msg);
 
-    // This is a completely new script (no asset id)
-    if (task_item->getAssetUUID().isNull())
+    // This is a completely new script (no asset id) and we've provided a template.
+    // Note that the script subtype on the template will override any subtype on the item.
+    if (task_item->getAssetUUID().isNull() && template_id.notNull())
     {
         msg->nextBlock("NewScriptInfo");
-        msg->addU8("Type", script_language);
         msg->addUUID("TemplateID", template_id);
     }
 
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 3225349506..db1a412c78 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -549,9 +549,9 @@ public:
     // in the new one. This method should be called with the asset id
     // of the new and old script AFTER the bytecode has been saved.
     // The simulator treats the script as new when item->getAssetUUID().isNull() is true; in that case
-    // template_id will be used (if non-null) to copy an existing script asset, otherwise script_language
-    // is used to request an appropriate generic starting script.
-    void saveScript(const LLViewerInventoryItem* item, bool active, bool is_new, U8 script_language, const LLUUID& template_id);
+    // template_id will be used (if non-null) to copy an existing script asset, otherwise the
+    // script subtype in the item will be used to select the correct template.
+    void saveScript(const LLViewerInventoryItem* item, bool active, bool is_new, const LLUUID& template_id);
 
     // move an inventory item out of the task and into agent
     // inventory. This operation is based on messaging. No permissions
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index d3d60ea584..ad3ddd5a94 100644
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -6820,7 +6820,6 @@ version 2.0
     }
     {
         NewScriptInfo Variable
-        {   Type            U8          }
         {   TemplateID      LLUUID      }
     }
 }
diff --git a/scripts/messages/message_template.msg.sha1 b/scripts/messages/message_template.msg.sha1
index 745eec1971..96f24ca1ba 100644
--- a/scripts/messages/message_template.msg.sha1
+++ b/scripts/messages/message_template.msg.sha1
@@ -1 +1 @@
-2244732a49f7b3fa00694b9870d5d6d3dc0c5cb2
\ No newline at end of file
+3edf45c784a5440d7dd24c59309faf52d1d01f47
\ No newline at end of file
-- 
cgit v1.3