Jaysyn904 84d583b489 Added Mine & Caverns raise & lower functionality
Added Mine & Caverns raise & lower functionality.  Revamped Level 1 events to match PnP.  Updated Level 1: Core.  Added new Footcatcher trap type. Added Underwater heartbeat to Glop Lake Underwater.  Full compile.
2023-09-16 09:04:37 -04:00

174 lines
5.8 KiB
Plaintext

//::////////////////////////////////////////////////////////////////////////////
//::
// 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);
}
}