Finished PRC8 integration. Moved creature abilities to top hak. Setup tooling. Created release archive
218 lines
8.8 KiB
Plaintext
218 lines
8.8 KiB
Plaintext
// hc_grenade
|
|
// Archaegeo 12 July 2002
|
|
// handles grenadelike attacks (oil flasks, alchemists fire, etc)
|
|
|
|
// Modified by Celedhros, 29 July 2002
|
|
// Added PHB deviation rules, enhanced visual effects, and various bug fixes
|
|
#include "prc_inc_racial"
|
|
#include "hc_text_grenade"
|
|
|
|
void main()
|
|
{
|
|
object oPC = OBJECT_SELF;
|
|
object oItem = GetLocalObject(oPC,"GRENADE");
|
|
object oTarget = GetLocalObject(oPC,"GRENADETARGET");
|
|
object oSplashTarget;
|
|
object oDeviation;
|
|
float nRangeInc;
|
|
float fDirection = GetFacing(oPC);
|
|
float fDist;
|
|
float fDeviation;
|
|
float fDeviateDist;
|
|
int iDirection;
|
|
location lTarget;
|
|
location lPC;
|
|
vector vTarget;
|
|
vector vDeviation;
|
|
effect eVis;
|
|
effect eExplode;
|
|
effect eDam;
|
|
effect eSplash;
|
|
string sNM = GetTag(oItem);
|
|
|
|
// Set Range Increment in meters
|
|
nRangeInc = FeetToMeters(10.0);
|
|
if (sNM == "hc_thunder")
|
|
nRangeInc = FeetToMeters(20.0);
|
|
// Determine if the target is an object or location and apply the correct function
|
|
if(oTarget == OBJECT_INVALID)
|
|
{
|
|
lTarget = GetItemActivatedTargetLocation();
|
|
} else {
|
|
lTarget = GetLocation(oTarget);
|
|
}
|
|
lPC = GetLocation(oPC);
|
|
fDist = GetDistanceBetweenLocations(lPC, lTarget);
|
|
// Test for maximum range
|
|
if(fDist > 5.0*nRangeInc)
|
|
{
|
|
SendMessageToPC(oPC, THROWLIMIT);
|
|
return;
|
|
}
|
|
// Determine damage and effect types
|
|
if(sNM == "hc_holywater")
|
|
{
|
|
eVis = EffectVisualEffect(VFX_IMP_HEALING_S);
|
|
eExplode = EffectVisualEffect(VFX_IMP_PULSE_WATER);
|
|
eDam = EffectDamage(d4(2), DAMAGE_TYPE_DIVINE);
|
|
eSplash = EffectDamage(d3(), DAMAGE_TYPE_DIVINE);
|
|
} else if(sNM == "hc_acidflask") {
|
|
eVis = EffectVisualEffect(VFX_IMP_ACID_S);
|
|
eDam = EffectDamage(d8(), DAMAGE_TYPE_ACID);
|
|
eSplash = EffectDamage(d3(), DAMAGE_TYPE_ACID);
|
|
} else if(sNM == "hc_thunder"){
|
|
eVis = EffectVisualEffect(VFX_IMP_SONIC);
|
|
eExplode = EffectVisualEffect(VFX_IMP_PULSE_WIND);
|
|
eDam = EffectDeaf();
|
|
eSplash = EffectDeaf();
|
|
} else if(sNM == "hc_tangle") {
|
|
eVis = EffectVisualEffect(VFX_IMP_SLOW);
|
|
eDam = EffectEntangle();
|
|
}
|
|
else {
|
|
eVis = EffectVisualEffect(VFX_IMP_FLAME_M);
|
|
eExplode = EffectVisualEffect(VFX_IMP_PULSE_FIRE);
|
|
eDam = EffectDamage(d6(), DAMAGE_TYPE_FIRE);
|
|
eSplash = EffectDamage(1, DAMAGE_TYPE_FIRE);
|
|
}
|
|
// Ranged touch attack for grenadelike weapons
|
|
int touchAttack = TouchAttackRanged(oTarget, 1);
|
|
if(touchAttack == 1 || touchAttack == 2)
|
|
{
|
|
if(sNM == "hc_tangle")
|
|
{
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDam, oTarget, TurnsToSeconds(1));
|
|
//Duration of standing still (assumes that the player takes 3 rounds removing themself from the "goo")
|
|
int iTangle = 3;
|
|
if (d20()+ GetAbilityModifier(ABILITY_STRENGTH, oTarget) > 27)
|
|
iTangle = 1;
|
|
//Reflex Save to avoid 90% movement decrease (standing still)
|
|
if (!ReflexSave(oTarget, 15))
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectMovementSpeedDecrease(90), oTarget, RoundsToSeconds(iTangle));
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_IMP_SLOW), oTarget, RoundsToSeconds(iTangle));
|
|
DestroyObject(oItem);
|
|
return;
|
|
}
|
|
|
|
if(sNM == "hc_oilflask" && Random(100) < 50)
|
|
{
|
|
SendMessageToPC(oPC, FAILIGNITE);
|
|
DestroyObject(oItem);
|
|
return;
|
|
}
|
|
if(sNM == "hc_holywater" && MyPRCGetRacialType(oTarget) != RACIAL_TYPE_UNDEAD)
|
|
{
|
|
SendMessageToPC(oPC, NOEFFECT);
|
|
DestroyObject(oItem);
|
|
}
|
|
else {
|
|
if (sNM == "hc_thunder")
|
|
{
|
|
if (!FortitudeSave(oTarget,15))
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eDam, oTarget);
|
|
}
|
|
else {
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget);
|
|
// Second round 1d6 Damage for Oil and Alchemist's Fire with Reflex DC15 to avoid
|
|
if (sNM != "hc_tangle" && sNM != "hc_thunder" &&
|
|
sNM != "hc_acidflask" && sNM != "hc_holywater" && !ReflexSave(oTarget, 15, SAVING_THROW_TYPE_FIRE))
|
|
{
|
|
eDam = EffectDamage(d6(), DAMAGE_TYPE_FIRE);
|
|
DelayCommand(6.0,ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
|
|
}
|
|
}
|
|
}
|
|
// Grenadelike weapon deviation per PHB pg. 138
|
|
} else if (touchAttack == 0 && oTarget != OBJECT_INVALID) {
|
|
vTarget = GetPositionFromLocation(lTarget);
|
|
oDeviation = GetAreaFromLocation(lTarget);
|
|
fDeviation = GetFacingFromLocation(lTarget);
|
|
fDeviateDist = IntToFloat(d6());
|
|
fDeviateDist = FeetToMeters(fDeviateDist) + (fDist/nRangeInc);
|
|
fDirection = fDirection/45;
|
|
iDirection = FloatToInt(fDirection);
|
|
if (iDirection == 8) iDirection = 0;
|
|
iDirection = iDirection + d8();
|
|
if (iDirection > 8) iDirection = iDirection - 8;
|
|
switch (iDirection)
|
|
{
|
|
case 1:
|
|
vDeviation = Vector(fDeviateDist,0.0,0.0);
|
|
break;
|
|
case 2:
|
|
fDeviateDist = sqrt((pow(fDeviateDist,2.0)/2));
|
|
vDeviation = Vector(fDeviateDist,(0.0-fDeviateDist),0.0);
|
|
break;
|
|
case 3:
|
|
vDeviation = Vector(0.0,(0.0-fDeviateDist),0.0);
|
|
break;
|
|
case 4:
|
|
fDeviateDist = sqrt((pow(fDeviateDist,2.0)/2));
|
|
vDeviation = Vector((0.0-fDeviateDist),(0.0-fDeviateDist),0.0);
|
|
break;
|
|
case 5:
|
|
vDeviation = Vector((0.0-fDeviateDist),0.0,0.0);
|
|
break;
|
|
case 6:
|
|
fDeviateDist = sqrt((pow(fDeviateDist,2.0)/2));
|
|
vDeviation = Vector((0.0-fDeviateDist),fDeviateDist,0.0);
|
|
break;
|
|
case 7:
|
|
vDeviation = Vector(0.0,fDeviateDist,0.0);
|
|
break;
|
|
case 8:
|
|
fDeviateDist = sqrt((pow(fDeviateDist,2.0)/2));
|
|
vDeviation = Vector(fDeviateDist,fDeviateDist,0.0);
|
|
break;
|
|
}
|
|
vDeviation = vDeviation + vTarget;
|
|
lTarget = Location(oDeviation,vDeviation,fDeviation);
|
|
}
|
|
// Apply visual effects at target location
|
|
if (sNM == "hc_holywater" && MyPRCGetRacialType(oTarget) == RACIAL_TYPE_UNDEAD && touchAttack == 1)
|
|
{
|
|
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eVis, lTarget);
|
|
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eExplode, lTarget);
|
|
} else if (sNM != "hc_holywater"){
|
|
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eVis, lTarget);
|
|
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eExplode, lTarget);
|
|
} else {
|
|
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eExplode, lTarget);
|
|
}
|
|
SignalEvent(oTarget, EventSpellCastAt(oPC, SPELL_MAGIC_MISSILE));
|
|
// Apply splash damage radius and get first target
|
|
float nSplashRange = FeetToMeters(5.0);
|
|
if (sNM == "hc_thunder")
|
|
nSplashRange = FeetToMeters(10.0);
|
|
oSplashTarget = GetFirstObjectInShape(SHAPE_SPHERE, nSplashRange, lTarget, TRUE, OBJECT_TYPE_CREATURE);
|
|
while(GetIsObjectValid(oSplashTarget))
|
|
{
|
|
// If PC makes successful touch attack, do not apply splash damage to target
|
|
if (oTarget == oSplashTarget && touchAttack == 1)
|
|
{
|
|
oSplashTarget = GetNextObjectInShape(SHAPE_SPHERE, nSplashRange, lTarget, TRUE, OBJECT_TYPE_CREATURE);
|
|
} else if (sNM!="hc_holywater"){
|
|
// Apply splash damage to valid target in radius and get next valid target
|
|
if (sNM == "hc_thunder") //Thunderstone Deafness
|
|
{
|
|
if (!FortitudeSave(oSplashTarget, 15))
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSplash, oSplashTarget);
|
|
}
|
|
else
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eSplash, oSplashTarget);
|
|
SignalEvent(oSplashTarget, EventSpellCastAt(oPC, SPELL_MAGIC_MISSILE));
|
|
oSplashTarget = GetNextObjectInShape(SHAPE_SPHERE, nSplashRange, lTarget, TRUE, OBJECT_TYPE_CREATURE);
|
|
} else if (sNM == "hc_holywater" && MyPRCGetRacialType(oTarget) == RACIAL_TYPE_UNDEAD){
|
|
// Apply holy water splash damage to valid target in radius and get next target
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eSplash, oSplashTarget);
|
|
SignalEvent(oSplashTarget, EventSpellCastAt(oPC, SPELL_MAGIC_MISSILE));
|
|
oSplashTarget = GetNextObjectInShape(SHAPE_SPHERE, nSplashRange, lTarget, TRUE, OBJECT_TYPE_CREATURE);
|
|
} else {
|
|
// Get next valid target if holy water splash target is not undead
|
|
oSplashTarget = GetNextObjectInShape(SHAPE_SPHERE, nSplashRange, lTarget, TRUE, OBJECT_TYPE_CREATURE);
|
|
}
|
|
}
|
|
DestroyObject(oItem);
|
|
return;
|
|
}
|