Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Server Code Submissions

Reply
 
Thread Tools Display Modes
  #1  
Old 07-16-2011, 09:09 PM
Criimson
Hill Giant
 
Join Date: Sep 2006
Posts: 172
Default 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
Reply With Quote
  #2  
Old 07-17-2011, 02:13 PM
Congdar
Developer
 
Join Date: Jul 2007
Location: my own little world
Posts: 751
Default

added to svn 1974
__________________
The Realm
Reply With Quote
  #3  
Old 07-17-2011, 03:05 PM
Derision
Developer
 
Join Date: Feb 2004
Location: UK
Posts: 1,540
Default

I think the setfollowdistance command needs to check that the player issuing the command actually owns the bot he has targetted ?
Reply With Quote
  #4  
Old 07-17-2011, 03:25 PM
Criimson
Hill Giant
 
Join Date: Sep 2006
Posts: 172
Default

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


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 12:02 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3