431 lines
15 KiB
Plaintext
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.
|