View Single Post
  #15  
Old 07-10-2011, 03:55 PM
Criimson
Hill Giant
 
Join Date: Sep 2006
Posts: 172
Default

Quote:
Originally Posted by lerxst2112 View Post
You might try making a unified diff which is very easy to apply using tortoise or patch. Another benefit is that it will include some context lines for people trying to apply the changes manually.
Thank you
I'll try that. Never made one before and just googled how.

Criimson

EDIT:
Here is the tortoise diff

Code:
Index: bot.cpp
===================================================================
--- bot.cpp	(revision 1958)
+++ bot.cpp	(working copy)
@@ -1212,7 +1212,8 @@
 			mitigation += GetLevel() * 13/10;	//the 13/10 might be wrong, but it is close...
 	}
 	int displayed = 0;
-	displayed += ((avoidance+mitigation)*1000)/847;	//natural AC
+	//displayed += ((avoidance+mitigation)*1000)/847;
+	displayed += ((avoidance+mitigation)*500)/950;	//natural AC
 
 	//Iksar AC, untested
 	if(GetRace() == IKSAR)
@@ -10076,6 +10077,7 @@
 		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 [hair|haircolor|beard|beardcolor|face|eyes|heritage|tattoo|details <value>] - Change your BOTs appearance.");
+		c->Message(0, "#bot setfollowdistance ### - sets target bots follow distance to ### (ie 30 or 250).");
 		// TODO:
 		// c->Message(0, "#bot illusion <bot/client name or target> - Enchanter Bot cast an illusion buff spell on you or your target.");
 		c->Message(0, "#bot pull [<bot name>] [target] - Bot Pulling Target NPC's");
@@ -10453,6 +10455,31 @@
 		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], "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 +10937,14 @@
 							Tracker = g->members[i];
 							TrackerClass = RANGER;
 							break;
+							//Criimson: Reordered code - was giving priority to bard
+						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;
 					}
@@ -11346,9 +11375,17 @@
 		else {
 			if(c->IsGrouped()) {
 				Group *g = c->GetGroup();
+				bool DoesGroupHaveEnchanter = false;
 
 				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)) {
+					if(g && g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == ENCHANTER)) {
+						DoesGroupHaveEnchanter = true;
+					}
+				}
+
+				for(int i=0; i<MAX_GROUP_MEMBERS; i++) {
+					//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 +11393,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) && (DoesGroupHaveEnchanter == 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.");*/
 				}
@@ -13255,7 +13309,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 +13355,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 +13433,7 @@
 	return false;
 }
 
+
 Mob* EntityList::GetMobByBotID(uint32 botID) {
 	Mob* Result = 0;
 
Index: bot.h
===================================================================
--- bot.h	(revision 1958)
+++ 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 1958)
+++ botspellsai.cpp	(working copy)
@@ -253,6 +253,29 @@
 							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:
+							//TODO: Include mana regen (breeze/clarity/etc), I don't know what spell effect it is
+							if(IsEffectInSpell(selectedBotSpell.SpellId, SE_IncreaseSpellHaste) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ManaPool))
+							{
+								continue;
+							}
+							break;
+						case ARCHETYPE_HYBRID:
+							//Hybrids get all buffs
+						default:
+							break;
+					}
+
 					if(CheckSpellRecastTimers(this, itr->SpellIndex))
 					{
 
@@ -297,6 +320,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);
@@ -532,16 +566,18 @@
 
 					Mob* addMob = GetFirstIncomingMobToMez(this, botSpell);
 
-					if(!addMob)
-						break;
+					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;
-							}
+			}
 		default: {
 			break;
 					  }
@@ -722,6 +758,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 +1349,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 1958)
+++ 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 1958)
+++ 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; }
Reply With Quote