Jump to content

Playerbot


Recommended Posts

  • Replies 799
  • Created
  • Last Reply

Top Posters In This Topic

I guess playerbot will be included in Mangos R2 ? (I still don't figure out what's the difference between all versions/branches... such a mess for a novice...)

It does, but only a lean version. If you wish to use all the features of playerbot then you need to get the code from the playerbot site.

When you mean 'version/branches' are you referring to how git manages the code. I was the same when I started, it's can be difficult to grasp and one of those things you must accept works. A brilliant concept by Linus Torvalds.

Link to comment
Share on other sites

MaNGOS is the official core for 3.3.5a.

MaNGOS Zero is the official core for 1.12. MaNGOS One is the official core for 2.43. These projects were split off to have their own dedicated development.

MaNGOS R2, Trinity, Orange, and other varieties are forks of those code bases. They use custom patches and are greatly modified from the MaNGOS code. As such, you can expect bugs to be present in these forks that are not in MaNGOS. To their benefit, the forks have fixed some MaNGOS bugs but sometimes this involves using hacks and workarounds.

Playerbot is built from the official MaNGOS code. You will most likely encounter conflicts and bugs when trying to merge Playerbot with one of the forks. Some forks already have Playerbot merged with their code, but be aware there may also be customizations and modification to Playerbot in these cores to accommodate their features.

It really is up to you which core you like best. I would recommend sticking with the official code base until you have become familiar with how things work and get comfortable with skills like using Git, merging patches, and resolving conflicts.

Link to comment
Share on other sites

By the way... are the Craft-Abilities only in the New-Ai-Branch? Or also in the master portal branch?

Can't wait to test them :D But i don't want to switch again xD Switched from the stable to portal a few hours ago :D

Ah, I've only just pushed that code so it's only on new-ai alpha branch. You can still use the 'craft' code with portal. Just create a snap-shot patch for just the 'craft' commit. Then apply this to your portal build, re-build and your rolling... ;)

Here is an amended bash script to create this snap-shot patch

#!/bin/bash -x

git clone git://github.com/mangos/mangos.git new-ai

cd new-ai

git fetch git://github.com/blueboy/portal.git new-ai:new-ai

git checkout new-ai

HASH=`git log --pretty=oneline | grep -m 1 'Revision to' | cut -d " " -f 1`

git diff $HASH > new-ai.patch

Then copy new-ai.patch to your <source-root>

git apply --check --whitespace=fix new-ai.patch

You shouldn't get any conflicts, but I always use '--check' as a precaution.

All feedback on the 'craft' code will be welcomed..

Hope this helps

Link to comment
Share on other sites

wish list:

.GM ON

so is the bots

I was testing in an instance, and died (:P )

but turned gm on, I was fine, bots kept getting killed.

just a wish :-)

But doesn't that take the fun out of the game ;) as a GM you are invunerable

yes that is true.. but puts a stinker on when doing test runs, quest, instances with the bots

Link to comment
Share on other sites

Thanks for this help, blueboy :)

thats the result of the first test, Mangos with applied Playerbot from Portal/Master:

error: patch failed: bot_readme.txt:27

error: bot_readme.txt: patch does not apply

error: patch failed: src/game/playerbot/PlayerbotAI.cpp:1006

error: src/game/playerbot/PlayerbotAI.cpp: patch does not apply

error: patch failed: src/game/playerbot/PlayerbotAI.h:1474

error: src/game/playerbot/PlayerbotAI.h: patch does not apply

and thats the result of a clean Mangos clone without Playerbot:

error: bot_readme.txt: No such file or directory

error: src/game/playerbot/PlayerbotAI.cpp: No such file or directory

error: src/game/playerbot/PlayerbotAI.h: No such file or directory

in both tests nothing was changed on any file.

Maybe i'm too tired to get this solved :D

Link to comment
Share on other sites

Hi darkfr3ak,

I think the best thing to do here is for me to provide you with a modified 'craft' patch that will merge with just the portal master code. Remember there are still features in new-ai that you won't have (i.e 'mail' and the modified 'use' command).

 diff --git a/bot_readme.txt b/bot_readme.txt
index 3fff571..3d0bace 100644
--- a/bot_readme.txt
+++ b/bot_readme.txt
@@ -27,7 +27,23 @@ For a full list of commands, use '/t BOTNAME help' or various subcommands e.g. '
/t BOTNAME assist (you'll need to be attacking something and the bot only does melee atm)
/t BOTNAME spells (replies with all spells known to bot)
/t BOTNAME cast <SPELLID | (part of) SPELLNAME | [sPELLLINK]>
-/t BOTNAME use [iTEM LINK]
+/t BOTNAME craft < alchemy | a >                  (List all learnt alchemy [RECIPE]..)
+                 < blacksmithing | b >            (List all learnt blacksmith [RECIPE]..)
+                 < cooking | c >                  (List all learnt cooking [RECIPE]..)
+                 < engineering | e >              (List all learnt engineering [RECIPE]..)
+                 < firstaid | f >                 (List all learnt firstaid [RECIPE]..)
+                 < inscription | i >              (List all learnt inscription [RECIPE]..)
+                 < jewelcrafting | j >            (List all learnt jewelcrafting [RECIPE]..)
+                 < leatherworking | l >           (List all learnt leatherworking [RECIPE]..)
+                 < magic | m >                    (List all learnt enchanting [RECIPE]..)
+                 < smelting | s >                 (List all learnt mining [RECIPE]..)
+                 < tailoring | t >                (List all learnt tailoring [RECIPE]..)
+/t BOTNAME craft [RECIPE] (craft any recipe that consumes reagents)
+/t BOTNAME craft [RECIPE] all (craft all instances of a particular recipe, indicated by it's [charge])
+/t BOTNAME use [iTEM LINK] (use item on self)
+/t BOTNAME use [iTEM LINK] TARGET (use item on selected unit)
+/t BOTNAME use [iTEM LINK][EQUIPPED ITEM LINK] (use item on equipped item)
+/t BOTNAME use [iTEM LINK][GAMEOBJECT LINK] (use item on gameobject )
/t BOTNAME equip [iTEM LINK]
/t BOTNAME reset (will reset states, orders and loot list)
/t BOTNAME report (bot reports all items, creatures or gameobjects needed to finish quests)
diff --git a/src/game/playerbot/PlayerbotAI.cpp b/src/game/playerbot/PlayerbotAI.cpp
index 59e1c00..92be366 100644
--- a/src/game/playerbot/PlayerbotAI.cpp
+++ b/src/game/playerbot/PlayerbotAI.cpp
@@ -1006,6 +1006,34 @@ void PlayerbotAI::HandleBotOutgoingPacket(const WorldPacket& packet)
                            pSpell->cancel();
                        return;
                    }
+                    case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
+                    {
+                        std::ostringstream out;
+
+                        SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
+                        if (!spellInfo)
+                            return;
+
+                        switch(spellInfo->RequiresSpellFocus) // SpellFocusObject.dbc id
+                        {
+                            case 1 : // need an anvil
+                                out << "|cffff0000I Require an Anvil";
+                                break;
+                            case 2 : // need a loom
+                                out << "|cffff0000I Require a Loom";
+                                break;
+                            case 3 : // need forge
+                                out << "|cffff0000I Require a Forge";
+                                break;
+                            case 4 : // need cooking fire
+                                out << "|cffff0000I Require a Cooking Fire";
+                                break;
+                            default:
+                                out << "|cffff0000I Require Spell Focus on " << spellInfo->RequiresSpellFocus;
+                        }
+                        TellMaster(out.str().c_str());
+                        break;
+                    }
                    default:
                        //DEBUG_LOG ("[%s] SMSG_CAST_FAIL: unknown (%u)",m_bot->GetName(),result);
                        return;
@@ -3347,6 +3375,29 @@ void PlayerbotAI::UpdateAI(const uint32 /*p_time*/)
            m_targetGuidCommand = ObjectGuid();
        }

+        else if ( m_botState == BOTSTATE_CRAFT)
+        {
+            SpellEntry const* spellInfo = sSpellStore.LookupEntry(m_CurrentlyCastingSpellId);
+            if (!spellInfo)
+                return;
+
+            Spell *spell = new Spell(m_bot, spellInfo, false);
+            if (!spell)
+                return;
+
+            if (GetSpellCharges(m_CurrentlyCastingSpellId) == 0 || !CanStore() || spell->CheckCast(true) != SPELL_CAST_OK)
+            {
+                SetState(BOTSTATE_NORMAL);
+                SetIgnoreUpdateTime(0);
+            }
+            else
+            {
+                SpellCastTargets targets;
+                spell->prepare(&targets);
+                SetIgnoreUpdateTime(3);
+            }
+        }
+
        //if master is unmounted, unmount the bot
        else if (!GetMaster()->IsMounted() && m_bot->IsMounted())
        {
@@ -3931,23 +3982,117 @@ bool PlayerbotAI::HasTool(uint32 TC)

    switch (TC)
    {
-        case TC_MINING_PICK:
+        case TC_MINING_PICK:                //  = 165
+
+            if (m_bot->HasItemTotemCategory(TC))
+                return true;
+            else
+                out << "|cffff0000I do not have a MINING PICK!";
+            break;
+
+        case TC_ARCLIGHT_SPANNER:          //  = 14
+
+            if (m_bot->HasItemTotemCategory(TC))
+                return true;
+            else
+                out << "|cffff0000I do not have an ARCLIGHT SPANNER!";
+            break;
+
+        case TC_BLACKSMITH_HAMMER:         //  = 162
+
+            if (m_bot->HasItemTotemCategory(TC))
+                return true;
+            else
+                out << "|cffff0000I do not have a BLACKSMITH's HAMMER!";
+            break;
+
+        case TC_SKINNING_KNIFE:            //  = 166
+
+            if (m_bot->HasItemTotemCategory(TC))
+                return true;
+            else
+                out << "|cffff0000I do not have a SKINNING KNIFE!";
+            break;
+
+        case TC_COPPER_ROD:                //  = 6,
+            if (m_bot->HasItemTotemCategory(TC))
+                return true;
+            else
+                out << "|cffff0000I do not have a RUNED COPPER ROD!";
+            break;
+
+        case TC_SILVER_ROD:                //  = 7,
+            if (m_bot->HasItemTotemCategory(TC))
+                return true;
+            else
+                out << "|cffff0000I do not have a RUNED SILVER ROD!";
+            break;
+
+        case TC_GOLDEN_ROD:                //  = 8,
+            if (m_bot->HasItemTotemCategory(TC))
+                return true;
+            else
+                out << "|cffff0000I do not have a RUNED GOLDEN ROD!";
+            break;
+
+        case TC_TRUESILVER_ROD:            //  = 9,
+            if (m_bot->HasItemTotemCategory(TC))
+                return true;
+            else
+                out << "|cffff0000I do not have a RUNED TRUESILVER ROD!";
+            break;
+
+        case TC_ARCANITE_ROD:              //  = 10,
+            if (m_bot->HasItemTotemCategory(TC))
+                return true;
+            else
+                out << "|cffff0000I do not have a RUNED ARCANITE ROD!";
+            break;
+
+        case TC_FEL_IRON_ROD:              //  = 41,
+            if (m_bot->HasItemTotemCategory(TC))
+                return true;
+            else
+                out << "|cffff0000I do not have a RUNED FEL IRON ROD!";
+            break;
+
+        case TC_ADAMANTITE_ROD:            //  = 62,
+            if (m_bot->HasItemTotemCategory(TC))
+                return true;
+            else
+                out << "|cffff0000I do not have a RUNED ADAMANTITE ROD!";
+            break;
+
+        case TC_ETERNIUM_ROD:              //  = 63,
+             if (m_bot->HasItemTotemCategory(TC))
+                return true;
+            else
+                out << "|cffff0000I do not have a RUNED ETERNIUM ROD!";
+            break;
+
+       case TC_RUNED_AZURITE_ROD:         //  = 101,
+            if (m_bot->HasItemTotemCategory(TC))
+                return true;
+            else
+                out << "|cffff0000I do not have a RUNED AZURITE ROD!";
+            break;

+        case TC_RUNED_COBALT_ROD:          //  = 189,
            if (m_bot->HasItemTotemCategory(TC))
                return true;
            else
-                out << "|cffffffffI do not have a pick!";
+                out << "|cffff0000I do not have a RUNED COBALT ROD!";
            break;

-        case TC_SKINNING_KNIFE:
+        case TC_RUNED_TITANIUM_ROD:        //  = 190,

            if (m_bot->HasItemTotemCategory(TC))
                return true;
            else
-                out << "|cffffffffI do not have a skinning knife!";
+                out << "|cffff0000I do not have a RUNED TITANIUM ROD!";
            break;
        default:
-            out << "|cffffffffI do not know what tool that needs!";
+            out << "|cffffffffI do not know what tool that needs! TC (" << TC << ")";
    }
    TellMaster(out.str().c_str());
    return false;
@@ -3977,6 +4122,75 @@ bool PlayerbotAI::HasSpellReagents(uint32 spellId)
    return true;
}

+uint32 PlayerbotAI::GetSpellCharges(uint32 spellId)
+{
+    const SpellEntry* const pSpellInfo = sSpellStore.LookupEntry(spellId);
+    if (!pSpellInfo)
+        return 0;
+
+    if (m_bot->CanNoReagentCast(pSpellInfo))
+        return 0;
+
+    uint32 charges = 0;
+    std::list<uint32> chargeList;
+    for (uint32 i = 0; i < MAX_SPELL_REAGENTS; ++i)
+    {
+        if (pSpellInfo->Reagent[i] <= 0)
+            continue;
+
+        uint32 totalcount = 0;
+        uint32 itemid = pSpellInfo->Reagent[i];
+        uint32 count = pSpellInfo->ReagentCount[i];
+        ItemCountInInv(itemid, totalcount);
+        chargeList.push_back((totalcount / count));
+    }
+
+    for (uint32 i = 0; i < MAX_SPELL_TOTEM_CATEGORIES; ++i)
+    {
+        if (pSpellInfo->TotemCategory[i] == 0)
+            continue;
+
+        if (!m_bot->HasItemTotemCategory(pSpellInfo->TotemCategory[i]))
+        {
+            m_noToolList.push_back(pSpellInfo->TotemCategory[i]);
+            return 0;
+        }
+    }
+
+    if (!chargeList.empty())
+    {
+        charges = chargeList.front();
+        chargeList.pop_front();
+        for (std::list<uint32>::iterator it = chargeList.begin(); it != chargeList.end(); ++it)
+            if (*it < charges)
+                charges = *it;
+    }
+    return charges;
+}
+
+void PlayerbotAI::ItemCountInInv(uint32 itemid, uint32 &count)
+{
+    for(int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i)
+    {
+        Item *pItem = m_bot->GetItemByPos( INVENTORY_SLOT_BAG_0, i );
+        if (pItem && pItem->GetEntry() == itemid && !pItem->IsInTrade())
+            count += pItem->GetCount();
+    }
+
+    for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
+    {
+        if (Bag* pBag = (Bag*)m_bot->GetItemByPos( INVENTORY_SLOT_BAG_0, i ))
+        {
+            for(uint32 j = 0; j < pBag->GetBagSize(); ++j)
+            {
+                Item* pItem = m_bot->GetItemByPos( i, j );
+                if (pItem && pItem->GetEntry() == itemid && !pItem->IsInTrade())
+                    count += pItem->GetCount();
+            }
+        }
+    }
+}
+
// extracts all item ids in format below
// I decided to roll my own extractor rather then use the one in ChatHandler
// because this one works on a const string, and it handles multiple links
@@ -6541,6 +6755,9 @@ void PlayerbotAI::HandleCommand(const std::string& text, Player& fromPlayer)
    else if (ExtractCommand("quest", input))
        _HandleCommandQuest(input, fromPlayer);

+    else if (ExtractCommand("craft", input))
+        _HandleCommandCraft(input, fromPlayer);
+
    else if (ExtractCommand("pet", input))
        _HandleCommandPet(input, fromPlayer);

@@ -7305,14 +7522,14 @@ void PlayerbotAI::_HandleCommandTalent(std::string &text, Player &fromPlayer)
                    if (!ApplyActiveTalentSpec())
                    {
                        SendWhisper("The talent spec has been set active but could not be applied. It appears something has gone awry.", fromPlayer);
-                        //DEBUG_LOG ("[PlayerbotAI]: Could set TalentSpec but could not apply it - 'talent spec #': Class: %i; chosenSpec: %li", (long)m_bot->getClass(), chosenSpec);
+                        //DEBUG_LOG ("[PlayerbotAI]: Could set TalentSpec but could not apply it - 'talent spec #': Class: %li; chosenSpec: %u", (long)m_bot->getClass(), chosenSpec);
                    }
                    InspectUpdate();
                }
                else
                {
                    SendWhisper("An error has occured. Please let a Game Master know. This error has been logged.", fromPlayer);
-                    DEBUG_LOG ("[PlayerbotAI]: Could not GetTalentSpec to set & apply - 'talent spec #': Class: %i; chosenSpec: %li", (long)m_bot->getClass(), chosenSpec);
+                    DEBUG_LOG ("[PlayerbotAI]: Could not GetTalentSpec to set & apply - 'talent spec #': Class: %li; chosenSpec: %u", (long)m_bot->getClass(), chosenSpec);
                }
            }
        }
@@ -7558,6 +7775,196 @@ void PlayerbotAI::_HandleCommandCollect(std::string &text, Player &fromPlayer)
        SendWhisper("I'm collecting nothing.", fromPlayer);
}

+void PlayerbotAI::_HandleCommandCraft(std::string &text, Player &fromPlayer)
+{
+    DEBUG_LOG("Craft (%s)",text.c_str());
+
+    std::ostringstream msg;
+    uint32 charges;
+    uint32 skill;
+    int32 category;
+    uint32 linkcount = 0;
+
+    if (ExtractCommand("alchemy", text, true)) // true -> "craft alchemy" OR "craft a"
+    {
+        if (m_bot->HasSkill(SKILL_ALCHEMY))
+        {
+            skill = SKILL_ALCHEMY;
+            category = SKILL_CATEGORY_PROFESSION;
+        }
+        else
+            return;
+    }
+    else if (ExtractCommand("blacksmithing", text, true)) // true -> "craft blacksmithing" OR "craft b"
+    {
+        if (m_bot->HasSkill(SKILL_BLACKSMITHING))
+        {
+            skill = SKILL_BLACKSMITHING;
+            category = SKILL_CATEGORY_PROFESSION;
+        }
+        else
+            return;
+    }
+    else if (ExtractCommand("cooking", text, true)) // true -> "craft cooking" OR "craft c"
+    {
+        if (m_bot->HasSkill(SKILL_COOKING))
+        {
+            skill = SKILL_COOKING;
+            category = SKILL_CATEGORY_SECONDARY;
+        }
+        else
+            return;
+    }
+    else if (ExtractCommand("engineering", text, true)) // true -> "craft engineering" OR "craft e"
+    {
+        if (m_bot->HasSkill(SKILL_ENGINEERING))
+        {
+            skill = SKILL_ENGINEERING;
+            category = SKILL_CATEGORY_PROFESSION;
+        }
+        else
+            return;
+    }
+    else if (ExtractCommand("firstaid", text, true)) // true -> "craft firstaid" OR "craft f"
+    {
+        if (m_bot->HasSkill(SKILL_FIRST_AID))
+        {
+            skill = SKILL_FIRST_AID;
+            category = SKILL_CATEGORY_SECONDARY;
+        }
+        else
+            return;
+    }
+    else if (ExtractCommand("inscription", text, true)) // true -> "craft inscription" OR "craft i"
+    {
+        if (m_bot->HasSkill(SKILL_INSCRIPTION))
+        {
+            skill = SKILL_INSCRIPTION;
+            category = SKILL_CATEGORY_PROFESSION;
+        }
+        else
+            return;
+    }
+    else if (ExtractCommand("jewelcrafting", text, true)) // true -> "craft jewelcrafting" OR "craft j"
+    {
+        if (m_bot->HasSkill(SKILL_JEWELCRAFTING))
+        {
+            skill = SKILL_JEWELCRAFTING;
+            category = SKILL_CATEGORY_PROFESSION;
+        }
+        else
+            return;
+    }
+    else if (ExtractCommand("leatherworking", text, true)) // true -> "craft leatherworking" OR "craft l"
+    {
+        if (m_bot->HasSkill(SKILL_LEATHERWORKING))
+        {
+            skill = SKILL_LEATHERWORKING;
+            category = SKILL_CATEGORY_PROFESSION;
+        }
+        else
+            return;
+    }
+    else if (ExtractCommand("magic", text, true)) // true -> "craft magic" OR "craft m"
+    {
+        if (m_bot->HasSkill(SKILL_ENCHANTING))
+        {
+            skill = SKILL_ENCHANTING;
+            category = SKILL_CATEGORY_PROFESSION;
+        }
+        else
+            return;
+    }
+    else if (ExtractCommand("smelting", text, true)) // true -> "craft smelting" OR "craft s"
+    {
+        if (m_bot->HasSkill(SKILL_MINING))
+        {
+            skill = SKILL_MINING;
+            category = SKILL_CATEGORY_PROFESSION;
+        }
+        else
+            return;
+    }
+    else if (ExtractCommand("tailoring", text, true)) // true -> "craft tailoring" OR "craft t"
+    {
+        if (m_bot->HasSkill(SKILL_TAILORING))
+        {
+            skill = SKILL_TAILORING;
+            category = SKILL_CATEGORY_PROFESSION;
+        }
+        else
+            return;
+    }
+    else
+    {
+        uint32 spellId;
+        extractSpellId(text, spellId);
+
+        SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
+        if (!spellInfo)
+            return;
+
+        if (text.find("all",0) != std::string::npos)
+        {
+            m_CurrentlyCastingSpellId = spellId;
+            SetState(BOTSTATE_CRAFT);
+        }
+        else
+        {
+            SpellCastTargets targets;
+            Spell *spell = new Spell(m_bot, spellInfo, false);
+            spell->prepare(&targets);
+        }
+        return;
+    }
+
+    m_spellsToLearn.clear();
+    m_bot->skill(m_spellsToLearn);
+    SendWhisper("I can create:\\n", fromPlayer);
+    ChatHandler ch(&fromPlayer);
+    for (std::list<uint32>::iterator it = m_spellsToLearn.begin(); it != m_spellsToLearn.end(); ++it)
+    {
+        SkillLineEntry const *SkillLine = sSkillLineStore.LookupEntry(*it);
+
+        if (SkillLine->categoryId == category && *it == skill)
+        {
+            for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
+            {
+                SkillLineAbilityEntry const *SkillAbility = sSkillLineAbilityStore.LookupEntry(j);
+                if (!SkillAbility)
+                    continue;
+
+                SpellEntry const* spellInfo = sSpellStore.LookupEntry(SkillAbility->spellId);
+                if (!spellInfo)
+                    continue;
+
+                if (IsPrimaryProfessionSkill(*it) && spellInfo->Effect[EFFECT_INDEX_0] != SPELL_EFFECT_CREATE_ITEM)
+                    continue;
+
+                if (SkillAbility->skillId == *it && m_bot->HasSpell(SkillAbility->spellId) && SkillAbility->forward_spellid == 0 && ((SkillAbility->classmask & m_bot->getClassMask()) == 0))
+                {
+                    MakeSpellLink(spellInfo, msg);
+                    ++linkcount;
+                    if ((charges = GetSpellCharges(SkillAbility->spellId)) > 0)
+                        msg << "[" << charges << "]";
+                    if (linkcount >= 20)
+                    {
+                        ch.SendSysMessage(msg.str().c_str());
+                        linkcount = 0;
+                        msg.str("");
+                    }
+                }
+            }
+        }
+    }
+    m_noToolList.unique();
+    for (std::list<uint32>::iterator it = m_noToolList.begin(); it != m_noToolList.end(); it++)
+        HasTool(*it);
+    ch.SendSysMessage(msg.str().c_str());
+    m_noToolList.clear();
+    m_spellsToLearn.clear();
+}
+
void PlayerbotAI::_HandleCommandQuest(std::string &text, Player &fromPlayer)
{
    std::ostringstream msg;
@@ -8350,6 +8757,28 @@ void PlayerbotAI::_HandleCommandHelp(std::string &text, Player &fromPlayer)
            return;
        }
    }
+    if (bMainHelp || ExtractCommand("craft", text))
+    {
+        ch.SendSysMessage(_HandleCommandHelpHelper("craft ", "I will create a single specified recipe", HL_RECIPE).c_str());
+        ch.SendSysMessage(_HandleCommandHelpHelper("craft [RECIPE] all", "I will create all specified recipes").c_str());
+
+        if (!bMainHelp)
+        {
+            ch.SendSysMessage(_HandleCommandHelpHelper("craft < alchemy | a >", "List all learnt alchemy recipes").c_str());
+            ch.SendSysMessage(_HandleCommandHelpHelper("craft < blacksmithing | b >", "List all learnt blacksmith recipes").c_str());
+            ch.SendSysMessage(_HandleCommandHelpHelper("craft < cooking | c >", "List all learnt cooking recipes").c_str());
+            ch.SendSysMessage(_HandleCommandHelpHelper("craft < engineering | e >", "List all learnt engineering recipes").c_str());
+            ch.SendSysMessage(_HandleCommandHelpHelper("craft < firstaid | f >", "List all learnt firstaid recipes").c_str());
+            ch.SendSysMessage(_HandleCommandHelpHelper("craft < inscription | i >", "List all learnt inscription recipes").c_str());
+            ch.SendSysMessage(_HandleCommandHelpHelper("craft < jewelcrafting | j >", "List all learnt jewelcrafting recipes").c_str());
+            ch.SendSysMessage(_HandleCommandHelpHelper("craft < leatherworking | l >", "List all learnt leatherworking recipes").c_str());
+            ch.SendSysMessage(_HandleCommandHelpHelper("craft < magic | m >", "List all learnt enchanting recipes").c_str());
+            ch.SendSysMessage(_HandleCommandHelpHelper("craft < smelting | s >", "List all learnt mining recipes").c_str());
+            ch.SendSysMessage(_HandleCommandHelpHelper("craft < tailoring | t >", "List all learnt tailoring recipes").c_str());
+            if (text != "") ch.SendSysMessage(sInvalidSubcommand.c_str());
+            return;
+        }
+    }
    if (bMainHelp || ExtractCommand("cast", text))
    {
        ch.SendSysMessage(_HandleCommandHelpHelper("cast", "I will cast the spell or ability listed.", HL_SPELL).c_str());
@@ -8781,6 +9210,12 @@ std::string PlayerbotAI::_HandleCommandHelpHelper(std::string sCommand, std::str
            if (bReqLinkMultiples)
                oss << " [AUCTION] ..";
        }
+        else if (reqLink == HL_RECIPE)
+        {
+            oss << " [RECIPE]";
+            if (bReqLinkMultiples)
+                oss << " [RECIPE] ..";
+        }
        else
        {
            oss << " {unknown}";
diff --git a/src/game/playerbot/PlayerbotAI.h b/src/game/playerbot/PlayerbotAI.h
index b5f36eb..89b91de 100644
--- a/src/game/playerbot/PlayerbotAI.h
+++ b/src/game/playerbot/PlayerbotAI.h
@@ -1473,7 +1473,8 @@ public:
        BOTSTATE_DEAD,              // we are dead and wait for becoming ghost
        BOTSTATE_DEADRELEASED,      // we released as ghost and wait to revive
        BOTSTATE_LOOTING,           // looting mode, used just after combat
-        BOTSTATE_FLYING             // bot is flying
+        BOTSTATE_FLYING,            // bot is flying
+        BOTSTATE_CRAFT              // bot is crafting
    };

    enum CollectionFlags
@@ -1561,7 +1562,8 @@ public:
        HL_SPELL,
        HL_TARGET,
        HL_NAME,
-        HL_AUCTION
+        HL_AUCTION,
+        HL_RECIPE
    };

public:
@@ -1672,6 +1674,8 @@ public:

    bool HasTool(uint32 TC);
    bool HasSpellReagents(uint32 spellId);
+    void ItemCountInInv(uint32 itemid, uint32 &count);
+    uint32 GetSpellCharges(uint32 spellId);

    uint8 GetHealthPercent(const Unit& target) const;
    uint8 GetHealthPercent() const;
@@ -1832,6 +1836,7 @@ private:
    void _HandleCommandGet(std::string &text, Player &fromPlayer);
    void _HandleCommandCollect(std::string &text, Player &fromPlayer);
    void _HandleCommandQuest(std::string &text, Player &fromPlayer);
+    void _HandleCommandCraft(std::string &text, Player &fromPlayer);
    void _HandleCommandPet(std::string &text, Player &fromPlayer);
    void _HandleCommandSpells(std::string &text, Player &fromPlayer);
    void _HandleCommandSurvey(std::string &text, Player &fromPlayer);
@@ -1891,6 +1896,7 @@ private:
    ObjectGuid m_lootPrev;              // previous loot
    BotEntryList m_collectObjects;      // object entries searched for in findNearbyGO
    BotTaxiNode m_taxiNodes;            // flight node chain;
+    BotEntryList m_noToolList;          // list of required tools

    uint8 m_collectionFlags;            // what the bot should look for to loot
    uint32 m_collectDist;               // distance to collect objects

copy this to an empty file and save. Then apply from your <source root>, where 'bot_readme.txt' is located

Hope this helps

Link to comment
Share on other sites

1/ Is it possible to auto-invite bots in a party as we invoke them into the game ?

2/ What's the differences between portal and new-ai ? Is new-ai "unofficial" ?

1) you can create a macro,

.bot add one

.bot add two

/invite one

/invite two

but you will find that it will probably complain that bot 'one' or 'two' are not yet online, the first time you apply it. It will work the second time. It's difficult to introduce a delay into macros without problems. Perhaps you might wish to look into this, I've tried.

2) 'portal' or more correctly portal 'master' contain our beta test code. 'new-ai' is one of our alpha branches that contains untested code that isn't yet ready for general testing. Every so often we will merge the contents of these branches into portal 'master'. You are free to use the code on the alpha branches but any feedback you provide is for the developers information only (minimal support).

Hope this helps

Link to comment
Share on other sites

Hi,

Check the end of the patch you copied from the thread. Just in case you might have included some text from the post in the patch. I did the same when I tried it. You should just have only the 3 line pattern at the end.

@@ -1891,6 +1896,7 @@ private:

ObjectGuid m_lootPrev; // previous loot

BotEntryList m_collectObjects; // object entries searched for in findNearbyGO

BotTaxiNode m_taxiNodes; // flight node chain;

+ BotEntryList m_noToolList; // list of required tools

uint8 m_collectionFlags; // what the bot should look for to loot

uint32 m_collectDist; // distance to collect objects

I know it works, I've just merged and compiled it ;)

You might also check that your text editor isn't adding something to the patch.

Link to comment
Share on other sites

Oh Boy,

Do you ever get days when your computer does your head in.

I got exactly what you got using notepad on xp.

fatal: corrupt patch at line 612

It appears that you need to insert a newline at the end of the file before saving it. You also need to save the file with 'Unicode' encoding. It then applies O.K

Mangos w/ Playerbot (Portal) and then switching to New-Ai: Works

Ah! I see you appear to have got it to work.

Hope this helps

Link to comment
Share on other sites

hi i did a fresh pull and merged with new-ai and mangos main and build failed

1>..\\..\\src\\mangosd\\Master.cpp(480): error C2065: 'REVISION_DB_PLAYERBOTAI' : undeclared identifier WheatyExceptionReport.cpp 1>Done Building Project "D:\\Server_stuff\\Mangos\\mangos_playerbot\\win\\VC100\\mangosd.vcxproj" (build target(s)) -- FAILED. Build FAILED.

Link to comment
Share on other sites

I highly recommend using Notepad++ for editing MaNGOS code in Windows. It is highly configurable and comes with many document templates, such as C++, to prevent encoding errors when doing cross-platform development.

Just be sure that whatever editor you use, to set Tab as four spaces. This follows MaNGOS coding style standards.

Then there's properly configuring Git for cross-platform. There used to be a document detailing Git config and MaNGOS coding standards on their Lighthouse page, but it has long since been closed. Good thing I kept an archive of it! The following does have some edits of my own, for clarity and additional information not originally included.

Configuring Git

The first thing you do should be configure a real name and email. By default, Git chooses a default

name based on the GECOS data (which is probably right) and a default email based on your login and

hostname (which is almost certainly wrong). Best practices dictate you use your real name and email

here, not your login, IRC handle, or any other aliases you may have. But you'll notice some do prefer

using an alias they've already established in a developer community, like MaNGOS. These fields will be

immortalized in the repository history so make sure you get them right. Windows users must set their

identity manually anyways.

$ git config --global user.name Your Name

$ git config --global user.email [email protected]ess

While you’re configuring, you may want to enable coloring for some commands:

$ git config --global color.diff auto

$ git config --global color.status auto

$ git config --global color.branch auto

$ git config --global color.interactive auto

If you prefer to use an editor other than the default Vi :

$ git config --global core.editor emacs (or whatever it is you prefer)

Finally, to properly handle line feeds between Windows and Linux, Windows users can use the following setting:

$ git config --global core.autocrlf auto

It is NOT recommended to set autocrlf to "true" as this forces converting CRLF into LF, which has been known to cause issues.

Linux users can set Git to automatically fix CRLF that can sometimes sneak in when a Windows user makes a commit by converting them into standard LF when making a commit:

$ git config --global core.autocrlf input

The above autocrlf settings should resolve line ending conflicts between Windows and Linux.

Link to comment
Share on other sites

Awww... i ran into compile errors again :(

10>..\\..\\src\\game\\playerbot\\PlayerbotAI.cpp(8490) : error C2039: 'isProvidedReqLevel': is not an element of 'TrainerSpell'

10> g:\\gameserver\\wow\\core\\mangos\\emu\\src\\game\\Creature.h(362): See Declaration of 'TrainerSpell'

10>..\\..\\src\\game\\playerbot\\PlayerbotAI.cpp(8492) : error C2660: 'Player::GetTrainerSpellState': function does not accept 2 Arguments

Link to comment
Share on other sites

The sharedbots branch in the portal repo is the official version for Playerbot.

There are some security issues presented when using bots from other accounts. It's rather difficult to prevent other players from using the summon bot command to activate bots from other accounts, even if the account does not belong to that player. If you don't mind such "borrowing" bots from other accounts, or you're the only person playing on your server, then it's not a problem.

Aside from that, the only other issue you may encounter is overloading your server by having too many active bots.

Link to comment
Share on other sites

Awww... i ran into compile errors again :(

10>..\\..\\src\\game\\playerbot\\PlayerbotAI.cpp(8490) : error C2039: 'isProvidedReqLevel': is not an element of 'TrainerSpell'

10> g:\\gameserver\\wow\\core\\mangos\\emu\\src\\game\\Creature.h(362): See Declaration of 'TrainerSpell'

10>..\\..\\src\\game\\playerbot\\PlayerbotAI.cpp(8492) : error C2660: 'Player::GetTrainerSpellState': function does not accept 2 Arguments

Hi,

All solved now. Sorry, in the excitment to change playerbot code I didn't sync the repositories with the core. Before this merge, the code was merged with MaNGOS [11846] that wouldn't include the TrainerSpell changes. So if you tried to compile the code on any branch as is, you would receive the error you got. All repositories are now merged with MaNGOS [11863]

Hope this helps

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use