Polymorph Self



  • Just a place to keep notes between me and sigriam for communication whiel we're working on it.

    This spell functions like alter self, except that you change into another form of living creature. The new form may be of any of the following types: aberration, animal, dragon, fey, giant, humanoid, magical beast, monstrous humanoid, ooze, plant, or vermin. The assumed form can’t have more Hit Dice than your caster level, to a maximum of 15 HD at 15th level. You can’t assume a form smaller than Fine, nor can you assume an incorporeal or gaseous form.

    To-do
    Seth~Make Sahuagin polymorph lines.
    (http://www.d20srd.org/srd/monsters/sahuagin.htm cause NWN's are using class levels)

    Sigriam - Determine creatures hit dice for up to 15, not including Undead, Constructs, Elementals, outsiders, Shapechangers, or Gaseous/Incorporeals.



  • The list, v1. I'll format this properly tomorrow.

    Abberations:
    211 Drider 6
    307 Female Drider 6
    212 Ettercap 5
    213 Eyeball 1
    214 Hook horror 5
    215 Intellect devourer 6
    216 Mind Flayer 8
    217 Umber Hulk 8
    218 Will-O'-Wisp 9
    
    Giants:
    174 Ogre 4
    175 Troll 6
    
    Humanoid:
    152 Bugbear 3
    157 Goblin 1
    163 Hobgoblin 1
    165 Kobold 1
    312 Troglodyte 2
    171 Yuan-ti 6
    170 Lizardfolk Warrior 2
    172 Minotaur 6
    166 Orc 1
    158 Gnoll 2
    167 Medusa 6
    168 Sea Hag 3
    169 Stinger 4
    6 Pixie 1
    
    Misc:
    208 Gelatinous Cube 4
    173 Harpy 7
    
    Magical Beasts:
    197 Basilisk 6
    190 Deep Rothe 2
    191 Gargoyle 4
    192 Gorgon 8
    193 Gynosphinx 8
    194 Krenshar 2
    195 Manticore 6
    
    Insects:
    178 Stag Beetle 7
    179 Stink Beetle 3
    177 Fire Beetle 1
    176 Bombardier Beetle 2
    180 Giant Spider 4
    196 Phase Spider 5
    181 Sword Spider 3
    
    Dragons:
    227 Wyrmling Blue Dragon 6
    226 Wyrmling Black Dragon 4
    228 Wyrmling Brass Dragon 4
    229 Wyrmling Bronze Dragon 6
    231 Wyrmling Gold Dragon 8
    230 Wyrmling Copper Dragon 5
    232 Wyrmling Green Dragon 5
    233 Wyrmling Red Dragon 7
    234 Wyrmling Silver Dragon 7
    235 Wyrmling White Dragon 3
    
    Animals:
    131 Black Bear 3
    21 Brown Bear 6
    148 Polar Bear 8
    147 Grizzly Bear 8
    40 Chicken 1
    133 Falcon 1
    325 Parrot 1
    26 Penguin 1
    134 Raven 1
    326 Seagull 1
    130 Dog 2
    257 Winter Wolf 6
    23 Wolf 2
    135 Cougar 3
    136 Crag Cat 3
    137 Jaguar 5
    138 Leopard 3
    139 Lion 5
    22 Panther 3
    144 Rat 1
    143 Ox 1
    327 Horse 1
    25 Badger 1
    140 Bat 1
    328 Black Cormyrian Cobra 3
    24 Boar 3
    27 Cow 1
    142 Deer 1
    37 Dire Badger 3
    36 Dire Boar 7
    149 Dire Rat 1
    40 Chicken 1
    258 Worg 4
    35 Dire Wolf 6
    145 White Stag 1
    
    --- Not found in 2da ---
    Dryad 2
    Grig 1
    Nixie 1
    Nymph 3
    Satyr 5
    Ochre Jelly 2-6
    Gray Ooze 3
    Stirge 1
    Blink Dog 4
    


  • By level, and added a few that got missed.

    Pixie's the default option for a non-setting, looks like (since it was in nwn's original spell, it's less confusing then using an orc or whatall). And it's impossible to not have enough Hit Dice to turn into one, even if you're a level 1 activating a item.

    325 Parrot 1
    326 Seagull 1
    327 Horse 1
    328 Black Cormyrian Cobra 3
    aren't in the list at the moment, since I made the lines locally, but on coa the numbers will be different (since I know a few morphs were added in between)

    Level 1
    Eyeball 213
    Goblin 157
    Hobgoblin 163
    Kobold 165
    Orc 166
    Pixie - Needs Line Created
    Fire Beetle 177
    Chicken 40
    Falcon 133
    Penguin 26
    Raven 134
    Rat 144
    Ox 143
    Badger 25
    Bat 140
    Cow 27
    Deer 142
    Dire rat 149
    Chicken 40
    White stag 145
    
    Level 2
    Troglodyte 312
    Lizardfolk 170
    Gnoll 158
    Sahuagin - Needs Line Created
    Deep Rothe 190
    Krenshar 194
    Bombadier Beetle 176
    Faerie Dragon 224
    Pseudodragon 225
    Dog 130
    Wolf 23
    Dryad  - Needs Line Created
    Ochre Jelly - Needs Line Created
    
    Level 3
    Bugbear 152
    Sea Hag 168
    Stink Beetle 179
    Sword spider 181
    Wyrmling White Dragon 235
    Black Bear 131
    Cougar 135
    Crag Cat 136
    Leopard 138
    Panther 22
    Boar 24
    Dire badger 37
    Nymph - Needs Line Created
    Gray Ooze - Needs Line Created
    
    Level 4
    Ogre 174
    Stinger 169
    Gelatinous Cube 208
    Gargoyle 191
    Giant spider 180
    Wyrmling Black Dragon 226
    Wyrmling Brass Dragon 228
    Worg 258
    Blink Dog - Needs Line Created
    
    Level 5
    Ettercap 212
    Hook Horror 214
    Cockatrice 189
    Wyrmling Copper Dragon 230
    Wyrmling Green Dragon 232
    Jaguar 137
    Lion 139
    Satyr - Needs Line Created
    
    Level 6
    Drider 211
    Female Drider 307
    Intellect Devourerer 215
    Troll 175
    Yuan-ti 171
    Minotaur 172
    Medusa 167
    Baislisk 197
    Manticore 195
    Wyrmling Blue Dragon 227
    Wyrmling Bronze Dragon 229
    Brown Bear 21
    Winter Wolf 257
    Dire wolf 35
    
    Level 7
    Harpy 173
    Stag Beetle 178
    Wyrmling Red Dragon 233
    Wyrmling Silver Dragon 234
    Dire boar 36
    
    Level 8
    Mind Flayer 216
    Umber Hulk 217
    Gorgon 192
    Sphinx 193
    Wyrmling Gold Dragon 231
    Polar Bear 148
    Grizzly Bear 147
    
    Level 9
    Battle Devourer 209
    Will O Wisp 218
    Bullette 313
    
    Level 10
    Ettin 187
    Grey Render 221
    Dire Spider 188
    
    Level 11
    Beholder 210
    
    Level 12
    Hill Giant 222
    Wyvern - Needs Line Created
    Dire Bear 33
    
    Level 13
    
    Level 14
    Frost Giant 259 308/Fem
    
    Level 15
    Fire Giant 289, 309/Female
    


  • Here's the scripts. They work, but need adjusting:

    • Local variable names
    • Store variable on token, not on pc
    • Shuffle critters around for balance
    • Not optimized (goes through each if each time) - best way to do it is "if (nMaxHD >= && nPoly == 0)"
    • Add more critters once they are in the 2da
    • Merge item properties?
    • Assign action cast spell if ends with "!" or something similar
    • Merge with other CoA changes?

    In the onPlayerChat event:

    object oPC = GetPCChatSpeaker();
        string sCommand = GetPCChatMessage();
    
        if (GetSubString(sCommand, 1, 2) == "ps")
        {
            string sPolyFormID = GetSubString(sCommand, 4, GetStringLength(sCommand) - 4);
            SetLocalString(oPC, "sPolyFormID", sPolyFormID);
            SendMessageToPC(oPC, "Poly set at: " + sPolyFormID);
            //AssignCommand(oPC, ActionCastSpellAtObject(SPELL_POLYMORPH_SELF));
        }
    

    Spell script I used and tested:```
    #include "x2_inc_spellhook"

    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
    int nSpell = GetSpellId();
    object oTarget = GetSpellTargetObject();
    effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH);
    effect ePoly;
    int nPoly = 0;
    string sFormID = GetLocalString(OBJECT_SELF, "sPolyFormID");
    
    int nCasterLevel = GetCasterLevel(OBJECT_SELF);
    int nTargetHD = GetHitDice(oTarget);
    int nMaxHD = (nCasterLevel < nTargetHD) ? nCasterLevel : nTargetHD;
    
    int nMetaMagic = GetMetaMagicFeat();
    int nDuration = nCasterLevel;
    //Enter Metamagic conditions
    if (nMetaMagic == METAMAGIC_EXTEND) {
        nDuration = nDuration *2; //Duration is +100%
    }
    
    //Determine Polymorph type
    
    // HD 1
    if (nMaxHD >= 1) {
        if(GetStringUpperCase(sFormID) == "EYEBALL")            { nPoly =  213; }
        else if(GetStringUpperCase(sFormID) == "GOBLIN")        { nPoly =  157; }
        else if(GetStringUpperCase(sFormID) == "HOBGOBLIN")     { nPoly =  163; }
        else if(GetStringUpperCase(sFormID) == "KOBOLD")        { nPoly =  165; }
        else if(GetStringUpperCase(sFormID) == "ORC")           { nPoly =  166; }
        else if(GetStringUpperCase(sFormID) == "FIRE BEETLE")   { nPoly =  177; }
        else if(GetStringUpperCase(sFormID) == "CHICKEN")       { nPoly =  40; }
        else if(GetStringUpperCase(sFormID) == "FALCON")        { nPoly =  133; }
        else if(GetStringUpperCase(sFormID) == "PENGUIN")       { nPoly =  26; }
        else if(GetStringUpperCase(sFormID) == "RAVEN")         { nPoly =  134; }
        else if(GetStringUpperCase(sFormID) == "RAT")           { nPoly =  144; }
        else if(GetStringUpperCase(sFormID) == "OX")            { nPoly =  143; }
        else if(GetStringUpperCase(sFormID) == "BADGER")        { nPoly =  25; }
        else if(GetStringUpperCase(sFormID) == "BAT")           { nPoly =  140; }
        else if(GetStringUpperCase(sFormID) == "COW")           { nPoly =  27; }
        else if(GetStringUpperCase(sFormID) == "DEER")          { nPoly =  142; }
        else if(GetStringUpperCase(sFormID) == "DIRE RAT")      { nPoly =  149; }
        else if(GetStringUpperCase(sFormID) == "CHICKEN")       { nPoly =  40; }
        else if(GetStringUpperCase(sFormID) == "WHITE STAG")    { nPoly =  145; }
    }
    
    // HD 2
    if (nMaxHD >= 2) {
        if(GetStringUpperCase(sFormID) == "TROGLODYTE")         { nPoly =  312; }
        else if(GetStringUpperCase(sFormID) == "LIZARDFOLK")    { nPoly =  170; }
        else if(GetStringUpperCase(sFormID) == "GNOLL")         { nPoly =  158; }
        else if(GetStringUpperCase(sFormID) == "DEEP ROTHE")    { nPoly =  190; }
        else if(GetStringUpperCase(sFormID) == "KRENSHAR")      { nPoly =  194; }
        else if(GetStringUpperCase(sFormID) == "BOMBADIER BEETLE") { nPoly =  176; }
        else if(GetStringUpperCase(sFormID) == "FAERIE DRAGON") { nPoly =  224; }
        else if(GetStringUpperCase(sFormID) == "PSEUDODRAGON")  { nPoly =  225; }
        else if(GetStringUpperCase(sFormID) == "DOG")           { nPoly =  130; }
        else if(GetStringUpperCase(sFormID) == "WOLF")          { nPoly =  23; }
    }
    
    // HD 3
    if (nMaxHD >= 3) {
        if(GetStringUpperCase(sFormID) == "BUGBEAR")            { nPoly =  152; }
        else if(GetStringUpperCase(sFormID) == "SEA HAG")       { nPoly =  168; }
        else if(GetStringUpperCase(sFormID) == "STINK BEETLE")  { nPoly =  179; }
        else if(GetStringUpperCase(sFormID) == "SWORD SPIDER")  { nPoly =  181; }
        else if(GetStringUpperCase(sFormID) == "WYRMLING WHITE DRAGON") { nPoly =  235; }
        else if(GetStringUpperCase(sFormID) == "BLACK BEAR")    { nPoly =  131; }
        else if(GetStringUpperCase(sFormID) == "COUGAR")        { nPoly =  135; }
        else if(GetStringUpperCase(sFormID) == "CRAG CAT")      { nPoly =  136; }
        else if(GetStringUpperCase(sFormID) == "LEOPARD")       { nPoly =  138; }
        else if(GetStringUpperCase(sFormID) == "PANTHER")       { nPoly =  22; }
        else if(GetStringUpperCase(sFormID) == "BOAR")          { nPoly =  24; }
        else if(GetStringUpperCase(sFormID) == "DIRE BADGER")   { nPoly =  37; }
    }
    
    // HD 4
    if (nMaxHD >= 4) {
        if(GetStringUpperCase(sFormID) == "OGRE")               { nPoly =  174; }
        else if(GetStringUpperCase(sFormID) == "STINGER")       { nPoly =  169; }
        else if(GetStringUpperCase(sFormID) == "GELATINOUS CUBE") { nPoly =  208; }
        else if(GetStringUpperCase(sFormID) == "GARGOYLE")      { nPoly =  191; }
        else if(GetStringUpperCase(sFormID) == "GIANT SPIDER")  { nPoly =  180; }
        else if(GetStringUpperCase(sFormID) == "WYRMLING BLACK DRAGON") { nPoly =  226; }
        else if(GetStringUpperCase(sFormID) == "WYRMLING BRASS DRAGON") { nPoly =  228; }
        else if(GetStringUpperCase(sFormID) == "WORG")          { nPoly =  258; }
    }
    
    // HD 5
    if (nMaxHD >= 5) {
        if(GetStringUpperCase(sFormID) == "ETTERCAP")           { nPoly =  212; }
        else if(GetStringUpperCase(sFormID) == "HOOK HORROR")   { nPoly =  214; }
        else if(GetStringUpperCase(sFormID) == "COCKATRICE")    { nPoly =  189; }
        else if(GetStringUpperCase(sFormID) == "WYRMLING COPPER DRAGON") { nPoly =  230; }
        else if(GetStringUpperCase(sFormID) == "WYRMLING GREEN DRAGON") { nPoly =  232; }
        else if(GetStringUpperCase(sFormID) == "JAGUAR")        { nPoly =  137; }
        else if(GetStringUpperCase(sFormID) == "LION")          { nPoly =  139; }
    }
    
    // HD 6
    if (nMaxHD >= 6) {
        if(GetStringUpperCase(sFormID) == "DRIDER")             { nPoly =  211; }
        else if(GetStringUpperCase(sFormID) == "FEMALE DRIDER") { nPoly =  307; }
        else if(GetStringUpperCase(sFormID) == "INTELLECT DEVOURERER") { nPoly =  215; }
        else if(GetStringUpperCase(sFormID) == "TROLL")         { nPoly =  175; }
        else if(GetStringUpperCase(sFormID) == "YUAN-TI")       { nPoly =  171; }
        else if(GetStringUpperCase(sFormID) == "MINOTAUR")      { nPoly =  172; }
        else if(GetStringUpperCase(sFormID) == "MEDUSA")        { nPoly =  167; }
        else if(GetStringUpperCase(sFormID) == "BAISLISK")      { nPoly =  197; }
        else if(GetStringUpperCase(sFormID) == "MANTICORE")     { nPoly =  195; }
        else if(GetStringUpperCase(sFormID) == "WYRMLING BLUE DRAGON") { nPoly =  227; }
        else if(GetStringUpperCase(sFormID) == "WYRMLING BRONZE DRAGON") { nPoly =  229; }
        else if(GetStringUpperCase(sFormID) == "BROWN BEAR")    { nPoly =  21; }
        else if(GetStringUpperCase(sFormID) == "WINTER WOLF")   { nPoly =  257; }
        else if(GetStringUpperCase(sFormID) == "DIRE WOLF")     { nPoly =  35; }
    }
    
    // HD 7
    if (nMaxHD >= 7) {
        if(GetStringUpperCase(sFormID) == "HARPY")              { nPoly =  173; }
        else if(GetStringUpperCase(sFormID) == "STAG BEETLE")   { nPoly =  178; }
        else if(GetStringUpperCase(sFormID) == "WYRMLING RED DRAGON") { nPoly =  233; }
        else if(GetStringUpperCase(sFormID) == "WYRMLING SILVER DRAGON") { nPoly =  234; }
        else if(GetStringUpperCase(sFormID) == "DIRE BOAR")     { nPoly =  36; }
    }
    
    // HD 8
    if (nMaxHD >= 8) {
        if(GetStringUpperCase(sFormID) == "MIND FLAYER")        { nPoly =  216; }
        else if(GetStringUpperCase(sFormID) == "UMBER HULK")    { nPoly =  217; }
        else if(GetStringUpperCase(sFormID) == "GORGON")        { nPoly =  192; }
        else if(GetStringUpperCase(sFormID) == "SPHINX")        { nPoly =  193; }
        else if(GetStringUpperCase(sFormID) == "WYRMLING GOLD DRAGON") { nPoly =  231; }
        else if(GetStringUpperCase(sFormID) == "POLAR BEAR")    { nPoly =  148; }
        else if(GetStringUpperCase(sFormID) == "GRIZZLY BEAR")  { nPoly =  14; }
    }
    
    // HD 9
    if (nMaxHD >= 9) {
        if(GetStringUpperCase(sFormID) == "BATTLE DEVOURER")    { nPoly =  209; }
        else if(GetStringUpperCase(sFormID) == "WILL O WISP")   { nPoly =  218; }
        else if(GetStringUpperCase(sFormID) == "BULLETTE")      { nPoly =  313; }
    }
    
    // HD 10
    if (nMaxHD >= 10) {
        if(GetStringUpperCase(sFormID) == "ETTIN")              { nPoly =  187; }
        else if(GetStringUpperCase(sFormID) == "GREY RENDER")   { nPoly =  221; }
        else if(GetStringUpperCase(sFormID) == "DIRE SPIDER")   { nPoly =  188; }
    }
    
    // HD 11
    if (nMaxHD >= 11) {
        if(GetStringUpperCase(sFormID) == "BEHOLDER") { nPoly =  210; }
    }
    
    // HD 12
    if (nMaxHD >= 12) {
        if(GetStringUpperCase(sFormID) == "HILL GIANT")     { nPoly =  222; }
        else if(GetStringUpperCase(sFormID) == "DIRE BEAR") { nPoly =  33; }
    }
    
    // HD 13
    if (nMaxHD >= 14) {
    
    }
    
    // HD 14
    if (nMaxHD >= 14) {
        if(GetStringUpperCase(sFormID) == "FROST GIANT")            { nPoly =  259; }
        else if(GetStringUpperCase(sFormID) == "FROST GIANT FEMALE"){ nPoly =  308; }
    }
    
    // HD 15
    if (nMaxHD >= 15) {
        if(GetStringUpperCase(sFormID) == "FIRE GIANT")            { nPoly =  289; }
        else if(GetStringUpperCase(sFormID) == "FIRE GIANT FEMALE"){ nPoly =  309; }
    }
    
    //couldn't determine the form and npoly is still 0
    if (nPoly == 0) {
        SendMessageToPC(OBJECT_SELF, "Unknown form type. Check spelling");}
    else if (nPoly > 0) {
        ePoly = EffectPolymorph(nPoly);
        //Fire cast spell at event for the specified target
        SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELL_POLYMORPH_SELF, FALSE));
    
        //Apply the VFX impact and effects
        AssignCommand(oTarget, ClearAllActions()); // prevents an exploit
        ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ePoly, oTarget, TurnsToSeconds(nDuration));
    }
    

    }



  • What about converting to the poly-number and the HD-needed for it right away when the ".ps WhatEver" is given, and storing those two numbers instead of the string? As you'd usually set your favorite form and then stick to that, it would save a lot of repeated conversions at casting time, and you could e.g. catch a typo in '.ps BAISLISK' before you try and cast the spell, or tell the player it won't work for some other reason. (like insufficient HD) You'd just have to do a quick double check if the player is allowed to use that shape at casting time.

    Also, why not just convert the string to uppercase once at the start of the conversion block, and store the result in sFormID:

    string sFormID = GetStringUpperCase(GetLocalString(OBJECT_SELF, "sPolyFormID"));

    Saves you doing the same conversion over and over again and makes the if statements more readable.

    The conversion code could also just compare as many characters as are actually in the argument given, and pick the first match, so you wouldn't have to type out the whole word, just a unique enough prefix (and add some 'aliases' for commonly misspelled names, and things like "Green Dragon Wyrmling" with the most significant bit first..)

    Actually you could even just publish a list of the Poly numbers and let people do their own conversions , as it's easier to memorize/refer to a note for your favorite few integers than typing in all those words all the time (this is used by casters that likely don't have many quickslots free…), I'd prefer typing .ps 231 over .ps WYRMLING GOLD DRAGON

    I think TestStringAgainstPattern("*n",sFormID) can be used to detect if the sFormID is already a number and try to use it as is.

    --
    Note that you actually did miss-spell BASILISK in the script. (and at least INTELLECT DEVOURER too.)



  • @omg:

    • Merge item properties?

    PolySelf doesn't do that one, it's one of them thigns that makes wildshape and shifters useful

    A feedback message if they try and store a form they don't enough HD to turn into too.



  • A feedback message if they try and store a form they don't enough HD to turn into too.

    convert the string to uppercase once at the start

    detect if the sFormID is already a number and try to use it as is

    some 'aliases' for commonly misspelled names

    Great ideas. I did want to implement the first two, but was eager to get it working.

    What about converting to the poly-number and the HD-needed for it right away when the ".ps WhatEver" is given, and storing those two numbers instead of the string?

    I wanted to keep OnPlayerChat clean, and put the list in the polymorph spell script. This idea would save very little processing time I think - best keep it this way for readability.



  • Yeah, OnPlayerChat is pretty crowded, and only likely to get moreso. Dumping 100some line tables into it would get pretty bloated to try and find any sort of bugs.



  • I still think you want to make sure the value set is valid at the time it is being set or the caster will get a nasty surprise when polymorphing in the heat of battle, and by then any feedback wouldn't be as useful anymore

    You can keep the player chat 'clean' (although according to other posts it is already pretty messy: /forum/viewtopic.php?t=107485&start=3 ) the way set kept the wildshape one clean, just call a worker script (or if the compiler/preprocessor being used allows it, use an include file.)



  • @luteijn:

    I still think you want to make sure the value set is valid at the time it is being set or the caster will get a nasty surprise when polymorphing in the heat of battle

    Very good thinking. I suppose we can extract a function to check and determine the form and place it in a already included script, if CoA wishes to avoid new scripts.
    But… If we don't include the same function call in the polymorph spell script, a non-valid form ID may its way to the poly spell script and the spell will fail or something strange will happen. Still, I dunno how anything but zero or undefined can make its way there, unless the 2da file is altered. We can check for those two and default to some neutral form.



  • We can check for those two and default to some neutral form.

    yes, you do have to do some checking of the validity of the stored state just before blindly using it, as it might be corrupted, not initialised etc. so that you know that if it's not what you expect it to be, you won't crash your plane or do something really unexpected, but some more or less harmless default instead. You (should) do this for digital circuits in hardware, it makes sense to do it for software too.

    Anyway, if the state is already an integer instead of a string, your state-space is smaller, and also you can use a 'switch' instead of a big 'if-then-else'. I don't know if the 'switch' is compiled to anything different than the 'if-then-else', even if it isn't, a 'switch' is easier to read, especially if you have a few simple checks in advance to make sure the integer is between 0 and some MAX_POLY_ID constant you'd set up, and use fall through for ranges of invalid/undefined IDs.
    Normally it's also a lot cheaper to use an integer as an index into a jump table (switch) than to repeatedly compare values until you find a match (if-tree).

    The conversion function is going to be rather a lot of work to type in, as you can't just use a hash table, or even iterate over an array, so I hope you're (or will be) using a program to generate the script text from the plain list of IDs and their Strings, so it's easier to change your mind on how to exactly implement/streamline the conversion function without having to do a lot of re-typing.



  • Um… yes. I did use a python script to generate the nwscript, but it's just bad practice to repeat the same code twice. Nwscript doesn't support hashtables, and arrays have to be done via a string codec or some similar hack.

    It's easy to check if 0 < nPoly < MAX_POLY_ID, but the unexpected can occur if it's a valid value not found in the ploymorph.2da

    If we get a valid nPoly into the polymorph spell script, we don't need a switch. Not unless CoA wishes to maintain two separate, identical tables.

    That said, I vote to keep it simple. On each restart, reset the nPoly to zero, which keeps the original spell working as it is. If someone uses the chat command to change it, they risk miss-spelling, or using a wrong number. And they will find out when the poly spell is cast - it will end up being a normal poly spell. Wizardry is a dangerous business and miscasts happen. 🙂

    I'll do the changes tomorrow.



  • if you're finding yourself typing the same code twice, you're not using functions enough, (or down to unrolling loops and inlining functions by hand because your compiler can't do it for you 🙂 )



  • Here are the scripts with some modifications:

    • Fixed spelling on basilisk and intellect devourer
    • Added an option to cast spell right away (end cmd with "!")
    • Now checking only for start of string (so ".ps mino" is as good as ".ps minotaur")
    • Some feedback if you type ".ps" with no param, some defensive checks
    • If bad param or no param, defaults to chicken. This will be a pixie.
    • Reduced the number of ifs each time spell is cast to a perfectly acceptable amount, in average case.
    • sFormID converted to uppercase at the start

    Remaining to be considered:

    • Currently no feedback after chat command, only after spell is cast
    • Currently can't use number (i.e. .ps 140). Since it still has to be checked for HD and existence, it's same as alias.
    • Add aliases as OR conditions.
    • Better feedback (Bad spelling or not enough HD?)
    // -------- From onPlayerChat -----------
        object oPC = GetPCChatSpeaker();
        string sCommand = GetPCChatMessage();
    
        if (GetStringLeft(sCommand, 3) == ".ps")
        {
            int nCmdLength = GetStringLength(sCommand);
            int nCastNow = FALSE;
    
            // Check if there's any param to the chat command
            if (nCmdLength ");
                return;
            }
    
            // Does it end with "!"?
            if (GetStringRight(sCommand, 1) == "!") nCastNow = TRUE;
    
            string sPolyFormID = GetSubString(sCommand, 4, nCmdLength - (nCastNow?5:4));
            SetLocalString(oPC, "sPolyFormID", sPolyFormID);
            SendMessageToPC(oPC, "Poly set at: " + sPolyFormID);
    
            // Assign cast spell if ends with "!"
            if (nCastNow) AssignCommand(oPC, ActionCastSpellAtObject(SPELL_POLYMORPH_SELF, oPC));
        }
    

    // -------- nw_s0_polyself -------
    #include "x2_inc_spellhook"

    // Returns true if sCreatureName starts with sFormID
    int ComparePolyStr(string sFormID, string sCreatureName) {
    return GetStringLeft(sCreatureName, GetStringLength(sFormID)) == sFormID;
    }

    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
    int nSpell = GetSpellId();
    object oTarget = GetSpellTargetObject();
    effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH);
    effect ePoly;
    int nPoly = 0;
    string sFormID = GetStringUpperCase(GetLocalString(OBJECT_SELF, "sPolyFormID"));
    
    int nCasterLevel = GetCasterLevel(OBJECT_SELF);
    int nTargetHD = GetHitDice(oTarget);
    int nMaxHD = (nCasterLevel < nTargetHD) ? nCasterLevel : nTargetHD;
    
    // Determine duration
    int nMetaMagic = GetMetaMagicFeat();
    int nDuration = nCasterLevel;
    if (nMetaMagic == METAMAGIC_EXTEND) {
        nDuration = nDuration *2; //Duration is +100%
    }
    
    // --------------------------------
    // --- Determine Polymorph type ---
    
    // HD 1
    if (nMaxHD >= 1 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "EYEBALL"))                        { nPoly =  213; }
        else if(ComparePolyStr(sFormID, "GOBLIN"))                    { nPoly =  157; }
        else if(ComparePolyStr(sFormID, "HOBGOBLIN"))                 { nPoly =  163; }
        else if(ComparePolyStr(sFormID, "KOBOLD"))                    { nPoly =  165; }
        else if(ComparePolyStr(sFormID, "ORC"))                       { nPoly =  166; }
        else if(ComparePolyStr(sFormID, "FIRE BEETLE"))               { nPoly =  177; }
        else if(ComparePolyStr(sFormID, "CHICKEN"))                   { nPoly =  40; }
        else if(ComparePolyStr(sFormID, "FALCON"))                    { nPoly =  133; }
        else if(ComparePolyStr(sFormID, "PENGUIN"))                   { nPoly =  26; }
        else if(ComparePolyStr(sFormID, "RAVEN"))                     { nPoly =  134; }
        else if(ComparePolyStr(sFormID, "RAT"))                       { nPoly =  144; }
        else if(ComparePolyStr(sFormID, "OX"))                        { nPoly =  143; }
        else if(ComparePolyStr(sFormID, "BADGER"))                    { nPoly =  25; }
        else if(ComparePolyStr(sFormID, "BAT"))                       { nPoly =  140; }
        else if(ComparePolyStr(sFormID, "COW"))                       { nPoly =  27; }
        else if(ComparePolyStr(sFormID, "DEER"))                      { nPoly =  142; }
        else if(ComparePolyStr(sFormID, "DIRE RAT"))                  { nPoly =  149; }
        else if(ComparePolyStr(sFormID, "CHICKEN"))                   { nPoly =  40; }
        else if(ComparePolyStr(sFormID, "WHITE STAG"))                { nPoly =  145; }
    }
    
    // HD 2
    if (nMaxHD >= 2 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "TROGLODYTE"))                     { nPoly =  312; }
        else if(ComparePolyStr(sFormID, "LIZARDFOLK"))                { nPoly =  170; }
        else if(ComparePolyStr(sFormID, "GNOLL"))                     { nPoly =  158; }
        else if(ComparePolyStr(sFormID, "DEEP ROTHE"))                { nPoly =  190; }
        else if(ComparePolyStr(sFormID, "KRENSHAR"))                  { nPoly =  194; }
        else if(ComparePolyStr(sFormID, "BOMBADIER BEETLE"))          { nPoly =  176; }
        else if(ComparePolyStr(sFormID, "FAERIE DRAGON"))             { nPoly =  224; }
        else if(ComparePolyStr(sFormID, "PSEUDODRAGON"))              { nPoly =  225; }
        else if(ComparePolyStr(sFormID, "DOG"))                       { nPoly =  130; }
        else if(ComparePolyStr(sFormID, "WOLF"))                      { nPoly =  23; }
    }
    
    // HD 3
    if (nMaxHD >= 3 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "BUGBEAR"))                        { nPoly =  152; }
        else if(ComparePolyStr(sFormID, "SEA HAG"))                   { nPoly =  168; }
        else if(ComparePolyStr(sFormID, "STINK BEETLE"))              { nPoly =  179; }
        else if(ComparePolyStr(sFormID, "SWORD SPIDER"))              { nPoly =  181; }
        else if(ComparePolyStr(sFormID, "WYRMLING WHITE DRAGON"))     { nPoly =  235; }
        else if(ComparePolyStr(sFormID, "BLACK BEAR"))                { nPoly =  131; }
        else if(ComparePolyStr(sFormID, "COUGAR"))                    { nPoly =  135; }
        else if(ComparePolyStr(sFormID, "CRAG CAT"))                  { nPoly =  136; }
        else if(ComparePolyStr(sFormID, "LEOPARD"))                   { nPoly =  138; }
        else if(ComparePolyStr(sFormID, "PANTHER"))                   { nPoly =  22; }
        else if(ComparePolyStr(sFormID, "BOAR"))                      { nPoly =  24; }
        else if(ComparePolyStr(sFormID, "DIRE BADGER"))               { nPoly =  37; }
    }
    
    // HD 4
    if (nMaxHD >= 4 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "OGRE"))                           { nPoly =  174; }
        else if(ComparePolyStr(sFormID, "STINGER"))                   { nPoly =  169; }
        else if(ComparePolyStr(sFormID, "GELATINOUS CUBE"))           { nPoly =  208; }
        else if(ComparePolyStr(sFormID, "GARGOYLE"))                  { nPoly =  191; }
        else if(ComparePolyStr(sFormID, "GIANT SPIDER"))              { nPoly =  180; }
        else if(ComparePolyStr(sFormID, "WYRMLING BLACK DRAGON"))     { nPoly =  226; }
        else if(ComparePolyStr(sFormID, "WYRMLING BRASS DRAGON"))     { nPoly =  228; }
        else if(ComparePolyStr(sFormID, "WORG"))                      { nPoly =  258; }
    }
    
    // HD 5
    if (nMaxHD >= 5 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "ETTERCAP"))                       { nPoly =  212; }
        else if(ComparePolyStr(sFormID, "HOOK HORROR"))               { nPoly =  214; }
        else if(ComparePolyStr(sFormID, "COCKATRICE"))                { nPoly =  189; }
        else if(ComparePolyStr(sFormID, "WYRMLING COPPER DRAGON"))    { nPoly =  230; }
        else if(ComparePolyStr(sFormID, "WYRMLING GREEN DRAGON"))     { nPoly =  232; }
        else if(ComparePolyStr(sFormID, "JAGUAR"))                    { nPoly =  137; }
        else if(ComparePolyStr(sFormID, "LION"))                      { nPoly =  139; }
    }
    
    // HD 6
    if (nMaxHD >= 6 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "DRIDER"))                         { nPoly =  211; }
        else if(ComparePolyStr(sFormID, "FEMALE DRIDER"))             { nPoly =  307; }
        else if(ComparePolyStr(sFormID, "INTELLECT DEVOURER"))        { nPoly =  215; }
        else if(ComparePolyStr(sFormID, "TROLL"))                     { nPoly =  175; }
        else if(ComparePolyStr(sFormID, "YUAN-TI"))                   { nPoly =  171; }
        else if(ComparePolyStr(sFormID, "MINOTAUR"))                  { nPoly =  172; }
        else if(ComparePolyStr(sFormID, "MEDUSA"))                    { nPoly =  167; }
        else if(ComparePolyStr(sFormID, "BASILISK"))                  { nPoly =  197; }
        else if(ComparePolyStr(sFormID, "MANTICORE"))                 { nPoly =  195; }
        else if(ComparePolyStr(sFormID, "WYRMLING BLUE DRAGON"))      { nPoly =  227; }
        else if(ComparePolyStr(sFormID, "WYRMLING BRONZE DRAGON"))    { nPoly =  229; }
        else if(ComparePolyStr(sFormID, "BROWN BEAR"))                { nPoly =  21; }
        else if(ComparePolyStr(sFormID, "WINTER WOLF"))               { nPoly =  257; }
        else if(ComparePolyStr(sFormID, "DIRE WOLF"))                 { nPoly =  35; }
    }
    
    // HD 7
    if (nMaxHD >= 7 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "HARPY"))                          { nPoly =  173; }
        else if(ComparePolyStr(sFormID, "STAG BEETLE"))               { nPoly =  178; }
        else if(ComparePolyStr(sFormID, "WYRMLING RED DRAGON"))       { nPoly =  233; }
        else if(ComparePolyStr(sFormID, "WYRMLING SILVER DRAGON"))    { nPoly =  234; }
        else if(ComparePolyStr(sFormID, "DIRE BOAR"))                 { nPoly =  36; }
    }
    
    // HD 8
    if (nMaxHD >= 8 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "MIND FLAYER"))                    { nPoly =  216; }
        else if(ComparePolyStr(sFormID, "UMBER HULK"))                { nPoly =  217; }
        else if(ComparePolyStr(sFormID, "GORGON"))                    { nPoly =  192; }
        else if(ComparePolyStr(sFormID, "SPHINX"))                    { nPoly =  193; }
        else if(ComparePolyStr(sFormID, "WYRMLING GOLD DRAGON"))      { nPoly =  231; }
        else if(ComparePolyStr(sFormID, "POLAR BEAR"))                { nPoly =  148; }
        else if(ComparePolyStr(sFormID, "GRIZZLY BEAR"))              { nPoly =  14; }
    }
    
    // HD 9
    if (nMaxHD >= 9 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "BATTLE DEVOURER"))                { nPoly =  209; }
        else if(ComparePolyStr(sFormID, "WILL O WISP"))               { nPoly =  218; }
        else if(ComparePolyStr(sFormID, "BULLETTE"))                  { nPoly =  313; }
    }
    
    // HD 10
    if (nMaxHD >= 10 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "ETTIN"))                          { nPoly =  187; }
        else if(ComparePolyStr(sFormID, "GREY RENDER"))               { nPoly =  221; }
        else if(ComparePolyStr(sFormID, "DIRE SPIDER"))               { nPoly =  188; }
    }
    
    // HD 11
    if (nMaxHD >= 11 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "BEHOLDER"))                       { nPoly =  210; }
    }
    
    // HD 12
    if (nMaxHD >= 12 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "HILL GIANT"))                     { nPoly =  222; }
        else if(ComparePolyStr(sFormID, "DIRE BEAR"))                 { nPoly =  33; }
    }
    
    // HD 13
    if (nMaxHD >= 13 && nPoly == 0) {
    
    }
    
    // HD 14
    if (nMaxHD >= 14 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "FROST GIANT"))                    { nPoly =  259; }
        else if(ComparePolyStr(sFormID, "FROST GIANT FEMALE"))        { nPoly =  308; }
    }
    
    // HD 15
    if (nMaxHD >= 15 && nPoly == 0) {
        if(ComparePolyStr(sFormID, "FIRE GIANT"))                     { nPoly =  289; }
        else if(ComparePolyStr(sFormID, "FIRE GIANT FEMALE"))         { nPoly =  309; }
    }
    
    //couldn't determine the form and npoly is still 0
    if (nPoly == 0) {
        SendMessageToPC(OBJECT_SELF, "Unknown form type or not enough HD. Check spelling.");
        // Default to chicken!
        nPoly = 40;
    }
    
    ePoly = EffectPolymorph(nPoly);
    //Fire cast spell at event for the specified target
    SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELL_POLYMORPH_SELF, FALSE));
    
    //Apply the VFX impact and effects
    AssignCommand(oTarget, ClearAllActions()); // prevents an exploit
    ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ePoly, oTarget, TurnsToSeconds(nDuration));
    

    }



  • @omg:

    • Currently can't use number (i.e. .ps 140). Since it still has to be checked for HD and existence, it's same as alias.

    Given there's something like 350 polymorphs in the 2da, and you're trying to make sure they stick to the 70 or so available there, doing the numbers while blocking access to the other stuff would be an incredible PITA. And I can't see too many people using a numbered list anyhow, even if it was published, since you can quickslot it either way in the same fashion.



  • well, there's only a very limited number of quickslots, so I'd probably not want to waste them on things you can type in quickly, like ".ps 132!"; but rather use them for things tht you'd have to click through a few layers of menu for to access..

    (oh another feature could be having .ps ! just cast the spell with whatever is the current polymorph target.)



  • To provide proper feedback (is it bad spelling or not enough caster levels, or not enough target HD), the script needs to be changed like so:

    if(ComparePolyStr(sFormID, "EYEBALL"))                        { nPoly =  213; nHD = 1; } 
    else if(ComparePolyStr(sFormID, "GOBLIN"))                    { nPoly =  157; nHD = 1; }
    //...
    ```The top level conditions (if nMaxHD >= ) need to be removed, and the check for HD done after you know which form caster desires. I think that would keep the script readable, so we may want to do it. Any takers?


  • Added proper feedback.
    Prevented casting the spell while already polymorphed.

    #include "x2_inc_spellhook"
    
    // Returns true if sCreatureName starts with sFormID
    int ComparePolyStr(string sFormID, string sCreatureName) {
        return GetStringLeft(sCreatureName, GetStringLength(sFormID)) == sFormID;
    }
    
    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
    
        // No spell if already polymorphed.
        if (GetHasEffect(EFFECT_TYPE_POLYMORPH, OBJECT_SELF)) return;
    
        //Declare major variables
        object oTarget = GetSpellTargetObject();
        effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH);
        effect ePoly;
        int nPoly = 0;
        int nHD = 0;
        string sFormID = GetStringUpperCase(GetLocalString(OBJECT_SELF, "sPolyFormID"));
    
        int nCasterLevel = GetCasterLevel(OBJECT_SELF);
        int nTargetHD = GetHitDice(oTarget);
    
        // Determine duration
        int nMetaMagic = GetMetaMagicFeat();
        int nDuration = nCasterLevel;
        if (nMetaMagic == METAMAGIC_EXTEND) {
            nDuration = nDuration *2; //Duration is +100%
        }
    
        // --------------------------------
        // --- Determine Polymorph type ---
    
        // HD 1
        if(ComparePolyStr(sFormID, "EYEBALL"))                        { nPoly =  213; nHD = 1; }
        else if(ComparePolyStr(sFormID, "GOBLIN"))                    { nPoly =  157; nHD = 1; }
        else if(ComparePolyStr(sFormID, "HOBGOBLIN"))                 { nPoly =  163; nHD = 1; }
        else if(ComparePolyStr(sFormID, "KOBOLD"))                    { nPoly =  165; nHD = 1; }
        else if(ComparePolyStr(sFormID, "ORC"))                       { nPoly =  166; nHD = 1; }
        else if(ComparePolyStr(sFormID, "FIRE BEETLE"))               { nPoly =  177; nHD = 1; }
        else if(ComparePolyStr(sFormID, "CHICKEN"))                   { nPoly =  40;  nHD = 1; }
        else if(ComparePolyStr(sFormID, "FALCON"))                    { nPoly =  133; nHD = 1; }
        else if(ComparePolyStr(sFormID, "PENGUIN"))                   { nPoly =  26;  nHD = 1; }
        else if(ComparePolyStr(sFormID, "RAVEN"))                     { nPoly =  134; nHD = 1; }
        else if(ComparePolyStr(sFormID, "RAT"))                       { nPoly =  144; nHD = 1; }
        else if(ComparePolyStr(sFormID, "OX"))                        { nPoly =  143; nHD = 1; }
        else if(ComparePolyStr(sFormID, "BADGER"))                    { nPoly =  25;  nHD = 1; }
        else if(ComparePolyStr(sFormID, "BAT"))                       { nPoly =  140; nHD = 1; }
        else if(ComparePolyStr(sFormID, "COW"))                       { nPoly =  27;  nHD = 1; }
        else if(ComparePolyStr(sFormID, "DEER"))                      { nPoly =  142; nHD = 1; }
        else if(ComparePolyStr(sFormID, "DIRE RAT"))                  { nPoly =  149; nHD = 1; }
        else if(ComparePolyStr(sFormID, "CHICKEN"))                   { nPoly =  40;  nHD = 1; }
        else if(ComparePolyStr(sFormID, "WHITE STAG"))                { nPoly =  145; nHD = 1; }
    
        // HD 2
        else if(ComparePolyStr(sFormID, "TROGLODYTE"))                { nPoly =  312; nHD = 2; }
        else if(ComparePolyStr(sFormID, "LIZARDFOLK"))                { nPoly =  170; nHD = 2; }
        else if(ComparePolyStr(sFormID, "GNOLL"))                     { nPoly =  158; nHD = 2; }
        else if(ComparePolyStr(sFormID, "DEEP ROTHE"))                { nPoly =  190; nHD = 2; }
        else if(ComparePolyStr(sFormID, "KRENSHAR"))                  { nPoly =  194; nHD = 2; }
        else if(ComparePolyStr(sFormID, "BOMBADIER BEETLE"))          { nPoly =  176; nHD = 2; }
        else if(ComparePolyStr(sFormID, "FAERIE DRAGON"))             { nPoly =  224; nHD = 2; }
        else if(ComparePolyStr(sFormID, "PSEUDODRAGON"))              { nPoly =  225; nHD = 2; }
        else if(ComparePolyStr(sFormID, "DOG"))                       { nPoly =  130; nHD = 2; }
        else if(ComparePolyStr(sFormID, "WOLF"))                      { nPoly =  23;  nHD = 2; }
    
        // HD 3
        else if(ComparePolyStr(sFormID, "BUGBEAR"))                   { nPoly =  152; nHD = 3; }
        else if(ComparePolyStr(sFormID, "SEA HAG"))                   { nPoly =  168; nHD = 3; }
        else if(ComparePolyStr(sFormID, "STINK BEETLE"))              { nPoly =  179; nHD = 3; }
        else if(ComparePolyStr(sFormID, "SWORD SPIDER"))              { nPoly =  181; nHD = 3; }
        else if(ComparePolyStr(sFormID, "WYRMLING WHITE DRAGON"))     { nPoly =  235; nHD = 3; }
        else if(ComparePolyStr(sFormID, "BLACK BEAR"))                { nPoly =  131; nHD = 3; }
        else if(ComparePolyStr(sFormID, "COUGAR"))                    { nPoly =  135; nHD = 3; }
        else if(ComparePolyStr(sFormID, "CRAG CAT"))                  { nPoly =  136; nHD = 3; }
        else if(ComparePolyStr(sFormID, "LEOPARD"))                   { nPoly =  138; nHD = 3; }
        else if(ComparePolyStr(sFormID, "PANTHER"))                   { nPoly =  22;  nHD = 3; }
        else if(ComparePolyStr(sFormID, "BOAR"))                      { nPoly =  24;  nHD = 3; }
        else if(ComparePolyStr(sFormID, "DIRE BADGER"))               { nPoly =  37;  nHD = 3; }
    
        // HD 4
        else if(ComparePolyStr(sFormID, "OGRE"))                      { nPoly =  174; nHD = 4; }
        else if(ComparePolyStr(sFormID, "STINGER"))                   { nPoly =  169; nHD = 4; }
        else if(ComparePolyStr(sFormID, "GELATINOUS CUBE"))           { nPoly =  208; nHD = 4; }
        else if(ComparePolyStr(sFormID, "GARGOYLE"))                  { nPoly =  191; nHD = 4; }
        else if(ComparePolyStr(sFormID, "GIANT SPIDER"))              { nPoly =  180; nHD = 4; }
        else if(ComparePolyStr(sFormID, "WYRMLING BLACK DRAGON"))     { nPoly =  226; nHD = 4; }
        else if(ComparePolyStr(sFormID, "WYRMLING BRASS DRAGON"))     { nPoly =  228; nHD = 4; }
        else if(ComparePolyStr(sFormID, "WORG"))                      { nPoly =  258; nHD = 4; }
    
        // HD 5
        else if(ComparePolyStr(sFormID, "ETTERCAP"))                  { nPoly =  212; nHD = 5; }
        else if(ComparePolyStr(sFormID, "HOOK HORROR"))               { nPoly =  214; nHD = 5; }
        else if(ComparePolyStr(sFormID, "COCKATRICE"))                { nPoly =  189; nHD = 5; }
        else if(ComparePolyStr(sFormID, "WYRMLING COPPER DRAGON"))    { nPoly =  230; nHD = 5; }
        else if(ComparePolyStr(sFormID, "WYRMLING GREEN DRAGON"))     { nPoly =  232; nHD = 5; }
        else if(ComparePolyStr(sFormID, "JAGUAR"))                    { nPoly =  137; nHD = 5; }
        else if(ComparePolyStr(sFormID, "LION"))                      { nPoly =  139; nHD = 5; }
    
        // HD 6
        else if(ComparePolyStr(sFormID, "DRIDER"))                    { nPoly =  211; nHD = 6; }
        else if(ComparePolyStr(sFormID, "FEMALE DRIDER"))             { nPoly =  307; nHD = 6; }
        else if(ComparePolyStr(sFormID, "INTELLECT DEVOURER"))        { nPoly =  215; nHD = 6; }
        else if(ComparePolyStr(sFormID, "TROLL"))                     { nPoly =  175; nHD = 6; }
        else if(ComparePolyStr(sFormID, "YUAN-TI"))                   { nPoly =  171; nHD = 6; }
        else if(ComparePolyStr(sFormID, "MINOTAUR"))                  { nPoly =  172; nHD = 6; }
        else if(ComparePolyStr(sFormID, "MEDUSA"))                    { nPoly =  167; nHD = 6; }
        else if(ComparePolyStr(sFormID, "BASILISK"))                  { nPoly =  197; nHD = 6; }
        else if(ComparePolyStr(sFormID, "MANTICORE"))                 { nPoly =  195; nHD = 6; }
        else if(ComparePolyStr(sFormID, "WYRMLING BLUE DRAGON"))      { nPoly =  227; nHD = 6; }
        else if(ComparePolyStr(sFormID, "WYRMLING BRONZE DRAGON"))    { nPoly =  229; nHD = 6; }
        else if(ComparePolyStr(sFormID, "BROWN BEAR"))                { nPoly =  21;  nHD = 6; }
        else if(ComparePolyStr(sFormID, "WINTER WOLF"))               { nPoly =  257; nHD = 6; }
        else if(ComparePolyStr(sFormID, "DIRE WOLF"))                 { nPoly =  35;  nHD = 6; }
    
        // HD 7
        else if(ComparePolyStr(sFormID, "HARPY"))                     { nPoly =  173; nHD = 7; }
        else if(ComparePolyStr(sFormID, "STAG BEETLE"))               { nPoly =  178; nHD = 7; }
        else if(ComparePolyStr(sFormID, "WYRMLING RED DRAGON"))       { nPoly =  233; nHD = 7; }
        else if(ComparePolyStr(sFormID, "WYRMLING SILVER DRAGON"))    { nPoly =  234; nHD = 7; }
        else if(ComparePolyStr(sFormID, "DIRE BOAR"))                 { nPoly =  36;  nHD = 7; }
    
        // HD 8
        else if(ComparePolyStr(sFormID, "MIND FLAYER"))               { nPoly =  216; nHD = 8; }
        else if(ComparePolyStr(sFormID, "UMBER HULK"))                { nPoly =  217; nHD = 8; }
        else if(ComparePolyStr(sFormID, "GORGON"))                    { nPoly =  192; nHD = 8; }
        else if(ComparePolyStr(sFormID, "SPHINX"))                    { nPoly =  193; nHD = 8; }
        else if(ComparePolyStr(sFormID, "WYRMLING GOLD DRAGON"))      { nPoly =  231; nHD = 8; }
        else if(ComparePolyStr(sFormID, "POLAR BEAR"))                { nPoly =  148; nHD = 8; }
        else if(ComparePolyStr(sFormID, "GRIZZLY BEAR"))              { nPoly =  14;  nHD = 8; }
    
        // HD 9
        else if(ComparePolyStr(sFormID, "BATTLE DEVOURER"))           { nPoly =  209; nHD = 9; }
        else if(ComparePolyStr(sFormID, "WILL O WISP"))               { nPoly =  218; nHD = 9; }
        else if(ComparePolyStr(sFormID, "BULLETTE"))                  { nPoly =  313; nHD = 9; }
    
        // HD 10
        else if(ComparePolyStr(sFormID, "ETTIN"))                     { nPoly =  187; nHD = 10; }
        else if(ComparePolyStr(sFormID, "GREY RENDER"))               { nPoly =  221; nHD = 10; }
        else if(ComparePolyStr(sFormID, "DIRE SPIDER"))               { nPoly =  188; nHD = 10; }
    
        // HD 11
        else if(ComparePolyStr(sFormID, "BEHOLDER"))                  { nPoly =  210; nHD = 11; }
    
        // HD 12
        else if(ComparePolyStr(sFormID, "HILL GIANT"))                { nPoly =  222; nHD = 12; }
        else if(ComparePolyStr(sFormID, "DIRE BEAR"))                 { nPoly =  33;  nHD = 12; }
    
        // HD 13
    
        // HD 14
        else if(ComparePolyStr(sFormID, "FROST GIANT"))               { nPoly =  259; nHD = 14; }
        else if(ComparePolyStr(sFormID, "FROST GIANT FEMALE"))        { nPoly =  308; nHD = 14; }
    
        // HD 15
        else if(ComparePolyStr(sFormID, "FIRE GIANT"))                { nPoly =  289; nHD = 14; }
        else if(ComparePolyStr(sFormID, "FIRE GIANT FEMALE"))         { nPoly =  309; nHD = 15; }
    
        // Couldn't determine the form
        if (nPoly == 0) {
            SendMessageToPC(OBJECT_SELF, "Unknown form type. Check spelling.");
            // Default to chicken!
            nPoly = 40;
        }
    
        // Caster level not high enough for the form
        if (nHD > nCasterLevel) {
            SendMessageToPC(OBJECT_SELF, "Caster level is too low for this form.");
            // Default to chicken!
            nPoly = 40;
        }
    
        // Target hasn't enough HD for the form
        if (nHD > nTargetHD) {
            SendMessageToPC(OBJECT_SELF, "Target doesn't have enough HD for this form.");
            // Default to chicken!
            nPoly = 40;
        }
    
        ePoly = EffectPolymorph(nPoly);
        //Fire cast spell at event for the specified target
        SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELL_POLYMORPH_SELF, FALSE));
    
        //Apply the VFX impact and effects
        AssignCommand(oTarget, ClearAllActions()); // prevents an exploit
        ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ePoly, oTarget, TurnsToSeconds(nDuration));
    }
    


  • As lovely as transgender polymorphing is, the male/female options should probably just go off the players gender with a check under the "FIRE GIANT" "FROST GIANT" etc



  • I'm just a female Fire-Giant trapped in a male dwarf wizard's body.


Log in to reply