Gaming
 

Random location include file

From NWNWiki


Contents

[edit] Random location include file

[edit] What it does

It generates a random location that can be used for e.g. creature, effect creation in different shapes. Base Forms : Full circle, ring, empty circle, Full Box, hollow box, empty box, Cone, ConeSegment, Star(one-way line, two-way line).


[edit] Notes

The Base Forms can be interpreted as Forms of [2D, HEMISPHERE_PLUS, 3D_PLUS] e.g. Circle, Half Sphere , Sphere within visible range OR proportional to distance [2D, HEMISPHERE, 3D] e.g. square, negative of an upside-down pyramid, square, negative of an upside-down pyramid + same form mirrored down.

Functions
RndLoc(x) := Creates One random location in specified form.
RndSign() := Generates an 1/-1.
RndFloat(x) := Generates an random float between 0 and X.
RndAngle(x) := Generates an random valid angle form X between 0 and 360
degrees.
RndUnitVector() := Generates an random UNIT vector.
RndZCoor(x) := Generates an random z-value for use in HEMISPHERE (_PLUS)
and 3D(_PLUS)
<pre>

== F.A.Q. ==
Q: Why do I need 3D locations if everything created is automatically stuck to the ground?
A: Basicly you only need 3D locations to produce special effects e.g. a floating sphere spiting fireballs in arcs in a berserk fit in all directions not only at the floor or so...

Q: Why is there a proportional to distance mode.
A: So can e.g. shot an arrow upwards at angle dependant on Target. 

Q: Why is the normal 3D height limited?
A: So you always can admire your own creations  

Q: Can you give me an example for what I can use it:
A: Sure, for realistic catapult projectiles for example. 
Use the Coneshape
Set angle (Bearing)
Set the minimal range and maximal range
Finally set the Anglewidth of the Cone

Fire a spell(effect) at location
And maybe even a projectile splash effect using the circle form.
Use e.g. a Circleshape with min. range 2 and max. range 4 to do Splash damage and if do it a few times 3d(2)
(see example script)

I gave up writing nice code due to a personal nerve problem…
Anyone writing such a dirty code should be spanked. OUCH stop that, I said should.

I wanted to make an fully Player controlled catapult as an example with different ammo e.g. tar pods, Karaturian stinking cauldrons and dead bloated cows. But I had to some TMI and sync problems and lost fun doing so.

So if anyone is interested in something like that, message me and maybe I’ll change my mind.

The example I added only shows how to use the RNDLOC()
Additionally it shows one way how to sync animations with each other and objects created by them.

== The Script ==

script(file)name: _incl_rndloc

<pre>
//::///////////////////////////////////////////////
//:: script(file)name: _incl_rndloc
//:: Type: includefile
//:://////////////////////////////////////////////
/*
  Generates random Locations v1.0
  Notes: To be refined and functions added.
*/
//:://////////////////////////////////////////////
//:: Created By: Hikade (nick: agem)
//:://////////////////////////////////////////////
// * (CONSTANTS) VARIABLES >
// NOTE: Only Vars here because i think editing the
// nwscript.nss is pointless due to the PATCH issue.
// Sorry this makes Function Declaration(s) less
// transparent, but this is the it is...
/* values form the nwscript.nss
int SHAPE_SPELLCYLINDER = 0;
int SHAPE_CONE = 1;
int SHAPE_CUBE = 2;
int SHAPE_SPELLCONE = 3;
int SHAPE_SPHERE = 4;
*/
int BASE_SHAPE_CONE = SHAPE_CONE;           // :=1
int BASE_SHAPE_BOX = SHAPE_CUBE;            // :=2
int BASE_SHAPE_CIRCLE = SHAPE_SPHERE;       // :=4
int BASE_SHAPE_STAR = SHAPE_SPELLCYLINDER;  // :=3
int DIMENSION_2D                        = 0;
int DIMENSION_HEMISPHERE                = 1;
int DIMENSION_HEMISPHERE_PLUS           = 2;
int DIMENSION_3D                        = 3;
int DIMENSION_3D_PLUS                   = 4;
// * (CONSTANTS) VARIABLES <

// * Function Declaration(s) >
// NOTE: These are also necassary to make descriptions visible

// Creates an Random Location in BASE_SHAPE_* (see Variables)
// - lTarget: Starting location from where to generate random location
// - iMaxRange : Maximal distance allowed for generated location
// - iMinRange : Minimal distance allowed for generated location
//          -> When iMinRange=0 generated location can be on startingpoint
//          -> When iMinRange=iMaxRange then generated location is always at Maximal Distance e.g. a empty circle
// - Shape : BASE_SHAPE_BOX = SHAPE_CUBE :=2 is Default (others see var BASE_SHAPE_*)
// - fAngle: Only used for certain BASE_SHAPE_*(see following)
//          -> BASE_SHAPE_CONE Sets the center angle off Cone (Half Cone)
//          -> BASE_SHAPE_STAR Sets Staring angel for first Starpoint
// - fAngle: Only used for certain BASE_SHAPE_*(see following)
//          -> BASE_SHAPE_CONE +- angel of Cone center angel
//          -> BASE_SHAPE_STAR Set value for ammount of Starpoints e.g. 5.0f = FIVE STAR
// - nDimension: Set Dimesion Type (see var DIMENSION_*)
//          -> DIMENSION_2D :normal 2D you will most commonly use e.g. full circle
//          -> DIMENSION_HEMISPHERE :Top Part of halfsphere, special: location z-value are porportional distance
//          -> DIMENSION_HEMISPHERE_PLUS : Top Part of halfsphere and z-values will always be visible
//          -> DIMENSION_3D: Full Sphere, ideal for floating things, special: location z-value are porportional distance
//          -> DIMENSION_3D_Plus : Full Sphere, ideal for floating things, and z-values will mostly be visible
// Handy special cases:
//          -> BASE_SHAPE_STAR with only 1 Starpoint is a Line with one direction.
//          -> BASE_SHAPE_STAR with 2 Starpoints is a Line with a middlepoint that has in an left/right property
location RndLoc(location lTarget,int iMaxRange,int iMinRange=0,int nShape_Type=2,float fAngle=0.0f, float fAngleWidth=90.0f,int nDimension=0);
/*
float SetFacingType(float fDirection,location lTarget,object oSource=OBJECT_SELF);
*/
void FillArea();
// Creates an Random Sign 1/-1
int RndSign();
// Creates an Random Float
float RndFloat(int nMaxFloat);
// Creates an Random Angle
float RndAngle(int iDeg=360);
// Creates an Random Unit Vector
vector RndUnitVector();
// Create an Random z-value for an vector based on DIMENSION_*
float RndZCoor(float fZCoor,int iMaxRange,int iMinRange,int nDimension=0);
// * Function Implementation >
// Creates an Random Sign 1/-1
int RndSign()
{
int iRndSign;
if(Random(2)) iRndSign = -1; else iRndSign =1;
return iRndSign;
}
// Creates an Random Float
float RndFloat(int nMaxFloat)
{
float fRandom;
int iPrefixPoint = Random(nMaxFloat);//+1;
int iSufixPoint = Random(10)+1;
return fRandom = IntToFloat(iPrefixPoint)+(IntToFloat(iSufixPoint)/10);
}
// Creates an Random Angle
float RndAngle(int iDeg=360)
{
float fAngle;
int iRndDeg = Random(iDeg)+1;
int iRndMinute = Random(10)+1;
return fAngle = IntToFloat(iRndDeg)+(IntToFloat(iRndMinute)/10);
}
// Creates an Random Unit Vector
vector RndUnitVector()
{
vector vRndUnitVector = AngleToVector(RndAngle());
return vRndUnitVector;
}
/*
float SetFacingType(float fDirection,location lTarget,object oSource=OBJECT_SELF)
{
vector vTarget = GetPositionFromLocation(lTarget);
vector vSource =GetPosition(oSource);
 vector vDirection = AngleToVector(fDurection);
float fFacing = VectorToAngle(vTarget-vSource)+ fDirection;
return fFacing;
}
*/
// Create an Random z-value for an vector based on DIMENSION_*
float RndZCoor(float fZCoor,int iMaxRange,int iMinRange,int nDimension)
{
float fRndZCoor;
switch (nDimension)
    {
     //DIMENSION_HEMISPHERE
    case 1 :
        {
        int zOffSet = Random(iMaxRange-iMinRange);
        fZCoor = fZCoor + (zOffSet + iMinRange);
        }break;
     // DIMENSION_HEMISPHERE_PLUS
    case 2 :
        {
        int zOffSet = Random(12);
        fZCoor = fZCoor + (zOffSet);
        }break;
     // DIMENSION_3D
    case 3 :
        {
        int zOffSet = Random(iMaxRange-iMinRange);
        fZCoor =fZCoor + (zOffSet + iMinRange)*RndSign();
        }break;
     //DIMENSION_3D_PLUS
    case 4 :
        {
        int zOffSet = Random(8);
        fZCoor = fZCoor + (zOffSet)*RndSign();
        }break;
    default: break;
}
return fRndZCoor=fZCoor;
}

// Creates an Random Location in BASE_SHAPE_*
location RndLoc(location lTarget,int iMaxRange,int iMinRange=0,int nShape_Type=2,
                float fAngle=0.0f, float fAngleWidth=90.0f,int nDimension=0)
{
object oTargetArea = GetAreaFromLocation(lTarget);
vector vTarget = GetPositionFromLocation(lTarget);
float fTargetfacing = GetFacingFromLocation(lTarget);
switch (nShape_Type)
{
    case 2: // BASE_SHAPE_BOX = SHAPE_CUBE :=2
    {
    if(Random(2))
        {
        int xOffSet = Random(iMaxRange-iMinRange);
        int yOffSet = Random(iMaxRange);
        // To enable Q2,Q3,Q4 positions of vector
        vTarget.x = vTarget.x + (xOffSet + iMinRange)*RndSign();
        vTarget.y = vTarget.y + (yOffSet)* RndSign();
        }
    else
        {
        int xOffSet = Random(iMaxRange);
        int yOffSet = Random(iMaxRange-iMinRange);
        // To enable Q2,Q3,Q4 positions of vector
        vTarget.x = vTarget.x + (xOffSet) *RndSign();
        vTarget.y = vTarget.y + (yOffSet + iMinRange)*RndSign();
        }
    // Adds according z-value if demanded
    vTarget.z =RndZCoor(vTarget.z,iMaxRange,iMinRange,nDimension);
    }break;
    case 4: // BASE_SHAPE_CIRCLE = SHAPE_SPHERE :=4
        {
        int iRndRange = Random((iMaxRange+1)-iMinRange);
        vector vRandomUnitVector = RndUnitVector();
        vRandomUnitVector *= IntToFloat(iRndRange+iMinRange);
        vTarget += vRandomUnitVector;
        // Adds according z-value if demanded
        vTarget.z =RndZCoor(vTarget.z,iMaxRange,iMinRange,nDimension);
        }break;
    case 1: // BASE_SHAPE_CONE = SHAPE_CONE :=1
        {
        int iRndRange = Random((iMaxRange+1)-iMinRange);
        float fRndAngle = RndAngle(FloatToInt(fAngleWidth)/2*RndSign());
        fRndAngle += fAngle;
        vector vRndVector = AngleToVector(fRndAngle);
        vRndVector *= IntToFloat(iRndRange+iMinRange);
        vTarget += vRndVector;
        // Adds according z-value if demanded
        vTarget.z =RndZCoor(vTarget.z,iMaxRange,iMinRange,nDimension);
        }break;
 /* //difference to SHAPE_CONE unknown and a CYLINDER can be made by BASE_SHAPE_CIRCLE
    case SHAPE_SPELLCONE:
    {
    }break;
*/
    case 3: // BASE_SHAPE_STAR = SHAPE_SPELLCYLINDER :=3
    {
    int iRndRange = Random((iMaxRange+1)-iMinRange);
    float fStartingAngle = fAngle;
    float fAngleStep = (360.0f/fAngleWidth);
    float fRndAngel = Random(FloatToInt(fAngleWidth)+1)*fAngleStep;
    vector vRandomVector = AngleToVector(fRndAngel)*IntToFloat(iRndRange+iMinRange);
    vTarget += vRandomVector;
    // Adds according z-value if demanded
    vTarget.z =RndZCoor(vTarget.z,iMaxRange,iMinRange,nDimension);
    }break;
default : break;
}
// return Random Location of wished type
return lTarget= Location(oTargetArea,vTarget,fTargetfacing);
}

[edit] Example script

place on a Catapult -> Event OnUsed (needs above script saved as “_incl_rndloc”)

#include "_incl_rndloc"
// Needed to sync effects with CreateObject
object DestroyObjectReturn(object oDestroy, float fDelay=0.0f);
object DestroyObjectReturn(object oDestroy, float fDelay=0.0f)
{
DestroyObject(oDestroy,fDelay);
return oDestroy;
}

void main()
{
location lSelf = GetLocation(OBJECT_SELF);
// Create Location in cut off cone
location lTarget = RndLoc(lSelf,30,15,BASE_SHAPE_CONE,DIRECTION_SOUTH,42.5f);
int i; int j = d3(2);
effect eExplode = EffectVisualEffect(VFX_FNF_FIREBALL);
effect eTar=EffectVisualEffect(VFX_DUR_PROT_GREATER_STONESKIN,FALSE);
float fDistance = GetDistanceBetweenLocations(lTarget, lSelf);
float fDelay= (GetDistanceBetweenLocations(lTarget, lSelf))/13.0f;  //Need to sync projectile with impact animation
float fDelayCountdown = 0.0f;
SetFacingPoint(GetPositionFromLocation(lTarget));
ActionCastFakeSpellAtLocation(SPELL_FIREBALL,lTarget,PROJECTILE_PATH_TYPE_BALLISTIC);

// While Loop isn't actualy needed and can be deleted
while (fDelay >= fDelayCountdown)
{
ActionWait(0.1f);
fDelayCountdown += 0.1f;
if (fDelay <= fDelayCountdown )
    {
    DelayCommand(fDelay,ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eExplode, lTarget));
    // Main impact
    DelayCommand(fDelay,
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eTar,
    DestroyObjectReturn(CreateObject(OBJECT_TYPE_PLACEABLE,"plc_stones",
    lTarget,TRUE),IntToFloat(d6(4))),12.0f));
    // Splash form Main impact
    for (i= 1;i <= j;i++)
        {
        // for explanation
        DelayCommand(fDelay,                                    // Need to sync projectile with impact
        ApplyEffectToObject(                                    // 1*> Do effect on splash objects
        DURATION_TYPE_TEMPORARY,EffectVisualEffect(261),        // Type of effect the splash objects shall do
        DestroyObjectReturn(                                    // 2*> begin Destroy objects after X.x secs
        CreateObject(OBJECT_TYPE_PLACEABLE,"plc_flamesmall",    // Create splash objects
        RndLoc(lTarget,6,2,BASE_SHAPE_CIRCLE),TRUE),            // Create splash objects location
        IntToFloat(d6(3))),                                     // 2*< end Destroy objects after X.x secs
        12.0f));                                                // 1*< Duration effect shall last on splash objects
        }
    }
}
}