Placeables just not scripting

This is the 2nd thread I’m starting with similar gripes, script should work, all resrefs, tags, spell needed are correctly used, double checked - still nothing. This script was generated with Lilac Soul. Tried 2 different spells for sanity check. Nothing. It’s going to make me throw in the towel on mod building and go do something else. I suppose I could resort to blueprinting everything and try Scriptease. It worked pretty well when I scripted Phantasie 10 years ago. Anyway, here was the latest:

/* BLACKSMITH SCRIPT, format 1.0

  • Smith type: 0
  • Script generated by LS Script Generator, v.TK.0
  • For download info, please visit:
  • http://nwvault.ign.com/View.php?view=Other.Detail&id=1502
    */
    // Put this OnSpellCastAt for a placeable.
    // Note that this will only create one item, even if there are enough ingredients for multiple recipes.

#include “x0_inc_skills”

// The number of combinations this script accepts for item creation.
const int NUM_RECIPES = 1;

// Initializes the local variables that define what can be created and how to
// create them.
void SetRecipeLocals(object oVarHolder);
void SetRecipeLocals(object oVarHolder)
{
// Recipe for creating Potion of Mage Armor.
SetLocalString(oVarHolder, “LS_SMITH_0_ResRef”, “potionofmagearmo”);
SetLocalInt (oVarHolder, “LS_SMITH_0_gold”, 0);
SetLocalInt (oVarHolder, “LS_SMITH_0_ingredient_count”, 2);
SetLocalString(oVarHolder, “LS_SMITH_0_ingredient0”, “x2_it_cfm_pbottl”); // Magic Potion Bottle
SetLocalString(oVarHolder, “LS_SMITH_0_ingredient1”, “NW_IT_MSMLMISC11”); // Quartz Crystal
SetLocalInt (oVarHolder, “LS_SMITH_0_quantity0”, 1);
SetLocalInt (oVarHolder, “LS_SMITH_0_quantity1”, 2);
SetLocalInt (oVarHolder, “LS_SMITH_0_spell”, SPELL_NEGATIVE_ENERGY_RAY);
SetLocalInt (oVarHolder, “LS_SMITH_0_vfx”, VFX_FNF_SMOKE_PUFF);
}

// -----------------------------------------------------------------------------

void main()
{
// Basic configuration:
object oItemHolder = OBJECT_SELF;
object oVarHolder = OBJECT_SELF;
int nAvailableGold = GetGold(oItemHolder);

// Make sure the recipes are initialized.
if ( !GetLocalInt(oVarHolder, "LS_SMITH_variables_set") )
{
    SetRecipeLocals(oVarHolder);
    SetLocalInt(oVarHolder, "LS_SMITH_variables_set", TRUE);
}


// Variables set inside the following loop.
int nNumIngredients, nIngredient, nGold;
string sVarPrefix;

// Find a matching recipe.
int bIsMatch = FALSE;
int nRecipe = 0;
while ( nRecipe++ < NUM_RECIPES  &&  !bIsMatch )
{
    sVarPrefix = "LS_SMITH_" + IntToString(nRecipe) + "_";

    // Gold requirement.
    nGold = GetLocalInt(oVarHolder, sVarPrefix + "gold");
    bIsMatch = nAvailableGold >= nGold;

    // Spell requirement.
    if ( bIsMatch )
        bIsMatch =  GetLastSpell() == GetLocalInt(oVarHolder, sVarPrefix + "spell");

    // Item requirements.
    nNumIngredients = GetLocalInt(oVarHolder, sVarPrefix + "ingredient_count");
    nIngredient = 0;
    while ( bIsMatch  &&  nIngredient++ < nNumIngredients )
        // OK to continue if we have enough of the specified item.
        // (This function was written for trap components, but it works for this, too.)
        bIsMatch = skillCTRAPGetHasComponent(
                        GetLocalString(oVarHolder, sVarPrefix + "ingredient" + IntToString(nIngredient)),
                        oItemHolder,
                        GetLocalInt(oVarHolder, sVarPrefix + "quantity" + IntToString(nIngredient)));


    // Done checking. Can we go ahead and create?
    if ( bIsMatch )
    {
        // Gold cost:
        if ( nGold > 0 )
            DestroyNumItems(oItemHolder, "NW_IT_GOLD001", nGold);

        // Remove the ingredients.
        for ( nIngredient = 1; nIngredient <= nNumIngredients; nIngredient++ )
            DestroyNumItems(oItemHolder,
                            GetLocalString(oVarHolder, sVarPrefix + "ingredient" + IntToString(nIngredient)),
                            GetLocalInt(oVarHolder, sVarPrefix + "quantity" + IntToString(nIngredient)));

        // Now create the item.
        CreateItemOnObject(GetLocalString(oVarHolder, sVarPrefix + "ResRef"), oItemHolder);
        // Add a spiffy visual effect?
        int nVFX = GetLocalInt(oVarHolder, sVarPrefix + "vfx");
        if ( nVFX != VFX_NONE )
            ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(nVFX), oItemHolder);
    }
}//while ( nRecipe )

}

Try to narrow down the problem by adding SendMessageToPC statements to diagnose what’s happening.

For example, does the script execute at all when a spell is cast at the placeable?

Does GetGold return a value for placeables?

…and so on. Then you can ask a much simpler question, identifying the line that doesn’t work as you expected.

How, exactly, do you want this crafting system you’re trying to set up to work? If you’re running into trouble with the script generators, it might go over easier if we write the code manually.

In the other thread you asked for a screenshot. Here’s an all encompassing collage showing all names are correct and in the correct place.

The Inventory contents is the inventory of a nearby alchemist desk showing where the PC got the components and that they match the item properties screen shots.

Complete script:

/* BLACKSMITH SCRIPT, format 1.0

  • Smith type: 0
  • Script generated by LS Script Generator, v.TK.0
  • For download info, please visit:
  • Neverwinter Nights Guide - IGN
    */
    // Put this OnSpellCastAt for a placeable.
    // Note that this will only create one item, even if there are enough ingredients for multiple recipes.

#include “x0_inc_skills”

// The number of combinations this script accepts for item creation.
const int NUM_RECIPES = 1;

// Initializes the local variables that define what can be created and how to
// create them.
void SetRecipeLocals(object oVarHolder);
void SetRecipeLocals(object oVarHolder)
{
// Recipe for creating Potion of Mage Armor.
SetLocalString(oVarHolder, “LS_SMITH_0_ResRef”, “potionofmagearmo”);
SetLocalInt (oVarHolder, “LS_SMITH_0_gold”, 0);
SetLocalInt (oVarHolder, “LS_SMITH_0_ingredient_count”, 2);
SetLocalString(oVarHolder, “LS_SMITH_0_ingredient0”, “x2_it_cfm_pbottl”); // Magic Potion Bottle
SetLocalString(oVarHolder, “LS_SMITH_0_ingredient1”, “NW_IT_MSMLMISC11”); // Quartz Crystal
SetLocalInt (oVarHolder, “LS_SMITH_0_quantity0”, 1);
SetLocalInt (oVarHolder, “LS_SMITH_0_quantity1”, 2);
SetLocalInt (oVarHolder, “LS_SMITH_0_spell”, SPELL_MAGE_ARMOR);
SetLocalInt (oVarHolder, “LS_SMITH_0_vfx”, VFX_FNF_SMOKE_PUFF);
}

// -----------------------------------------------------------------------------

void main()
{
// Basic configuration:
object oItemHolder = OBJECT_SELF;
object oVarHolder = OBJECT_SELF;
int nAvailableGold = GetGold(oItemHolder);

// Make sure the recipes are initialized.
if ( !GetLocalInt(oVarHolder, "LS_SMITH_variables_set") )
{
    SetRecipeLocals(oVarHolder);
    SetLocalInt(oVarHolder, "LS_SMITH_variables_set", TRUE);
}


// Variables set inside the following loop.
int nNumIngredients, nIngredient, nGold;
string sVarPrefix;

// Find a matching recipe.
int bIsMatch = FALSE;
int nRecipe = 0;
while ( nRecipe++ < NUM_RECIPES  &&  !bIsMatch )
{
    sVarPrefix = "LS_SMITH_" + IntToString(nRecipe) + "_";

    // Gold requirement.
    nGold = GetLocalInt(oVarHolder, sVarPrefix + "gold");
    bIsMatch = nAvailableGold >= nGold;

    // Spell requirement.
    if ( bIsMatch )
        bIsMatch =  GetLastSpell() == GetLocalInt(oVarHolder, sVarPrefix + "spell");

    // Item requirements.
    nNumIngredients = GetLocalInt(oVarHolder, sVarPrefix + "ingredient_count");
    nIngredient = 0;
    while ( bIsMatch  &&  nIngredient++ < nNumIngredients )
        // OK to continue if we have enough of the specified item.
        // (This function was written for trap components, but it works for this, too.)
        bIsMatch = skillCTRAPGetHasComponent(
                        GetLocalString(oVarHolder, sVarPrefix + "ingredient" + IntToString(nIngredient)),
                        oItemHolder,
                        GetLocalInt(oVarHolder, sVarPrefix + "quantity" + IntToString(nIngredient)));


    // Done checking. Can we go ahead and create?
    if ( bIsMatch )
    {
        // Gold cost:
        if ( nGold > 0 )
            DestroyNumItems(oItemHolder, "NW_IT_GOLD001", nGold);

        // Remove the ingredients.
        for ( nIngredient = 1; nIngredient <= nNumIngredients; nIngredient++ )
            DestroyNumItems(oItemHolder,
                            GetLocalString(oVarHolder, sVarPrefix + "ingredient" + IntToString(nIngredient)),
                            GetLocalInt(oVarHolder, sVarPrefix + "quantity" + IntToString(nIngredient)));

        // Now create the item.
        CreateItemOnObject(GetLocalString(oVarHolder, sVarPrefix + "ResRef"), oItemHolder);
        // Add a spiffy visual effect?
        int nVFX = GetLocalInt(oVarHolder, sVarPrefix + "vfx");
        if ( nVFX != VFX_NONE )
            ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(nVFX), oItemHolder);
    }
}//while ( nRecipe )

}

I’m not a coder so I’m not sure how to do that (don’t know how to code exact syntax). I rely on Lilac Soul’s scripter as noted below. The script clearly doesn’t fire though, when spell is cast, required and provided components are not consumed, resultant item is not produced, visual effect not produced.

Ah, it appears that I’m not the only one with placeable issues with Lilac Soul scripter. “Roaringthing” has had the exact same issue: https://neverwintervault.org/project/nwn1/other/tool/ls-tk-script-generator#comment-45725

Try it like this. I’ve set up a test environment and combed through the code until it ?worked?. Fingers crossed, no guarantees.

/* BLACKSMITH SCRIPT, format 1.0

Smith type: 0
Script generated by LS Script Generator, v.TK.0
For download info, please visit:
http://nwvault.ign.com/View.php?view=Other.Detail&id=1502
*/
// Put this OnSpellCastAt for a placeable.
// Note that this will only create one item, even if there are enough ingredients for multiple recipes.
#include "x0_inc_skills"

// The number of combinations this script accepts for item creation.
const int NUM_RECIPES = 1;

// Initializes the local variables that define what can be created and how to
// create them.
void SetRecipeLocals(object oVarHolder);
void SetRecipeLocals(object oVarHolder)
{
    // Recipe for creating Potion of Mage Armor.
    SetLocalString(oVarHolder, "LS_SMITH_1_ResRef", "potionofmagearmo");
    SetLocalInt (oVarHolder,   "LS_SMITH_1_gold", 0);
    SetLocalInt (oVarHolder,   "LS_SMITH_1_ingredient_count", 2);
    SetLocalString(oVarHolder, "LS_SMITH_1_ingredient1", "x2_it_cfm_pbottl"); // Magic Potion Bottle
    SetLocalString(oVarHolder, "LS_SMITH_1_ingredient2", "NW_IT_MSMLMISC11"); // Quartz Crystal
    SetLocalInt (oVarHolder,   "LS_SMITH_1_quantity1", 1);
    SetLocalInt (oVarHolder,   "LS_SMITH_1_quantity2", 2);
    SetLocalInt (oVarHolder,   "LS_SMITH_1_spell", SPELL_NEGATIVE_ENERGY_RAY);
    SetLocalInt (oVarHolder,   "LS_SMITH_1_vfx", VFX_FNF_SMOKE_PUFF);
}

// -----------------------------------------------------------------------------

void main()
{
    object oPC = GetLastSpellCaster();
    string sTest;
    int nCount;
    SendMessageToPC(oPC, "Caster recognized.");

    // Basic configuration:
    object oItemHolder = OBJECT_SELF;
    object oVarHolder  = OBJECT_SELF;
    int nAvailableGold = GetGold(oItemHolder);

    // Make sure the recipes are initialized.
    if ( !GetLocalInt(oVarHolder, "LS_SMITH_variables_set") )
    {
        SetRecipeLocals(oVarHolder);
        SetLocalInt(oVarHolder, "LS_SMITH_variables_set", TRUE);

        SendMessageToPC(oPC, "Variables initialized.");
    }

    // Variables set inside the following loop.
    int nNumIngredients, nIngredient, nGold;
    string sVarPrefix;

    // Find a matching recipe.
    int bIsMatch = FALSE;
    int nRecipe = 0;
    while ( nRecipe++ < NUM_RECIPES  &&  !bIsMatch )
    {
        sVarPrefix = "LS_SMITH_" + IntToString(nRecipe) + "_";
        SendMessageToPC(oPC, "Checking for recipe "+sVarPrefix);

        // Gold requirement.
        nGold = GetLocalInt(oVarHolder, sVarPrefix + "gold");
        bIsMatch = nAvailableGold >= nGold;
        if (bIsMatch)
            SendMessageToPC(oPC, "Gold requirement is a match. "+IntToString(nGold)+"g required.");
        else
            SendMessageToPC(oPC, "ERROR - Gold requirement is NOT a match.");

        // Spell requirement.
        bIsMatch = (GetLastSpell() == GetLocalInt(oVarHolder, sVarPrefix + "spell"));
        if (bIsMatch)
            SendMessageToPC(oPC, "Spell requirement is a match.");
        else
            SendMessageToPC(oPC, "ERROR - Spell requirement is NOT a match.");

    // Item requirements.
    nNumIngredients = GetLocalInt(oVarHolder, sVarPrefix + "ingredient_count");
    SendMessageToPC(oPC, "Expecting "+IntToString(nNumIngredients)+" ingredients.");
    nIngredient = 0;
    while ( bIsMatch  &&  nIngredient++ < nNumIngredients )
        {
        sTest = GetLocalString(oVarHolder, sVarPrefix + "ingredient" + IntToString(nIngredient));
        SendMessageToPC(oPC, "Checking for ingredient "+IntToString(nIngredient)+": "+sTest+".");
        // OK to continue if we have enough of the specified item.
        // (This function was written for trap components, but it works for this, too.)
        bIsMatch = skillCTRAPGetHasComponent(
                        sTest,
                        oItemHolder,
                        nCount = GetLocalInt(oVarHolder, sVarPrefix + "quantity" + IntToString(nIngredient)));

        if (!bIsMatch)
            SendMessageToPC(oPC, "Failed to find "+IntToString(nCount)+"x ingredient "+sTest+".");
        else
            SendMessageToPC(oPC, "Found "+IntToString(nCount)+"x ingredient "+sTest+".");
        }


    // Done checking. Can we go ahead and create?
    if ( bIsMatch )
    {
        SendMessageToPC(oPC, "Trying to create item "+GetLocalString(oVarHolder, sVarPrefix + "ResRef")+".");

        // Gold cost:
        if ( nGold > 0 )
            DestroyNumItems(oItemHolder, "NW_IT_GOLD001", nGold);

        // Remove the ingredients.
        for ( nIngredient = 1; nIngredient <= nNumIngredients; nIngredient++ )
            DestroyNumItems(oItemHolder,
                            GetLocalString(oVarHolder, sVarPrefix + "ingredient" + IntToString(nIngredient)),
                            GetLocalInt(oVarHolder, sVarPrefix + "quantity" + IntToString(nIngredient)));

        // Now create the item.
        CreateItemOnObject(GetLocalString(oVarHolder, sVarPrefix + "ResRef"), oItemHolder);
        // Add a spiffy visual effect?
        int nVFX = GetLocalInt(oVarHolder, sVarPrefix + "vfx");
        if ( nVFX != VFX_NONE )
            ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(nVFX), oItemHolder);
    }
    }//while ( nRecipe )
}

No guarantees, though. x_x Did not dig into this thoroughly, just added debug messages and poked the parts that weren’t behaving.

Left the debug messages in for educational value. You can comment them out by adding //s in front of the lines.

Like this:

   // if (Cake == Tasty)
   //     SendMessageToPC(oPC, "Bleh bleh bleh");

Yep, 's exactly what it means. The currently-existing recipe is specifically set up for the Negative Energy Ray spell. Only one that’ll qualify, as things are. :slight_smile:

It failed due to spell requirement not a match? That’s a WTF moment. WTF does that mean? Does “not a match” mean wrong spell? The hell it’s the wrong spell.

Check at the top, in the recipe list:

    // Recipe for creating Potion of Mage Armor.
    SetLocalString(oVarHolder, "LS_SMITH_1_ResRef", "potionofmagearmo");
    SetLocalInt (oVarHolder,   "LS_SMITH_1_gold", 0);
    SetLocalInt (oVarHolder,   "LS_SMITH_1_ingredient_count", 2);
    SetLocalString(oVarHolder, "LS_SMITH_1_ingredient1", "x2_it_cfm_pbottl"); // Magic Potion Bottle
    SetLocalString(oVarHolder, "LS_SMITH_1_ingredient2", "NW_IT_MSMLMISC11"); // Quartz Crystal
    SetLocalInt (oVarHolder,   "LS_SMITH_1_quantity1", 1);
    SetLocalInt (oVarHolder,   "LS_SMITH_1_quantity2", 2);
    SetLocalInt (oVarHolder,   "LS_SMITH_1_spell", SPELL_NEGATIVE_ENERGY_RAY);
    SetLocalInt (oVarHolder,   "LS_SMITH_1_vfx", VFX_FNF_SMOKE_PUFF);

Change the constant SPELL_NEGATIVE_ENERGY_RAY to SPELL_MAGE_ARMOR. if you want the spell requirement to be Mage Armor.

You used my OLD one, the first one in the thread. I’ll have to modify yours with the NEW one.

Okay NOW it works. I’d have to see what the difference between what you did and the LS generated script and why it didn’t work.

The key I found was incrementing all these values by 1. It must be a bug in LS generation somehow. Thanks for the help!

1 Like