PWE_PRC8/_module/nss/groundtrap1.nss
Jaysyn904 ee1dc35889 Initial Commit
Initial Commit
2025-04-03 10:29:41 -04:00

431 lines
15 KiB
Plaintext

//::///////////////////////////////////////////////
//:: Name Respawning Ground Traps
//:: FileName groundtrap1
//:: Written by Firestarter
//:://////////////////////////////////////////////
/*
Allows ground traps to respawn. Works in association
with David Etheridge/Firestarter's illusion/trap
detection system but those scripts not essential.
Closely follows individual scripts for nw traps
ie. nw_t1_* created by Preston Watamaniuk.
Instructions:
Put this script in the OnEnter of a generic trigger.
Place a trapped placeable with tag: "Trapme" over the trigger.
The placeable must be within 3m of the trigger.
Modify the Appearance of the placeable to a throw rug,
stones, grass stalk etc to match its environment.
Uncheck the Has Inventory box of the placeable.
Alter the placeable description as required.
Check the plot box of the placeable - this is used not only
to preserve the trap but as a switch to ensure that
multiple trap objects do not spawn.
The faction of the placeable & trigger should be Hostile.
Put a trap on the placeable of your choice.
Make a custom copy of the placeable and use that custom
copy to place the placeable - otherwise the ResRef will
not match and the placeable will not respawn.
It is a good idea to make a few custom placeables with
those changes made for quicker placement later.
The trigger area must not extend out from the trapped
placeable so that the PC can reach the placeable
without setting off the trap.
This script closely reproduces the effects of all
the standard game traps. It will work in Persistant
Worlds.
To alter the respawn time see the line 74. The
respawn time is from when the script is triggered so if
noone steps on the trigger the trap won't respawn. The
minimum respawn time is 5.0 seconds. If fDelay is set to 0.0
the trap won't respawn at all then any respawning must be
controlled by another script.
*/
//:://////////////////////////////////////////////
//:: Created By: Firestarter
//:: Created On: 10 Dec 2002
//:: Modified & debugged: 19th Feb 2003
//:://////////////////////////////////////////////
#include "prc_inc_spells"
//needed for MySavingThrow function
#include "NW_I0_SPELLS"
//function to respawn trap
void CreateTrap(string sTrap,location lTrap)
{
CreateObject(OBJECT_TYPE_PLACEABLE,sTrap,lTrap);
}
void main()
{
object oEnter=GetEnteringObject();
object oTrap=GetNearestObjectByTag("Trapme");
effect eKillTrap=EffectDamage(200);
string sTrap=GetResRef(oTrap);
location lTrap=GetLocation(oTrap);
float fDelay=60.0; //delay before trap respawns
//if 0.0 trap will not respawn
//check if oEnter is a someone trying to remove trap
int iAction=GetCurrentAction(oEnter);
if (iAction==ACTION_DISABLETRAP
|| iAction==ACTION_RECOVERTRAP
|| iAction==ACTION_EXAMINETRAP) return;
if ((GetIsEnemy(oEnter,oTrap))
&&GetIsTrapped(oTrap)
&&GetDistanceToObject(oTrap)<3.0)
{
//object oTrapper=GetTrapCreator(oTrap);
//SendMessageToPC(oTrapper,"trap away");
object oTarget; //area targets
int iTrap=GetTrapBaseType(oTrap);
int iTrapDC=GetTrapDisarmDC(oTrap); //**?
location lTarget=GetLocation(oEnter);
//centre of area (sphere) effects
int eTrap; //visual effect number
int iAreaEffect=0; //set to 1 if vis effect is an area effect
effect eEffect;
effect eLightning; //beam effect in lightning trap
//Used e for effect int numbers
int eBeam; //any beam effect to add
effect eBad; //bad effect of trap
int NoSaveBad=0; //set to 1 if there is no save vs eBad
int eToLink; //effect number to link to eBad
effect eLink; //linked eBad+eToLink effect
int iDamageFactor; //minor(1),average(2),strong(3),deadly(4)
int iDamageType;
effect eDam; //damage effect
int iSaveType;
int iDamage; //actual damage done
int NoSaveDam=0; //Set to 1 if there is no save vs damage
//int iTrapSpell; //any associated spells
//int iTrapSpell2;
int iFakeSpell;
int iRepeat; //**? if TRUE spell iDamageFactor times
int iCount; //for spell repeating
int iNuDice; //number of damage dice
location lTrapvis; //used if vis effect to apply to location
int iRacialType; //type of monster the trap attacks
float fRadius=0.0; //radius for area effect traps
int iMaxHits=99; //maximum creatures that can be hit
//for elecric traps is less
int iDuration; //any effect duration
int iDC; //any difficulty check
int iSaveThrow=SAVING_THROW_REFLEX; //normal saving throw
//set trap effect type and damage
if (iTrap<4)
{
//spike trap
eTrap=253; //spikes
lTrapvis=GetLocation(oEnter);
iDamageFactor=1+iTrap;
iDamageType=DAMAGE_TYPE_PIERCING;
iNuDice=iDamageFactor+1;
if (iDamageFactor==3) iNuDice=5;
if (iDamageFactor==4) iNuDice=25;
NoSaveDam=1;
}
else if (iTrap<8)
{
//holy trap (do 1/3 damage if not undead)
eTrap=VFX_IMP_SUNSTRIKE;
iDamageFactor=iTrap-3;
iDamageType=DAMAGE_TYPE_DIVINE;
iNuDice=(iDamageFactor*5)-1; //approx as d10s not used
iRacialType=RACIAL_TYPE_UNDEAD;
NoSaveDam=1;
}
else if (iTrap<12)
{
//tangle trap
eTrap=VFX_IMP_SLOW;
iDamageFactor=iTrap-7;
//iTrapSpell=SPELL_SLOW;
//iRepeat=TRUE;
eBad=EffectSlow();
iSaveType=SAVING_THROW_TYPE_NONE;
iDC=(iDamageFactor+3)*5;
fRadius=RADIUS_SIZE_SMALL;
if (iDamageFactor>2) fRadius=RADIUS_SIZE_MEDIUM;
}
else if (iTrap<16)
{
//acid trap
eTrap=VFX_IMP_ACID_S;
eBad=EffectParalyze();
eToLink=VFX_DUR_PARALYZED;
iDamageFactor=iTrap-11;
iDuration=iDamageFactor+1;
iDamageType=DAMAGE_TYPE_ACID;
iSaveType=SAVING_THROW_TYPE_ACID;
iNuDice=(iDamageFactor*iDamageFactor)+2;
iDC=(iDamageFactor+2)*5;
if (iDamageFactor==4) iDC=25;
NoSaveDam=1;
}
else if (iTrap<20)
{
//fire trap
eTrap=VFX_IMP_FLAME_M;
iDamageFactor=iTrap-15;
iDamageType=DAMAGE_TYPE_FIRE;
iSaveType=SAVING_THROW_TYPE_FIRE;
fRadius=RADIUS_SIZE_SMALL;
if (iDamageFactor>2) fRadius=RADIUS_SIZE_MEDIUM;
iNuDice=(iDamageFactor*iDamageFactor)+4;
if (iDamageFactor==3) iNuDice=11;
if (iDamageFactor==4) iNuDice=14;
iDC=(iDamageFactor*3)+14; //1 low for minor trap
}
else if (iTrap<24)
{
//electrical trap
eTrap=VFX_IMP_LIGHTNING_S;
eBeam=VFX_BEAM_LIGHTNING;
iDamageFactor=iTrap-19;
iDamageType=DAMAGE_TYPE_ELECTRICAL;
iSaveType=SAVING_THROW_TYPE_ELECTRICITY;
iNuDice=iDamageFactor*8;
fRadius=RADIUS_SIZE_LARGE;
iMaxHits=iDamageFactor+2;
iDC=(iDamageFactor*3)+16; //1 low for strong trap
}
else if (iTrap<28)
{
//gas trap
iDamageFactor=iTrap-23;
iFakeSpell=SPELL_STINKING_CLOUD;//??
eTrap=AOE_PER_FOGACID;
if (iDamageFactor==1) eBad=EffectPoison(POISON_GIANT_WASP_POISON);
if (iDamageFactor==2) eBad=EffectPoison(POISON_DEATHBLADE);
if (iDamageFactor==3) eBad=EffectPoison(POISON_DARK_REAVER_POWDER);
if (iDamageFactor==4) eBad=EffectPoison(POISON_BLACK_LOTUS_EXTRACT);
fRadius=RADIUS_SIZE_LARGE;
iDuration=3;
iAreaEffect=1;
NoSaveBad=1;
}
else if (iTrap<32)
{
//frost trap
eTrap=VFX_IMP_FROST_S;
iDamageFactor=iTrap-27;
iDamageType=DAMAGE_TYPE_COLD;
iSaveType=SAVING_THROW_TYPE_COLD;
iNuDice=2;
if (iDamageFactor==4) iNuDice=6;
eBad=EffectParalyze();
eToLink=VFX_DUR_BLUR;
iDuration=iDamageFactor;
iDC=11+iDamageFactor;
int iSaveThrow=SAVING_THROW_FORT;
NoSaveDam=1;
}
else if (iTrap<36)
{
//negative trap
eTrap=VFX_IMP_REDUCE_ABILITY_SCORE;
iDamageFactor=iTrap-31;
iDamageType=DAMAGE_TYPE_NEGATIVE;
iSaveType=SAVING_THROW_TYPE_NEGATIVE;
iNuDice=(iDamageFactor+1);
if (iDamageFactor==4) iNuDice=10;
int StrLoss=iDamageFactor-1;
if (StrLoss==0) StrLoss=1;
eBad=EffectAbilityDecrease(ABILITY_STRENGTH, StrLoss);
eBad = SupernaturalEffect(eBad);
iDC=(iDamageFactor*3)+9;
int iSaveThrow=SAVING_THROW_FORT;
NoSaveDam=1;
}
else if (iTrap<40)
{
//sonic trap
eTrap=VFX_FNF_SOUND_BURST;
iDamageFactor=iTrap-35;
iDamageType=DAMAGE_TYPE_SONIC;
iSaveType=SAVING_THROW_TYPE_SONIC;
iNuDice=iDamageFactor; //approx as d4s not used
if (iDamageFactor==4) iNuDice=6;
eBad = EffectStunned();
eToLink = VFX_DUR_MIND_AFFECTING_DISABLED;
fRadius=RADIUS_SIZE_MEDIUM;
int iSaveThrow=SAVING_THROW_WILL;
iDuration=iDamageFactor+1;
iDC=(iDamageFactor*3)+8; //1 low for minor trap
iAreaEffect=1;
NoSaveDam=1;
}
else
{
//acid splash trap
eTrap=VFX_IMP_ACID_S;
iDamageFactor=iTrap-39;
iDamageType=DAMAGE_TYPE_ACID;
iSaveType=SAVING_THROW_TYPE_ACID;
iNuDice=(iDamageFactor*2);//approx as d8s not used
if (iDamageFactor==4) iNuDice=10;
iDC=(iDamageFactor*3)+9;
}
//set universal variables
if (eTrap==AOE_PER_FOGACID) eEffect=EffectAreaOfEffect(eTrap, "****", "****", "****");
else eEffect=EffectVisualEffect(eTrap);
iDamage=d6(iNuDice);
eDam = EffectDamage(iDamage, iDamageType);
//Apply trap effects
if (fRadius>0.0) //for traps with area effect
{
//Place visible effect
if (eTrap==AOE_PER_FOGACID)
{
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eEffect,
lTarget, RoundsToSeconds(iDuration));
}
if (eToLink>0) //sonic
{
//Place visible effect
ApplyEffectAtLocation(DURATION_TYPE_INSTANT,eEffect,lTarget);
effect eMind=EffectVisualEffect(eToLink);
eLink=EffectLinkEffects(eBad, eMind);
}
oTarget = GetFirstObjectInShape(SHAPE_SPHERE,
fRadius,lTarget);
int nCount;
for(nCount=1;GetIsObjectValid(oTarget)&&nCount<=iMaxHits;nCount++)
{
if(!GetIsReactionTypeFriendly(oTarget))
{
//Adjust the trap damage based on the feats of the target
if(!PRCMySavingThrow(iSaveThrow, oTarget, iDC, iSaveType))
{
if (GetHasFeat(FEAT_IMPROVED_EVASION, oTarget))
iDamage /= 2;
}
else if (GetHasFeat(FEAT_EVASION, oTarget) || GetHasFeat(FEAT_IMPROVED_EVASION, oTarget))
iDamage = 0;
else iDamage /= 2;
if(NoSaveDam==1) iDamage=d6(iNuDice);
if (iDamage > 0)
{
//Apply effects to the target.
eDam = EffectDamage(iDamage, iDamageType);
if (iAreaEffect==0)
ApplyEffectToObject(DURATION_TYPE_INSTANT, eEffect, oTarget);
if (eBeam>0)
{
//Connect the beam from initial target to all others.
eLightning = EffectBeam(eBeam, oEnter, BODY_NODE_CHEST);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLightning, oTarget, 0.75);
}
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget);
}
if (GetIsEffectValid(eBad)) //Tangle or Gas or Sonic trap
{
if (NoSaveBad=1)ApplyEffectToObject(DURATION_TYPE_INSTANT, eBad, oTarget);
else if(!PRCMySavingThrow(iSaveThrow,oTarget,iDC,iSaveType))
{
//Apply bad effect and visible effect
if (eToLink>0)
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
eLink, oTarget, RoundsToSeconds(iDuration));
else
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, eEffect, oTarget);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBad, oTarget, RoundsToSeconds(iDuration));
}
}
}
}
//if (GetCurrentHitPoints(oTarget)<=0)
//GiveXPToCreature(oTrapper,FloatToInt
//(IntToFloat(GetHitDice(oTarget))*20/(FloatToInt(IntToFloat(GetHitDice(oTrapper))/2))));
oTarget = GetNextInPersistentObject();
}
}
else //Acid, Frost, Negative, Holy, Spike or Acid Splash
{
if(!PRCMySavingThrow(iSaveThrow, oTarget, iDC, iSaveType))
{
if (eToLink>0) //Acid, Frost
{
effect eBadLink=EffectVisualEffect(eToLink);
eLink=EffectLinkEffects(eBad, eBadLink);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
eBadLink, oTarget, RoundsToSeconds(iDuration));
}
else ApplyEffectToObject(DURATION_TYPE_PERMANENT,
eBad, oTarget);
}
if ((!MyPRCGetRacialType(oTarget) == RACIAL_TYPE_UNDEAD)
&& eTrap==VFX_IMP_SUNSTRIKE) //holy trap not vs undead
iDamage=FloatToInt(IntToFloat(iDamage)/3);
if (eTrap==VFX_IMP_ACID_S)//acid splash
iDamage=PRCGetReflexAdjustedDamage(iDamage,
oTarget, iDC, iSaveType);
//renew eDam for above tests
eDam = EffectDamage(iDamage, iDamageType);
//apply visible and damage
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oEnter);
if (eTrap==253)//spike effect at location
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eEffect, lTarget);
else ApplyEffectToObject(DURATION_TYPE_INSTANT, eEffect, oEnter);
}
//destroy trap and respawn it in one minute
SetTrapDisabled(oTrap);
SetPlotFlag(oTrap,FALSE);
DelayCommand(5.0,ApplyEffectToObject(DURATION_TYPE_INSTANT,
eKillTrap,oTrap));
//Trap has gone off, respawn it after fDelay seconds.
if (fDelay>0.0)
{
if (fDelay<5.0) fDelay=5.0;
DelayCommand(fDelay,CreateTrap(sTrap,lTrap));
}
}
//if trap has been disarmed then respawn it in fDelay seconds
if(!GetIsTrapped(oTrap)
&&GetDistanceToObject(oTrap)<3.0
&&GetPlotFlag(oTrap)==TRUE
&&fDelay>0.0)
{
//SendMessageToPC(GetFirstPC(),"no trap ..");
SetPlotFlag(oTrap,FALSE);
//change the 55.0 and 60.0 (keep ~5 secs between) to alter
//the respawn time.
if (fDelay<5.0) fDelay=5.0;
DelayCommand(fDelay-5.0,ApplyEffectToObject(DURATION_TYPE_INSTANT,
eKillTrap,oTrap));
DelayCommand(fDelay,CreateTrap(sTrap,lTrap));
}
}
//Notes:
//Could not use TrapDoElectricalDamage nw function
//-it seemed indiscriminate.
//Only used gas trap visible AOE.
//Negative deadly does not use EffectNegativeLevel(1)
//instead applies extra damage and more Strength loss.