SpellDesc* ArcScriptCreatureAI::AddSpell(uint32 pSpellId, TargetType pTargetType, float pChance, float pCastTime, int32 pCooldown, float pMinRange, float pMaxRange, bool pStrictRange, char* pText, TextType pTextType, uint32 pSoundId) { //Cannot add twice same spell id SpellDesc* NewSpell = FindSpellById(pSpellId); if( NewSpell ) return NewSpell; //Find spell info from spell id SpellEntry* Info = dbcSpell.LookupEntry(pSpellId); #ifdef USE_DBC_SPELL_INFO float CastTime = ( Info->CastingTimeIndex ) ? GetCastTime(dbcSpellCastTime.LookupEntry(Info->CastingTimeIndex)) : pCastTime; int32 Cooldown = Info->RecoveryTime; float MinRange = ( Info->rangeIndex ) ? GetMinRange(dbcSpellRange.LookupEntry(Info->rangeIndex)) : pMinRange; float MaxRange = ( Info->rangeIndex ) ? GetMaxRange(dbcSpellRange.LookupEntry(Info->rangeIndex)) : pMaxRange; sLog.outColor(TYELLOW, "ArcScriptCreatureAI::AddSpell(%u) : casttime=%.1f cooldown=%d minrange=%.1f maxrange=%.1f\n", pSpellId, CastTime, Cooldown, MinRange, MaxRange); #else float CastTime = pCastTime; int32 Cooldown = pCooldown; float MinRange = pMinRange; float MaxRange = pMaxRange; #endif //Create new spell NewSpell = new SpellDesc(Info, NULL, pTargetType, pChance, CastTime, Cooldown, MinRange, MaxRange, pStrictRange, pText, pTextType, pSoundId); mSpells.push_back(NewSpell); return NewSpell; }
void ObjectMgr::LoadExtraCreatureProtoStuff() { { StorageContainerIterator<CreatureProto> * itr = CreatureProtoStorage.MakeIterator(); CreatureProto * cn; while(!itr->AtEnd()) { cn = itr->Get(); if(itr->Get()->aura_string) { string auras = string(itr->Get()->aura_string); vector<string> aurs = StrSplit(auras, " "); for(vector<string>::iterator it = aurs.begin(); it != aurs.end(); ++it) { uint32 id = atol((*it).c_str()); if(id) itr->Get()->start_auras.insert( id ); } } if(!itr->Get()->MinHealth) itr->Get()->MinHealth = 1; if(!itr->Get()->MaxHealth) itr->Get()->MaxHealth = 1; if (itr->Get()->AttackType > SCHOOL_ARCANE) itr->Get()->AttackType = SCHOOL_NORMAL; cn->m_canFlee = cn->m_canRangedAttack = cn->m_canCallForHelp = false; cn->m_fleeHealth = 0.0f; // please.... m_fleeDuration is a uint32... //cn->m_fleeDuration = 0.0f; cn->m_fleeDuration = 0; if(!itr->Inc()) break; } itr->Destruct(); } { StorageContainerIterator<CreatureInfo> * itr = CreatureNameStorage.MakeIterator(); CreatureInfo * ci; while(!itr->AtEnd()) { ci = itr->Get(); ci->lowercase_name = string(ci->Name); for(uint32 j = 0; j < ci->lowercase_name.length(); ++j) ci->lowercase_name[j] = tolower(ci->lowercase_name[j]); // Darvaleo 2008/08/15 - Copied lowercase conversion logic from ItemPrototype task ci->gossip_script = sScriptMgr.GetDefaultGossipScript(); if(!itr->Inc()) break; } itr->Destruct(); } { StorageContainerIterator<Quest> * itr = QuestStorage.MakeIterator(); Quest * qst; while(!itr->AtEnd()) { qst = itr->Get(); qst->pQuestScript = NULL; if( !itr->Inc() ) break; } itr->Destruct(); } // Load AI Agents QueryResult * result = WorldDatabase.Query( "SELECT * FROM ai_agents" ); CreatureProto * cn; if( result != NULL ) { AI_Spell *sp; SpellEntry * spe; uint32 entry; if(Config.OptionsConfig.GetBoolDefault("Server", "LoadAIAgents", true)) { do { Field *fields = result->Fetch(); entry = fields[0].GetUInt32(); cn = CreatureProtoStorage.LookupEntry(entry); spe = dbcSpell.LookupEntryForced(fields[5].GetUInt32()); if( spe == NULL ) { Log.Warning("AIAgent", "For %u has nonexistant spell %u.", fields[0].GetUInt32(), fields[5].GetUInt32()); } if(!cn) continue; sp = new AI_Spell; sp->entryId = fields[0].GetUInt32(); sp->agent = fields[1].GetUInt16(); sp->procChance = fields[3].GetUInt32(); sp->procCount = fields[4].GetUInt32(); sp->spell = spe; sp->spellType = fields[6].GetUInt32(); sp->spelltargetType = fields[7].GetUInt32(); sp->cooldown = fields[8].GetUInt32(); sp->floatMisc1 = fields[9].GetFloat(); sp->autocast_type=(uint32)-1; sp->custom_pointer=false; sp->cooldowntime=getMSTime(); sp->procCounter=0; /* if (!sp->procCountDB) sp->procCount = uint32(-1); else sp->procCount = sp->procCountDB;*/ sp->Misc2 = fields[10].GetUInt32(); if(sp->agent == AGENT_SPELL) { if(!sp->spell) { //printf("SpellId %u in ai_agent for %u is invalid.\n", (unsigned int)fields[5].GetUInt32(), (unsigned int)sp->entryId); delete sp; continue; } if(sp->spell->Effect[0] == SPELL_EFFECT_LEARN_SPELL || sp->spell->Effect[1] == SPELL_EFFECT_LEARN_SPELL || sp->spell->Effect[2] == SPELL_EFFECT_LEARN_SPELL) { //printf("Teaching spell %u in ai_agent for %u\n", (unsigned int)fields[5].GetUInt32(), (unsigned int)sp->entryId); delete sp; continue; } sp->minrange = GetMinRange(dbcSpellRange.LookupEntry(sp->spell->rangeIndex)); sp->maxrange = GetMaxRange(dbcSpellRange.LookupEntry(sp->spell->rangeIndex)); //omg the poor darling has no clue about making ai_agents if(sp->cooldown==0xffffffff) { //now this will not be exact cooldown but maybe a bigger one to not make him spam spells to often int cooldown; SpellDuration *sd=dbcSpellDuration.LookupEntry(sp->spell->DurationIndex); int Dur=0; int Casttime=0;//most of the time 0 int RecoveryTime=sp->spell->RecoveryTime; if(sp->spell->DurationIndex) Dur =::GetDuration(sd); Casttime=GetCastTime(dbcSpellCastTime.LookupEntry(sp->spell->CastingTimeIndex)); cooldown=Dur+Casttime+RecoveryTime; if(cooldown<0) sp->cooldown=0;//huge value that should not loop while adding some timestamp to it else sp->cooldown=cooldown; } /* //now apply the morron filter if(sp->procChance==0) { //printf("SpellId %u in ai_agent for %u is invalid.\n", (unsigned int)fields[5].GetUInt32(), (unsigned int)sp->entryId); delete sp; continue; } if(sp->spellType==0) { //right now only these 2 are used if(IsBeneficSpell(sp->spell)) sp->spellType==STYPE_HEAL; else sp->spellType==STYPE_BUFF; } if(sp->spelltargetType==0) sp->spelltargetType = RecommandAISpellTargetType(sp->spell); */ } if(sp->agent == AGENT_RANGED) { cn->m_canRangedAttack = true; delete sp; } else if(sp->agent == AGENT_FLEE) { cn->m_canFlee = true; if(sp->floatMisc1) cn->m_canFlee = (sp->floatMisc1>0.0f ? true : false); else cn->m_fleeHealth = 0.2f; if(sp->Misc2) cn->m_fleeDuration = sp->Misc2; else cn->m_fleeDuration = 10000; delete sp; } else if(sp->agent == AGENT_CALLFORHELP) { cn->m_canCallForHelp = true; if(sp->floatMisc1) cn->m_callForHelpHealth = 0.2f; delete sp; } else { cn->spells.push_back(sp); } } while( result->NextRow() ); } delete result; } }
void AiAgentHealSupport::Update(uint32 p_time) { _UpdateTimer(p_time); _UpdateMovement(p_time); if( !m_PetOwner ) return; //oh noez, our master has abandoned us ! Where is te luv ? //we used this spell to create healbot. To avoid logout / login recreate we need to remove aura // lol, this will never work :( if( !m_Unit->isAlive() ) m_PetOwner->RemoveAura( 36765 ); if( m_Unit->GetMapMgr() != m_PetOwner->GetMapMgr() ) { m_PetOwner->RemoveAura( 36765 ); m_Unit->EventSummonPetExpire(); } if( m_Unit->isCasting() ) return; // we are already supporting someone ...get back later //we should be at same level at owner so we profit of fighting formulas same as owner if( m_Unit->GetUInt32Value( UNIT_FIELD_LEVEL ) != m_PetOwner->GetUInt32Value( UNIT_FIELD_LEVEL ) ) { m_Unit->SetUInt32Value( UNIT_FIELD_LEVEL, m_PetOwner->GetUInt32Value( UNIT_FIELD_LEVEL ) ); DifficultyLevel = m_PetOwner->GetUInt32Value( UNIT_FIELD_LEVEL ) / 80.0f; //printf("difficulty changed to %f \n",DifficultyLevel); //scale health and mana.when we level we max out our stats m_Unit->SetUInt32Value( UNIT_FIELD_MAXHEALTH , (uint32)(m_Unit->GetUInt32Value( UNIT_FIELD_BASE_HEALTH ) * ( 1 + DifficultyLevel ) * CREATURE_STATS_SCALE_WITH_DIFFICULTY) ); m_Unit->SetUInt32Value( UNIT_FIELD_MAXPOWER1 , (uint32)(m_Unit->GetUInt32Value( UNIT_FIELD_BASE_MANA ) * ( 1 + DifficultyLevel ) * CREATURE_STATS_SCALE_WITH_DIFFICULTY) ); m_Unit->SetUInt32Value( UNIT_FIELD_HEALTH , (uint32)(m_Unit->GetUInt32Value( UNIT_FIELD_HEALTH ) * ( 1 + DifficultyLevel ) * CREATURE_STATS_SCALE_WITH_DIFFICULTY) ); m_Unit->SetUInt32Value( UNIT_FIELD_POWER1 , (uint32)(m_Unit->GetUInt32Value( UNIT_FIELD_POWER1 ) * ( 1 + DifficultyLevel ) * CREATURE_STATS_SCALE_WITH_DIFFICULTY) ); } //if owner fights a long combat then we he desrvers to get lasy at the end ? if( m_PetOwner->CombatStatus.IsInCombat() ) CombatDifficultyLevel += DIFFICULTY_UPDATE_SPEED; else CombatDifficultyLevel = 0; if( CombatDifficultyLevel > 1 ) CombatDifficultyLevel = 1; uint32 Time_Now = getMSTime(); std::list<healagentspell*>::iterator itr; SpellCastTargets targets( m_PetOwner->GetGUID() ); healagentspell *m_castingSpell = NULL; Unit *SpellTarget = m_PetOwner; //poor thing died. Res him. //will never work if( !m_PetOwner->isAlive() && CheckCanCast( revive_spell.sp, SpellTarget ) ) { m_castingSpell = &revive_spell; //printf("master died, we are going to resurect him\n"); } //if we are injusred we should try to survive it if ( m_castingSpell== NULL && m_Unit->GetUInt32Value( UNIT_FIELD_HEALTH ) < m_Unit->GetUInt32Value( UNIT_FIELD_MAXHEALTH ) ) { //printf("we are injured, diff is %u \n",m_Unit->GetUInt32Value( UNIT_FIELD_MAXHEALTH ) - m_Unit->GetUInt32Value( UNIT_FIELD_HEALTH )); if( !Protect_self() ) //first we try to escape combat { m_castingSpell = PickSpellFromList( &m_healspells, m_Unit ); SpellTarget = m_Unit; } else { m_castingSpell = &m_defend_self; SpellTarget = m_Unit; } } //select an augment spell if we have nothing better to do if( m_castingSpell== NULL && m_PetOwner->GetUInt32Value( UNIT_FIELD_HEALTH ) == m_PetOwner->GetUInt32Value( UNIT_FIELD_MAXHEALTH ) ) { //printf("master is ok, we can try augment someone\n"); m_castingSpell = PickSpellFromList( &m_AugmentSelf, m_Unit ); //try augment owner ? if( !m_castingSpell ) { m_castingSpell = PickSpellFromList( &m_AugmentTarget, m_PetOwner ); SpellTarget = m_Unit; } } //master is injured, this should be most common case if( m_castingSpell==NULL && m_PetOwner->GetUInt32Value( UNIT_FIELD_HEALTH ) < m_PetOwner->GetUInt32Value( UNIT_FIELD_MAXHEALTH ) ) { //printf("master is injured, will try to heal him\n"); m_castingSpell = PickSpellFromList( &m_healspells , m_PetOwner); SpellTarget = m_PetOwner; } if( m_castingSpell ) { //printf("we have a spell to cast\n"); SpellCastTime *sd = dbcSpellCastTime.LookupEntry( m_castingSpell->sp->CastingTimeIndex ); //do not stop for instant casts if(GetCastTime(sd) != 0) { StopMovement(0); //printf("spell is not instant so we are going to stop movement \n"); } float distance = m_Unit->GetDistanceSq( SpellTarget ); if( distance <= m_castingSpell->sp->base_range_or_radius_sqr || m_castingSpell->sp->base_range_or_radius_sqr == 0 ) { //printf("we are in range and going to cast spell \n"); m_AIState = STATE_CASTING; Spell *nspell = SpellPool.PooledNew(); nspell->Init(m_Unit, m_castingSpell->sp, false, NULL); #ifdef SPELL_EFF_PCT_SCALE_WITH_DIFFICULTY if( m_castingSpell->max_scale ) { nspell->forced_basepoints[ 0 ] = (uint32)( m_castingSpell->max_scale * ( DifficultyLevel + CombatDifficultyLevel) ); if( nspell->forced_basepoints[ 0 ] > m_castingSpell->max_scale * 2) nspell->forced_basepoints[ 0 ] = m_castingSpell->max_scale * 2; } #endif targets.m_unitTarget = SpellTarget->GetGUID(); nspell->prepare( &targets ); CastSpell( m_Unit, m_castingSpell->sp, targets ); SetSpellDuration( m_castingSpell ); //mana regen is to big, he can cast forever, double mana usage maybe regulates this m_Unit->ModSignedInt32Value( UNIT_FIELD_POWER1, -m_castingSpell->sp->manaCost ); } else // Target out of Range -> Run to it { //printf("we are going to move closer \n"); m_moveRun = true; _CalcDestinationAndMove( SpellTarget, sqrt( m_castingSpell->sp->base_range_or_radius_sqr ) ); } } // check if pets regenrate mana, If not then we should implement that too //if owner is mounted then we mount too. Speed is not set though if( m_PetOwner->GetUInt32Value( UNIT_FIELD_MOUNTDISPLAYID ) && m_Unit->GetUInt32Value( UNIT_FIELD_MOUNTDISPLAYID ) == 0 ) { if( Owner_side == OWNER_SIDE_ALIANCE ) m_Unit->SetUInt32Value( UNIT_FIELD_MOUNTDISPLAYID, HELPER_MOUNT_A_DISPLAY ); else m_Unit->SetUInt32Value( UNIT_FIELD_MOUNTDISPLAYID, OWNER_SIDE_HORDE ); m_moveSprint = true; } else if( m_PetOwner->GetUInt32Value( UNIT_FIELD_MOUNTDISPLAYID ) == 0 && m_Unit->GetUInt32Value( UNIT_FIELD_MOUNTDISPLAYID ) != 0 ) { m_Unit->SetUInt32Value( UNIT_FIELD_MOUNTDISPLAYID, 0 ); m_moveSprint = false; } //for fun : mimic master standstate. Note that this might give strange results if( m_PetOwner->GetStandState() != m_Unit->GetStandState() ) m_Unit->SetStandState( m_PetOwner->GetStandState() ); if( m_castingSpell == NULL ) { if( First_noaction_stamp == 0 ) First_noaction_stamp = Time_Now; float dist = m_Unit->CalcDistance( m_PetOwner ); //printf("we are far from owner, we should move closer , dist %f from %f \n",dist,(FollowDistance*FollowDistance)); if ( dist > FollowDistance ) //if out of range { m_moveRun = true; if(dist > 20.0f) m_moveSprint = true; float delta_x = UnitToFollow->GetPositionX(); float delta_y = UnitToFollow->GetPositionY(); float d = 3; MoveTo(delta_x+(d*(cosf(m_fallowAngle+m_PetOwner->GetOrientation()))), delta_y+(d*(sinf(m_fallowAngle+m_PetOwner->GetOrientation()))), m_PetOwner->GetPositionZ(),m_PetOwner->GetOrientation()); } } else if(m_castingSpell != NULL ) First_noaction_stamp = 0; //if( First_noaction_stamp )printf("ms to say something %u and ms for say cooldown %u\n",First_noaction_stamp + BOREDOM_TIMER_TO_START_TRIGGERING - Time_Now,Boredom_cooldown - Time_Now ); if( First_noaction_stamp && First_noaction_stamp + BOREDOM_TIMER_TO_START_TRIGGERING < Time_Now && Boredom_cooldown < Time_Now ) { //some chance to say something if( Rand( 50 ) ) m_Unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, LANG_UNIVERSAL, bored_texts[ RandomUInt( BOREDOM_TEXTCOUNT ) ]); else m_Unit->SetUInt32Value ( UNIT_NPC_EMOTESTATE, bored_emotes[ RandomUInt( BOREDOM_EMOTECOUNT ) ] ); Boredom_cooldown = Time_Now + BOREDOM_TRIGGER_INTERVAL; } }
void ObjectMgr::LoadExtraCreatureProtoStuff() { { StorageContainerIterator<CreatureProto> * itr = CreatureProtoStorage.MakeIterator(); CreatureProto* cn; while(!itr->AtEnd()) { cn = itr->Get(); // Process spell fields for( uint32 i = 0; i < MAX_CREATURE_PROTO_SPELLS; i++ ){ if( cn->AISpells[ i ] == 0 ) continue; SpellEntry *sp = dbcSpell.LookupEntryForced( cn->AISpells[ i ] ); if( sp == NULL ) continue; if( ( sp->Attributes & ATTRIBUTES_PASSIVE ) == 0 ) cn->castable_spells.push_back( sp->Id ); else cn->start_auras.insert( sp->Id ); } // process creature spells from creaturespelldata.dbc if( cn->spelldataid != 0 ){ CreatureSpellDataEntry* spe = dbcCreatureSpellData.LookupEntry( cn->spelldataid ); for( uint32 i = 0; i < 3; i++ ){ if( spe->Spells[ i ] == 0 ) continue; SpellEntry *sp = dbcSpell.LookupEntryForced( spe->Spells[ i ] ); if( sp == NULL ) continue; if( ( sp->Attributes & ATTRIBUTES_PASSIVE ) == 0 ) cn->castable_spells.push_back( sp->Id ); else cn->start_auras.insert( sp->Id ); } } if(cn->aura_string) { string auras = string(cn->aura_string); vector<string> aurs = StrSplit(auras, " "); for(vector<string>::iterator it = aurs.begin(); it != aurs.end(); ++it) { uint32 id = atol((*it).c_str()); if(id) cn->start_auras.insert(id); } } if(!cn->MinHealth) cn->MinHealth = 1; if(!cn->MaxHealth) cn->MaxHealth = 1; if(cn->AttackType > SCHOOL_ARCANE) cn->AttackType = SCHOOL_NORMAL; cn->m_canFlee = cn->m_canRangedAttack = cn->m_canCallForHelp = false; cn->m_fleeHealth = 0.0f; // please.... m_fleeDuration is a uint32... //cn->m_fleeDuration = 0.0f; cn->m_fleeDuration = 0; if(!itr->Inc()) break; } itr->Destruct(); } { StorageContainerIterator<CreatureInfo> * itr = CreatureNameStorage.MakeIterator(); CreatureInfo* ci; while(!itr->AtEnd()) { ci = itr->Get(); ci->lowercase_name = string(ci->Name); for(uint32 j = 0; j < ci->lowercase_name.length(); ++j) ci->lowercase_name[j] = static_cast<char>(tolower(ci->lowercase_name[j])); // Darvaleo 2008/08/15 - Copied lowercase conversion logic from ItemPrototype task for(int i = 0; i < NUM_MONSTER_SAY_EVENTS; i++) ci->MonsterSay[i] = objmgr.HasMonsterSay(ci->Id, MONSTER_SAY_EVENTS(i)); if(!itr->Inc()) break; } itr->Destruct(); } // Load AI Agents if(Config.MainConfig.GetBoolDefault("Server", "LoadAIAgents", true)) { QueryResult* result = WorldDatabase.Query("SELECT * FROM ai_agents"); CreatureProto* cn; if(result != NULL) { AI_Spell* sp; SpellEntry* spe; uint32 entry; do { Field* fields = result->Fetch(); entry = fields[0].GetUInt32(); cn = CreatureProtoStorage.LookupEntry(entry); spe = dbcSpell.LookupEntryForced(fields[6].GetUInt32()); if(spe == NULL) { Log.Error("AIAgent", "For %u has nonexistent spell %u.", fields[0].GetUInt32(), fields[6].GetUInt32()); continue; } if(!cn) continue; sp = new AI_Spell; sp->entryId = fields[0].GetUInt32(); sp->instance_mode = fields[1].GetUInt32(); sp->agent = fields[2].GetUInt16(); sp->procChance = fields[4].GetUInt32(); sp->procCount = fields[5].GetUInt32(); sp->spell = spe; sp->spellType = static_cast<uint8>(fields[7].GetUInt32()); int32 targettype = fields[8].GetInt32(); if(targettype == -1) sp->spelltargetType = static_cast<uint8>(GetAiTargetType(spe)); else sp->spelltargetType = static_cast<uint8>(targettype); sp->cooldown = fields[9].GetInt32(); sp->floatMisc1 = fields[10].GetFloat(); sp->autocast_type = (uint32) - 1; sp->cooldowntime = getMSTime(); sp->procCounter = 0; sp->Misc2 = fields[11].GetUInt32(); if(sp->agent == AGENT_SPELL) { if(!sp->spell) { LOG_DEBUG("SpellId %u in ai_agent for %u is invalid.", (unsigned int)fields[6].GetUInt32(), (unsigned int)sp->entryId); delete sp; sp = NULL; continue; } if(sp->spell->Effect[0] == SPELL_EFFECT_LEARN_SPELL || sp->spell->Effect[1] == SPELL_EFFECT_LEARN_SPELL || sp->spell->Effect[2] == SPELL_EFFECT_LEARN_SPELL) { LOG_DEBUG("Teaching spell %u in ai_agent for %u", (unsigned int)fields[6].GetUInt32(), (unsigned int)sp->entryId); delete sp; sp = NULL; continue; } sp->minrange = GetMinRange(dbcSpellRange.LookupEntry(sp->spell->rangeIndex)); sp->maxrange = GetMaxRange(dbcSpellRange.LookupEntry(sp->spell->rangeIndex)); //omg the poor darling has no clue about making ai_agents if(sp->cooldown == (uint32) - 1) { //now this will not be exact cooldown but maybe a bigger one to not make him spam spells to often int cooldown; SpellDuration* sd = dbcSpellDuration.LookupEntry(sp->spell->DurationIndex); int Dur = 0; int Casttime = 0; //most of the time 0 int RecoveryTime = sp->spell->RecoveryTime; if(sp->spell->DurationIndex) Dur =::GetDuration(sd); Casttime = GetCastTime(dbcSpellCastTime.LookupEntry(sp->spell->CastingTimeIndex)); cooldown = Dur + Casttime + RecoveryTime; if(cooldown < 0) sp->cooldown = 2000; //huge value that should not loop while adding some timestamp to it else sp->cooldown = cooldown; } /* //now apply the moron filter if(sp->procChance== 0) { //printf("SpellId %u in ai_agent for %u is invalid.\n", (unsigned int)fields[5].GetUInt32(), (unsigned int)sp->entryId); delete sp; sp = NULL; continue; } if(sp->spellType== 0) { //right now only these 2 are used if(IsBeneficSpell(sp->spell)) sp->spellType==STYPE_HEAL; else sp->spellType==STYPE_BUFF; } if(sp->spelltargetType== 0) sp->spelltargetType = RecommandAISpellTargetType(sp->spell); */ } if(sp->agent == AGENT_RANGED) { cn->m_canRangedAttack = true; delete sp; sp = NULL; } else if(sp->agent == AGENT_FLEE) { cn->m_canFlee = true; if(sp->floatMisc1) cn->m_canFlee = (sp->floatMisc1 > 0.0f ? true : false); else cn->m_fleeHealth = 0.2f; if(sp->Misc2) cn->m_fleeDuration = sp->Misc2; else cn->m_fleeDuration = 10000; delete sp; sp = NULL; } else if(sp->agent == AGENT_CALLFORHELP) { cn->m_canCallForHelp = true; if(sp->floatMisc1) cn->m_callForHelpHealth = 0.2f; delete sp; sp = NULL; } else { cn->spells.push_back(sp); } } while(result->NextRow()); delete result; } } }
//will get bigger if it is better to cast this spell then some other version float GetSpellEficiencyFactor(SpellEntry *sp) { SpellCastTime *sd = dbcSpellCastTime.LookupEntry( sp->CastingTimeIndex ); return (float)(sp->EffectBasePoints[0]) / ( GetCastTime( sd ) * 2 + sp->manaCost + 1) ; }