Problème avec mon script de création d'un objet sur un point aléatoire

Répondre
Partager Rechercher
Yop,

Bon, plusieurs jours que je me débats avec un script que je n'arrive pas à faire fonctionner. Il utilise 2 includes :

Code:
/*
"location_valid"

PLZ Read Genjis txt header just below!!! You still need null_human.

I needed a location checker to random place a lift from a airship, most of
the script i found didn't work as desired, placing the lift in holes/cliffs/...
and on some tilesets it didn't work at all, sometimes it the placeable was
placed on the edge of a tile (to water), and the placeables angle was facing the
water preventing the PC from using it anyway...

I modified Genji's GetIsLocationValid() script so that it returns FALSE if
nwn moves the "null_humal", checking X/Z coordinates, ignoring Z.

Lastly, moving a PC to a location below/above floorlevel of a tileset,
would result in nwn fixing its height...
this is not so for placeables (planted in ground/hanging in air).
Now, when this script returns a TRUE, a locallocation is saved on the object
running this script, which should logically be the one who called the function
from "opendoor", this locallocation is the ValidLocation with a fixed Z to be
used to create placeables at that location.
"open door" can access it via
GetLocalLocation(OBJECT_SELF,"Landing_Height");
the localvar can then be deleted to keep ur module clean.

If you are only moveing a PC/NPC around then edit out all locallocation parts
in this script, its only there for random placeables to spawn at floor level.

DONT use this in a (posible) infinite while loop!:
"while(GetIsLocationValid()){}"
i got it to work fine by looping it 5-10 times. See how i did it in 'dooropen'
script.

ma'drynn    27/1/2005
ck_madrynn@Yahoo.co.uk
*/



//ORIGINAL BY GENJI
/*
Make an npc tagged and resrefed "null_human". remove all his scripts and everything,
and set his appearance to null_human. Put him in the palette.
This function is a KLUDGE to find if a location is valid or not. Will return whether
a given location can have an object created there or not, i.e. it will determine if
a 1 meter sphere around that location is free of creatures, placeables, doors, and
tileset objects.
Caveat: the real problem with this is that if everything else checks out, when I go
to see if the tileset is the blocking entity, I create an npc there to see if he
get's relocated by the engine. This will tell you if the location is over a pit, or
in a tree, or in a cliff, etc, but it really isn't practical in a loop construct.
I use this in testing mostly.

Genji
Written for 1.27
*/

// Genji 1-7-3 KLUDGE for location validation.
// will return if the location is valid or not.
// valid is defined as an available OPEN space 1 meter (NOTE modified to 0.8)
// in diameter centered on the location loc passed in.
// if any creature, placeable, door, or tileset part occupies this space,
// it will return FALSE.
// Used primarily with CreateObject calls to see that the location will be available.
// issues? Genji@thegenji.com

int GetIsLocationValid(location loc);

int GetIsLocationValid(location loc)
{
        object blocker;
//NOT SURE Y THIS IS HERE, IS YOU KNOW BETTER UNCOMMENT.
//        float angle = VectorToAngle(GetPositionFromLocation(loc));
// Is the location on a valid part of area
//        if (angle > 90.0 || angle < 0.0)
//            return FALSE;

// Any placeable/npc/... at the spot?
        if ((blocker = GetFirstObjectInShape(SHAPE_SPHERE,0.3,loc,FALSE,OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE)) != OBJECT_INVALID)
            return FALSE;

//from here i modified the script --ma'drynn
        else
        {

//convert entered location to vector
            vector vDest2,vDest1 = GetPositionFromLocation(loc);

// create a npc at entered location
            object marker = CreateObject(OBJECT_TYPE_CREATURE,"null_human",loc);

// get the npc's location, see if moved
            vDest2 = GetPosition(marker);

// save the npc location to localvar
            SetLocalLocation(OBJECT_SELF,"Landing_Height",GetLocation(marker));

// neglect any changes in the height
            vDest1.z = 0.0;
            vDest2.z = 0.0;

// remove the npc
            DestroyObject(marker,1.0);

// the vector magnitute should be 0.0 for best results
            if (pow(VectorMagnitude(vDest1) - VectorMagnitude(vDest2),2.0) > 0.0)
            {
                DeleteLocalLocation(OBJECT_SELF,"Landing_Height");
                return FALSE;
            }
            return TRUE;
        }
}
----------

Code:
location GetRandomLocation(int iMinDistance, int iMaxDistance)
  //CREATED BY:     CCC_MADNESS
  //DATE:           1/23/2003
  //FUNCTION INFO:  THIS FUNCTION RETURNS A RANDOM LOCATION SOMEWHERE BETWEEN THE MAX AND MIN
  //            DISTANCES SPECIFIED.
  //USE:        location lRandomLoc = GetRandomLocation(iMin, iMax);

{
    //Set Variables
    int iMeters = iMaxDistance;
    object oArea = GetArea(OBJECT_SELF);
    vector vMyPosition = GetPosition(OBJECT_SELF);

    //Generate X Coordinate
    iMeters = Random(iMeters*2) - iMeters;
    //Ensure that the X Coordinate is the correct distance away from the object
    if ((iMeters > (iMinDistance * -1)) && (iMeters < 0)) {
        iMeters = iMeters - iMinDistance;
    }
    if ((iMeters < (iMinDistance)) && (iMeters > 0))  {
        iMeters = iMeters + iMinDistance;
    }
    float fX = IntToFloat(iMeters) + vMyPosition.x;

    //Generate Y Coordinate
    iMeters = iMaxDistance;
    iMeters = Random(iMeters*2) - iMeters;
    //Ensure that the Y Coordinate is the correct distance away from the object
    if ((iMeters > (iMinDistance * -1)) && (iMeters < 0)) {
        iMeters = iMeters - iMinDistance;
    }
    if ((iMeters < (iMinDistance)) && (iMeters > 0))  {
        iMeters = iMeters + iMinDistance;
    }
    float fY = IntToFloat(iMeters) + vMyPosition.y;

    //Copy Z Coordinate
    float fZ =vMyPosition.z;

    //Generate New Vector and Facing
    vector vPosition = Vector(fX, fY, fZ);
    float fFacing =GetFacingFromLocation(GetLocation(OBJECT_SELF));

    //Generate New Location
    location lRandomLocation = Location(oArea, vPosition, fFacing);
    return lRandomLocation;
}
J'ai évidemment plusieurs fois vérifiées, j'ai bien un npc null_human répondant à toutes les spécifications (j'ai vérifié le resref, celui de l'objet que je veux placer aussi… J'ai vérifié tous ces détails là).

Voici mon script, que je place dans le OnEnter d'une zone :

Code:
#include "locationvalid"
#include "aaa_test"
void main()
{
    int nVL = FALSE;
    int nTh = 0;
    location lExit;
    while((nVL == FALSE) && (nTh < 30))
    {
        lExit = GetRandomLocation(1,4);   //our random location
        nVL = GetIsLocationValid(lExit);                //test it
        nTh++;                                          //add to counter
    }

//Is the location valid?
    if(nVL == TRUE)
    {
//Get the height-corrected location
        lExit = GetLocalLocation(OBJECT_SELF,"Landing_Height");
        object oExit = CreateObject(OBJECT_TYPE_PLACEABLE,"sentierdubois",lExit,FALSE);
        DeleteLocalLocation(OBJECT_SELF,"Landing_Height");
    }
}
… Mon problème, c'est que… Ça fonctionne pas. C'est sans doute un problème totalement évident pour quelqu'un sachant scripter convenablement, mais pour moi qui fais surtout du bricolage, ça dépasse mes capacités. J'ai testé plein de trucs, et le meilleur résultat que j'ai obtenu, c'est de faire planter le serveur. Actuellement, c'est ce qu'il se passe lorsque j'arrive dans la zone.

Pliz èlp.
Je vois que tu créés un plaçable dans le OnEnter. Une chose à savoir : le OnEnter est exécuté chaque fois qu'un nouvel objet (joueur, item, plaçable, PNJ, ...) entre dans la zone.

Donc si tu génères un objet dans le OnEnter sans vérifier qu'il est déjà présent, cela va engendrer une exécution infinie du script jusqu'au plantage du module.

J'ai bien l'impression que c'est ce qui se passe.

Dernière modification par Holgadard ; 08/10/2012 à 19h18.
Alors juste pour information et pour la postérité, il semblerait que mon système ne fonctionne tout simplement pas sur le OnEnter de la zone, quoiqu'il arrive. J'ai donc trouvé une solution alternative en version un déclencheur placé autour du point d'arrivée du joueur, qui traverse donc le déclencheur au moindre mouvement, et le script se trouve sur le OnEnter du déclencheur.
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés