Blocage lvl

Répondre
Partager Rechercher
Salut,

Je suis en train de chercher comment je pourrais faire une gestion de blocage de niveau sur notre module. Genre un blocage suivant des palier qui seront débloqué par les DMs.

Quelqu'un a déjà quelque chose comme ça? ou une idée?
J'ai pensé à (comme les caract des pj sont posé dans ma DataB) d'insérer un champ "lvlmax" et de le tester à chaque connexion du pj sur le module, mais j'ai peur que celà soit un peu lourd. Et lorsqu'il passe un lvl si le "lvlmax" est inférieur à son lvl le pj retourne au nombre d'xp du lvlmax moins 1.
Qu'en pensez-vous?
J'ai vu ce meme genre de script sur un module appelé "FastFrench".
Malheureusement, je ne sais pas comment ils ont faits pour definir tout cela, désolé. Mais ca existe, j'en suis certain. . .
A plus
Oui je sais, je suis un grand joueur de FastFrench, mais FF n'est pas très bavard et ne veut rien lacher .

Même pour son nwn_ff il ne dit pas plus que son guide, alors qu'il a rajouté dernièrement des choses et ne les expliquent pas . Alors je cherche ailleurs
Citation :
Publié par dams63
Salut,

Je suis en train de chercher comment je pourrais faire une gestion de blocage de niveau sur notre module. Genre un blocage suivant des palier qui seront débloqué par les DMs.

Quelqu'un a déjà quelque chose comme ça? ou une idée?
J'ai pensé à (comme les caract des pj sont posé dans ma DataB) d'insérer un champ "lvlmax" et de le tester à chaque connexion du pj sur le module, mais j'ai peur que celà soit un peu lourd. Et lorsqu'il passe un lvl si le "lvlmax" est inférieur à son lvl le pj retourne au nombre d'xp du lvlmax moins 1.
Qu'en pensez-vous?
Si c'est à la connection du joueur, ce n'est pas très grave en terme de CPU (tu n'as pas 15 connections par seconde)
Si ton serveur n'accepte que des personnages locaux, tu peux le faire sur l'evenement "onlevelup".
Tu peux ainsi bloquer des niveaux ou interdire certaines classes, certains multiclassages voir certains dons.

Si tu veux un exemple de code, dit le moi, j'en posterais.
Le principe en est simple :
Sur l'évènement du level up, on remet, par calcul, les XP pile au maximum du niveau inférieur après avoir testé la condition qui permet ou non de passer le niveau. Après, au choix, tu sauvegardes les XP pour les redonner après la validation du passage ou pas. Deionara a posté pas loin la formule de calcul des XP pour chaque niveau.

Bon courage
Dans le onlevelup event tu place ce code.

Cela te permet de verifier des dons, voir des caractéristiques et de bloquer un joueur selon son niveau.


Code:
// demande au PJ de refaire son lvl
// lui retire les px en trop
void Refaitlvl(object pj)
{  int PXLvL = (GetHitDice(pj)-1)*(GetHitDice(pj))*1000/2;
   int CurrentPX = GetXP(pj);
   WriteTimestampedLogEntry("Lvl Redo :"+GetName(pj)+" lvl:"+IntToString(GetHitDice(pj))+" "+GetPCPublicCDKey(pj)+" "+GetPCPlayerName(pj));
   DelayCommand(1.0,FloatingTextStringOnCreature("Tu vas devoir refaire ton niveau",pj));
   SetXP(pj,PXLvL-10);
   DelayCommand(10.0,SetXP(pj,CurrentPX));
}

// verifie les dons.
// ici j'interdit le combat au corps à corps pour les pretres
// tu peux en rajouter d'autres
// ainsi que des checks sur les caracteristique ou autre
int CheckDon(object pj)
{  if ((GetLevelByClass(CLASS_TYPE_CLERIC,pj)>=1) && (GetHasFeat(FEAT_IMPROVED_UNARMED_STRIKE,pj)))
      {DelayCommand(8.0,FloatingTextStringOnCreature("La Classe de Prètre n'a pas le droit au don 'combat à main nu'.",pj)); return -1;}
      return 0;
}

// donne le niveau max d'un joueur, stocke dans une variable locale par exemple
// à voir selon la persistance que tu utilises pour la stocker en "dur"
int GetLevelMaxPJ(object pj) {
  int resultat = GetLocalInt(pj,"levelMax");
  return     resultat;
}

// determine le max d'XPs du pj (selon le niveau qu'il a le droit d'atteindre) et l'informe
void MaxLevelHPs(object pj=OBJECT_SELF) {
    int i = GetLevelMaxPJ(pj); int z;
    if (i<21) i = 20;
    if (i > 30) {
        z = 440000;
        for (;i>30;i--) z += (i*1000);
    } else
      switch (i) {
        case 20: z = 204000; break;
        case 21: z = 215000; break;
        case 22: z = 235000; break;
        case 23: z = 257000; break;
        case 24: z = 280000; break;
        case 25: z = 305000; break;
        case 26: z = 330000; break;
        case 27: z = 355000; break;
        case 28: z = 383000; break;
        case 29: z = 410000; break;
        case 30: z = 440000; break;
        default: z = 204000;
      }
    if (GetXP(pj) > z) {
        FloatingTextStringOnCreature(sRed+"tu viens de perdre des points d'experiences car tu as perdu des niveaux", pj);
        SetXP(pj, z);
    }
    SetLocalInt(pj, LocalMaxLvl, z);
    if (GetXP(pj) > z) SetXP(pj, z);
}

void main()
{  object pj = GetPCLevellingUp()
   MaxLevelHPs(pj);  // bloque un joueur à un certain niveau (en px/lvl)
   CheckPJ(pj);      // verifie si le joueur n'a pas pris des dons interdit
   //CheckKarak(pj); // pour verifié les carac du joueur
}
n'hesite pas si tu as des questions
-yi- j'aurai une question a te poser si cela ne te derange pas.
Ton script bloque le pj a un niveau mais si on veut faire des lvl que seul un dm peut debloquer,comment on fait?
Ou alors j'ai pas super bien suivis et donc serais tu aimable de me reexpliquer s'il te plait
Pour débloquer les niveaux par un DM, personnellement j'ai crée un objet pour le DM avec "pouvoir unique".

Dans l'évènement du serveur On Activate j'ai ce code ci


Code:
// pj : la cible, appelant : l'utilisateur du baton
void SceptreDeNiveau(object pj,object appelant, string sS) {
  if (GetIsDM(appelant))
   {  ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_MIND),appelant);
       int lvlCategorie = GetCampaignInt(Identifiant(pj),"levelMax");
       SetCampaignInt(Identifiant(pj), "levelMax" ,lvlCategorie+1);
       SetLocalInt(pj,"levelMax",lvlCategorie+1);
   }
}
   
void main()
{  object quoi = GetItemActivated();
    object pj = GetItemActivator();
    object target = GetItemActivatedTarget();
    string sS = GetStringUpperCase(GetTag(quoi)); 

    if (FindSubString(sS,"YI_SCEP")>=0) {SceptreDeNiveau(target,pj,sS);}

}
comptes tu utiliser une persistance ? si oui laquelle ?
j'espère que mon exemple t'aide.
Si tu aimes éditer les 2da, j'ai une solution très appréciable, qui demande juste un peu de temps à consacrer.

Dans le fichier "classes.2da", chaque classe a un champ PreReqTable. Tu peux donc créer une table 2da pour chaque classe, comprenant les champs LABEL, ReqType, ReqParam1, et ReqParam2. Par exemple pour le paladin, j'ai créé le fichier "Class_PreReq_Pal.2da" et j'y ai mis :
Code:
     LABEL        ReqType   ReqParam1       ReqParam2

0    ScriptVar    VAR       ALLOW_PALADIN   0
Ceci signifie que si la variable "ALLOW_PALADIN" sur le joueur est à 0 ou absente, il pourra passer un niveau dans la classe de paladin. Si je mets cette variable à une autre valeur, la classe de paladin sera grisée, donc indisponible. Les classes de prestige sont toutes équipées d'une telle option. J'ai ensuite rajouté le nom du 2da dans le champ "PreReqTable" du fichier "classes.2da".


Il ne reste plus qu'à mettre quelques lignes de script à l'intention des joueurs, dans le OnClientEnter ainsi que dans le OnPlayerLevelUp. En retrouvant le niveau actuel à l'aide de GetHitDice(), tu pourras mettre toutes ces variables à 1, selon le ou les paliers que tu auras choisis.

Par exemple, au niveaux 5, 10, 15 et 20, je souhaite mettre un palier, je marquerai :
Code PHP:

void main()
{
    
object oPC GetPlayerLevelingUp(); // ou "GetEnteringObject" pour le OnClientEnter
    
int nLevel GetHitDice(oPC);

    if(
nLevel==5||nLevel==10||nLevel==15||nLevel==20)
    {
        
SetLocalInt(oPC,"ALLOW_PALADIN",1);
        
SetLocalInt(oPC,"ALLOW_CLERIC",1);
        
SetLocalInt(oPC,"ALLOW_ROGUE",1);
        
// etc, etc, etc...
    
}

Ensuite, suivant ta version d'accorder le droit de passer un niveau, par exemple un objet acquis :
Code PHP:

void main()
{
    
object oItem GetModuleItemAcquired();
    
object oPC GetModuleItemAcquiredBy();

    if(
GetTag(oItem)=="PASS_MD")
    {
        
DeleteLocalInt(oPC,"ALLOW_PALADIN");
        
DeleteLocalInt(oPC,"ALLOW_CLERIC");
        
DeleteLocalInt(oPC,"ALLOW_ROGUE");
        
// etc, etc, etc...
    
}

Cette méthode nécessite peut-être l'usage d'un HakPack, mais elle est plus souple au niveau du passage de niveau, Evitant tous les calculs d'xp encombrants.

C'est également une méthode très pratique à utiliser si tu te sers d'un dialogue avec un maître pouvant permettre le joueur de passer un niveau dans une classe précise.

Attention cependant, lors de la création d'un personnage, aucun prérequis personnalisé ne sera pris en compte, toutes les modifications seront effectives quand le joueur sera "physiquement" dans le module, donc à partir du niveau 2.
Le probleme c'est que le module ne doit pas necessiter de Hak Pak afin qu'il puisse etre ouvert a un maximum de gens (merci quand meme Deyonara (et oui encore une fois, tu m'aides ).
Pour le type de persistance,je pense que ca sera un persistance roleplay. . .
Pourquoi cette question -yi- *inculte de base * ?
Si c'est un problème venant de la taille du HakPack, il ne dépassera pas les 1 Mo.

Mais bon ça servira à d'autres si tu ne t'en sers pas, je ne te mets pas le couteau sous la gorge non plus. ^^
Je sais,je sais mais le master du module veut pas un seul Hakpak
En plus, il est vrai que c'est tres utile pour d'autres.
Dans ton script -yi-,si j'ai bien compris quand j'utilise le baton,il debloque 1 lvl c'est cela?
J'adore ta solution Deyonara, très élégante !!!

@ Arronax, je t'ai demandé la persistance car il faudra bien stocké les valeurs des niveaux "max" qu'auront tes joueurs... comme ca au reboot du serveur, ils peuvent les garder. Dans mon exemple j'utilise la persistance bioware SetCampaignInt GetCampaignInt

Sinon pour le script, n'hesite pas si tu as d'autres soucis.

Edit : oui il débloque 1 level à la fois
Oui j'ai un petit soucis au niveau du premier script que tu nous a donnés (en script je suis pas trop un pro alors ne t'enerve pas mdr ).
Voila, je voudrais faire des limites pour les niveaux 15-20-25-30-35-40 (par exemple) et j'arrive pas a transcrire cela dans ton premier script .
Pourrais-tu m'aider s'il te plait ?
si je comprends bien, tu veux bloquer à partir du niveau 15 et ensuite que le DM te débloque par tranche de 5 lvls ?
Si c'est bien ça je te le ferais demain soir
ok,
je posterais ca ce soir (j'ai pas Aurora au travail ^^ et pas le temps non plus).

dam63, si je fais une version avec SetCampaignInt et GetCampaingInt pourra tu modifier le script pour utiliser tes propres fonctions de persistance ?
Citation :
Publié par -yi-
ok,
je posterais ca ce soir (j'ai pas Aurora au travail ^^ et pas le temps non plus).

dam63, si je fais une version avec SetCampaignInt et GetCampaingInt pourra tu modifier le script pour utiliser tes propres fonctions de persistance ?
à mon stade d'avancement sur mes compétence en nwn_ff/script, je ne pense pas
=> mais j'y travail

Je pense y arriver, mais je ne suis pas contre un vrai coup de main
Je ne débute que dans ce superbe monde qu'est le développement de "script/persistence/requète sql" dans nwn , et il me manque pas mal de cas concret encore pour arriver à tout comprendre comment tout ce petit univers interragit
Dams, je n'ai jamais regardé nwn_ff, par contre tu dois avoir des fonctions "de base" fournies qui te permettent de :
- mémoriser un entier (int) dans la table d'un joueur
- lire cet entier (int) dans la même table ?


Si tu trouves ce fonction (ou si quelqu'un d'autres les connaît) je te ferais la version nwn_ff

dans le pire des cas, envoie moi le lien sur nwn_ff ou sur les sources de leur script
pour nwn_ff les fonctions de base sont :

Code PHP:

string ff_GetPersistentString(string ValueNamestring sTable="global"string DefaultValue="");
int ff_GetPersistentInt(string ValueNamestring sTable="global"int DefaultValue=0);
float ff_GetPersistentFloat(string ValueNamestring sTable="global"float DefaultValue=0.0);
location ff_GetPersistentLocation(string ValueNamestring sTable="global");
vector ff_GetPersistentVector(string ValueNamestring sTable="global");
void ff_SetPersistentString(string ValueNamestring sValuestring sTable="global");
void ff_SetPersistentInt(string ValueNameint iValuestring sTable="global");
void ff_SetPersistentFloat(string ValueNamefloat fValuestring sTable="global");
void ff_SetPersistentLocation(string ValueNamelocation lValuestring sTable="global");
void ff_SetPersistentVector(string ValueNamevector vValuestring sTable="global");
void ff_DeletePersistentVariable(string ValueNamestring sTable="global"); 
la meme chose mais cela ecrit toujours dans une meme table PCData.
Code PHP:

string ff_GetPCPersistentString(object oPCstring ValueName);
int ff_GetPCPersistentInt(object oPCstring ValueName);
float ff_GetPCPersistentFloat(object oPCstring ValueName);
location ff_GetPCPersistentLocation(object oPCstring ValueName);
vector ff_GetPCPersistentVector(object oPCstring ValueName);
void ff_SetPCPersistentString(object oPCstring ValueNamestring sValue);
void ff_SetPCPersistentInt(object oPCstring ValueNameint iValue);
void ff_SetPCPersistentFloat(object oPCstring ValueNamefloat fValue);
void ff_SetPCPersistentLocation(object oPCstring ValueNamelocation lValue);
void ff_SetPCPersistentVector(object oPCstring ValueNamevector lValue);
void ff_DeletePCPersistentVariable(object oPCstring ValueName); 
C'est les fonctions de base de nwn_ff, mais on est pas oblige de les utiliser, et d'ailleurs on s'en passe tres bien si on pratique le SQL.
Je crois pas avoir bcq d'endroit ou j'utilise ces fonctions perso
Voila ce que ca peut donner (Presque tout droit tiré d'Arkalym )

1) il faut créer un fichier include.
Je le nomme inc_yi_lvlup. On va y ranger toutes les fonctions de base

Code:
// renvoie une string lie au joueur et a son pero
string Identifiant(object pj);
// demande au PJ de refaire son lvl
// lui retire les px en trop
void Refaitlvl(object pj);
// verifie les dons.
// ici j'interdit le combat au corps à corps pour les pretres
// tu peux en rajouter d'autres
// ainsi que des checks sur les caracteristique ou autre
int CheckDon(object pj);
// donne le niveau max d'un joueur, stocke dans une variable locale par exemple
// à voir selon la persistance que tu utilises pour la stocker en "dur"
int GetLevelMaxPJ(object pj);
// determine le max d'XPs du pj (selon le niveau qu'il a le droit d'atteindre) et l'informe
void MaxLevelHPs(object pj=OBJECT_SELF);
// Intialise les varialbes des lvls du PJ
void InitLvlPj(object pj);

//*****************************************************************************
//                                        IMPLEMENTATION
//*****************************************************************************


// renvoie une string lie au joueur et a son pero
string Identifiant(object pj) {
    string name = GetLocalString(pj,"player_name");
    string s = name+IntToString(GetStringLength(name))+GetName(pj);
    return s;
}

// demande au PJ de refaire son lvl
// lui retire les px en trop
void Refaitlvl(object pj)
{  int PXLvL = (GetHitDice(pj)-1)*(GetHitDice(pj))*1000/2;
   int CurrentPX = GetXP(pj);
   WriteTimestampedLogEntry("Lvl Redo :"+GetName(pj)+" lvl:"+IntToString(GetHitDice(pj))+" "+GetPCPublicCDKey(pj)+" "+GetPCPlayerName(pj));
   DelayCommand(1.0,FloatingTextStringOnCreature("Tu vas devoir refaire ton niveau",pj));
   SetXP(pj,PXLvL-10);
   DelayCommand(10.0,SetXP(pj,CurrentPX));
}

// verifie les dons.
// ici j'interdit le combat au corps à corps pour les pretres
// tu peux en rajouter d'autres
// ainsi que des checks sur les caracteristique ou autre
int CheckDon(object pj)
{  if ((GetLevelByClass(CLASS_TYPE_CLERIC,pj)>=1) && (GetHasFeat(FEAT_IMPROVED_UNARMED_STRIKE,pj)))
      {DelayCommand(8.0,FloatingTextStringOnCreature("La Classe de Prètre n'a pas le droit au don 'combat à main nu'.",pj)); return -1;}
      return 0;
}

// donne le niveau max d'un joueur, stocke dans une variable locale par exemple
// à voir selon la persistance que tu utilises pour la stocker en "dur"
int GetLevelMaxPJ(object pj) {
  int resultat = GetLocalInt(pj,"levelMax");
  return     resultat;
}

// determine le max d'XPs du pj (selon le niveau qu'il a le droit d'atteindre) et l'informe
void MaxLevelHPs(object pj=OBJECT_SELF) {
    int i = GetLevelMaxPJ(pj); int z;
    if (i<21) i = 20;
    if (i > 30) {
        z = 440000;
        for (;i>30;i--) z += (i*1000);
    } else
      switch (i) {
        case 20: z = 204000; break;
        case 21: z = 215000; break;
        case 22: z = 235000; break;
        case 23: z = 257000; break;
        case 24: z = 280000; break;
        case 25: z = 305000; break;
        case 26: z = 330000; break;
        case 27: z = 355000; break;
        case 28: z = 383000; break;
        case 29: z = 410000; break;
        case 30: z = 440000; break;
        default: z = 204000;
      }
    if (GetXP(pj) > z) {
        FloatingTextStringOnCreature(sRed+"tu viens de perdre des points d'experiences car tu as perdu des niveaux", pj);
        SetXP(pj, z);
    }
    SetLocalInt(pj, LocalMaxLvl, z);
    if (GetXP(pj) > z) SetXP(pj, z);
}

// Intialise les varialbes des lvls du PJ
void InitLvlPj(object pj) {
  int lvl = GetCampaignInt(Identifiant(pj),"levelMax");
  if (lvl==0) // nouveau joueur
    { lvl = 15;
      SetCampaignInt(Identifiant(pj),"levelMax",lvl);
    }
  SetLocalInt(pj,"levelMax",lvl); // pour eviter les acces disques, on stocke la valeur sur le pj
  FloatingTextStringOnCreature("Ton mérite te permet d'atteindre le niveau :"+IntToString(lvl),pj,FALSE);
  MaxLevelHPs(pj);
}
2) On passe ensuite aux evenements
dans on enter du module, on charge les valeurs (ou on les initialises à lvl=15 pour les nouveaux joueurs
Code:
#include "inc_yi_lvlup"
void main()
{  object pj = GetEnteringObject();
   InitLvlPj(pj);
}
dans on level up, pour vérifier si un joueur fait un level up alors qu'il n'a pas le droit.
on en profite pour lui retirer les px si besoin (et la j'en profite même pour vérifier des dons et/ou classe interdites : CheckPJ

Code:
#include "inc_yi_lvlup"
void main()
{  object pj = GetPCLevellingUp()
   MaxLevelHPs(pj);  // bloque un joueur à un certain niveau (en px/lvl)
   CheckPJ(pj);      // verifie si le joueur n'a pas pris des dons interdit
   //CheckKarak(pj); // pour verifié les carac du joueur
}
et enfin l'evenement on item activated, il permet à un DM d'utiliser un objet ayant un pouvoir unique et ayant dans son tag "YI_SCEP" de débloquer de 5 niveaux le joueur


Code:
#include "inc_yi_lvlup"

// pj : la cible, appelant : l'utilisateur du baton
void SceptreDeNiveau(object pj,object appelant, string sS) {
  if (GetIsDM(appelant))
   {  ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_MIND),appelant);
       int lvl = GetLocalInt(pj,"levelMax");
       if (lvl==40) 
      {  FloatingTextStringOnCreature("Ce joueur peut déjà atteindre le niveau 40",appelant);
          return;
       }
       lvl = lvl + 5;
       SetCampaignInt(Identifiant(pj), "levelMax" ,lvl);
       SetLocalInt(pj,"levelMax",lvl);
   }
}
   
void main()
{  object quoi = GetItemActivated();
    object pj = GetItemActivator();
    object target = GetItemActivatedTarget();
    string sS = GetStringUpperCase(GetTag(quoi)); 

    if (FindSubString(sS,"YI_SCEP")>=0) {SceptreDeNiveau(target,pj,sS);}

}
Voila.

Pour utiliser nwn_ff il suffit de modifier 3 lignes.
On remplace SetCampaignInt(Identifiant(pj),"levelMax",lvl); par
ff_SetPCPersistentInt(pj,"levelMax",lvl); les 2 fois où on le croise
et remplacer GetCampaingInt(Identifiant(pj),"levelMax"); par
ff_GetPCPersistentInt(pj, "levelMax");

Dites moi ce que cela donne
Répondre

Connectés sur ce fil

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