Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - LoveLess

#1
Suggestions / Travel Dialogue Destinations
April 22, 2024, 08:43:58 PM
Just a small quality of life, you can currently hear every other part of the dialogue when the speaker is talking to the NPC, except what destination the player chooses at the end.

It would be nice if the player spoke it around them like the other dialogue options just for a small convenience.
#2
Screen Shots & Obituaries / Re: Cosine Mevura
April 05, 2024, 01:46:28 AM
killed the music
#3
Suggestions / Project Star Chart
March 20, 2024, 05:52:33 PM
It doesn't allow you to recast it while it's up, stating that you already have it in the combat log. This shouldn't be needed as the game won't let these stack since they are the same effect from the same script, much like you cant have two One With the Land giving you double skill bonuses. A bit annoying when you want to recast a spell that's about to run out of time anyway.

Would like it to just remove that check entirely and let it be cast, or remove the old cast if there's some other reason I am missing.
#4
Suggestions / Re: Spells Suggestions Thread
March 07, 2024, 06:57:27 AM
Horizikaul's boom added to Bard's first circle spell list. Would be cool for mage or evoker style bards and it's even sonic damage. It's only 4d4 at level 8.
#5
Player Workshop / Re: Expanded Item Tooltips
February 20, 2024, 08:46:13 PM
//expands tooltip of the selected item
void ExpandItemTooltip(object oTarget);

void ExpandItemTooltip(object oTarget)
{
    string sTooltip, sBaseItemType, s2daLookup, sAspect, sPrename;
    int nAspectID;

    int nBaseItemType = GetBaseItemType(oTarget);

    if (nBaseItemType == BASE_ITEM_BLANK_POTION || nBaseItemType == BASE_ITEM_BLANK_SCROLL ||  nBaseItemType == BASE_ITEM_BLANK_WAND
    ||  nBaseItemType == BASE_ITEM_ENCHANTED_POTION || nBaseItemType == BASE_ITEM_ENCHANTED_SCROLL || nBaseItemType == BASE_ITEM_ENCHANTED_WAND
    ||  nBaseItemType == BASE_ITEM_POTIONS || nBaseItemType == BASE_ITEM_SPELLSCROLL || nBaseItemType == BASE_ITEM_MAGICWAND) {
        return;
    }

    //turn this to FALSE when not testing
    int nFeedback = TRUE;

    if(GetLocalInt(oTarget, "nTooltipName") == FALSE)
        sPrename = GetName(oTarget, FALSE);
    else
        sPrename = GetLocalString(oTarget, "sTooltipPrename");

    if(!JsonGetLength(RegExpMatch("</c>", sPrename))) {
        //sPrename = ColorString(sPrename, Orange());
    }

    itemproperty iprpTarget = GetFirstItemProperty(oTarget);

    // base item type
    // moved above aspect to break the color between name/aspect
    // removed extra padding
    s2daLookup = Get2DAString("baseitems", "Name", GetBaseItemType(oTarget));
    sBaseItemType = GetStringByStrRef(StringToInt(s2daLookup));
    sTooltip += sBaseItemType;

    if (GetLocalInt(oTarget, "nAspectID"))
    {
        // We want to skip no aspect given and "None" entirely
        if(nAspectID > 1)
        {
            //string sAspect = GetAspectName(GetLocalInt(oTarget, "nAspectID"));
            sTooltip += "\n" + sAspect;
        }
    }

    float fWeight = IntToFloat(GetWeight(oTarget)) * 0.1f;
    if(fWeight > 0.5) // dont show weight if this or below
        sTooltip += "\n" + "Weight: " + FloatToString(fWeight, 4, 1);

    int nCharges = GetItemCharges(oTarget);
    if(nCharges > 0)
        sTooltip += "\n" + "Charges: " + IntToString(nCharges);

    while(GetIsItemPropertyValid(iprpTarget))
    {
        // if it has a duration, it is only temporary
        if(GetItemPropertyDurationRemaining(iprpTarget))
        {
            iprpTarget = GetNextItemProperty(oTarget);
            continue;
        }

        int nType = GetItemPropertyType(iprpTarget);

        // item types we want to skip and not print to the tooltip
        switch(nType){
            // base item weight reduction
            case 11 : iprpTarget = GetNextItemProperty(oTarget); continue;
            // additional weight
            case 81 : iprpTarget = GetNextItemProperty(oTarget); continue;
            // secret properties
            case 87 : iprpTarget = GetNextItemProperty(oTarget); continue;
        }

        int nSubtype = GetItemPropertySubType(iprpTarget);
        int nCostTable = GetItemPropertyCostTable(iprpTarget);
        int nCostTableValue = GetItemPropertyCostTableValue(iprpTarget);
        int nParam1 = GetItemPropertyParam1(iprpTarget);
        int nParam1Value = GetItemPropertyParam1Value(iprpTarget);

        string sParam1, sParam1Value, sType, sCostTable, sCostTableValue, sSubtype;
        string sBadstrref = "Bad Strref";

        sType = Get2DAString("ItemProps", "StringRef", nType);

        sSubtype = Get2DAString("itempropdef", "SubTypeResRef", nType);

        sSubtype = Get2DAString(sSubtype, "Name", nSubtype);
        sParam1 = Get2DAString("iprp_paramtable", "TableResRef", nParam1);
        sParam1Value = Get2DAString(sParam1, "Name", nParam1Value);

        sCostTable = Get2DAString("iprp_costtable", "Name", nCostTable);
        sCostTableValue = Get2DAString(sCostTable, "Name", nCostTableValue);

        // used for exceptions
        int nSkip = FALSE;

        // formatting for the new string that will be saved
        // define exceptions here that you want to rename/alter
        sTooltip += "\n";
        if((nType == 65) ||
           (nType == 64) ||
           (nType == 63)) 
        {
            // only useable by for class, alignment, race
            sTooltip += "OUB: ";
        }
        else if(nType == 1)
        {
            // armor class bonus
            nSkip = TRUE;
            sTooltip += GetStringByStrRef(StringToInt(sCostTableValue)) + " AC";
        }
        else if(nType == 2 || nType == 3 || nType == 4 || nType == 5)
        {
            // armor class bonus vs specific
            nSkip = TRUE;
            // bonus
            sTooltip += GetStringByStrRef(StringToInt(sCostTableValue)) + " AC";
            // versus what
            sTooltip += " vs. " + GetStringByStrRef(StringToInt(sSubtype));
        }
        else if(nType == 13) // spell slot for classes
        {
            sTooltip += "Spell Slot: ";
        }
        else if(nType == 15  || // cast spell iprp
                nType == 20) // damage immunity
        {
            // do nothing, leave blank
        }
        else if(nType == 37)
        {
            // used for broad immunities like crit, sneak, minda ffecting, etc
            sTooltip += "Immunity: ";
        }
        else if(nType == 40 || nType == 41)
        {
            // saves item property, comment out if you want it gone
            sTooltip += "Save vs. ";
        }
        else if(nType == 52)
        {
            // skills item property, comment out if you want it gone
            //sTooltip += "Skill: ";
        }
        else if(nType == 56)
        {
            // generic Attack Bonus
            nSkip = TRUE;
            sTooltip += GetStringByStrRef(StringToInt(sCostTableValue))  + " Attack Bonus";
        }
        else if(nType == 57 || nType == 58 ||nType == 59)
        {
            // Attack Bonus vs specific
            nSkip = TRUE;
            // bonus
            sTooltip += GetStringByStrRef(StringToInt(sCostTableValue)) + " AB";
            // versus what
            sTooltip += " vs. " + GetStringByStrRef(StringToInt(sSubtype));
        }
        else if(nType == 16)
        {
            // generic damage bonus
            nSkip = TRUE;
            // bonus
            string sDamageBonus = GetStringByStrRef(StringToInt(sCostTableValue));
            sTooltip += "+" + GetSubString(sDamageBonus, 0, FindSubString(sDamageBonus, "Damage"));
            // type
            sTooltip += GetStringByStrRef(StringToInt(sSubtype)) + " Damage";
        }
        else if(nType == 17 || nType == 18 ||nType == 19)
        {
            // specific damage bonus vs

            nSkip = TRUE;
            // bonus
            string sDamageBonus = GetStringByStrRef(StringToInt(sCostTableValue));
            sTooltip += "+" + GetSubString(sDamageBonus, 0, FindSubString(sDamageBonus, "Damage"));
            // type
            sTooltip += GetStringByStrRef(StringToInt(sParam1Value));
            // versus what
            sTooltip += " vs. " + GetStringByStrRef(StringToInt(sSubtype));
        }
        else
        {
            // non exception, print as tlk defines
            sTooltip += GetStringByStrRef(StringToInt(sType));

            if((nSubtype != 255)     ||
               (nParam1Value != 255) ||
               (nCostTableValue != 255) )
            {
                // add to anything with subtypes, excluding exceptions listed above
                sTooltip += ": ";
            }
        }

        string sFeedback;
        sFeedback += "nType: " + IntToString(nType) + " = " + GetStringByStrRef(StringToInt(sType)) + "\n";

        // find values assigned from 2das and tlk
        // this is everything from what alignment vs, to what value, and what spell is used
        if((nSubtype != 255 ||
           nParam1Value != 255 ||
           nCostTableValue != 255)
           && !nSkip)
        {

            if(nSubtype == 335)
            {
                sTooltip += "Unique Power (Self Only)";
            }
            else if(nSubtype != 255)
            {
                string sSubtypestrref = GetStringByStrRef(StringToInt(sSubtype));
                if(FindSubString(sSubtypestrref, sBadstrref, 0) != 0)
                {
                    sTooltip += sSubtypestrref;
                }

                if(nSubtype == 329)
                    sTooltip += "(Use)";
            }

            if(nParam1Value != 255)
            {
                string sParamstrref = GetStringByStrRef(StringToInt(sParam1Value));
                if(FindSubString(sParamstrref, sBadstrref, 0) != 0)
                {
                    sTooltip += " ";
                    sTooltip += sParamstrref;
                }
            }

            if(nCostTableValue != 255)
            {
                string sCoststrref = GetStringByStrRef(StringToInt(sCostTableValue));
                if(FindSubString(sCoststrref, sBadstrref, 0) != 0)
                {
                    sTooltip += " ";
                    sTooltip += sCoststrref;
                }
            }
        }

        sFeedback += "nSubtype: " + IntToString(nSubtype) + " = " + GetStringByStrRef(StringToInt(sSubtype)) + "\n";
        sFeedback += "nCostTable: " + IntToString(nCostTable) + " = " + GetStringByStrRef(StringToInt(sCostTable)) + "\n";
        sFeedback += "nCostTableValue: " + IntToString(nCostTableValue) + " = " + GetStringByStrRef(StringToInt(sCostTableValue)) + "\n";
        sFeedback += "nParam1: " + IntToString(nParam1) + " = " + GetStringByStrRef(StringToInt(sParam1)) + "\n";
        sFeedback += "nParam1Value: " + IntToString(nParam1Value) + " = " + GetStringByStrRef(StringToInt(sParam1Value));     

        if(nFeedback == TRUE)
            //SendMessageToAllDMs(sFeedback);
            SendMessageToPC(GetFirstPC(), sFeedback);

        //end, loop back with next property
        iprpTarget = GetNextItemProperty(oTarget);
    }

    SetObjectTextBubbleOverride(oTarget, OBJECT_UI_TEXT_BUBBLE_OVERRIDE_REPLACE, sPrename + "\n" + sTooltip);
}

Made more exceptions for the longest names I could find like Use, Attack Bonus, Armor Bonus, and Saves. Shorted up skills and more item properties. Will no longer show the weight of items that have a weight 0.5 or less.
#6
Suggestions / Re: Spells Suggestions Thread
February 19, 2024, 08:47:42 AM
Astral Blade - When it kills a target from the astral damage, can it add a cleave attack to the queue? Your blade was in alignment with the heavens this swing, cleaving through one foe and striking another.

Something fun to add since I've noticed it actually kills things with the 2 or 3 astral damage more often than you would expect, preventing characters with Cleave from triggering an additional attack at all, since it's considered a spell not an attack. Thought a fun compromise would be to just give it cleave in general when only that small bit of damage manages to kill a target, give it a bit more fun.
#7
Player Workshop / Re: Expanded Item Tooltips
February 19, 2024, 07:22:15 AM
//expands tooltip of the selected item
void ExpandItemTooltip(object oTarget);

void ExpandItemTooltip(object oTarget)
{
    string sTooltip, sBaseItemType, s2daLookup, sAspect, sPrename;
    int nAspectID;

    //turn this to FALSE when not testing
    int nFeedback = FALSE;

    if(GetLocalInt(oTarget, "nTooltipName") == FALSE)
        sPrename = GetName(oTarget, FALSE);
    else
        sPrename = GetLocalString(oTarget, "sTooltipPrename");

    if(!JsonGetLength(RegExpMatch("</c>", sPrename))) {
        sPrename = ColorString(sPrename, Orange());
    }

    itemproperty iprpTarget = GetFirstItemProperty(oTarget);

    // base item type
    // moved above aspect to break the color between name/aspect
    // removed extra padding
    s2daLookup = Get2DAString("baseitems", "Name", GetBaseItemType(oTarget));
    sBaseItemType = GetStringByStrRef(StringToInt(s2daLookup));
    sTooltip += "Item Type: " + sBaseItemType;

    if (GetLocalInt(oTarget, "nAspectID"))
    {
        // We want to skip no aspect given and "None" entirely
        if(nAspectID > 1)
        {
            string sAspect = GetAspectName(GetLocalInt(oTarget, "nAspectID"));
            sTooltip += "\n" + sAspect;
        }
    }

    float fWeight = IntToFloat(GetWeight(oTarget)) * 0.1f;
    if(fWeight > 0.1) // dont show weight if it's 0.1 or less
        sTooltip += "\n" + "Weight: " + FloatToString(fWeight, 4, 1);

    int nCharges = GetItemCharges(oTarget);
    if(nCharges > 0)
        sTooltip += "\n" + "Charges: " + IntToString(nCharges);

    while(GetIsItemPropertyValid(iprpTarget))
    {
        if(GetItemPropertyDurationRemaining(iprpTarget))
        {
            iprpTarget = GetNextItemProperty(oTarget);
            continue;
        }

        int nType = GetItemPropertyType(iprpTarget);

        // item types we want to skip and not print to the tooltip
        switch(nType){
            // base item weight reduction
            case 11 : iprpTarget = GetNextItemProperty(oTarget); continue;
            // additional weight
            case 81 : iprpTarget = GetNextItemProperty(oTarget); continue;
            // secret properties
            case 87 : iprpTarget = GetNextItemProperty(oTarget); continue;
        }

        int nSubtype = GetItemPropertySubType(iprpTarget);
        int nCostTable = GetItemPropertyCostTable(iprpTarget);
        int nCostTableValue = GetItemPropertyCostTableValue(iprpTarget);
        int nParam1 = GetItemPropertyParam1(iprpTarget);
        int nParam1Value = GetItemPropertyParam1Value(iprpTarget);

        string sParam1, sParam1Value, sType, sCostTable, sCostTableValue, sSubtype;
        string sBadstrref = "Bad Strref";

        sType = Get2DAString("ItemProps", "StringRef", nType);

        sSubtype = Get2DAString("itempropdef", "SubTypeResRef", nType);

        sSubtype = Get2DAString(sSubtype, "Name", nSubtype);
        sParam1 = Get2DAString("iprp_paramtable", "TableResRef", nParam1);
        sParam1Value = Get2DAString(sParam1, "Name", nParam1Value);

        sCostTable = Get2DAString("iprp_costtable", "Name", nCostTable);
        sCostTableValue = Get2DAString(sCostTable, "Name", nCostTableValue);

        // formatting for the new string that will be saved
        // define exceptions here that you want to rename/alter
        sTooltip += "\n";
        if((nType == 65) ||
           (nType == 64) ||
           (nType == 63))  // only useable by for class, alignment, race
        {
            sTooltip += "Only Useable By";
        }
        else if(nType == 13) // spell slot for classes
        {
            sTooltip += "Bonus Spell Slot";
        }
        else if(nType == 15) // cast spell iprp
        {
            sTooltip += "Use";
        }
        else
        {
            sTooltip += GetStringByStrRef(StringToInt(sType));
        }

        string sFeedback;
        sFeedback += "nType: " + IntToString(nType) + " = " + GetStringByStrRef(StringToInt(sType)) + "\n";

        if((nSubtype != 255) ||
           (nParam1Value != 255) ||
           (nCostTableValue != 255))
        {
            sTooltip += ": ";

            if(nSubtype == 335)
            {
                sTooltip += "Unique Power (Self Only)";
            }
            else if(nSubtype != 255)
            {
                string sSubtypestrref = GetStringByStrRef(StringToInt(sSubtype));
                if(FindSubString(sSubtypestrref, sBadstrref, 0) != 0)
                {
                    sTooltip += sSubtypestrref;
                }

                if(nSubtype == 329)
                    sTooltip += ",";
            }

            if(nParam1Value != 255)
            {
                string sParamstrref = GetStringByStrRef(StringToInt(sParam1Value));
                if(FindSubString(sParamstrref, sBadstrref, 0) != 0)
                {
                    sTooltip += " ";
                    sTooltip += GetStringByStrRef(StringToInt(sParam1Value));
                }
            }

            if(nCostTableValue != 255)
            {
                string sCoststrref = GetStringByStrRef(StringToInt(sCostTableValue));
                if(FindSubString(sCoststrref, sBadstrref, 0) != 0)
                {
                    sTooltip += " ";
                    sTooltip += GetStringByStrRef(StringToInt(sCostTableValue));
                }
            }

            sFeedback += "nSubtype: " + IntToString(nSubtype) + " = " + GetStringByStrRef(StringToInt(sSubtype)) + "\n";
            sFeedback += "nCostTable: " + IntToString(nCostTable) + " = " + GetStringByStrRef(StringToInt(sCostTable)) + "\n";
            sFeedback += "nCostTableValue: " + IntToString(nCostTableValue) + " = " + GetStringByStrRef(StringToInt(sCostTableValue)) + "\n";
            sFeedback += "nParam1: " + IntToString(nParam1) + " = " + GetStringByStrRef(StringToInt(sParam1)) + "\n";
            sFeedback += "nParam1Value: " + IntToString(nParam1Value) + " = " + GetStringByStrRef(StringToInt(sParam1Value));
        }
        //end, loop back with next property
        iprpTarget = GetNextItemProperty(oTarget);

        if(nFeedback == TRUE)
            SendMessageToAllDMs(sFeedback);
    }

    SetObjectTextBubbleOverride(oTarget, OBJECT_UI_TEXT_BUBBLE_OVERRIDE_REPLACE, sPrename + "\n" + sTooltip);

}

Updated with some exceptions and hopefully clean up a lot of the erroneous items that there are currently. Also moved Item Type to be above the aspect of an item, replacing the blank space that used to be there and it looks better there I think. Alternatively can comment it out.

Updated from the one Abala most recently posted to discord.
#8
Player Workshop / Re: Expanded Item Tooltips
February 18, 2024, 09:52:41 PM
This is because some people are still running 8193.35, which will not show these expanded tooltips in an inventory. If they are on 8193.36, it will show on both the ground and in inventories. They would need to update to the latest version of Enhanced Edition.
#9
Player Workshop / Re: Expanded Item Tooltips
February 18, 2024, 02:12:48 AM
This was added tentatively to EFU, so if you see any issues or errors with it, please post here so I can try to fix them

This also includes any suggestions regarding it, or what is bad about the design/change.

There's nothing I can do about how wide or tall the box can get, unfortunately. That's always been an issue with long named objects.
#10
Suggestions / Re: Spells Suggestions Thread
February 03, 2024, 06:52:10 PM
Can the spell Prayer cast your selected Turn Undead in addition to it's base effects? And maybe double the duration of Prayer for Priests, to give them some more incentive to use it?

Other ideas for some buffs to it might be for good/neutral, players heal 1d4 health per round. And enemies take 1d4 negative damage per round? Both perhaps?
#11
Suggestions / Re: Random / Large VP suggestion thread
January 28, 2024, 07:42:21 AM
I do think rogues having something like a x/day ability to make sneak attacks against sneak immune, and maybe even their current target. Sanctuary as a free action scaling it's DC and effects based on your rogue level? Would be really nice for melee rogue survivability and give them a much needed escape tool
#12
Suggestions / Re: Random / Large VP suggestion thread
January 28, 2024, 07:29:19 AM
QuoteGive Rangers ITWF at 8 instead of 9 to match the prior change / requirement to 8 AB

- Give Rangers second FE at 4, and third at 8

- Rangers maintain their bonuses in medium armor instead of just light
Quote- Chain shirts are considered light armor

Rangers seem great as they are now though and have a great scaling from level to level though:

Level 6: +1 damage and AB to FE, FE perks
Level 7: nothing new, gets 10 in skills (5 for cross class)
Level 8: Ranger 2 slot, which is now enhance ability...
Level 9: +2 damage and AB to FE, improved two weapon fighting
Level 10: third favored enemy, giving +3 AB and +3 damage to a new race, plus the associated perks

I think moving those will just make people entirely drop pure ranger after Ranger 8, opting for something with Tumble and UMD for the 2 other levels. Maybe something that gives sneak attacks for your improved two weapon fighting.

QuotePure clerics need a little something to step outside of the massively consistent role.
Tithe 1/day / 3 levels. By using /c tithe, you sacrifice 50 GP to gain ONE of the following as a /free action/:

* 1 Bonus APR for 2 turns
* +3 true damage for 2 turns
* +4 regen / round for 2 turns
* A divine explosion, dealing 2dlvl true damage to enemies in a colossal radius.
* Divine stand - All allies in a large radius are bestowed with Contingency for 2 turns
* etc... insert other ideas

God no. I think Clerics are still one of the best classes and they have a lot of variety. Their biggest issue is more that people don't portray them much and just play buff bots. I don't see how this fixes that.

They don't need the ability to get back 4 APR at level 8, they dont need a second level 9 divine favor that lasts twice as long, and they don't need an entire Druidic Channeling perk.

#13
General Discussion / Re: DM Appreciation Day - Abala
October 24, 2023, 01:56:45 AM
Thank you Abala, for all the fun stories you've shared with us as a player and all of the work you've done as a DM. You are someone who can eloquently drop a few lines, gather all the attention in a room, and make the game more engaging for everyone involved. That's regardless of which client you're playing through.

So really, thank you.
#14
Halfbrood plays a huge part of what makes EFU unique for me.

Hilarious as a player and always willing to invite someone new along, super friendly. Helped me understand a lot more about EFU and was easily one of the kindest people to not just me when I was still new.

Incredibly inventive and regularly makes the game feel fresh with the content he creates. I am always excited to hear he's working on something and has never disappointed in the delivery.

Thank you Halfbrood, for everything you have done, and will eventually do.
#15
Suggestions / Re: Combining Wands
September 28, 2023, 07:37:14 PM
Something like being able to transfer 1dX charges from one wand to another with a check and minor cost would be very interesting. Prerequisite being having the Craft Wand skill.