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/
Submerged caverns and diving
  • How is the submerged cavern in Talore set up? I'd like to include something similar for one of the areas i'm building.


    And on a related note...is there any simple way to make PC movement automatically slowed in an area...for example in areas where water is chest deep.
  • I'll make an export of the relevant code for that cavern.
    As to the second question - I'd say a trigger with onenter and onexit scripts would do that - I'll code you something up :)
  • for the drowning thing, add this areaonentr_water to the areas onenter event.
    // Script: areaonentr_water

    // By: Mistcaller, edited by Sindol

    // Last edited: 17-10-2005

    // Purpose: Area entering script for flooded areas, applies damage for drowning



    #include "deth_include"



    int GetACPenalty(object oPC)

    {

        int iPenalty = 0;

        int bIdentified;

        object oItem;



        // Get the armor part of the armor check penalty

        oItem = GetItemInSlot(INVENTORY_SLOT_CHEST, oPC);

        if(GetIsObjectValid(oItem))

        {

            // Get the identified flag for safe keeping.

            bIdentified = GetIdentified(oItem);

            SetIdentified(oItem,FALSE);



            int nType;

            switch (GetGoldPieceValue(oItem))

            {

                case    1: nType = 0; break; // None

                case    5: nType = 0; break; // Padded

                case   10: nType = 1; break; // Leather

                case   15: nType = 2; break; // Studded Leather / Hide

                case  100: nType = 3; 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 = 6; break; // Full Plate

            }

            // Restore the identified flag, and return armor type.

            SetIdentified(oItem,bIdentified);

            iPenalty += nType;

        }

        // Get the shield part of the armor check penalty

        oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);

        if(GetIsObjectValid(oItem) && (

            GetBaseItemType(oItem) == BASE_ITEM_SMALLSHIELD ||

            GetBaseItemType(oItem) == BASE_ITEM_LARGESHIELD ||

            GetBaseItemType(oItem) == BASE_ITEM_TOWERSHIELD ))

        {

            // Get the identified flag for safe keeping.

            bIdentified = GetIdentified(oItem);

            SetIdentified(oItem,FALSE);



            int nType;

            switch (GetGoldPieceValue(oItem))

            {

                case   9: nType =  1; break; // Small Shield

                case  50: nType =  2; break; // Large Shield

                case 100: nType = 10; break; // Tower Shield

            }

            // Restore the identified flag, and return armor type.

            SetIdentified(oItem,bIdentified);

            iPenalty += nType;

        }

        return iPenalty;

    }



    void DrownDamage(object oPC, object oArea, int iDC, int iDamage)

    {

        object oCurrentArea = GetArea(oPC);



        // if oPC already left the area: bail

        if(oArea != oCurrentArea)

            return;



        // if oPC is a DM or NPC: bail

        if (GetIsDM(oPC) || !GetIsPC(oPC))

            return;



        // if oPC is already dead: bail (not sure if this is necessary)

        int iState = GetDeathState(oPC);

        if(iState == DEATH_STATE_DEAD || iState == DEATH_STATE_GHOST)

            return;



        // Constitution check vs the current DC

        int iCon = GetAbilityModifier(ABILITY_CONSTITUTION, oPC);

        int iCheck = d20() + iCon - GetACPenalty(oPC);

        if(iCheck >= iDC)

        {

            SendMessageToPC(oPC, "Check result: "+IntToString(iCheck)+" vs. DC for this round: "+IntToString(iDC)+" -> Save vs drowning successful!");

        }

        else

        {

            SendMessageToPC(oPC, "Check result: "+IntToString(iCheck)+" vs. DC for this round: "+IntToString(iDC)+" -> Save vs drowning failed!");

            SendMessageToPC(oPC, "Water gets into your lungs: you're drowning!");

            iDamage += iCheck;

            ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(iDamage, DAMAGE_TYPE_DIVINE), oPC);

        }



        // Movement speed decrease, dependent on strength check

        int nSlow = 60 - (d20() + GetAbilityModifier(ABILITY_STRENGTH, oPC));

        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectMovementSpeedDecrease(nSlow), oPC, 6.1);



        // Recursive loop

        DelayCommand(6.0, DrownDamage(oPC, oArea, iDC+1, iDamage));

    }





    void main()

    {

        object oArea = OBJECT_SELF;

        object oPC = GetEnteringObject();



        // Breath issues

        int iCon = GetAbilityModifier(ABILITY_CONSTITUTION, oPC);

        if(iCon < 0)

            iCon = -1;

        DelayCommand(RoundsToSeconds(iCon+2), DrownDamage(oPC, oArea, 10, 0));



        // Movement speed decrease, dependent on strength check

        int nSlow = 60 - (d20() + GetAbilityModifier(ABILITY_STRENGTH, oPC));

        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectMovementSpeedDecrease(nSlow), oPC, RoundsToSeconds(iCon+2)+0.1);

        // Execute basic script

        ExecuteScript("c_areaonenter", oArea);

    }
     
  • http://catara.orkpiraten.de/files/trg_slowmovement.rar
    This is a trigger that applies the slow effect to a PC on entering and removes it again on exiting the trigger.
  • How does that script work? Is it applying x amount of damage per round or something? If so, surely drowning is a bit more black and white than that, you either drown, or you don't? Picky, I know, but, I'd be asking myself as a player, why am I taking damage?
  • basically, you'll be making a bunch of CON saving throws (each one more difficult than the one before that). Failing the saving throw makes you take damage. Wearing armour makes the saving throws harder.
    Also, there are notes about successful or failed throws, and messages like "Water gets into your lungs: you're drowning!", so you know what's happening.

Howdy, Stranger!

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