void Creature::UpdateDamagePhysical(WeaponAttackType attType) { UnitMods unitMod; switch(attType) { case BASE_ATTACK: default: unitMod = UNIT_MOD_DAMAGE_MAINHAND; break; case OFF_ATTACK: unitMod = UNIT_MOD_DAMAGE_OFFHAND; break; case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED; break; } //float att_speed = float(GetAttackTime(attType))/1000.0f; float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE); float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE); /* difference in AP between current attack power and base value from DB */ float att_pwr_change = GetTotalAttackPowerValue(attType) - GetCreatureInfo()->attackpower; float base_value = GetModifierValue(unitMod, BASE_VALUE) + (att_pwr_change * GetAPMultiplier(attType, false) / 14.0f); float base_pct = GetModifierValue(unitMod, BASE_PCT); float total_value = GetModifierValue(unitMod, TOTAL_VALUE); float total_pct = GetModifierValue(unitMod, TOTAL_PCT); float dmg_multiplier = GetCreatureInfo()->dmg_multiplier; if(!CanUseAttackType(attType)) { weapon_mindamage = 0; weapon_maxdamage = 0; } float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct * dmg_multiplier; float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct * dmg_multiplier; switch(attType) { case BASE_ATTACK: default: SetStatFloatValue(UNIT_FIELD_MINDAMAGE,mindamage); SetStatFloatValue(UNIT_FIELD_MAXDAMAGE,maxdamage); break; case OFF_ATTACK: SetStatFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE,mindamage); SetStatFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE,maxdamage); break; case RANGED_ATTACK: SetStatFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,mindamage); SetStatFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,maxdamage); break; } }
void Creature::generateMoneyLoot() { uint32 maxgold = GetCreatureInfo()->maxgold; if (GetCreatureInfo()->maxgold > 0) { uint32 mingold = GetCreatureInfo()->mingold; if (maxgold <= mingold) loot.gold = uint32(maxgold * sWorld.getRate(RATE_DROP_MONEY)); else loot.gold = uint32(rand32(mingold, maxgold) * sWorld.getRate(RATE_DROP_MONEY)); } }
void Totem::Update(uint32 update_diff, uint32 time ) { Unit *owner = GetOwner(); if (!owner || !owner->isAlive() || !isAlive()) { UnSummon(); // remove self return; } if (m_duration <= update_diff) { UnSummon(); // remove self return; } else m_duration -= update_diff; // Grounding totem + polymorph = unsummon if(GetCreatureInfo()->Entry == 5925 && HasAuraType(SPELL_AURA_MOD_CONFUSE)) { UnSummon(); // remove self return; } Creature::Update( update_diff, time ); }
void Totem::Summon(Unit* owner) { sLog.outDebug("AddObject at Totem.cpp line 49"); SetInstanceId(owner->GetInstanceId()); owner->GetMap()->Add((Creature*)this); // select totem model in dependent from owner team CreatureInfo const *cinfo = GetCreatureInfo(); if(owner->GetTypeId()==TYPEID_PLAYER && cinfo) { uint32 display_id = objmgr.ChooseDisplayId(((Player*)owner)->GetTeam(),cinfo); CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id); if (minfo) display_id = minfo->modelid; SetDisplayId(display_id); } WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); data << GetGUID(); SendMessageToSet(&data,true); AIM_Initialize(); switch(m_type) { case TOTEM_PASSIVE: CastSpell(this, GetSpell(), true); break; case TOTEM_STATUE: CastSpell(GetOwner(), GetSpell(), true); break; default: break; } }
bool Pet::CreateBaseAtCreature(Creature* creature) { ASSERT(creature); if (!CreateBaseAtTamed(creature->GetCreatureInfo(), creature->GetMap(), creature->GetPhaseMask())) return false; Relocate(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation()); if (!IsPositionValid()) { sLog->outError("Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)", GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); return false; } CreatureTemplate const* cinfo = GetCreatureInfo(); if (!cinfo) { sLog->outError("CreateBaseAtCreature() failed, creatureInfo is missing!"); return false; } SetDisplayId(creature->GetDisplayId()); if (CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family)) SetName(cFamily->Name[sWorld->GetDefaultDbcLocale()]); else SetName(creature->GetNameForLocaleIdx(sObjectMgr->GetDBCLocaleIndex())); return true; }
bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team) { SetMapId(map->GetId()); SetInstanceId(map->GetInstanceId()); Object::_Create(guidlow, Entry, HIGHGUID_VEHICLE); if(!InitEntry(Entry, team)) return false; m_defaultMovementType = IDLE_MOTION_TYPE; AIM_Initialize(); SetVehicleId(vehicleId); SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); CreatureInfo const *ci = GetCreatureInfo(); setFaction(team == ALLIANCE ? ci->faction_A : ci->faction_H); SetMaxHealth(ci->maxhealth); SelectLevel(ci); SetHealth(GetMaxHealth()); for( int i = 0; i < 4; ++i ) this->m_spells[i] = this->GetCreatureInfo()->spells[i]; // So our vehicles can have spells on bar GetMotionMaster()->MovePoint(0, GetPositionX(), GetPositionY(), GetPositionZ()+2 ); // So we can fly with Dragon Vehicles return true; }
void Totem::InitStats(uint32 duration) { Minion::InitStats(duration); CreatureInfo const *cinfo = GetCreatureInfo(); if(m_owner->GetTypeId() == TYPEID_PLAYER && cinfo) { uint32 display_id = objmgr.ChooseDisplayId(((Player*)m_owner)->GetTeam(), cinfo); CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id); if (minfo) display_id = minfo->modelid; SetDisplayId(display_id); } // Get spell casted by totem SpellEntry const * totemSpell = sSpellStore.LookupEntry(GetSpell()); if (totemSpell) { // If spell have cast time -> so its active totem if (GetSpellCastTime(totemSpell)) m_type = TOTEM_ACTIVE; } if(GetEntry() == SENTRY_TOTEM_ENTRY) SetReactState(REACT_AGGRESSIVE); m_duration = duration; SetLevel(m_owner->getLevel()); }
bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team) { SetMapId(map->GetId()); SetInstanceId(map->GetInstanceId()); Object::_Create(guidlow, Entry, HIGHGUID_VEHICLE); if(!InitEntry(Entry, team)) return false; m_defaultMovementType = IDLE_MOTION_TYPE; AIM_Initialize(); SetVehicleId(vehicleId); SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); CreatureInfo const *ci = GetCreatureInfo(); setFaction(team == ALLIANCE ? ci->faction_A : ci->faction_H); SetMaxHealth(ci->maxhealth); SelectLevel(ci); SetHealth(GetMaxHealth()); return true; }
void Totem::InitStats(uint32 duration) { Minion::InitStats(duration); CreatureTemplate const *cinfo = GetCreatureInfo(); if (m_owner->GetTypeId() == TYPEID_PLAYER && cinfo) { uint32 displayID = sObjectMgr->ChooseDisplayId(m_owner->ToPlayer()->GetTeam(), cinfo); sObjectMgr->GetCreatureModelRandomGender(&displayID); switch (m_owner->ToPlayer()->GetTeam()) { case ALLIANCE: displayID = cinfo->Modelid1; break; case HORDE: if (cinfo->Modelid3) displayID = cinfo->Modelid3; else displayID = cinfo->Modelid1; switch (((Player*)m_owner)->getRace()) { case RACE_ORC: if (cinfo->Modelid2) displayID = cinfo->Modelid2; else displayID = cinfo->Modelid1; break; case RACE_TROLL: if (cinfo->Modelid4) displayID = cinfo->Modelid4; else displayID = cinfo->Modelid1; break; default: break; } break; default: break; } SetDisplayId(displayID); } // Get spell casted by totem SpellEntry const * totemSpell = sSpellStore.LookupEntry(GetSpell()); if (totemSpell) { // If spell have cast time -> so its active totem if (GetSpellCastTime(totemSpell)) m_type = TOTEM_ACTIVE; } if (GetEntry() == SENTRY_TOTEM_ENTRY) SetReactState(REACT_AGGRESSIVE); m_duration = duration; SetLevel(m_owner->getLevel()); }
void Vehicle::RemovePassenger(Unit *unit) { SeatMap::iterator seat; for(seat = m_Seats.begin(); seat != m_Seats.end(); ++seat) { if((seat->second.flags & (SEAT_FULL | SEAT_VEHICLE_FREE | SEAT_VEHICLE_FULL)) && seat->second.passenger == unit) { unit->SetVehicleGUID(0); if(seat->second.vs_flags & SF_MAIN_RIDER) { RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE); if(unit->GetTypeId() == TYPEID_PLAYER) { ((Player*)unit)->SetMover(unit); ((Player*)unit)->SetClientControl(unit, 1); ((Player*)unit)->SetMoverInQueve(NULL); ((Player*)unit)->RemovePetActionBar(); if(((Player*)unit)->GetGroup()) ((Player*)unit)->SetGroupUpdateFlag(GROUP_UPDATE_VEHICLE); } unit->SetCharm(NULL); SetCharmerGUID(NULL); setFaction(GetCreatureInfo()->faction_A); } if(GetVehicleFlags() & VF_NON_SELECTABLE) RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); if(seat->second.vs_flags & SF_UNATTACKABLE) unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); // restore player control if(unit->GetTypeId() == TYPEID_PLAYER) { ((Player*)unit)->GetCamera().ResetView(); if(seat->second.vs_flags & SF_CAN_CAST) { WorldPacket data0(SMSG_FORCE_MOVE_UNROOT, 10); data0 << unit->GetPackGUID(); data0 << (uint32)(2); // can rotate unit->SendMessageToSet(&data0,true); } else { WorldPacket data1(SMSG_FORCE_MOVE_UNROOT, 10); data1 << unit->GetPackGUID(); data1 << (uint32)(0); // cannot rotate unit->SendMessageToSet(&data1,true); } } unit->m_movementInfo.ClearTransportData(); seat->second.passenger = NULL; seat->second.flags = SEAT_FREE; unit->m_movementInfo.RemoveMovementFlag(MOVEFLAG_ONTRANSPORT); EmptySeatsCountChanged(); break; } } }
void Totem::Summon(Unit* owner) { owner->GetMap()->Add((Creature*)this); // select totem model in dependent from owner team CreatureInfo const *cinfo = GetCreatureInfo(); if(owner->GetTypeId() == TYPEID_PLAYER && cinfo) { uint32 display_id = sObjectMgr.ChooseDisplayId(((Player*)owner)->GetTeam(), cinfo); CreatureModelInfo const *minfo = sObjectMgr.GetCreatureModelRandomGender(display_id); if (minfo) display_id = minfo->modelid; SetDisplayId(display_id); } AIM_Initialize(); // there are some totems, which exist just for their visual appeareance if (!GetSpell()) return; switch(m_type) { case TOTEM_PASSIVE: CastSpell(this, GetSpell(), true); break; case TOTEM_STATUE: CastSpell(GetOwner(), GetSpell(), true); break; default: break; } }
npc_unworthy_initiateAI(Creature *c) : ScriptedAI(c) { me->SetReactState(REACT_PASSIVE); if (!me->GetEquipmentId()) if (const CreatureInfo *info = GetCreatureInfo(28406)) if (info->equipmentId) const_cast<CreatureInfo*>(me->GetCreatureInfo())->equipmentId = info->equipmentId; }
void Creature::UpdateDamagePhysical(WeaponAttackType attType) { if(attType > BASE_ATTACK) return; UnitMods unitMod = UNIT_MOD_DAMAGE_MAINHAND; /* difference in AP between current attack power and base value from DB */ float att_pwr_change = GetTotalAttackPowerValue(attType) - GetCreatureInfo()->attackpower; float base_value = GetModifierValue(unitMod, BASE_VALUE) + (att_pwr_change * GetAPMultiplier(attType, false) / 14.0f); float base_pct = GetModifierValue(unitMod, BASE_PCT); float total_value = GetModifierValue(unitMod, TOTAL_VALUE); float total_pct = GetModifierValue(unitMod, TOTAL_PCT); float dmg_multiplier = GetCreatureInfo()->dmg_multiplier; float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); float mindamage = ((base_value + weapon_mindamage) * dmg_multiplier * base_pct + total_value) * total_pct; float maxdamage = ((base_value + weapon_maxdamage) * dmg_multiplier * base_pct + total_value) * total_pct; SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage); SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage); }
void Totem::Summon(Unit* owner) { CreatureInfo const *cinfo = GetCreatureInfo(); if (owner->GetTypeId()==TYPEID_PLAYER && cinfo) { uint32 modelid = 0; if(((Player*)owner)->GetTeam() == HORDE) { if(cinfo->Modelid_H1) modelid = cinfo->Modelid_H1; else if(cinfo->Modelid_H2) modelid = cinfo->Modelid_H2; } else { if(cinfo->Modelid_A1) modelid = cinfo->Modelid_A1; else if(cinfo->Modelid_A2) modelid = cinfo->Modelid_A2; } if (modelid) SetDisplayId(modelid); else sLog.outErrorDb("Totem::Summon: Missing modelid information for entry %u, team %u, totem will use default values.",GetEntry(),((Player*)owner)->GetTeam()); } // Only add if a display exists. sLog.outDebug("AddObject at Totem.cpp line 49"); SetInstanceId(owner->GetInstanceId()); owner->GetMap()->Add((Creature*)this); WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); data << GetGUID(); SendMessageToSet(&data,true); AIM_Initialize(); switch(m_type) { case TOTEM_PASSIVE: CastSpell(this, GetSpell(), true); break; case TOTEM_STATUE: CastSpell(GetOwner(), GetSpell(), true); break; default: break; } if(GetEntry() == SENTRY_TOTEM_ENTRY) SetReactState(REACT_AGGRESSIVE); }
bool Pet::HaveInDiet(ItemTemplate const* item) const { if (!item->FoodType) return false; CreatureTemplate const* cInfo = GetCreatureInfo(); if (!cInfo) return false; CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->family); if (!cFamily) return false; uint32 diet = cFamily->petFoodMask; uint32 FoodMask = 1 << (item->FoodType-1); return diet & FoodMask; }
void Totem::InitStats(uint32 duration) { Minion::InitStats(duration); CreatureInfo const *cinfo = GetCreatureInfo(); if (m_owner->GetTypeId() == TYPEID_PLAYER && cinfo) { uint32 modelid = 0; if (m_owner->ToPlayer()->GetTeam() == HORDE) { if (cinfo->Modelid_H1) modelid = cinfo->Modelid_H1; else if (cinfo->Modelid_H2) modelid = cinfo->Modelid_H2; } else { if (cinfo->Modelid_A1) modelid = cinfo->Modelid_A1; else if (cinfo->Modelid_A2) modelid = cinfo->Modelid_A2; } if (modelid) SetDisplayId(modelid); else sLog.outErrorDb("Totem::Summon: Missing modelid information for entry %u, team %u, totem will use default values.",GetEntry(),m_owner->ToPlayer()->GetTeam()); } // Get spell casted by totem SpellEntry const * totemSpell = sSpellStore.LookupEntry(GetSpell()); if (totemSpell) { // If spell have cast time -> so its active totem if (GetSpellCastTime(totemSpell)) m_type = TOTEM_ACTIVE; } if (GetEntry() == SENTRY_TOTEM_ENTRY) SetReactState(REACT_AGGRESSIVE); m_duration = duration; SetLevel(m_owner->getLevel()); }
void Totem::Summon(Unit* owner) { sLog.outDebug("AddObject at Totem.cpp line 49"); SetInstanceId(owner->GetInstanceId()); owner->GetMap()->Add((Creature*)this); // select totem model in dependent from owner team [-ZERO] not implemented/useful CreatureInfo const *cinfo = GetCreatureInfo(); if(owner->GetTypeId() == TYPEID_PLAYER && cinfo) { uint32 display_id = sObjectMgr.ChooseDisplayId(((Player*)owner)->GetTeam(), cinfo); CreatureModelInfo const *minfo = sObjectMgr.GetCreatureModelRandomGender(display_id); if (minfo) display_id = minfo->modelid; SetDisplayId(display_id); } WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); data << GetGUID(); SendMessageToSet(&data,true); AIM_Initialize(); if (owner->GetTypeId() == TYPEID_UNIT && ((Creature*)owner)->AI()) ((Creature*)owner)->AI()->JustSummoned((Creature*)this); // there are some totems, which exist just for their visual appeareance if (!GetSpell()) return; switch(m_type) { case TOTEM_PASSIVE: CastSpell(this, GetSpell(), true); break; case TOTEM_STATUE: CastSpell(GetOwner(), GetSpell(), true); break; default: break; } }
void Creature::UpdateDamagePhysical(WeaponAttackType attType) { if(attType > BASE_ATTACK) return; UnitMods unitMod = UNIT_MOD_DAMAGE_MAINHAND; float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType); float base_pct = GetModifierValue(unitMod, BASE_PCT); float total_value = GetModifierValue(unitMod, TOTAL_VALUE); float total_pct = GetModifierValue(unitMod, TOTAL_PCT); float dmg_multiplier = GetCreatureInfo()->dmg_multiplier; float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct * dmg_multiplier; float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct * dmg_multiplier; SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage); SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage); }
void Vehicle::RemovePassenger(Unit *unit) { SeatMap::iterator seat; for(seat = m_Seats.begin(); seat != m_Seats.end(); ++seat) { if((seat->second.flags & (SEAT_FULL | SEAT_VEHICLE_FREE | SEAT_VEHICLE_FULL)) && seat->second.passenger == unit) { unit->SetVehicleGUID(0); if(seat->second.vs_flags & SF_MAIN_RIDER) { RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE); if(unit->GetTypeId() == TYPEID_PLAYER) { ((Player*)unit)->SetMover(unit); ((Player*)unit)->SetClientControl(unit, 1); ((Player*)unit)->SetMoverInQueve(NULL); ((Player*)unit)->RemovePetActionBar(); if(((Player*)unit)->GetGroup()) ((Player*)unit)->SetGroupUpdateFlag(GROUP_UPDATE_VEHICLE); } unit->SetCharm(NULL); SetCharmerGUID(NULL); setFaction(GetCreatureInfo()->faction_A); } if(GetVehicleFlags() & VF_NON_SELECTABLE) RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); if(GetVehicleFlags() & VF_CAST_AURA && m_VehicleData && m_VehicleData->v_spells[0] != 0) unit->RemoveAurasDueToSpell(m_VehicleData->v_spells[0]); if(seat->second.vs_flags & SF_UNATTACKABLE) unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); // restore player control if(unit->GetTypeId() == TYPEID_PLAYER) { ((Player*)unit)->SetFarSightGUID(NULL); if(seat->second.vs_flags & SF_CAN_CAST) { WorldPacket data0(SMSG_FORCE_MOVE_UNROOT, 10); data0 << unit->GetPackGUID(); data0 << (uint32)(2); // can rotate unit->SendMessageToSet(&data0,true); } else { WorldPacket data1(SMSG_FORCE_MOVE_UNROOT, 10); data1 << unit->GetPackGUID(); data1 << (uint32)(0); // cannot rotate unit->SendMessageToSet(&data1,true); } } unit->m_SeatData.OffsetX = 0.0f; unit->m_SeatData.OffsetY = 0.0f; unit->m_SeatData.OffsetZ = 0.0f; unit->m_SeatData.Orientation = 0.0f; unit->m_SeatData.c_time = 0; unit->m_SeatData.dbc_seat = 0; unit->m_SeatData.seat = 0; unit->m_SeatData.s_flags = 0; unit->m_SeatData.v_flags = 0; seat->second.passenger = NULL; seat->second.flags = SEAT_FREE; EmptySeatsCountChanged(); break; } } }
bool Creature::LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId) { bool external = (result != NULL); if (!external) // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 result = sDatabase.PQuery("SELECT `id`,`map`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`spawn_position_x`,`spawn_position_y`,`spawn_position_z`,`curhealth`,`curmana`,`respawntime`,`DeathState`,`MovementType`,`auras` " "FROM `creature` LEFT JOIN `creature_respawn` ON ((`creature`.`guid`=`creature_respawn`.`guid`) AND (`creature_respawn`.`instance` = '%u')) WHERE `creature`.`guid` = '%u'", InstanceId, guid); if(!result) { sLog.outErrorDb("Creature (GUID: %u) not found in table `creature`, can't load. ",guid); return false; } Field *fields = result->Fetch(); uint32 stored_guid = guid; if (InstanceId != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_UNIT); SetInstanceId(InstanceId); if(!Create(guid,fields[1].GetUInt32(),fields[2].GetFloat(),fields[3].GetFloat(), fields[4].GetFloat(),fields[5].GetFloat(),fields[0].GetUInt32())) { if (!external) delete result; return false; } m_DBTableGuid = stored_guid; if(GetCreatureInfo()->rank > 0) this->m_corpseDelay *= 3; //if creature is elite, then remove corpse later SetHealth(fields[11].GetUInt32()); SetPower(POWER_MANA,fields[12].GetUInt32()); m_respawnradius = fields[7].GetFloat(); respawn_cord[0] = fields[8].GetFloat(); respawn_cord[1] = fields[9].GetFloat(); respawn_cord[2] = fields[10].GetFloat(); m_respawnDelay = fields[6].GetUInt32(); m_deathState = (DeathState)fields[14].GetUInt32(); if(m_deathState == JUST_DIED) // Dont must be set to JUST_DEAD, see Creature::setDeathState JUST_DIED -> CORPSE promoting. { sLog.outErrorDb("Creature (GUIDLow: %u Entry: %u ) in wrong state: JUST_DEAD (1). State set to ALIVE.",GetGUIDLow(),GetEntry()); m_deathState = ALIVE; } else if(m_deathState < ALIVE || m_deathState > DEAD) { sLog.outErrorDb("Creature (GUIDLow: %u Entry: %u ) in wrong state: %d. State set to ALIVE.",GetGUIDLow(),GetEntry(),m_deathState); m_deathState = ALIVE; } m_respawnTime = (time_t)fields[13].GetUInt64(); if(m_respawnTime > time(NULL)) // not ready to respawn m_deathState = DEAD; else // ready to respawn { m_respawnTime = 0; sDatabase.PExecute("DELETE FROM `creature_respawn` WHERE `guid` = '%u' AND `instance` = '%u'", m_DBTableGuid, GetInstanceId()); } { uint32 mtg = fields[15].GetUInt32(); if(mtg < MAX_DB_MOTION_TYPE) m_defaultMovementType = MovementGeneratorType(mtg); else { m_defaultMovementType = IDLE_MOTION_TYPE; sLog.outErrorDb("Creature (GUID: %u ID: %u) have wrong movement generator type value %u, ignore and set to IDLE.",guid,GetEntry(),mtg); } } if(!external) delete result; LoadFlagRelatedData(); AIM_Initialize(); return true; }
bool Vehicle::LoadFromDB(uint32 guid, Map *map) { CreatureData const* data = objmgr.GetCreatureData(guid); if(!data) { sLog.outErrorDb("Creature (GUID: %u) not found in table `creature`, can't load. ",guid); return false; } uint32 id = 0; if(const CreatureInfo *cInfo = objmgr.GetCreatureTemplate(data->id)) id = cInfo->VehicleId; if(!id || !sVehicleStore.LookupEntry(id)) return false; m_DBTableGuid = guid; if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_VEHICLE); uint16 team = 0; if(!Create(guid,map,data->phaseMask,data->id,id,team,data->posX,data->posY,data->posZ,data->orientation,data)) return false; //We should set first home position, because then AI calls home movement SetHomePosition(data->posX,data->posY,data->posZ,data->orientation); m_respawnradius = data->spawndist; m_respawnDelay = data->spawntimesecs; m_isDeadByDefault = data->is_dead; m_deathState = m_isDeadByDefault ? DEAD : ALIVE; m_respawnTime = objmgr.GetCreatureRespawnTime(m_DBTableGuid,GetInstanceId()); if(m_respawnTime > time(NULL)) // not ready to respawn { m_deathState = DEAD; if(canFly()) { float tz = GetMap()->GetHeight(data->posX,data->posY,data->posZ,false); if(data->posZ - tz > 0.1) Relocate(data->posX,data->posY,tz); } } else if(m_respawnTime) // respawn time set but expired { m_respawnTime = 0; objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),0); } uint32 curhealth = data->curhealth; if(curhealth) { curhealth = uint32(curhealth*_GetHealthMod(GetCreatureInfo()->rank)); if(curhealth < 1) curhealth = 1; } SetHealth(m_deathState == ALIVE ? curhealth : 0); SetPower(POWER_MANA,data->curmana); // checked at creature_template loading m_defaultMovementType = MovementGeneratorType(data->movementType); m_creatureData = data; return true; }
bool Creature::isCanTrainingOf(Player* pPlayer, bool msg) const { if(!isTrainer()) return false; if(m_tspells.empty()) { sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_TRAINER but have empty trainer spell list.", GetGUIDLow(),GetCreatureInfo()->Entry); return false; } switch(GetCreatureInfo()->trainer_type) { case TRAINER_TYPE_CLASS: if(pPlayer->getClass()!=GetCreatureInfo()->classNum) { if(msg) { pPlayer->PlayerTalkClass->ClearMenus(); switch(GetCreatureInfo()->classNum) { case CLASS_DRUID: pPlayer->PlayerTalkClass->SendGossipMenu( 4913,GetGUID()); break; case CLASS_HUNTER: pPlayer->PlayerTalkClass->SendGossipMenu(10090,GetGUID()); break; case CLASS_MAGE: pPlayer->PlayerTalkClass->SendGossipMenu( 328,GetGUID()); break; case CLASS_PALADIN:pPlayer->PlayerTalkClass->SendGossipMenu( 1635,GetGUID()); break; case CLASS_PRIEST: pPlayer->PlayerTalkClass->SendGossipMenu( 4436,GetGUID()); break; case CLASS_ROGUE: pPlayer->PlayerTalkClass->SendGossipMenu( 4797,GetGUID()); break; case CLASS_SHAMAN: pPlayer->PlayerTalkClass->SendGossipMenu( 5003,GetGUID()); break; case CLASS_WARLOCK:pPlayer->PlayerTalkClass->SendGossipMenu( 5836,GetGUID()); break; case CLASS_WARRIOR:pPlayer->PlayerTalkClass->SendGossipMenu( 4985,GetGUID()); break; } } return false; } break; case TRAINER_TYPE_PETS: if(pPlayer->getClass()!=CLASS_HUNTER) { pPlayer->PlayerTalkClass->ClearMenus(); pPlayer->PlayerTalkClass->SendGossipMenu(3620,GetGUID()); return false; } break; case TRAINER_TYPE_MOUNTS: if(GetCreatureInfo()->race && pPlayer->getRace() != GetCreatureInfo()->race) { if(msg) { pPlayer->PlayerTalkClass->ClearMenus(); switch(GetCreatureInfo()->classNum) { case RACE_DWARF: pPlayer->PlayerTalkClass->SendGossipMenu(5865,GetGUID()); break; case RACE_GNOME: pPlayer->PlayerTalkClass->SendGossipMenu(4881,GetGUID()); break; case RACE_HUMAN: pPlayer->PlayerTalkClass->SendGossipMenu(5861,GetGUID()); break; case RACE_NIGHTELF: pPlayer->PlayerTalkClass->SendGossipMenu(5862,GetGUID()); break; case RACE_ORC: pPlayer->PlayerTalkClass->SendGossipMenu(5863,GetGUID()); break; case RACE_TAUREN: pPlayer->PlayerTalkClass->SendGossipMenu(5864,GetGUID()); break; case RACE_TROLL: pPlayer->PlayerTalkClass->SendGossipMenu(5816,GetGUID()); break; case RACE_UNDEAD_PLAYER:pPlayer->PlayerTalkClass->SendGossipMenu( 624,GetGUID()); break; } } return false; } break; case TRAINER_TYPE_TRADESKILLS: if(GetCreatureInfo()->trainer_spell && !pPlayer->HasSpell(GetCreatureInfo()->trainer_spell)) { if(msg) { pPlayer->PlayerTalkClass->ClearMenus(); pPlayer->PlayerTalkClass->SendGossipMenu(11031,GetGUID()); } return false; } break; default: sLog.outErrorDb("Creature %u (entry: %u) have trainer type %u",GetGUIDLow(),GetCreatureInfo()->Entry,GetCreatureInfo()->trainer_type); return false; } return true; }
bool Pet::UpdateStats(Stats stat) { if(stat > STAT_SPIRIT) return false; // value = ((base_value * base_pct) + total_value) * total_pct float value = GetTotalStatValue(stat); Unit *owner = GetOwner(); if ( stat == STAT_STAMINA ) { if(owner) { float scale_coeff = 0.3f; switch (owner->getClass()) { case CLASS_HUNTER: scale_coeff = 0.4493f; break; case CLASS_WARLOCK: { CreatureInfo const *cinfo = GetCreatureInfo(); CreatureFamily petFamily = (CreatureFamily) cinfo->family; switch (petFamily) { case CREATURE_FAMILY_FELHUNTER: value += float(owner->GetStat(stat)) * 0.7125f; break; case CREATURE_FAMILY_VOIDWALKER: value += float(owner->GetStat(stat)) * 0.825f; break; case CREATURE_FAMILY_FELGUARD: value += float(owner->GetStat(stat)) * 0.825f; break; case CREATURE_FAMILY_SUCCUBUS: value += float(owner->GetStat(stat)) * 0.6825f; break; case CREATURE_FAMILY_IMP: value += float(owner->GetStat(stat)) * 0.63f; break; default: value += float(owner->GetStat(stat)) * 0.3f; break; } break; } case CLASS_DEATH_KNIGHT: scale_coeff = 0.3928f; break; } value += float(owner->GetStat(stat)) * scale_coeff; } } //warlock's and mage's pets gain 30% of owner's intellect else if ( stat == STAT_INTELLECT && getPetType() == SUMMON_PET ) { if(owner && (owner->getClass() == CLASS_WARLOCK || owner->getClass() == CLASS_MAGE) ) value += float(owner->GetStat(stat)) * 0.3f; } SetStat(stat, int32(value)); switch(stat) { case STAT_STRENGTH: UpdateAttackPowerAndDamage(); break; case STAT_AGILITY: UpdateArmor(); break; case STAT_STAMINA: UpdateMaxHealth(); break; case STAT_INTELLECT: UpdateMaxPower(POWER_MANA); break; case STAT_SPIRIT: default: break; } return true; }
bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool current) { m_loading = true; uint32 ownerid = owner->GetGUIDLow(); QueryResult result; if (petnumber) // known petnumber entry 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType " "FROM character_pet WHERE owner = '%u' AND id = '%u'", ownerid, petnumber); else if (current) // current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType " "FROM character_pet WHERE owner = '%u' AND slot = '%u'", ownerid, PET_SAVE_AS_CURRENT); else if (petentry) // known petentry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets) // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType " "FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '%u' OR slot > '%u') ", ownerid, petentry, PET_SAVE_AS_CURRENT, PET_SAVE_LAST_STABLE_SLOT); else // any current or other non-stabled pet (for hunter "call pet") // 0 1 2(?) 3 4 5 6 7 8 9 10 11 12 13 14 15 16 result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType " "FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u') ", ownerid, PET_SAVE_AS_CURRENT, PET_SAVE_LAST_STABLE_SLOT); if (!result) { m_loading = false; return false; } Field* fields = result->Fetch(); // update for case of current pet "slot = 0" petentry = fields[1].GetUInt32(); if (!petentry) return false; uint32 summon_spell_id = fields[15].GetUInt32(); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(summon_spell_id); bool is_temporary_summoned = spellInfo && spellInfo->GetDuration() > 0; // check temporary summoned pets like mage water elemental if (current && is_temporary_summoned) return false; PetType pet_type = PetType(fields[16].GetUInt8()); if (pet_type == HUNTER_PET) { CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petentry); if (!creatureInfo || !creatureInfo->isTameable(owner->CanTameExoticPets())) return false; } uint32 pet_number = fields[0].GetUInt32(); if (current && owner->IsPetNeedBeTemporaryUnsummoned()) { owner->SetTemporaryUnsummonedPetNumber(pet_number); return false; } Map* map = owner->GetMap(); uint32 guid = sObjectMgr->GenerateLowGuid(HIGHGUID_PET); if (!Create(guid, map, owner->GetPhaseMask(), petentry, pet_number)) return false; float px, py, pz; owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, GetFollowAngle()); Relocate(px, py, pz, owner->GetOrientation()); if (!IsPositionValid()) { sLog->outError("Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)", GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); return false; } setPetType(pet_type); setFaction(owner->getFaction()); SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id); CreatureTemplate const* cinfo = GetCreatureInfo(); if (cinfo->type == CREATURE_TYPE_CRITTER) { map->AddToMap(this->ToCreature()); return true; } m_charmInfo->SetPetNumber(pet_number, IsPermanentPetFor(owner)); SetDisplayId(fields[3].GetUInt32()); SetNativeDisplayId(fields[3].GetUInt32()); uint32 petlevel = fields[4].GetUInt16(); SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); SetName(fields[8].GetString()); switch (getPetType()) { case SUMMON_PET: petlevel = owner->getLevel(); SetUInt32Value(UNIT_FIELD_BYTES_0, 0x800); // class = mage SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet dismiss, cancel) break; case HUNTER_PET: SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); // class = warrior, gender = none, power = focus SetSheath(SHEATH_STATE_MELEE); SetByteFlag(UNIT_FIELD_BYTES_2, 2, fields[9].GetBool() ? UNIT_CAN_BE_ABANDONED : UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED); SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet abandon, cancel) SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS)); SetPower(POWER_HAPPINESS, fields[12].GetUInt32()); setPowerType(POWER_FOCUS); break; default: if (!IsPetGhoul()) sLog->outError("Pet have incorrect type (%u) for pet loading.", getPetType()); break; } SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped here SetCreatorGUID(owner->GetGUID()); InitStatsForLevel(petlevel); SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32()); SynchronizeLevelWithOwner(); SetReactState(ReactStates(fields[6].GetUInt8())); SetCanModifyStats(true); if (getPetType() == SUMMON_PET && !current) //all (?) summon pets come with full health when called, but not when they are current SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); else { uint32 savedhealth = fields[10].GetUInt32(); uint32 savedmana = fields[11].GetUInt32(); if (!savedhealth && getPetType() == HUNTER_PET) setDeathState(JUST_DIED); else { SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth); SetPower(POWER_MANA, savedmana > GetMaxPower(POWER_MANA) ? GetMaxPower(POWER_MANA) : savedmana); } } // set current pet as current // 0=current // 1..MAX_PET_STABLES in stable slot // PET_SAVE_NOT_IN_SLOT(100) = not stable slot (summoning)) if (fields[7].GetUInt8()) { SQLTransaction trans = CharacterDatabase.BeginTransaction(); trans->PAppend("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND slot = '%u' AND id <> '%u'", PET_SAVE_NOT_IN_SLOT, ownerid, PET_SAVE_AS_CURRENT, m_charmInfo->GetPetNumber()); trans->PAppend("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND id = '%u'", PET_SAVE_AS_CURRENT, ownerid, m_charmInfo->GetPetNumber()); CharacterDatabase.CommitTransaction(trans); } // Send fake summon spell cast - this is needed for correct cooldown application for spells // Example: 46584 - without this cooldown (which should be set always when pet is loaded) isn't set clientside // TODO: pets should be summoned from real cast instead of just faking it? if (summon_spell_id) { WorldPacket data(SMSG_SPELL_GO, (8+8+4+4+2)); data.append(owner->GetPackGUID()); data.append(owner->GetPackGUID()); data << uint8(0); data << uint32(summon_spell_id); data << uint32(256); // CAST_FLAG_UNKNOWN3 data << uint32(0); owner->SendMessageToSet(&data, true); } owner->SetMinion(this, true); map->AddToMap(this->ToCreature()); InitTalentForLevel(); // set original talents points before spell loading uint32 timediff = uint32(time(NULL) - fields[14].GetUInt32()); _LoadAuras(timediff); // load action bar, if data broken will fill later by default spells. if (!is_temporary_summoned) { m_charmInfo->LoadPetActionBar(fields[13].GetString()); _LoadSpells(); InitTalentForLevel(); // re-init to check talent count _LoadSpellCooldowns(); LearnPetPassives(); InitLevelupSpellsForLevel(); CastPetAuras(current); } CleanupActionBar(); // remove unknown spells from action bar after load sLog->outDebug(LOG_FILTER_PETS, "New Pet has guid %u", GetGUIDLow()); owner->PetSpellInitialize(); if (owner->GetGroup()) owner->SetGroupUpdateFlag(GROUP_UPDATE_PET); owner->SendTalentsInfoData(true); if (getPetType() == HUNTER_PET) { result = CharacterDatabase.PQuery("SELECT genitive, dative, accusative, instrumental, prepositional FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", owner->GetGUIDLow(), GetCharmInfo()->GetPetNumber()); if (result) { delete m_declinedname; m_declinedname = new DeclinedName; Field* fields2 = result->Fetch(); for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { m_declinedname->name[i] = fields2[i].GetString(); } } } //set last used pet number (for use in BG's) if (owner->GetTypeId() == TYPEID_PLAYER && isControlled() && !isTemporarySummoned() && (getPetType() == SUMMON_PET || getPetType() == HUNTER_PET)) owner->ToPlayer()->SetLastPetNumber(pet_number); m_loading = false; return true; }
bool Creature::isCanTrainingAndResetTalentsOf(Player* pPlayer) const { return pPlayer->getLevel() >= 10 && GetCreatureInfo()->trainer_type == TRAINER_TYPE_CLASS && pPlayer->getClass() == GetCreatureInfo()->classNum; }
// TODO: Move stat mods code to pet passive auras bool Guardian::InitStatsForLevel(uint8 petlevel) { CreatureTemplate const* cinfo = GetCreatureInfo(); ASSERT(cinfo); SetLevel(petlevel); //Determine pet type PetType petType = MAX_PET_TYPE; if (isPet() && m_owner->GetTypeId() == TYPEID_PLAYER) { if ((m_owner->getClass() == CLASS_WARLOCK) || (m_owner->getClass() == CLASS_SHAMAN) // Fire Elemental || (m_owner->getClass() == CLASS_DEATH_KNIGHT)) // Risen Ghoul petType = SUMMON_PET; else if (m_owner->getClass() == CLASS_HUNTER) { petType = HUNTER_PET; m_unitTypeMask |= UNIT_MASK_HUNTER_PET; } else sLog->outError("Unknown type pet %u is summoned by player class %u", GetEntry(), m_owner->getClass()); } uint32 creature_ID = (petType == HUNTER_PET) ? 1 : cinfo->Entry; SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel*50)); SetAttackTime(BASE_ATTACK, BASE_ATTACK_TIME); SetAttackTime(OFF_ATTACK, BASE_ATTACK_TIME); SetAttackTime(RANGED_ATTACK, BASE_ATTACK_TIME); SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); //scale CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family); if (cFamily && cFamily->minScale > 0.0f && petType == HUNTER_PET) { float scale; if (getLevel() >= cFamily->maxScaleLevel) scale = cFamily->maxScale; else if (getLevel() <= cFamily->minScaleLevel) scale = cFamily->minScale; else scale = cFamily->minScale + float(getLevel() - cFamily->minScaleLevel) / cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale); SetFloatValue(OBJECT_FIELD_SCALE_X, scale); } // Resistance for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i])); //health, mana, armor and resistance PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(creature_ID, petlevel); if (pInfo) // exist in DB { SetCreateHealth(pInfo->health); if (petType != HUNTER_PET) //hunter pet use focus SetCreateMana(pInfo->mana); if (pInfo->armor > 0) SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor)); for (uint8 stat = 0; stat < MAX_STATS; ++stat) SetCreateStat(Stats(stat), float(pInfo->stats[stat])); } else // not exist in DB, use some default fake data { // remove elite bonuses included in DB values CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(petlevel, cinfo->unit_class); SetCreateHealth(stats->BaseHealth[cinfo->expansion]); SetCreateMana(stats->BaseMana); SetCreateStat(STAT_STRENGTH, 22); SetCreateStat(STAT_AGILITY, 22); SetCreateStat(STAT_STAMINA, 25); SetCreateStat(STAT_INTELLECT, 28); SetCreateStat(STAT_SPIRIT, 27); } SetBonusDamage(0); switch (petType) { case SUMMON_PET: { //the damage bonus used for pets is either fire or shadow damage, whatever is higher uint32 fire = m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE); uint32 shadow = m_owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW); uint32 val = (fire > shadow) ? fire : shadow; SetBonusDamage(int32 (val * 0.15f)); //bonusAP += val * 0.57; SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4))); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4))); //SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, float(cinfo->attackpower)); break; } case HUNTER_PET: { SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32(sObjectMgr->GetXPForLevel(petlevel)*PET_XP_FACTOR)); //these formula may not be correct; however, it is designed to be close to what it should be //this makes dps 0.5 of pets level SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4))); //damage range is then petlevel / 2 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4))); //damage is increased afterwards as strength and pet scaling modify attack power break; } default: { switch (GetEntry()) { case 510: // mage Water Elemental { SetBonusDamage(int32(m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_FROST) * 0.33f)); break; } case 1964: //force of nature { if (!pInfo) SetCreateHealth(30 + 30*petlevel); float bonusDmg = m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_NATURE) * 0.15f; SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 2.5f - (petlevel / 2) + bonusDmg)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 2.5f + (petlevel / 2) + bonusDmg)); break; } case 15352: //earth elemental 36213 { if (!pInfo) SetCreateHealth(100 + 120*petlevel); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4))); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4))); break; } case 15438: //fire elemental { if (!pInfo) { SetCreateHealth(40*petlevel); SetCreateMana(28 + 10*petlevel); } SetBonusDamage(m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_FIRE) * 0.5f); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 4 - petlevel)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 4 + petlevel)); break; } case 19668: // Shadowfiend { if (!pInfo) { SetCreateMana(28 + 10*petlevel); SetCreateHealth(28 + 30*petlevel); } int32 bonus_dmg = (int32(m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_SHADOW)* 0.3f)); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel) + bonus_dmg)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel) + bonus_dmg)); break; } case 19833: //Snake Trap - Venomous Snake { SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel / 2) - 25)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel / 2) - 18)); break; } case 19921: //Snake Trap - Viper { SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel / 2 - 10)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel / 2)); break; } case 29264: // Feral Spirit { if (!pInfo) SetCreateHealth(30*petlevel); float dmg_multiplier = 0.3f; if (m_owner->GetAuraEffect(63271, 0)) // Glyph of Feral Spirit dmg_multiplier = 0.6f; SetBonusDamage(int32(m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier)); // 14AP == 1dps, wolf's strike speed == 2s so dmg = basedmg + AP / 14 * 2 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float((petlevel * 4 - petlevel) + (m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier * 2 / 14))); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float((petlevel * 4 + petlevel) + (m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier * 2 / 14))); SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(m_owner->GetArmor()) * 0.35f); // Bonus Armor (35% of player armor) SetModifierValue(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(m_owner->GetStat(STAT_STAMINA)) * 0.3f); // Bonus Stamina (30% of player stamina) if (!HasAura(58877))//prevent apply twice for the 2 wolves AddAura(58877, this);//Spirit Hunt, passive, Spirit Wolves' attacks heal them and their master for 150% of damage done. break; } case 31216: // Mirror Image { SetBonusDamage(int32(m_owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_FROST) * 0.33f)); SetDisplayId(m_owner->GetDisplayId()); if (!pInfo) { SetCreateMana(28 + 30*petlevel); SetCreateHealth(28 + 10*petlevel); } break; } case 27829: // Ebon Gargoyle { if (!pInfo) { SetCreateMana(28 + 10*petlevel); SetCreateHealth(28 + 30*petlevel); } SetBonusDamage(int32(m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f)); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4))); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4))); break; } } break; } } UpdateAllStats(); SetFullHealth(); SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); return true; }
void Creature::prepareGossipMenu( Player *pPlayer,uint32 gossipid ) { PlayerMenu* pm=pPlayer->PlayerTalkClass; pm->ClearMenus(); if(!m_goptions.size()) LoadGossipOptions(); GossipOption* gso; GossipOption* ingso; for( GossipOptionList::iterator i = m_goptions.begin( ); i != m_goptions.end( ); i++ ) { gso=&*i; if(gso->GossipId == gossipid) { bool cantalking=true; if(gso->Id==1) { uint32 textid=GetNpcTextId(); GossipText * gossiptext=objmgr.GetGossipText(textid); if(!gossiptext) cantalking=false; } else { switch (gso->Action) { case GOSSIP_OPTION_QUESTGIVER: pPlayer->PrepareQuestMenu(GetGUID()); //if (pm->GetQuestMenu()->MenuItemCount() == 0) cantalking=false; //pm->GetQuestMenu()->ClearMenu(); break; case GOSSIP_OPTION_ARMORER: cantalking=false; // added in special mode break; case GOSSIP_OPTION_SPIRITHEALER: if( !pPlayer->isDead() ) cantalking=false; break; case GOSSIP_OPTION_VENDOR: if(!GetItemCount()) { sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_VENDOR but have empty trading item list.", GetGUIDLow(),GetCreatureInfo()->Entry); cantalking=false; } break; case GOSSIP_OPTION_TRAINER: if(!isCanTrainingOf(pPlayer,false)) cantalking=false; break; case GOSSIP_OPTION_UNLEARNTALENTS: if(!isCanTrainingAndResetTalentsOf(pPlayer)) cantalking=false; break; case GOSSIP_OPTION_TAXIVENDOR: if ( pPlayer->GetSession()->SendLearnNewTaxiNode(GetGUID()) ) return; case GOSSIP_OPTION_GUARD: case GOSSIP_OPTION_INNKEEPER: case GOSSIP_OPTION_BANKER: case GOSSIP_OPTION_PETITIONER: case GOSSIP_OPTION_STABLEPET: case GOSSIP_OPTION_TABARDVENDOR: case GOSSIP_OPTION_BATTLEFIELD: case GOSSIP_OPTION_AUCTIONEER: break; // no checks default: sLog.outErrorDb("Creature %u (entry: %u) have unknown gossip option %u",GetGUIDLow(),GetCreatureInfo()->Entry,gso->Action); break; } } if(gso->Option!="" && cantalking ) { pm->GetGossipMenu()->AddMenuItem((uint8)gso->Icon,gso->Option.c_str(), gossipid,gso->Action,false); ingso=gso; } } } if(pm->GetGossipMenu()->MenuItemCount()==0 && HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_TRAINER) && !pm->GetQuestMenu()->MenuItemCount()) isCanTrainingOf(pPlayer,true); /* if(pm->GetGossipMenu()->MenuItemCount()==1 && ingso->Id==8 && GetGossipCount( ingso->GossipId )>0) { pm->ClearMenus(); for( GossipOptionList::iterator i = m_goptions.begin( ); i != m_goptions.end( ); i++ ) { gso=&*i; if(gso->GossipId==ingso->Id) { if(gso->Option!="") pm->GetGossipMenu()->AddMenuItem((uint8)gso->Icon,gso->Option.c_str(),ingso->GossipId,gso->Action,false); } } } */ }
void Creature::CreateTrainerSpells() { for(SpellsList::iterator i = m_tspells.begin(); i != m_tspells.end(); ++i) delete *i; m_tspells.clear(); TrainerSpell *tspell; Field *fields; QueryResult *result = sDatabase.PQuery("SELECT `spell`,`spellcost`,`reqskill`,`reqskillvalue`,`reqlevel` FROM `npc_trainer` WHERE `entry` = '%u'", GetCreatureInfo()->Entry); if(!result) return; do { fields = result->Fetch(); uint32 spellid = fields[0].GetUInt32(); SpellEntry const *spellinfo = sSpellStore.LookupEntry(spellid); if(!spellinfo) { sLog.outErrorDb("Trainer (GUID: %u ID: %u ) have in list non existed spell %u",GetGUIDLow(),GetEntry(),spellid); continue; } tspell = new TrainerSpell; tspell->spell = spellinfo; tspell->spellcost = fields[1].GetUInt32(); tspell->reqskill = fields[2].GetUInt32(); tspell->reqskillvalue = fields[3].GetUInt32(); tspell->reqlevel = fields[4].GetUInt32(); m_tspells.push_back(tspell); } while( result->NextRow() ); delete result; }
void MailDraft::SendMailTo(SQLTransaction& trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked, uint32 deliver_delay) { Player* pReceiver = receiver.GetPlayer(); // can be NULL if (pReceiver) prepareItems(pReceiver, trans); // generate mail template items uint32 mailId = sObjectMgr->GenerateMailID(); time_t deliver_time = time(NULL) + deliver_delay; //expire time if COD 3 days, if no COD 30 days, if auction sale pending 1 hour uint32 expire_delay; // auction mail without any items and money if (sender.GetMailMessageType() == MAIL_AUCTION && m_items.empty() && !m_money) expire_delay = sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY); // mail from battlemaster (rewardmarks) should last only one day else if (sender.GetMailMessageType() == MAIL_CREATURE) { CreatureInfo const * creatureinfo = GetCreatureInfo(sender.GetSenderId()); if (creatureinfo && creatureinfo->unit_flags & UNIT_NPC_FLAG_BATTLEMASTER) expire_delay = DAY; else expire_delay = (m_COD > 0) ? 3 * DAY : 30 * DAY; } else expire_delay = (m_COD > 0) ? 3 * DAY : 30 * DAY; time_t expire_time = deliver_time + expire_delay; // Add to DB uint8 index = 0; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_MAIL); stmt->setUInt32( index, mailId); stmt->setUInt8 (++index, uint8(sender.GetMailMessageType())); stmt->setInt8 (++index, int8(sender.GetStationery())); stmt->setUInt16(++index, GetMailTemplateId()); stmt->setUInt32(++index, sender.GetSenderId()); stmt->setUInt32(++index, receiver.GetPlayerGUIDLow()); stmt->setString(++index, GetSubject()); stmt->setString(++index, GetBody()); stmt->setBool (++index, !m_items.empty()); stmt->setUInt64(++index, uint64(expire_time)); stmt->setUInt64(++index, uint64(deliver_time)); stmt->setUInt32(++index, m_money); stmt->setUInt32(++index, m_COD); stmt->setUInt8 (++index, uint8(checked)); trans->Append(stmt); for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) { Item* pItem = mailItemIter->second; stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_MAIL_ITEM); stmt->setUInt32(0, mailId); stmt->setUInt32(1, pItem->GetGUIDLow()); stmt->setUInt32(2, receiver.GetPlayerGUIDLow()); trans->Append(stmt); } // For online receiver update in game mail status and data if (pReceiver) { pReceiver->AddNewMailDeliverTime(deliver_time); if (pReceiver->IsMailsLoaded()) { Mail * m = new Mail; m->messageID = mailId; m->mailTemplateId = GetMailTemplateId(); m->subject = GetSubject(); m->body = GetBody(); m->money = GetMoney(); m->COD = GetCOD(); for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) { Item* item = mailItemIter->second; m->AddItem(item->GetGUIDLow(), item->GetEntry()); } m->messageType = sender.GetMailMessageType(); m->stationery = sender.GetStationery(); m->sender = sender.GetSenderId(); m->receiver = receiver.GetPlayerGUIDLow(); m->expire_time = expire_time; m->deliver_time = deliver_time; m->checked = checked; m->state = MAIL_STATE_UNCHANGED; pReceiver->AddMail(m); // to insert new mail to beginning of maillist if (!m_items.empty()) { for (MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) pReceiver->AddMItem(mailItemIter->second); } } else if (!m_items.empty()) { SQLTransaction temp = SQLTransaction(NULL); deleteIncludedItems(temp); } } else if (!m_items.empty()) { SQLTransaction temp = SQLTransaction(NULL); deleteIncludedItems(temp); } }
bool Creature::CreateFromProto(uint32 guidlow,uint32 Entry) { Object::_Create(guidlow, HIGHGUID_UNIT); m_DBTableGuid = guidlow; SetUInt32Value(OBJECT_FIELD_ENTRY,Entry); CreatureInfo const *cinfo = objmgr.GetCreatureTemplate(Entry); if(!cinfo) { sLog.outError("Error: creature entry %u does not exist.",Entry); return false; } uint32 rank = isPet()? 0 : cinfo->rank; float damagemod = _GetDamageMod(rank);; uint32 display_id = cinfo->randomDisplayID(); SetUInt32Value(UNIT_FIELD_DISPLAYID,display_id ); SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID,display_id ); SetUInt32Value(UNIT_FIELD_BYTES_2,1); // let creature used equiped weapon in fight SetName(GetCreatureInfo()->Name); SelectLevel(cinfo); SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction); SetUInt32Value(UNIT_NPC_FLAGS,cinfo->npcflag); SetFloatValue(UNIT_FIELD_MINDAMAGE,cinfo->mindmg * damagemod); SetFloatValue(UNIT_FIELD_MAXDAMAGE,cinfo->maxdmg * damagemod); SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,cinfo->minrangedmg * damagemod); SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,cinfo->maxrangedmg * damagemod); SetAttackTime(BASE_ATTACK, cinfo->baseattacktime); SetAttackTime(RANGED_ATTACK,cinfo->rangeattacktime); SetUInt32Value(UNIT_FIELD_FLAGS,cinfo->Flags); SetUInt32Value(UNIT_DYNAMIC_FLAGS,cinfo->dynamicflags); SetArmor(cinfo->armor); SetResistance(SPELL_SCHOOL_HOLY,cinfo->resistance1); SetResistance(SPELL_SCHOOL_FIRE,cinfo->resistance2); SetResistance(SPELL_SCHOOL_NATURE,cinfo->resistance3); SetResistance(SPELL_SCHOOL_FROST,cinfo->resistance4); SetResistance(SPELL_SCHOOL_SHADOW,cinfo->resistance5); SetResistance(SPELL_SCHOOL_ARCANE,cinfo->resistance6); //this is probably wrong SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, cinfo->equipmodel[0]); SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO , cinfo->equipinfo[0]); SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 1, cinfo->equipslot[0]); SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, cinfo->equipmodel[1]); SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 2, cinfo->equipinfo[1]); SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 2 + 1, cinfo->equipslot[1]); SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+2, cinfo->equipmodel[2]); SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 4, cinfo->equipinfo[2]); SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 4 + 1, cinfo->equipslot[2]); SetFloatValue(OBJECT_FIELD_SCALE_X, cinfo->size); SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS,cinfo->bounding_radius); SetFloatValue(UNIT_FIELD_COMBATREACH,cinfo->combat_reach ); FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cinfo->faction); if (factionTemplate) { FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplate->faction); if (factionEntry) if (cinfo->civilian != 1 && (factionEntry->team == ALLIANCE || factionEntry->team == HORDE)) SetPvP(true); } else sLog.outErrorDb("Error: invalid faction (%u) for creature (GUIDLow: %u Entry: %u)", cinfo->faction, GetGUIDLow(),Entry); if (cinfo->mount != 0) Mount(cinfo->mount); m_spells[0] = cinfo->spell1; m_spells[1] = cinfo->spell2; m_spells[2] = cinfo->spell3; m_spells[3] = cinfo->spell4; SetSpeed(MOVE_WALK, cinfo->speed ); SetSpeed(MOVE_RUN, cinfo->speed ); SetSpeed(MOVE_WALKBACK, cinfo->speed ); SetSpeed(MOVE_SWIM, cinfo->speed); SetSpeed(MOVE_SWIMBACK, cinfo->speed); if(cinfo->MovementType < MAX_DB_MOTION_TYPE) m_defaultMovementType = MovementGeneratorType(cinfo->MovementType); else { m_defaultMovementType = IDLE_MOTION_TYPE; sLog.outErrorDb("Creature template %u have wrong movement generator type value %u, ignore and set to IDLE.",Entry,cinfo->MovementType); } return true; }