RoT2_PRC8/_module/nss/ffx_bounce_inc.nss
Jaysyn904 499aba4eb3 Initial upload
Initial upload
2023-09-25 18:13:22 -04:00

357 lines
14 KiB
Plaintext

//////
// Force Effects: Bounce
// Created by Solias (sorcerer@wnwn.net)
// http://www.wnwn.net/
//
////
// ffx_bounce_inc - Force Effects: Bounce Include File
//
// functions used by bounce force scripts
//
//-----------< Function List >-------------------------------------//
// add an area to the module's recompute list, call ffx_recompute all to recomupte static lighting in
// all areas in the list.
void ffx_set_area_need_recompute(object area);
// Recompute static lighting in all areas in the module's recompute list
void ffx_recompute_all();
// Command a creature to bounce to target
// ffx_bounce() assigns this to a creatures with AssignCommand()
// It clears their action queue, orders them to jump, locks the queue,
// and unlocks it after the jump.
void ffx_bounce_creature(location target);
// Create a placable with tag: visual_object at the location of every
// object with the tag: marker_object in the module. This is used to
// create visual effects placables via a script. Specificly it is used
// by the force cage and force wall scripts. The recompute param determines
// if RecomputeStaticLighting() is called after the objects are created
// group_tag is the force group to which the new objects should belong.
void ffx_create_visual_objects(string object_template, string marker_tag, string group_tag, int recompute = TRUE);
// Destroy all placable objects with object_tag. Then recompute lighting.
// if group_tag is "null" objects from all groups are destroyed, otherwise
// only objects belonging to this force group are affected
void ffx_destroy_visual_objects(string object_tag, string group_tag, int recompute = TRUE);
// Activate a force group with the give group tag. It will create
// visual objects at any marker with the giver group id
void ffx_activate_forcegroup(string group_tag, string object_template = "ffx_", string marker_tag = "ffx_mark_");
// Deactivate a force group.
void ffx_deactivate_forcegroup(string group_tag, string object_tag = "ffx_");
// Apply the bounce effect to creature, deflecting them bounce_strength distance.
// It will also play a visual effect specified by visual_effect, this should be a
// VFX_* constant, use VFX_NONE if you don't want an effect. do_knock_down will apply
// a 3 second knock down effect to the creature after the bounce, at the moment knock
// down seems to crash NWN so this has been added for future compatability only.
void ffx_bounce(object creature, float bounce_strength=2.5, int visual_effect=VFX_IMP_SUNSTRIKE, int do_knock_down=FALSE);
// Apply the bounce effect to creature, deflecting them bounce_strength distance.
// This is similar to ffx_bounce, but the creature will always bounce towares the
// nearest waypoint with the tag specified in target_tag.
// It will also play a visual effect specified by visual_effect, this should be a
// VFX_* constant, use VFX_NONE if you don't want an effect. do_knock_down will apply
// a 3 second knock down effect to the creature after the bounce, at the moment knock
// down seems to crash NWN so this has been added for future compatability only.
void ffx_bounce_towards_point(object creature, string target_tag, float bounce_strength=2.5, int visual_effect=VFX_IMP_SUNSTRIKE, int do_knock_down=FALSE);
//-----------< Function Implementation >----- ---------------------//
// add an area to the module's recompute list, call ffx_recompute all to recomupte static lighting in
// all areas in the list.
void ffx_set_area_need_recompute(object area) {
// get length of list
int list_length = GetLocalInt(GetModule(), "ffx_rsl_list_length");
int i;
// verify area is not in list already
for(i = 0; i < list_length; i++) {
object list_area = GetLocalObject(GetModule(), "ffx_rsl_list_" + IntToString(i));
if(GetTag(list_area) == GetTag(area)) return;
}
// add area to list
SetLocalObject(GetModule(), "ffx_rsl_list_" + IntToString(list_length), area);
SetLocalInt(GetModule(), "ffx_rsl_list_length", list_length + 1);
}
// Recompute static lighting in all areas in the module's recompute list
void ffx_recompute_all() {
// get length of list
int list_length = GetLocalInt(GetModule(), "ffx_rsl_list_length");
int i;
// recompute lighting in each area in the list and then remove it from the list
for(i = 0; i < list_length; i++) {
object area = GetLocalObject(GetModule(), "ffx_rsl_list_" + IntToString(i));
RecomputeStaticLighting(area);
DeleteLocalObject(GetModule(), "ffx_rsl_list_" + IntToString(i));
}
// reset list length to 0
SetLocalInt(GetModule(), "ffx_rsl_list_length", 0);
}
// actions to be taken by the creature on a bounce
void ffx_bounce_creature(location loc) {
ClearAllActions();
JumpToLocation(loc);
ActionDoCommand(SetCommandable(TRUE));
SetCommandable(FALSE);
}
// create placable objects at markers
void ffx_create_visual_objects(string object_template, string marker_tag, string group_tag, int recompute = TRUE) {
int i = 0;
marker_tag = marker_tag + group_tag;
object force_bar = GetObjectByTag(marker_tag, i++); // get each marker object
object new_area = GetArea(force_bar);
object old_area = new_area;
// create all of the objects
while(GetIsObjectValid(force_bar)) {
// create the object
object new_object = CreateObject(OBJECT_TYPE_PLACEABLE, object_template, GetLocation(force_bar));
SetLocalString(new_object, "ffx_force_group", group_tag);
// recompute lighting if the area has changed
new_area = GetArea(force_bar);
if(new_area != old_area && recompute) ffx_set_area_need_recompute(old_area);
old_area = new_area;
// get the next marker object
force_bar = GetObjectByTag(marker_tag, i++);
}
if(recompute) ffx_set_area_need_recompute(new_area);
}
// destroy placable objects
void ffx_destroy_visual_objects(string object_tag, string group_tag, int recompute = TRUE) {
int i = 0;
object force_bar = GetObjectByTag(object_tag, i++); // get each object
// get areas with object so we can recompute lighting
object new_area = GetArea(force_bar);
object old_area = new_area;
int affect_all_groups = (group_tag == "NULL");
while(GetIsObjectValid(force_bar)) {
// destroy the object
if(affect_all_groups) {
DestroyObject(force_bar);
new_area = GetArea(force_bar);
}
else if(GetLocalString(force_bar, "ffx_force_group") == group_tag) {
DestroyObject(force_bar);
new_area = GetArea(force_bar);
}
// recompute lighting if the area has changed
if(new_area != old_area && recompute) ffx_set_area_need_recompute(old_area);
old_area = new_area;
// get the next object
force_bar = GetObjectByTag(object_tag, i++);
}
if(recompute) ffx_set_area_need_recompute(new_area);
}
// activate the force cage
void ffx_activate_forcegroup(string group_tag, string object_template = "ffx_", string marker_tag = "ffx_mark_") {
// activate the force field
SetLocalInt(GetModule(), "ffx_group_active_" + group_tag, 1);
// create the bars
ffx_create_visual_objects(object_template + "bar_yellow", marker_tag + "by_", group_tag);
ffx_create_visual_objects(object_template + "bar_blue", marker_tag + "bb_", group_tag);
ffx_create_visual_objects(object_template + "bar_green", marker_tag + "bg_", group_tag);
ffx_create_visual_objects(object_template + "bar_red", marker_tag + "br_", group_tag);
ffx_create_visual_objects(object_template + "bar_white", marker_tag + "bw_", group_tag);
ffx_create_visual_objects(object_template + "bar_purple", marker_tag + "bp_", group_tag);
ffx_create_visual_objects(object_template + "bar_orange", marker_tag + "bo_", group_tag);
ffx_create_visual_objects(object_template + "spark_yellow", marker_tag + "sy_", group_tag);
ffx_create_visual_objects(object_template + "spark_blue", marker_tag + "sb_", group_tag);
ffx_create_visual_objects(object_template + "spark_green", marker_tag + "sg_", group_tag);
ffx_create_visual_objects(object_template + "spark_red", marker_tag + "sr_", group_tag);
ffx_create_visual_objects(object_template + "spark_white", marker_tag + "sw_", group_tag);
ffx_create_visual_objects(object_template + "spark_purple", marker_tag + "sp_", group_tag);
ffx_create_visual_objects(object_template + "spark_orange", marker_tag + "so_", group_tag);
ffx_recompute_all();
}
// destroy the force cage
void ffx_deactivate_forcegroup(string group_tag, string object_tag = "ffx_") {
// deactivate the force field
SetLocalInt(GetModule(), "ffx_group_active_" + group_tag, 0);
// destroy the bars
ffx_destroy_visual_objects(object_tag + "bar_yellow", group_tag);
ffx_destroy_visual_objects(object_tag + "bar_blue", group_tag);
ffx_destroy_visual_objects(object_tag + "bar_green", group_tag);
ffx_destroy_visual_objects(object_tag + "bar_red", group_tag);
ffx_destroy_visual_objects(object_tag + "bar_white", group_tag);
ffx_destroy_visual_objects(object_tag + "bar_orange", group_tag);
ffx_destroy_visual_objects(object_tag + "bar_purple", group_tag);
ffx_destroy_visual_objects(object_tag + "spark_yellow", group_tag);
ffx_destroy_visual_objects(object_tag + "spark_blue", group_tag);
ffx_destroy_visual_objects(object_tag + "spark_green", group_tag);
ffx_destroy_visual_objects(object_tag + "spark_red", group_tag);
ffx_destroy_visual_objects(object_tag + "spark_white", group_tag);
ffx_destroy_visual_objects(object_tag + "spark_orange", group_tag);
ffx_destroy_visual_objects(object_tag + "spark_purple", group_tag);
ffx_recompute_all();
}
// apply the bounce effect to a creature
void ffx_bounce(object creature, float bounce_strength=2.5, int visual_effect=VFX_IMP_SUNSTRIKE, int do_knock_down=FALSE) {
// obtain the player and his nearest bouncer
object bouncer = GetNearestObjectByTag("ffx_bouncer", creature);
// find the location of player and bouncer
location creature_location = GetLocation(creature);
location bouncer_location = GetLocation(bouncer);
// extract position vectors
vector creature_position = GetPositionFromLocation(creature_location);
vector bouncer_position = GetPositionFromLocation(bouncer_location);
// extract other location components
object creature_area = GetAreaFromLocation(creature_location);
float creature_ori = GetFacingFromLocation(creature_location);
// calculate vector away from bouncer through player_point
vector displacement = creature_position - bouncer_position;
// ensure that the magnitude of the vector is greater than 0
// otherwise use the inverse of the player's orientation as the vector
if(VectorMagnitude(displacement) <= 0.0) {
displacement = -1.0 * AngleToVector(creature_ori);
}
// normalize the displacement vector
displacement = VectorNormalize(displacement);
// multiply displacement by force strength
displacement = displacement * bounce_strength;
// calculate new player position by adding displacement to current position
creature_position = displacement + creature_position;
creature_location = Location(creature_area, creature_position, creature_ori);
// Play a neat visual effect
if(visual_effect != VFX_NONE) {
effect bounce_flash = EffectVisualEffect(visual_effect);
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, bounce_flash, bouncer_location);
}
// Jump the player there
AssignCommand(creature, ffx_bounce_creature(creature_location));
// Apply a knockdown effect
if(do_knock_down) {
effect knock_down = EffectKnockdown();
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, knock_down, creature, 3.0);
}
}
// apply the bounce effect to a creature, in the direction of nearest waypoint with target_tag
void ffx_bounce_towards_point(object creature, string target_tag, float bounce_strength=2.5, int visual_effect=VFX_IMP_SUNSTRIKE, int do_knock_down=FALSE) {
// obtain the player and his nearest bouncer
object bouncer = GetNearestObjectByTag("ffx_bouncer", creature);
object remote_target = GetNearestObjectByTag(target_tag, creature);
// find the location of player and bouncer
location creature_location = GetLocation(creature);
location bouncer_location = GetLocation(bouncer);
location target_location = GetLocation(remote_target);
// extract position vectors
vector creature_position = GetPositionFromLocation(creature_location);
vector bouncer_position = GetPositionFromLocation(bouncer_location);
vector target_position = GetPositionFromLocation(target_location);
// extract other location components
object creature_area = GetAreaFromLocation(creature_location);
float creature_ori = GetFacingFromLocation(creature_location);
// calculate vector away from bouncer through player_point
vector displacement = target_position - bouncer_position;
// ensure that the magnitude of the vector is greater than 0
// otherwise use the inverse of the player's orientation as the vector
if(VectorMagnitude(displacement) <= 0.0) {
displacement = -1.0 * AngleToVector(creature_ori);
}
// normalize the displacement vector
displacement = VectorNormalize(displacement);
// multiply displacement by force strength
displacement = displacement * bounce_strength;
// calculate new player position by adding displacement to current position
creature_position = displacement + creature_position;
creature_location = Location(creature_area, creature_position, creature_ori);
// Play a neat visual effect
if(visual_effect != VFX_NONE) {
effect bounce_flash = EffectVisualEffect(visual_effect);
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, bounce_flash, bouncer_location);
}
// Jump the player there
AssignCommand(creature, ffx_bounce_creature(creature_location));
// Apply a knockdown effect
if(do_knock_down) {
effect knock_down = EffectKnockdown();
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, knock_down, creature, 3.0);
}
}