//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //:::::::::::::::::::::::: Shayan's Subrace Engine ::::::::::::::::::::::::::::: //::::::::::::::::::::::: File Name: sha_subr_methds ::::::::::::::::::::::::::: //:::::::::::::::::::::::::: Include script :::::::::::::::::::::::::::::::::::: //:: Written by: Shayan ::// //:: Contact: mail_shayan@yhaoo.com ::// // // ::Description: Holds all the methods used in the Subrace System. DO NOT CHANGE // :: ANYTHING UNLESS YOU ARE CERTAIN. // :: This is the 'core engine script'. In updates, more than likely // :: this script is changed... so unless you do not plan to update to // :: possible future releases of this engine, it will be in your best // :: interest NOT to make any changes to this script. Because then you // :: will have to redo them again. // :: Should you disregard this warning and proceed to editing... // :: Remember that: // :: * If you have made a change you must recompile all scripts for // :: changes to take place. // // ::Please refer to the script file 'sha_subr_consts' to change any values of the // ::constants or default values. // ::Version 1.4: Reduced the numbers of local variables, by "encoding a single interger // :: variable to hold several 'bits' of information". - Using Axe Murderer's Flag-sets. // ::Version 1.2: Support for NWNX added. Refer to Lines: 37, 3890, 3905, 3914, and 3983. //Uncomment the line below if you wish to use NWNX Database instead. //(Make sure you have imported in these files from the NWNX package, available from // :: http://www.nwnx.org) //#include "aps_include" #include "sha_subr_consts" #include "sha_misc_funcs" //Version 1.1: Changed from storing the data on the module to an object. //object oStorer = GetObjectByTag(SUBRACE_INFO_STORER_TAG); //Version 1.1a Revision: Changed it back to Module for faster access. object oStorer = GetModule(); /* ::::::::::::::::::::::::::: Function definers :::::::::::::::::::::::::::::::::: */ // :: Below lies the list of all the functions useable OnModuleLoad to setup // :: a subrace. //:: - ALL SUBRACE RELATED METHODS MUST BE CALLED AFTER THIS METHOD! - //:: -- The Main function. Call this OnModuleLoad. // // ::Race: This is the base race that you want to create your subrace from // :: Use ONLY: RACIAL_TYPE_ALL, or RACIAL_TYPE_DWARF, RACIAL_TYPE_ELF, // :: RACIAL_TYPE_GNOME, RACIAL_TYPE_HALFELF, RACIAL_TYPE_HALFLING, // :: RACIAL_TYPE_HALFORC, or RACIAL_TYPE_HUMAN. // :: If you want to add additional races that can become part of this subrace call // :: AddAdditionalBaseRaceToSubrace() AFTER this method. // // ::SubraceName: The subrace's name. This is what the PC will have to type in his/her // :: Subrace field. DO NOT HAVE SPACES IN NAMES. // :: IE: Use "Dark-elf" NOT "Dark elf". // :: (Not case sensitive.) // // ::HideResRef: This is the resref of the Creature Hide/Skin you want to equip on the PC. // :: This will have all the subrace traits like ability modifiers and base feats etc. // // :: If you do not want a skin, write either "none" or leave it as blank. // // ::UniqueItemResref: This is the resref of the item that you want given to the player. For example this item // :: could hold can spells on it, or just description of the subrace. Ideally this item will not be droppable, // :: and is marked as being a plot item. Regardless of what type of item this is it will be given to player when they enter the module. // :: (If they lose it or drop it they will again get it back on the next time they enter). // // :: If you do not want to give the PC a unique item then, write either "none" or leave it as blank. // // ::IsLightSensitive: Set to TRUE if the subrace is light senstive. IE: Blinded when in Sunlight and/or gets saves and AB decreases. // :: If the PC does not pass the fort saving throw, then it is blinded for that round. // :: The DC for the saving throw can be changed by changing the value of // :: LIGHT_SENSITIVE_SAVING_THROW_DC in the file sha_subr_consts. Also you can change the interval (rounds) between each time the PC // :: is 'struk' by light by changing the value of LIGHT_BLINDNESS_STRIKES_EVERY_ROUND. And also you can change the number of rounds // :: the PC stays blinded for if it fails the saving throw by changing tha value of LIGHT_STRUCK_BLIND_FOR_ROUNDS. // // :: If APPLY_AB_AND_SAVING_THROW_DECREASES_IN_LIGHT is set to TRUE, then the PC also suffers // :: an attack bonus decrease of LIGHT_AB_DECREASE and saving throw decrease of LIGHT_SAVE_DECREASE for a number of rounds // :: determined by: LIGHT_CAUSES_AB_AND_SAVES_DECREASE_FOR_ROUNDS. // // :: Rememeber: IF YOU CHANGE ANYTHING IN THE CONSTANTS FILE, IT WILL APPLY TO ALL SUBRACES. // :: (IE: If you change the DC for the saving throw then all subraces that have light sensitivity will have to make that saving throw). // // ::DamageTakenWhileInLight: The amount of divine Damage the PC suffers ever round while // :: it is in sunlight. Note: PC does not necessarily have to be Light Sensitive // :: for this to work. // :: If this value is negative then the PC will regenerate that amount. // // ::IsUndergroundSensitive: Same as IsLightSenstive but this applies when the PC is in // :: Underground type of areas. This does not mean the PC is affected by Night time. // // ::DamageTakenWhileInUnderground: The amount of Negative Damage taken per round while in the Underground. // :: Note: This too doesn't need the PC to be Under ground sensitive to apply. // :: If this value is negative then the PC will regenerate that amount. // // :: ECL: Effective Character Level: Use any integer value. // :: (For those that do not know what this is... // :: Effective Character Level is a way of lessening your subrace's bonus abilities // :: by reducing the amount of experience points gained per kill.) // :: IE: If you have a Subrace with ECL of 3, then a PC (Player character) of level 10 belonging to // :: that subrace is regarded being level 13 when gaining XP points per kill. // :: Thus will get less experience points. // :: NOTE: This can work for negative values as well. // // :: IsUndead: Mark the PC belonging to this sub-race as being Undead. It will mean that Healing spells will hurt the PC. // :: And harming spells will heal the PC. // // :: PrestigiousSubrace: Mark this sub-race as being prestigious. Which means players can't become part of it when they enter in with a level 1 character with this as their chosen subrace. // :: (Set this to TRUE, if you are making a subrace that players can become part of once they reach a certain level in another sub-race) // :: -Refer to SetupSubraceSwitch() for more information - // // :: Example: You wish to create a subrace called Drow, and you have created a Creature Skin/Hide in the toolset with // :: resref "sha_pc_drow". The Unique item (which contains spell like abilities and information about the Drow subrace) // :: has the resref "sha_subrace_drow". And you want to make the Drow light sensitive and take 2 divine damage while in light areas. // :: Also you would like to mark the Drow as having an Effective Character level of +1. // :: Simply call this OnModuleLoad. (Remember to #include "sha_subr_methds", in the script) // // :: CreateSubrace(RACIAL_TYPE_ELF, "drow", "sha_pc_drow", "sha_subrace_drow", TRUE, 2, FALSE, 0, 1); void CreateSubrace(int Race, string SubraceName, string HideResRef = "", string UniqueItemResref = "", int IsLightSensitive = FALSE, int DamageTakenWhileInLight = 0, int IsUndergroundSensitive = FALSE, int DamageTakenWhileInUnderground = 0, int ECL = 0, int IsUndead = FALSE, int PrestigiousSubrace = FALSE); //- Add another Race that can be part of the subrace. // :: subraceName should be the same as the Subrace's name used in CreateSubrace() // :: AdditionalBaseRace can only be RACIAL_TYPE_ALL, RACIAL_TYPE_DWARF, RACIAL_TYPE_ELF, RACIAL_TYPE_GNOME, // :: RACIAL_TYPE_HALFELF, RACIAL_TYPE_HALFLING, RACIAL_TYPE_HALFORC, or RACIAL_TYPE_HUMAN. void AddAdditionalBaseRaceToSubrace(string subraceName, int AdditionalBaseRace); // ::Limit the classes the PC can be, when trying to be part of this subrace. // :: subraceName should be the same as the Subrace's name used in CreateSubrace() // :: Set the CanBe_ values as desired. // // ::Note: This will only check PC's first class. IE: You limit your subrace's classes to only Fighter and Rogue // :: A player with classes Wizard/Fighter/Cleric will not meet the criteria, nor will a Monk/Cleric/Rogue. // :: Only a PC with either Rogue or Fighter as their first class will meet the requirement. // :: IE: Rogue/WeaponMaster or Fighter/Wizard/Cleric. void CreateSubraceClassRestriction(string subraceName, int CanBe_Barbarian = TRUE, int CanBe_Bard = TRUE, int CanBe_Cleric = TRUE, int CanBe_Druid = TRUE, int CanBe_Fighter = TRUE, int CanBe_Monk = TRUE, int CanBe_Paladin = TRUE, int CanBe_Ranger = TRUE, int CanBe_Rogue = TRUE, int CanBe_Sorcerer = TRUE, int CanBe_Wizard = TRUE); //Limit the Alignment the PC can be, when trying to be part of this subrace. //Note this alignment restriction only applies when the PC enters the module for the first time. (A database entry is made). // :: IE: It will not stop the PC from being part of the subrace after the PC adventures and changes in alignment. // // :: subraceName should be the same as the Subrace's name used in CreateSubrace() // :: Set the CanBe_ to as desired. void CreateSubraceAlignmentRestriction(string subraceName, int CanBeAlignment_Good = TRUE , int CanBeAlignment_Neutral1 = TRUE, int CanBeAlignment_Evil = TRUE, int CanBeAlignment_Lawful = TRUE, int CanBeAlignment_Neutral2 = TRUE, int CanBeAlignment_Chaotic = TRUE); //Use this method of Spell resistance if you want the Spell resistance to increase (or decrease) with the PC's level. // :: subraceName should be the same as the Subrace's name used in CreateSubrace() // // :: SpellResistanceBase: Is the vaule of SR the PC gains at level 1 // :: int SpellResistanceMax: Is the value of the SR PC gains at the maximum level achievable (default is 40, you can change the maximum level value in "sha_subr_consts") void CreateSubraceSpellResistance(string subraceName, int SpellResistanceBase, int SpellResistanceMax); //Use this method if you want the PC's Appearance to change for the subrace. // // :: subraceName should be the same as the Subrace's name used in CreateSubrace() // :: AppearanceChangeTime: Time of day you want the Appearance to change. // :: if you want to have a permanent appearance change then use: TIME_BOTH. // :: if you want the appearance to only change when it is night time and revert back when it is day time then use: TIME_DAY. // :: if you want the appearance to only change when it is day time and revert back to the PC's original form when it is night time then use: TIME_NIGHT. // :: if you plan on making a controlable appearance, then set to TIME_NONE. (Refer to .pdf tutorial for more information) // // ::MaleAppearance: This is the appearance of a Male PC. Use any of the APPEARANCE_TYPE_* values. // ::FemaleAppearance: This is the appearance of a Female PC. Use any of the APPEARANCE_TYPE_* values. // ::Level: From which level to apply this appearance change from... // // ::NOTE: Not all APPEARANCE_TYPE_* constants work in standard NWN. IE: If you use APPEARANCE_TYPE_WYRMLING_BLACK, and you only have installed just NWN (no expansions), // :: Then your appearance will be different... (in the case of wyrmiling, you will look like a mephit) - You have been warned. void CreateSubraceAppearance(string subraceName, int AppearanceChangeTime, int MaleAppearance, int FemaleAppearance, int Level = 1); // - (You may use this twice per subrace. Once for TIME_DAY, and once for TIME_NIGHT) - // // Use this method if you want the PC's ability scores or AC or AB to change when it is either day or night. // (The use of this function is slightly more complicated) // // :: subraceName: Should be the same as the Subrace's name used in CreateSubrace() // // :: struct SubraceStats Stats: (Explained below) // // :: TimeToApply: if you want the stats/ability scores to only change when it is night time and revert back when it is day time then use: TIME_NIGHT. // :: if you want the stats/ability scores to only change when it is day time and revert back to the PC's original stats/ability scores when it is night time then use: TIME_DAY. // // :: InInteriorArea: Set to TRUE if you want these changes to ability scores to happen in Interior Areas. // :: InExteriorArea: Set to TRUE if you want these changes to ability scores to happen in Exterior Areas. // :: InNaturalArea: Set to TRUE if you want these changes to ability scores to happen in Natural Areas. // :: InArtifacialArea: Set to TRUE if you want these changes to ability scores to happen in Artifical Areas. // :: InUndergroundArea: Set to TRUE if you want these changes to ability scores to happen in Underground Areas. // :: InAbovegroundArea: Set to TRUE if you want these changes to ability scores to happen in Above Ground Areas. // // :: How to use this function. // // :: First create a structure of SubraceStats. It can be done by: // // :: struct SubraceStats mystats = CreateCustomeStats(). // // :: then you want to add this to your subrace. So call // // :: CreateTemporaryStatModifier("mysubrace", mystats, TIME_DAY, TRUE, FALSE); // // ::Hence the PC belonging to "mysubrace" will have it's ability scores changed during day time, when they are in Exterior (IE: outdoors) areas. void CreateTemporaryStatModifier(string subraceName, struct SubraceStats Stats, int TimeToApply, int InInteriorArea = TRUE, int InExteriorArea = TRUE, int InNaturalArea = TRUE, int InArtifacialArea = TRUE, int InUndergroundArea = TRUE, int InAbovegroundArea = TRUE); //This is the first half of CreateTemporaryStatModifier function. // //(The use of this function is slightly more complicated) // // :: StatModiferType: Use only SUBRACE_STAT_MODIFIER_TYPE_PERCENTAGE (if you wish to increase or decrease a PC's ability scores/AC/AB based on the percentage of the PC's current ability scores) // :: or SUBRACE_STAT_MODIFIER_TYPE_POINTS (if you wish to increase or decrease a PC's ability scores/AC/AB by constant number. // :: Fill in the values of the floats appropriately. // // ::Example: You wish to change reduce the PC's strength by 80% and increase it's dexterity by 50% and increase it's consitituion by 60%, whilst you want to increase the AC by 65%, but reduce the AB by 10%. // // ::so you create your stats: // // ::struct SubraceStats mystats = CreateCustomStats(SUBRACE_STAT_MODIFIER_TYPE_PERCENTAGE, -0.80, 0.50, 0.60, 0.0, 0.0, 0.0, 0.65, -0.10); // // ::You then use this in CreateTemporaryStatModifier(). struct SubraceStats CreateCustomStats(int StatModifierType, float StrengthModifier, float DexterityModifier, float ConstitutionModifier, float IntelligenceModifier, float WisdomModifier, float CharismaModifier, float ACModifier, float ABModifier); //(Use this only ONCE per subrace. It will not work correctly if used more than once per subrace) // //This method will allow you to disable/enable the use of Melee or ranged weapons or other types of weapons by the particular subrace. // // :: subraceName: Should be the same as the Subrace's name used in CreateSubrace() // :: WeaponType: The type of weapon you want the restriction to apply to... // :: Use either SUBRACE_RESTRICTION_WEAPON_MELEE (gloves are excluded) // :: or SUBRACE_RESTRICTION_WEAPON_RANGED (ranged and throwing type of weapons) // :: or SUBRACE_RESTRICTION_WEAPON_EXOTIC or SUBRACE_RESTRICTION_WEAPON_LARGE or // :: or SUBRACE_RESTRICTION_WEAPON_MARTIAL or SUBRACE_RESTRICTION_WEAPON_SIMPLE // :: or SUBRACE_RESTRICTION_WEAPON_TINY or SUBRACE_RESTRICTION_WEAPON_ALL // // :: TimeOfDay: To Restrict the use of WeaponType at various times: Use TIME_NIGHT, TIME_DAY or TIME_BOTH // // :: Allow: If you want to allow the use of ONLY these weapons, then set it to TRUE. If set to FALSE, the engine // :: will prohibit the use of WeaponType. void SubraceRestrictUseOfWeaponsOfType(string subraceName, int WeaponType, int TimeOfDay = TIME_BOTH, int Allow = FALSE); //(Use this only ONCE per subrace. It will not work correctly if used more than once per subrace) // // ::This method will allow you to disable/enable the use of items that grant defense. (Shields and Armour) // // :: subraceName: Should be the same as the Subrace's name used in CreateSubrace() // :: Type: The category of armor and shield thats you want the restriction to apply to... // // :: SUBRACE_RESTRICTION_DEFENSE_ALL (All shields and Armor -including cloths) // :: SUBRACE_RESTRICTION_DEFENSE_CLOTHING (Cloths only, no shields) // :: SUBRACE_RESTRICTION_DEFENSE_HEAVY (Full plates, half plates and Tower shields, and helms) // :: SUBRACE_RESTRICTION_DEFENSE_MEDIUM (Chain Shirt, Scale Mail, Chainmail, Breastplate, Splint Mail, Banded Mail and Large Shields and helms) // :: SUBRACE_RESTRICTION_DEFENSE_LIGHT (Padded, Leather armour,Studded Armor and small shields.) // // :: TimeOfDay: To Restrict the use of WeaponType at various times: Use TIME_NIGHT, TIME_DAY or TIME_BOTH // // :: Allow: If you want to allow the use of ONLY these weapons, then set it to TRUE. If set to FALSE, the engine // :: will prohibit the use of WeaponType. void SubraceRestrictUseOfArmourAndShieldsOfType(string subraceName, int Type, int TimeOfDay = TIME_BOTH, int Allow = FALSE); //:: Add a favored class to the subrace. // // (Use this only ONCE per subrace. It will not work correctly if used more than once per subrace) // This would mean that when determining XP penalty for multiclassing, the favored // classes do not apply when determining it (Works the same way as default NWN favored classes) // ::(This will work ONLY if you are using the attached Shayan's XP System script). // //NOTE: You can use any playable base CLASS_TYPE_* constant. Do NOT USE Prestige classes, // :: as they are not taken into consideration when determining multiclassing penalty by NWN. // :: Also if you do specify a prestige class it will end up giving players a 20% boost to the XP gained. // :: (Thanks to Masterlexx for spotting this bug) void AddSubraceFavoredClass(string subraceName, int MaleFavoredClass, int FamaleFavoredClass); //Add a permanent or a temporary subrace effect on the PC, during day or night or permanently. // //:: subraceName: Should be the same as the Subrace's name used in CreateSubrace() //:: EffectID: There are a limited number of effects you can use here... //:: EFFECT_TYPE_ARCANE_SPELL_FAILURE //:: EFFECT_TYPE_BLINDNESS //:: EFFECT_TYPE_CHARMED //:: EFFECT_TYPE_CONCEALMENT //:: EFFECT_TYPE_CONFUSED //:: EFFECT_TYPE_CUTSCENEGHOST //:: EFFECT_TYPE_HASTE //:: EFFECT_TYPE_IMMUNITY //:: EFFECT_TYPE_IMPROVEDINVISIBILITY //:: EFFECT_TYPE_INVISIBILITY //:: EFFECT_TYPE_MISS_CHANCE //:: EFFECT_TYPE_MOVEMENT_SPEED_DECREASE //:: EFFECT_TYPE_MOVEMENT_SPEED_INCREASE //:: EFFECT_TYPE_POLYMORPH //:: EFFECT_TYPE_REGENERATE //:: EFFECT_TYPE_SANCTUARY //:: EFFECT_TYPE_SLOW //:: EFFECT_TYPE_TEMPORARY_HITPOINTS //:: EFFECT_TYPE_TRUESEEING //:: EFFECT_TYPE_ULTRAVISION //:: EFFECT_TYPE_VISUALEFFECT // // :: Value1: This is the value of the first parameter (from left) that you can input for the effect. // :: IE: If you choose EFFECT_TYPE_CONCEALMENT, which means the effect applied will be: // :: EffectConcealment(int nPercentage, int nMissType=MISS_CHANCE_TYPE_NORMAL) // :: Thus Value1 will be the value of nPercentage. // :: YOU MUST INPUT A VALUE! IF NOT THE SCRIPT WILL PUT IN 0!! // // :: Value2: This is the value of the second parameter you can input for the effect. // :: IE: (Refer to Value1's example) This will be the value of nMissType. // :: YOU MUST INPUT A VALUE! IF NOT THE SCRIPT WILL PUT IN 0!! // // ::nDurationType: Duration type of the effect being applied... // :: DURATION_TYPE_INSTANT, DURATION_TYPE_PERMANENT, or DURATION_TYPE_TEMPORARY. // // ::fDuration: The number of seconds the effect should last for... // :: (Put 0.0 if you are making it last "forever" -IE: Whole of day time, or night time or permanetly) // // ::TimeOfDay: The time of day you want this applied. Use TIME_BOTH if you want this permanently applied on the PC. // // Use as many times as desired. void AddSubraceEffect(string subraceName, int EffectID, int Value1, int Value2, int nDurationType, float fDuration, int TimeOfDay); //Add a different skin to the subrace at specified level. (Use as many times as desired) // //:: subraceName: Should be the same as the Subrace's name used in CreateSubrace() //:: SkinResRef: The Blueprint ResRef of the skin that you want the subrace to be equipped. //:: EquipLevel: The level at which you want the skin to be applied. //:: iTime: The time at which you want the skin to be equipped. (Use TIME_DAY, TIME_NIGHT, or TIME_BOTH.) // // ::Example: You want to add a skin for the subrace Illithid to use at level 15, during day time. // // ::Then call onModuleLoad script: // :: AddAdditionalSkinsToSubrace("Illithid", "my_illithid_skin", 15, TIME_DAY); // // ::(Where "my_illithid_skin" is the resref of the skin you want equipped.) // // :::: // :::: Remeber: If you say add a skin for a subrace to be equipped at level 15, then all PCs belonging to the // :::: subrace above level 15 will also use the same skin for that time -unless you add a different skin for those levels.) // // ::::Use as many times as desired. void AddAdditionalSkinsToSubrace(string subraceName, string SkinResRef, int EquipLevel, int iTime = TIME_BOTH); //::: Add equipable creature claws to the subrace. (Use as many times as desired) // // :: This allows you to add 'Claws' to your subrace. You simply specify the Blue print resref of // :: the claw you want equipped on the player, and at what level. // :: (You can use this to equip claws/slams/gore or what ever else that maybe equipped in a PC's claw item slots // // //:: subraceName: Should be the same as the Subrace's name used in CreateSubrace() //:: RightClawResRef: The resref of the right hand claw. (Use "" if you do not want to specify a claw, use "none" if you want any existing right claws to be removed from the player.) //:: LeftClawResRef: The resref of the left hand claw. (Use "" if you do not want to specify a claw, use "none" if you want any existing right claws to be removed from the player.) //:: EquipLevel: The level at which these claws should be equipped. // // ::NOTE: 1. Make sure the PCs have weapon proficiency in creature weapons!!! I can't stress this enough. // :: (Give the feat through the subrace Skin) // // :: 2. If you are going to use one claw, make sure it is the right claw. // // :: 3. Also note that you need not change both claws at once. // :: (IE: Say you equipped a right and left claw at level 5, then say at level 10, if you want to change the left claw // :: then you only need to specify the resref of the left claw... the PC keeps the existing right claw.) void AddClawsToSubrace(string subraceName, string RightClawResRef, string LeftClawResRef , int EquipLevel, int iTime = TIME_BOTH); //::: Switch the player from one subrace to another :::: // // ::(Use only once per Level) // // :: This allows you to switch a player from one subrace to another. // //:: subraceName: Should be the same as the Subrace's name used in CreateSubrace() //:: switchSubraceName: The syntax of the subraces, you wish to switch the player (Should be the same as whatever the new subraces' name used in it's CreateSubrace()) //:: Level: The level at which this switch should take place. //:: MustMeetRequirements: Set to FALSE, if you want the switching to bypass any class/race/alignment restriction the new subrace might have. // // :: If MustMeetRequirements set to TRUE, and the character fails to meet a requirement... then they will continue on as part of their current sub-race. // // ::IDEA: You can set the subrace you want the player to switch to as a hidden and unaccessible subrace for new characters, by setting // :: PrestigiousSubrace to TRUE, in CreateSubrace(). // :: That way, players must earn their way to this new subrace (switchSubraceNames). // // ::Note: Inorder for this to work the subrace you wish to switch the player to does NOT have to be marked as prestigious. // // ::IE: If I had set up three subraces like: // :: CreateSubrace(RACIAL_TYPE_HUMAN, "illithid", "sha_pc_illithid", "sha_subrace_illi", TRUE, 0, FALSE, 0, 3); // :: //(Along with other setting for subrace, like class restrictions, appearance, additional skins, etc) // // :: CreateSubrace(RACIAL_TYPE_HUMAN, "vampire", "sha_pc_vamp001", "sha_subrace_vamp", TRUE, 2, FALSE, 0, 3, TRUE); // :: //Can only be evil. // :: CreateSubraceAlignmentRestriction("vampire", FALSE, FALSE, TRUE); // :: //(Along with other setting for subrace, like class restrictions, appearance, additional skins, etc) // // :: CreateSubrace(RACIAL_TYPE_HUMAN, "wolkier", "sha_pc_wolk", "sha_subrace_wolk", TRUE); // :: //Can only be Neutra;. // :: CreateSubraceAlignmentRestriction("wolkier", FALSE, TRUE, FALSE); // :: //(Along with other setting for subrace, like class restrictions, appearance, additional skins, etc) // // ::And I wished that PCs belonging to illithid be switched to vampire or wolkier at level 15, depending on which criteria they meet, then I would call: // // :: SetupSubraceSwitch("illithid", "vampire_wolkier", 15, TRUE); // // ::If I didn't want the alignment criteria to be check during switching then I would call: // // :: SetupSubraceSwitch("illithid", "vampire_wolkier", 15, FALSE); // // :: The order in which you choose the subrace to be switched is important. If the player can meet both requirements, it gives prioirty to the first one. // // // :: You can put in any number of subraces to switch to.. // :: IE: // SetupSubraceSwitch("illithid", "vampire_wolkier_pixie_shadow", 8, TRUE); // // If a player doesn't meet the criteria for any one of the subraces, he/she wil remain part of thier usual subrace: subraceName. // // You can use SetupSwitchSubrace() as many times as you like. EG: // // SetupSubraceSwitch("illithid", "vampire_wolkier_pixie_shadow", 12, TRUE); // SetupSubraceSwitch("illithid", "air-genasi_underminion", 18, TRUE); // SetupSubraceSwitch("illithid", "mindbreaker_telephathest_darkmoon", 32, TRUE); // SetupSubraceSwitch("illithid", "greatone", 40, FALSE); // // Where: vampire, wolkier, pixie, shadow, air-genasi, underminion, mindbreaker, // telephathest, darkmoon, and greatone are all subraces. void SetupSubraceSwitch(string subraceName, string switchSubraceName, int Level, int MustMeetRequirements = TRUE); // :: Give the player belonging to a subrace, additional unique items :: // (Use as many times as desired for any levels) // // This allows you to give players belonging to a subrace additional unique items, at any level. // // :: subraceName: Should be the same as the Subrace's name used in CreateSubrace() // :: ItemResRef: The blueprint res-ref of the item to give. // :: Level: The level at which to give the item. // // Example: // // Say I wanted to give my players belonging to the vampire subrace, an armour and a scythe at level 2. // And then an amulet at level 10. // The armor's resref is: "sha_vamp_arm" // The scythe's resref is: "sha_vamp_scythe" // The amulet's resref is: "sha_vamp_ammy" // // So I simply call: // AddSubraceItem("vampire", "sha_vamp_arm", 2); // AddSubraceItem("vampire", "sha_vamp_scythe", 2); // AddSubraceItem("vampire", "sha_vamp_ammy", 10); // //// NOTE: You can only give ONE item of each. IE: You CAN'T do this expecting to give 2 amulets: // // AddSubraceItem("vampire", "sha_vamp_ammy", 10); // AddSubraceItem("vampire", "sha_vamp_ammy", 10); void AddSubraceItem(string subraceName, string ItemResRef, int Level = 1); // :: Setup a Prestige class restriction for a 'Prestige' subrace. // // NOTE: This will only be checked during a 'subrace switch' for obvious reasons. Refer to SetupSubraceSwitch(...) // // subraceName = Should be the same as the Subrace's name used in CreateSubrace(). // MinimumLevels = The minimum number of levels in a/any particular prestigious class allowed to pass the restriction. // Set CanBe_ values as desired. // // Example: // // Say I have a subrace 'Phantasm' and I wanted to add a restriction so that only Shadow Dancers, Blackguards, and Assasin can be part of. // AND they must have atleast 5 levels in any of those classes. // So I set: // // CreateSubracePrestigiousClassRestriction("phantasm", 5, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE); // // * A player with class combination like /Assasin(2)/ShadowDancer(3) will meet this criteria. // // NOTE: This can be used in combination with CreateSubraceClassRestriction(...) // // If you wanted to you can also set-up a primary/base class restriction with CreateSubraceClassRestriction(...) and also create a Prestigious class restriction with this. void CreateSubracePrestigiousClassRestriction(string subraceName, int MinimumLevels = 1, int CanBe_ArcaneArcher = TRUE, int CanBe_Assasin = TRUE, int CanBe_Blackguard = TRUE, int CanBe_ChampionOfTorm = TRUE, int CanBe_RedDragonDisciple = TRUE, int CanBe_DwarvenDefender = TRUE, int CanBe_HarperScout = TRUE, int CanBe_PaleMaster = TRUE, int CanBe_ShadowDancer = TRUE, int CanBe_Shifter = TRUE, int CanBe_WeaponMaster = TRUE); /* :::::::::::::::::::::::: Function Definers usuable anywhere :::::::::::::::::::: */ //:: You may use these functions anywhere, and they would work appropriately. // ::Erases all "temporary" subracial abilities, so that after respawn or a restoring spell is cast // ::the heartbeat script will then reapply the stats again. void ReapplySubraceAbilities(object oPC); //Add this on the Module OnClientEnter script. void SubraceOnClientEnter(); //Add this to Module OnPlayerRespawn script. void SubraceOnPlayerRespawn(); //Add this to Module OnPlayerLevelUp script. void SubraceOnPlayerLevelUp(); //Add this to Module OnPlayerEquipItem script. void SubraceOnPlayerEquipItem(); //Add this to the Module OnItemActivated script. void SubraceOnItemActivated(); //Subrace Heartbeat function - For use in default.nss void SubraceHeartbeat(object oPC = OBJECT_SELF); //:: Force the player to properly un-equip the item. void SHA_SubraceForceUnequipItem(object oItem); //:: Force the player to properly equip oItem in the inventory slot: InvoSlot. void SHA_SubraceForceEquipItem(object oItem, int InvoSlot); //Return the XP modifier for being part of the Subrace //(Calclates modifer value for Subrace Favored classes) float GetSubraceXPModifier(object oPC); //:: Returns TRUE if the player is marked as being part of an undead subrace. //:: (Shayan's Subrace Engine) int Subrace_GetIsUndead(object oPC); //:: Returns the Effective Character level of oPC. //:: (Shayan's Subrace Engine) int GetECL(object oPC); //:: Deletes every bit of subracial information stored on the PC. Also destroys equipped skins and claws. //:: (Does not however delete the 'subrace' set on the PC. Use SetSubRace(oPC, "") AFTER calling this, if you wish to remove the PC from the subrace completely.) //:: (Shayan's Subrace Engine) void DeleteSubraceInfoOnPC(object oPC); //:: Change the PC to his/her default humaniod appearance. //:: IE: If the player is human and his/her appearance is Illithid, this will turn them back //:: to looking like human again. //:: (Shayan's Subrace Engine) void ChangeToPCDefaultAppearance(object oPC); //:: Returns TRUE if PC belongs to a subrace which is Light sensitive. //:: (Shayan's Subrace Engine) int GetIsPCLightSensitive(object oPC); //:: Reads al the subraces avaliable in this module to the object oDM. //:: (Shayan's Subrace Engine) void ReadAllSubraces(object oDM); //:: Return the Favored class of the PC. Returns -1 if there is none. //:: (Shayan's Subrace Engine) int Subrace_GetFavouredClass(object oPC); //:: Send's a message to PC, with a Subrace Engine title. Set Important to TRUE if //:: it is an important message. (Refer to sha_subr_consts for more info.) //:: (Shayan's Subrace Engine) void SHA_SendSubraceMessageToPC(object oPC, string message, int Important = TRUE); //:: Traverses through oPC's inventory, destroying all Skins, and creature items. void SearchAndDestroySkinsAndClaws(object oPC); //:: Removes temporary subrace ability scores and AB boosts. void ClearSubraceEffects(object oPC); //:: Returns TIME_DAY, or TIME_NIGHT depending on the current hour of day. int SHA_GetCurrentTime(); //:: Returns the default appearance type of oPC. (It ignores any appearance //:: change by SetAppearance()). //:: NOTE: oPC must be a player character in order for this to work. int SHA_GetDefaultAppearanceType(object oPC); // //::::::::::::::::::::::::: Interal Function definers::::::::::::::::::::::::::: // // :: Do not use these functions outside this script. They may not work correctly. void SaveSubraceOnModule(struct Subrace shaSubrace); void GiveSubraceUniqueItem(string SubraceTag, object oPC); void SaveSubraceAlignmentRestrictionOnModule(struct SubraceAlignmentRestriction shaSubraceAlignRes); void SaveSubraceClassRestrictionOnModule(struct SubraceClassRestriction shaSubraceClassRes); void SaveSubraceSpellResistanceOnModule(struct SubraceSpellResistance shaSubraceSpellRes); void SaveSubraceAppearanceChangeOnModule(struct SubraceDifferentAppearance shaSubraceApp); int CheckIfPCMeetsClassCriteria(object oPC, string SubraceTag); int CheckIfPCMeetsAlignmentCriteria(object oPC, string SubraceTag); int CheckIfPCMeetsAnySubraceCriteria(object oPC); void SHA_ApplyTemporaryStats(object oPC, string SubraceTag, int iCurrentTime, int iTimeDay, int iTimeNight,int AreaUndAbove, int AreaIntExt, int AreaNatArt); void ApplyTemporarySubraceStats(object oPC, string SubraceTag, int iCurrentTime, int AreaUndAbove, int AreaIntExt, int AreaNatArt); void ApplyStat_AbilityByPercentage(int AbilityToMod, float percentage, object oPC); void ApplySubraceBonusStatsByPercentage(object oPC, string SubraceTag); void ApplyAttackBonusByPercentage(float percentage, object oPC); void ApplyArmourClassBonusByPercentage(float percentage, object oPC); void ApplySubraceBonusStatsByPoints(object oPC, string SubraceTag); void ApplyStat_AbilityByPoints(int AbilityToMod, float points, object oPC); void ApplyAttackBonusByPoints(float points, object oPC); void ApplyArmourClassBonusByPoints(float points, object oPC); void ClearSubraceTemporaryStats(object oPC); void LoadSubraceInfoOnPC(object oPC, string subraceName); void ApplyPermanentSubraceSpellResistance(string subrace, object oPC); void InitiateSubraceChecking(object oPC); int GetFavoredClassExceedsGap(int Race1Favored, int Race2Favored, int Class1, int Class2, int Class3, int Class13Gap, int Class23Gap, int Class12Gap); void ApplySubraceEffect(object oPC, string SubraceTag, int TimeOfDay); void CheckIfCanUseEquipedWeapon(object oPC); void ReadSubraceInformation(string subraceName, object oDM, object oTarget = OBJECT_INVALID); void ReadSubrace(object oDM, int MaxCount, int CurrentCount); void EquipTemporarySubraceClaw(string subraceTag, object oPC, int iTime); void EquipTemporarySubraceSkin(string subraceTag, object oPC, int iTime); void CheckAndSwitchSubrace(object oPC); void SubraceCheckItemActivated(object oPC, object oItem); string Subrace_DefenseRestrictionToString(int ResType); string Subrace_WeaponRestrictionToString(int ResType); string Subrace_TimeToString(int iTime); int CheckIfPCMeetsPrestigiousClassCriteria(object oPC, string SubraceTag); //:: --------------------------------------------------------------------------- //:: Functions for the Subrace Engine. //:: --------------------------------------------------------------------------- void SHA_SendSubraceMessageToPC(object oPC, string message, int Important = TRUE) { if(MINIMALISE_SUBRACE_MESSAGES_TO_PC) { if(Important) { SendMessageToPC(oPC, SUBRACE_ENGINE + message); } } else { SendMessageToPC(oPC, SUBRACE_ENGINE + message); } } void CreateSubrace(int Race, string SubraceName, string HideResRef = "", string UniqueItemResRef = "", int IsLightSensitive = FALSE, int DamageTakenWhileInLight = 0, int IsUndergroundSensitive = FALSE, int DamageTakenWhileInUnderground = 0, int ECL = 0, int IsUndead = FALSE, int PrestigiousSubrace = FALSE) { struct Subrace shaSubrace; shaSubrace.BaseRace = Race; shaSubrace.Name = SubraceName; shaSubrace.SkinResRef = HideResRef; shaSubrace.UniqueItemResRef = UniqueItemResRef; shaSubrace.IsLightSensitive = IsLightSensitive; shaSubrace.DamageTakenWhileInLight = DamageTakenWhileInLight; shaSubrace.IsUndergroundSensitive = IsUndergroundSensitive; shaSubrace.DamageTakenWhileInUnderground = DamageTakenWhileInUnderground; shaSubrace.ECL = ECL; shaSubrace.IsUndead = IsUndead; shaSubrace.PrestigiousSubrace = PrestigiousSubrace; SaveSubraceOnModule(shaSubrace); } void CreateSubraceAlignmentRestriction(string subraceName, int CanBeAlignment_Good = TRUE , int CanBeAlignment_Neutral1 = TRUE, int CanBeAlignment_Evil = TRUE, int CanBeAlignment_Lawful = TRUE, int CanBeAlignment_Neutral2 = TRUE, int CanBeAlignment_Chaotic = TRUE) { struct SubraceAlignmentRestriction shaSubraceAlignRes; shaSubraceAlignRes.subraceName = subraceName; shaSubraceAlignRes.CanBeAlignment_Good = CanBeAlignment_Good; shaSubraceAlignRes.CanBeAlignment_Neutral1 = CanBeAlignment_Neutral1; shaSubraceAlignRes.CanBeAlignment_Evil =CanBeAlignment_Evil; shaSubraceAlignRes.CanBeAlignment_Lawful = CanBeAlignment_Lawful; shaSubraceAlignRes.CanBeAlignment_Neutral2 = CanBeAlignment_Neutral2; shaSubraceAlignRes.CanBeAlignment_Chaotic = CanBeAlignment_Chaotic; SaveSubraceAlignmentRestrictionOnModule(shaSubraceAlignRes); } void CreateSubraceClassRestriction(string subraceName, int CanBe_Barbarian = TRUE, int CanBe_Bard = TRUE, int CanBe_Cleric = TRUE, int CanBe_Druid = TRUE, int CanBe_Fighter = TRUE, int CanBe_Monk = TRUE, int CanBe_Paladin = TRUE, int CanBe_Ranger = TRUE, int CanBe_Rogue = TRUE, int CanBe_Sorcerer = TRUE, int CanBe_Wizard = TRUE) { struct SubraceClassRestriction shaSubraceClassRes; shaSubraceClassRes.subraceName = subraceName; shaSubraceClassRes.CanBe_Barbarian = CanBe_Barbarian; shaSubraceClassRes.CanBe_Bard = CanBe_Bard; shaSubraceClassRes.CanBe_Cleric = CanBe_Cleric; shaSubraceClassRes.CanBe_Druid = CanBe_Druid; shaSubraceClassRes.CanBe_Fighter = CanBe_Fighter; shaSubraceClassRes.CanBe_Monk = CanBe_Monk; shaSubraceClassRes.CanBe_Paladin = CanBe_Paladin; shaSubraceClassRes.CanBe_Ranger = CanBe_Ranger; shaSubraceClassRes.CanBe_Rogue = CanBe_Rogue; shaSubraceClassRes.CanBe_Sorcerer = CanBe_Sorcerer; shaSubraceClassRes.CanBe_Wizard = CanBe_Wizard; SaveSubraceClassRestrictionOnModule(shaSubraceClassRes); } void CreateSubraceSpellResistance(string subraceName, int SpellResistanceBase, int SpellResistanceMax) { struct SubraceSpellResistance shaSubraceSpellRes; shaSubraceSpellRes.subraceName = subraceName; shaSubraceSpellRes.SpellResistanceBase = SpellResistanceBase; shaSubraceSpellRes.SpellResistanceMax = SpellResistanceMax; SaveSubraceSpellResistanceOnModule(shaSubraceSpellRes); } void CreateSubraceAppearance(string subraceName, int AppearanceChangeTime, int MaleAppearance, int FemaleAppearance, int Level = 1) { struct SubraceDifferentAppearance shaSubraceApp; shaSubraceApp.subraceName = subraceName; shaSubraceApp.ChangeAppearanceTime = AppearanceChangeTime; shaSubraceApp.MaleAppearance = MaleAppearance; shaSubraceApp.FemaleAppearance = FemaleAppearance; shaSubraceApp.Level = Level; SaveSubraceAppearanceChangeOnModule(shaSubraceApp); } void AddAdditionalBaseRaceToSubrace(string subraceName, int AdditionalBaseRace) { subraceName = GetStringLowerCase(subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; int Flag = NOFLAGS; switch(AdditionalBaseRace) { case RACIAL_TYPE_DWARF: Flag = FLAG1; break; case RACIAL_TYPE_ELF: Flag = FLAG2; break; case RACIAL_TYPE_GNOME: Flag = FLAG3; break; case RACIAL_TYPE_HALFELF: Flag = FLAG4; break; case RACIAL_TYPE_HALFLING: Flag = FLAG5; break; case RACIAL_TYPE_HALFORC: Flag = FLAG6; break; case RACIAL_TYPE_HUMAN: Flag = FLAG7; break; case RACIAL_TYPE_ALL: Flag = ALLFLAGS; break; default: Flag = NOFLAGS; break; } SetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, Flag, SUBRACE_BASE_RACE_FLAGS); } void AddSubraceEffect(string subraceName, int EffectID, int Value1, int Value2, int nDurationType, float fDuration, int TimeOfDay) { subraceName = GetStringLowerCase(subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; int Count = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_EFFECT_COUNT); Count++; SetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_EFFECT_COUNT, Count); SubraceTag = SubraceTag + IntToString(Count); SetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_EFFECT, EffectID); SetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_EFFECT_VALUE_1, Value1); SetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_EFFECT_VALUE_2, Value2); SetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_EFFECT_DURATION_TYPE, nDurationType); SetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_EFFECT_DURATION, fDuration); SetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_EFFECT_APPLY_TIME, TimeOfDay); } void AddSubraceFavoredClass(string subraceName, int MaleFavoredClass, int FamaleFavoredClass) { subraceName = GetStringLowerCase(subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; SetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_FAVORED_CLASS, MaleFavoredClass + 1, SUBRACE_FAVORED_CLASS_MALE_FLAG); SetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_FAVORED_CLASS, FamaleFavoredClass + 1, SUBRACE_FAVORED_CLASS_FEMALE_FLAG); } void CreateSubracePrestigiousClassRestriction(string subraceName, int MinimumLevels = 1, int CanBe_ArcaneArcher = TRUE, int CanBe_Assasin = TRUE, int CanBe_Blackguard = TRUE, int CanBe_ChampionOfTorm = TRUE, int CanBe_RedDragonDisciple = TRUE, int CanBe_DwarvenDefender = TRUE, int CanBe_HarperScout = TRUE, int CanBe_PaleMaster = TRUE, int CanBe_ShadowDancer = TRUE, int CanBe_Shifter = TRUE, int CanBe_WeaponMaster = TRUE) { subraceName = GetStringLowerCase(subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; SetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION_MINIMUM_LEVELS, MinimumLevels); //Flags SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG1, TRUE); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG2, CanBe_ArcaneArcher); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG3, CanBe_Assasin); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG4, CanBe_Blackguard); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG5, CanBe_ChampionOfTorm); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG6, CanBe_RedDragonDisciple); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG7, CanBe_DwarvenDefender); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG8, CanBe_PaleMaster); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG9, CanBe_ShadowDancer); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG10, CanBe_Shifter); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG11, CanBe_WeaponMaster); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG12, CanBe_HarperScout); } void CreateTemporaryStatModifier(string subraceName, struct SubraceStats Stats, int TimeToApply, int InInteriorArea = TRUE, int InExteriorArea = TRUE, int InNaturalArea = TRUE, int InArtifacialArea = TRUE, int InUndergroundArea = TRUE, int InAbovegroundArea = TRUE) { subraceName = GetStringLowerCase(subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG1, TRUE); if(TimeToApply == TIME_DAY) { SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG2, TRUE); } else if(TimeToApply == TIME_NIGHT) { SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG3, TRUE); } int ModType = Stats.ModType; float StrengthModifier = Stats.StrengthModifier; float DexterityModifier = Stats.DexterityModifier; float ConstitutionModifier = Stats.ConstitutionModifier; float IntelligenceModifier = Stats.IntelligenceModifier; float WisdomModifier = Stats.WisdomModifier; float CharismaModifier = Stats.CharismaModifier; float ACModifier = Stats.ACModifier; float ABModifier = Stats.ABModifier; SubraceTag = SubraceTag + IntToString(TimeToApply); SetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIER_TYPE, ModType); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG4, InInteriorArea); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG5, InExteriorArea); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG6, InArtifacialArea); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG7, InNaturalArea); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG8, InAbovegroundArea); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG9, InUndergroundArea); SetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_STR_MODIFIER, StrengthModifier); SetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_DEX_MODIFIER, DexterityModifier); SetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_CON_MODIFIER, ConstitutionModifier); SetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_WIS_MODIFIER, WisdomModifier); SetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_INT_MODIFIER, IntelligenceModifier); SetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_CHA_MODIFIER, CharismaModifier); SetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_AB_MODIFIER, ABModifier); SetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_AC_MODIFIER, ACModifier); } //For StatModiferType use only SUBRACE_STAT_MODIFIER_TYPE_PERCENTAGE or SUBRACE_STAT_MODIFIER_TYPE_POINTS struct SubraceStats CreateCustomStats(int StatModifierType, float StrengthModifier, float DexterityModifier, float ConstitutionModifier, float IntelligenceModifier, float WisdomModifier, float CharismaModifier, float ACModifier, float ABModifier) { struct SubraceStats Stats; Stats.ModType = StatModifierType; Stats.StrengthModifier = StrengthModifier; Stats.DexterityModifier = DexterityModifier; Stats.ConstitutionModifier = ConstitutionModifier; Stats.IntelligenceModifier = IntelligenceModifier; Stats.WisdomModifier = WisdomModifier; Stats.CharismaModifier = CharismaModifier; Stats.ACModifier = ACModifier; Stats.ABModifier = ABModifier; return Stats; } void SubraceRestrictUseOfWeaponsOfType(string subraceName, int WeaponType, int TimeOfDay = TIME_BOTH, int Allow = FALSE) { //Why bother adding a restriction if you are going to allow the use of all weapons?! if(WeaponType == SUBRACE_RESTRICTION_WEAPON_ALL && Allow) { return; } subraceName = GetStringLowerCase(subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; SetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, SUBRACE_ALLOW_ONLY_THIS_TYPE, SUBRACE_RESTRICTION_FLAGS, Allow); SetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, SUBRACE_HAS_RESTRICTION, SUBRACE_RESTRICTION_FLAGS); SetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, WeaponType, SUBRACE_RESTRICTION_WEAPON); SetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, TimeOfDay, TIME_FLAGS); } void SubraceRestrictUseOfArmourAndShieldsOfType(string subraceName, int Type, int TimeOfDay = TIME_BOTH, int Allow = FALSE) { //Why bother adding a restriction if you are going to allow the use of all armour?! if(Type == SUBRACE_RESTRICTION_DEFENSE_ALL && Allow) { return; } subraceName = GetStringLowerCase(subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; SetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, SUBRACE_ALLOW_ONLY_THIS_TYPE, SUBRACE_RESTRICTION_FLAGS, Allow); SetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, SUBRACE_HAS_RESTRICTION, SUBRACE_RESTRICTION_FLAGS); SetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, Type, SUBRACE_RESTRICTION_DEFENSE); SetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, TimeOfDay, TIME_FLAGS); } void SetupSubraceSwitch(string subraceName, string switchSubraceNames, int Level, int MustMeetRequirements = TRUE) { subraceName = GetStringLowerCase(subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; SetLocalString(oStorer, SubraceTag + "_" + SUBRACE_SWITCH_NAME + IntToString(Level), switchSubraceNames); if(MustMeetRequirements) { SetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_SWITCH_MUST_MEET_REQUIREMENTS + IntToString(Level), TRUE); } } //:: Internal Functions void SaveSubraceOnModule(struct Subrace shaSubrace) { string subraceName = GetStringLowerCase(shaSubrace.Name); string SubraceTag = SUBRACE_TAG + "_" + subraceName; SetLocalInt(oStorer, SubraceTag, TRUE); //Save the count, and the name of the subrace. int iCount = GetLocalInt(oStorer, MODULE_SUBRACE_COUNT); iCount++; SetLocalInt(oStorer, MODULE_SUBRACE_COUNT, iCount); SetLocalString(oStorer, MODULE_SUBRACE_NUMBER + IntToString(iCount), subraceName); int Flag = NOFLAGS; switch(shaSubrace.BaseRace) { case RACIAL_TYPE_DWARF: Flag = FLAG1; break; case RACIAL_TYPE_ELF: Flag = FLAG2; break; case RACIAL_TYPE_GNOME: Flag = FLAG3; break; case RACIAL_TYPE_HALFELF: Flag = FLAG4; break; case RACIAL_TYPE_HALFLING: Flag = FLAG5; break; case RACIAL_TYPE_HALFORC: Flag = FLAG6; break; case RACIAL_TYPE_HUMAN: Flag = FLAG7; break; case RACIAL_TYPE_ALL: Flag = ALLFLAGS; break; default: Flag = NOFLAGS; break; } SetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, Flag, SUBRACE_BASE_RACE_FLAGS); if(shaSubrace.SkinResRef != "none" && shaSubrace.SkinResRef != "") { SetLocalString(oStorer, SubraceTag + "_" + SUBRACE_SKIN + "_1" + "_" + IntToString(TIME_BOTH), shaSubrace.SkinResRef); } if(shaSubrace.UniqueItemResRef != "" && shaSubrace.UniqueItemResRef != "none") { int SubraceUniqueItemCount = 1; SetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_UNIQUEITEM_COUNT, SubraceUniqueItemCount); SetLocalString(oStorer, SubraceTag + "_" + SUBRACE_UNIQUEITEM + "_1", shaSubrace.UniqueItemResRef + "_1"); } SetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_LIGHT_SENSITIVE, SUBRACE_BASE_INFORMATION_FLAGS, shaSubrace.IsLightSensitive); SetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_UNDERGROUND_SENSITIVE, SUBRACE_BASE_INFORMATION_FLAGS, shaSubrace.IsUndergroundSensitive); SetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_UNDEAD, SUBRACE_BASE_INFORMATION_FLAGS, shaSubrace.IsUndead); SetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_PRESTIGIOUS_SUBRACE, SUBRACE_BASE_INFORMATION_FLAGS, shaSubrace.PrestigiousSubrace); if(shaSubrace.DamageTakenWhileInLight != 0) { SetLocalInt(oStorer, SubraceTag + "_" + DAMAGE_AMOUNT_IN_LIGHT, shaSubrace.DamageTakenWhileInLight); } if(shaSubrace.DamageTakenWhileInUnderground != 0) { SetLocalInt(oStorer, SubraceTag + "_" + DAMAGE_AMOUNT_IN_UNDERGROUND, shaSubrace.DamageTakenWhileInUnderground); } if(shaSubrace.ECL != 0) { SetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, shaSubrace.ECL, SUBRACE_BASE_INFORMATION_ECL); } } void SaveSubraceAlignmentRestrictionOnModule(struct SubraceAlignmentRestriction shaSubraceAlignRes) { string subraceName = GetStringLowerCase(shaSubraceAlignRes.subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG1, TRUE); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG2, shaSubraceAlignRes.CanBeAlignment_Good); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG3, shaSubraceAlignRes.CanBeAlignment_Neutral1); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG4, shaSubraceAlignRes.CanBeAlignment_Evil); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG5, shaSubraceAlignRes.CanBeAlignment_Lawful); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG6, shaSubraceAlignRes.CanBeAlignment_Neutral2); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG7, shaSubraceAlignRes.CanBeAlignment_Chaotic); } void SaveSubraceClassRestrictionOnModule(struct SubraceClassRestriction shaSubraceClassRes) { string subraceName = GetStringLowerCase(shaSubraceClassRes.subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; //Flags SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG1, TRUE); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG2, shaSubraceClassRes.CanBe_Barbarian); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG3, shaSubraceClassRes.CanBe_Bard); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG4, shaSubraceClassRes.CanBe_Cleric); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG5, shaSubraceClassRes.CanBe_Druid); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG6, shaSubraceClassRes.CanBe_Fighter); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG7, shaSubraceClassRes.CanBe_Monk); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG8, shaSubraceClassRes.CanBe_Paladin); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG9, shaSubraceClassRes.CanBe_Ranger); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG10, shaSubraceClassRes.CanBe_Rogue); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG11, shaSubraceClassRes.CanBe_Sorcerer); SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG12, shaSubraceClassRes.CanBe_Wizard); } void SaveSubraceSpellResistanceOnModule(struct SubraceSpellResistance shaSubraceSpellRes) { string subraceName = GetStringLowerCase(shaSubraceSpellRes.subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; SetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_SPELL_RESISTANCE, shaSubraceSpellRes.SpellResistanceBase,SUBRACE_SPELL_RESISTANCE_BASE_FLAGS); SetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_SPELL_RESISTANCE, shaSubraceSpellRes.SpellResistanceMax, SUBRACE_SPELL_RESISTANCE_MAX_FLAGS); } void SaveSubraceAppearanceChangeOnModule(struct SubraceDifferentAppearance shaSubraceApp) { string subraceName = GetStringLowerCase(shaSubraceApp.subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; SubraceTag = SubraceTag + "_" + IntToString(shaSubraceApp.Level); SetLocalGroupFlag(oStorer, SubraceTag + "_" + APPEARANCE_CHANGE, shaSubraceApp.ChangeAppearanceTime, TIME_FLAGS); SetLocalGroupFlagValue(oStorer, SubraceTag + "_" + APPEARANCE_CHANGE, shaSubraceApp.MaleAppearance, APPEARANCE_CHANGE_MALE_FLAG); SetLocalGroupFlagValue(oStorer, SubraceTag + "_" + APPEARANCE_CHANGE, shaSubraceApp.FemaleAppearance, APPEARANCE_CHANGE_FEMALE_FLAG); } void AddAdditionalSkinsToSubrace(string subraceName, string SkinResRef, int EquipLevel, int iTime = TIME_BOTH) { subraceName = GetStringLowerCase(subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; SetLocalString(oStorer, SubraceTag + "_" + SUBRACE_SKIN + "_" + IntToString(EquipLevel) + "_" + IntToString(iTime), SkinResRef); } void AddClawsToSubrace(string subraceName, string RightClawResRef, string LeftClawResRef , int EquipLevel, int iTime = TIME_BOTH) { subraceName = GetStringLowerCase(subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; if(RightClawResRef != "") { SetLocalString(oStorer, SubraceTag + "_" + SUBRACE_RIGHT_CLAW + "_" + IntToString(EquipLevel) + "_" + IntToString(iTime), RightClawResRef); } if(LeftClawResRef != "") { SetLocalString(oStorer, SubraceTag + "_" + SUBRACE_LEFT_CLAW + "_" + IntToString(EquipLevel) + "_" + IntToString(iTime), LeftClawResRef); } } void AddSubraceItem(string subraceName, string ItemResRef, int Level = 1) { subraceName = GetStringLowerCase(subraceName); string SubraceTag = SUBRACE_TAG + "_" + subraceName; int SubraceUniqueItemCount = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_UNIQUEITEM_COUNT); SubraceUniqueItemCount++; SetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_UNIQUEITEM_COUNT, SubraceUniqueItemCount); SetLocalString(oStorer, SubraceTag + "_" + SUBRACE_UNIQUEITEM + "_" + IntToString(SubraceUniqueItemCount), ItemResRef + "_" + IntToString(Level)); } void SetIsInDarkness(object oPC, int Flag) { string subrace = GetStringLowerCase(GetSubRace(oPC)); if(subrace == "") { return; } string SubraceTag = SUBRACE_TAG + "_" + subrace; int IsLightSens = GetLocalGroupFlag(oPC, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_LIGHT_SENSITIVE, SUBRACE_BASE_INFORMATION_FLAGS); int DmgTakenL = GetLocalInt(oPC, SubraceTag + "_" + DAMAGE_AMOUNT_IN_LIGHT); if(IsLightSens || DmgTakenL > 0) { SetLocalInt(oPC, SUBRACE_IN_SPELL_DARKNESS, Flag); } } int Subrace_GetIsInDarkness(object oPC) { return GetLocalInt(oPC, SUBRACE_IN_SPELL_DARKNESS); } void ApplyLightSensitivity(object oPC) { if(SPELL_DARKNESS_STOPS_LIGHT_SENSITIVITY && Subrace_GetIsInDarkness(oPC)) { return; } if(!GetLocalInt(oPC, "STRUCK_BLIND")) { if(APPLY_LIGHT_BLINDNESS) { if(FortitudeSave(oPC, LIGHT_SENSITIVE_SAVING_THROW_DC) == 0) { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectBlindness(), oPC, RoundsToSeconds(LIGHT_STRUCK_BLIND_FOR_ROUNDS)); } SetLocalInt(oPC, "STRUCK_BLIND", TRUE); DelayCommand(RoundsToSeconds(LIGHT_BLINDNESS_STRIKES_EVERY_ROUND), SetLocalInt(oPC, "STRUCK_BLIND", FALSE)); } } if(APPLY_AB_AND_SAVING_THROW_DECREASES_IN_LIGHT && !GetLocalInt(oPC, "STRUCK_LIGHT_DEC")) { effect ABDecrease = EffectAttackDecrease(LIGHT_AB_DECREASE, ATTACK_BONUS_ONHAND); effect ABDecrease1 = EffectAttackDecrease(LIGHT_AB_DECREASE, ATTACK_BONUS_OFFHAND); effect SaveDecrease = EffectSavingThrowDecrease(SAVING_THROW_ALL, LIGHT_SAVE_DECREASE, SAVING_THROW_TYPE_ALL); effect Link = EffectLinkEffects(ABDecrease, ABDecrease1); Link = SupernaturalEffect(EffectLinkEffects(SaveDecrease, Link)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, Link, oPC, RoundsToSeconds(LIGHT_CAUSES_AB_AND_SAVES_DECREASE_FOR_ROUNDS + 1)); SetLocalInt(oPC, "STRUCK_LIGHT_DEC", TRUE); DelayCommand(RoundsToSeconds(LIGHT_CAUSES_AB_AND_SAVES_DECREASE_FOR_ROUNDS), SetLocalInt(oPC, "STRUCK_LIGHT_DEC", FALSE)); } } int GetIsPCLightSensitive(object oPC) { string SubraceTag = SUBRACE_TAG + "_" + GetStringLowerCase(GetSubRace(oPC)); return GetLocalGroupFlag(oPC, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_LIGHT_SENSITIVE, SUBRACE_BASE_INFORMATION_FLAGS); } void ApplyUndergroundSensitivity(object oPC) { if(!GetLocalInt(oPC, "STRUCK_BLIND_UND")) { if(FortitudeSave(oPC, DARK_SENSITIVE_SAVING_THROW_DC) == 0) { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectBlindness(), oPC, DARK_STRUCK_BLIND_FOR_ROUNDS*6.0); } SetLocalInt(oPC, "STRUCK_BLIND_UND", TRUE); DelayCommand(RoundsToSeconds(DARK_BLINDNESS_STRIKES_EVERY_ROUND), SetLocalInt(oPC, "STRUCK_BLIND_UND", FALSE)); } } void SubraceSpontaneouslyCombust(object oPC) { if(ReflexSave(oPC, SUBRACE_SPONTANEOUSLY_COMBUST_DC) != 0) { return; } effect FireDmg = EffectDamage(d8(), DAMAGE_TYPE_FIRE, DAMAGE_POWER_NORMAL); effect VisEffect = EffectVisualEffect(VFX_IMP_FLAME_S); effect iLink = EffectLinkEffects(FireDmg, VisEffect); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, iLink, oPC, 6.0); } void ApplyDamageWhileInLight(object oPC, int DmgTaken) { if(SPELL_DARKNESS_STOPS_LIGHT_SENSITIVITY && Subrace_GetIsInDarkness(oPC)) { return; } if(!GetLocalInt(oPC, "SB_LGHT_DMGED")) { SetLocalInt(oPC, "SB_LGHT_DMGED", TRUE); effect LightDamage; if(DmgTaken > 0) { LightDamage = EffectDamage(DmgTaken, DAMAGE_TYPE_DIVINE, DAMAGE_POWER_ENERGY); } else if(DmgTaken < 0) { DmgTaken = abs(DmgTaken); LightDamage = EffectRegenerate(DmgTaken, 1.0); } if(SUBRACE_SPONTANEOUS_COMBUSTION_WHILE_IN_LIGHT) { if(d100() <= SUBRACE_SPONTANEOUS_COMBUSTION_PERCENTAGE) { int i = 0; //Combust visual effect. effect eDur = EffectVisualEffect(498); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDur, oPC, RoundsToSeconds(LIGHT_DAMAGES_EVERY_ROUNDS)); while(i != LIGHT_DAMAGES_EVERY_ROUNDS) { DelayCommand(RoundsToSeconds(i), SubraceSpontaneouslyCombust(oPC)); i++; } } } ApplyEffectToObject(DURATION_TYPE_TEMPORARY, LightDamage, oPC, 1.0); DelayCommand(RoundsToSeconds(LIGHT_DAMAGES_EVERY_ROUNDS), SetLocalInt(oPC,"SB_LGHT_DMGED", FALSE)); } } void ApplyDamageWhileInDark(object oPC, int DmgTaken) { if(!GetLocalInt(oPC, "SB_DARK_DMGED")) { SetLocalInt(oPC, "SB_DARK_DMGED", TRUE); effect DarkDamage; if(DmgTaken > 0) { DarkDamage = EffectDamage(DmgTaken, DAMAGE_TYPE_NEGATIVE, DAMAGE_POWER_ENERGY); } else if(DmgTaken < 0) { DmgTaken = abs(DmgTaken); DarkDamage = EffectRegenerate(DmgTaken, 1.0); } ApplyEffectToObject(DURATION_TYPE_TEMPORARY, DarkDamage, oPC, 1.0); DelayCommand(RoundsToSeconds(DARKNESS_DAMAGES_EVERY_ROUNDS), SetLocalInt(oPC,"SB_DARK_DMGED", FALSE)); } } int CheckIfPCMeetsBaseRaceCriteria(object oPC, string SubraceTag) { int PCRace = GetRacialType(oPC); int iResult = FALSE; switch(PCRace) { case RACIAL_TYPE_DWARF: { if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG1, SUBRACE_BASE_RACE_FLAGS)) { iResult = TRUE; } break; } case RACIAL_TYPE_ELF: { if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG2, SUBRACE_BASE_RACE_FLAGS)) { iResult = TRUE; } break; } case RACIAL_TYPE_GNOME: { if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG3, SUBRACE_BASE_RACE_FLAGS)) { iResult = TRUE; } break; } case RACIAL_TYPE_HALFELF: { if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG4, SUBRACE_BASE_RACE_FLAGS)) { iResult = TRUE; } break; } case RACIAL_TYPE_HALFLING: { if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG5, SUBRACE_BASE_RACE_FLAGS)) { iResult = TRUE; } break; } case RACIAL_TYPE_HALFORC: { if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG6, SUBRACE_BASE_RACE_FLAGS)) { iResult = TRUE; } break; } case RACIAL_TYPE_HUMAN: { if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG7, SUBRACE_BASE_RACE_FLAGS)) { iResult = TRUE; } break; } case RACIAL_TYPE_ALL: { if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, ALLFLAGS, SUBRACE_BASE_RACE_FLAGS)) { iResult = TRUE; } break; } default: { if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, NOFLAGS, SUBRACE_BASE_RACE_FLAGS)) { iResult = TRUE; } break; } } return iResult; //return CheckPCRaceFitsAdditionalBaseRace(oPC, SubraceTag, NumberOfBaseRace); } int CheckIfPCMeetsClassCriteria(object oPC, string SubraceTag) { int check = FALSE; int PCClass = GetClassByPosition(1, oPC); int canBeBarbarian = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG2); int canBeBard = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG3); int canBeCleric = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG4); int canBeDruid = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG5); int canBeFighter = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG6); int canBeMonk = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG7); int canBePaladin = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG8); int canBeRanger = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG9); int canBeRogue = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG10); int canBeSorcerer = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG11); int canBeWizard = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG12); if((PCClass == CLASS_TYPE_BARBARIAN && canBeBarbarian) || (PCClass == CLASS_TYPE_BARD && canBeBard) || (PCClass == CLASS_TYPE_CLERIC && canBeCleric) || (PCClass == CLASS_TYPE_DRUID && canBeDruid) || (PCClass == CLASS_TYPE_FIGHTER && canBeFighter) || (PCClass == CLASS_TYPE_MONK && canBeMonk) || (PCClass == CLASS_TYPE_PALADIN && canBePaladin) || (PCClass == CLASS_TYPE_RANGER && canBeRanger) || (PCClass == CLASS_TYPE_ROGUE && canBeRogue) || (PCClass == CLASS_TYPE_SORCERER && canBeSorcerer) || (PCClass == CLASS_TYPE_WIZARD && canBeWizard)) { check = TRUE; } return check; } int CheckIfPCMeetsPrestigiousClassCriteria(object oPC, string SubraceTag) { int MinLevel = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION_MINIMUM_LEVELS); //Flags SetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG1, TRUE); int CanBe_AA = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG2); int CanBe_ASS = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG3); int CanBe_BG = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG4); int CanBe_COT = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG5); int CanBe_RDD = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG6); int CanBe_DD = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG7); int CanBe_PM = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG8); int CanBe_SD = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG9); int CanBe_SHF = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG10); int CanBe_WM = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG11); int CanBe_Harper = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION, FLAG12); int PClass1 = GetClassByPosition(2, oPC); int PClass2 = GetClassByPosition(3, oPC); int PClass1Level = GetLevelByClass(PClass1, oPC); int PClass2Level = GetLevelByClass(PClass2, oPC); int Class1Check = FALSE; int Class2Check = FALSE; switch(PClass1) { case CLASS_TYPE_ARCANE_ARCHER: if(CanBe_AA) { Class1Check = TRUE; } break; case CLASS_TYPE_ASSASSIN: if(CanBe_ASS) { Class1Check = TRUE; } break; case CLASS_TYPE_BLACKGUARD: if(CanBe_BG) { Class1Check = TRUE; } break; case CLASS_TYPE_DIVINE_CHAMPION: if(CanBe_COT) { Class1Check = TRUE; } break; case CLASS_TYPE_DRAGON_DISCIPLE: if(CanBe_RDD) { Class1Check = TRUE; } break; case CLASS_TYPE_DWARVEN_DEFENDER: if(CanBe_DD) { Class1Check = TRUE; } break; case CLASS_TYPE_HARPER: if(CanBe_Harper) { Class1Check = TRUE; } break; case CLASS_TYPE_PALE_MASTER: if(CanBe_PM) { Class1Check = TRUE; } break; case CLASS_TYPE_SHADOWDANCER: if(CanBe_SD) { Class1Check = TRUE; } break; case CLASS_TYPE_SHIFTER: if(CanBe_SHF) { Class1Check = TRUE; } break; case CLASS_TYPE_WEAPON_MASTER: if(CanBe_WM) { Class1Check = TRUE; } break; default: break; } switch(PClass2) { case CLASS_TYPE_ARCANE_ARCHER: if(CanBe_AA) { Class2Check = TRUE; } break; case CLASS_TYPE_ASSASSIN: if(CanBe_ASS) { Class2Check = TRUE; } break; case CLASS_TYPE_BLACKGUARD: if(CanBe_BG) { Class2Check = TRUE; } break; case CLASS_TYPE_DIVINE_CHAMPION: if(CanBe_COT) { Class2Check = TRUE; } break; case CLASS_TYPE_DRAGON_DISCIPLE: if(CanBe_RDD) { Class2Check = TRUE; } break; case CLASS_TYPE_DWARVEN_DEFENDER: if(CanBe_DD) { Class2Check = TRUE; } break; case CLASS_TYPE_HARPER: if(CanBe_Harper) { Class2Check = TRUE; } break; case CLASS_TYPE_PALE_MASTER: if(CanBe_PM) { Class2Check = TRUE; } break; case CLASS_TYPE_SHADOWDANCER: if(CanBe_SD) { Class2Check = TRUE; } break; case CLASS_TYPE_SHIFTER: if(CanBe_SHF) { Class2Check = TRUE; } break; case CLASS_TYPE_WEAPON_MASTER: if(CanBe_WM) { Class2Check = TRUE; } break; default: break; } if(!Class1Check && !Class2Check) { return FALSE; } if(Class1Check && Class2Check) { if(PClass1Level + PClass2Level >= MinLevel) { return TRUE; } else { return FALSE; } } if(Class1Check) { if(PClass1Level >= MinLevel) { return TRUE; } else { return FALSE; } } if(Class2Check) { if(PClass2Level >= MinLevel) { return TRUE; } else { return FALSE; } } return FALSE; } int CheckIfPCMeetsAlignmentCriteria(object oPC, string SubraceTag) { int check1 = FALSE; int check2 = FALSE; int PCAlign1 = GetAlignmentGoodEvil(oPC); int PCAlign2 = GetAlignmentLawChaos(oPC); int align1 = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG2); int align2 = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG3); int align3 = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG4); int align4 = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG5); int align5 = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG6); int align6 = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG7); if((PCAlign1 == ALIGNMENT_GOOD && align1) || (PCAlign1 == ALIGNMENT_NEUTRAL && align2) || (PCAlign1 == ALIGNMENT_EVIL && align3)) {check1 = TRUE;} if((PCAlign2 == ALIGNMENT_LAWFUL && align4) || (PCAlign2 == ALIGNMENT_NEUTRAL && align5) || (PCAlign2 == ALIGNMENT_CHAOTIC && align6)) {check2 = TRUE;} if(check1 && check2) { return TRUE; } else { return FALSE;} } int CheckIfPCMeetsAnySubraceCriteria(object oPC) { string subraceName = GetStringLowerCase(GetSubRace(oPC)); int check = FALSE; string SubraceTag = SUBRACE_TAG + "_" + subraceName; int CheckForSubrace = GetLocalInt(oStorer, SubraceTag); if(CheckForSubrace) { int IsPrestigious = GetLocalGroupFlag(oPC, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_PRESTIGIOUS_SUBRACE, SUBRACE_BASE_INFORMATION_FLAGS); if(IsPrestigious && GetPlayerLevel(oPC) == 1) { SHA_SendSubraceMessageToPC(oPC, "The sub-race you had chosen was a prestigious sub-race... you cannot become part of this sub-race directly (Contact a DM for more info)!", TRUE); check = FALSE; SetSubRace(oPC, ""); return check; } if(IsPrestigious && GetPlayerLevel(oPC) > 1) { int checkPClass = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_PRESTIGIOUS_CLASS_RESTRICTION); if(checkPClass != 0) { if(!CheckIfPCMeetsPrestigiousClassCriteria(oPC, SubraceTag)) { SHA_SendSubraceMessageToPC(oPC, "You have failed to meet the prestigious class restrictions!", TRUE); SetSubRace(oPC, ""); return FALSE; } } } int checkRace = CheckIfPCMeetsBaseRaceCriteria(oPC, SubraceTag); if(checkRace) { int CheckForAlignment = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_ALIGNMENT_RESTRICTION, FLAG1); if(CheckForAlignment) { int checkAlign = CheckIfPCMeetsAlignmentCriteria(oPC, SubraceTag); if(checkAlign) { int CheckForClass = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG1); if(CheckForClass) { int checkClass = CheckIfPCMeetsClassCriteria(oPC,SubraceTag); if(checkClass) { SHA_SendSubraceMessageToPC(oPC, "You have met all the requirements for your chosen subrace!", TRUE); check = TRUE; } else { SHA_SendSubraceMessageToPC(oPC, "You have not met the class requirements for your chosen subrace.", TRUE); check = FALSE; SetSubRace(oPC, ""); } } else { //NO NEED FOR CLASS CHECKING SHA_SendSubraceMessageToPC(oPC, "You have met all the requirements for your chosen subrace!", TRUE); check = TRUE; } } else { //FAILED ALIGNMENT CRITERIA SHA_SendSubraceMessageToPC(oPC, "You have not met the alignment requirements for your chosen subrace.", TRUE); check = FALSE; SetSubRace(oPC, ""); } } else { //NO NEED FOR ALIGNMENT CHECKING int CheckForClass = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_CLASS_RESTRICTION, FLAG1); if(CheckForClass) { int checkClass = CheckIfPCMeetsClassCriteria(oPC,SubraceTag); if(checkClass) { SHA_SendSubraceMessageToPC(oPC, "You have met all the requirements for your chosen subrace!", TRUE); check = TRUE; } else { SHA_SendSubraceMessageToPC(oPC, "You have not met the class requirements for your chosen subrace.", TRUE); check = FALSE; SetSubRace(oPC, ""); } } else { //NO NEED FOR CLASS CHECKING SHA_SendSubraceMessageToPC(oPC, "You have met all the requirements for your chosen subrace!", TRUE); check = TRUE; } } } else { SHA_SendSubraceMessageToPC(oPC, "You are not part of the base race required in order to be part of your chosen sub-race.", TRUE); check = FALSE; SetSubRace(oPC, ""); //FAILED BASE RACE } } else { SHA_SendSubraceMessageToPC(oPC, "You are part of an unrecognised sub-race: " + GetSubRace(oPC), TRUE); check = SUBRACE_UNRECOGNISED; //FAILED TO FIND ANY SUCH SUBRACE } return check; } string GetTemporarySubraceSkin(object oPC, string SubraceTag, int iTime) { int Level = GetPlayerLevel(oPC); string SkinResRef; while(Level > 0) { string resref = GetLocalString(oPC, SubraceTag + "_" + SUBRACE_SKIN + "_" + IntToString(Level) + "_" + IntToString(iTime)); if(resref != "") { SkinResRef = resref; break; } Level--; } return SkinResRef; } void EquipTemporarySubraceSkin(string subraceTag, object oPC, int iTime) { string oSkin = GetTemporarySubraceSkin(oPC, subraceTag, iTime); if(oSkin == "") { oSkin = GetTemporarySubraceSkin(oPC, subraceTag, TIME_BOTH); } object ExistingSkin = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC); string ResrefExistingSkin = GetStringLowerCase(GetResRef(ExistingSkin)); if(ResrefExistingSkin != oSkin) { object NewSkin = CreateItemOnObject(oSkin, oPC); if(GetIsObjectValid(ExistingSkin)) { SetPlotFlag(ExistingSkin, FALSE); DestroyObject(ExistingSkin, 0.2); } SetIdentified(NewSkin, TRUE); DelayCommand(1.0, AssignCommand(oPC, SHA_SubraceForceEquipItem(NewSkin, INVENTORY_SLOT_CARMOUR))); } } string GetTemporarySubraceClaw(object oPC, string subraceTag, string Claw, int iTime) { int Level = GetPlayerLevel(oPC); string ClawResRef = ""; while(Level > 0) { string resref = GetLocalString(oPC, subraceTag + "_" + Claw + "_" + IntToString(Level) + "_" + IntToString(iTime)); if(resref != "") { ClawResRef = resref; break; } Level--; } return ClawResRef; } void EquipTemporarySubraceClaw(string subraceTag, object oPC, int iTime) { string sLeftClaw = GetTemporarySubraceClaw(oPC, subraceTag, SUBRACE_LEFT_CLAW, iTime); string sRightClaw = GetTemporarySubraceClaw(oPC, subraceTag, SUBRACE_RIGHT_CLAW, iTime); if(sLeftClaw == "") { sLeftClaw = GetTemporarySubraceClaw(oPC, subraceTag, SUBRACE_LEFT_CLAW, TIME_BOTH); } if(sRightClaw == "") { sRightClaw = GetTemporarySubraceClaw(oPC, subraceTag, SUBRACE_RIGHT_CLAW, TIME_BOTH); } object ExistingLeftClaw = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oPC); object ExistingRightClaw = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oPC); string ResrefExistingLClaw = GetStringLowerCase(GetResRef(ExistingLeftClaw)); string ResrefExistingRClaw = GetStringLowerCase(GetResRef(ExistingRightClaw)); if((ResrefExistingRClaw != sRightClaw) || (ResrefExistingLClaw != sLeftClaw)) { SHA_SendSubraceMessageToPC(oPC, "Please wait... while your sub-racial claws are checked and equipped or unequipped.", FALSE); if(!GetHasFeat(FEAT_WEAPON_PROFICIENCY_CREATURE, oPC)) { SHA_SendSubraceMessageToPC(oPC, "You do not have creature weapon proficiency... yet your subrace wants to equip a creature claw. Inform a DM!", TRUE); return; } DelayCommand(9.0, SHA_SendSubraceMessageToPC(oPC, "Your new sub-racial claws should have now been properly equipped or unequipped.", FALSE)); } if(ResrefExistingRClaw != sRightClaw) { object NewRClaw = CreateItemOnObject(sRightClaw, oPC); if(sRightClaw == "none" || GetIsObjectValid(ExistingRightClaw)) { SetPlotFlag(ExistingRightClaw, FALSE); DestroyObject(ExistingRightClaw, 0.2); } SetIdentified(NewRClaw, TRUE); DelayCommand(1.0, AssignCommand(oPC, SHA_SubraceForceEquipItem(NewRClaw, INVENTORY_SLOT_CWEAPON_R))); } if(ResrefExistingLClaw != sLeftClaw) { object NewLClaw = CreateItemOnObject(sLeftClaw, oPC); if(sLeftClaw == "none" || GetIsObjectValid(ExistingLeftClaw)) { SetPlotFlag(ExistingLeftClaw, FALSE); DestroyObject(ExistingLeftClaw, 0.3); } SetIdentified(NewLClaw, TRUE); DelayCommand(5.0, AssignCommand(oPC, SHA_SubraceForceEquipItem(NewLClaw, INVENTORY_SLOT_CWEAPON_L))); } } void SearchAndDestroySkinsAndClaws(object oPC) { object oItem = GetFirstItemInInventory(oPC); while(GetIsObjectValid(oItem)) { int iType = GetBaseItemType(oItem); if(iType == BASE_ITEM_CREATUREITEM || iType == BASE_ITEM_CPIERCWEAPON || iType == BASE_ITEM_CSLASHWEAPON || iType == BASE_ITEM_CSLSHPRCWEAP) { SetPlotFlag(oItem, FALSE); DestroyObject(oItem, 0.1); } oItem = GetNextItemInInventory(oPC); } } void GiveSubraceUniqueItem(string SubraceTag, object oPC) { int SubraceUniqueItemCount = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_UNIQUEITEM_COUNT); int i = 0; while(i <= SubraceUniqueItemCount) { i++; string resref = GetLocalString(oStorer, SubraceTag + "_" + SUBRACE_UNIQUEITEM + "_" + IntToString(i)); if(resref != "") { string sLevel = GetStringRight(resref, 2); if(GetStringLeft(sLevel, 1) == "_") { sLevel = GetStringRight(sLevel, 1); } int iLevel = StringToInt(sLevel); resref = GetStringLeft(resref, GetStringLength(resref) - 2); if(iLevel <= GetPlayerLevel(oPC)) { object oItem = GetFirstItemInInventory(oPC); int HasUniqueItem = FALSE; while(GetIsObjectValid(oItem)) { if(GetResRef(oItem) == resref) { HasUniqueItem = TRUE; break; } oItem = GetNextItemInInventory(oPC); } if(!HasUniqueItem) { object oItem = CreateItemOnObject(resref, oPC, 1); SHA_SendSubraceMessageToPC(oPC, "You have acquired " + GetName(oItem) + "; a sub-racial item.", FALSE); SetIdentified(oItem, TRUE); SetPlotFlag(oItem, TRUE); } } } } } void CheckAndGiveSubraceItems(object oPC) { string subrace = GetSubRace(oPC); string SubraceTag = SUBRACE_TAG + "_" + GetStringLowerCase(subrace); GiveSubraceUniqueItem(SubraceTag, oPC); } int SHA_GetDefaultAppearanceType(object oPC) { int iRace = GetRacialType(oPC); int DefaultAppearance; switch(iRace) { case RACIAL_TYPE_DWARF: DefaultAppearance = APPEARANCE_TYPE_DWARF; break; case RACIAL_TYPE_ELF: DefaultAppearance = APPEARANCE_TYPE_ELF; break; case RACIAL_TYPE_GNOME: DefaultAppearance = APPEARANCE_TYPE_GNOME; break; case RACIAL_TYPE_HALFELF: DefaultAppearance = APPEARANCE_TYPE_HALF_ELF; break; case RACIAL_TYPE_HALFLING: DefaultAppearance = APPEARANCE_TYPE_HALFLING; break; case RACIAL_TYPE_HALFORC: DefaultAppearance = APPEARANCE_TYPE_HALF_ORC; break; case RACIAL_TYPE_HUMAN: DefaultAppearance = APPEARANCE_TYPE_HUMAN; break; default: DefaultAppearance = APPEARANCE_TYPE_HUMAN; break; } return DefaultAppearance; } int Subrace_GetFavouredClass(object oPC) { int iClass = -1; if(GetLocalInt(oPC, SUBRACE_FAVORED_CLASS) != 0) { iClass = GetLocalInt(oPC, SUBRACE_FAVORED_CLASS) - 1; } return iClass; } int GetRacialFavoredClass(int Race) { int Class = CLASS_TYPE_NONE; switch(Race) { case RACIAL_TYPE_DWARF: Class = CLASS_TYPE_FIGHTER; break; case RACIAL_TYPE_HUMAN: Class = CLASS_TYPE_ANY; break; case RACIAL_TYPE_ELF: Class = CLASS_TYPE_WIZARD; break; case RACIAL_TYPE_GNOME: Class = CLASS_TYPE_WIZARD; break; case RACIAL_TYPE_HALFELF: Class = CLASS_TYPE_ANY; break; case RACIAL_TYPE_HALFORC: Class = CLASS_TYPE_BARBARIAN; break; case RACIAL_TYPE_HALFLING: Class = CLASS_TYPE_ROGUE; break; } return Class; } int GetFavoredClassExceedsGap(int Race1Favored, int Race2Favored, int Class1, int Class2, int Class3, int Class13Gap, int Class23Gap, int Class12Gap) { //Has PC got Race 1 Favored class? int iR1Class1Favored = FALSE; int iR1Class2Favored = FALSE; int iR1Class3Favored = FALSE; //Has PC got Race 2 Favored class? int iR2Class1Favored = FALSE; int iR2Class2Favored = FALSE; int iR2Class3Favored = FALSE; if(Race1Favored == Class1) { iR1Class1Favored = TRUE; } if(Race1Favored == Class2 && Class2 != CLASS_TYPE_INVALID) { iR1Class2Favored = TRUE; } if(Race1Favored == Class3 && Class3 != CLASS_TYPE_INVALID) { iR1Class3Favored = TRUE; } if(Race2Favored == Class1) { iR2Class1Favored = TRUE; } if(Race2Favored == Class2 && Class2 != CLASS_TYPE_INVALID) { iR2Class2Favored = TRUE; } if(Race2Favored == Class3 && Class3 != CLASS_TYPE_INVALID) { iR2Class3Favored = TRUE; } int Exceed12 = FALSE; int Exceed13 = FALSE; int Exceed23 = FALSE; int iResult12 = FALSE; int iResult13 = FALSE; int iResult23 = FALSE; if(abs(Class12Gap) >=2) { Exceed12 = TRUE; } else if(abs(Class13Gap) >=2) { Exceed13 = TRUE; } else if(abs(Class23Gap) >=2) { Exceed23 = TRUE; } if(Exceed12) { if(iR1Class1Favored || iR1Class2Favored) { iResult12 = TRUE; if((iR2Class1Favored && Class3 != CLASS_TYPE_INVALID) || (iR2Class2Favored && Class3 != CLASS_TYPE_INVALID)) { iResult12 = FALSE; } } } if(Exceed13) { if(iR1Class1Favored || iR1Class3Favored) { iResult13 = TRUE; if(iR2Class1Favored ||iR2Class3Favored) { iResult13 = FALSE; } } } if(Exceed23) { if(iR1Class2Favored || iR1Class3Favored) { iResult23 = TRUE; if(iR2Class2Favored ||iR2Class3Favored) { iResult23 = FALSE; } } } if(iResult12 || iResult13 || iResult23) { return TRUE; } else { return FALSE; } } int XPPenaltyOrBoostForSubrace(object oPC, int FClass) { int iRace = GetRacialType(oPC); int iRFavored = GetRacialFavoredClass(iRace); int iSFavored = FClass; if(iSFavored == iRFavored) { return SUBRACE_XP_UNCHANGED; } int Class1 = GetClassByPosition(1, oPC); int Class2 = GetClassByPosition(2, oPC); int Class3 = GetClassByPosition(3, oPC); int Class1Level = GetLevelByClass(Class1, oPC); int Class2Level = GetLevelByClass(Class2, oPC); int Class3Level = GetLevelByClass(Class3, oPC); if(iRFavored == CLASS_TYPE_ANY) { int Max1 = Max(Class1Level, Class2Level); int Max2 = Max(Max1, Class3Level); if(Max2 == Class1Level) { iRFavored = Class1; } else if(Max2 == Class2Level) { iRFavored = Class2; } else if(Max2 == Class3Level) { iRFavored = Class3; } } if(iSFavored == CLASS_TYPE_ANY) { int Max1 = Max(Class1Level, Class2Level); int Max2 = Max(Max1, Class3Level); if(Max2 == Class1Level) { iSFavored = Class1; } else if(Max2 == Class2Level) { iSFavored = Class2; } else if(Max2 == Class3Level) { iSFavored = Class3; } } int Class12Gap = Class1Level - Class2Level; int Class13Gap = Class1Level - Class3Level; int Class23Gap = Class2Level - Class3Level; if(Class2Level == 0) { Class12Gap = 0; Class23Gap = 0; } if(Class3Level == 0) { Class13Gap = 0; } int SubraceFClassExcGap = FALSE; int RacialFClassExcGap = FALSE; if(SUBRACE_IGNORE_BASE_RACE_FAVORED_CLASS) { RacialFClassExcGap = GetFavoredClassExceedsGap(iRFavored, iSFavored, Class1, Class2, Class3, Class13Gap, Class23Gap, Class12Gap); } SubraceFClassExcGap = GetFavoredClassExceedsGap(iSFavored, iRFavored, Class1, Class2, Class3, Class13Gap, Class23Gap, Class12Gap); //Racial Favored Class Exceeds the Multiclass Level gap, and Subrace Favored class does not //So give a decrease in XP to counter NWN engine XP distribution. if(RacialFClassExcGap && !SubraceFClassExcGap) { return SUBRACE_XP_DECREASE; } //Subrace Favored Class Exceeds the Multiclass Level gap, and Racial Favored class does not //So give a boost in XP to override the NWN engine XP distribution. else if(!RacialFClassExcGap && SubraceFClassExcGap) { return SUBRACE_XP_BOOST; } //Both exceed the Multiclass Level gap or do not. //So since the effects of both exceeding cancel each other out, return normal XP. return SUBRACE_XP_UNCHANGED; } float GetSubraceXPModifier(object oPC) { int FClass = Subrace_GetFavouredClass(oPC); float iMod = 1.0; if(FClass != -1) { int XPMod = XPPenaltyOrBoostForSubrace(oPC, FClass); if(XPMod == SUBRACE_XP_BOOST) { iMod = 1.25; } else if(XPMod == SUBRACE_XP_DECREASE) { iMod = 0.8; } else if(XPMod == SUBRACE_XP_UNCHANGED) { } } return iMod; } int GetECL(object oPC) { string SubraceTag = SUBRACE_TAG + "_" + GetStringLowerCase(GetSubRace(oPC)); return GetLocalGroupFlagValue(oPC, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_ECL); } int Subrace_GetIsUndead(object oTarget) { if(!GetIsPC(oTarget)) { return FALSE; } string subraceName = GetStringLowerCase(GetSubRace(oTarget)); if(subraceName == "") { return FALSE; } string SubraceTag = SUBRACE_TAG + "_" + subraceName; int IsUndead = GetLocalGroupFlag(oTarget, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_UNDEAD, SUBRACE_BASE_INFORMATION_FLAGS); return IsUndead; } void ApplyUniqueSubraceEffect(object oPC, string SubraceTag, int iEffect) { if(iEffect == 0) { return; } int Value1 = GetLocalInt(oPC, SubraceTag + "_" + SUBRACE_EFFECT_VALUE_1); int Value2 = GetLocalInt(oPC, SubraceTag + "_" + SUBRACE_EFFECT_VALUE_2); int DurationType = GetLocalInt(oPC, SubraceTag + "_" + SUBRACE_EFFECT_DURATION_TYPE); float fDuration = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_EFFECT_DURATION); effect eEffect = SHA_GetEffectFromID(iEffect, Value1, Value2); effect eEffectApp = SupernaturalEffect(eEffect); ApplyEffectToObject(DurationType, eEffectApp, oPC, fDuration); } void ApplySubraceEffect(object oPC, string SubraceTag, int TimeOfDay) { int EffectCount = GetLocalInt(oPC, SubraceTag + "_" + SUBRACE_EFFECT_COUNT); if(EffectCount == 0) { return; } ClearSubraceEffects(oPC); int i = 0; while(i != EffectCount) { i++; string SubraceTag1 = SubraceTag + IntToString(i); int Effect = GetLocalInt(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT); int EffectTimeOfDay = GetLocalInt(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT_APPLY_TIME); if(EffectTimeOfDay == TIME_BOTH || EffectTimeOfDay == TimeOfDay) { ApplyUniqueSubraceEffect(oPC, SubraceTag1, Effect); } } SHA_SendSubraceMessageToPC(oPC, "Sub-racial effects have been appiled", FALSE); } void LoadSubraceInfoOnPC(object oPC, string subraceName) { if(GetLocalInt(oPC, SUBRACE_INFO_LOADED_ON_PC)) { ReapplySubraceAbilities(oPC); return; } if(subraceName == "") { return; } string SubraceTag = SUBRACE_TAG + "_" + subraceName; //Oh oh, someone has removed the subrace! >.< if(!GetLocalInt(oStorer, SubraceTag)) { SHA_SendSubraceMessageToPC(oPC, "Data for your sub-race is missing or support for your sub-race has been removed from the server! Contact a DM", TRUE); return; } SHA_SendSubraceMessageToPC(oPC, "Loading your sub-race; " + CapitalizeString(subraceName) + "'s data...", FALSE); //Load all skin resrefs int Level = 1; while(Level <= MAXIMUM_PLAYER_LEVEL) { string resref = GetLocalString(oStorer, SubraceTag + "_" + SUBRACE_SKIN + "_" + IntToString(Level) + "_" + IntToString(TIME_BOTH)); if(resref != "") { SetLocalString(oPC, SubraceTag + "_" + SUBRACE_SKIN + "_" + IntToString(Level) + "_" + IntToString(TIME_BOTH), resref); } //and the temporary skins resref = GetLocalString(oStorer, SubraceTag + "_" + SUBRACE_SKIN + "_" + IntToString(Level) + "_" + IntToString(TIME_DAY)); if(resref != "") { SetLocalString(oPC, SubraceTag + "_" + SUBRACE_SKIN + "_" + IntToString(Level) + "_" + IntToString(TIME_DAY), resref); } resref = GetLocalString(oStorer, SubraceTag + "_" + SUBRACE_SKIN + "_" + IntToString(Level) + "_" + IntToString(TIME_NIGHT)); if(resref != "") { SetLocalString(oPC, SubraceTag + "_" + SUBRACE_SKIN + "_" + IntToString(Level) + "_" + IntToString(TIME_NIGHT), resref); } string switchSubraceName = GetLocalString(oStorer, SubraceTag + "_" + SUBRACE_SWITCH_NAME + IntToString(Level)); if(switchSubraceName != "") { SetLocalString(oPC, SubraceTag + "_" + SUBRACE_SWITCH_NAME + IntToString(Level), switchSubraceName); int requirements = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_SWITCH_MUST_MEET_REQUIREMENTS + IntToString(Level)); if(requirements) { SetLocalInt(oPC, SubraceTag + "_" + SUBRACE_SWITCH_MUST_MEET_REQUIREMENTS + IntToString(Level), requirements); } } Level++; } //Load all creature claws. Level = 1; while(Level <= MAXIMUM_PLAYER_LEVEL) { string resref = GetLocalString(oStorer, SubraceTag + "_" + SUBRACE_LEFT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_BOTH)); if(resref != "") { SetLocalString(oPC, SubraceTag + "_" + SUBRACE_LEFT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_BOTH), resref); } resref = GetLocalString(oStorer, SubraceTag + "_" + SUBRACE_RIGHT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_BOTH)); if(resref != "") { SetLocalString(oPC, SubraceTag + "_" + SUBRACE_RIGHT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_BOTH), resref); } resref = GetLocalString(oStorer, SubraceTag + "_" + SUBRACE_LEFT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_DAY)); if(resref != "") { SetLocalString(oPC, SubraceTag + "_" + SUBRACE_LEFT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_DAY), resref); } resref = GetLocalString(oStorer, SubraceTag + "_" + SUBRACE_RIGHT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_DAY)); if(resref != "") { SetLocalString(oPC, SubraceTag + "_" + SUBRACE_RIGHT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_DAY), resref); } resref = GetLocalString(oStorer, SubraceTag + "_" + SUBRACE_LEFT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_NIGHT)); if(resref != "") { SetLocalString(oPC, SubraceTag + "_" + SUBRACE_LEFT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_NIGHT), resref); } resref = GetLocalString(oStorer, SubraceTag + "_" + SUBRACE_RIGHT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_NIGHT)); if(resref != "") { SetLocalString(oPC, SubraceTag + "_" + SUBRACE_RIGHT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_NIGHT), resref); } Level++; } int iDmgTakenInLight = GetLocalInt(oStorer, SubraceTag + "_" + DAMAGE_AMOUNT_IN_LIGHT); int iDmgTakenInUnder = GetLocalInt(oStorer, SubraceTag + "_" + DAMAGE_AMOUNT_IN_UNDERGROUND); SetLocalString(oPC, SUBRACE_TAG, subraceName); int BaseFlags = GetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_FLAGS); SetLocalGroupFlagValue(oPC, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, BaseFlags, SUBRACE_BASE_INFORMATION_FLAGS); if(iDmgTakenInLight != 0) { SetLocalInt(oPC, SubraceTag + "_" + DAMAGE_AMOUNT_IN_LIGHT, iDmgTakenInLight); } if(iDmgTakenInUnder != 0) { SetLocalInt(oPC, SubraceTag + "_" + DAMAGE_AMOUNT_IN_UNDERGROUND, iDmgTakenInUnder); } Level = 1; while(Level <=40) { string SubraceTag1 = SubraceTag + "_" + IntToString(Level); if(GetLocalInt(oStorer, SubraceTag1 + "_" + APPEARANCE_CHANGE) != 0) { int iTime = GetLocalGroupFlagValue(oStorer, SubraceTag1 + "_" + APPEARANCE_CHANGE,TIME_FLAGS); int MaleAppearance = GetLocalGroupFlagValue(oStorer, SubraceTag1 + "_" + APPEARANCE_CHANGE, APPEARANCE_CHANGE_MALE_FLAG); int FemaleAppearance = GetLocalGroupFlagValue(oStorer, SubraceTag1 + "_" + APPEARANCE_CHANGE, APPEARANCE_CHANGE_FEMALE_FLAG); if(iTime != 0 && (MaleAppearance != 0 || FemaleAppearance !=0)) { SetLocalGroupFlagValue(oPC, SubraceTag1 + "_" + APPEARANCE_CHANGE, iTime ,TIME_FLAGS); if(GetGender(oPC) == GENDER_MALE) { SetLocalGroupFlagValue(oPC, SubraceTag1 + "_" + APPEARANCE_CHANGE,MaleAppearance, APPEARANCE_CHANGE_APPEARANCE_FLAG); } else { SetLocalGroupFlagValue(oPC, SubraceTag1 + "_" + APPEARANCE_CHANGE,FemaleAppearance, APPEARANCE_CHANGE_APPEARANCE_FLAG); } } } Level++; } SubraceTag = SUBRACE_TAG + "_" + subraceName; int HasDiffStats = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG1); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG1, HasDiffStats); if(HasDiffStats) { //day int iTime = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG2); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG2, iTime); if(iTime) { SubraceTag = SubraceTag + IntToString(TIME_DAY); int ModType = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIER_TYPE); int AreaInt = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG4); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG4, AreaInt); int AreaExt = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG5); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG5, AreaExt); int AreaUnd = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG9); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG9, AreaUnd); int AreaAbove = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG8); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG8, AreaAbove); int AreaArt = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG6); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG6, AreaArt); int AreaNat = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG7); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG7, AreaNat); float StrengthModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_STR_MODIFIER); float DexterityModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_DEX_MODIFIER); float ConstitutionModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_CON_MODIFIER); float WisdomModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_WIS_MODIFIER); float IntelligenceModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_INT_MODIFIER); float CharismaModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_CHA_MODIFIER); float ABModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_AB_MODIFIER); float ACModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_AC_MODIFIER); SetLocalInt(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIER_TYPE, ModType); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_STR_MODIFIER, StrengthModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_DEX_MODIFIER, DexterityModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_CON_MODIFIER, ConstitutionModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_WIS_MODIFIER, WisdomModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_INT_MODIFIER, IntelligenceModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_CHA_MODIFIER, CharismaModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_AB_MODIFIER, ABModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_AC_MODIFIER, ACModifier); } SubraceTag = SUBRACE_TAG + "_" + subraceName; //night iTime = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG3); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG3, iTime); if(iTime) { SubraceTag = SubraceTag + IntToString(TIME_NIGHT); int AreaInt = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG4); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG4, AreaInt); int AreaExt = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG5); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG5, AreaExt); int AreaUnd = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG9); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG9, AreaUnd); int AreaAbove = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG8); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG8, AreaAbove); int AreaArt = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG6); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG6, AreaArt); int AreaNat = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG7); SetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG7, AreaNat); float StrengthModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_STR_MODIFIER); float DexterityModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_DEX_MODIFIER); float ConstitutionModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_CON_MODIFIER); float WisdomModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_WIS_MODIFIER); float IntelligenceModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_INT_MODIFIER); float CharismaModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_CHA_MODIFIER); float ABModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_AB_MODIFIER); float ACModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_AC_MODIFIER); int ModType = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIER_TYPE); SetLocalInt(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIER_TYPE, ModType); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_STR_MODIFIER, StrengthModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_DEX_MODIFIER, DexterityModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_CON_MODIFIER, ConstitutionModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_WIS_MODIFIER, WisdomModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_INT_MODIFIER, IntelligenceModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_CHA_MODIFIER, CharismaModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_AB_MODIFIER, ABModifier); SetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_AC_MODIFIER, ACModifier); } } SubraceTag = SUBRACE_TAG + "_" + subraceName; int HasRes = GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, SUBRACE_HAS_RESTRICTION, SUBRACE_RESTRICTION_FLAGS); if(HasRes) { int WepResData = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION); SetLocalInt(oPC, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, WepResData); } HasRes = GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, SUBRACE_HAS_RESTRICTION, SUBRACE_RESTRICTION_FLAGS); if(HasRes) { int DefResData = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION); SetLocalInt(oPC, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, DefResData); } int Count = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_EFFECT_COUNT); if(Count != 0 ) { SetLocalInt(oPC, SubraceTag + "_" + SUBRACE_EFFECT_COUNT, Count); int i = 0; while(i != Count) { i++; string SubraceTag1 = SubraceTag + IntToString(i); int Effect = GetLocalInt(oStorer, SubraceTag1 + "_" + SUBRACE_EFFECT); int Value1 = GetLocalInt(oStorer, SubraceTag1 + "_" + SUBRACE_EFFECT_VALUE_1); int Value2 = GetLocalInt(oStorer, SubraceTag1 + "_" + SUBRACE_EFFECT_VALUE_2); int TimeOfDay = GetLocalInt(oStorer, SubraceTag1 + "_" + SUBRACE_EFFECT_APPLY_TIME); int DurationType = GetLocalInt(oStorer, SubraceTag1 + "_" + SUBRACE_EFFECT_DURATION_TYPE); float fDuration = GetLocalFloat(oStorer, SubraceTag1 + "_" + SUBRACE_EFFECT_DURATION); SetLocalInt(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT, Effect); SetLocalInt(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT_VALUE_1, Value1); SetLocalInt(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT_VALUE_2, Value2); SetLocalInt(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT_DURATION_TYPE, DurationType); SetLocalInt(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT_APPLY_TIME, TimeOfDay); SetLocalFloat(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT_DURATION, fDuration); } } int HasFClass = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_FAVORED_CLASS); if(HasFClass != 0) { int MaleFavoredClass = GetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_FAVORED_CLASS, SUBRACE_FAVORED_CLASS_MALE_FLAG); int FemaleFavoredClass = GetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_FAVORED_CLASS, SUBRACE_FAVORED_CLASS_FEMALE_FLAG); if(GetGender(oPC) == GENDER_MALE) { SetLocalInt(oPC, SUBRACE_FAVORED_CLASS, MaleFavoredClass); } else { SetLocalInt(oPC, SUBRACE_FAVORED_CLASS, FemaleFavoredClass); } } GiveSubraceUniqueItem(SubraceTag, oPC); DelayCommand(3.0, SetLocalInt(oPC, SUBRACE_INFO_LOADED_ON_PC, TRUE)); DelayCommand(12.0, SHA_SendSubraceMessageToPC(oPC, "Your sub-racial data has been loaded on your character.", FALSE)); } void DeleteSubraceInfoOnPC(object oPC) { string subraceName = GetStringLowerCase(GetSubRace(oPC)); string SubraceTag = SUBRACE_TAG + "_" + subraceName; if(subraceName == "") { return; } SHA_SendSubraceMessageToPC(oPC, "Purging sub-race...", FALSE); ClearSubraceTemporaryStats(oPC); ClearSubraceEffects(oPC); ChangeToPCDefaultAppearance(oPC); effect iEffect = GetFirstEffect(oPC); while(GetIsEffectValid(iEffect)) { int iEffectType = GetEffectType(iEffect); if(iEffectType == EFFECT_TYPE_SPELL_RESISTANCE_INCREASE || iEffectType == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE) { RemoveEffect(oPC, iEffect); } iEffect = GetNextEffect(oPC); } DeleteLocalInt(oPC, SUBRACE_INFO_LOADED_ON_PC); int Level = 1; while(Level <= MAXIMUM_PLAYER_LEVEL) { DeleteLocalString(oPC, SubraceTag + "_" + SUBRACE_LEFT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_BOTH)); DeleteLocalString(oPC, SubraceTag + "_" + SUBRACE_RIGHT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_BOTH)); DeleteLocalString(oPC, SubraceTag + "_" + SUBRACE_LEFT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_DAY)); DeleteLocalString(oPC, SubraceTag + "_" + SUBRACE_RIGHT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_DAY)); DeleteLocalString(oPC, SubraceTag + "_" + SUBRACE_LEFT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_NIGHT)); DeleteLocalString(oPC, SubraceTag + "_" + SUBRACE_RIGHT_CLAW + "_" + IntToString(Level) + "_" + IntToString(TIME_NIGHT)); DeleteLocalString(oPC, SubraceTag + "_" + SUBRACE_SWITCH_NAME + IntToString(Level)); DeleteLocalInt(oPC, SubraceTag + "_" + SUBRACE_SWITCH_MUST_MEET_REQUIREMENTS + IntToString(Level)); DeleteLocalInt(oPC, SubraceTag + "_" + IntToString(Level) + "_" + APPEARANCE_CHANGE); DeleteLocalString(oPC, SubraceTag + "_" + SUBRACE_SKIN + "_" + IntToString(Level) + "_" + IntToString(TIME_BOTH)); DeleteLocalString(oPC, SubraceTag + "_" + SUBRACE_SKIN + "_" + IntToString(Level) + "_" + IntToString(TIME_DAY)); DeleteLocalString(oPC, SubraceTag + "_" + SUBRACE_SKIN + "_" + IntToString(Level) + "_" + IntToString(TIME_NIGHT)); Level++; } Level = 40; while(Level != 0) { string SubraceTag1 = SubraceTag + "_" + IntToString(Level); DeleteLocalInt(oStorer, SubraceTag1 + "_" + APPEARANCE_CHANGE); Level--; } DeleteLocalInt(oPC, SubraceTag + "_" + DAMAGE_AMOUNT_IN_LIGHT); DeleteLocalInt(oPC, SubraceTag + "_" + DAMAGE_AMOUNT_IN_UNDERGROUND); DeleteLocalInt(oPC, SubraceTag + "_" + SUBRACE_BASE_INFORMATION); DeleteLocalInt(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS); SubraceTag = SubraceTag + IntToString(TIME_DAY); DeleteLocalInt(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIER_TYPE); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_STR_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_DEX_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_CON_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_WIS_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_INT_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_CHA_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_AB_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_AC_MODIFIER); SubraceTag = SUBRACE_TAG + "_" + subraceName; SubraceTag = SubraceTag + IntToString(TIME_NIGHT); DeleteLocalInt(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIER_TYPE); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_STR_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_DEX_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_CON_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_WIS_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_INT_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_CHA_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_AB_MODIFIER); DeleteLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_AC_MODIFIER); SubraceTag = SUBRACE_TAG + "_" + subraceName; DeleteLocalInt(oPC, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION); DeleteLocalInt(oPC, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION); int Count = GetLocalInt(oPC, SubraceTag + "_" + SUBRACE_EFFECT_COUNT); DeleteLocalInt(oPC, SubraceTag + "_" + SUBRACE_EFFECT_COUNT); if(Count != 0) { int i = 0; while(i != Count) { i++; string SubraceTag1 = SubraceTag + IntToString(i); DeleteLocalInt(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT); DeleteLocalInt(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT_VALUE_1); DeleteLocalInt(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT_VALUE_2); DeleteLocalInt(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT_DURATION_TYPE); DeleteLocalInt(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT_APPLY_TIME); DeleteLocalFloat(oPC, SubraceTag1 + "_" + SUBRACE_EFFECT_DURATION); } } DeleteLocalInt(oPC, SUBRACE_FAVORED_CLASS); object Skin = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC); SetPlotFlag(Skin, FALSE); DestroyObject(Skin, 0.1); object ClawLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oPC); object ClawRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oPC); SetPlotFlag(ClawLeft, FALSE); SetPlotFlag(ClawRight, FALSE); DestroyObject(ClawLeft, 0.5); DestroyObject(ClawRight, 0.5); string oResRef = GetLocalString(oStorer, SubraceTag + "_" + SUBRACE_UNIQUEITEM + "_1"); object oItem = GetFirstItemInInventory(oPC); while(GetIsObjectValid(oItem)) { if(GetResRef(oItem) == oResRef) { SetPlotFlag(oItem, FALSE); DestroyObject(oItem, 0.1); } oItem = GetNextItemInInventory(oPC); } DeleteLocalInt(oPC, SUBRACE_TAG + "SB_NITE_OCE"); DeleteLocalInt(oPC, SUBRACE_TAG + "SB_DAY_OCE"); DeleteLocalInt(oPC, APPEARANCE_TEMP_CHANGED); DeleteLocalInt(oPC, SUBRACE_IN_SPELL_DARKNESS); DeleteLocalInt(oPC, "SUB_EFCT_D_APD"); DeleteLocalInt(oPC, "SUB_EFCT_N_APD"); DeleteLocalInt(oPC,"SB_LGHT_DMGED"); DeleteLocalInt(oPC,"SB_DARK_DMGED"); DeleteLocalInt(oPC, SUBRACE_STATS_STATUS); DelayCommand(4.0, SHA_SendSubraceMessageToPC(oPC, "Purging sub-race...DONE.", FALSE)); } void SHA_SubraceReadSubrace(object oDM, string sStuff) { SendMessageToPC(oDM, sStuff); //PrintString(sStuff); } void ReadAllSubraces(object oDM) { //Save the count, and the name of the subrace. int iCount = GetLocalInt(oStorer, MODULE_SUBRACE_COUNT); SHA_SubraceReadSubrace(oDM, "--------- Module Subraces ----------"); ReadSubrace(oDM, iCount, 1); } void ReadSubrace(object oDM, int MaxCount, int CurrentCount) { if(CurrentCount <= MaxCount) { string subraceName = GetLocalString(oStorer, MODULE_SUBRACE_NUMBER + IntToString(CurrentCount)); string Name = GetStringUpperCase(GetStringLeft(subraceName, 1)) + GetStringRight(subraceName, GetStringLength(subraceName) - 1); SHA_SubraceReadSubrace(oDM, IntToString(CurrentCount) + "."); SHA_SubraceReadSubrace(oDM, " Subrace: " + Name); ReadSubraceInformation(subraceName, oDM); SHA_SubraceReadSubrace(oDM, " "); CurrentCount++; DelayCommand(0.1, ReadSubrace(oDM, MaxCount, CurrentCount)); } if(CurrentCount == MaxCount) { DelayCommand(0.2, SHA_SubraceReadSubrace(oDM, "--------- End Module Subraces --------")); DelayCommand(0.2,SHA_SubraceReadSubrace(oDM, "-- Total Subrace Count: " + IntToString(MaxCount))); } } void ReadSubraceInformation(string subraceName, object oDM, object oTarget = OBJECT_INVALID) { string SubraceTag = SUBRACE_TAG + "_" + subraceName; if(subraceName == "") { SHA_SubraceReadSubrace(oDM, " This player character is not part of a subrace."); return; } if(oTarget != OBJECT_INVALID) { SHA_SubraceReadSubrace(oDM, " Player Subrace: " + CapitalizeString(subraceName)); SHA_SubraceReadSubrace(oDM, " Race: " + race(GetRacialType(oTarget))); if(!GetLocalInt(oStorer, SubraceTag)) { SHA_SubraceReadSubrace(oDM, " This subrace is not supported by this world."); return; } } else { SHA_SubraceReadSubrace(oDM, " Races that qualify: "); if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG1, SUBRACE_BASE_RACE_FLAGS)) { SHA_SubraceReadSubrace(oDM, " Dwarf"); } if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG2, SUBRACE_BASE_RACE_FLAGS)) { SHA_SubraceReadSubrace(oDM, " Elf"); } if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG3, SUBRACE_BASE_RACE_FLAGS)) { SHA_SubraceReadSubrace(oDM, " Gnome"); } if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG4, SUBRACE_BASE_RACE_FLAGS)) { SHA_SubraceReadSubrace(oDM, " Half-elf"); } if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG5, SUBRACE_BASE_RACE_FLAGS)) { SHA_SubraceReadSubrace(oDM, " Halfling"); } if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG6, SUBRACE_BASE_RACE_FLAGS)) { SHA_SubraceReadSubrace(oDM, " Half-Orc"); } if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_RACE, FLAG7, SUBRACE_BASE_RACE_FLAGS)) { SHA_SubraceReadSubrace(oDM, " Human"); } } SHA_SubraceReadSubrace(oDM, " "); SHA_SubraceReadSubrace(oDM, " Base information: "); int iDmgTakenInLight = GetLocalInt(oStorer, SubraceTag + "_" + DAMAGE_AMOUNT_IN_LIGHT); int iDmgTakenInUnder = GetLocalInt(oStorer, SubraceTag + "_" + DAMAGE_AMOUNT_IN_UNDERGROUND); if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_LIGHT_SENSITIVE, SUBRACE_BASE_INFORMATION_FLAGS)) { SHA_SubraceReadSubrace(oDM, " *Light Sensitive"); } if(iDmgTakenInLight != 0) { if(iDmgTakenInLight > 0) { SHA_SubraceReadSubrace(oDM, " *Takes " + IntToString(iDmgTakenInLight) + " damage in sunlight."); } else { SHA_SubraceReadSubrace(oDM, " *Regenerates " + IntToString(abs(iDmgTakenInLight)) + " hitpoints in sunlight."); } } if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_UNDERGROUND_SENSITIVE, SUBRACE_BASE_INFORMATION_FLAGS)) { SHA_SubraceReadSubrace(oDM, " *Underground Sensitive"); } if(iDmgTakenInUnder != 0) { if(iDmgTakenInUnder > 0) { SHA_SubraceReadSubrace(oDM, " *Takes " + IntToString(iDmgTakenInUnder) + " damage in underground."); } else { SHA_SubraceReadSubrace(oDM, " *Regenerates " + IntToString(abs(iDmgTakenInUnder)) + " hitpoints in underground areas."); } } if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_UNDEAD, SUBRACE_BASE_INFORMATION_FLAGS)) { SHA_SubraceReadSubrace(oDM, " *Undead subrace"); } if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_PRESTIGIOUS_SUBRACE, SUBRACE_BASE_INFORMATION_FLAGS)) { SHA_SubraceReadSubrace(oDM, " *Prestigious subrace"); } int ECL = GetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_ECL); if(ECL != 0) { SHA_SubraceReadSubrace(oDM, " *ECL: " + IntToString(ECL)); } SHA_SubraceReadSubrace(oDM, " "); int HasFClass = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_FAVORED_CLASS); if(HasFClass != 0) { SHA_SubraceReadSubrace(oDM, " *Favored Classs:"); int MaleFavoredClass = GetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_FAVORED_CLASS, SUBRACE_FAVORED_CLASS_MALE_FLAG); int FemaleFavoredClass = GetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_FAVORED_CLASS, SUBRACE_FAVORED_CLASS_FEMALE_FLAG); SHA_SubraceReadSubrace(oDM, " Male: " + class(MaleFavoredClass - 1)); SHA_SubraceReadSubrace(oDM, " Female: " + class(FemaleFavoredClass - 1)); SHA_SubraceReadSubrace(oDM, " "); } int Level = 1; while(Level <=40) { string SubraceTag1 = SubraceTag + "_" + IntToString(Level); if(GetLocalInt(oStorer, SubraceTag1 + "_" + APPEARANCE_CHANGE) != 0) { SHA_SubraceReadSubrace(oDM, " Appearance is altered."); SHA_SubraceReadSubrace(oDM, " "); break; } Level++; } int HasDiffStats = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG1); if(HasDiffStats) { SHA_SubraceReadSubrace(oDM, " Ability scores change:"); //day int iTime = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG2); if(iTime) { SubraceTag = SubraceTag + IntToString(TIME_DAY); SHA_SubraceReadSubrace(oDM, " For day time:"); int ModType = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIER_TYPE); float multiplier = 1.0; string percent = ""; if(ModType == SUBRACE_STAT_MODIFIER_TYPE_PERCENTAGE) { multiplier = 100.0; percent = "%"; } float StrengthModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_STR_MODIFIER); float DexterityModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_DEX_MODIFIER); float ConstitutionModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_CON_MODIFIER); float WisdomModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_WIS_MODIFIER); float IntelligenceModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_INT_MODIFIER); float CharismaModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_CHA_MODIFIER); float ABModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_AB_MODIFIER); float ACModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_AC_MODIFIER); SHA_SubraceReadSubrace(oDM, " STR: " + FloatToString(multiplier*StrengthModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " DEX: " + FloatToString(multiplier*DexterityModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " CON: " + FloatToString(multiplier*ConstitutionModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " WIS: " + FloatToString(multiplier*WisdomModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " INT: " + FloatToString(multiplier*IntelligenceModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " CHA: " + FloatToString(multiplier*CharismaModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " AB : " + FloatToString(multiplier*ABModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " AC : " + FloatToString(multiplier*ACModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " Changes happen in:"); if(GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG4)) { SHA_SubraceReadSubrace(oDM, " Interior Areas"); } if(GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG5)) { SHA_SubraceReadSubrace(oDM, " Exterior Areas"); } if(GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG9)) { SHA_SubraceReadSubrace(oDM, " Underground Areas"); } if(GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG8)) { SHA_SubraceReadSubrace(oDM, " Above-ground Areas"); } if(GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG6)) { SHA_SubraceReadSubrace(oDM, " Artificial Areas"); } if(GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG7)) { SHA_SubraceReadSubrace(oDM, " Natural Areas"); } } SubraceTag = SUBRACE_TAG + "_" + subraceName; //night iTime = GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG3); if(iTime) { SubraceTag = SubraceTag + IntToString(TIME_NIGHT); SHA_SubraceReadSubrace(oDM, " For night time:"); int ModType = GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIER_TYPE); float multiplier = 1.0; string percent = ""; if(ModType == SUBRACE_STAT_MODIFIER_TYPE_PERCENTAGE) { multiplier = 100.0; percent = "%"; } float StrengthModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_STR_MODIFIER); float DexterityModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_DEX_MODIFIER); float ConstitutionModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_CON_MODIFIER); float WisdomModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_WIS_MODIFIER); float IntelligenceModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_INT_MODIFIER); float CharismaModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_CHA_MODIFIER); float ABModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_AB_MODIFIER); float ACModifier = GetLocalFloat(oStorer, SubraceTag + "_" + SUBRACE_STAT_AC_MODIFIER); SHA_SubraceReadSubrace(oDM, " STR: " + FloatToString(multiplier*StrengthModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " DEX: " + FloatToString(multiplier*DexterityModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " CON: " + FloatToString(multiplier*ConstitutionModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " WIS: " + FloatToString(multiplier*WisdomModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " INT: " + FloatToString(multiplier*IntelligenceModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " CHA: " + FloatToString(multiplier*CharismaModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " AB : " + FloatToString(multiplier*ABModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " AC : " + FloatToString(multiplier*ACModifier, 18, 2) + percent); SHA_SubraceReadSubrace(oDM, " Changes happen in:"); if(GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG4)) { SHA_SubraceReadSubrace(oDM, " Interior Areas"); } if(GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG5)) { SHA_SubraceReadSubrace(oDM, " Exterior Areas"); } if(GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG9)) { SHA_SubraceReadSubrace(oDM, " Underground Areas"); } if(GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG8)) { SHA_SubraceReadSubrace(oDM, " Above-ground Areas"); } if(GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG6)) { SHA_SubraceReadSubrace(oDM, " Artificial Areas"); } if(GetLocalFlag(oStorer, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG7)) { SHA_SubraceReadSubrace(oDM, " Natural Areas"); } } SHA_SubraceReadSubrace(oDM, " "); } SubraceTag = SUBRACE_TAG + "_" + subraceName; int HasRes = GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, SUBRACE_HAS_RESTRICTION, SUBRACE_RESTRICTION_FLAGS); if(HasRes) { SHA_SubraceReadSubrace(oDM, " Subrace has weapon restrictions: "); int ResType = GetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, SUBRACE_RESTRICTION_WEAPON); int ResTime = GetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, TIME_FLAGS); int Allow = GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, SUBRACE_ALLOW_ONLY_THIS_TYPE, SUBRACE_RESTRICTION_FLAGS); string isonly = "Not allowed to use "; if(Allow) { isonly = "Is only allowed to use "; } SHA_SubraceReadSubrace(oDM, " -" + isonly + " " + Subrace_WeaponRestrictionToString(ResType)); SHA_SubraceReadSubrace(oDM, " -Restriction applies during: " + Subrace_TimeToString(ResTime)); SHA_SubraceReadSubrace(oDM, " "); } HasRes = GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, SUBRACE_HAS_RESTRICTION, SUBRACE_RESTRICTION_FLAGS); if(HasRes) { SHA_SubraceReadSubrace(oDM, " Subrace has armor/shield restrictions:"); string isonly = ""; if(GetLocalGroupFlag(oStorer, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, SUBRACE_ALLOW_ONLY_THIS_TYPE, SUBRACE_RESTRICTION_FLAGS)) { isonly = "Is only allowed to use "; } int ResType = GetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, SUBRACE_RESTRICTION_DEFENSE); int ResTime = GetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, TIME_FLAGS); SHA_SubraceReadSubrace(oDM, " -" + isonly + Subrace_DefenseRestrictionToString(ResType)); SHA_SubraceReadSubrace(oDM, " -Restriction applies during: " + Subrace_TimeToString(ResTime)); SHA_SubraceReadSubrace(oDM, " "); } } string Subrace_TimeToString(int iTime) { string ret = "ERROR"; switch(iTime) { case TIME_DAY: ret = "Day time"; break; case TIME_NIGHT: ret = "Night time"; break; case TIME_BOTH: ret = "Day & Night time"; break; case TIME_NONE: ret = "None - Special"; break; default: break; } return ret; } void ChangePCAppearance(object oPC, string SubraceTag) { int App = GetLocalGroupFlagValue(oPC, SubraceTag + "_" + APPEARANCE_CHANGE, APPEARANCE_CHANGE_APPEARANCE_FLAG); if(App == GetAppearanceType(oPC)) { return; } int Alignment = GetAlignmentGoodEvil(oPC); int VFX_ID = VFX_IMP_UNSUMMON; if(Alignment == ALIGNMENT_GOOD) { VFX_ID = VFX_IMP_GOOD_HELP; } else if (Alignment == ALIGNMENT_NEUTRAL) { VFX_ID = VFX_FNF_SUMMON_MONSTER_3; } else if (Alignment == ALIGNMENT_EVIL) { VFX_ID = VFX_IMP_EVIL_HELP; } effect VisualBurst = EffectVisualEffect(VFX_ID); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, VisualBurst, oPC); if(PC_SCREAMS_WHEN_CHANGING_IN_APPEARANCE) { AssignCommand(oPC, SpeakString(SUBRACE_WORDS_SPOKEN_ON_APPEARANCE_CHANGE_TO_MONSTER)); } SetCreatureAppearanceType(oPC, App); if(GetAppearanceType(oPC) == App) { SHA_SendSubraceMessageToPC(oPC, "Your appearance has been changed to better suit your sub-racial features.", FALSE); } } void ChangeToPCDefaultAppearance(object oPC) { int App = SHA_GetDefaultAppearanceType(oPC); if(App == GetAppearanceType(oPC)) { return; } int Alignment = GetAlignmentGoodEvil(oPC); int VFX_ID = VFX_IMP_UNSUMMON; if(Alignment == ALIGNMENT_GOOD) { VFX_ID = VFX_IMP_GOOD_HELP; } else if (Alignment == ALIGNMENT_NEUTRAL) { VFX_ID = VFX_FNF_SUMMON_MONSTER_3; } else if (Alignment == ALIGNMENT_EVIL) { VFX_ID = VFX_IMP_EVIL_HELP; } effect VisualBurst = EffectVisualEffect(VFX_ID); if(PC_SCREAMS_WHEN_CHANGING_IN_APPEARANCE) { AssignCommand(oPC, SpeakString(SUBRACE_WORDS_SPOKEN_ON_APPEARANCE_CHANGE_TO_DEFAULT_RACIAL_TYPE)); } ApplyEffectToObject(DURATION_TYPE_TEMPORARY, VisualBurst, oPC); SetCreatureAppearanceType(oPC, App); SHA_SendSubraceMessageToPC(oPC, "Your appearance has been reverted back to your typical racial appearance.", FALSE); } void ApplyPermanentSubraceAppearance(string subrace, object oPC) { string SubraceTag = SUBRACE_TAG + "_" + subrace; int Level = GetPlayerLevel(oPC); while(Level != 0) { string SubraceTag1 = SubraceTag + "_" + IntToString(Level); int iTime = GetLocalGroupFlagValue(oStorer, SubraceTag1 + "_" + APPEARANCE_CHANGE, TIME_FLAGS); if(iTime == TIME_BOTH) { ChangePCAppearance(oPC, SubraceTag1); return; } Level--; } ChangeToPCDefaultAppearance(oPC); } void ApplyTemporarySubraceAppearance(string SubraceTag, object oPC, int iCurrentTime) { int Level = GetPlayerLevel(oPC); while(Level != 0) { string SubraceTag1 = SubraceTag + "_" + IntToString(Level); int iTime = GetLocalGroupFlagValue(oStorer, SubraceTag1 + "_" + APPEARANCE_CHANGE, TIME_FLAGS); if(iTime != 0 && iTime != TIME_NONE) { if(iTime == TIME_BOTH) { } else if(iTime == iCurrentTime) { ChangePCAppearance(oPC, SubraceTag1); } else if(iTime != iCurrentTime) { ChangeToPCDefaultAppearance(oPC); } return; } Level--; } } void ApplyPermanentSubraceSpellResistance(string subrace, object oPC) { string SubraceTag = SUBRACE_TAG + "_" + subrace; if(GetLocalInt(oStorer, SubraceTag + "_" + SUBRACE_SPELL_RESISTANCE) == 0) { return; } //Remove all spell resistances so we can get the correct base spell resistance //given by items if(SUBRACE_SPELL_RESISTANCE_STACKS && (GetHasSpellEffect(SPELL_SPELL_RESISTANCE, oPC) || GetHasSpellEffect(SPELL_GREATER_SPELL_BREACH, oPC))) { effect iEffect = GetFirstEffect(oPC); while(GetIsEffectValid(iEffect)) { int iEffectType = GetEffectType(iEffect); if(iEffectType == EFFECT_TYPE_SPELL_RESISTANCE_INCREASE || iEffectType == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE) { RemoveEffect(oPC, iEffect); } iEffect = GetNextEffect(oPC); } } int SpellResAtLevel1 = GetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_SPELL_RESISTANCE, SUBRACE_SPELL_RESISTANCE_BASE_FLAGS); int SpellResAtLevelMax = GetLocalGroupFlagValue(oStorer, SubraceTag + "_" + SUBRACE_SPELL_RESISTANCE, SUBRACE_SPELL_RESISTANCE_MAX_FLAGS); float AvgSR; effect SpellResistance; float baseSR = IntToFloat(SpellResAtLevel1); float maxSR = IntToFloat(SpellResAtLevelMax); AvgSR = maxSR - baseSR; float SRPerLevel = AvgSR/IntToFloat(MAXIMUM_PLAYER_LEVEL); float PCLevel = IntToFloat(GetPlayerLevel(oPC)); float SR = (PCLevel*SRPerLevel)+ baseSR; int SR_int = FloatToInt(SR); if(SUBRACE_SPELL_RESISTANCE_STACKS) { SR_int = SR_int + GetSpellResistance(oPC); } if(SR_int < 0) { int SR1 = abs(SR_int); SpellResistance = EffectSpellResistanceDecrease(SR1); } else { SpellResistance = EffectSpellResistanceIncrease(SR_int); } ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(SpellResistance), oPC); SHA_SendSubraceMessageToPC(oPC, "Your spell resistance has been modified to fit your sub-racial features.", FALSE); } void ApplyTemporarySubraceStats(object oPC, string SubraceTag, int iCurrentTime, int AreaUndAbove, int AreaIntExt, int AreaNatArt) { int iTimeDay = GetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG2); int iTimeNight = GetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG3); if(iTimeDay || iTimeNight) { SHA_ApplyTemporaryStats(oPC, SubraceTag, iCurrentTime, iTimeDay, iTimeNight, AreaUndAbove, AreaIntExt, AreaNatArt); } } void TemporaryStatsVisualFX(object oPC) { effect eVis = EffectVisualEffect(VFX_IMP_IMPROVE_ABILITY_SCORE); effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE); effect Vfx = EffectLinkEffects(eVis, eDur); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, Vfx, oPC); } void SHA_ApplyTemporaryStats(object oPC, string SubraceTag, int iCurrentTime, int iTimeDay, int iTimeNight,int AreaUndAbove, int AreaIntExt, int AreaNatArt) { if(AreaUndAbove == AREA_INVALID) { return; } string SubraceTag1 = SubraceTag + IntToString(iCurrentTime); int AreaInt = GetLocalFlag(oPC, SubraceTag1 + "_" + SUBRACE_STAT_MODIFIERS, FLAG4); int AreaExt = GetLocalFlag(oPC, SubraceTag1 + "_" + SUBRACE_STAT_MODIFIERS, FLAG5); int AreaUnd = GetLocalFlag(oPC, SubraceTag1 + "_" + SUBRACE_STAT_MODIFIERS, FLAG9); int AreaAbove = GetLocalFlag(oPC, SubraceTag1 + "_" + SUBRACE_STAT_MODIFIERS, FLAG8); int AreaArt = GetLocalFlag(oPC, SubraceTag1 + "_" + SUBRACE_STAT_MODIFIERS, FLAG6); int AreaNat = GetLocalFlag(oPC, SubraceTag1 + "_" + SUBRACE_STAT_MODIFIERS, FLAG7); int check1 = TRUE; int check2 = TRUE; int check3 = TRUE; //current area: Is above ground.... subrace infor says: apply the stats in Underground only or Don't apply it anywhere. if(AreaUndAbove == AREA_ABOVEGROUND && !AreaAbove) { check2 = FALSE; } if(AreaUndAbove == AREA_UNDERGROUND && !AreaUnd) { check2 = FALSE; } //interior if(AreaIntExt && !AreaInt) { check3 = FALSE; } //exterior if(!AreaIntExt && !AreaExt) { check3 = FALSE; } //natural if(AreaNatArt == AREA_NATURAL && !AreaNat) { check1 = FALSE; } if(AreaNatArt == AREA_ARTIFICIAL && !AreaArt) { check1 = FALSE; } if(iCurrentTime == TIME_DAY) { if(iTimeDay && check1 && check2 && check3) { if(GetLocalFlag(oPC, SUBRACE_STATS_STATUS, SUBRACE_DAY_STATS_APPLIED)) { return; } } if(GetLocalFlag(oPC, SUBRACE_STATS_STATUS, SUBRACE_DAY_STATS_APPLIED)) { ClearSubraceTemporaryStats(oPC); SHA_SendSubraceMessageToPC(oPC, "Your ability scores have been reverted.", FALSE); SetLocalFlag(oPC, SUBRACE_STATS_STATUS, SUBRACE_DAY_STATS_APPLIED, FALSE); } if(GetLocalFlag(oPC, SUBRACE_STATS_STATUS, SUBRACE_NIGHT_STATS_APPLIED)) { ClearSubraceTemporaryStats(oPC); SHA_SendSubraceMessageToPC(oPC, "Your ability scores have been reverted.", FALSE); SetLocalFlag(oPC, SUBRACE_STATS_STATUS, SUBRACE_NIGHT_STATS_APPLIED, FALSE); } } else if(iCurrentTime == TIME_NIGHT) { if(iTimeNight && check1 && check2 && check3) { if(GetLocalFlag(oPC, SUBRACE_STATS_STATUS, SUBRACE_NIGHT_STATS_APPLIED)) { return; } } if(GetLocalFlag(oPC, SUBRACE_STATS_STATUS, SUBRACE_NIGHT_STATS_APPLIED)) { ClearSubraceTemporaryStats(oPC); SHA_SendSubraceMessageToPC(oPC, "Your ability scores have been reverted.", FALSE); SetLocalFlag(oPC, SUBRACE_STATS_STATUS, SUBRACE_NIGHT_STATS_APPLIED, FALSE); } if(GetLocalFlag(oPC, SUBRACE_STATS_STATUS, SUBRACE_DAY_STATS_APPLIED)) { ClearSubraceTemporaryStats(oPC); SHA_SendSubraceMessageToPC(oPC, "Your ability scores have been reverted.", FALSE); SetLocalFlag(oPC, SUBRACE_STATS_STATUS, SUBRACE_DAY_STATS_APPLIED, FALSE); } } if((!iTimeNight && iCurrentTime == TIME_NIGHT) && (!iTimeDay && iCurrentTime == TIME_DAY)) { return; } if(!check1 || !check2 || !check3) { return; } int iType = GetLocalInt(oPC, SubraceTag + IntToString(iCurrentTime) + "_" + SUBRACE_STAT_MODIFIER_TYPE); SubraceTag = SubraceTag + IntToString(iCurrentTime); if(GetIsResting(oPC)) { AssignCommand(oPC, ClearAllActions(TRUE)); } if(iType == SUBRACE_STAT_MODIFIER_TYPE_PERCENTAGE) { ApplySubraceBonusStatsByPercentage(oPC, SubraceTag); } else if(iType == SUBRACE_STAT_MODIFIER_TYPE_POINTS) { ApplySubraceBonusStatsByPoints(oPC, SubraceTag); } else { return; } //STAT MODIFIER TYPE Unrecognised TemporaryStatsVisualFX(oPC); SHA_SendSubraceMessageToPC(oPC, "Your ability scores have changed...", FALSE); if(iCurrentTime == TIME_DAY) { SetLocalFlag(oPC, SUBRACE_STATS_STATUS, SUBRACE_DAY_STATS_APPLIED, TRUE); } else if(iCurrentTime == TIME_NIGHT) { SetLocalFlag(oPC, SUBRACE_STATS_STATUS, SUBRACE_NIGHT_STATS_APPLIED, TRUE); } } void ClearSubraceEffects(object oPC) { effect eBad = GetFirstEffect(oPC); while(GetIsEffectValid(eBad)) { int iType = GetEffectType(eBad); if (iType == EFFECT_TYPE_ARCANE_SPELL_FAILURE || iType == EFFECT_TYPE_BLINDNESS || iType == EFFECT_TYPE_CHARMED || iType == EFFECT_TYPE_CONCEALMENT || iType == EFFECT_TYPE_CONFUSED || iType == EFFECT_TYPE_CUTSCENEGHOST || iType == EFFECT_TYPE_HASTE || iType == EFFECT_TYPE_IMMUNITY || iType == EFFECT_TYPE_IMPROVEDINVISIBILITY || iType == EFFECT_TYPE_INVISIBILITY || iType == EFFECT_TYPE_MISS_CHANCE || iType == EFFECT_TYPE_MOVEMENT_SPEED_DECREASE || iType == EFFECT_TYPE_MOVEMENT_SPEED_INCREASE || iType == EFFECT_TYPE_POLYMORPH || iType == EFFECT_TYPE_REGENERATE || iType == EFFECT_TYPE_SANCTUARY || iType == EFFECT_TYPE_SLOW || iType == EFFECT_TYPE_TEMPORARY_HITPOINTS || iType == EFFECT_TYPE_TRUESEEING || iType == EFFECT_TYPE_ULTRAVISION || iType == EFFECT_TYPE_VISUALEFFECT) { if(GetEffectSubType(eBad) == SUBTYPE_SUPERNATURAL) { RemoveEffect(oPC, eBad); } } eBad = GetNextEffect(oPC); } } void ClearSubraceTemporaryStats(object oPC) { effect eBad = GetFirstEffect(oPC); while(GetIsEffectValid(eBad)) { int iType = GetEffectType(eBad); if (iType == EFFECT_TYPE_ABILITY_DECREASE || iType == EFFECT_TYPE_ABILITY_INCREASE || iType == EFFECT_TYPE_AC_DECREASE || iType == EFFECT_TYPE_AC_INCREASE || iType == EFFECT_TYPE_ATTACK_INCREASE || iType == EFFECT_TYPE_ATTACK_DECREASE || iType == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE || iType == EFFECT_TYPE_SPELL_RESISTANCE_INCREASE || iType == EFFECT_TYPE_SAVING_THROW_DECREASE) { if(GetEffectSubType(eBad) == SUBTYPE_SUPERNATURAL) { RemoveEffect(oPC, eBad); } } eBad = GetNextEffect(oPC); } } void ApplySubraceBonusStatsByPoints(object oPC, string SubraceTag) { float strMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_STR_MODIFIER); float dexMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_DEX_MODIFIER); float conMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_CON_MODIFIER); float wisMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_WIS_MODIFIER); float intMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_INT_MODIFIER); float chaMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_CHA_MODIFIER); float ABMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_AB_MODIFIER); float ACMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_AC_MODIFIER); if(strMod != 0.0) { ApplyStat_AbilityByPoints(ABILITY_STRENGTH, strMod, oPC); } if(dexMod !=0.0) { ApplyStat_AbilityByPoints(ABILITY_DEXTERITY, dexMod, oPC); } if(conMod != 0.0) { ApplyStat_AbilityByPoints(ABILITY_CONSTITUTION, conMod, oPC); } if(wisMod != 0.0) { ApplyStat_AbilityByPoints(ABILITY_WISDOM, wisMod, oPC); } if(intMod != 0.0) { ApplyStat_AbilityByPoints(ABILITY_INTELLIGENCE, intMod, oPC); } if(chaMod != 0.0) { ApplyStat_AbilityByPoints(ABILITY_CHARISMA, chaMod, oPC); } if(ABMod != 0.0) { ApplyAttackBonusByPoints(ABMod, oPC); } if(ACMod != 0.0) { ApplyArmourClassBonusByPoints(ACMod, oPC); } } void ApplyStat_AbilityByPoints(int AbilityToMod, float points, object oPC) { int StatIncrease = FloatToInt(points); effect StatEffect; if(StatIncrease > 0) { StatEffect = EffectAbilityIncrease(AbilityToMod, StatIncrease); } else if(StatIncrease < 0) { int StatIncrease1 = abs(StatIncrease); StatEffect = EffectAbilityDecrease(AbilityToMod, StatIncrease1); } ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(StatEffect), oPC); } void ApplyAttackBonusByPoints(float points, object oPC) { int ABChange = FloatToInt(points); effect StatEffect; effect StatEffect1; if(ABChange > 0) { StatEffect = EffectAttackIncrease(ABChange, ATTACK_BONUS_ONHAND); StatEffect1 = EffectAttackIncrease(ABChange, ATTACK_BONUS_OFFHAND); } else if(ABChange < 0) { int ABChange1 = abs(ABChange); StatEffect = EffectAttackDecrease(ABChange1, ATTACK_BONUS_ONHAND); StatEffect1 = EffectAttackDecrease(ABChange1, ATTACK_BONUS_OFFHAND); } ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(StatEffect), oPC); ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(StatEffect1), oPC); } void ApplyArmourClassBonusByPoints(float points, object oPC) { int ACChange = FloatToInt(points); effect StatEffect; if(ACChange > 0) { StatEffect = EffectACIncrease(ACChange, AC_NATURAL_BONUS); } else if(ACChange < 0) { int ACChange1 = abs(ACChange); StatEffect = EffectACDecrease(ACChange1, AC_NATURAL_BONUS); } ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(StatEffect), oPC); } void ApplySubraceBonusStatsByPercentage(object oPC, string SubraceTag) { float strMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_STR_MODIFIER); float dexMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_DEX_MODIFIER); float conMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_CON_MODIFIER); float wisMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_WIS_MODIFIER); float intMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_INT_MODIFIER); float chaMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_CHA_MODIFIER); float ABMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_AB_MODIFIER); float ACMod = GetLocalFloat(oPC, SubraceTag + "_" + SUBRACE_STAT_AC_MODIFIER); if(strMod != 0.0) { ApplyStat_AbilityByPercentage(ABILITY_STRENGTH, strMod, oPC); } if(dexMod !=0.0) { ApplyStat_AbilityByPercentage(ABILITY_DEXTERITY, dexMod, oPC); } if(conMod != 0.0) { ApplyStat_AbilityByPercentage(ABILITY_CONSTITUTION, conMod, oPC); } if(wisMod != 0.0) { ApplyStat_AbilityByPercentage(ABILITY_WISDOM, wisMod, oPC); } if(intMod != 0.0) { ApplyStat_AbilityByPercentage(ABILITY_INTELLIGENCE, intMod, oPC); } if(chaMod != 0.0) { ApplyStat_AbilityByPercentage(ABILITY_CHARISMA, chaMod, oPC); } if(ABMod != 0.0) { ApplyAttackBonusByPercentage(ABMod, oPC); } if(ACMod != 0.0) { ApplyArmourClassBonusByPercentage(ACMod, oPC); } } void ApplyStat_AbilityByPercentage(int AbilityToMod, float percentage, object oPC) { int currentStat = GetAbilityScore(oPC, AbilityToMod); float cStat = IntToFloat(currentStat); float Stat = cStat*percentage; int newStat = FloatToInt(Stat); effect StatEffect; if(newStat > 0) { StatEffect = EffectAbilityIncrease(AbilityToMod, newStat); } else if(newStat < 0) { int newStat1 = abs(newStat); StatEffect = EffectAbilityDecrease(AbilityToMod, newStat1); } ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(StatEffect), oPC); } void ApplyAttackBonusByPercentage(float percentage, object oPC) { float currentAB = IntToFloat(GetBaseAttackBonus(oPC)); int Neg = FALSE; int Neg2 = FALSE; if(currentAB < 0.0 ) { Neg = TRUE; } if(percentage < 0.0 ) { Neg2 = TRUE; } int newAB = FloatToInt(currentAB*percentage); if(Neg && Neg2 ) { newAB = -newAB; } effect StatEffect; effect StatEffect1; if(newAB > 0) { StatEffect = EffectAttackIncrease(newAB, ATTACK_BONUS_ONHAND); StatEffect1 = EffectAttackIncrease(newAB, ATTACK_BONUS_OFFHAND); } else if(newAB < 0) { int newAB1 = abs(newAB); StatEffect = EffectAttackDecrease(newAB1, ATTACK_BONUS_ONHAND); StatEffect1 = EffectAttackDecrease(newAB1, ATTACK_BONUS_OFFHAND); } ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(StatEffect), oPC); ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(StatEffect1), oPC); } void ApplyArmourClassBonusByPercentage(float percentage, object oPC) { float currentAC = IntToFloat(GetAC(oPC)); int newAC = FloatToInt(currentAC*percentage); effect StatEffect; if(newAC > 0) { StatEffect = EffectACIncrease(newAC, AC_NATURAL_BONUS, AC_VS_DAMAGE_TYPE_ALL); } else if(newAC < 0) { int newAC1 = abs(newAC); StatEffect = EffectACDecrease(newAC1, AC_NATURAL_BONUS, AC_VS_DAMAGE_TYPE_ALL); } ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(StatEffect), oPC); } void SHA_SubraceForceUnequipItem(object oItem) { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectCutsceneImmobilize(), OBJECT_SELF, 0.1); ClearAllActions(TRUE); ActionUnequipItem(oItem); ActionDoCommand(SetCommandable(TRUE)); SetCommandable(FALSE); } void SHA_SubraceForceEquipItem(object oItem, int InvoSlot) { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectCutsceneImmobilize(), OBJECT_SELF, 0.1); ClearAllActions(TRUE); ActionEquipItem(oItem, InvoSlot); ActionDoCommand(SetCommandable(TRUE)); SetCommandable(FALSE); } string Subrace_WeaponRestrictionToString(int ResType) { string ret = ""; switch(ResType) { case SUBRACE_RESTRICTION_WEAPON_MELEE: ret = "Melee Weapons"; break; case SUBRACE_RESTRICTION_WEAPON_RANGED: ret = "Ranged Weapons"; break; case SUBRACE_RESTRICTION_WEAPON_TINY: ret = "Tiny Weapons"; break; case SUBRACE_RESTRICTION_WEAPON_LARGE: ret = "Large Weapons"; break; case SUBRACE_RESTRICTION_WEAPON_SIMPLE: ret = "Simple Weapons"; break; case SUBRACE_RESTRICTION_WEAPON_MARTIAL: ret = "Martial Weapons"; break; case SUBRACE_RESTRICTION_WEAPON_EXOTIC: ret = "Exotic Weapons"; break; case SUBRACE_RESTRICTION_WEAPON_ALL: ret = "All types of Weapons"; break; default: ret = "ERROR"; break; } return ret; } string Subrace_DefenseRestrictionToString(int ResType) { string ret = ""; switch(ResType) { case SUBRACE_RESTRICTION_DEFENSE_CLOTHING: ret = "Clothing"; break; case SUBRACE_RESTRICTION_DEFENSE_HEAVY: ret = "Heavy Defense"; break; case SUBRACE_RESTRICTION_DEFENSE_LIGHT: ret = "Light Defense"; break; case SUBRACE_RESTRICTION_DEFENSE_MEDIUM: ret = "Medium Weapons"; break; case SUBRACE_RESTRICTION_DEFENSE_ALL: ret = "All Defenses"; break; default: ret = "ERROR"; break; } return ret; } void CheckCanUseWeapon(object oItem, object oPC, string SubraceTag) { int HasRes = GetLocalGroupFlag(oPC, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, SUBRACE_HAS_RESTRICTION, SUBRACE_RESTRICTION_FLAGS); if(HasRes) { int ResType = GetLocalGroupFlagValue(oPC, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, SUBRACE_RESTRICTION_WEAPON); int ResTime = GetLocalGroupFlagValue(oPC, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, TIME_FLAGS); int Allow = GetLocalGroupFlag(oPC, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, SUBRACE_ALLOW_ONLY_THIS_TYPE, SUBRACE_RESTRICTION_FLAGS); //First make sure it is a weapon... if(!SHA_GetIsRangedWeapon(oItem) && !SHA_GetIsMeleeWeapon(oItem)) { return; } int iResult = 100; if(ResTime == TIME_NIGHT) { if(!GetIsNight() && !GetIsDusk()) { return; } } else if(ResTime == TIME_DAY) { if(!GetIsDay() && !GetIsDawn()) { return; } } switch(ResType) { case SUBRACE_RESTRICTION_WEAPON_MELEE: iResult = SHA_GetIsMeleeWeapon(oItem); break; case SUBRACE_RESTRICTION_WEAPON_RANGED: iResult = SHA_GetIsRangedWeapon(oItem); break; case SUBRACE_RESTRICTION_WEAPON_TINY: iResult = SHA_GetIsWeaponTiny(oItem); break; case SUBRACE_RESTRICTION_WEAPON_LARGE: iResult = SHA_GetIsWeaponLarge(oItem); break; case SUBRACE_RESTRICTION_WEAPON_SIMPLE: iResult = SHA_GetIsSimpleWeapon(oItem); break; case SUBRACE_RESTRICTION_WEAPON_MARTIAL: iResult = SHA_GetIsMartialWeapon(oItem); break; case SUBRACE_RESTRICTION_WEAPON_EXOTIC: iResult = SHA_GetIsExoticWeapon(oItem); break; case SUBRACE_RESTRICTION_WEAPON_ALL: iResult = TRUE; default: iResult = FALSE; } //It is the type of weapon the sub-race is restricted against. if(iResult && !Allow) { iResult = FALSE; } if(!iResult) { SHA_SendSubraceMessageToPC(oPC, "You cannot equip this weapon because of your sub-race's limitations.", TRUE); DelayCommand(0.3, AssignCommand(oPC, SHA_SubraceForceUnequipItem(oItem))); } } } void CheckCanUseArmor(object oItem, object oPC, string SubraceTag) { int HasRes = GetLocalGroupFlag(oPC, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, SUBRACE_HAS_RESTRICTION, SUBRACE_RESTRICTION_FLAGS); if(HasRes) { int ResType = GetLocalGroupFlagValue(oPC, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, SUBRACE_RESTRICTION_DEFENSE); int ResTime = GetLocalGroupFlagValue(oPC, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, TIME_FLAGS); int Allow = GetLocalGroupFlag(oPC, SubraceTag + "_" + SUBRACE_ARMOUR_RESTRICTION, SUBRACE_ALLOW_ONLY_THIS_TYPE, SUBRACE_RESTRICTION_FLAGS); int iCheck = FALSE; int iType = GetBaseItemType(oItem); if(iType == BASE_ITEM_ARMOR || iType == BASE_ITEM_LARGESHIELD || iType == BASE_ITEM_TOWERSHIELD || iType == BASE_ITEM_SMALLSHIELD || iType == BASE_ITEM_HELMET) { iCheck = TRUE; } if(iCheck) { int iResult = 100; if(ResTime == TIME_NIGHT) { if(!GetIsNight() && !GetIsDusk()) { return; } } else if(ResTime == TIME_DAY) { if(!GetIsDay() && !GetIsDawn()) { return; } } int BaseAC = GetArmorType(oItem); if(ResType == SUBRACE_RESTRICTION_DEFENSE_HEAVY) { if(BaseAC >= 7 || iType == BASE_ITEM_TOWERSHIELD || iType == BASE_ITEM_HELMET) { iResult = TRUE; } else { iResult = FALSE; } } else if(ResType == SUBRACE_RESTRICTION_DEFENSE_MEDIUM) { if((BaseAC >= 4 && BaseAC < 7) || iType == BASE_ITEM_LARGESHIELD || iType == BASE_ITEM_HELMET) { iResult = TRUE; } else { iResult = FALSE; } } else if(ResType == SUBRACE_RESTRICTION_DEFENSE_LIGHT) { if((BaseAC >= 1 && BaseAC < 4) || iType == BASE_ITEM_SMALLSHIELD) { iResult = TRUE; } else { iResult = FALSE; } } else if(ResType == SUBRACE_RESTRICTION_DEFENSE_CLOTHING) { if(BaseAC == 0 && iType != BASE_ITEM_LARGESHIELD && iType != BASE_ITEM_TOWERSHIELD && iType != BASE_ITEM_SMALLSHIELD && iType != BASE_ITEM_HELMET) { iResult = TRUE; } else { iResult = FALSE; } } else if(ResType == SUBRACE_RESTRICTION_DEFENSE_ALL) { iResult = TRUE; } if(iResult && !Allow) { iResult = FALSE; } if(!iResult) { SHA_SendSubraceMessageToPC(oPC, "You cannot equip this armor because of your sub-race's limitations.", TRUE); DelayCommand(0.3, AssignCommand(oPC, SHA_SubraceForceUnequipItem(oItem))); } } } } void CheckCanUseItem(object oItem, object oPC) { string subrace = GetStringLowerCase(GetSubRace(oPC)); if(subrace == "") { return; } string SubraceTag = SUBRACE_TAG + "_" + subrace; CheckCanUseArmor(oItem, oPC, SubraceTag); CheckCanUseWeapon(oItem, oPC, SubraceTag); } void SubraceOnPlayerEquipItem() { object oItem = GetPCItemLastEquipped(); object oPC = GetPCItemLastEquippedBy(); CheckCanUseItem(oItem, oPC); } void CheckIfCanUseEquipedWeapon(object oPC) { string subrace = GetStringLowerCase(GetSubRace(oPC)); if(subrace == "") { return; } string SubraceTag = SUBRACE_TAG + "_" + subrace; int HasRes = GetLocalGroupFlag(oPC, SubraceTag + "_" + SUBRACE_WEAPON_RESTRICTION, SUBRACE_HAS_RESTRICTION, SUBRACE_RESTRICTION_FLAGS); if(!HasRes) { return; } object Wep1 = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC); object Wep2 = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC); CheckCanUseItem(Wep1, oPC); CheckCanUseItem(Wep2, oPC); } void InitiateSubraceChecking(object oPC) { string subrace = GetStringLowerCase(GetSubRace(oPC)); if(subrace != "") { int check1 = GetCampaignInt(SUBRACE_DATABASE, SUBRACE_TAG + "_" + subrace, oPC); //NWNX Equivalent of the above. If using NWNX, then comment the above line, and uncomment the line below. //int check1 = GetPersistentInt(oPC, SUBRACE_TAG + "_" + subrace, SUBRACE_DATABASE); if(check1 == SUBRACE_UNINITIALIZED) { int check2 = CheckIfPCMeetsAnySubraceCriteria(oPC); if(check2 == SUBRACE_UNRECOGNISED) { return; } else if(!check2) { SetCampaignInt(SUBRACE_DATABASE, SUBRACE_TAG + "_" + subrace, SUBRACE_REJECTED, oPC); //NWNX Equivalent of the above. If using NWNX, then comment the above line, and uncomment the line below. //SetPersistentInt(oPC, SUBRACE_TAG + "_" + subrace , SUBRACE_REJECTED, 0, SUBRACE_DATABASE); return; } else if(check2) { SetCampaignInt(SUBRACE_DATABASE, SUBRACE_TAG + "_" + subrace, SUBRACE_ACCEPTED, oPC); //NWNX Equivalent of the above. If using NWNX, then comment the above line, and uncomment the line below. //SetPersistentInt(oPC, SUBRACE_TAG + "_" + subrace, SUBRACE_ACCEPTED, 0, SUBRACE_DATABASE); } } else if(check1 == SUBRACE_ACCEPTED) { } else if(check1 == SUBRACE_REJECTED) { //SUBRACE was rejected previously. return; } if(SEARCH_AND_DESTROY_SKINS_IN_INVENTORY) { SearchAndDestroySkinsAndClaws(oPC); } DelayCommand(1.0, LoadSubraceInfoOnPC(oPC, subrace)); DelayCommand(2.0, ApplyPermanentSubraceSpellResistance(subrace, oPC)); DelayCommand(4.0, ApplyPermanentSubraceAppearance(subrace, oPC)); } } void CheckAndSwitchSubrace(object oPC) { string subrace = GetStringLowerCase(GetSubRace(oPC)); if(subrace == "") { return; } string SubraceTag = SUBRACE_TAG + "_" + subrace; int Level = GetPlayerLevel(oPC); int End = FALSE; string switchSubraceNames = GetLocalString(oPC, SubraceTag + "_" + SUBRACE_SWITCH_NAME + IntToString(Level)); if(switchSubraceNames != "") { while(switchSubraceNames != "") { int iPos = FindSubString(switchSubraceNames, "_"); string sSubrace; if(iPos != -1) { sSubrace = GetStringLeft(switchSubraceNames, iPos); } else { sSubrace = switchSubraceNames; End = TRUE; } switchSubraceNames = GetStringRight(switchSubraceNames, GetStringLength(switchSubraceNames) - iPos - 1); string CurrentSubrace = GetSubRace(oPC); string NewSubrace = CapitalizeString(sSubrace); SetSubRace(oPC, NewSubrace); subrace = GetStringLowerCase(GetSubRace(oPC)); SHA_SendSubraceMessageToPC(oPC, "Checking whether your character meets the requirements for the '" + NewSubrace +"' sub-race...", TRUE); int check = TRUE; int NeedToMeetRequirements = GetLocalInt(oPC, SubraceTag + "_" + SUBRACE_SWITCH_MUST_MEET_REQUIREMENTS + IntToString(Level)); //only check restrictions if need be. if(NeedToMeetRequirements) { check = CheckIfPCMeetsAnySubraceCriteria(oPC); } if(check == SUBRACE_UNRECOGNISED) { return; } else if(!check) { SHA_SendSubraceMessageToPC(oPC, "Your character has failed to meet criteria for the '" + NewSubrace + "' sub-race!", TRUE); SetSubRace(oPC, CurrentSubrace); if(End == TRUE) { return; } } else if(check) { SetCampaignInt(SUBRACE_DATABASE, SUBRACE_TAG + "_" + subrace, SUBRACE_ACCEPTED, oPC); //NWNX Equivalent of the above. If using NWNX, then comment the above line, and uncomment the line below. //SetPersistentInt(oPC, SUBRACE_TAG + "_" + subrace, SUBRACE_ACCEPTED, 0, SUBRACE_DATABASE); //revert it back to delete the stored info. SetSubRace(oPC, CurrentSubrace); DeleteSubraceInfoOnPC(oPC); subrace = GetStringLowerCase(NewSubrace); DelayCommand(4.2, SHA_SendSubraceMessageToPC(oPC, "Switching sub-races to: " + NewSubrace + "...", TRUE)); DelayCommand(4.2, SetSubRace(oPC, NewSubrace)); DelayCommand(5.1, LoadSubraceInfoOnPC(oPC, subrace)); DelayCommand(7.0, ApplyPermanentSubraceSpellResistance(subrace, oPC)); DelayCommand(8.5, ApplyPermanentSubraceAppearance(subrace, oPC)); DelayCommand(9.0, SHA_SendSubraceMessageToPC(oPC, "Sub-race was switched!", TRUE)); return; } } } } void SubraceOnPlayerLevelUp() { object oPC = GetPCLevellingUp(); ReapplySubraceAbilities(oPC); DelayCommand(2.0, CheckAndGiveSubraceItems(oPC)); DelayCommand(6.0, CheckAndSwitchSubrace(oPC)); } void SubraceOnPlayerRespawn() { object oPC = GetLastRespawnButtonPresser(); ReapplySubraceAbilities(oPC); } void ReapplySubraceAbilities(object oPC) { string subrace = GetStringLowerCase(GetSubRace(oPC)); if(subrace == "") { return; } SetLocalInt(oPC, SUBRACE_INFO_LOADED_ON_PC, FALSE); DeleteLocalInt(oPC, SUBRACE_TAG + "SB_NITE_OCE"); DeleteLocalInt(oPC, SUBRACE_TAG + "SB_DAY_OCE"); DeleteLocalInt(oPC, APPEARANCE_TEMP_CHANGED); DeleteLocalInt(oPC, SUBRACE_IN_SPELL_DARKNESS); DeleteLocalInt(oPC, "SUB_EFCT_D_APD"); DeleteLocalInt(oPC, "SUB_EFCT_N_APD"); string SubraceTag = SUBRACE_TAG + "_" + subrace; int IsLightSens = GetLocalGroupFlag(oPC, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_LIGHT_SENSITIVE, SUBRACE_BASE_INFORMATION_FLAGS); int IsUndergSens = GetLocalGroupFlag(oPC, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_UNDERGROUND_SENSITIVE, SUBRACE_BASE_INFORMATION_FLAGS); if(IsLightSens) { DeleteLocalInt(oPC,"SB_LGHT_DMGED"); } if(IsUndergSens) { DeleteLocalInt(oPC,"SB_DARK_DMGED"); } ApplyPermanentSubraceSpellResistance(subrace, oPC); int HasDiffStats = GetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG1); if(HasDiffStats) { DeleteLocalInt(oPC, SUBRACE_STATS_STATUS); ClearSubraceTemporaryStats(oPC); } DelayCommand(2.0, ApplyPermanentSubraceAppearance(subrace, oPC)); DelayCommand(3.0, SearchAndDestroySkinsAndClaws(oPC)); DelayCommand(4.0, SetLocalInt(oPC, SUBRACE_INFO_LOADED_ON_PC, TRUE)); } int SHA_GetCurrentTime() { if(GetIsNight() || GetIsDusk()) { return TIME_NIGHT; } return TIME_DAY; } void SwapAppearance(object oPC, string subrace) { string SubraceTag = SUBRACE_TAG + "_" + subrace; int Level = GetPlayerLevel(oPC); while(Level != 0) { string SubraceTag1 = SubraceTag + "_" + IntToString(Level); int iTime = GetLocalGroupFlagValue(oStorer, SubraceTag1 + "_" + APPEARANCE_CHANGE, TIME_FLAGS); if(iTime != 0) { if(SHA_GetDefaultAppearanceType(oPC) == GetAppearanceType(oPC)) { ChangePCAppearance(oPC, SubraceTag1); } else { ChangeToPCDefaultAppearance(oPC); } return; } Level--; } } void SubraceCheckItemActivated(object oPC, object oItem) { string subrace = GetStringLowerCase(GetSubRace(oPC)); if(subrace == "") { return; } string sTag = GetStringLowerCase(GetTag(oItem)); if(subrace == sTag) { SwapAppearance(oPC, subrace); } } void SubraceOnItemActivated() { object oPC = GetItemActivator(); object oItem = GetItemActivated(); SubraceCheckItemActivated(oPC, oItem); } void SubraceOnClientEnter() { object oPC = GetEnteringObject(); int infoLoaded = GetLocalInt(oPC, SUBRACE_INFO_LOADED_ON_PC); if(!infoLoaded) { string subrace = GetStringLowerCase(GetSubRace(oPC)); if(subrace == "") { return; } DelayCommand(1.0, InitiateSubraceChecking(oPC)); } else { ReapplySubraceAbilities(oPC); } } //Subrace Default Heartbeat. (For use in default.nss) void SubraceHeartbeat(object oPC = OBJECT_SELF) { if(!GetLocalInt(oPC, SUBRACE_INFO_LOADED_ON_PC)) { return; } string subrace = GetLocalString(oPC, SUBRACE_TAG); if(subrace == "") { return; } string SubraceTag = SUBRACE_TAG + "_" + subrace; int IsDay = GetIsDay(); int IsDawn = GetIsDawn(); int IsNight = GetIsNight(); int IsDusk = GetIsDusk(); object oArea = GetArea(oPC); int AreaLocation = GetIsAreaAboveGround(oArea); int Interior = GetIsAreaInterior(oArea); int Natural = GetIsAreaNatural(oArea); string oAreaTag = GetTag(oArea); int HasDiffStats = GetLocalFlag(oPC, SubraceTag + "_" + SUBRACE_STAT_MODIFIERS, FLAG1); if(IsDay || IsDawn) { if(AreaLocation == AREA_ABOVEGROUND && !Interior) { int IsLightSens = GetLocalGroupFlag(oPC, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_LIGHT_SENSITIVE, SUBRACE_BASE_INFORMATION_FLAGS); int DmgTakenL = GetLocalInt(oPC, SubraceTag + "_" + DAMAGE_AMOUNT_IN_LIGHT); if(IsLightSens) { ApplyLightSensitivity(oPC); } if(DmgTakenL != 0) { ApplyDamageWhileInLight(oPC, DmgTakenL); } } if(AreaLocation == AREA_UNDERGROUND) { int IsUndergSens = GetLocalGroupFlag(oPC, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_UNDERGROUND_SENSITIVE, SUBRACE_BASE_INFORMATION_FLAGS); int DmgTakenU = GetLocalInt(oPC, SubraceTag + "_" + DAMAGE_AMOUNT_IN_UNDERGROUND); if(IsUndergSens) { ApplyUndergroundSensitivity(oPC); } if(DmgTakenU != 0) { ApplyDamageWhileInDark(oPC, DmgTakenU); } } if(HasDiffStats) { ApplyTemporarySubraceStats(oPC, SubraceTag, TIME_DAY, AreaLocation, Interior, Natural); } if(!GetLocalInt(oPC, SUBRACE_TAG + "SB_DAY_OCE")) { ApplyTemporarySubraceAppearance(SubraceTag, oPC, TIME_DAY); ApplySubraceEffect(oPC, SubraceTag, TIME_DAY); CheckIfCanUseEquipedWeapon(oPC); DelayCommand(2.0, EquipTemporarySubraceSkin(SubraceTag, oPC, TIME_DAY)); DelayCommand(6.0, EquipTemporarySubraceClaw(SubraceTag, oPC, TIME_DAY)); SetLocalInt(oPC, SUBRACE_TAG + "SB_DAY_OCE", TRUE); DeleteLocalInt(oPC, SUBRACE_TAG + "SB_NITE_OCE"); } } else if(IsNight || IsDusk) { if(AreaLocation == AREA_UNDERGROUND) { int IsUndergSens = GetLocalGroupFlag(oPC, SubraceTag + "_" + SUBRACE_BASE_INFORMATION, SUBRACE_BASE_INFORMATION_UNDERGROUND_SENSITIVE, SUBRACE_BASE_INFORMATION_FLAGS); int DmgTakenU = GetLocalInt(oPC, SubraceTag + "_" + DAMAGE_AMOUNT_IN_UNDERGROUND); if(IsUndergSens) { ApplyUndergroundSensitivity(oPC); } if(DmgTakenU > 0) { ApplyDamageWhileInDark(oPC, DmgTakenU); } } if(HasDiffStats) { ApplyTemporarySubraceStats(oPC, SubraceTag, TIME_NIGHT, AreaLocation, Interior, Natural); } if(!GetLocalInt(oPC, SUBRACE_TAG + "SB_NITE_OCE")) { ApplyTemporarySubraceAppearance(SubraceTag, oPC, TIME_NIGHT); ApplySubraceEffect(oPC, SubraceTag, TIME_NIGHT); CheckIfCanUseEquipedWeapon(oPC); DelayCommand(2.0, EquipTemporarySubraceSkin(SubraceTag, oPC, TIME_NIGHT)); DelayCommand(6.0, EquipTemporarySubraceClaw(SubraceTag, oPC, TIME_NIGHT)); SetLocalInt(oPC, SUBRACE_TAG + "SB_NITE_OCE", TRUE); DeleteLocalInt(oPC, SUBRACE_TAG + "SB_DAY_OCE"); } } } //void main() { }