Author Sticky: Post Working Scripts Here
Solias Posted: Saturday, 29 June 11:13PM
NOTE: This is an update to my earlier force field script, it now works for force walls and cages in addition to
bouncers. Mods, please delete my earlier post on page 11 of this thread. The main change is that it fixed a bug that allowed a player to walk right through the field if it was used in a force wall.

Name: Force Field v2

Function: This script creates an impassable wall of force that will knock the player back if they get too close. It can be used to repulsion fields, force walls, and other similar effects.

Notes: To use this script create a waypoint with the tag "force_bouncer", you may have as many bouncers as you
wish, the closest one to the player will be used. Place the bouncer in the center of the force field and draw a trigger around it. Place the script in the trigger's onEnter event. If you are using a non circular field, such as for a force wall you will want to place multiple bouncers inside the field to ensure the player bounces away properly. Be careful when placing multiple seperate force fields near each other as the may interfear with each other. You will probably want to use a placeable such as a beam of light or a portal to show the player where the field is, although invisable fields work fine too. Also, be sure you knock the player back far enough that they are outside the trigger.

Note for v2: The only way to pass through a force field now is to be jumped through it, however this means that bouncing off of a field can send you safely through another one if they are too close to each other. I'm going to look at adding this functionality for the next version so you can bounce from field to field.


NWScript:
void bounce_player(location loc) {

    ClearAllActions();

    JumpToLocation(loc);

    ActionDoCommand( SetCommandable(TRUE) );

    SetCommandable(FALSE);

}

void main() {

    // obtain the player and his nearest bouncer

    object player = GetEnteringObject();

    object bouncer = GetNearestObjectByTag( "force_bouncer", player );

    // find the location of player and bouncer

    location player_location = GetLocation(player);

    location bouncer_location = GetLocation(bouncer);

    // extract position vectors

    vector player_position = GetPositionFromLocation( player_location );

    vector bouncer_position = GetPositionFromLocation( bouncer_location );

    // extract other location components

    object player_area = GetAreaFromLocation( player_location );

    float player_ori   = GetFacingFromLocation( player_location );

    // calculate vector away from bouncer through player_point

    vector displacement = player_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( player_ori );

    }

    // normalize the displacement vector

    displacement = VectorNormalize( displacement );

    // multiply displacement by force strength

    float bounce_strength = 3.5;

    displacement = displacement * bounce_strength;

    // calculate new player position by adding displacement to current position

    player_position = displacement + player_position;

    player_location = Location( player_area, player_position, player_ori );

    // Play a neat visual effect

    effect bounce_flash = EffectVisualEffect( VFX_IMP_SUNSTRIKE );

    ApplyEffectAtLocation( DURATION_TYPE_INSTANT, bounce_flash, bouncer_location);

    // Jump the player there

    AssignCommand(player, bounce_player(player_location));

    

    // Apply a knockdown effect

    //effect knock_down = EffectKnockdown();

    //ApplyEffectToObject( DURATION_TYPE_TEMPORARY, knock_down, player, 3.0);

    //AssignCommand(player, ApplyEffectToObject( DURATION_TYPE_TEMPORARY, knock_down, player, 3.0));

}



5. Implementation Notes:
v1
If the player is right on top of the bouncer when the script fires they could possibly be the same, therefore I check the magnitude of the displacement vector before I use it. If the magnitude is zero I simply knock them backwards based on their facing.

This plays a visual effect when they are knocked back, feel free to remove or change the effect to suit your purposes.

If you want to use different bounce strength values for different bouncers or change the bounce strength in a script uncomment the line that checks for a local float on the bouncer.

I wanted to knock the player down as part of the effect, but knockdown seems to crash my client. Poly mentioned the same problem in another thread, but until I know what is causing it I'll have to leave knockdown out. The effect is still pretty cool.

v2
Making the force walls entirely impassable was a real challenge. The problem was that if a player clicks on the screen it clears their action queue. If they have not yet jumped to the bounce point the action will be cancled, since they are still inside the trigger it won't fire again and they can walk through. This made it very easy to walk right through the wall by rapidly clicking. My solution was to disable player control using SetCommandable() after filling their queue. Unfortunatly a bug with AssignCommand() prevented this from working and it took several hours to hit on something that worked. There are two issues with AssignCommand(), the first is probably not a bug and is related to timing. The AssignCommand() seems to be delayed until after the current script has executed, this makes sense. What doesn't make sense is that if you set commandable to false after you have assigned a command, the assign function will not work. Instead you must order the player to use setcommandable on himself. The second problem with assign I believe is a bug, although possibly related to timing as well. If you have multiple AssignCommand() calls, they may not all be executed. Sometimes they will be, but it is not reliable. Putting all of the commands into a function and assigning that function with a single assign call seems to be a good work around.

If anyone finds a way to walk through one of these fields (as a player without jumping) please let me know.

-Solias