172 lines
7.8 KiB
Plaintext
172 lines
7.8 KiB
Plaintext
//This function is called from the onenter event of an underwater area
|
|
//
|
|
//Set a local int on the underwater creatures that will be spawned in the underwater
|
|
//area. If you do not the creatures will also drown.
|
|
// Name: Aquatic
|
|
// Type: int
|
|
// Value: 1
|
|
// -----------------------------------------------------------------------------
|
|
// CONSTANTS
|
|
// -----------------------------------------------------------------------------
|
|
const float BREATH_CHECK = 6.0; // << Breath check delay in seconds
|
|
const string WATER_BREATHING_ITEM = "vg_wb_item"; // << Tag of water breathing items
|
|
const string WATER_SWIMMING_ITEM = "vg_ws_item"; // << Tag of water swimming items
|
|
// -----------------------------------------------------------------------------
|
|
// PROTOTYPES
|
|
// -----------------------------------------------------------------------------
|
|
// Check player is wearing an underwater breathing item
|
|
int WearingWaterItemCheck(object oPC);
|
|
//Do the underwater check
|
|
void UnderWaterCheck(object oPC);
|
|
|
|
#include "prc_inc_racial"
|
|
|
|
//:: void main (){}
|
|
// -----------------------------------------------------------------------------
|
|
// FUNCTIONS
|
|
// -----------------------------------------------------------------------------
|
|
int WearingWaterBreathingItem(object oPC)
|
|
{
|
|
if(GetTag(GetItemInSlot(INVENTORY_SLOT_ARMS, oPC)) == WATER_BREATHING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_BELT, oPC)) == WATER_BREATHING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_BOOTS, oPC)) == WATER_BREATHING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC)) == WATER_BREATHING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_CHEST, oPC)) == WATER_BREATHING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_CLOAK, oPC)) == WATER_BREATHING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_HEAD, oPC)) == WATER_BREATHING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_LEFTRING, oPC)) == WATER_BREATHING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_NECK, oPC)) == WATER_BREATHING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_RIGHTRING, oPC)) == WATER_BREATHING_ITEM ||
|
|
GetLocalInt(oPC, "WBPOTION"))
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
int WearingWaterSwimmingItem(object oPC)
|
|
{
|
|
if(GetTag(GetItemInSlot(INVENTORY_SLOT_ARMS, oPC)) == WATER_SWIMMING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_BELT, oPC)) == WATER_SWIMMING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_BOOTS, oPC)) == WATER_SWIMMING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC)) == WATER_SWIMMING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_CHEST, oPC)) == WATER_SWIMMING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_CLOAK, oPC)) == WATER_SWIMMING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_HEAD, oPC)) == WATER_SWIMMING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_LEFTRING, oPC)) == WATER_SWIMMING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_NECK, oPC)) == WATER_SWIMMING_ITEM ||
|
|
GetTag(GetItemInSlot(INVENTORY_SLOT_RIGHTRING, oPC)) == WATER_SWIMMING_ITEM ||
|
|
GetLocalInt(oPC, "WSPOTION"))
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
void UnderWaterCheck(object oPC)
|
|
{
|
|
int iCON = GetAbilityModifier(ABILITY_CONSTITUTION,oPC); // << Constitution Modifier of oPC
|
|
int iCONSave = d20(1) + iCON; // << CON Save if failed to hold breath
|
|
int iHOLD = 2 + (iCON*2); // << Let them hold their breath in seconds
|
|
|
|
if(GetLocalInt(oPC, "UNDERWATER") == 0) return;
|
|
|
|
if(WearingWaterBreathingItem(oPC) == FALSE)
|
|
{
|
|
if(WearingWaterSwimmingItem(oPC) == FALSE)
|
|
{
|
|
// Reduce the entering objects movement speed and mark them as being under water
|
|
ApplyEffectToObject(2, EffectMovementSpeedDecrease(50), oPC, 0.0);
|
|
}
|
|
int iROUND = GetLocalInt(oPC,"ROUND"); // << Determines number of rounds
|
|
if (iROUND <= iHOLD)
|
|
{
|
|
iROUND=iROUND+1;
|
|
SetLocalInt(oPC,"ROUND",iROUND);
|
|
SendMessageToPC(oPC,"** You are holding your breath **");
|
|
|
|
// DEBUG
|
|
if (GetLocalInt(GetModule(),"Debug")==1)
|
|
{
|
|
string sROUND = IntToString(iROUND);
|
|
SendMessageToPC(oPC,"DEBUG: This is round number "+sROUND);
|
|
}
|
|
}
|
|
if (iROUND > iHOLD)
|
|
{
|
|
int iDC = GetLocalInt(oPC,"DC"); // << DC to keep holding breath
|
|
if (iCONSave>=iDC)
|
|
{
|
|
iDC=iDC+1;
|
|
SetLocalInt(oPC,"DC",iDC);
|
|
SendMessageToPC(oPC,"** You are barely holding your breath **");
|
|
FloatingTextStringOnCreature("** blub blub **", oPC);
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_DUR_BUBBLES), oPC);
|
|
|
|
// DEBUG
|
|
if (GetLocalInt(GetModule(),"Debug")==1)
|
|
{
|
|
string sDC = IntToString(iDC);
|
|
SendMessageToPC(oPC,"DEBUG: The DC is now "+sDC);
|
|
}
|
|
}
|
|
if (iCONSave < iDC)
|
|
{
|
|
int iHPs=GetCurrentHitPoints(oPC);
|
|
int iDROWN=GetLocalInt(oPC,"DROWN");
|
|
FloatingTextStringOnCreature("** Drowning: blub blub **", oPC, FALSE);
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_DUR_BUBBLES), oPC);
|
|
if(iDROWN == 2)
|
|
{
|
|
effect eDamage=EffectDamage(iHPs,DAMAGE_TYPE_DIVINE,DAMAGE_POWER_PLUS_TWENTY);
|
|
//effect eDamage=EffectDamage(10,DAMAGE_TYPE_DIVINE,DAMAGE_POWER_PLUS_TWENTY);
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT,eDamage,oPC,0.0);
|
|
SetLocalInt(oPC,"DROWN",0);
|
|
}
|
|
if(iDROWN == 1)
|
|
{
|
|
effect eDamage=EffectDamage(iHPs/2,DAMAGE_TYPE_DIVINE,DAMAGE_POWER_PLUS_TWENTY);
|
|
//effect eDamage=EffectDamage(1,DAMAGE_TYPE_DIVINE,DAMAGE_POWER_PLUS_TWENTY);
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT,eDamage,oPC,0.0);
|
|
SetLocalInt(oPC,"DROWN",2);
|
|
}
|
|
if(iDROWN == 0)
|
|
{
|
|
effect eDamage=EffectDamage(iHPs/4,DAMAGE_TYPE_DIVINE,DAMAGE_POWER_PLUS_TWENTY);
|
|
//effect eDamage=EffectDamage(iHPs,DAMAGE_TYPE_DIVINE,DAMAGE_POWER_PLUS_TWENTY);
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT,eDamage,oPC,0.0);
|
|
SetLocalInt(oPC,"DROWN",1);
|
|
}
|
|
}
|
|
iROUND=iROUND+1;
|
|
SetLocalInt(oPC,"ROUND",iROUND);
|
|
}
|
|
}
|
|
DelayCommand(BREATH_CHECK, UnderWaterCheck(oPC));
|
|
}
|
|
void Water_Enter(object oPC)
|
|
{
|
|
// Skip creatures set to breathe underwater
|
|
if(GetLocalInt(oPC, "Aquatic") == TRUE) return;
|
|
// Skip DM's
|
|
if(GetIsDM(oPC) || GetIsDMPossessed(oPC)) return;
|
|
// Skip Undead, Constructs & Elementals
|
|
if(MyPRCGetRacialType(oPC) == RACIAL_TYPE_UNDEAD ||
|
|
MyPRCGetRacialType(oPC) == RACIAL_TYPE_CONSTRUCT ||
|
|
MyPRCGetRacialType(oPC) == RACIAL_TYPE_ELEMENTAL) return;
|
|
// Torch goes out underwater
|
|
object oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
|
|
if(GetBaseItemType(oItem) == BASE_ITEM_TORCH)
|
|
{
|
|
DelayCommand(1.0, FloatingTextStringOnCreature("Your torch fizzles out.", oPC));
|
|
DelayCommand(1.0, AssignCommand(oPC, ActionUnequipItem(oItem)));
|
|
}
|
|
if(WearingWaterSwimmingItem(oPC) == FALSE)
|
|
{
|
|
// Reduce the entering objects movement speed and mark them as being under water
|
|
ApplyEffectToObject(2, EffectMovementSpeedDecrease(75), oPC, 0.0);
|
|
}
|
|
// Set up drowning control Ints
|
|
SetLocalInt(oPC, "UNDERWATER", 1);
|
|
SetLocalInt(oPC,"ROUND",0);
|
|
SetLocalInt(oPC,"DC",10);
|
|
SetLocalInt(oPC,"DROWN",0);
|
|
DelayCommand(0.1, FloatingTextStringOnCreature("** This water is deep! **", oPC));
|
|
// Start checking for holding of breath and damage
|
|
DelayCommand(0.5, UnderWaterCheck(oPC));
|
|
}
|