EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Development::Server Code Submissions (https://www.eqemulator.org/forums/forumdisplay.php?f=669)
-   -   COMMITTED: Various bot tweaks (https://www.eqemulator.org/forums/showthread.php?t=33868)

Criimson 07-16-2011 09:09 PM

COMMITTED: Various bot tweaks
 
Hello everyone

Here are some bot code changes that I'd like to submit.
Pfyon has approved his code changes which are included.

Here is the change log:

Quote:

Bot Code Changes:

Pfyon's Archetype code - ie Warriors won't get KEI and wizards won't get attack haste
Pfyon's Cleric Mana Code - Cleric will stop DDing at 75% mana

Enchanter Mana Code - Enchanter will stop DDing at 75% mana
Enchanter will stop casting Rune at 75% mana (can still use #bot runeme)

Corrected Tracking Priority - Ranger > Druid > Bard

Tweaked Calm - Only one Bot will cast and Enchanter has priority

Enchanters will automatically cast mez (v1 - will tweak urgency and add AoE)

Added bot command setfollowdistance - allows spacing of bots behind player

Altered shrinkme command to shrink - allows target shrink (I play a dwarf )

Changed healing so hybrids wont start healing until health < 20%

Added check in slows - if a BST is grouped with a shaman or chanter they wont try to slow
The .patch was created with the most recent svn 1971

Code:

Index: bot.cpp
===================================================================
--- bot.cpp        (revision 1971)
+++ bot.cpp        (working copy)
@@ -5,6 +5,7 @@
 #include "doors.h"
 #include "QuestParserCollection.h"
 
+
 // This constructor is used during the bot create command
 Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, 0, 0, 0, 0, 0, 0, false), rest_timer(1) {
        if(botOwner) {
@@ -3559,7 +3560,7 @@
                ns->spawn.is_npc = 0;                                // 0=no, 1=yes
                ns->spawn.is_pet = 0;
                ns->spawn.guildrank = 0;
-                ns->spawn.showhelm = 1;
+                ns->spawn.showhelm = 1;  //I had this changed to 0 as I dont like helms
                ns->spawn.flymode = 0;
                ns->spawn.size = 0;
                ns->spawn.NPC = 0;                                        // 0=player,1=npc,2=pc corpse,3=npc corpse
@@ -10075,6 +10076,7 @@
                c->Message(0, "#bot group help - Displays the commands available to manage any BOTs in your group.");
                c->Message(0, "#bot botgroup help - Displays the commands available to manage BOT ONLY groups.");
                c->Message(0, "#bot mana [<bot name or target> | all] - Displays a mana report for all your spawned bots.");
+                c->Message(0, "#bot setfollowdistance ### - sets target bots follow distance to ### (ie 30 or 250).");
                c->Message(0, "#bot [hair|haircolor|beard|beardcolor|face|eyes|heritage|tattoo|details <value>] - Change your BOTs appearance.");
                // TODO:
                // c->Message(0, "#bot illusion <bot/client name or target> - Enchanter Bot cast an illusion buff spell on you or your target.");
@@ -10117,6 +10119,21 @@
                }
                return;
        }
+
+        //Criimson added Bot follow distance - SetFollowDistance
+        if(!strcasecmp(sep->arg[1], "setfollowdistance")) {
+                if((c->GetTarget() == NULL) || (c->GetTarget() == c) || (!c->GetTarget()->IsBot()) ) {
+                        c->Message(15, "You must target a bot!");
+                }
+                else {
+                        int32 BotFollowDistance = atoi(sep->arg[2]);
+                        c->GetTarget()->SetFollowDistance(BotFollowDistance);
+
+                }
+
+                return;
+        }
+
       
        if(!strcasecmp(sep->arg[1], "augmentitem")) {
                AugmentItem_Struct* in_augment = new AugmentItem_Struct[sizeof(AugmentItem_Struct)];
@@ -10453,6 +10470,17 @@
                return;
        }
 
+        if(!strcasecmp(sep->arg[1], "picklock")) {
+                if((c->GetTarget() == NULL) || (c->GetTarget() == c) || !c->GetTarget()->IsBot() || (c->GetTarget()->GetClass() != ROGUE)) {
+                        c->Message(15, "You must target a rogue bot!");
+                }
+                else {
+                        entity_list.BotPickLock(c->GetTarget()->CastToBot());
+                }
+
+                return;
+        }
+
        if(!strcasecmp(sep->arg[1], "archery")) {
                if((c->GetTarget() == NULL) || (c->GetTarget() == c) || !c->GetTarget()->IsBot()) {
                        c->Message(15, "You must target a bot!");
@@ -10910,6 +10938,13 @@
                                                        Tracker = g->members[i];
                                                        TrackerClass = RANGER;
                                                        break;
+                                                case DRUID:
+                                                        // Unless we have a ranger, druid is next best.
+                                                        if(TrackerClass != RANGER) {
+                                                                Tracker = g->members[i];
+                                                                TrackerClass = DRUID;
+                                                        }
+                                                        break;
                                                case BARD:
                                                        // If we haven't found a tracker yet, use bard.
                                                        if(TrackerClass == 0) {
@@ -10917,13 +10952,7 @@
                                                                TrackerClass = BARD;
                                                        }
                                                        break;
-                                                case DRUID:
-                                                        // Unless we have a ranger, druid is next best.
-                                                        if(TrackerClass != RANGER) {
-                                                                Tracker = g->members[i];
-                                                                TrackerClass = DRUID;
-                                                        }
-                                                        break;
+                       
                                                default:
                                                        break;
                                        }
@@ -11348,7 +11377,8 @@
                                Group *g = c->GetGroup();
 
                                for(int i=0; i<MAX_GROUP_MEMBERS; i++) {
-                                        if(g && g->members[i] && g->members[i]->IsBot() && ((g->members[i]->GetClass() == ENCHANTER) || g->members[i]->GetClass() == CLERIC)) {
+                                        //Criimson - seperated cleric and chanter so chanter is primary
+                                        if(g && g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == ENCHANTER)) {
                                                Bot *pacer = g->members[i]->CastToBot();
                                                pacer->Say("Trying to pacify %s \n", target->GetCleanName());
 
@@ -11356,12 +11386,29 @@
                                                        if(target->FindType(SE_Lull) || target->FindType(SE_Harmony) || target->FindType(SE_Calm))
                                                        //if(pacer->IsPacified(target))
                                                                c->Message(0, "I have successfully pacified %s.", target->GetCleanName());
+                                                                return;
                                                        /*else
                                                                c->Message(0, "I failed to pacify %s.", target->GetCleanName());*/
                                                }
                                                else
                                                        c->Message(0, "I failed to pacify %s.", target->GetCleanName());
                                        }
+                                        //Criimson - seperated cleric and chanter so chanter is primary
+                                        if(g && g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == CLERIC) && (GroupHasEnchanterClass(g) == false)) {
+                                                Bot *pacer = g->members[i]->CastToBot();
+                                                pacer->Say("Trying to pacify %s \n", target->GetCleanName());
+
+                                                if(pacer->Bot_Command_CalmTarget(target)) {
+                                                        if(target->FindType(SE_Lull) || target->FindType(SE_Harmony) || target->FindType(SE_Calm))
+                                                        //if(pacer->IsPacified(target))
+                                                                c->Message(0, "I have successfully pacified %s.", target->GetCleanName());
+                                                                return;
+                                                        /*else
+                                                                c->Message(0, "I failed to pacify %s.", target->GetCleanName());*/
+                                                }
+                                                else
+                                                        c->Message(0, "I failed to pacify %s.", target->GetCleanName());
+                                        }
                                        /*else
                                                c->Message(15, "You must have an Enchanter or Cleric in your group.");*/
                                }
@@ -11730,12 +11777,16 @@
        }
 
        // Shrink
-        if ((!strcasecmp(sep->arg[1], "shrinkme")) && (c->IsGrouped())) {
+        if ((!strcasecmp(sep->arg[1], "shrink")) && (c->IsGrouped())) {
                Mob *Shrinker;
                int32 ShrinkerClass = 0;
                Group *g = c->GetGroup();
+                Mob *target = c->GetTarget();
 
-                if(g) {
+                if(target == NULL || (!target->IsClient() && !target->IsBot()))
+                        c->Message(15, "You must select a player or bot");
+
+                else if(g) {
                        for(int i=0; i<MAX_GROUP_MEMBERS; i++){
                                if(g->members[i] && g->members[i]->IsBot()) {
                                        switch(g->members[i]->GetClass()) {
@@ -11760,7 +11811,8 @@
                                        if (c->GetLevel() >= 15) {
                                                Shrinker->Say("Casting Shrink...");
                                                //Shrinker->CastToBot()->BotRaidSpell(345);
-                                                Shrinker->CastSpell(345, c->GetID(), 1);
+                                                //Shrinker->CastSpell(345, id), 1);
+                                                Shrinker->CastToBot()->SpellOnTarget(345, target);
                                        }
                                        else if (c->GetLevel() <= 14) {
                                                Shrinker->Say("I'm not level 15 yet.");
@@ -11772,7 +11824,8 @@
                                        if (c->GetLevel() >= 23) {
                                                Shrinker->Say("Casting Shrink...");
                                                //Shrinker->CastToBot()->BotRaidSpell(345);
-                                                Shrinker->CastSpell(345, c->GetID(), 1);
+                                                //Shrinker->CastSpell(345, id), 1);
+                                                Shrinker->CastToBot()->SpellOnTarget(345, target);
                                        }
                                        else if (c->GetLevel() <= 22) {
                                                Shrinker->Say("I'm not level 23 yet.");
@@ -13255,7 +13308,8 @@
 
        int8 botCasterClass = caster->GetClass();
 
-        if( botCasterClass == CLERIC || botCasterClass == DRUID || botCasterClass == SHAMAN || botCasterClass == PALADIN || botCasterClass == BEASTLORD || botCasterClass == RANGER) {
+        //CRIIMSON: Changed so heal based on health percentage is different for hybrids
+        if( botCasterClass == CLERIC || botCasterClass == DRUID || botCasterClass == SHAMAN) {
                //If AI_EngagedCastCheck() said to the healer that he had to heal
                if( iSpellTypes == SpellType_Heal )        {
                        // check in group
@@ -13300,6 +13354,52 @@
                }
        }
 
+                //CRIIMSON: Changed so heal based on health percentage is different for hybrids
+                if( botCasterClass == PALADIN || botCasterClass == BEASTLORD || botCasterClass == RANGER) {
+                //If AI_EngagedCastCheck() said to the healer that he had to heal
+                if( iSpellTypes == SpellType_Heal )        {
+                        // check in group
+                        if(caster->HasGroup()) {
+                                Group *g = caster->GetGroup();
+                               
+                                if(g) {
+                                        for(int i = 0; i < MAX_GROUP_MEMBERS; i++) {
+                                                if(g->members[i] && !g->members[i]->qglobal) {
+                                                        if(g->members[i]->IsClient() && g->members[i]->GetHPRatio() < 20) {
+                                                                if(caster->AICastSpell(g->members[i], iChance, SpellType_Heal))
+                                                                        return true;
+                                                        }
+                                                        else if((g->members[i]->GetClass() ==  WARRIOR || g->members[i]->GetClass() == PALADIN || g->members[i]->GetClass() == SHADOWKNIGHT) &&
+                                                                g->members[i]->GetHPRatio() < 20)
+                                                        {
+                                                                if(caster->AICastSpell(g->members[i], 100, SpellType_Heal))
+                                                                        return true;
+                                                        }
+                                                        else if(g->members[i]->GetClass() ==  ENCHANTER && g->members[i]->GetHPRatio() < 20) {
+                                                                if(caster->AICastSpell(g->members[i], 100, SpellType_Heal))
+                                                                        return true;
+                                                        }
+                                                        else if(g->members[i]->GetHPRatio() < 20) {
+                                                                if(caster->AICastSpell(g->members[i], 100, SpellType_Heal))
+                                                                        return true;
+                                                        }
+                                                }
+
+                                                if(g->members[i] && !g->members[i]->qglobal && g->members[i]->HasPet() && g->members[i]->GetPet()->GetHPRatio() < 20) {
+                                                        if(g->members[i]->GetPet()->GetOwner() != caster && caster->IsEngaged() && g->members[i]->IsCasting() && g->members[i]->GetClass() != ENCHANTER )
+                                                                continue;
+
+                                                        if(caster->AICastSpell(g->members[i]->GetPet(), 100, SpellType_Heal))
+                                                                return true;
+                                                }
+                                        }
+                                }
+                        }
+
+                        // TODO: raid heals
+                }
+        }
+       
        //Ok for the buffs..
        if( iSpellTypes == SpellType_Buff) {
                // Let's try to make Bard working...
@@ -13332,6 +13432,7 @@
        return false;
 }
 
+
 Mob* EntityList::GetMobByBotID(uint32 botID) {
        Mob* Result = 0;
 
Index: bot.h
===================================================================
--- bot.h        (revision 1971)
+++ bot.h        (working copy)
@@ -292,6 +292,7 @@
        static bool GroupHasClericClass(Group* group) { return GroupHasClass(group, CLERIC); }
        static bool GroupHasDruidClass(Group* group) { return GroupHasClass(group, DRUID); }
        static bool GroupHasShamanClass(Group* group) { return GroupHasClass(group, SHAMAN); }
+        static bool GroupHasEnchanterClass(Group* group) { return GroupHasClass(group, ENCHANTER); }
        static bool GroupHasPriestClass(Group* group) { return GroupHasClass(group, CLERIC | DRUID | SHAMAN); }
 
        // "GET" Class Methods
Index: botspellsai.cpp
===================================================================
--- botspellsai.cpp        (revision 1971)
+++ botspellsai.cpp        (working copy)
@@ -40,6 +40,39 @@
        botSpell.ManaCost = 0;
 
        switch (iSpellTypes) {
+                case SpellType_Mez: {
+                        if (tar->GetBodyType() != BT_Giant) {
+                                        if(!checked_los) {
+                                                if(!CheckLosFN(tar))
+                                                        break;        //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call
+                                               
+                                                checked_los = true;
+                                        }
+                                       
+                                        //TODO
+                                        //Check if single target or AoE mez is best
+                                        //if (TARGETS ON MT IS => 3 THEN botSpell = AoEMez)
+                                        //if (TARGETS ON MT IS <= 2 THEN botSpell = BestMez)
+
+                                        botSpell = GetBestBotSpellForMez(this);
+
+                                        if(botSpell.SpellId == 0)
+                                                break;
+
+                                        Mob* addMob = GetFirstIncomingMobToMez(this, botSpell);
+
+                                        if(!addMob){
+                                                //Say("!addMob.");
+                                                break;}
+
+                                        if(!(!addMob->IsImmuneToSpell(botSpell.SpellId, this) && addMob->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))
+                                                break;
+                                       
+                                        castedSpell = AIDoSpellCast(botSpell.SpellIndex, addMob, botSpell.ManaCost);
+
+                        }
+                        break;
+                        }
                case SpellType_Heal: {
                        if (tar->DontHealMeBefore() < Timer::GetCurrentTime()) {
                                int8 hpr = (int8)tar->GetHPRatio();
@@ -186,7 +219,7 @@
                                }
                        }
                        break;
-                                                        }
+                        }
                case SpellType_Root: {
                        if (!tar->IsRooted() && tar->DontRootMeBefore() < Timer::GetCurrentTime()) {
                                        if(!checked_los) {
@@ -214,7 +247,7 @@
                                                tar->SetDontRootMeBefore(TempDontRootMeBefore);
                        }
                        break;
-                                                        }
+                        }
                case SpellType_Buff: {
                        if (tar->DontBuffMeBefore() < Timer::GetCurrentTime()) {
                                std::list<BotSpell> buffSpellList = GetBotSpellsBySpellType(this, SpellType_Buff);
@@ -253,6 +286,35 @@
                                                        continue;
                                        }
 
+                                        switch(tar->GetArchetype())
+                                        {
+                                                case ARCHETYPE_CASTER:
+                                                        //TODO: probably more caster specific spell effects in here
+                                                        if(IsEffectInSpell(selectedBotSpell.SpellId, SE_AttackSpeed) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ATK) ||
+                                                                IsEffectInSpell(selectedBotSpell.SpellId, SE_STR) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ReverseDS))
+                                                        {
+                                                                continue;
+                                                        }
+                                                        break;
+                                                case ARCHETYPE_MELEE:
+                                                        if(IsEffectInSpell(selectedBotSpell.SpellId, SE_IncreaseSpellHaste) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaPool) ||
+                                                                IsEffectInSpell(selectedBotSpell.SpellId, SE_CurrentMana))
+                                                        {
+                                                                continue;
+                                                        }
+                                                        break;
+                                                case ARCHETYPE_HYBRID:
+                                                        //Hybrids get all buffs
+                                                default:
+                                                        break;
+                                        }
+
+                                        if(botClass == ENCHANTER && this->GetManaRatio() <= 75.0f && IsEffectInSpell(selectedBotSpell.SpellId, SE_Rune))
+                                        {
+                                                //If we're at 75% mana or below, don't rune as enchanter
+                                                break;
+                                        }
+
                                        if(CheckSpellRecastTimers(this, itr->SpellIndex))
                                        {
 
@@ -269,7 +331,7 @@
                                }
                        }
                        break;
-                                                        }
+                        }
                case SpellType_Escape: {
                        int8 hpr = (int8)GetHPRatio();
 #ifdef IPC         
@@ -286,7 +348,7 @@
                                castedSpell = AIDoSpellCast(botSpell.SpellIndex, this, botSpell.ManaCost);
                        }
                        break;
-                                                          }
+                        }
                case SpellType_Nuke: {
                        if((tar->GetHPRatio() <= 95.0f) || ((botClass == BARD) || (botClass == SHAMAN) || (botClass == ENCHANTER)))
                        {
@@ -297,6 +359,17 @@
                                        checked_los = true;
                                }
 
+                                if(botClass == CLERIC && this->GetManaRatio() <= 75.0f)
+                                {
+                                        //If we're at 75% mana or below, don't nuke as a cleric or 50% as enchanter
+                                        break;
+                                }
+                                if(botClass == ENCHANTER && this->GetManaRatio() <= 50.0f)
+                                {
+                                        //If we're at 75% mana or below, don't nuke as a cleric or 50% as enchanter
+                                        break;
+                                }
+
                                if(botClass == MAGICIAN || botClass == SHADOWKNIGHT || botClass == NECROMANCER || botClass == PALADIN || botClass == RANGER || botClass == DRUID || botClass == CLERIC) {
                                        if(tar->GetBodyType() == BT_Undead || tar->GetBodyType() == BT_SummonedUndead || tar->GetBodyType() == BT_Vampire)
                                                botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Undead);
@@ -341,7 +414,7 @@
                                castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost);
                        }
                        break;
-                                                        }
+                        }
                case SpellType_Dispel: {
                        if(tar->GetHPRatio() > 95.0f) {
                                if(!checked_los) {
@@ -363,7 +436,7 @@
                                }
                        }
                        break;
-                                                          }
+                        }
                case SpellType_Pet: {
                                //keep mobs from recasting pets when they have them.
                                if (!IsPet() && !GetPetID() && !IsBotCharmer()) {
@@ -378,7 +451,7 @@
                                        castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost);
                                }
                                break;
-                                                        }
+                                }
                case SpellType_Lifetap: {
                        if (GetHPRatio() < 90.0f) {
                                if(!checked_los) {
@@ -399,7 +472,7 @@
                                castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost);
                        }
                        break;
-                                                                }
+                        }
                case SpellType_Snare: {
                        if (tar->DontSnareMeBefore() < Timer::GetCurrentTime()) {
                                        if(!checked_los) {
@@ -425,7 +498,7 @@
                                                tar->SetDontSnareMeBefore(TempDontSnareMeBefore);
                        }
                        break;
-                                                          }
+                        }
                case SpellType_DOT: {
                        if ((tar->GetHPRatio() <= 98.0f) && (tar->DontDotMeBefore() < Timer::GetCurrentTime()) && (tar->GetHPRatio() > 15.0f)) {
                                if(!checked_los) {
@@ -467,9 +540,12 @@
                                }
                        }
                        break;
-                                                        }
+                        }
                case SpellType_Slow: {
                        if (tar->GetHPRatio() <= 99.0f) {
+                                bool GroupHasEnchanter = false;
+                                bool GroupHasShaman = false;
+
                                        if(!checked_los) {
                                                if(!CheckLosFN(tar))
                                                        break;        //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call
@@ -479,10 +555,15 @@
                                       
                                        if(botClass == SHAMAN && tar->GetDR() < tar->GetMR() && ((tar->GetMR() - tar->GetDR()) > 75)) {
                                                botSpell = GetBestBotSpellForDiseaseBasedSlow(this);
+                                                GroupHasShaman = true;
                                        }
-                                        else {
+                                        else if (botClass == ENCHANTER){
                                                botSpell = GetBestBotSpellForMagicBasedSlow(this);
+                                                GroupHasEnchanter = true;
                                        }
+                                        else if (botClass == BEASTLORD && GroupHasEnchanter == false && GroupHasShaman == false){
+                                                botSpell = GetBestBotSpellForDiseaseBasedSlow(this);
+                                        }
 
                                        if(botSpell.SpellId == 0)
                                                break;
@@ -493,7 +574,7 @@
                                        castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost);
                        }
                        break;
-                                                        }
+                        }
                case SpellType_Debuff: {
                        if((tar->GetHPRatio() <= 99.0f) || ((botClass == BARD) || (botClass == SHAMAN) || (botClass == ENCHANTER) || (botClass == DRUID)) && (tar->GetHPRatio() > 25.0f))
                        {
@@ -515,38 +596,8 @@
                                castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost);
                        }
                        break;
-                                                        }
-                case SpellType_Mez: {
-                        if (tar->GetBodyType() != BT_Giant) {
-                                        if(!checked_los) {
-                                                if(!CheckLosFN(tar))
-                                                        break;        //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call
-                                               
-                                                checked_los = true;
-                                        }
-                                       
-                                        botSpell = GetBestBotSpellForMez(this);
-
-                                        if(botSpell.SpellId == 0)
-                                                break;
-
-                                        Mob* addMob = GetFirstIncomingMobToMez(this, botSpell);
-
-                                        if(!addMob)
-                                                break;
-
-                                        if(!(!addMob->IsImmuneToSpell(botSpell.SpellId, this) && addMob->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0))
-                                                break;
-                                       
-                                        castedSpell = AIDoSpellCast(botSpell.SpellIndex, addMob, botSpell.ManaCost);
                        }
-                        break;
-                                                        }
-                default: {
-                        break;
-                                          }
-        }
-
+                }
        return castedSpell;
 }
 
@@ -722,6 +773,8 @@
 
                mlog(AI__SPELLS, "Engaged autocast check triggered (BOTS). Trying to cast healing spells then maybe offensive spells.");
 
+
+
                if(botClass == CLERIC) {
                        if(!AICastSpell(this, 100, SpellType_Heal)) {
                                if(!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) {
@@ -1311,7 +1364,7 @@
 
                std::list<NPC*> npc_list;
                entity_list.GetNPCList(npc_list);
-
+               
                for(std::list<NPC*>::iterator itr = npc_list.begin(); itr != npc_list.end(); itr++) {
                        NPC* npc = *itr;
 
Index: mob.cpp
===================================================================
--- mob.cpp        (revision 1971)
+++ mob.cpp        (working copy)
@@ -672,6 +672,53 @@
        }
 }
 
+uint8 Mob::GetArchetype() const {
+        switch(class_)
+        {
+        case PALADIN:
+        case RANGER:
+        case SHADOWKNIGHT:
+        case BARD:
+        case BEASTLORD:
+        case PALADINGM:
+        case RANGERGM:
+        case SHADOWKNIGHTGM:
+        case BARDGM:
+        case BEASTLORDGM:
+                return ARCHETYPE_HYBRID;
+                break;
+        case CLERIC:
+        case DRUID:
+        case SHAMAN:
+        case NECROMANCER:
+        case WIZARD:
+        case MAGICIAN:
+        case ENCHANTER:
+        case CLERICGM:
+        case DRUIDGM:
+        case SHAMANGM:
+        case NECROMANCERGM:
+        case WIZARDGM:
+        case MAGICIANGM:
+        case ENCHANTERGM:
+                return ARCHETYPE_CASTER;
+                break;
+        case WARRIOR:
+        case MONK:
+        case ROGUE:
+        case BERSERKER:
+        case WARRIORGM:
+        case MONKGM:
+        case ROGUEGM:
+        case BERSERKERGM:
+                return ARCHETYPE_MELEE;
+                break;
+        default:
+                return ARCHETYPE_HYBRID;
+                break;
+        }
+}
+
 void Mob::CreateSpawnPacket(EQApplicationPacket* app, Mob* ForWho) {
        app->SetOpcode(OP_NewSpawn);
        app->size = sizeof(NewSpawn_Struct);
Index: mob.h
===================================================================
--- mob.h        (revision 1971)
+++ mob.h        (working copy)
@@ -52,6 +52,18 @@
 #define CON_YELLOW                15
 #define CON_RED                        13
 
+#define APPEAR_HEIGHT        0x001d
+#define        APPEAR_HP_TIC        0x0011
+
+#define ARCHETYPE_HYBRID        1
+#define ARCHETYPE_CASTER        2
+#define ARCHETYPE_MELEE                3
+
+#define CON_GREEN                2
+#define CON_LIGHTBLUE        18
+#define CON_BLUE                4
+
+
 //LOS Parameters:
 #define HEAD_POSITION 0.9f        //ratio of GetSize() where NPCs see from
 #define SEE_POSITION 0.5f        //ratio of GetSize() where NPCs try to see for LOS
@@ -669,9 +681,10 @@
        void                        SetZone(int32 zone_id, int32 instance_id);
 
        // neotokyo: moved from client to use in NPC too
-        char GetCasterClass() const;
-        virtual sint32 CalcMaxMana();
-
+        char GetCasterClass() const;
+        uint8 GetArchetype() const;
+        virtual sint32 CalcMaxMana();
+
        inline virtual sint16        GetAC()                const { return AC + itembonuses.AC + spellbonuses.AC; } // Quagmire - this is NOT the right math
        inline virtual sint16        GetATK()        const { return ATK + itembonuses.ATK + spellbonuses.ATK; }
        inline virtual sint16        GetATKBonus()        const { return itembonuses.ATK + spellbonuses.ATK; }

the sql

Code:

INSERT INTO `npc_spells_entries` (`id`, `npc_spells_id`, `spellid`, `type`, `minlevel`, `maxlevel`) VALUES (18145, 705, 190, 2048, 47, 55);
INSERT INTO `npc_spells_entries` (`id`, `npc_spells_id`, `spellid`, `type`, `minlevel`, `maxlevel`) VALUES (18146, 705, 292, 2048, 2, 55);
INSERT INTO `npc_spells_entries` (`id`, `npc_spells_id`, `spellid`, `type`, `minlevel`, `maxlevel`) VALUES (18147, 705, 187, 2048, 13, 55);
INSERT INTO `npc_spells_entries` (`id`, `npc_spells_id`, `spellid`, `type`, `minlevel`, `maxlevel`) VALUES (18148, 705, 188, 2048, 30, 55);
INSERT INTO `npc_spells_entries` (`id`, `npc_spells_id`, `spellid`, `type`, `minlevel`) VALUES (18150, 705, 1691, 2048, 54);
INSERT INTO `npc_spells_entries` (`id`, `npc_spells_id`, `spellid`, `type`, `minlevel`) VALUES (18151, 705, 1692, 2048, 59);
INSERT INTO `npc_spells_entries` (`id`, `npc_spells_id`, `spellid`, `type`, `minlevel`) VALUES (18152, 705, 2120, 2048, 60);
INSERT INTO `npc_spells_entries` (`id`, `npc_spells_id`, `spellid`, `type`, `minlevel`) VALUES (18153, 705, 3341, 2048, 61);
INSERT INTO `npc_spells_entries` (`id`, `npc_spells_id`, `spellid`, `type`, `minlevel`) VALUES (18154, 705, 3354, 2048, 63);
INSERT INTO `npc_spells_entries` (`id`, `npc_spells_id`, `spellid`, `type`, `minlevel`) VALUES (18155, 705, 3358, 2048, 64);
INSERT INTO `npc_spells_entries` (`id`, `npc_spells_id`, `spellid`, `type`, `minlevel`) VALUES (18156, 705, 5503, 2048, 67);
INSERT INTO `npc_spells_entries` (`id`, `npc_spells_id`, `spellid`, `type`, `minlevel`) VALUES (18157, 705, 8035, 2048, 68);
INSERT INTO `npc_spells_entries` (`id`, `npc_spells_id`, `spellid`, `type`, `minlevel`) VALUES (18158, 705, 5520, 2048, 69);

UPDATE `npc_spells_entries` SET `priority`=1 WHERE `priority`=0 AND 'npc_spells_id' = 705;
UPDATE `npc_spells_entries` SET `priority`=8 WHERE `priority`=7 AND 'npc_spells_id' = 705;
UPDATE `npc_spells_entries` SET `priority`=7 WHERE `priority`=6 AND 'npc_spells_id' = 705;
UPDATE `npc_spells_entries` SET `priority`=6 WHERE `priority`=5 AND 'npc_spells_id' = 705;
UPDATE `npc_spells_entries` SET `priority`=5 WHERE `priority`=4 AND 'npc_spells_id' = 705;
UPDATE `npc_spells_entries` SET `priority`=4 WHERE `priority`=3 AND 'npc_spells_id' = 705;
UPDATE `npc_spells_entries` SET `priority`=3 WHERE `priority`=2 AND 'npc_spells_id' = 705;
UPDATE `npc_spells_entries` SET `priority`=2 WHERE `priority`=1 AND TYPE != 2048 AND 'npc_spells_id' = 705;

UPDATE `npc_spells_entries` SET `maxlevel`=12 WHERE `id`=18146 LIMIT 1;
UPDATE `npc_spells_entries` SET `maxlevel`=29 WHERE `id`=18147 LIMIT 1;
UPDATE `npc_spells_entries` SET `maxlevel`=46 WHERE `id`=18148 LIMIT 1;
UPDATE `npc_spells_entries` SET `maxlevel`=58 WHERE `id`=18150 LIMIT 1;
UPDATE `npc_spells_entries` SET `maxlevel`=59 WHERE `id`=18151 LIMIT 1;
UPDATE `npc_spells_entries` SET `maxlevel`=60 WHERE `id`=18152 LIMIT 1;
UPDATE `npc_spells_entries` SET `maxlevel`=62 WHERE `id`=18153 LIMIT 1;
UPDATE `npc_spells_entries` SET `maxlevel`=63 WHERE `id`=18154 LIMIT 1;
UPDATE `npc_spells_entries` SET `maxlevel`=66 WHERE `id`=18155 LIMIT 1;
UPDATE `npc_spells_entries` SET `maxlevel`=67 WHERE `id`=18156 LIMIT 1;
UPDATE `npc_spells_entries` SET `maxlevel`=68 WHERE `id`=18157 LIMIT 1;

Criimson

EDIT: forgot i disabled helms on bots so set it back to show helms

Congdar 07-17-2011 02:13 PM

added to svn 1974

Derision 07-17-2011 03:05 PM

I think the setfollowdistance command needs to check that the player issuing the command actually owns the bot he has targetted ? :)

Criimson 07-17-2011 03:25 PM

I added it to my code. I should be posting a code submission some time today and the change will be included.


All times are GMT -4. The time now is 06:35 PM.

Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.