//:://////////////////////////////////////////////////////////////////////////// //:: // underwater_hb.nss /* Handles being underwater. */ // //:: //:://////////////////////////////////////////////////////////////////////////// #include "prc_inc_spells" #include "x0_i0_match" //:: Checks if a creature is Aquatic for underwater related scripting int GetIsAquatic(object oCreature) { //:: Check if the provided object is valid if (!GetIsObjectValid(oCreature)) { return FALSE; } //:: Get the subrace field of the creature or player, set to lowercase string sSubrace = GetStringLowerCase(GetSubRace(oCreature)); if (FindSubString(sSubrace, "aquatic") != -1) { return TRUE; } //:: Check for aquatic or amphibious appearance int nAppearance = GetAppearanceType(oCreature); switch(nAppearance) { case APPEARANCE_TYPE_SHARK_GOBLIN: case APPEARANCE_TYPE_SHARK_HAMMERHEAD: case APPEARANCE_TYPE_SHARK_MAKO: case APPEARANCE_TYPE_MEPHIT_OOZE: case APPEARANCE_TYPE_MEPHIT_WATER: case APPEARANCE_TYPE_SEA_HAG: //:: CEP appearances follow case 872: //:: Leviathan case 990: //:: Troll, Scrag case 1427: //:: Crab: Blue: Giant* (Eligio Sacateca) case 1428: //:: Crab: Blue: Small* (Eligio Sacateca) case 1429: //:: Crab: Red: Giant 1* (Eligio Sacateca) case 1430: //:: Crab: Red: Small 1* (Eligio Sacateca) case 3053: //:: Bullywug: Brown-Green* (baba yaga) case 3054: //:: Bullywug: Green* (baba yaga) case 3055: //:: Bullywug: Brown* (baba yaga) case 3538: //:: Fish: Pike* (JFK) case 3539: //:: Fish: Pike, Giant* (JFK) case 3889: //:: Hag: Sea 2* (Hardpoints) return TRUE; } //:: If you made it this far, return false. return FALSE; } //:: Can't breathe in water void ApplySuffocationEffect(object oCreature) { int iConstitution = GetAbilityScore(oCreature, ABILITY_CONSTITUTION); int iBreathRounds = iConstitution * 2; int iSuffocationDC = 10; // Starting suffocation DC int iCurrentRound = GetLocalInt(oCreature, "SuffocationRound"); if (iCurrentRound <= iBreathRounds) { if (GetResRef(OBJECT_SELF) != "mepooze001" && GetResRef(OBJECT_SELF) != "tarmephit001" && !GetHasFeat(FEAT_WATER_BREATHING, oCreature) && !GetHasFeat(FEAT_BREATHLESS, oCreature) && !GetHasSpellEffect(SPELL_WATER_BREATHING, oCreature) && (MyPRCGetRacialType(oCreature) != RACIAL_TYPE_UNDEAD) && (MyPRCGetRacialType(oCreature) != RACIAL_TYPE_ELEMENTAL) && (MyPRCGetRacialType(oCreature) != RACIAL_TYPE_CONSTRUCT)) { SendMessageToPC(oCreature, "You are struggling to breathe in the water!"); if (d20() + GetFortitudeSavingThrow(oCreature) >= iSuffocationDC) { SendMessageToPC(oCreature, "You manage to hold your breath and avoid suffocation for now."); } else { SendMessageToPC(oCreature, "You are drowning!"); if (iCurrentRound == 1) { AssignCommand(oCreature, ActionPlayAnimation(ANIMATION_LOOPING_SPASM, 0.5f, 6.0f)); SetCurrentHitPoints(oCreature, 1); } else if (iCurrentRound == 2) { SetCurrentHitPoints(oCreature, 0); } else if (iCurrentRound == 3) { ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_DEATH), oCreature); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectDeath(), oCreature); } iCurrentRound++; } } // Store the updated round counter back in the creature's local variables SetLocalInt(oCreature, "SuffocationRound", iCurrentRound); } } //:: Water slows non-aquatic to 1/2 speed //:: unless they are under the effect of Freedom of Movement void ApplySlowEffect(object oCreature) { if (GetIsAquatic(oCreature) == FALSE && GetResRef(OBJECT_SELF) != "mepooze001" && GetResRef(OBJECT_SELF) != "tarmephit001" && !GetHasSpellEffect(SPELL_FREEDOM_OF_MOVEMENT, oCreature) || GetHasEffect(IMMUNITY_TYPE_MOVEMENT_SPEED_DECREASE, oCreature)) { // Object has either Freedom of Movement spell effect or IMMUNITY_TYPE_MOVEMENT_SPEED_DECREASE effect SendMessageToPC(GetFirstPC(), "This object has Freedom of Movement or immunity to movement speed decrease!"); } ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectMovementSpeedDecrease(50), oCreature, 6.0f); } void main() { object oArea = GetArea(OBJECT_SELF); object oCreature = GetFirstObjectInArea(oArea, OBJECT_TYPE_CREATURE); string sResref = GetResRef(oCreature); while (GetIsObjectValid(oCreature)) { //:: Calculate the armor penalty int iArmorPenalty = 0; object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature); if (GetIsObjectValid(oArmor)) { iArmorPenalty = GetItemACValue(oArmor); } //:: Calculate the DC for the Strength check int iStrengthDC = 15 + iArmorPenalty; //:: Be an Ooze Mephit or roll a Strength check against the DC if (GetIsAquatic(oCreature) == FALSE && GetResRef(OBJECT_SELF) != "mepooze001" && GetResRef(OBJECT_SELF) != "tarmephit001" || GetAppearanceType(oCreature) != APPEARANCE_TYPE_MEPHIT_OOZE || d20() + GetAbilityModifier(ABILITY_STRENGTH, oCreature) < iStrengthDC) { //:: Apply the other effects since the Strength check failed SendMessageToPC(oCreature, "You are floundering in the water!"); ApplySuffocationEffect(oCreature); } //:: Tar is always hot & slowing ApplySlowEffect(oCreature); oCreature = GetNextObjectInArea(oArea, OBJECT_TYPE_CREATURE); } }