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.)
-
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 <= 4) { SendMessageToPC(oPC, "Usage: .ps <shape>"); 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)); }</shape>
// -------- 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 >= <n>) 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?</n>
-
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.