I realised that there was never a formal announcement here to read up: The Catara NWN server is offline for quite some time now, due to time constraints. I might revive it someday, but it is pretty unlikely. If anyone wants to use our custom classes or tools, ping me on twitter (@jollyorc) and we can see what we can do for you! In the meantime, I do recommend The World of Avlis: https://avlis.org/
Climbing system
  • Wanting to include some PnP elements to the areas I'm building I decided to add a location where the PCs would have to climb down the side of a slippery waterfall...this also allowed me have a believable one way exit from a dungeon. Instead of using the simple JumpToLocation script I thought it would be nice to have a more believable system for such things in general. Since I dont know much about scripting I did a searched on nwvault to see what climbing systems are available out there. After checking out quite a few I came across this one: http://nwvault.ign.com/View.php?view=Prefabs.Detail&id=697

    Its a nice system which checks for armour and shield penalties and allows hostile creatures to follow the PC through. However after examining it I discovered it had some quirks, but after some effort I was bale to solve them (mind you, I'm no scripter! :D) :
    1) The original system used GetNearestObjectbyTag to identify the waypoints to jump the PC to, which makes it unsuitable if you are supposed to end up in another area. I was able to modify this to allow you to set the waypoints via variables set on the placeable which initiates the climb. The system is much more flexible in this way.
    2) It used a trigger at the fall location to deal out damage and an animation...and required you to place a trigger (with its own extra script attached to it) around the fall waypoint, so that the PC would trigger it once he moved. The original scripter implemented this to circumvent a problem he had which would occur if the PC died due to the fall (in which case he would die at the placeable, and not at the fall location). This in itself seemed very problematic...it required alot of hassle in painting the trigger correctly, and even then the effect would be weird and unrealistic in my opinion. After studying some other climbing scripts I figured out that there was a simple solution to this. I put in an ActionWait, and replaced the AssignCommand he had with ActionDoCommand (what is the difference between these two commands, I have no idea! :D ), to allow for a delay to jump the PC before pummeling him with damage.
    So now the damage, effects and animations are directly in the climbing script, which does not require a trigger with a separate script at the fall location.
    3) I modified the effects of failed climbs...in the original a failed climb only resulted in a knockdown effect. I felt it more realistic if both regular failure and critical failure resulted in damage...so, now one deals out d6 and the other d12 damage (multiplied by a hight modifier set as a variable on the climbing placeable). The effects on the PC are also changed...a regular fall just knockdowns and dazes the PC for a short while, while a critical fall will knockdown, daze and slow a PC for a bit longer.
    4) It gave the ability to a PC to activate a rope item in his inventory, which would grant him a +10 on his climb checks. Although nice, this solution just didn't seem realistic to me...so I scratched it completely from the system. What I would like to see is a conversation which allows a PC to tie a rope item from his inventory to a placeable (like a rock or something) either to allow the climb at all, or to make the climb easier by lowering the DC...and then have other PCs be able to climb this one rope. And also have the rope disappear after some time passes (mice eat it or something :D ). ...However...for the time being, ropes are not implemented.


    Luckily the original scripts from the system I altered had good info in them, explaining what each line of code did. I still cant believe that I was able to resolve all these modifications myself! And the damn thing still works! :D

    What do you think?
  • /////////////////////////////////////////////////////////////////
    //Catara Climbing System v1.0 by Borneo //
    // //
    //*considerable parts of this system consist of modified //
    //scripts originally from Nsignificants's Climbing System //
    //by JJRittenhouse //
    //*this system does not use triggers to deal out effects //
    //and damage, uses variables to define locations to move //
    //the PC, cicumvents the problem that used to occur when //
    //PC dies due to fall(the PC is now corectly transfered to //
    //the fall location), and deals out damage both for regular //
    //and critical climb failure. //
    /////////////////////////////////////////////////////////////////
    //
    //This script is placed on the OnUsed event of any useable
    //placeable. It will calculate a climb check, adding a +1
    //modifier for each level the creature has in a class that
    //normally gets Climb as a class skill in the PnP version.
    //This check will take armor class check into account. On
    //success the PC will be moved to the waypoint whose Tag is
    //the same as the sTarget variable set on the climbing placeble.
    //On a failure the PC will be moved to a waypoint whose Tag is
    //the same as the sFall_Target variable set on the climbing placeble.
    //This script requires #include "climb_inc" and the
    //ClimbCheck(), GetClimbClassMod(), and the
    //JumpAllAssociatesToLocation() functions
    //
    //
    //Variables required on placable:
    //sTarget - Tag of waypoint where a PC ends up if climb is successful
    //sFall_Target - Tag of waypoint where a PC ends up if climb fails
    //nDC - DC of climb
    //nFallDistance - falling height, the assigned value is multiplied with
    // 1d6(Fail) or 1d12 (Critical fail) to calculate damage
    // (a value of 1 can be considered as approximately 10 feet)


    #include "climb_inc"

    void main()
    {
    int nDC=GetLocalInt(OBJECT_SELF, "nDC");//Climb DC - local variable set on the placeable
    object oDestination=GetObjectByTag(GetLocalString(OBJECT_SELF, "sTarget"));//local variable set manually on the climbing placeable
    object oFall=GetObjectByTag(GetLocalString(OBJECT_SELF, "sFall_Target"));//the object that stores the fall location, set manually by the builder
    location lDestination=GetLocation(oDestination);//location of oDestination
    location lFall = GetLocation (oFall);//location of oFall
    object oCreature = GetLastUsedBy();//creature using the placeable
    int nClimb=ClimbCheck(oCreature, nDC); //perform the check
    object oHostileFollow;//hostile creature that might follow the player
    int nNth=1;//counter to get the next nearest creature until no more are found
    object OClimbable=OBJECT_SELF;//assign to variable to use within an
    //AssignAction command which would return the creature instead of the
    //placeable as OBJECT_SELF. This is the climbing placeable now being
    //used.
    int nFall=GetLocalInt (OBJECT_SELF, "nFallDistance");

    //assing objects for armor check penalties later
    object oArmorSlot= GetItemInSlot(INVENTORY_SLOT_CHEST,oCreature);
    object oLeftHandSlot= GetItemInSlot (INVENTORY_SLOT_LEFTHAND, oCreature);
    int nTumbleMod;//modifier due to armor check penalty, later assigned
    int nArmorMod=GetArmorCheckMod(oArmorSlot);//armor check penalty of item worn on chest
    int nShieldMod=GetShieldArmorCheckMod(oLeftHandSlot);//armor check penalty of item in left hand (shield, if any)
    effect eDaze= EffectDazed();
    effect eSlow= EffectSlow();
    effect eKnockdown= EffectKnockdown();
    effect eDamage;//damage effect, assigned later


    ...continued...
  • switch(nClimb)
    {
    case 0: //Failure
    AssignCommand(oCreature, JumpToLocation(lFall));//fall location from the waypoint placed manually by the builder
    AssignCommand(oCreature, ActionPlayAnimation (ANIMATION_LOOPING_SIT_CROSS, 8.0));//animation, knockdown effect.
    nTumbleMod=nArmorMod+nShieldMod;//assign tumble modifier
    //Make a tumble check, DC 15+the armor check penalty of the creature entering the trigger
    //if it passes, subtract one die from the damage
    if (GetIsSkillSuccessful (oCreature, SKILL_TUMBLE, 15-nTumbleMod))
    {
    nFall=nFall-1;
    }
    eDamage= EffectDamage (d6(nFall), DAMAGE_TYPE_BLUDGEONING);//determine the amount of damage by d6 per nFall
    ActionWait(2.0);
    ActionDoCommand(ApplyEffectToObject (DURATION_TYPE_TEMPORARY, eDaze, oCreature, 6.0));
    ActionDoCommand(ApplyEffectToObject (DURATION_TYPE_TEMPORARY, eKnockdown, oCreature, 4.0));
    ActionDoCommand(ApplyEffectToObject (DURATION_TYPE_INSTANT, eDamage, oCreature)); //apply the damage
    //controls hostile creatures climbing down to follow a creature who falls, same conditions as above
    oHostileFollow=GetNearestCreature (CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC, OBJECT_SELF,nNth);
    while (GetIsObjectValid(oHostileFollow))
    {
    if (!GetIsFriend(oHostileFollow, oCreature))
    {
    if (GetObjectSeen(oCreature, oHostileFollow))
    {
    int nChance=d20();
    int nFollow=nDC-GetClimbClassMod(oHostileFollow);
    if (nFollow>19)
    {
    nFollow=19;
    }
    if (!(nFollow+nChance>20))
    {
    AssignCommand (oHostileFollow, ClearAllActions(TRUE));
    AssignCommand(oHostileFollow, ActionInteractObject (OClimbable));
    }


    }
    }
    nNth++;
    oHostileFollow=GetNearestCreature (CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC, OBJECT_SELF,nNth);
    }
    break;
    case 1: //succeed, move to appropriate waypoint, move associates
    // to the waypoint, find the nearest hostile creatures and
    // have them use the placeable to try to follow.
    // The script will make a random check, giving more chance
    // for the creature to try the climb the more they are capable
    AssignCommand(oCreature, JumpToLocation(lDestination));//move the creature using the placeable to the climb location
    JumpAllAssociatesToLocation (oCreature, lDestination);//move all associates to the same location
    //This next block handles the ability of hostile creatures to follow the player using the Climbable.
    oHostileFollow=GetNearestCreature (CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC, OBJECT_SELF,nNth);//get the first Non-pc creature to the placeable
    //does not return PC's so it will not force them to use the placeable.
    while (GetIsObjectValid(oHostileFollow))//break condition, when all the creatures in the area have been checked this will break
    {
    if (!GetIsFriend(oHostileFollow, oCreature))//checks if hostile to the creature using the placeable.
    {
    if (GetObjectSeen(oCreature, oHostileFollow))//checks if the hostile can see the creature that just used the placeable
    {
    //compare the creature's climb skill modifier to the DC
    //the greater the chance for the creature to succeed, the more
    //likely it is to follow
    int nChance=d20();
    //finds the difference between the climb DC and the class modifier of the hostile creature
    int nFollow=nDC-GetClimbClassMod(oHostileFollow);
    //5% chance to try to follow even if the creauture can't make the
    //climb. To remove this behaviour comment out this if statement and the following three lines.
    if (nFollow>19)
    {
    nFollow=19;
    }
    //add the d20 roll to the difference between the DC and the creatures climb modifier.
    //If the creature's climb modifier is greater than the DC it will always follow.
    //If it is less than 20 (no chance) it will only follow on a roll of 20. The better the
    //chance the creature has to make the climb, the more likely it will try.
    if (!(nFollow+nChance>20))
    {
    AssignCommand (oHostileFollow, ClearAllActions(TRUE));//clear all actions in cue, including combat
    AssignCommand(oHostileFollow, ActionInteractObject (OClimbable));//use the climbable to try to follow (running this script for the hostile as well)
    }


    }
    }
    nNth++;//advance the counter to the next nearest creature to the placeable.
    oHostileFollow=GetNearestCreature (CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC, OBJECT_SELF,nNth);//get the next nearest non-pc creature and test While condition(above)
    }
    break;
    case 2: //Critical Failure
    AssignCommand(oCreature, JumpToLocation(lFall));//fall location from the waypoint placed manually by the builder
    AssignCommand(oCreature, ActionPlayAnimation (ANIMATION_LOOPING_DEAD_BACK, 8.0));//fall animation, no actual knockdown effect.
    nTumbleMod=nArmorMod+nShieldMod;//assign tumble modifier
    if (GetIsSkillSuccessful (oCreature, SKILL_TUMBLE, 15-nTumbleMod))
    {
    nFall=nFall-1;
    }
    eDamage= EffectDamage (d12(nFall), DAMAGE_TYPE_BLUDGEONING);//determine the amount of damage by d12 per nFall
    ActionWait(2.0);
    ActionDoCommand(ApplyEffectToObject (DURATION_TYPE_TEMPORARY, eSlow, oCreature, 15.0));
    ActionDoCommand(ApplyEffectToObject (DURATION_TYPE_TEMPORARY, eDaze, oCreature, 15.0));
    ActionDoCommand(ApplyEffectToObject (DURATION_TYPE_TEMPORARY, eKnockdown, oCreature, 6.0));
    ActionDoCommand(ApplyEffectToObject (DURATION_TYPE_INSTANT, eDamage, oCreature)); //apply the damage
    //controls hostile creatures climbing down to follow a creature who falls, same conditions as above
    oHostileFollow=GetNearestCreature (CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC, OBJECT_SELF,nNth);
    while (GetIsObjectValid(oHostileFollow))
    {
    if (!GetIsFriend(oHostileFollow, oCreature))
    {
    if (GetObjectSeen(oCreature, oHostileFollow))
    {
    int nChance=d20();
    int nFollow=nDC-GetClimbClassMod(oHostileFollow);
    if (nFollow>19)
    {
    nFollow=19;
    }
    if (!(nFollow+nChance>20))
    {
    AssignCommand (oHostileFollow, ClearAllActions(TRUE));
    AssignCommand(oHostileFollow, ActionInteractObject (OClimbable));
    }


    }
    }
    nNth++;
    oHostileFollow=GetNearestCreature (CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC, OBJECT_SELF,nNth);
    }
    break;
    }



    }
  • As well as "climb_inc":




    #include "nw_i0_plot"


    ////////////////////////////////////////////////////////////////
    //Catara Climbing System v1.0 by Borneo ///
    // ///
    //*considerable parts of this system consist of modified ///
    //scripts originally from Nsignificants's Climbing System ///
    //by JJRittenhouse ///
    // ///
    ////////////////////////////////////////////////////////////////

    //Functions in this Library

    //GetArmorCheckMod(): Returns the Armor Check modifier of oItem
    // 0 if invalid, or not armor, or just plain not found.
    // 0 to -8 as the value of AC got from the armor - 0 for none, -8 for Full plate.

    //GetShieldArmorCheckMod(): Returns the Armor Check modifier of oItem
    //Will Return a 0 Value to any non-sheild item passed

    //ClimbCheck(): Calculates a climb modifer subtracting Armor check
    //penalties and adding a +1 modifier for each level in a class
    //that normally possesses Climb as a class skill.
    //Performs the Climb roll and compares it to the DC passed to the
    //function (nDC).
    //Returns 0 if failed, 1 if Passed and 2 if failed by more than 10
    //Sends combat message to the player telling them that a climb
    //check was made, the DC of the climb check, the Armor check modifier
    //applied as well as the class modifier applied. Indicates success
    //or Failure to the Player.

    //JumpAllAssociatesToLocation()
    //Gets familiar, animal companion, summon, up to four henchmen, and dominated
    //creature, any 1 summon of a creature the PC summoned, and any 1
    //summon of a creature the PC dominates and jumps them to a location


    int GetArmorCheckMod(object oItem)
    {
    // Make sure the item is valid and is an armor.
    if (!(GetIsObjectValid(oItem)))
    return 0;
    if (GetBaseItemType(oItem) != BASE_ITEM_ARMOR)
    return 0;

    // Get the identified flag for safe keeping.
    int bIdentified = GetIdentified(oItem);
    SetIdentified(oItem,FALSE);

    int nType = 0;
    switch (GetGoldPieceValue(oItem))
    {
    case 1: nType = 0; break; // None
    case 5: nType = 0; break; // Padded
    case 10: nType = 0; break; // Leather
    case 15: nType = -1; break; // Studded Leather / Hide
    case 100: nType = -2; break; // Chain Shirt / Scale Mail
    case 150: nType = -5; break; // Chainmail / Breastplate
    case 200: nType = -7; break; // Splint Mail / Banded Mail
    case 600: nType = -7; break; // Half-Plate
    case 1500: nType = -8; break; // Full Plate
    }
    // Restore the identified flag, and return armor check modifier.
    SetIdentified(oItem,bIdentified);
    return nType;
    }


    // GetShieldArmorCheckMod ()
    //Find the Armor check modifier of the item in the shield hand
    //of the creature. If the object is not a shield return 0.
    int GetShieldArmorCheckMod (object oItem)
    {
    int nMod=0;
    // Make sure the item is valid, if not return 0 value
    if (!GetIsObjectValid(oItem))
    nMod=0;
    //if the object is a largeshield return -2
    if (GetBaseItemType(oItem) == BASE_ITEM_LARGESHIELD)
    nMod= -2;
    //If the object is a smallshield return -1
    if (GetBaseItemType (oItem) == BASE_ITEM_SMALLSHIELD)
    nMod= -1;
    //If the object is a TowerShield return -10
    if (GetBaseItemType (oItem) == BASE_ITEM_TOWERSHIELD)
    nMod= -10;
    return nMod;
    }




    ...continued...
  • ...continued from above...



    // GetClimbClassMod ()
    //calculate the class modifier by adding one for each level in a
    //class that normally gets climb as a skill.
    //While 4 ranks might be normally taken at first level, it might
    //not have been raised one rank every level. This only represents
    //a reasonable climb skill by class of the character.
    //This script is not adapted for the PRC hak.
    int GetClimbClassMod (object oPC)
    {

    int nPCClassMod;
    int nCreatureClimbMod=GetLocalInt (oPC, "nClimbMod");//local integer set on a creature to give them a climb bonus

    nPCClassMod=nPCClassMod+nCreatureClimbMod;//add that bonus

    if (GetLevelByClass (CLASS_TYPE_ASSASSIN, oPC)>0)
    {
    nPCClassMod=nPCClassMod+(GetLevelByClass (CLASS_TYPE_ASSASSIN, oPC));
    }
    if (GetLevelByClass (CLASS_TYPE_BARBARIAN, oPC)>0)
    {
    nPCClassMod=nPCClassMod+(GetLevelByClass (CLASS_TYPE_BARBARIAN, oPC));
    }
    if (GetLevelByClass (CLASS_TYPE_BARD, oPC)>0)
    {
    nPCClassMod=nPCClassMod+(GetLevelByClass (CLASS_TYPE_BARD, oPC));
    }
    if (GetLevelByClass (CLASS_TYPE_FIGHTER, oPC)>0)
    {
    nPCClassMod=nPCClassMod+ (GetLevelByClass (CLASS_TYPE_FIGHTER, oPC));
    }
    if (GetLevelByClass (CLASS_TYPE_HARPER, oPC)>0)
    {
    nPCClassMod=nPCClassMod+ (GetLevelByClass (CLASS_TYPE_HARPER, oPC));
    }
    if (GetLevelByClass (CLASS_TYPE_MONK, oPC)>0)
    {
    nPCClassMod=nPCClassMod+ (GetLevelByClass (CLASS_TYPE_MONK, oPC));
    }
    if (GetLevelByClass (CLASS_TYPE_RANGER, oPC)>0)
    {
    nPCClassMod=nPCClassMod+ (GetLevelByClass (CLASS_TYPE_RANGER, oPC));
    }
    if (GetLevelByClass (CLASS_TYPE_ROGUE, oPC)>0)
    {
    nPCClassMod=nPCClassMod+ (GetLevelByClass (CLASS_TYPE_ROGUE, oPC));
    }
    if (GetLevelByClass (CLASS_TYPE_SHADOWDANCER, oPC)>0)
    {
    nPCClassMod=nPCClassMod+ (GetLevelByClass (CLASS_TYPE_SHADOWDANCER, oPC));
    }

    return nPCClassMod;
    }

    // ClimbCheck ()
    //Returns whether a climb check was passed
    //Returns 0 if failed, 1 if Passed and 2 if failed by 10 or more
    //If the player has Climbing Rope and they are marked as using it
    //Check to see if the rope is still useable

    int ClimbCheck (object oCreature, int nDC)
    {
    string sPassFail;//string value for messaging to player result
    int nRoll; //climb check roll
    int nStrMod=GetAbilityModifier (ABILITY_STRENGTH, oCreature);//get str modifier
    object oArmorSlot= GetItemInSlot(INVENTORY_SLOT_CHEST,oCreature);//get object worn on chest
    object oLeftHandSlot= GetItemInSlot (INVENTORY_SLOT_LEFTHAND, oCreature);//get object in left hand
    //The total climb modifier is the armor check penalty, plus class modifier, plus str modifier
    int nClimbMod=GetArmorCheckMod(oArmorSlot)+GetShieldArmorCheckMod(oLeftHandSlot)
    +GetClimbClassMod(oCreature)+nStrMod;
    nRoll=d20();//d20 skill roll
    int nClimbTotal=nRoll+nClimbMod;//add total modifier

    if (nClimbTotal>=nDC)//if total exceeds or meets the DC
    {
    sPassFail=" Success! "; //indicate success, this variable
    //is used both to determine what value to return as well as to pass in
    //a message to the player the result.
    }
    else if (nClimbTotal
  • These are the two scripts that do all the work...the first one goes on the OnUsed event of a placeable.
    I had to break up the code in separate posts due to limitations on the number of characters.
  • Oh yea...it also sends feedback to the player with his climb check and DC of the climb, and what is the final success of the climb....some of this feedback (like the climb DC) can be easily eliminated.
  • Looks nice - can you make/send me a small sample mod with just some climbing in it for evaluation and testing? (send it to jollyorc@gmail.com)
  • Maybe it's possible to incorporate the C.R.A.P. climbing animations into this, once the "climb script" part is smoothed out? They have both jumping and climbing animations in the C.R.A.P. package, but their climbing script system was not as developed as this or I'd have stopped you a few versions back Borneo. :D

    The "jump associates to location" code may come in handy with fixing the familiar/companion issues reported as well, if the bugs are still on the loose?
  • I declare the system fit for use, as far as my testing shows. If you can give pointers on how to add in the shiny animations, we'll all be happy!
     
    If these here are the familiar/companion issues you refer to, this won't help - they aren't caused by the animal not knowing when to follow, but rather that they got eaten up by the despawner in certain cases. That issue should be fixed now though.
  • Great!

    Here is a link to an erf of the scripts, and a test module with some climbs set up (includes a wild gang of goblins, orcs and big cats to chase you up and down the cliffs :) ) if someone wants to try it out some more.

    http://www.filefactory.com/file/b054eh2/n/ClimbingSystem.erf

    http://www.filefactory.com/file/b054eh8/n/test_climbing.mod

    So this will be version 1.0
    If there are any new ideas on how the system can be tweaked, or expanded further i suggest to add the ideas in this thread.

    Here are some things I think might be cool to add to it eventually:
    *a rope system as I described in my initial post
    *have equipable items such as climbing boots add a + to your climb check

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!