[préfab] Une serveuse qui vient prendre les commandes.

Répondre
Partager Rechercher
Un tit script de serveuse pour aller un peu plus loin que les préfabs habituels.

Le fonctionnement général est le suivant :
-La serveuse s'occupe à de petites tâches dans sa taverne (par défaut : RandomWalk ^^).
-Quand un client s'assied à une table, elle vient le voir pour prendre sa commande en dialogue direct (par mot-clé).
-Elle fait le tour des clients assis qui n'ont pas encore commandé.
-Elle va chercher les boissons au bar.
-Elle revient servir les clients et leur donner ce qu'ils ont demandé.

Le but était d'avoir un PNJ aussi peu "PNJ" que possible, vu que c'était une serveuse pour un serveur roleplay. Les interactions avec elle sont donc similaires à celles avec un joueur, et son comportement relativement réaliste (ça reste un script ).

Le mieux est sans doute de jeter un coup d'oeil au module de démo, même si le script est surtout intéressant en multijoueur.

[Le module de démo et le .erf pour importer la serveuse dans un autre module sont là.]

On va dire que pour l'instant c'est une beta, vu qu'elle est encore en test sur Faltazia mais que les bugs sont pas évidents à dépister en solo.
Elle ne gère pas la dépense d'argent car Faltazia a un système économique un peu particulier, mais la fonction est facile à implémenter.
_____

Pour l'utiliser, il faut importer le .erf livré dans le zip, poser la serveuse dans la taverne (par défaut, un PNJ humain appelé Silwenne, mais on peut en créer une autre, du moment qu'elle possède les trois scripts onConversation, onPerception et onSpawn).

Il lui faut également deux waypoints pour lui indiquer l'emplacement de son bar ou des cuisines, nommés "WP_Bar1" et "WP_Bar2". Le premier est un point intermédiaire sur le trajet pour aller au waypoint WP_Bar2 "derrière" le bar, car sinon le pathfinding du jeu a du mal (en général, il n'arrive pas à contourner le bar pour passer derrière).
_____

Elle connaît par défaut les boissons suivantes : vin chaud, eau, bière, hydromel, liqueurs diverses, calvat, whisky, rhum, vodka, saké, gnôle, grog, vin, lait, thé, tisane, jus de fruits divers, cidre et bécasse (ce sont les boissons servies à l'auberge de mon mod, en fait ). Il est facile d'en rajouter.

Il est possible de l'appeler quand elle est à portée de voix, avec des phrases comme *appelle la serveuse*, *fait signe à Silwenne*, *hèle Sil*, *appelle Silwenne*, *fait signe à la serveuse*, etc, etc. Auquel cas elle vient peu de temps après prendre la commande (sinon elle reprend les commandes toutes les 90 min par défaut, pour éviter le squattage de table sans consommer ).
__________________

Serveur francophone Faltazia,
serveur 100% roleplay.
Lightbulb
Les scripts, pour les curieux qui n'ont pas envie de tester. ;)
onSpawn :
Code PHP:

#include "serv_inc"

void main()
{
  
SetListening(oServeuseTRUE);
  
SetListenPattern(oServeuse"** vin chaud**",      5000);
  
SetListenPattern(oServeuse"**('| )eau**",        5001);
  
SetListenPattern(oServeuse"** bi(è|e)(r|rr)e**"5002);
  
SetListenPattern(oServeuse"**('| )hydromel**",   5003);
  
SetListenPattern(oServeuse"**liqueur**",         5004);
  
SetListenPattern(oServeuse"**calvat**",          5005);
  
SetListenPattern(oServeuse"**whisky**",          5006);
  
SetListenPattern(oServeuse"**rhum**",            5007);
  
SetListenPattern(oServeuse"**vodka**",           5008);
  
SetListenPattern(oServeuse"**sak(é|e)**",        5009);
  
SetListenPattern(oServeuse"** gn(o|ô)le**",      5010);
  
SetListenPattern(oServeuse"** grog**",           5011);
  
SetListenPattern(oServeuse"** vin**",            5012);
  
SetListenPattern(oServeuse"** lait**",           5013);
  
SetListenPattern(oServeuse"** th(é|e)**",        5014);
  
SetListenPattern(oServeuse"**tisane**",          5015);
  
SetListenPattern(oServeuse"** jus d**",          5016);
  
SetListenPattern(oServeuse"** cidre**",          5017);
  
SetListenPattern(oServeuse"** b(é|e)casse**",    5018);
  
SetListenPattern(oServeuse"** rien**",           5019);
  
SetListenPattern(oServeuse"**((appelle|fait signe à)|hèle) (la serveuse|(Silwenne|Sil))**"6000);
  
Idle();

onConversation :
Code PHP:

#include "serv_inc"

void main()
{
  
int iPattern GetListenPatternNumber();
  
object oPC GetLastSpeaker();
  if (
iPattern == -1//Dialogue
  
{
    
BeginConversation();
    return;
  }
  if (
GetLocalInt(oServeuse"State") == STATE_OFF) return;
  if (
iPattern == 6000//Serveuse appelee
  
{
    
SpeakString("Un instant, j'arrive !");
    
DeleteLocalInt(oPC"CommandePrise");
    return;
  }
  
string sCommande;
  if (
GetLocalString(oServeuse"CurrentClient") != GetName(oPC)) return;
  switch (
iPattern)
  {
    case 
5000 sCommande "drk_vincho"; break;
    case 
5001 sCommande "drk_eau"; break;
    case 
5002 sCommande "drk_biere"; break;
    case 
5003 sCommande "drk_hydromel"; break;
    case 
5004 sCommande "drk_liqueur"; break;
    case 
5005 sCommande "drk_calvat"; break;
    case 
5006 sCommande "drk_whisky"; break;
    case 
5007 sCommande "drk_rhum"; break;
    case 
5008 sCommande "drk_vodka"; break;
    case 
5009 sCommande "drk_sake"; break;
    case 
5010 sCommande "drk_gnole"; break;
    case 
5011 sCommande "drk_grog"; break;
    case 
5012 sCommande "drk_vin"; break;
    case 
5013 sCommande "drk_lait"; break;
    case 
5014 sCommande "drk_the"; break;
    case 
5015 sCommande "drk_tisane"; break;
    case 
5016 sCommande "drk_jufruit"; break;
    case 
5017 sCommande "drk_cidre"; break;
    case 
5018 sCommande "drk_becasse"; break;
    case 
5019 sCommande "neant"; break;
  }
  
SetLocalString(oServeuse"Commande de " GetName(oPC), sCommande);

onPerception :
Code PHP:

#include "serv_inc"

void main()
{
  if (!
GetLastPerceptionSeen()) return;
  
object oPC GetLastPerceived();
  if (!
GetIsPC(oPC)) return;
  if (
GetLocalInt(oPC"CommandePrise")) return;
  
AddClientToList(oPC);

include :
Code PHP:

object oServeuse OBJECT_SELF;
int STATE_IDLE 1;
int STATE_BUSY 2;
int STATE_LISTENING 3;
int STATE_OFF 4;
//Cette constante determine la frequence en secondes a laquelle
//la serveuse revient prendre les commandes. Par defaut, 90min.
float FREQUENCE_COMMANDES 5400.0;



//Prend la valeur "sire" ou "dame" selon le sexe de oPC
string GenderToString(object oPC);
//Ajoute oPC a la liste de ceux consideres comme
//clients par la serveuse
void AddClientToList(object oPC);
//Retire le nom sClientName de la liste des clients
void RemoveClientFromList(string sClientName);
//Renvoie un PC a partir de son nom
object GetPCByName(string sName);
//Renvoie le client le plus proche de la serveuse,
//assis et dont la commande n'a pas encore ete prise
object GetNearestClient();
//Fait le tour des clients qui n'ont pas encore passe
//de commande pour demander ce qu'ils veulent
void PrendCommandes();
//Enregistre la commande de oPC
void ConfirmeCommande(object oPC);
//Fait le tour des clients qui ont command pour les servir
void SertClients();
//Action effectuee quand la serveuse n'a rien d'autre a faire
void Idle();

string GenderToString(object oPC)
{
  
string sReturn;
  if (
GetGender(oPC) != GENDER_FEMALE)
    
sReturn "sire";
  else
    
sReturn "dame";
  return (
sReturn);
}

void AddClientToList(object oPC)
{
  if (!
GetIsPC(oPC)) return;
  
int iNbClients GetLocalInt(oServeuse"Nombre de clients");
  
int i;
  for (
0iNbClientsi++)
    if (
GetLocalString(oServeuse"Client" IntToString(i)) == GetName(oPC)) return;
  
SetLocalString(oServeuse"Client" IntToString(iNbClients), GetName(oPC));
  
iNbClients++;
  
SetLocalInt(oServeuse"Nombre de clients"iNbClients);
}

void RemoveClientFromList(string sClientName)
{
  
int iNbClients GetLocalInt(oServeuse"Nombre de clients");
  if (
iNbClients <= 0) return;
  
int i 0;
  while (
iNbClients)
  {
    if (
GetLocalString(oServeuse"Client" IntToString(i)) == sClientName) break;
    
i++;
  }
  
iNbClients--;
  
//Defragmentation de la liste au passage
  
SetLocalString(oServeuse"Client" IntToString(i), GetLocalString(oServeuse"Client" IntToString(iNbClients)));
  
DeleteLocalString(oServeuse"Client" IntToString(iNbClients));
  
SetLocalInt(oServeuse"Nombre de clients"iNbClients);
}

object GetPCByName(string sName)
{
  
object oPC GetFirstPC();
  while (
GetIsObjectValid(oPC) && GetName(oPC) != sName)
    
oPC GetNextPC();
  return 
oPC;
}

object GetNearestClient()
{
  
int iNbClients GetLocalInt(oServeuse"Nombre de clients");
  if (
iNbClients <= 0) return OBJECT_INVALID;
  
int i 0;
  
float fDistanceMin 40.0;
  
float fDistanceClient;
  
object oClient;
  
object oNearestClient;
  
object oAreaServeuse GetArea(oServeuse);
  while (
GetLocalInt(oServeuse"Nombre de clients"))
  {
    
oClient GetPCByName(GetLocalString(oServeuse"Client" IntToString(i)));
    
//Si le client a quitte la taverne, on le retire de la liste
    
if ((GetArea(oClient) != oAreaServeuse) || (!GetIsObjectValid(oClient)))
    {
      
RemoveClientFromList(GetLocalString(oServeuse"Client" IntToString(i)));
      
DeleteLocalInt(oClient"CommandePrise");
    }
    else
    {
      if ((!
GetLocalInt(oClient"CommandePrise")) && (GetCurrentAction(oClient) == ACTION_SIT))
      {
        
fDistanceClient GetDistanceToObject(oClient);
        
//La serveuse ne s'occupe que des clients a proximite (40m par defaut)
        
if (fDistanceClient fDistanceMin)
        {
          
oNearestClient oClient;
          
fDistanceMin fDistanceClient;
        }
      }
      
i++;
    }
  }
  return 
oNearestClient;
}

void PrendCommandes()
{
  if (
GetLocalInt(oServeuse"State") == STATE_LISTENING) return;
  
string sText;
  
int iNbClients GetLocalInt(oServeuse"Nombre de clients");
  if (
iNbClients <= 0)
  {
    
Idle();
    return;
  }
  
object oPC GetNearestClient();
  if (!
GetIsObjectValid(oPC)) //tous les clients assis ont passe leur commande
  
{
    
SertClients();
    return;
  }
  if (
GetLocalInt(oServeuse"State") == STATE_IDLE)
    
ClearAllActions();
  
SetLocalInt(oServeuse"State"STATE_LISTENING);
  
ActionMoveToObject(oPC);
  
ActionWait(1.0);
  switch (
Random(4))
  {
    case 
sText "Bonjour " GenderToString(oPC) + ", qu'est-ce que je vous sers ?"; break;
    case 
sText "Que prendrez-vous, " GenderToString(oPC) + " ?"; break;
    case 
sText "Vous désirez ?"; break;
    case 
sText "Vous prendrez, " GenderToString(oPC) + " ?"; break;
  }
  
ActionSpeakString(sText);
  
ActionDoCommand(SetLocalString(oServeuse"CurrentClient"GetName(oPC)));
  
ActionDoCommand(ConfirmeCommande(oPC));
}

void ConfirmeCommande(object oPC)
{
  
string sCommande GetLocalString(oServeuse"Commande de " GetName(oPC));
  
string sText;
  if (
sCommande == "")
  {
    
ActionWait(2.0);
    
ActionDoCommand(SetLocalInt(oServeuse"Patience"GetLocalInt(oServeuse"Patience") + 1));
    if (
GetLocalInt(oServeuse"Patience") > 30)
      
SetLocalString(oServeuse"Commande de " GetName(oPC), "neant");
    
ActionDoCommand(ConfirmeCommande(oPC));
  }
  else
  {
    switch (
Random(4))
    {
      case 
sText "Je vous apporte ça dans un instant."; break;
      case 
sText "C'est noté, " GenderToString(oPC) + "."; break;
      case 
sText "Je vous l'apporte."; break;
      case 
sText "*Acquiesce et prend note mentalement.*"; break;
    }
    if (
sCommande == "neant")
      
ActionSpeakString("Je repasserai tout à l'heure. *Sourire aimable.*");
    else
      
ActionSpeakString(sText);
    
ActionDoCommand(DeleteLocalString(oServeuse"CurrentClient"));
    
ActionDoCommand(DeleteLocalInt(oServeuse"Patience"));
    
ActionDoCommand(SetLocalInt(oPC"CommandePrise"TRUE));
    
ActionDoCommand(DelayCommand(FREQUENCE_COMMANDESDeleteLocalInt(oPC"CommandePrise")));
    
ActionDoCommand(SetLocalInt(oServeuse"State"STATE_BUSY));
    
ActionWait(1.0);
    
ActionDoCommand(PrendCommandes());
  }
}

void SertClients()
{
  
int i 0;
  
int iCommandesServies 0;
  
string sCommand;
  
string sText;
  
object oClient;
  
object oItem;
  
object oAreaServeuse GetArea(oServeuse);
  while (
GetLocalInt(oServeuse"Nombre de clients"))
  {
    
oClient GetPCByName(GetLocalString(oServeuse"Client" IntToString(i)));
    if ((
GetArea(oClient) != oAreaServeuse) || (!GetIsObjectValid(oClient)))
    {
      
RemoveClientFromList(GetLocalString(oServeuse"Client" IntToString(i)));
      
DeleteLocalInt(oClient"CommandePrise");
      
DeleteLocalString(oServeuse"Commande de " GetLocalString(oServeuse"Client" IntToString(i)));
    }
    else
    {
      
sCommand GetLocalString(oServeuse"Commande de " GetLocalString(oServeuse"Client" IntToString(i)));
      if ((
sCommand != "neant") && (sCommand != ""))
      {
        if (
GetLocalInt(oServeuse"State") == STATE_IDLE)
          
ClearAllActions();
        if (
iCommandesServies%== 0//La serveuse retourne au bar toutes les trois commandes
        
{
          
ActionMoveToLocation(GetLocation(GetObjectByTag("WP_Bar1")));
          
ActionMoveToLocation(GetLocation(GetObjectByTag("WP_Bar2")));
          
ActionDoCommand(SetFacing(GetFacing(GetObjectByTag("WP_Bar2"))));
          
ActionPlayAnimation(ANIMATION_LOOPING_GET_MID1.05.0);
          
ActionWait(2.0);
          
ActionMoveToLocation(GetLocation(GetObjectByTag("WP_Bar1")));
        }
        
oItem CreateItemOnObject(sCommand);
        
ActionMoveToObject(oClient);
        switch (
Random(4))
        {
          case 
sText "Votre " GetStringLowerCase(GetName(oItem)) + ". *Le sourire aux levres.*"; break;
          case 
sText "Voila votre " GetStringLowerCase(GetName(oItem)) + ". *Pose le verre sur la table.*"; break;
          case 
sText "Et votre " GetStringLowerCase(GetName(oItem)) + ", " GenderToString(oClient) + "."; break;
          case 
sText "Tenez, votre " GetStringLowerCase(GetName(oItem)) + ", " GenderToString(oClient) + "."; break;
        }
        
ActionSpeakString(sText);
        
ActionPlayAnimation(ANIMATION_LOOPING_GET_MID1.01.0);
        
ActionGiveItem(oItemoClient);
        
ActionWait(2.0);
        
iCommandesServies++;
      }
      
ActionDoCommand(DeleteLocalString(oServeuse"Commande de " GetName(oClient)));
      
i++;
    }
  }
  
Idle();
}

void Idle()
{
  
DelayCommand(30.0PrendCommandes());
  if (
GetLocalInt(oServeuse"State") != STATE_IDLE)
  {
    
SetLocalInt(oServeuse"State"STATE_IDLE);
    
//Par defaut, la serveuse deambule aleatoirement dans la taverne, mais
    //un script plus personnalise est preferable
    
ActionRandomWalk();
  }

La serveuse possède un inner dialog quand on la clic (inexploité dans la démo) et les scripts fonctionnent de paire avec une panoplie d'items dont les resrefs commencent par "drk_", items de potions symbolisant les diverses boissons (pasque les PJ préfèrent obtenir un objet dans l'histoire, apparemment ).
Répondre

Connectés sur ce fil

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