EFUPW Forums

Main Forums => Suggestions => Player Workshop => Topic started by: Dhund on September 13, 2021, 05:12:31 AM

Title: Custom Curse System - A Revamp of Bestow Curse (and using PC Blood to cast it)
Post by: Dhund on September 13, 2021, 05:12:31 AM
Are you a vengeful hag, looking to punish those who break faith with you?
Maybe you're a High Priest, looking to bring your faith's disfavor upon those who betray your dogma?
Maybe you're just a spiteful wizard, raging against those who call you Mad?

If you are any of the above, or countless others, then BESTOW CURSE might be for you!

But right now, it is... lackluster. Thematically, and mechanically it doesn't feel quite as impactful as your other options would be for spells of the same level.

And we can fix that!

First, lets bring out some more of that sweet, sweet flavour.

[hide=The Big Book of Curses]
    //Is our target real, or a Bloody Simulacrum?
    if (TestStringAgainstPattern(GetName(oTarget), "Bloody Simulacrum"))
    {
        //if so, we need to get the real target
            string sTargetName = GetTag(oTarget);

            string sBloodTag = "";

            int nI;
            for (nI = 0; nI < GetStringLength(sTargetName); nI++)
            {
                if (GetSubString(sTargetName, nI, 1) == "_")
                {
                    sBloodTag += " ";
                }
                else
                {
                    sBloodTag += GetSubString(sTargetName, nI, 1);
                }
            }

            sTargetName = sBloodTag;

            object oPC = GetFirstPC();

            while(GetIsObjectValid(oPC))
            {
                if(GetName(oPC) == sTargetName)
                {
                    ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_DEMON_HAND), oTarget);
                    DestroyObject(oTarget, 3.0f);

                    oTarget = oPC;
                }
                oPC = GetNextPC();
            }

    }
[/hide]
---------Scripts-----------

[hide=Bestow Curse - nw_s0_bescurse]

   In the variable section, this section needs to be changed to correctly pull off of player tokens.
//Fetch the variable from either PC or PC token
    //nCurse = GetTokenInt(GetLastSpellCaster(), "CCS_Curse");
    nCurse = GetLocalInt(OBJECT_SELF, "CCS_Curse");




//::///////////////////////////////////////////////
//:: Bestow Curse
//:: NW_S0_BesCurse.nss
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    Afflicted creature must save or suffer a penalty.
    This is a supernatural effect.
*/
//:://////////////////////////////////////////////
//:: Created By: Bob McCabe
//:: Created On: March 6, 2001
//:://////////////////////////////////////////////
//:: Last Updated By: Dhund
//:: On: September 12, 2021

//Our Flavours of Curses
//0  Curse of Draining - Standard Curse, -2 to all stats
//1  Curse of Stumbling - -1 AC
//2  Curse of Flailing - -2 AB
//3  Curse of Fumbling - -2 Damage
//4  Curse of Plodding - 10% Movement Speed Decrease
//5  Curse of Tongues - 20% Arcane Spell Failure
//6  Curse of Breaching - -10 Spell Resist
//
//7  Curse of Yeman - 20% Fire Vulnerability
//8  Curse of Gnipir - 20% Cold Vulnerability
//9  Curse of Klink - 20% Sonic Vulnerability
//10  Curse of Fumigation - 20% Acid Vulnerability
//11  Curse of the Storm - 20% Lightning Vulnerability
//
//12  Curse of Vulnerability - -2 Universal Saves
//13  Curse of Reactions - -3 Reflex Save
//14  Curse of Constitution - -3 Fortitude Save
//15  Curse of the Mind   - -3 Will Save
//
//16  Curse of Illumination - Light and -3 Hide/MoveSilent
//17  Curse of Eyesight - -3 Spot/Search
//18  Curse of the Bridge - 5% Physical Vulnerability


#include "NW_I0_SPELLS"
#include "x2_inc_spellhook"
#include "inc_char_token"

void main()
{

/*
  Spellcast Hook Code
  Added 2003-06-23 by GeorgZ
  If you want to make changes to all spells,
  check x2_inc_spellhook.nss to find out more

*/

    if (!X2PreSpellCastCode())
    {
    // If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
        return;
    }

// End of Spell Cast Hook


    //Declare major variables
    object oTarget = GetSpellTargetObject();
    effect eVis = EffectVisualEffect(VFX_IMP_REDUCE_ABILITY_SCORE);
    //We need a Curse effect to allow it to be a curse
    effect eCurse = EffectCurse(0, 0, 0, 0, 0, 0);
    //If we want the custom curse to have a unique visual, we'll change it here
    effect eVisTwo = EffectVisualEffect(VFX_IMP_REDUCE_ABILITY_SCORE);

    //Pull the curse variable from the PC. Defaults to 0 if none set, or outside the range
    int nCurse = 0;

    //Fetch the variable from either PC or PC token
    //nCurse = GetTokenInt(GetLastSpellCaster(), "CCS_Curse");
    nCurse = GetLocalInt(OBJECT_SELF, "CCS_Curse");

    //Do we have Spell Focus or Greater Spell Focus?
    int nSpellPower = 0;
    if (GetHasFeat(FEAT_GREATER_SPELL_FOCUS_TRANSMUTATION, OBJECT_SELF))
    {
        nSpellPower = 2;
    }
    else if (GetHasFeat(FEAT_SPELL_FOCUS_TRANSMUTATION, OBJECT_SELF))
    {
        nSpellPower = 1;
    }

    //Make sure its a valid curse (increment value if adding new curses...)
    if (nCurse < 0 && nCurse > 18)
    {
        nCurse = 0;
    }

    //Determine which curse to use
    switch(nCurse)
    {
        case 0: //Curse of Draining - Standard Curse, -2 to all stats
                eCurse = EffectLinkEffects(eCurse, EffectCurse(2, 2, 2, 2, 2, 2));

                //Do we have extra/changed effects for SF or GSF Transmutation?
                //SF: Transmutation
                if (nSpellPower == 2)
                {
                    //Change effect to -3 to all stats
                    eCurse = EffectCurse(3, 3, 3, 3, 3, 3);
                }


        break;
        case 1: //Curse of Stumbling - -1 AC
                eCurse = EffectLinkEffects(eCurse, EffectACDecrease(1, AC_DODGE_BONUS, AC_VS_DAMAGE_TYPE_ALL));

                //Do we have extra/changed effects for SF or GSF Transmutation?
                //SF: Transmutation
                if (nSpellPower == 2)
                {
                    //Removing an additional 1 AC
                    eCurse = EffectLinkEffects(eCurse, EffectACDecrease(1, AC_NATURAL_BONUS, AC_VS_DAMAGE_TYPE_ALL));
                }

        break;
        case 2: //Curse of Flailing - -2 AB
                eCurse = EffectLinkEffects(eCurse, EffectAttackDecrease(2, ATTACK_BONUS_MISC));

                //Do we have extra/changed effects for SF or GSF Transmutation?
                //SF: Transmutation
                if (nSpellPower == 2)
                {
                    //Subtract 1 damage
                    eCurse = EffectLinkEffects(eCurse, EffectDamageDecrease(1, DAMAGE_TYPE_MAGICAL));
                }

        break;
        case 3: //Curse of Fumbling - -2 Damage
                eCurse = EffectLinkEffects(eCurse, EffectDamageDecrease(2, DAMAGE_TYPE_MAGICAL));

                //Do we have extra/changed effects for SF or GSF Transmutation?
                //SF: Transmutation
                if (nSpellPower == 2)
                {
                    //Subtract one AB too
                    eCurse = EffectLinkEffects(eCurse, EffectAttackDecrease(1, ATTACK_BONUS_MISC));
                }

        break;
        case 4: //Curse of Plodding - 10% Movement Speed Decrease
                eCurse = EffectLinkEffects(eCurse, EffectMovementSpeedDecrease(10));
                eVisTwo = EffectVisualEffect(VFX_IMP_SLOW);

                //Do we have extra/changed effects for SF or GSF Transmutation?
                //SF: Transmutation
                if (nSpellPower == 1)
                {
                    //Lower Reflex saves by 1
                    eCurse  = EffectLinkEffects(eCurse, EffectSavingThrowDecrease(SAVING_THROW_REFLEX, 1, SAVING_THROW_TYPE_ALL));
                }
                //GSF: Transmutation
                else if (nSpellPower == 2)
                {
                    //Lower Dodge AC by 1
                    eCurse = EffectLinkEffects(eCurse, EffectACDecrease(1, AC_DODGE_BONUS, AC_VS_DAMAGE_TYPE_ALL));
                }
        break;
        case 5: //Curse of Tongues - 20% Arcane Spell Failure
                eCurse = EffectLinkEffects(eCurse, EffectSpellFailure(20, SPELL_SCHOOL_GENERAL));
                eVisTwo = EffectVisualEffect(VFX_IMP_HEAD_MIND);

                //Do we have extra/changed effects for SF or GSF Transmutation?
                //SF: Transmutation
                if (nSpellPower == 2)
                {
                    //Lower spellcraft by 2
                    eCurse = EffectLinkEffects(eCurse, EffectSkillDecrease(SKILL_SPELLCRAFT, 3));
                }
        break;
        case 6: //Curse of Breaching - -10 Spell Resist
                eCurse = EffectLinkEffects(eCurse, EffectSpellResistanceDecrease(10));
                eVisTwo = EffectVisualEffect(VFX_IMP_HEAD_ODD);
        break;
        case 7: //Curse of Yeman - 20% Fire Vulnerability
                eCurse = EffectLinkEffects(eCurse, EffectDamageImmunityDecrease(DAMAGE_TYPE_FIRE, 20));
                eVisTwo = EffectVisualEffect(VFX_IMP_FLAME_M);

                //Do we have extra/changed effects for SF or GSF Transmutation?
                //SF: Transmutation
                if (nSpellPower == 2)
                {
                    //Lower saves vs Fire
                    eCurse = EffectLinkEffects(eCurse, EffectSavingThrowDecrease(SAVING_THROW_ALL, 1, SAVING_THROW_TYPE_FIRE));
                }
        break;
        case 8: //Curse of Gnipir - 20% Cold Vulnerability
                eCurse = EffectLinkEffects(eCurse, EffectDamageImmunityDecrease(DAMAGE_TYPE_COLD, 20));
                eVisTwo = EffectVisualEffect(VFX_IMP_FROST_S);

                //Do we have extra/changed effects for SF or GSF Transmutation?
                //SF: Transmutation
                if (nSpellPower == 2)
                {
                    //Lower saves vs Cold
                    eCurse = EffectLinkEffects(eCurse, EffectSavingThrowDecrease(SAVING_THROW_ALL, 1, SAVING_THROW_TYPE_COLD));
                }
        break;
        case 9: //Curse of Klink - 20% Sonic Vulnerability
                eCurse = EffectLinkEffects(eCurse, EffectDamageImmunityDecrease(DAMAGE_TYPE_SONIC, 20));
                eVisTwo = EffectVisualEffect(VFX_IMP_SONIC);

                //Do we have extra/changed effects for SF or GSF Transmutation?
                //SF: Transmutation
                if (nSpellPower == 2)
                {
                    //Lower saves vs Sonic
                    eCurse = EffectLinkEffects(eCurse, EffectSavingThrowDecrease(SAVING_THROW_ALL, 1, SAVING_THROW_TYPE_SONIC));
                }
        break;
        case 10: //Curse of Fumigation - 20% Acid Vulnerability
                eCurse = EffectLinkEffects(eCurse, EffectDamageImmunityDecrease(DAMAGE_TYPE_ACID, 20));
                eVisTwo = EffectVisualEffect(VFX_IMP_ACID_S);

                //Do we have extra/changed effects for SF or GSF Transmutation?
                //SF: Transmutation
                if (nSpellPower == 2)
                {
                    //Lower saves vs acid
                    eCurse = EffectLinkEffects(eCurse, EffectSavingThrowDecrease(SAVING_THROW_ALL, 1, SAVING_THROW_TYPE_ACID));
                }
        break;
        case 11: //Curse of the Storm - 20% Lightning Vulnerability
                eCurse = EffectLinkEffects(eCurse, EffectDamageImmunityDecrease(DAMAGE_TYPE_ELECTRICAL, 20));
                eVisTwo = EffectVisualEffect(VFX_IMP_LIGHTNING_S);

                //Do we have extra/changed effects for SF or GSF Transmutation?
                //SF: Transmutation
                if (nSpellPower == 2)
                {
                    //Lower saves vs lightning
                    eCurse = EffectLinkEffects(eCurse, EffectSavingThrowDecrease(SAVING_THROW_ALL, 1, SAVING_THROW_TYPE_ELECTRICITY));
                }
        break;
        case 12: //Curse of Vulnerability - -2 Universal Saves
                eCurse = EffectLinkEffects(eCurse, EffectSavingThrowDecrease(SAVING_THROW_ALL, 2, SAVING_THROW_TYPE_ALL));

                //Do we have extra/changed effects for SF or GSF Transmutation?
                //SF: Transmutation
                if (nSpellPower == 2)
                {
                    //Do -3 Saves instead
                    eCurse = EffectCurse(0, 0, 0, 0, 0, 0);
                    eCurse = EffectLinkEffects(eCurse, EffectSavingThrowDecrease(SAVING_THROW_ALL, 3, SAVING_THROW_TYPE_ALL));
                }
        break;
        case 13: //Curse of Reactions - -3 Reflex Save
                eCurse = EffectLinkEffects(eCurse, EffectSavingThrowDecrease(SAVING_THROW_REFLEX, 3, SAVING_THROW_TYPE_ALL));

        break;
        case 14: //Curse of Constitution - -3 Fortitude Save
                eCurse = EffectLinkEffects(eCurse, EffectSavingThrowDecrease(SAVING_THROW_FORT, 3, SAVING_THROW_TYPE_ALL));

        break;
        case 15: //Curse of the Mind   - -3 Will Save
                eCurse = EffectLinkEffects(eCurse, EffectSavingThrowDecrease(SAVING_THROW_WILL, 3, SAVING_THROW_TYPE_ALL));

        break;
        case 16: //Curse of Illumination - Light and -3 Hide/MoveSilent
                eCurse = EffectLinkEffects(eCurse, EffectSkillDecrease(SKILL_HIDE, 3));
                eCurse = EffectLinkEffects(eCurse, EffectSkillDecrease(SKILL_MOVE_SILENTLY, 3));
                eCurse = EffectLinkEffects(eCurse, EffectVisualEffect(VFX_DUR_LIGHT_YELLOW_20));

        break;
        case 17: //Curse of Eyesight - -3 Spot/Search
                eCurse = EffectLinkEffects(eCurse, EffectSkillDecrease(SKILL_SPOT, 3));
                eCurse = EffectLinkEffects(eCurse, EffectSkillDecrease(SKILL_SEARCH, 3));

        break;
        case 18: //Curse of the Bridge - 5% Physical Vulnerability
                eCurse = EffectLinkEffects(eCurse, EffectDamageImmunityDecrease(DAMAGE_TYPE_BLUDGEONING, 5));
                eCurse = EffectLinkEffects(eCurse, EffectDamageImmunityDecrease(DAMAGE_TYPE_PIERCING, 5));
                eCurse = EffectLinkEffects(eCurse, EffectDamageImmunityDecrease(DAMAGE_TYPE_SLASHING, 5));

        break;
    }

    //Is our target real, or a Bloody Simulacrum?
    if (TestStringAgainstPattern(GetName(oTarget), "Bloody Simulacrum"))
    {
        //if so, we need to get the real target
            string sTargetName = GetTag(oTarget);

            string sBloodTag = "";

            int nI;
            for (nI = 0; nI < GetStringLength(sTargetName); nI++)
            {
                if (GetSubString(sTargetName, nI, 1) == "_")
                {
                    sBloodTag += " ";
                }
                else
                {
                    sBloodTag += GetSubString(sTargetName, nI, 1);
                }
            }

            sTargetName = sBloodTag;

            object oPC = GetFirstPC();

            while(GetIsObjectValid(oPC))
            {
                if(GetName(oPC) == sTargetName)
                {
                    ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_DEMON_HAND), oTarget);
                    DestroyObject(oTarget, 3.0f);

                    oTarget = oPC;
                }
                oPC = GetNextPC();
            }

    }

    //Make sure that curse is of type supernatural not magical
    eCurse = SupernaturalEffect(eCurse);
//    if(!GetIsReactionTypeFriendly(oTarget))
    {
        //Signal spell cast at event
        SignalEvent(oTarget, EventSpellCastAt(oTarget, SPELL_BESTOW_CURSE));
         //Make SR Check
         if (!MyResistSpell(OBJECT_SELF, oTarget))
         {
            //Make Will Save
            if (!/*Will Save*/ MySavingThrow(SAVING_THROW_WILL, oTarget, GetSpellSaveDC()))
            {
                //Apply Effect and VFX
                ApplyEffectToObject(DURATION_TYPE_PERMANENT, eCurse, oTarget);
                ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
                ApplyEffectToObject(DURATION_TYPE_INSTANT, eVisTwo, oTarget);
            }
        }
    }
}

[/hide]

[hide=Player Tool implementation of Bloody Simulacrum summoning]

Something odd with the forums keeps happening.         

if (nValid = = 0)
        {
            SendMessageToPC(oUser, "No bond could be made");
        }


This section will not post if done correctly. The space between the '= =' in the IF statement needs to be removed to work

#include "inc_vistransform"
void main()
{
    object oUser = OBJECT_SELF;

    //Make sure the tool was used on a blood vial
    object oClicked = GetSpellTargetObject(); //Need to get clicked item here

    string sClicked = GetName(oClicked);

    //Check if its a vial of blood...
    string sBloody = GetStringRight(sClicked, 5);
    if (TestStringAgainstPattern(sBloody, "Blood"))
    {

        int nNameLength = GetStringLength(sClicked);
        string sBloodName = GetSubString(sClicked, 0, nNameLength - 8);


        SendMessageToPC(oUser, "You attempt to create a bond between " + sBloodName + "'s Blood and " + sBloodName);

        //Is the player online?

        object oPC = GetFirstPC();
        int nValid = 0;
        while(GetIsObjectValid(oPC))
        {
            if(GetName(oPC) == sBloodName)
            {
                nValid = 1;
                SendMessageToPC(oUser, "You create the bond...");

                //Does the other PC detect it? Opposed Spellcraft checks
                int nDC = d20(1) + GetSkillRank(SKILL_SPELLCRAFT, oUser, FALSE);
                if (GetIsSkillSuccessful(oPC, SKILL_SPELLCRAFT, nDC))
                {
                     SendMessageToPC(oUser, "A chill runs down your spine as you sense " + GetName(oUser) + " forge a connection to you...");
                }
                else
                {
                    SendMessageToPC(oUser, "A chill runs down your spine...");
                }


                //Now we make the name into something we can store in a new tag...
                string sBloodTag = "";

                int nI;
                for (nI = 0; nI < GetStringLength(sBloodName); nI++)
                {
                    if (GetSubString(sBloodName, nI, 1) == " ")
                    {
                        sBloodTag += "_";
                    }
                    else
                    {
                        sBloodTag += GetSubString(sBloodName, nI, 1);
                    }
                }

                object oBloodSim = CreateObject(OBJECT_TYPE_CREATURE, "bloodysimulacrum", GetLocation(oUser),
                    FALSE, sBloodTag);

                ApplyVisualTransformOnTarget(oBloodSim, "scale", "x", "TO", 0.4f);

                ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_IMP_EVIL_HELP), oUser, 0.4f);

                //Burn the blood as it is used, then in a minute, get rid of the simulacrum
                DestroyObject(oClicked);
                DestroyObject(oBloodSim, 60.0f);

            }
                oPC = GetNextPC();
        }

        if (nValid = = 0)
        {
            SendMessageToPC(oUser, "No bond could be made");
        }



    }
    else
    {
        SendMessageToPC(oUser, "This is not a vial of blood.");
    }

}

[/hide]

[hide=Bloody Simulacrum NPC]
Not a script, but an NPC. For this, I was just using the Ruby Golem model, with all scripts removed, and a resref of 'bloodysimulacrum'
[/hide]