generated from Jaysyn/ModuleTemplate
151 lines
6.5 KiB
Plaintext
151 lines
6.5 KiB
Plaintext
////
|
|
// Bead of Force
|
|
// Created by Solias (sorcerer@wnwn.net)
|
|
// http://www.wnwn.net/
|
|
//
|
|
// This script implements the unique power for the bead of force item.
|
|
// Include it into your item handler and call the functions below
|
|
//
|
|
//
|
|
|
|
// actions to be taken by the creature on a bounce
|
|
// loc is the location to bounce to.
|
|
void wi_bounce_creature(location loc);
|
|
|
|
|
|
// calculate where a creature should land after a blast
|
|
// creature - location of creature hit by blast
|
|
// blast - blast point
|
|
// blast_strength - maximum distance to throw creature
|
|
// max_range - if you want to use a linear fall-off function to determine how far to throw
|
|
// the creatures then set this value to the maximum blast radius, if you want to
|
|
// blast all creatures with the same force then set this value to 0.0 (the default).
|
|
// blast_strength should be less than max range or the effects may look strange.
|
|
location wi_calculate_blast(location creature, location blast, float blast_strength=3.0, float max_range=0.0);
|
|
|
|
|
|
// This function will apply the bead of force effect at the given location
|
|
// self is the location of the user, target is the target he chose.
|
|
void wi_bof_effect(object self, location target);
|
|
|
|
|
|
// actions to be taken by the creature on a bounce
|
|
void wi_bounce_creature(location loc) {
|
|
ClearAllActions();
|
|
JumpToLocation(loc);
|
|
ActionDoCommand(SetCommandable(TRUE));
|
|
SetCommandable(FALSE);
|
|
}
|
|
|
|
// calculate where a creature should land after a blast
|
|
location wi_calculate_blast(location creature, location blast, float blast_strength, float max_range=0.0) {
|
|
|
|
// Calculate the direction vector from blast through creature
|
|
vector vc = GetPositionFromLocation(creature);
|
|
vector vb = GetPositionFromLocation(blast);
|
|
vector dv = vc - vb;
|
|
|
|
float blast_distance = VectorMagnitude(dv);
|
|
|
|
// Calculate blast strength (linear fall-off):
|
|
if(max_range > 0.0) {
|
|
|
|
// Case 1: target out of blast range
|
|
if(blast_distance >= max_range) blast_strength = 0.0;
|
|
|
|
// Case 2: Target at blast point
|
|
// In this case just choose a random direction to blast the creature.
|
|
// Use maximum strength
|
|
else if(blast_distance <= 0.0) dv = AngleToVector(IntToFloat(Random(360)));
|
|
|
|
// Case 3: Target in range
|
|
else {
|
|
blast_distance = (max_range - blast_distance) / max_range;
|
|
blast_strength = blast_strength * blast_distance;
|
|
}
|
|
}
|
|
|
|
// Even if we are not using linear fall-off we still need to avoid degenerate vectors
|
|
else if(blast_distance <= 0.0) dv = AngleToVector(IntToFloat(Random(360)));
|
|
|
|
// Normalize the vector since all we want is direction
|
|
dv = VectorNormalize(dv);
|
|
|
|
// Calculate final displacement vector
|
|
dv = (dv * blast_strength);
|
|
|
|
// Return the new location
|
|
return Location(GetAreaFromLocation(creature), vc + dv, GetFacingFromLocation(creature));
|
|
}
|
|
|
|
|
|
// This function will apply the bead of force effect at the given location
|
|
void wi_bof_effect(object self, location target) {
|
|
|
|
location self_location = GetLocation(self);
|
|
|
|
effect bead = EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_MIND);
|
|
effect blast = EffectVisualEffect(VFX_FNF_SOUND_BURST);
|
|
effect shake = EffectVisualEffect(VFX_FNF_SCREEN_BUMP);
|
|
effect field = EffectVisualEffect(VFX_DUR_GLOBE_INVULNERABILITY);
|
|
effect impact = EffectVisualEffect(VFX_IMP_SUNSTRIKE);
|
|
effect strike = EffectVisualEffect(VFX_IMP_KNOCK);
|
|
effect damage = EffectDamage(d6(5),DAMAGE_TYPE_BLUDGEONING);
|
|
effect hold = EffectParalyze();
|
|
effect immune_blunt = EffectDamageResistance(DAMAGE_TYPE_BLUDGEONING, 60);
|
|
effect immune_pierce = EffectDamageResistance(DAMAGE_TYPE_PIERCING, 60);
|
|
effect immune_slash = EffectDamageResistance(DAMAGE_TYPE_SLASHING, 60);
|
|
|
|
float fDist = GetDistanceBetweenLocations(self_location, target);
|
|
float fDelay = fDist/(3.0 * log(fDist) + 2.0);
|
|
|
|
int object_filter = OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE;
|
|
float blast_radius = 6.0;
|
|
|
|
// Create moving bead visual
|
|
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, bead, target);
|
|
|
|
// Play area blast
|
|
DelayCommand(fDelay, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, blast, target));
|
|
DelayCommand(fDelay, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, shake, target));
|
|
|
|
// Find who gets affected
|
|
object target_object = GetFirstObjectInShape(SHAPE_SPHERE, blast_radius, target, TRUE, object_filter);
|
|
|
|
while(target_object != OBJECT_INVALID) {
|
|
|
|
if(!GetIsReactionTypeFriendly(target_object, self)) {
|
|
// Damage them
|
|
DelayCommand(fDelay + 0.5, ApplyEffectToObject(DURATION_TYPE_INSTANT, damage, target_object));
|
|
DelayCommand(fDelay + 0.5, ApplyEffectToObject(DURATION_TYPE_INSTANT, impact, target_object));
|
|
|
|
// Creatures only
|
|
if(GetObjectType(target_object) == OBJECT_TYPE_CREATURE) {
|
|
|
|
// Blast them away from impact point
|
|
location landing_point = wi_calculate_blast(GetLocation(target_object), target, 7.0, 6.5);
|
|
DelayCommand(fDelay + 0.6, AssignCommand(target_object, wi_bounce_creature(landing_point)));
|
|
|
|
// Give them a reflex save and make sure they are not immune to paralysis
|
|
if(ReflexSave(target_object, 16) == 0 && GetIsImmune(target_object,IMMUNITY_TYPE_PARALYSIS) == 0) {
|
|
|
|
// Trap them in a force sphere
|
|
float duration = IntToFloat(d6(3)) * 10.0;
|
|
DelayCommand(fDelay + 0.9, ApplyEffectToObject(DURATION_TYPE_INSTANT, strike, target_object));
|
|
DelayCommand(fDelay + 1.0, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, field, target_object, duration));
|
|
DelayCommand(fDelay + 1.0, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, hold, target_object, duration));
|
|
DelayCommand(fDelay + 1.0, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, immune_blunt, target_object, duration));
|
|
DelayCommand(fDelay + 1.0, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, immune_pierce, target_object, duration));
|
|
DelayCommand(fDelay + 1.0, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, immune_slash, target_object, duration));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get next object
|
|
target_object = GetNextObjectInShape(SHAPE_SPHERE, blast_radius, target, TRUE, object_filter);
|
|
}
|
|
|
|
|
|
}
|
|
|