rendered paste bodyIndex: src/game/Creature.cpp
===================================================================
--- src/game/Creature.cpp (revision 6319)
+++ src/game/Creature.cpp (working copy)
@@ -629,9 +629,31 @@
GossipOption* gso;
GossipOption* ingso;
+ CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(GetEntry());
+ std::string ScriptName = cinfo->ScriptName;
+ if(cinfo->npcflag == 1 && ScriptName == "script_bot_giver")
+ {
+ if(!pPlayer->HaveBot())
+ {
+ pm->GetGossipMenu()->AddMenuItem((uint8)9, "Recruit Warrior", 60000, 60000, "Recruit Warrior", false);
+ pm->GetGossipMenu()->AddMenuItem((uint8)9, "Recruit Hunter", 60001, 60001, "Recruit Hunter", false);
+ pm->GetGossipMenu()->AddMenuItem((uint8)9, "Recruit Paladin", 60002, 60002, "Recruit Paladin", false);
+ //pm->GetGossipMenu()->AddMenuItem((uint8)9, "Recruit Deathknight", 60003, 60003, "Recruit Deathknight", false);
+ pm->GetGossipMenu()->AddMenuItem((uint8)9, "Recruit Shaman", 60004, 60004, "Recruit Shaman", false);
+ pm->GetGossipMenu()->AddMenuItem((uint8)9, "Recruit Rogue", 60005, 60005, "Recruter Rogue", false);
+ pm->GetGossipMenu()->AddMenuItem((uint8)3, "Recruit Druid", 60006, 60006, "Recruit Druid", false);
+ pm->GetGossipMenu()->AddMenuItem((uint8)3, "Recruit Mage", 60007, 60007, "Recruit Mage", false);
+ pm->GetGossipMenu()->AddMenuItem((uint8)3, "Recruter Priest", 60008, 60008, "Recruter Priest", false);
+ pm->GetGossipMenu()->AddMenuItem((uint8)3, "Recruit Warlock", 60009, 60009, "Recruit Warlock", false);
+ }
+ else
+ pm->GetGossipMenu()->AddMenuItem((uint8)0, "Do you want to abandon your recruit?", 60010, 60010, "Do you want to abandon your recruit?", false);
+ }
+
for( GossipOptionList::iterator i = m_goptions.begin( ); i != m_goptions.end( ); i++ )
{
gso=&*i;
+
if(gso->GossipId == gossipid)
{
bool cantalking=true;
@@ -700,6 +722,7 @@
case GOSSIP_OPTION_STABLEPET:
case GOSSIP_OPTION_TABARDDESIGNER:
case GOSSIP_OPTION_AUCTIONEER:
+ case GOSSIP_OPTION_BOT:
break; // no checks
default:
sLog.outErrorDb("Creature %u (entry: %u) have unknown gossip option %u",GetGUIDLow(),GetCreatureInfo()->Entry,gso->Action);
@@ -833,6 +856,8 @@
player->GetSession()->SendBattlegGroundList( GetGUID(), bgTypeId );
break;
}
+ case GOSSIP_OPTION_BOT:
+ break;
default:
OnPoiSelect( player, gossip );
break;
Index: src/game/Creature.h
===================================================================
--- src/game/Creature.h (revision 6319)
+++ src/game/Creature.h (working copy)
@@ -53,7 +53,8 @@
GOSSIP_OPTION_STABLEPET = 14, //UNIT_NPC_FLAG_STABLE = 8192,
GOSSIP_OPTION_ARMORER = 15, //UNIT_NPC_FLAG_ARMORER = 16384,
GOSSIP_OPTION_UNLEARNTALENTS = 16, //UNIT_NPC_FLAG_TRAINER (bonus option for GOSSIP_OPTION_TRAINER)
- GOSSIP_OPTION_UNLEARNPETSKILLS = 17 //UNIT_NPC_FLAG_TRAINER (bonus option for GOSSIP_OPTION_TRAINER)
+ GOSSIP_OPTION_UNLEARNPETSKILLS = 17, //UNIT_NPC_FLAG_TRAINER (bonus option for GOSSIP_OPTION_TRAINER)
+ GOSSIP_OPTION_BOT = 100
};
enum Gossip_Guard
Index: src/game/NPCHandler.cpp
===================================================================
--- src/game/NPCHandler.cpp (revision 6319)
+++ src/game/NPCHandler.cpp (working copy)
@@ -285,7 +285,15 @@
if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
- if( unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider())
+ CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(unit->GetEntry());
+ std::string ScriptName = cinfo->ScriptName;
+ if(cinfo->npcflag == 1 && ScriptName == "script_bot_giver")
+ {
+ _player->TalkedToCreature(unit->GetEntry(),unit->GetGUID());
+ unit->prepareGossipMenu(_player,GOSSIP_OPTION_BOT);
+ unit->sendPreparedGossip( _player );
+ }
+ else if( unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider())
{
unit->StopMoving();
//npcIsStopped[unit->GetGUID()] = true;
@@ -343,7 +351,102 @@
// remove fake death
if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ uint32 entry = 0;
+ uint32 BoTclass = 0;
+ uint32 BoTrace = 0;
+ switch(_player->PlayerTalkClass->GossipOptionSender(option))
+ {
+ case 60000: BoTclass = 1; break;
+ case 60001: BoTclass = 3; break;
+ case 60002: BoTclass = 2; break;
+ /* case 60003: BoTclass = 6; break; */ //DEATH KNIGHT
+ case 60004: BoTclass = 7; break;
+ case 60005: BoTclass = 4; break;
+ case 60006: BoTclass = 11; break;
+ case 60007: BoTclass = 8; break;
+ case 60008: BoTclass = 5; break;
+ case 60009: BoTclass = 9; break;
+ case 60010:
+ {
+ //Abandon of bot
+ if(GetPlayer()->HaveBot())
+ {
+ Creature* m_bot = GetPlayer()->GetBot();
+ GetPlayer()->m_bot->DealDamage(GetPlayer()->m_bot, GetPlayer()->m_bot->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ GetPlayer()->m_bot->RemoveFromWorld();
+ GetPlayer()->RemoveBot();
+ GetPlayer()->PlayerTalkClass->CloseGossip();
+ }
+ GetPlayer()->PlayerTalkClass->CloseGossip();
+ break;
+ }
+ default:
+ break;
+ }
+
+ if(!GetPlayer()->HaveBot() && (_player->PlayerTalkClass->GossipOptionSender(option) != 60010)
+ && (_player->PlayerTalkClass->GossipOptionSender(option) >= 60000))
+ {
+ entry = 0;
+ QueryResult *coucount = NULL;
+ if(GetPlayer()->GetTeam()==ALLIANCE)
+ coucount = WorldDatabase.PQuery("SELECT count(entry) FROM creature_template WHERE scriptname = 'script_bot' and class = %u and (race = 1 or race = 3 or race = 4 or race = 7 or race = 11)", BoTclass);
+ else if(GetPlayer()->GetTeam()==HORDE)
+ coucount = WorldDatabase.PQuery("SELECT count(entry) FROM creature_template WHERE scriptname = 'script_bot' and class = %u and (race = 2 or race = 5 or race = 6 or race = 8 or race = 10)", BoTclass);
+
+ if(coucount)
+ {
+ uint32 ranrand = coucount->Fetch()[0].GetUInt32();
+
+ uint32 m_rand = uint32(rand() % ranrand) + 1;
+
+ QueryResult *result = NULL;
+
+ if(GetPlayer()->GetTeam()==ALLIANCE)
+ result = WorldDatabase.PQuery("SELECT entry, race FROM creature_template WHERE scriptname = 'script_bot' and class = %u and (race = 1 or race = 3 or race = 4 or race = 7 or race = 11)", BoTclass);
+ else if(GetPlayer()->GetTeam()==HORDE)
+ result = WorldDatabase.PQuery("SELECT entry, race FROM creature_template WHERE scriptname = 'script_bot' and class = %u and (race = 2 or race = 5 or race = 6 or race = 8 or race = 10)", BoTclass);
+ uint32 tmp_rand = 0;
+ do
+ {
+ Field *fields = result->Fetch();
+ entry = fields[0].GetUInt32();
+ BoTrace = fields[1].GetUInt32();
+ tmp_rand++;
+ if(tmp_rand == m_rand)
+ break;
+ }while (result->NextRow());
+
+ delete result;
+ delete coucount;
+ }
+ }
+
+ if(!GetPlayer()->HaveBot() && (_player->PlayerTalkClass->GossipOptionSender(option) != 60010)
+ && (_player->PlayerTalkClass->GossipOptionSender(option) >= 60000)
+ && (entry != 0))
+ {
+ Creature* BoT = GetPlayer()->SummonCreature(entry/*must be in DB*/, unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetOrientation(),TEMPSUMMON_DEAD_DESPAWN,0);
+ GetPlayer()->SetBot(BoT);
+ GetPlayer()->SetBotClass(BoTclass);
+ GetPlayer()->SetBotRace(BoTrace);
+ BoT->SetCharmerGUID(GetPlayer()->GetGUID());
+ BoT->CombatStop();
+ BoT->DeleteThreatList();
+ BoT->AIM_Initialize();
+ CharmInfo *charmInfoBoT = BoT->InitCharmInfo(BoT);
+ BoT->setFaction(GetPlayer()->getFaction());
+ charmInfoBoT->SetReactState( REACT_AGGRESSIVE );
+ charmInfoBoT->SetCommandState( COMMAND_FOLLOW );
+ GetPlayer()->PlayerTalkClass->CloseGossip();
+ }
+ else if((entry != 0) && (GetPlayer()->HaveBot()))
+ {
+ GetPlayer()->PlayerTalkClass->CloseGossip();
+ }
+
if(!code.empty())
{
Index: src/game/Player.cpp
===================================================================
--- src/game/Player.cpp (revision 6319)
+++ src/game/Player.cpp (working copy)
@@ -330,6 +330,7 @@
m_lastDailyQuestTime = 0;
m_regenTimer = 0;
+
m_weaponChangeTimer = 0;
m_breathTimer = 0;
m_isunderwater = 0;
@@ -417,6 +418,17 @@
m_miniPet = 0;
m_bgAfkReportedTimer = 0;
+
+ ///////////////////// Bot System ////////////////////////
+
+ m_botTimer = 0;
+ m_bot = NULL;
+ m_bot_form = 0;
+ m_bot_race = 0;
+ m_bot_class = 0;
+ m_bot_must_wait_for_spell_1 = 0;
+ m_bot_must_wait_for_spell_2 = 0;
+ m_bot_must_wait_for_spell_3 = 0;
}
Player::~Player ()
@@ -456,6 +468,14 @@
for(size_t x = 0; x < ItemSetEff.size(); x++)
if(ItemSetEff[x])
delete ItemSetEff[x];
+
+ if(HaveBot())
+ {
+ Creature* m_bot = GetBot();
+ m_bot->DealDamage(m_bot, m_bot->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ m_bot->RemoveFromWorld();
+ RemoveBot();
+ }
}
void Player::CleanupsBeforeDelete()
@@ -1078,6 +1098,14 @@
m_regenTimer -= p_time;
}
+ if(m_botTimer > 0)
+ {
+ if(p_time >= m_botTimer)
+ m_botTimer = 0;
+ else
+ m_botTimer -= p_time;
+ }
+
if (m_weaponChangeTimer > 0)
{
if(p_time >= m_weaponChangeTimer)
@@ -1111,6 +1139,7 @@
if (isAlive())
{
RegenerateAll();
+ RefreshBot();
}
if (m_deathState == JUST_DIED)
@@ -1731,6 +1760,647 @@
m_regenTimer = regenDelay;
}
+void Player::RefreshBot()
+{
+ if (m_botTimer != 0)
+ return;
+ uint32 refreshDelay = 100;
+
+ if(HaveBot())
+ {
+ Creature* m_bot = GetBot();
+ if(!m_bot->isAlive())
+ {
+ m_bot->RemoveFromWorld();
+ RemoveBot();
+ }
+ }
+
+ if(HaveBot())
+ {
+ //CHANGELEVEL SUPPORT
+ Creature* m_bot = GetBot();
+ if(m_bot->getLevel() != getLevel())
+ {
+ //DATABASE STATS
+ PlayerLevelInfo info;
+ objmgr.GetPlayerLevelInfo(GetBotRace(),GetBotClass(),getLevel(),&info);
+
+ PlayerClassLevelInfo classInfo;
+ objmgr.GetPlayerClassLevelInfo(GetBotClass(),getLevel(),&classInfo);
+
+ m_bot->SetLevel(getLevel());
+
+ //player -> m_bot->UpdateAllStats
+ for (int i = STAT_STRENGTH; i < MAX_STATS; i++)
+ {
+ //float value = m_bot->GetTotalStatValue(Stats(i));
+ //m_bot->SetStat(Stats(i), (int32)value);
+ m_bot->SetStat(Stats(i), info.stats[i]);
+ }
+
+ //player -> m_bot->UpdateAttackPowerAndDamage();
+ float val2 = 0.0f;
+ float level = float(m_bot->getLevel());
+
+ UnitMods unitMod = UNIT_MOD_ATTACK_POWER;
+
+ uint16 index = UNIT_FIELD_ATTACK_POWER;
+ uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS;
+ uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER;
+
+ switch(m_bot->getClass())
+ {
+ case CLASS_WARRIOR: val2 = level*3.0f + m_bot->GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ case CLASS_PALADIN: val2 = level*3.0f + m_bot->GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ case CLASS_ROGUE: val2 = level*2.0f + m_bot->GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break;
+ case CLASS_HUNTER: val2 = level*2.0f + m_bot->GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break;
+ case CLASS_SHAMAN: val2 = level*2.0f + m_bot->GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ //case CLASS_DRUID: val2 = m_bot->GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ case CLASS_DRUID:
+ {
+ //Check if Predatory Strikes is skilled
+ float mLevelMult = 0.0;
+ /*switch(m_bot->m_form)
+ {
+ case FORM_CAT:
+ case FORM_BEAR:
+ case FORM_DIREBEAR:
+ case FORM_MOONKIN:
+ {
+ Unit::AuraList const& mDummy = m_bot->GetAurasByType(SPELL_AURA_DUMMY);
+ for(Unit::AuraList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
+ {
+ // Predatory Strikes
+ if ((*itr)->GetSpellProto()->SpellIconID == 1563)
+ {
+ mLevelMult = (*itr)->GetModifier()->m_amount / 100.0f;
+ break;
+ }
+ }
+ break;
+ }
+ }*/
+ switch(GetBotForm())
+ {
+ case 892:
+ case 8571:
+ val2 = m_bot->getLevel()*(mLevelMult+2.0f) + m_bot->GetStat(STAT_STRENGTH)*2.0f + m_bot->GetStat(STAT_AGILITY) - 20.0f; break;
+ case 2281:
+ case 2289:
+ val2 = m_bot->getLevel()*(mLevelMult+3.0f) + m_bot->GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ /*case FORM_MOONKIN:
+ val2 = m_bot->getLevel()*(mLevelMult+1.5f) + m_bot->GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;*/
+ default:
+ val2 = m_bot->GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
+ }
+ break;
+ }
+ case CLASS_MAGE: val2 = m_bot->GetStat(STAT_STRENGTH) - 10.0f; break;
+ case CLASS_PRIEST: val2 = m_bot->GetStat(STAT_STRENGTH) - 10.0f; break;
+ case CLASS_WARLOCK: val2 = m_bot->GetStat(STAT_STRENGTH) - 10.0f; break;
+ }
+
+ m_bot->SetModifierValue(unitMod, BASE_VALUE, val2);
+ float base_attPower = m_bot->GetModifierValue(unitMod, BASE_VALUE) * m_bot->GetModifierValue(unitMod, BASE_PCT);
+ float attPowerMod = m_bot->GetModifierValue(unitMod, TOTAL_VALUE);
+
+ float attPowerMultiplier = m_bot->GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
+
+ m_bot->SetUInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field
+ m_bot->SetUInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field
+ m_bot->SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
+
+ //automatically update weapon damage after attack power modification
+ m_bot->UpdateDamagePhysical(BASE_ATTACK);
+
+ //player -> m_bot->UpdateAttackPowerAndDamage(true); // ---> STUPID CREATURE CAN NOT BE RANGED
+
+ //player -> m_bot->UpdateArmor();
+ float value = 0.0f;
+ unitMod = UNIT_MOD_ARMOR;
+
+ value = m_bot->GetModifierValue(unitMod, BASE_VALUE); // base armor (from items)
+ value *= m_bot->GetModifierValue(unitMod, BASE_PCT); // armor percent from items
+ value += m_bot->GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats
+ value += m_bot->GetModifierValue(unitMod, TOTAL_VALUE);
+
+ //add dynamic flat mods
+ /*AuraList const& mResbyIntellect = GetAurasByType(SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT);
+ for(AuraList::const_iterator i = mResbyIntellect.begin();i != mResbyIntellect.end(); ++i)
+ if((*i)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)
+ value += int32(GetStat(STAT_INTELLECT) * (*i)->GetModifier()->m_amount / 100.0f);*/
+
+ value *= m_bot->GetModifierValue(unitMod, TOTAL_PCT);
+
+ m_bot->SetArmor(int32(value));
+
+ //player -> m_bot->UpdateMaxHealth();
+ unitMod = UNIT_MOD_HEALTH;
+
+ value = 0.0f;
+ //value = m_bot->GetModifierValue(unitMod, BASE_VALUE) /*+ m_bot->GetCreateHealth()*/;
+ value = classInfo.basehealth;
+ value *= m_bot->GetModifierValue(unitMod, BASE_PCT);
+
+ //player -> m_bot->GetHealthBonusFromStamina()
+ float stamina = m_bot->GetStat(STAT_STAMINA);
+
+ float baseStam = stamina < 20 ? stamina : 20;
+ float moreStam = stamina - baseStam;
+
+ value += m_bot->GetModifierValue(unitMod, TOTAL_VALUE) + baseStam + (moreStam*10.0f);
+ value *= m_bot->GetModifierValue(unitMod, TOTAL_PCT);
+
+ m_bot->SetMaxHealth((uint32)value);
+ //SOMETHING IS BAD HERE...
+ for(int i = POWER_MANA; i < MAX_POWERS; i++)
+ {
+ //player -> m_bot->UpdateMaxPower(Powers(i));
+ UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + Powers(i));
+
+ //player -> m_bot->GetManaBonusFromIntellect()
+ float bonusPower = 0;
+ if(i == POWER_MANA)
+ {
+ float intellect = GetStat(STAT_INTELLECT);
+ float baseInt = intellect < 20 ? intellect : 20;
+ float moreInt = intellect - baseInt;
+ //float bonusPower = (i == POWER_MANA) ? (baseInt + (moreInt*15.0f)) : 0;
+ bonusPower = (baseInt + (moreInt*15.0f));
+ float value = 0.0f;
+ value = classInfo.basemana;
+ value *= m_bot->GetModifierValue(unitMod, BASE_PCT);
+ value += m_bot->GetModifierValue(unitMod, TOTAL_VALUE) + bonusPower;
+ value *= m_bot->GetModifierValue(unitMod, TOTAL_PCT);
+ m_bot->SetMaxPower(Powers(i), uint32(value));
+ }
+ else
+ {
+ m_bot->SetMaxPower(Powers(i), uint32(classInfo.basemana));
+ }
+ }
+
+ /*ONLY FOR PLAYER*/
+ /*player -> m_bot->UpdateAllCritPercentages();
+ player -> m_bot->UpdateAllSpellCritChances();
+ player -> m_bot->UpdateDefenseBonusesMod();
+ UpdateShieldBlockValue();
+ UpdateSpellDamageAndHealingBonus();
+ UpdateManaRegen();
+ UpdateExpertise(BASE_ATTACK);
+ UpdateExpertise(OFF_ATTACK);
+ for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
+ UpdateResistances(i);*/
+
+ m_bot->SetHealth(GetMaxHealth());
+ m_bot->SetPower(POWER_MANA, m_bot->GetMaxPower(POWER_MANA));
+ m_bot->SetPower(POWER_ENERGY, m_bot->GetMaxPower(POWER_ENERGY));
+ if(m_bot->GetPower(POWER_RAGE) > m_bot->GetMaxPower(POWER_RAGE))
+ m_bot->SetPower(POWER_RAGE, m_bot->GetMaxPower(POWER_RAGE));
+ m_bot->SetPower(POWER_FOCUS, 0);
+ m_bot->SetPower(POWER_HAPPINESS, 0);
+ }
+
+ //MOUNT SUPPORT
+ if(IsMounted() && !m_bot->IsMounted())
+ {
+ int m_mount = 0;
+ int m_rand = rand()%100;
+
+ if(m_rand < 33)
+ m_mount = 1;
+ else if(m_rand > 64)
+ m_mount = 2;
+ else
+ m_mount = 3;
+
+ if((GetBotClass()==11) && (GetBotRace()==4) && (m_bot->getLevel()<60))
+ m_mount = 0;
+ if((GetBotClass()==11) && (GetBotRace()==6) && (m_bot->getLevel()<60))
+ m_mount = 0;
+
+ switch(GetBotRace())
+ {
+ case 1: //Humain
+ {
+ if(getLevel() < 60)
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(2409); break;
+ case 2: m_bot->Mount(2404); break;
+ case 3: m_bot->Mount(2405); break;
+ default : break;
+ }
+ }
+ else
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(14338); break;
+ case 2: m_bot->Mount(14583); break;
+ case 3: m_bot->Mount(14582); break;
+ default : break;
+ }
+ }
+ break;
+ }
+ case 2: //Orc
+ {
+ if(getLevel() < 60)
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(247); break;
+ case 2: m_bot->Mount(2327); break;
+ case 3: m_bot->Mount(2328); break;
+ default : break;
+ }
+ }
+ else
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(14575); break;
+ case 2: m_bot->Mount(14574); break;
+ case 3: m_bot->Mount(14573); break;
+ default : break;
+ }
+ }
+ break;
+ }
+ case 3: //Nain
+ {
+ if(getLevel() < 60)
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(2785); break;
+ case 2: m_bot->Mount(2786); break;
+ case 3: m_bot->Mount(2736); break;
+ default : break;
+ }
+ }
+ else
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(14347); break;
+ case 2: m_bot->Mount(14576); break;
+ case 3: m_bot->Mount(14346); break;
+ default : break;
+ }
+ }
+ break;
+ }
+ case 4: //Elfe de la Nuit
+ {
+ if(getLevel() < 60)
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(6080); break;
+ case 2: m_bot->Mount(6448); break;
+ case 3: m_bot->Mount(6444); break;
+ default : break;
+ }
+ }
+ else
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(14632); break;
+ case 2: m_bot->Mount(14332); break;
+ case 3: m_bot->Mount(14331); break;
+ default : break;
+ }
+ }
+ break;
+ }
+ case 5: //Mort Vivant
+ {
+ if(getLevel() < 60)
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(10670); break;
+ case 2: m_bot->Mount(10671); break;
+ case 3: m_bot->Mount(10672); break;
+ default : break;
+ }
+ }
+ else
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(10721); break;
+ case 2: m_bot->Mount(10720); break;
+ case 3: m_bot->Mount(10719); break;
+ default : break;
+ }
+ }
+ break;
+ }
+ case 6: //Tauren
+ {
+ if(getLevel() < 60)
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(12246); break;
+ case 2: m_bot->Mount(11641); break;
+ case 3: m_bot->Mount(12245); break;
+ default : break;
+ }
+ }
+ else
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(14579); break;
+ case 2: m_bot->Mount(14349); break;
+ case 3: m_bot->Mount(14578); break;
+ default : break;
+ }
+ }
+ break;
+ }
+ case 7: //Gnome
+ {
+ if(getLevel() < 60)
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(9473); break;
+ case 2: m_bot->Mount(10661); break;
+ case 3: m_bot->Mount(6569); break;
+ default : break;
+ }
+ }
+ else
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(14376); break;
+ case 2: m_bot->Mount(14374); break;
+ case 3: m_bot->Mount(14377); break;
+ default : break;
+ }
+ }
+ break;
+ }
+ case 8: //Troll
+ {
+ if(getLevel() < 60)
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(6472); break;
+ case 2: m_bot->Mount(4806); break;
+ case 3: m_bot->Mount(6473); break;
+ default : break;
+ }
+ }
+ else
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(14344); break;
+ case 2: m_bot->Mount(14339); break;
+ case 3: m_bot->Mount(14342); break;
+ default : break;
+ }
+ }
+ break;
+ }
+ case 10: //Elfe de Sang
+ {
+ if(getLevel() < 60)
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(18696); break;
+ case 2: m_bot->Mount(19480); break;
+ case 3: m_bot->Mount(19478); break;
+ default : break;
+ }
+ }
+ else
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(19484); break;
+ case 2: m_bot->Mount(18697); break;
+ case 3: m_bot->Mount(19482); break;
+ default : break;
+ }
+ }
+ break;
+ }
+ case 11: //Draenei
+ {
+ if(getLevel() < 60)
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(17063); break;
+ case 2: m_bot->Mount(19870); break;
+ case 3: m_bot->Mount(19869); break;
+ default : break;
+ }
+ }
+ else
+ {
+ switch(m_mount)
+ {
+ case 1: m_bot->Mount(19871); break;
+ case 2: m_bot->Mount(19872); break;
+ case 3: m_bot->Mount(19873); break;
+ default : break;
+ }
+ }
+ break;
+ }
+
+ }
+ /*NOT REALY SUPPORTED BY CLIENT BUT IT WORKS SO...*/
+ m_bot->SetSpeed(MOVE_RUN, GetSpeed(MOVE_RUN), true);
+ }
+
+ if(!IsMounted() && m_bot->IsMounted())
+ {
+ m_bot->Unmount();
+ CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(m_bot->GetEntry());
+ m_bot->SetSpeed(MOVE_RUN, cinfo->speed, true);
+ }
+
+ //SPELL AI CUSTOM SUPPORT
+ switch(GetBotClass())
+ {
+ case 9: //WARLOCK SUMMON & DOT SUPPORT
+ {
+ //MIDNESS SPELL
+ if((GetBotMustWaitForSpell2() == 0) && (m_bot->isInCombat()) && (m_bot->GetHealth() > (m_bot->GetMaxHealth())/2))
+ {
+ Creature* Summon1 = m_bot->SummonCreature(4677, m_bot->GetPositionX() - 2, m_bot->GetPositionY(), m_bot->GetPositionZ(), m_bot->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,20000);
+ Summon1->setFaction(getFaction());
+ Summon1->SetLevel(getLevel());
+ Summon1->CombatStop();
+ Summon1->DeleteThreatList();
+ Summon1->AIM_Initialize();
+ Summon1->SetCharmerGUID(m_bot->GetGUID());
+ CharmInfo *charmInfoSummon1 = Summon1->InitCharmInfo(Summon1);
+ charmInfoSummon1->SetReactState( REACT_AGGRESSIVE );
+ charmInfoSummon1->SetCommandState( COMMAND_FOLLOW );
+
+ SetBotMustWaitForSpell2(30000);
+ }
+ //MORE POWERFULL SPELL
+ else if((GetBotMustWaitForSpell3() == 0) && (m_bot->isInCombat()) && (m_bot->GetHealth() < (m_bot->GetMaxHealth())/4))
+ {
+ Creature* Summon1 = m_bot->SummonCreature(89, m_bot->GetPositionX(), m_bot->GetPositionY() + 2, m_bot->GetPositionZ(), m_bot->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,20000);
+ Summon1->setFaction(getFaction());
+ Summon1->SetLevel(getLevel());
+ Summon1->CombatStop();
+ Summon1->DeleteThreatList();
+ Summon1->AIM_Initialize();
+ Summon1->SetCharmerGUID(m_bot->GetGUID());
+ CharmInfo *charmInfoSummon1 = Summon1->InitCharmInfo(Summon1);
+ charmInfoSummon1->SetReactState( REACT_AGGRESSIVE );
+ charmInfoSummon1->SetCommandState( COMMAND_FOLLOW );
+
+ Creature* Summon2 = m_bot->SummonCreature(89, m_bot->GetPositionX() + 2, m_bot->GetPositionY(), m_bot->GetPositionZ(), m_bot->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,20000);
+ Summon2->setFaction(getFaction());
+ Summon2->SetLevel(getLevel());
+ Summon2->CombatStop();
+ Summon2->DeleteThreatList();
+ Summon2->AIM_Initialize();
+ Summon1->AIM_Initialize();
+ Summon2->SetCharmerGUID(m_bot->GetGUID());
+ CharmInfo *charmInfoSummon2 = Summon2->InitCharmInfo(Summon2);
+ charmInfoSummon2->SetReactState( REACT_AGGRESSIVE );
+ charmInfoSummon2->SetCommandState( COMMAND_FOLLOW );
+
+ Creature* Summon3 = m_bot->SummonCreature(89, m_bot->GetPositionX() - 2, m_bot->GetPositionY(), m_bot->GetPositionZ(), m_bot->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,20000);
+ Summon3->setFaction(getFaction());
+ Summon3->SetLevel(getLevel());
+ Summon3->CombatStop();
+ Summon3->DeleteThreatList();
+ Summon3->AIM_Initialize();
+ Summon3->AIM_Initialize();
+ Summon3->SetCharmerGUID(m_bot->GetGUID());
+ CharmInfo *charmInfoSummon3 = Summon3->InitCharmInfo(Summon3);
+ charmInfoSummon3->SetReactState( REACT_AGGRESSIVE );
+ charmInfoSummon3->SetCommandState( COMMAND_FOLLOW );
+
+ SetBotMustWaitForSpell3(120000);
+ }
+ break;
+ }
+ case 11: //DRUID FORM SUPPORT
+ {
+ CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(m_bot->GetEntry());
+ uint32 m_old_bot_form = m_bot->GetDisplayId();
+
+ if((GetBotMustWaitForSpell1() == 0) && (m_bot->IsInWater()))
+ {
+ if((GetBotRace()==4) && (m_bot->GetDisplayId()!=2428))
+ m_bot->SetDisplayId(2428);
+ if((GetBotRace()==6) && (m_bot->GetDisplayId()!=2428))
+ m_bot->SetDisplayId(2428);
+ SetBotForm(m_bot->GetDisplayId());
+ SetBotMustWaitForSpell1(3000);
+ }
+ else if((GetBotMustWaitForSpell1() == 0) && (m_bot->isInCombat()))
+ {
+ if((GetBotRace()==4) && (m_bot->GetDisplayId()!=2281))
+ m_bot->SetDisplayId(2281);
+ if((GetBotRace()==6) && (m_bot->GetDisplayId()!=2289))
+ m_bot->SetDisplayId(2289);
+ SetBotForm(m_bot->GetDisplayId());
+ SetBotMustWaitForSpell1(3000);
+ }
+ else if((GetBotMustWaitForSpell1() == 0) && (((IsMounted()) && (m_bot->getLevel()<60)) || (m_form == FORM_TRAVEL)))
+ {
+ if((GetBotRace()==4) && (m_bot->GetDisplayId()!=632))
+ m_bot->SetDisplayId(632);
+ if((GetBotRace()==6) && (m_bot->GetDisplayId()!=632))
+ m_bot->SetDisplayId(632);
+ SetBotForm(m_bot->GetDisplayId());
+ SetBotMustWaitForSpell1(3000);
+ }
+ else if((GetBotMustWaitForSpell1() == 0) && (m_form == FORM_CAT))
+ {
+ if((GetBotRace()==4) && (m_bot->GetDisplayId()!=892))
+ m_bot->SetDisplayId(892);
+ if((GetBotRace()==6) && (m_bot->GetDisplayId()!=8571))
+ m_bot->SetDisplayId(8571);
+ SetBotForm(m_bot->GetDisplayId());
+ SetBotMustWaitForSpell1(3000);
+ }
+
+ if(m_old_bot_form != GetBotForm())
+ {
+ m_bot->SetSpeed(MOVE_SWIM, cinfo->speed, true);
+ m_bot->SetSpeed(MOVE_RUN, cinfo->speed, true);
+ if(GetBotForm() == 2428)
+ m_bot->SetSpeed(MOVE_SWIM, cinfo->speed * 1.50f, true);
+ if( (GetBotForm()==2281) || (GetBotForm()==2289) )
+ {/* EMPTY : BOOST BEAR*/}
+ if(GetBotForm()==632)
+ m_bot->SetSpeed(MOVE_RUN, GetSpeed(MOVE_RUN), true);
+ if( (GetBotForm()==892) || (GetBotForm()==8571) )
+ m_bot->SetSpeed(MOVE_RUN, GetSpeed(MOVE_RUN), true);
+ }
+
+ //RESET FORMS
+ if( (!m_bot->IsInWater()) && (!m_bot->isInCombat()) && (!IsMounted()) && (m_form != FORM_TRAVEL) && (m_form != FORM_CAT) )
+ {
+ if((GetBotRace()==4) && (m_bot->GetDisplayId()!=cinfo->DisplayID_A))
+ m_bot->SetDisplayId(cinfo->DisplayID_A);
+ if((GetBotRace()==6) && (m_bot->GetDisplayId()!=cinfo->DisplayID_H))
+ m_bot->SetDisplayId(cinfo->DisplayID_H);
+ m_bot->SetSpeed(MOVE_SWIM, cinfo->speed, true);
+ m_bot->SetSpeed(MOVE_RUN, cinfo->speed, true);
+ SetBotForm(m_bot->GetDisplayId());
+ }
+
+ //SPECIAL SPELL FOR DRUID
+ if((GetBotMustWaitForSpell2() == 0) && (GetHealth() < GetMaxHealth()/2))
+ {
+ if((GetBotRace()==4) && (m_bot->GetDisplayId()!=cinfo->DisplayID_A))
+ m_bot->SetDisplayId(cinfo->DisplayID_A);
+ if((GetBotRace()==6) && (m_bot->GetDisplayId()!=cinfo->DisplayID_H))
+ m_bot->SetDisplayId(cinfo->DisplayID_H);
+ SetBotForm(m_bot->GetDisplayId());
+ m_bot->SetSpeed(MOVE_SWIM, cinfo->speed, true);
+ m_bot->SetSpeed(MOVE_RUN, cinfo->speed, true);
+ m_bot->SendHealSpellLog(this, 5185, (m_bot->getLevel() / 2) * 100);
+ SetHealth(GetHealth() + (m_bot->getLevel() / 2) * 100);
+ SetBotMustWaitForSpell2(5000);
+ }
+ break;
+ }
+ }//END SWITCH
+ }
+
+ if(GetBotMustWaitForSpell1() != 0)
+ {
+ SetBotMustWaitForSpell1(GetBotMustWaitForSpell1() - refreshDelay);
+ }
+ if(GetBotMustWaitForSpell2() != 0)
+ {
+ SetBotMustWaitForSpell2(GetBotMustWaitForSpell2() - refreshDelay);
+ }
+ if(GetBotMustWaitForSpell3() != 0)
+ {
+ SetBotMustWaitForSpell3(GetBotMustWaitForSpell3() - refreshDelay);
+ }
+
+ m_botTimer = refreshDelay;
+}
+
void Player::Regenerate(Powers power)
{
uint32 curValue = GetPower(power);
Index: src/game/Player.h
===================================================================
--- src/game/Player.h (revision 6319)
+++ src/game/Player.h (working copy)
@@ -1275,9 +1275,11 @@
void SendPetSkillWipeConfirm();
void CalcRage( uint32 damage,bool attacker );
void RegenerateAll();
+ void RefreshBot();
void Regenerate(Powers power);
void RegenerateHealth();
void setRegenTimer(uint32 time) {m_regenTimer = time;}
+ void setBotTimer(uint32 time) {m_botTimer = time;}
void setWeaponChangeTimer(uint32 time) {m_weaponChangeTimer = time;}
uint32 GetMoney() { return GetUInt32Value (PLAYER_FIELD_COINAGE); }
@@ -1965,6 +1967,8 @@
GridReference<Player> &GetGridRef() { return m_gridRef; }
+ bool HaveBot(){if(m_bot==NULL) return false; else return true;}
+
protected:
/*********************************************************/
@@ -2187,6 +2191,42 @@
float m_summon_x;
float m_summon_y;
float m_summon_z;
+
+ /*********************************************************/
+ /*** BOT SYSTEM ***/
+ /*********************************************************/
+
+ Creature* m_bot;
+ uint8 m_bot_class;
+ uint8 m_bot_race;
+ uint32 m_bot_form; //Only for Druid
+ uint32 m_bot_must_wait_for_spell_1; //in ms
+ uint32 m_bot_must_wait_for_spell_2; //in ms
+ uint32 m_bot_must_wait_for_spell_3; //in ms
+ uint32 m_botTimer;
+
+ Creature* GetBot(){return m_bot;}
+ void SetBot(Creature* bot){m_bot = bot;}
+ void RemoveBot(){ m_bot = NULL; m_bot_class = 0; m_bot_race = 0; m_bot_form = 0;
+ m_bot_must_wait_for_spell_1 = 0; m_bot_must_wait_for_spell_2 = 0;
+ m_bot_must_wait_for_spell_3 = 0;
+ }
+
+ uint8 GetBotClass(){return m_bot_class;}
+ uint8 GetBotRace(){return m_bot_race;}
+ uint32 GetBotForm(){return m_bot_form;}
+
+ void SetBotClass(uint8 botclass){m_bot_class = botclass;}
+ void SetBotRace(uint8 botrace){m_bot_race = botrace;}
+ void SetBotForm(uint32 form){m_bot_form = form;}
+
+ void SetBotMustWaitForSpell1(uint32 wait){m_bot_must_wait_for_spell_1 = wait;}
+ uint32 GetBotMustWaitForSpell1(){return m_bot_must_wait_for_spell_1;}
+ void SetBotMustWaitForSpell2(uint32 wait){m_bot_must_wait_for_spell_2 = wait;}
+ uint32 GetBotMustWaitForSpell2(){return m_bot_must_wait_for_spell_2;}
+ void SetBotMustWaitForSpell3(uint32 wait){m_bot_must_wait_for_spell_3 = wait;}
+ uint32 GetBotMustWaitForSpell3(){return m_bot_must_wait_for_spell_3;}
+
private:
// internal common parts for CanStore/StoreItem functions
uint8 _CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountVec& dest, ItemPrototype const *pProto, uint32& count, bool swap, Item *pSrcItem ) const;