Howdy, Stranger!

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

Categories

Neverwinter Nights: Enhanced Edition has been released! Visit nwn.beamdog.com to make an order. NWN:EE FAQ is available.
Soundtracks for BG:EE, SoD, BG2:EE, IWD:EE, PST:EE are now available in the Beamdog store.
Attention, new and old users! Please read the new rules of conduct for the forums, and we hope you enjoy your stay!

Get Spell Name without 2da

badstrrefbadstrref Member Posts: 103
edited January 14 in Builders - Scripting
For my dispeling script I wanted to provide feedback to players as to wich spell was being targeted, and the first option was to use

string Get2DAString(string s2DA, string sColumn, int nRow)

wich shouldn't be used too heavily... sadly as offered it can only be used inside a loop for my needs, and spells.2da is almost 0.6mb size

My second option was to "cache" the 2da file and relevant info (Label, or spell name) inside the local data of an object, this would require heavy read / SetLocalString (839 times), but only once at module load
void SetupSpellsNameByID()
{
    object oHolder = GetObjectByTag("_SPELLS_ID_2DA_");

    int i = 0; int n= 839;
    for(i; i<=n; i++)
    {
      SetLocalString(oHolder, IntToString(i), Get2DAString("spells", "Label", i));
    }
}
and this was still bad, so the last option, and best, was to log all spells inside a basic function, but to build that function with 839 lines was a daunting task, instead of going by hand I wrote a script that will generate the function itself, write it inside the Logs, and then I would just copy paste it to use inside the toolset.
void LogBuildFunctionGetSpellName()
{
    string s = "\n"+"string GetSpellName(int i)"+"\n";
           s+= "{"+"\n";
           s+= "string s;"+"\n";
           s+= "switch(i)"+"\n";
           s+= "{"+"\n";


    int i = 0; int n= 839;
    for(i; i<=n; i++)
    {
        s+= "case "+IntToString(i)+" : s = \""+Get2DAString("spells", "Label", i)+"\"; break;"+"\n";
    }

    s+= "}"+"\n"; // end switch
    s+= "return s;"+"\n";
    s+= "}"+"\n";// end whole function
    WriteTimestampedLogEntry(s);
}

Result :
string GetSpellName(int i)
{
string s;
switch(i)
{
case 0 : s = "Acid_Fog"; break;
case 1 : s = "Aid"; break;
case 2 : s = "Animate_Dead"; break;
case 3 : s = "Barkskin"; break;
case 4 : s = "Bestow_Curse"; break;
case 5 : s = "Blade_Barrier"; break;
case 6 : s = "Bless"; break;
case 7 : s = "Bless_Weapon"; break;
case 8 : s = "Blindness_and_Deafness"; break;
case 9 : s = "Bulls_Strength"; break;
case 10 : s = "Burning_Hands"; break;
case 11 : s = "Call_Lightning"; break;
case 12 : s = "Calm_Emotions"; break;
case 13 : s = "Cats_Grace"; break;

... 

case 833 : s = "PLAYER_TOOL_04"; break;
case 834 : s = "PLAYER_TOOL_05"; break;
case 835 : s = "PLAYER_TOOL_06"; break;
case 836 : s = "PLAYER_TOOL_07"; break;
case 837 : s = "PLAYER_TOOL_08"; break;
case 838 : s = "PLAYER_TOOL_09"; break;
case 839 : s = "PLAYER_TOOL_10"; break;
}
return s;
}

Then to remove the "_" characters you can use notepad++ and ctrl+f / replace tab "_" to " " (space)

Final result
string GetSpellName(int i)
{
string s;
switch(i)
{
case 0 : s = "Acid Fog"; break;
case 1 : s = "Aid"; break;
case 2 : s = "Animate Dead"; break;
case 3 : s = "Barkskin"; break;
case 4 : s = "Bestow Curse"; break;
case 5 : s = "Blade Barrier"; break;
case 6 : s = "Bless"; break;
case 7 : s = "Bless Weapon"; break;
case 8 : s = "Blindness and Deafness"; break;
case 9 : s = "Bulls Strength"; break;
case 10 : s = "Burning Hands"; break;
case 11 : s = "Call Lightning"; break;
case 12 : s = "Calm Emotions"; break;
case 13 : s = "Cats Grace"; break;
case 14 : s = "Chain Lightning"; break;
case 15 : s = "Charm Monster"; break;
case 16 : s = "Charm Person"; break;
case 17 : s = "Charm Person or Animal"; break;
case 18 : s = "Circle of Death"; break;
case 19 : s = "Circle of Doom"; break;
case 20 : s = "Clairaudience and Clairvoyance"; break;
case 21 : s = "Clarity"; break;
case 22 : s = "Cloak of Chaos"; break;
case 23 : s = "Cloudkill"; break;
case 24 : s = "Color Spray"; break;

...

Post edited by badstrref on

Comments

  • DazDaz Member Posts: 31
    Get2daString() should be fine to use these days, it caches the result in memory the first time it's called.

    badstrref
  • badstrrefbadstrref Member Posts: 103
    edited January 14
    Daz said:

    Get2daString() should be fine to use these days, it caches the result in memory the first time it's called.

    Ah ! I didn't knew about that!

    (nwnlexcion : "Get2daString() now is cached the first time it is called, into the memory of the computer. Basically - you can now use this function in a loop with a lot less noticeable loss of speed!")

    was tricked by the toolset's description :

    // Gets a value from a 2DA file on the server and returns it as a string
    // avoid using this function in loops
    // - s2DA: the name of the 2da file, 16 chars max
    // - sColumn: the name of the column in the 2da
    // - nRow: the row in the 2da
    // * returns an empty string if file, row, or column not found

    thanks

  • SherincallSherincall Member Posts: 340
    Always profile before (and after) optimizing. Chances are, you'll put your 800+ line function in an include file, which will be picked up by all the scripts. Now each script has inflated in size by those 800+ strings and the associated switch table.
    This in turn makes your script caching slower, causing all your scripts to be slower. It is possible this optimization had a net negative result on the performance of your module.
    This is a stretch, as these kinds of things are totally negligible in terms of perf, but illustrates the point of "premature optimization is the root of all evil". Always profile before (and after) optimizing.

  • badstrrefbadstrref Member Posts: 103
    edited January 14

    Always profile before (and after) optimizing. Chances are, you'll put your 800+ line function in an include file, which will be picked up by all the scripts. Now each script has inflated in size by those 800+ strings and the associated switch table.
    This in turn makes your script caching slower, causing all your scripts to be slower. It is possible this optimization had a net negative result on the performance of your module.
    This is a stretch, as these kinds of things are totally negligible in terms of perf, but illustrates the point of "premature optimization is the root of all evil". Always profile before (and after) optimizing.

    Interesting stuff, I don't know how to profile (bench?) though, concerning the include file, i will use it only in one file that all dispels and breaches refers to with ExecuteScript and GetSpellID to differenciate them in terms of power etc

Sign In or Register to comment.