I need some help

Hello everyone!
I am new here albeit I play NWN since ages. However I just started to make real modules for it. Not quite new with modules but my modules so far never had any scripts just areas filled with monsters to be able to play my characters passed NWN + Xp1 & Xp2 campaigns…
But now that I started to use scripts I met some troubles: Not all scripts works as I wanted. The first one is an NPC who must attack the PC when open a chest. The second is a boulder what the PC may climb to reach another area. Since I am not sure whether my scripts failed or the objects’ setups I uploaded the module:
https://www.mediafire.com/file/hvq2hk3l9qowtiw/MyFirstModule.zip/file
If someone could figure out what is wrong I would glad and grateful! Oh, I use common NWN with expansion + 1.69 patch, not diamond or EE!
I also wonder if there is some guide how to include new item graphics, like rings, plot objects in the game?
Thanks!

I thought to take a look (even though I only work with NWN2 nowadays) but looking at the whole thing in the toolset I felt a bit intimidated. If people are to help checking your scripts and objects’ setups it would be a huge help if you could tell us in what area, which objects’ setups you are talking about, and what scripts. It’s a bit much to go over the whole thing (at least for me) so I won’t do anything about this until then.

Yes, please post the script lines that aren’t working (as a bbcode [code] block for legibility).

The Custom Content Guide on NeverwinterVault.org is the best guide to making new graphics - quite rightly, you’ve chosen some simple tasks to begin with, so don’t be overwhelmed by all the complicated stuff like armour, just seek out what you need, & feel free to ask here if unclear.

Sorry, my bad! Were in a bit hurry and forgot the most important things!
1.
-Area: Eastern parts of the Woods
-Placeables: strange builder
It has a script enable a conversation: climb_rock <= that, if check success, enable the PC to enter a new area (Hilltop groove) using a waypoint dropped in the hilltop area.
-Problem: even if the skill check is succeed the text appears to managed climb the rock but not teleport the PC to the destination waypoint…
2.
-Area: Forbidden ruin
-Placeables: chest
In it’s OnOpen there is the script (chestguardattack) what intented to trigger the NPC Urkab Barkas (present near the chest) to attack the PC.
-Problem: Urkab just stay and watch but not attack. Not sure if the chest setup is wrong, the attack script or the NPC need some special in it’s script-set…

  • Thanks for the hint about the CCG! I would have a look for sure!

Like Proleric said, could you post those scripts here then? It will be easier to help and discuss for everyone.

So, looking in the toolset it’s this script here it seems:

void main()
{
    object oPlayer = GetPCSpeaker();
    int nStrMod = GetAbilityModifier (ABILITY_STRENGTH, oPlayer);
    int nDexMod = GetAbilityModifier (ABILITY_DEXTERITY, oPlayer);
    int nLevel = GetHitDice (oPlayer);
    int nRoll = d20();
    int nCheck = nRoll+nStrMod+nDexMod;
    effect eConfused = EffectVisualEffect (VFX_IMP_DAZED_S);
    AssignCommand (oPlayer, ActionPlayAnimation (ANIMATION_LOOPING_GET_MID, 1.0, 1.0));
    if ( (nCheck) >= 10)
    {
        string sThisTag = GetTag(OBJECT_SELF);
        string sWaypoint = "TELE_CLIMB";
        string sTeleportTo =sWaypoint+sThisTag;
        object oWaypoint = GetWaypointByTag (sTeleportTo);
     // object oWaypoint = GetObjectByTag("TELE_CLIMB");
        location lLocation = GetLocation(oWaypoint);
        AssignCommand (oPlayer, ActionJumpToObject (oWaypoint));
        ActionSpeakString ("You've managed to climb over the rock", TALKVOLUME_TALK);
    }
    if ( (nCheck) <= 9 && (nCheck) >= 7)
    {
        ActionSpeakString ("You've failed to climb the rock", TALKVOLUME_TALK);
        AssignCommand (oPlayer, ActionPlayAnimation (ANIMATION_LOOPING_SIT_CROSS, 1.0, 1.0));
    }
    if ( (nCheck) <= 6 && (nCheck) >= 4)
    {
        effect eDamage = EffectDamage (d3(nLevel), DAMAGE_TYPE_BLUDGEONING);
        ApplyEffectToObject (DURATION_TYPE_INSTANT, eDamage, oPlayer);
        ApplyEffectToObject (DURATION_TYPE_TEMPORARY, eConfused, oPlayer, 3.0);
        ActionSpeakString ("You've fallen and suffered slight injuries", TALKVOLUME_TALK);
        AssignCommand (oPlayer, ActionPlayAnimation (ANIMATION_LOOPING_SIT_CROSS, 1.0, 3.0));
        ApplyEffectToObject (DURATION_TYPE_TEMPORARY, eConfused, oPlayer, 3.0);
    }
    if ( (nCheck) <= 3 && (nCheck) >= 0)
    {
        effect eDamage = EffectDamage (d6(nLevel), DAMAGE_TYPE_BLUDGEONING);
        ApplyEffectToObject (DURATION_TYPE_INSTANT, eDamage, oPlayer);
        ActionSpeakString ("You've fallen and suffered bad injuries", TALKVOLUME_TALK);
        AssignCommand (oPlayer, ActionPlayAnimation (ANIMATION_LOOPING_SIT_CROSS, 1.0, 6.0));
        ApplyEffectToObject (DURATION_TYPE_TEMPORARY, eConfused, oPlayer, 6.0);
    }
 }

I changed your script to this since you said that the teleportation failed:

void main()
{
    object oPlayer = GetPCSpeaker();
    int nStrMod = GetAbilityModifier (ABILITY_STRENGTH, oPlayer);
    int nDexMod = GetAbilityModifier (ABILITY_DEXTERITY, oPlayer);
    int nLevel = GetHitDice (oPlayer);
    int nRoll = d20();
    int nCheck = nRoll+nStrMod+nDexMod;
    effect eConfused = EffectVisualEffect (VFX_IMP_DAZED_S);
    AssignCommand (oPlayer, ActionPlayAnimation (ANIMATION_LOOPING_GET_MID, 1.0, 1.0));
    if ( (nCheck) >= 10)
    {
        string sThisTag = GetTag(OBJECT_SELF);
        string sWaypoint = "TELE_CLIMB";
        string sTeleportTo =sWaypoint+sThisTag;
        object oWaypoint = GetWaypointByTag (sTeleportTo);


     // object oWaypoint = GetObjectByTag("TELE_CLIMB");
        location lLocation = GetLocation(oWaypoint);

        if(GetIsObjectValid(oWaypoint))
        {
        SendMessageToPC(oPlayer,"The waypoint is vaild");
        AssignCommand (oPlayer, ActionJumpToObject (oWaypoint));
        ActionSpeakString ("You've managed to climb over the rock", TALKVOLUME_TALK);
        }

        else
        {
          SendMessageToPC(oPlayer,"The waypoint is invaild");
        }


    }
    if ( (nCheck) <= 9 && (nCheck) >= 7)
    {
        ActionSpeakString ("You've failed to climb the rock", TALKVOLUME_TALK);
        AssignCommand (oPlayer, ActionPlayAnimation (ANIMATION_LOOPING_SIT_CROSS, 1.0, 1.0));
    }
    if ( (nCheck) <= 6 && (nCheck) >= 4)
    {
        effect eDamage = EffectDamage (d3(nLevel), DAMAGE_TYPE_BLUDGEONING);
        ApplyEffectToObject (DURATION_TYPE_INSTANT, eDamage, oPlayer);
        ApplyEffectToObject (DURATION_TYPE_TEMPORARY, eConfused, oPlayer, 3.0);
        ActionSpeakString ("You've fallen and suffered slight injuries", TALKVOLUME_TALK);
        AssignCommand (oPlayer, ActionPlayAnimation (ANIMATION_LOOPING_SIT_CROSS, 1.0, 3.0));
        ApplyEffectToObject (DURATION_TYPE_TEMPORARY, eConfused, oPlayer, 3.0);
    }
    if ( (nCheck) <= 3 && (nCheck) >= 0)
    {
        effect eDamage = EffectDamage (d6(nLevel), DAMAGE_TYPE_BLUDGEONING);
        ApplyEffectToObject (DURATION_TYPE_INSTANT, eDamage, oPlayer);
        ActionSpeakString ("You've fallen and suffered bad injuries", TALKVOLUME_TALK);
        AssignCommand (oPlayer, ActionPlayAnimation (ANIMATION_LOOPING_SIT_CROSS, 1.0, 6.0));
        ApplyEffectToObject (DURATION_TYPE_TEMPORARY, eConfused, oPlayer, 6.0);
    }
 }

Looking at the area of Hilltop groove the waypoint there seem to have the tag of “TELE_CLIMB”, yet the tag of the waypoint the PC is jumping to has the tag of “TELE_CLIMBTELE_CLIMB” or something like that (because of string sTeleportTo =sWaypoint+sThisTag;, since the tag of the waypoint and the tag of the boulder is the same, so no wonder the PC doesn’t teleport .

Solution: Try with changing the waypoint tag to something else like HILL_TELE perhaps?

EDIT:

Regarding nr.2: This sounds awefully similar to what we discussed very recently in another thread. Try changing the “chestguardattack” to this:

#include "nw_i0_generic"

void main()
{
    object oPC = GetLastOpenedBy();
    if (!GetIsPC(oPC)) return;
    int DoOnce = GetLocalInt(oPC, GetTag(OBJECT_SELF));
    if (DoOnce==TRUE) return;
    SetLocalInt(oPC, GetTag(OBJECT_SELF), TRUE);
    object oTarget;
    oTarget = GetObjectByTag("URKAB");
    ChangeToStandardFaction(oTarget,STANDARD_FACTION_HOSTILE);
    SetIsTemporaryEnemy(oPC, oTarget);
    AssignCommand(oTarget, DetermineCombatRound(oPC));
}

Andgalf!
Thanks all your help! It seems the teleport script I just written idiotic and paid not attention the " sWaypoint+sThisTag" part. For an object and NPC the same TAGs would may work but teleporting between areas it is not a good idea. Thanks again to point this out for me!
Quick question: STANDARD_FACTION_HOSTILE would not change the whole faction hostile? It need them a custom faction because make commoner faction hostile in a module not trully good.

As far as I know when you do it like this in the script it only changes this particular creature’s faction.

ChangeToStandardFaction() isn’t a problem because it only changes one creature. The faction that creature used to belong to is unaffected.

P.S. SetIsTemporaryEnemy() isn’t necessary in this case, because the Hostile faction is already hostile to the PC.

Thanks for the help guys! I finally managed to solve both things a bit different ways. Wanted to much with way to little knowledge of NWN-coding. Now everything works and ready to upload&share but I first want to ask how to do that properly? May I use outside file storage (MediaFire) or is there some services of the vault for upload and store files? Then how to share them? Launch a topic?

+1
I want to reskin original driders. Found the mdl files but the textures, well, only ~64x64 tga files I found. Doubt those are used so is there a way to find out what number of tga means the drider textures? I use a bit “hacked” NWN viewer to explore Xp1&Xp2 bifs but it is very unstable (crash about every 2.-3. file I want to view)…

So, I found myself in trouble. I want to reskin things but I not know how to reassign the TGA texture files of an mdl. The CCG said ObsidianSS as a tool of reskin but I found no such things available! Anyone have this tool or know some alternative ways works under WinXP?

With NWN explorer you can view the model, click an the ASCII tab and save it as a text file (https://forums.beamdog.com/discussion/76541/tools-nwn-explorer-1-8).
If there was a .txt added to the filename, remove that before or after you edited the file with a text editor of your choice.
Look for occurances of “bitmap” which is followed by a texture’s name. When you see the texture you want to replace, replace the name and save when finished.

Zwerkules! Thanks the answer! Everything works fine! Now reskin models what I shall share later. Interesting work found out what texture pieces goes where on a model…

to upload a project follow link https://neverwintervault.org/#overlay=node/add/project
after you log in there should be “contribute” on the left side of every page

I need some help once again…
There is this script:

void main()
{
int nXP = 2; // amount of xp per damage point
int nXPMax = 2000; // Max amount of xp a PC can get from the Dummy
int nMaxLevel = 3; // Max level the PC can be to still gain xp from beating up a Dummy
int nDam = GetTotalDamageDealt();
object oPC = GetLastDamager();
if(GetIsPC(oPC) && GetHitDice(oPC) <= nMaxLevel && GetLocalInt(GetModule(),“Dummy”+GetName(oPC)) < nXPMax+1)
{
GiveXPToCreature(oPC,nDamnXP);
SetLocalInt(GetModule(),“Dummy”+GetName(oPC),GetLocalInt(GetModule(),“Dummy”+GetName(oPC)) + nDam
nXP);
// Heal the dummy so it don’t get destroyed
ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHeal(nDam),OBJECT_SELF);
}
else
{
SendMessageToPC(oPC,"You have exceeded Level "+IntToString(nMaxLevel));
SendMessageToPC(oPC,“Or you have gained “+IntToString(nXPMax)+” amount of xp”);
ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHeal(nDam),OBJECT_SELF);
}
}

It works fine but the target not filters if the dealt damage is melee, ranged or spell. So, is there any viable way to make a version what records only ranged damage and\or magical damage?

You really need to use these forum’s code formatting options even if only because of 2 things. The first is that the underlying software converts ordinary double quotes (")into the 6699 (" ") style meaning code not using the formatting facilities will need to be edited by anybody who copies it before it will work. The other is that code in a code block has a neat download button when you hover your mouse pointer over it. Here is your code formatted and with the three ints that the values are not meant to change converted to const ints -

const int nXP = 2;        // amount of xp per damage point
const int nXPMax = 2000;  // Max amount of xp a PC can get from the Dummy
const int nMaxLevel = 3;  // Max level the PC can be to still gain xp from beating up a Dummy

void main()
{
    int nDam = GetTotalDamageDealt();
    object oPC = GetLastDamager();

    if(GetIsPC(oPC) && GetHitDice(oPC) <= nMaxLevel && GetLocalInt(GetModule(), "Dummy" + GetName(oPC)) < nXPMax + 1)
    {
        GiveXPToCreature(oPC,nDamnXP);
        SetLocalInt(GetModule(), "Dummy" + GetName(oPC), GetLocalInt(GetModule(), "Dummy" + GetName(oPC)) + nDamnXP);

        // Heal the dummy so it don’t get destroyed

        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(nDam), OBJECT_SELF);
    }
    else
    {
        SendMessageToPC(oPC, "You have exceeded Level " + IntToString(nMaxLevel));
        SendMessageToPC(oPC, "Or you have gained " + IntToString(nXPMax) + " amount of xp");
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(nDam), OBJECT_SELF);
    }
}

See this thread - A Short Tour of These Forums - for three different ways to format your code.

TR

1 Like

Problem is, melee v ranged is not a damage type.

I guess you could examine the weapon currently equipped by the damager.

OK. I used the already posted basic code with some extensions and it works with ranged weapons BUT also with melee. Because I need some “if” and “else” statement but have no clue what kind of (mostly for the “else” part).
The script:

void main()
{
int nXP = 5; // amount of xp per damage point
int nXPMax = 2000; // Max amount of xp a PC can get from the Dummy
int nMaxLevel = 3; // Max level the PC can be to still gain xp from beating up a Dummy
int nDam = GetTotalDamageDealt();
object oPC = GetLastDamager();
if(GetIsPC(oPC) && GetHitDice(oPC) <= nMaxLevel && GetLocalInt(GetModule(),"Dummy"+GetName(oPC)) < nXPMax+1)
  {
    GetWeaponRanged(GetLastWeaponUsed(oPC));
    GetDistanceToObject(oPC) > 12.0;
    GiveXPToCreature(oPC,nDam*nXP);
    SetLocalInt(GetModule(),"Dummy"+GetName(oPC),GetLocalInt(GetModule(),"Dummy"+GetName(oPC)) + nDam*nXP);
    // Heal the dummy so it don't get destroyed
    ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHeal(nDam),OBJECT_SELF);
    }
else
    {
    SendMessageToPC(oPC,"You have exceeded Level "+IntToString(nMaxLevel));
    SendMessageToPC(oPC,"Or you have gained "+IntToString(nXPMax)+" amount of xp");
    ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHeal(nDam),OBJECT_SELF);
  }
}

I think the “GetWeaponRanged” and “GetDistanceToObject” maybe possible to be in the same “if” statement but what should I use to the “else” part to prevent getting XP if the target hit be non-ranged weapons?

You did not explain what you’re trying to achieve with your script.

It appears you want to give PC xp based on damage dealt to a combat dummy placeable when specific conditions are met.

Try this code (click).
// by NWShacker, 2021-06-12

// global setting constants
const string VAR_DUMMY = "dummy_"; // module variable to store current xp amount
const float  MIN_DIST  = 12.0;     // minimum distance for PC to gain xp
const int    XP_SCALE  = 5;        // amount of xp per damage point
const int    MAX_XP    = 2000;     // Max amount of xp a PC can get
const int    MAX_LEVEL = 3;        // Max level PC can be to still gain xp

// OnDamaged event handler
void main()
{
    object oDamager;
    object oWeapon;
    string sPlayerID;
    int iCurrentXP;
    int iGainedXP;

    // heal self to max hp
    ApplyEffectToObject(DURATION_TYPE_INSTANT,
        EffectHeal(GetMaxHitPoints()), OBJECT_SELF);

    // get last damager
    oDamager = GetLastDamager();

    // quit if damager is not a PC
    if(!GetIsPC(oDamager))
    {
        return;
    }

    // quit if damager has already attained level higher than MAX_LEVEL
    if(GetHitDice(oDamager) > MAX_LEVEL)
    {
        FloatingTextStringOnCreature("You have already attained level higher than " +
            IntToString(MAX_LEVEL), oDamager);
        return;
    }

    // get unique ID of damager
    sPlayerID = VAR_DUMMY + GetPCPublicCDKey(oDamager, TRUE) +
        "_" + GetName(oDamager);

    // get current amount of XP gained by damager
    iCurrentXP = GetLocalInt(GetModule(), sPlayerID);

    // quit if damager has already gained more XP than MAX_XP
    if(iCurrentXP > MAX_XP)
    {
        FloatingTextStringOnCreature("You have already gained " +
            IntToString(MAX_XP) + " xp", oDamager);
        return;
    }

    // get last weapon used by damager
    oWeapon = GetLastWeaponUsed(oDamager);

    // quit if damager did not use a ranged weapon or is too close
    if(GetDistanceToObject(oDamager) < MIN_DIST ||
        !GetWeaponRanged(oWeapon) ||
        GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oDamager) != oWeapon ||
        GetDamageDealtByType(DAMAGE_TYPE_BASE_WEAPON) == -1)
    {
        FloatingTextStringOnCreature("You must shoot from " +
            FloatToString(MIN_DIST, 0, 0) + " meters or more", oDamager);
        return;
    }

    // calculate amount of XP gained
    iGainedXP = GetTotalDamageDealt() * XP_SCALE;

    // give xp to damager and show a floating message about it
    GiveXPToCreature(oDamager, iGainedXP);
    FloatingTextStringOnCreature("You have gained " +
        IntToString(iGainedXP) + " xp", oDamager);

    // save current amount of XP
    SetLocalInt(GetModule(), sPlayerID, iCurrentXP + iGainedXP);
}

It’s a variation of your script that should cover all possible cases, including the one when PC cheats by dealing non-weapon damage from afar after a valid shot. It assumes however that the dummy has no resistance versus normal damage.

Notice how this script uses a “multi-stage” approach, with individual if checks for failure states (and resulting early returns), each with a specific message telling the player what’s going on. Constants at the top provide a centralized control over the script.