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() {
object player = GetEnteringObject();
object bouncer = GetNearestObjectByTag( "force_bouncer", player );
location player_location = GetLocation(player);
location bouncer_location = GetLocation(bouncer);
vector player_position = GetPositionFromLocation( player_location );
vector bouncer_position = GetPositionFromLocation( bouncer_location );
object player_area = GetAreaFromLocation( player_location );
float player_ori = GetFacingFromLocation( player_location );
vector displacement = player_position - bouncer_position;
if( VectorMagnitude( displacement ) <= 0.0 ) {
displacement = -1.0 * AngleToVector( player_ori );
}
displacement = VectorNormalize( displacement );
float bounce_strength = 3.5;
displacement = displacement * bounce_strength;
player_position = displacement + player_position;
player_location = Location( player_area, player_position, player_ori );
effect bounce_flash = EffectVisualEffect( VFX_IMP_SUNSTRIKE );
ApplyEffectAtLocation( DURATION_TYPE_INSTANT, bounce_flash, bouncer_location);
AssignCommand(player, bounce_player(player_location));
}
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
|