le spawn de pnj

Répondre
Partager Rechercher
Je sais que l'on peut faire apparaitre les pnj par "spawn" plutôt que de les placer dans une zones mais je ne sais pas du tout comment il faut s'y prendre ... est-ce que quelqu'un pourrait éclairer ma lanterne s'il vous plait ? (en m'expliquant pas à pas par exemple )

Merci d'avance.
Ce se fait en plaçant des points de spawn sur la carte et ensuite par script.

Voilà un exemple tiré de ma campagne qui spawn un ennemi et son escorte :

/
Code PHP:

spawn Selim Sinan and his escort

void main
()
{
    
CreateObject(OBJECT_TYPE_CREATURE"selim"GetLocation(GetWaypointByTag("spawn_selim")));
    
    
int n =0;
    
object oEscort GetObjectByTag("spawn_escort");
    
    while (
GetIsObjectValid(oEscort))
    {
        
CreateObject(OBJECT_TYPE_CREATURE"escort_sinan"GetLocation(oEscort));
        
n++;
        
oEscort GetObjectByTag("spawn_escort"n);
    }

Dans le CreateObject on indique le "template" ou resref de la créature à créer. Elle doit doit être définie dans un blueprint. Toujours avoir un tag et un resref identiques, ça évite de se prendre la tête en fonction des fonctions utilisées.

Le script génère le PNJ Selim à l'emplacement défini par le point de spawn "spawn_selim" et autant de soldat d'escorte qu'il y a de points de spawn taggés "spawn_escort".

Du coup pour augmenter ou diminuer l'escorte, il suffit d'ajouter ou d'enlever des points de spawn, pratique non?

NB : pour les compagnons il faut utiliser SpawnRosterMember().

Un point de spawn est un Waypoint, pour ma part j'utilise un des ceux définis tels que spawn_khelgar puis le change tag et resref. Ensuite je le nouveau autant que nécessaire.
Ok, merci, ça devrait être assez simple à faire.

Maintenant, ce script tu le mets ou ? Dans le chargement de la zone lors de l'entrée je suppose ?

Autre question, est-ce que les persos conserve les modifs lorsque l'on change de module et que l'on revient (via un load module bien sur) (comme les quêtes, les monstres morts etc) ?
Tout dépend du scénario, tu peux mettre le script dans l'entrée de zone, dans une conversation, après un évènement particulier (le PJ a trouvé un objet)...

Celui là est dans une conversation, le PJ et ses copains ont enfin trouvé la personne à accompagner, mais ont été suivis sans le savoir... Et ça se passe une bonne heure de gameplay après l'entrée dans la zone...

Oui toutes les modifications sont conservées lors d'un LoadModule.
Tu peux aussi les faire apparaître comme des "encounters" / rencontres.

Au lieu que ce soit une rencontre hostile type monstres tu places tes PNJs neutres ou amicaux dans la liste.

C'est très simple de cette manière, et plus souple à gérer peut-être ?

Personnellement, je place le trigger de rencontre sur l'ensemble de la zone, au contraire de ce qu'il faut faire pour un encounter hostile, pour lequel il est important que tous les membres d'un groupe soient présents sur la zone afin que les calculs de difficulté s'effectuent convenablement.
Bah, n'écoutes pas ce vieux barbu (Coucou Laban )

Il y a un moteur de spawn super génial la, prêt à l'emploi avec toutes les explications ici :
https://forums.jeuxonline.info/showthread.php?t=930375
Le moteur gère l'initialisation de la zone (Les PNJ que tu veux placer dès qu'un joueur y pénètre), les spawns récurent, la vitesse de respawn, la population de PNJ maxi de la zone et le nettoyage en différé lorsque le dernier joueur s'en va en abondant ses paquets de chips vide sur le sol.

Il est même en download là avec 2 zones en exemple :
http://beckrunes.info/clic.php?url=h..._nettoyeur.rar
Je remonte ce topic car il me faudrait un script de spawn particulier.

Je voudrais que la mort d'un monstre dans une zone A déclenche le spawn d'un PNJ dans une zone B (même module, mais un script avec possibilité sur un autre module pourrait être utile aussi). J'avais déja un quelque chose qui permettait ça mais uniquement dans la même zone ce qui ne correspondait pas à ce que je voulais.
Salut Lyendhal !

Dans le OnDeath du mobs, tu rajoutes un petit bout de code style :

Code PHP:

object oWP GetObjectByTag("le tag d'un wp");
location lLoc GetLocation (oWP);

CreateObject(OBJECT_TYPE_CREATURE"resref",lLocFALSE); 
Par contre, aucune idée en ce qui concerne des modules différents.

Je pense que ça devrait marcher ^^

Si ça ne marche pas, n'hésite pas à le signaler, et si question également !
Définis une variable globale pour le module, par le onDeath de la créature.

Si cette variable est sur 1 (par exemple... du coup True), alors tu spawn l'autre sur l'autre carte.

Script à mettre sur le onDeath donc :

Code:
void main()
{
      SetGlobalBool("IsMonsterDead",1);
}
https://nwn2.jeuxonline.info/articles/3957.html
Voici pour l'utilisation des variables Globales (communes à tout ton module), Locales (qui restent définies pour un objet donné), et de Campagne (stockées dans un fichier externe, qui est accessible même en changeant de module).

Condition pour le spawn du mob :
Code:
void main()
{ 
    if(GetGlobalBool("IsMonsterDead"))
      {
CreateObject(OBJECT_TYPE_CREATURE, "Chasseur de prime", GetLocation(GetWaypointByTag("spawn_PrimeHunter")));
    }
}  
(en reprenant l'exemple de Selim un peu plus haut, via Claudius33)
Pas sûr de la syntaxe, mais il n'y a pas de difficulté à celà...

Tu devrais peut être regarder cette page pour voir un peu plus les moyens à ta disposition :
https://nwn2.jeuxonline.info/articles/4333.html

A noter cependant : je viens de chercher, il est impossible de supprimer une variable globale.
Donc, tu peux sinon, pour éviter d'avoir une variable inutile qui bouffe la mémoire (il n'y a pas de petite optimisation), l'enregistrer plutôt sur l'objet joueur (marche de plus ainsi en multi), de cette manière :

Code:
void main()
{
      object oWhoIsTheChiefHere = GetLastKiller();
      SetLocalInt(oWhoIsTheChiefHere,"IsMonsterDead",1);
}
Puis, pour le onEnter de la zone :

Code:
void main()
{
   object oJoueur = GetEnteringObject();
    if(GetLocalInt(oJoueur,"IsMonsterDead"))
      {
         CreateObject(OBJECT_TYPE_CREATURE, "Chasseur de prime", GetLocation(GetWaypointByTag("spawn_PrimeHunter")));
    }
}  
Il y a cependant un problème qui n'en est peut être pas un : le GetLastKiller peut être aussi bien un lanceur de sort ennemis qui lance malencontreusement une boule de feu sur son chef, c'est lui qui aura la variable. Dès lors, le joueur peut bien entrer dans la zone B, le spawn ne se fera pas.

Donc, un peu casse-gueule.

On peut alors modifier le script onDeath ainsi :

Code:
 void main()
 {
      object oWhoIsTheChiefHere = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,1,OBJECT_SELF,1,PLAYER_CHAR_IS_PC,1);
       SetLocalInt(oWhoIsTheChiefHere,"IsMonsterDead",1);
 }
Alors, cependant, il y a le fait, non négligeable, que je n'ai jamais utilisée cette fonction. De fait, je ne sais pas exactement la syntaxe. Enfin, le principe est là, à toi les bugs et les tests en tout genre.

Cependant, si quelqu'un sait la syntaxe exacte de cette fonction, je serais assez curieux de voir comment l'utiliser dans ce cas de figure...
Dans le même module, ça marche sans problème. En fait tout le module est accessible pas seulement la zone où se trouve le PJ. C'est pourquoi si on place deux créatures ennemies dans une autre zone elles vont commencer à se taper dessus dès le chargement du module et pas seulement quand le PJ y arrive.

Par contre entre deux modules ce n'est pas possible, il faut passer comme le dit Mymm par une variable globale ou par le journal de quête. Variable à tester dans le onClientEnter de la zone concernée du deuxième module ou dans le onEnterClient du module.

Les variables globales ne bouffent quasiment rien en mémoire et sont stockées dans un fichier XML dans le dossier de sauvegarde (elles sont donc faciles à vérifier). A titre personnel je préfère les variable int car elles sont directement accessibles par les scripts standards ga_global_int et gc_global_int et ne sont pas limitées à 0 ou 1.

L'exemple (extrait de script d'une célèbre campagne ) ci-dessous montre un spawn de compagnon (Joachim) quand le joueur l'a trouvé... dans un autre module :

Code PHP:

#include "ginc_companion"

void SpawnAtCamp(string sRosterName)
{
    
string   sSpawn "spawn_" sRosterName;
    
location lSpawn GetLocation(GetObjectByTag(sSpawn));
    
object oNPC GetObjectFromRosterName(sRosterName);
    
    if (
GetIsObjectValid(oNPC)) AssignCommand(oNPCActionJumpToLocation(lSpawn));
    else 
SpawnRosterMember(sRosterNamelSpawn);
}

void main()
{
    
object oPC GetFirstPC();
     ..........
     ..........  
    
SpawnAtCamp("nathan");    //in all cases
    
if (GetGlobalInt("Found_Joachim")==1SpawnAtCamp("joachim");

Et un autre avec un CreateObject conditionné par le journal (les créatures provenant d'un premier module ne sont pas recrées si elles existent déjà dans le deuxième module, sinon bonjour les clones ):

Code PHP:

    if ((GetJournalEntry("q_roxana"oPC)==40)&&(!GetIsObjectValid(GetObjectByTag("roxana"))))
    {
        
CreateObject(OBJECT_TYPE_CREATURE"roxana"GetLocation(GetWaypointByTag("spawn_roxana")));
        
CreateObject(OBJECT_TYPE_CREATURE"alexandros"GetLocation(GetWaypointByTag("spawn_alexandros")));
    } 
Citation :
C'est pourquoi si on place deux créatures ennemies dans une autre zone elles vont commencer à se taper dessus dès le chargement du module et pas seulement quand le PJ y arrive.
Tiens je pensais que si aucun PJ n'etait présent dans la zone, le fait de cocher "Désactiver IA blabla chez pu quoi" dans les propriétés des créatures les rendaient inertes. C'est donc faux ?
A condition de les mettre en script dissimulé, je crois. Mais la plupart du temps on y pense pas... et on se demande où sont passés ces foutus civils et leur animaux..

Je n'ai pas essayé d'utiliser IA désactivée et script dissimulé (je n'arrive pas pas à voir quelles sont les fonctions qui permettent de les gérer ), et je trouve que c'est aussi simple de "spawner" les créatures ou de les changer de faction quand le PJ arrive...
Répondre

Connectés sur ce fil

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