Open-Wow / le-codex

Open-Wow est un projet communautaire visant à centraliser des tutoriels et des ressources en français pour les développeurs.
3 stars 1 forks source link

[Tutoriel - LUA]Mr Spell #36

Open ghost opened 4 years ago

ghost commented 4 years ago

Mr Spell

Tutoriel par @iThorgrim-Hub

Heyio,

Aujourd'hui je vous propose un tutoriel pour l'un des scripts les plus connus du monde des serveurs privés UltraFun. On va apprendre à faire un Mr.Spell Avant de commencer mes blagues super sympas, je tiens tout de même à vous signaler que ce tutoriel est le sujet d'une de mes vidéos Youtube

Alors le Mr Spell cé kwa ?

Le Mr. Spell ou appelés "Misteur Spaile" par les non Anglophones est un PNJ qui vous permet d'apprendre un sort qui n'est pas de votre classe. Il est très utilisés sur les serveurs UltraFun afin de .. de ..

-Le Mr Spell il sert à quoi Bob ? -C'est pour que le jeux soit plus Fun. -Ah.

Donc il est très utilisés sur les serveurs en manque d'imagination et qui ont du mal à chier du contenu. (Oui je prend partit durant mes tutoriels écris, je n'aime pas les serveurs ultraFun poubelle).

Bref .. trêve de grivoiserie, il est tant d'entrer dans le vif du sujet.

Pour commencer on va déclerer nos tableaux qui vont nous êtres utile.

local MrSpell = {};

MrSpell.Locale = {
    [1] = 'Guerrier',
};

MrSpell.spellList = {
    [1] = {},
};

MrSpell.spellCost = {
};

Alors comme vous pouvez le voir j'ai déjà mis quelques informations, c'est tout simplement pour vous aider pour la suite. Il reste tout de même 2 tableaux qui sont vide :

MrSpell.spellList = {
    [1] = {},
};

MrSpell.spellCost = {
};

Voici un exemple un peu plus valide.

local MrSpell = {};

MrSpell.Locale = {
    [1] = 'Guerrier',
};

MrSpell.spellList = {
    [1] = {
        [12550] = 'Frappe mortelle',
        [69] = 'Frappe héroïque',
    },
};

MrSpell.spellCost = {
    [12550] = 50,
    [69] = 100,
};

Ici je dis donc que le sort 12550 se nomme 'Frappe mortelle' et que ce même sort couteras 50 de notre monnaie.

function MrSpell.onHello(event, player, object)
    local pClass = player:GetClass();

    for k, v in pairs(MrSpell.Locale) do
        if (pClass ~= k) then
            player:GossipMenuAddItem(0, v, 0, k)
        end
    end

    player:GossipSendMenu(1, object);
end

Ici c'est très simple quand notre joueur parleras au PNJ on lui demande d'afficher la liste des classes et de ne pas afficher la classe qui correspond au joueur.

Par exemple un Guerrier ne peu pas voir la catégorie Guerrier et acheter un sort de guerrier.

Si vous vouhaitez permettre ceci il vous suffiras simplement de retirer le :

if (pClass ~= k) then
    ...
end

Et ainsi les Guerriers pourrons acheter les sorts de Guerriers.

Je n'ai pas spécialement besoin d'expliquer ce qu'il ce passe durant ce morceau de code vue .. qu'il ne passe pas grand choses, j'ai fait une boucle "for" pour parcourir mon tableau et afficher des informations dans un menu Gossip.

D'ailleurs si vous souhaitez en savoir plus sur les gossip Kazuma a fait un tutoriel là dessus.

Maintenant il nous faire le GossipSelect qui vas d'ailleurs contenir les 3/4 de notre code.

function MrSpell.onSelect(event, player, object, sender, intid)
    for classId, classSubArray in pairs(MrSpell.spellList) do

    end
end

Ont commence par faire une boucle des sorts de notre list complète.

function MrSpell.onSelect(event, player, object, sender, intid)
    for classId, classSubArray in pairs(MrSpell.spellList) do
        if (intid == classId) then
            for spellId, spellName in pairs(classSubArray) do

            end
        end
    end
end

Ici ont vérifie que si notre intid est égale à la classId. Cela va servir à afficher les sorts qui ne concerne que la classe que nous avons séléctionnés dans le menu principal.

Après quoi ont fait une boucle "for" du sous tableau de MrSpell.spellList. (Je m'explique):

MrSpell.spellList = {

};

Ca c'est le tableau "principal" un tableau simple, sauf que nous lui demandons de stocker les sorts pour une certains classe.

MrSpell.spellList = {
    [1] = {
        [12550] = 'Frappe mortelle',
        [69] = 'Frappe héroïque',
    },
};

Ce qui fait que dans notre tableau, nous avons un tableau. On dis que MrSpell.spellList est un tableau multidimensionnel.

Et comme nous avons besoin d'afficher les noms des sorts nous allons donc faire une boucle "for" pour afficher ceux-ci.

function MrSpell.onSelect(event, player, object, sender, intid)
    for classId, classSubArray in pairs(MrSpell.spellList) do
        if (intid == classId) then
            for spellId, spellName in pairs(classSubArray) do
                local pSpell = player:HasSpell(spellId);

                local msg = '';
                if (pSpell) then 
                    msg = '|CFF009D09Déjà Appris|r';
                else 
                    msg = '|CFF9D1C00Non appris|r';
                end

                player:GossipMenuAddItem(0, spellName..' '..msg, 0, spellId)
                player:GossipSendMenu(1, object);
            end
        end
    end
end

Donc ici on peu voir que j'ai ajoutés un variable local (pSpell) qui va avoir comme mission de vérifier si nous connaissons ou non le sort.

Celon si nous connaissons le sort ou pas, la variable local "msg" va stocker l'informations "Déjà appris" ou "Non appris". Ce qui va nous servir à le mettre à côté du nom du sort pour que le joueur soit au courant du fait qu'il ai appris le sort ou non.

A la suite de quoi nous faisons simplement le listing des sorts de la catégorie choisis en ajoutant la petite variable locale "msg" pour informer le joueur.

function MrSpell.onSelect(event, player, object, sender, intid)
    for classId, classSubArray in pairs(MrSpell.spellList) do
        if (intid == classId) then
            for spellId, spellName in pairs(classSubArray) do
                local pSpell = player:HasSpell(spellId);

                local msg = '';
                if (pSpell) then 
                    msg = '|CFF009D09Déjà Appris|r';
                else 
                    msg = '|CFF9D1C00Non appris|r';
                end

                player:GossipMenuAddItem(0, spellName..' '..msg, 0, spellId)
                player:GossipSendMenu(1, object);
            end
        end

        for spellId, _ in pairs(classSubArray) do
            if (intid == spellId) then

            end
        end
    end
end

Ici on va récupérer une manière de faire que l'ont utilise un peu plus haut sauf que l'ont vas inverser la technique. On va d'abord va un listing des sorts qui sont pour notre catégorie et ont vérifie si l'intid envoyés correspond à un sort de notre catégorie.

function MrSpell.onSelect(event, player, object, sender, intid)
    for classId, classSubArray in pairs(MrSpell.spellList) do
        if (intid == classId) then
            for spellId, spellName in pairs(classSubArray) do
                local pSpell = player:HasSpell(spellId);

                local msg = '';
                if (pSpell) then 
                    msg = '|CFF009D09Déjà Appris|r';
                else 
                    msg = '|CFF9D1C00Non appris|r';
                end

                player:GossipMenuAddItem(0, spellName..' '..msg, 0, spellId)
                player:GossipSendMenu(1, object);
            end
        end

        for spellId, _ in pairs(classSubArray) do
            if (intid == spellId) then
                for spellCostId, Cost in pairs(MrSpell.spellCost) do
                    if (spellId == spellCostId) then
                        local pMoney = player:GetItemCount(40752);
                    end
                end
            end
        end
    end
end

Alors là on lui demande de nous faire le listing de tout les prix des sorts. Puis ont va lui demander de vérifier que le sort que l'ont a choisis correspond à un sort qui a un prix (cela va nous servir juste après). A la suite de quoi je demande à enregistrer le nombre d'exemplaire de l'object 40752 que je posséde. A savoir que vous pouvez modifier ici l'entry de l'objet pour mettre celui de votre choix.

function MrSpell.onSelect(event, player, object, sender, intid)
    for classId, classSubArray in pairs(MrSpell.spellList) do
        if (intid == classId) then
            for spellId, spellName in pairs(classSubArray) do
                local pSpell = player:HasSpell(spellId);

                local msg = '';
                if (pSpell) then 
                    msg = '|CFF009D09Déjà Appris|r';
                else 
                    msg = '|CFF9D1C00Non appris|r';
                end

                player:GossipMenuAddItem(0, spellName..' '..msg, 0, spellId)
                player:GossipSendMenu(1, object);
            end
        end

        for spellId, _ in pairs(classSubArray) do
            if (intid == spellId) then
                for spellCostId, Cost in pairs(MrSpell.spellCost) do
                    if (spellId == spellCostId) then
                        local pMoney = player:GetItemCount(40752);

                        if (pMoney >= Cost)then
                            local pSpell = player:HasSpell(spellId);
                        else
                            player:SendNotification('Vous n\'avez pas assez de point pour effectuer cette action.');
                            MrSpell.onHello(event, player, object);
                        end
                    end
                end
            end
        end
    end
end

Le PNJ vérifie que je posséde le nombre de points ou que je posséde plus de points que le prix, sinon quoi, je recevrais un message d'erreur et je serais re-envoyés au menu principal. Si je posséde le bon nombre de points je lui demande de vérifier si je posséde le sort.

function MrSpell.onSelect(event, player, object, sender, intid)
    for classId, classSubArray in pairs(MrSpell.spellList) do
        if (intid == classId) then
            for spellId, spellName in pairs(classSubArray) do
                local pSpell = player:HasSpell(spellId);

                local msg = '';
                if (pSpell) then 
                    msg = '|CFF009D09Déjà Appris|r';
                else 
                    msg = '|CFF9D1C00Non appris|r';
                end

                player:GossipMenuAddItem(0, spellName..' '..msg, 0, spellId)
                player:GossipSendMenu(1, object);
            end
        end

        for spellId, _ in pairs(classSubArray) do
            if (intid == spellId) then
                for spellCostId, Cost in pairs(MrSpell.spellCost) do
                    if (spellId == spellCostId) then
                        local pMoney = player:GetItemCount(40752);

                        if (pMoney >= Cost)then
                            local pSpell = player:HasSpell(spellId);
                            if (not(pSpell)) then
                                player:RemoveItem(40752, Cost);
                                player:LearnSpell(spellId);
                                player:GossipComplete();
                                player:SendNotification('Merci pour votre achat.');
                            else
                                player:SendNotification('Vous connaissez déjà ce sort.');
                                MrSpell.onHello(event, player, object);
                            end
                        else
                            player:SendNotification('Vous n\'avez pas assez de point pour effectuer cette action.');
                            MrSpell.onHello(event, player, object);
                        end
                    end
                end
            end
        end
    end
end

Et là c'est la fin, je lui dis que si je ne posséde pas le sort alors :

Sinon il m'envoie un message d'erreur et me re-envoie vers le menu principal. Il ne reste qu'a ajouter les Events qui vont régire mon code.

RegisterCreatureGossipEvent(197, 1, MrSpell.onHello)
RegisterCreatureGossipEvent(197, 2, MrSpell.onSelect)

Voilà j'espère que ce tutoriel vous auras plût, j'ai essayer d'être le plus clair possible, si vous avez des questions hésitez pas! Le code complet lui ressemble à ceci :

local MrSpell = {};

MrSpell.Locale = {
    [1] = 'Guerrier',
};

MrSpell.spellList = {
    [1] = {
        [12550] = 'Frappe mortelle',
        [69] = 'Frappe héroïque',
    },
};

MrSpell.spellCost = {
    [12550] = 50,
    [69] = 100,
};

function MrSpell.onHello(event, player, object)
    local pClass = player:GetClass();
    for k, v in pairs(MrSpell.Locale) do
        if (pClass ~= k) then
            player:GossipMenuAddItem(0, v, 0, k)
        end
    end
    player:GossipSendMenu(1, object);
end

function MrSpell.onSelect(event, player, object, sender, intid)
    for classId, classSubArray in pairs(MrSpell.spellList) do

        if (intid == classId) then
            for spellId, spellName in pairs(classSubArray) do
                local pSpell = player:HasSpell(spellId);

                local msg = '';
                if (pSpell) then 
                    msg = '|CFF009D09Déjà Appris|r';
                else 
                    msg = '|CFF9D1C00Non appris|r';
                end

                player:GossipMenuAddItem(0, spellName..' '..msg, 0, spellId)
                player:GossipSendMenu(1, object);
            end
        end

        for spellId, _ in pairs(classSubArray) do
            if (intid == spellId) then
                for spellCostId, Cost in pairs(MrSpell.spellCost) do
                    if (spellId == spellCostId) then
                        local pMoney = player:GetItemCount(40752);
                        if (pMoney >= Cost)then

                            local pSpell = player:HasSpell(spellId);
                            if (not(pSpell)) then
                                player:RemoveItem(40752, Cost);
                                player:LearnSpell(spellId);
                                player:GossipComplete();
                                player:SendNotification('Merci pour votre achat.');
                            else
                                player:SendNotification('Vous connaissez déjà ce sort.');
                                MrSpell.onHello(event, player, object);
                            end
                        else
                            player:SendNotification('Vous n\'avez pas assez de point pour effectuer cette action.');
                            MrSpell.onHello(event, player, object);
                        end

                    end
                end
            end
        end
    end
end
RegisterCreatureGossipEvent(197, 1, MrSpell.onHello)
RegisterCreatureGossipEvent(197, 2, MrSpell.onSelect)