mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 04:37:00 +00:00
Updated objects stuff
This commit is contained in:
parent
579fc917bb
commit
9c8864f134
12 changed files with 896 additions and 500 deletions
|
|
@ -645,8 +645,11 @@ bool Creature::isCanIneractWithBattleMaster(Player* pPlayer, bool msg) const
|
|||
case BATTLEGROUND_NA:
|
||||
case BATTLEGROUND_BE:
|
||||
case BATTLEGROUND_AA:
|
||||
case BATTLEGROUND_RL: pPlayer->PlayerTalkClass->SendGossipMenu(10024,GetGUID()); break;
|
||||
break;
|
||||
case BATTLEGROUND_RL:
|
||||
case BATTLEGROUND_SA:
|
||||
case BATTLEGROUND_DS:
|
||||
case BATTLEGROUND_RV: pPlayer->PlayerTalkClass->SendGossipMenu(10024,GetGUID()); break;
|
||||
default: break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1353,11 +1356,7 @@ void Creature::LoadEquipment(uint32 equip_entry, bool force)
|
|||
if (force)
|
||||
{
|
||||
for (uint8 i = 0; i < 3; i++)
|
||||
{
|
||||
SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, 0);
|
||||
SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), 0);
|
||||
SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, 0);
|
||||
}
|
||||
SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, 0);
|
||||
m_equipmentId = 0;
|
||||
}
|
||||
return;
|
||||
|
|
@ -1369,11 +1368,7 @@ void Creature::LoadEquipment(uint32 equip_entry, bool force)
|
|||
|
||||
m_equipmentId = equip_entry;
|
||||
for (uint8 i = 0; i < 3; i++)
|
||||
{
|
||||
SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, einfo->equipmodel[i]);
|
||||
SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), einfo->equipinfo[i]);
|
||||
SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, einfo->equipslot[i]);
|
||||
}
|
||||
SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, einfo->equipentry[i]);
|
||||
}
|
||||
|
||||
bool Creature::hasQuest(uint32 quest_id) const
|
||||
|
|
|
|||
|
|
@ -210,9 +210,7 @@ struct CreatureLocale
|
|||
struct EquipmentInfo
|
||||
{
|
||||
uint32 entry;
|
||||
uint32 equipmodel[3];
|
||||
uint32 equipinfo[3];
|
||||
uint32 equipslot[3];
|
||||
uint32 equipentry[3];
|
||||
};
|
||||
|
||||
// from `creature` table
|
||||
|
|
|
|||
|
|
@ -123,10 +123,10 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float
|
|||
SetFloatValue(GAMEOBJECT_POS_Z, z);
|
||||
SetFloatValue(GAMEOBJECT_FACING, ang); //this is not facing angle
|
||||
|
||||
SetFloatValue (GAMEOBJECT_ROTATION, rotation0);
|
||||
SetFloatValue (GAMEOBJECT_ROTATION+1, rotation1);
|
||||
SetFloatValue (GAMEOBJECT_ROTATION+2, rotation2);
|
||||
SetFloatValue (GAMEOBJECT_ROTATION+3, rotation3);
|
||||
SetFloatValue(GAMEOBJECT_PARENTROTATION, rotation0);
|
||||
SetFloatValue(GAMEOBJECT_PARENTROTATION+1, rotation1);
|
||||
SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rotation2);
|
||||
SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3);
|
||||
|
||||
SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size);
|
||||
|
||||
|
|
@ -510,10 +510,10 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask)
|
|||
data.posY = GetFloatValue(GAMEOBJECT_POS_Y);
|
||||
data.posZ = GetFloatValue(GAMEOBJECT_POS_Z);
|
||||
data.orientation = GetFloatValue(GAMEOBJECT_FACING);
|
||||
data.rotation0 = GetFloatValue(GAMEOBJECT_ROTATION+0);
|
||||
data.rotation1 = GetFloatValue(GAMEOBJECT_ROTATION+1);
|
||||
data.rotation2 = GetFloatValue(GAMEOBJECT_ROTATION+2);
|
||||
data.rotation3 = GetFloatValue(GAMEOBJECT_ROTATION+3);
|
||||
data.rotation0 = GetFloatValue(GAMEOBJECT_PARENTROTATION+0);
|
||||
data.rotation1 = GetFloatValue(GAMEOBJECT_PARENTROTATION+1);
|
||||
data.rotation2 = GetFloatValue(GAMEOBJECT_PARENTROTATION+2);
|
||||
data.rotation3 = GetFloatValue(GAMEOBJECT_PARENTROTATION+3);
|
||||
data.spawntimesecs = m_spawnedByDefault ? m_respawnDelayTime : -(int32)m_respawnDelayTime;
|
||||
data.animprogress = GetGoAnimProgress();
|
||||
data.go_state = GetGoState();
|
||||
|
|
@ -530,10 +530,10 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask)
|
|||
<< GetFloatValue(GAMEOBJECT_POS_Y) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_POS_Z) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_FACING) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_ROTATION) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_ROTATION+1) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_ROTATION+2) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_ROTATION+3) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_PARENTROTATION) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_PARENTROTATION+1) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_PARENTROTATION+2) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_PARENTROTATION+3) << ", "
|
||||
<< m_respawnDelayTime << ", "
|
||||
<< (uint32)GetGoAnimProgress() << ", "
|
||||
<< (uint32)GetGoState() << ")";
|
||||
|
|
@ -1222,6 +1222,26 @@ void GameObject::Use(Unit* user)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case GAMEOBJECT_TYPE_BARBER_CHAIR: //32
|
||||
{
|
||||
GameObjectInfo const* info = GetGOInfo();
|
||||
if(!info)
|
||||
return;
|
||||
|
||||
if(user->GetTypeId()!=TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
Player* player = (Player*)user;
|
||||
|
||||
// fallback, will always work
|
||||
player->TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET);
|
||||
|
||||
WorldPacket data(SMSG_ENABLE_BARBER_SHOP, 0);
|
||||
player->GetSession()->SendPacket(&data);
|
||||
|
||||
player->SetStandState(PLAYER_STATE_SIT_LOW_CHAIR+info->barberChair.chairheight);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
sLog.outDebug("Unknown Object Type %u", GetGoType());
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -334,12 +334,12 @@ struct GameObjectInfo
|
|||
uint32 mapID; //0
|
||||
uint32 difficulty; //1
|
||||
} dungeonDifficulty;
|
||||
//32 GAMEOBJECT_TYPE_DO_NOT_USE_YET
|
||||
//32 GAMEOBJECT_TYPE_BARBER_CHAIR
|
||||
struct
|
||||
{
|
||||
uint32 mapID; //0
|
||||
uint32 difficulty; //1
|
||||
} doNotUseYet;
|
||||
uint32 chairheight; //0
|
||||
uint32 heightOffset; //1
|
||||
} barberChair;
|
||||
//33 GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING
|
||||
struct
|
||||
{
|
||||
|
|
@ -348,6 +348,13 @@ struct GameObjectInfo
|
|||
uint32 state1Name; //2
|
||||
uint32 state2Name; //3
|
||||
} destructibleBuilding;
|
||||
//34 GAMEOBJECT_TYPE_TRAPDOOR
|
||||
struct
|
||||
{
|
||||
uint32 whenToPause; // 0
|
||||
uint32 startOpen; // 1
|
||||
uint32 autoClose; // 2
|
||||
} trapDoor;
|
||||
|
||||
// not use for specific field access (only for output with loop by all filed), also this determinate max union size
|
||||
struct // GAMEOBJECT_TYPE_SPELLCASTER
|
||||
|
|
@ -497,14 +504,14 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
|
|||
void SetSpellId(uint32 id) { m_spellId = id;}
|
||||
uint32 GetSpellId() const { return m_spellId;}
|
||||
void getFishLoot(Loot *loot);
|
||||
GameobjectTypes GetGoType() const { return GameobjectTypes(GetUInt32Value(GAMEOBJECT_TYPE_ID)); }
|
||||
void SetGoType(GameobjectTypes type) { SetUInt32Value(GAMEOBJECT_TYPE_ID, type); }
|
||||
uint32 GetGoState() const { return GetUInt32Value(GAMEOBJECT_STATE); }
|
||||
void SetGoState(uint32 state) { SetUInt32Value(GAMEOBJECT_STATE, state); }
|
||||
uint32 GetGoArtKit() const { return GetUInt32Value(GAMEOBJECT_ARTKIT); }
|
||||
void SetGoArtKit(uint32 artkit) { SetUInt32Value(GAMEOBJECT_ARTKIT, artkit); }
|
||||
uint32 GetGoAnimProgress() const { return GetUInt32Value(GAMEOBJECT_ANIMPROGRESS); }
|
||||
void SetGoAnimProgress(uint32 animprogress) { SetUInt32Value(GAMEOBJECT_ANIMPROGRESS, animprogress); }
|
||||
GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); }
|
||||
void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); }
|
||||
uint8 GetGoState() const { return GetByteValue(GAMEOBJECT_BYTES_1, 0); }
|
||||
void SetGoState(uint8 state) { SetByteValue(GAMEOBJECT_BYTES_1, 0, state); }
|
||||
uint8 GetGoArtKit() const { return GetByteValue(GAMEOBJECT_BYTES_1, 2); }
|
||||
void SetGoArtKit(uint8 artkit) { SetByteValue(GAMEOBJECT_BYTES_1, 2, artkit); }
|
||||
uint8 GetGoAnimProgress() const { return GetByteValue(GAMEOBJECT_BYTES_1, 3); }
|
||||
void SetGoAnimProgress(uint8 animprogress) { SetByteValue(GAMEOBJECT_BYTES_1, 3, animprogress); }
|
||||
|
||||
void Use(Unit* user);
|
||||
|
||||
|
|
|
|||
398
src/game/Pet.cpp
398
src/game/Pet.cpp
|
|
@ -39,27 +39,6 @@ char const* petTypeSuffix[MAX_PET_TYPE] =
|
|||
"'s Companion" // MINI_PET
|
||||
};
|
||||
|
||||
//numbers represent minutes * 100 while happy (you get 100 loyalty points per min while happy)
|
||||
uint32 const LevelUpLoyalty[6] =
|
||||
{
|
||||
5500,
|
||||
11500,
|
||||
17000,
|
||||
23500,
|
||||
31000,
|
||||
39500,
|
||||
};
|
||||
|
||||
uint32 const LevelStartLoyalty[6] =
|
||||
{
|
||||
2000,
|
||||
4500,
|
||||
7000,
|
||||
10000,
|
||||
13500,
|
||||
17500,
|
||||
};
|
||||
|
||||
Pet::Pet(PetType type) : Creature()
|
||||
{
|
||||
m_isPet = true;
|
||||
|
|
@ -69,12 +48,9 @@ Pet::Pet(PetType type) : Creature()
|
|||
m_removed = false;
|
||||
m_regenTimer = 4000;
|
||||
m_happinessTimer = 7500;
|
||||
m_loyaltyTimer = 12000;
|
||||
m_duration = 0;
|
||||
m_bonusdamage = 0;
|
||||
|
||||
m_loyaltyPoints = 0;
|
||||
m_TrainingPoints = 0;
|
||||
m_resetTalentsCost = 0;
|
||||
m_resetTalentsTime = 0;
|
||||
|
||||
|
|
@ -130,19 +106,19 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
QueryResult *result;
|
||||
|
||||
if(petnumber)
|
||||
// known petnumber entry 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND id = '%u'",ownerid, petnumber);
|
||||
// known petnumber entry 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, 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 17 18 19 20 21 22
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid );
|
||||
// current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid );
|
||||
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 17 18 19 20 21 22
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry );
|
||||
// 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry );
|
||||
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 17 18 19 20 21 22
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid);
|
||||
// 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid);
|
||||
|
||||
if(!result)
|
||||
return false;
|
||||
|
|
@ -157,7 +133,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32 summon_spell_id = fields[21].GetUInt32();
|
||||
uint32 summon_spell_id = fields[19].GetUInt32();
|
||||
SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id);
|
||||
|
||||
bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0;
|
||||
|
|
@ -170,7 +146,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
}
|
||||
|
||||
Map *map = owner->GetMap();
|
||||
uint32 guid=objmgr.GenerateLowGuid(HIGHGUID_PET);
|
||||
uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_PET);
|
||||
uint32 pet_number = fields[0].GetUInt32();
|
||||
if(!Create(guid, map, petentry, pet_number))
|
||||
{
|
||||
|
|
@ -179,7 +155,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
}
|
||||
|
||||
float px, py, pz;
|
||||
owner->GetClosePoint(px, py, pz,GetObjectSize(),PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
|
||||
owner->GetClosePoint(px, py, pz, GetObjectSize(), PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
||||
|
||||
Relocate(px, py, pz, owner->GetOrientation());
|
||||
|
||||
|
|
@ -190,8 +166,8 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
return false;
|
||||
}
|
||||
|
||||
setPetType(PetType(fields[22].GetUInt8()));
|
||||
SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
|
||||
setPetType(PetType(fields[20].GetUInt8()));
|
||||
SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, owner->getFaction());
|
||||
SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id);
|
||||
|
||||
CreatureInfo const *cinfo = GetCreatureInfo();
|
||||
|
|
@ -202,72 +178,67 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
delete result;
|
||||
return true;
|
||||
}
|
||||
if(getPetType()==HUNTER_PET || getPetType()==SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK)
|
||||
|
||||
if(getPetType() == HUNTER_PET || getPetType() == SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK)
|
||||
m_charmInfo->SetPetNumber(pet_number, true);
|
||||
else
|
||||
m_charmInfo->SetPetNumber(pet_number, false);
|
||||
|
||||
SetUInt64Value(UNIT_FIELD_SUMMONEDBY, owner->GetGUID());
|
||||
SetDisplayId(fields[3].GetUInt32());
|
||||
SetNativeDisplayId(fields[3].GetUInt32());
|
||||
uint32 petlevel=fields[4].GetUInt32();
|
||||
SetUInt32Value(UNIT_NPC_FLAGS , 0);
|
||||
SetName(fields[11].GetString());
|
||||
uint32 petlevel = fields[4].GetUInt32();
|
||||
SetUInt32Value(UNIT_NPC_FLAGS, 0);
|
||||
SetName(fields[9].GetString());
|
||||
|
||||
switch(getPetType())
|
||||
{
|
||||
|
||||
case SUMMON_PET:
|
||||
petlevel=owner->getLevel();
|
||||
|
||||
SetUInt32Value(UNIT_FIELD_BYTES_0,2048);
|
||||
SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
|
||||
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);
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, 1, fields[8].GetUInt32());
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 );
|
||||
|
||||
if(fields[12].GetBool())
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
|
||||
else
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, 1, fields[7].GetUInt32());
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 2, fields[10].GetBool() ? UNIT_RENAME_NOT_ALLOWED : UNIT_RENAME_ALLOWED);
|
||||
|
||||
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||
// this enables popup window (pet abandon, cancel)
|
||||
SetTP(fields[9].GetInt32());
|
||||
SetMaxPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS));
|
||||
SetPower( POWER_HAPPINESS,fields[15].GetUInt32());
|
||||
SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
|
||||
SetPower(POWER_HAPPINESS, fields[13].GetUInt32());
|
||||
setPowerType(POWER_FOCUS);
|
||||
break;
|
||||
default:
|
||||
sLog.outError("Pet have incorrect type (%u) for pet loading.",getPetType());
|
||||
sLog.outError("Pet have incorrect type (%u) for pet loading.", getPetType());
|
||||
}
|
||||
InitStatsForLevel( petlevel);
|
||||
|
||||
InitStatsForLevel(petlevel);
|
||||
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
|
||||
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32());
|
||||
SetUInt64Value(UNIT_FIELD_CREATEDBY, owner->GetGUID());
|
||||
|
||||
m_charmInfo->SetReactState( ReactStates( fields[6].GetUInt8() ));
|
||||
m_loyaltyPoints = fields[7].GetInt32();
|
||||
m_charmInfo->SetReactState(ReactStates(fields[6].GetUInt8()));
|
||||
|
||||
uint32 savedhealth = fields[13].GetUInt32();
|
||||
uint32 savedmana = fields[14].GetUInt32();
|
||||
uint32 savedhealth = fields[11].GetUInt32();
|
||||
uint32 savedmana = fields[12].GetUInt32();
|
||||
|
||||
// set current pet as current
|
||||
if(fields[10].GetUInt32() != 0)
|
||||
if(fields[8].GetUInt32() != 0)
|
||||
{
|
||||
CharacterDatabase.BeginTransaction();
|
||||
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'",ownerid, m_charmInfo->GetPetNumber());
|
||||
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'",ownerid, m_charmInfo->GetPetNumber());
|
||||
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'", ownerid, m_charmInfo->GetPetNumber());
|
||||
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'", ownerid, m_charmInfo->GetPetNumber());
|
||||
CharacterDatabase.CommitTransaction();
|
||||
}
|
||||
|
||||
if(!is_temporary_summoned)
|
||||
{
|
||||
// permanent controlled pets store state in DB
|
||||
Tokens tokens = StrSplit(fields[16].GetString(), " ");
|
||||
Tokens tokens = StrSplit(fields[14].GetString(), " ");
|
||||
|
||||
if(tokens.size() != 20)
|
||||
{
|
||||
|
|
@ -285,7 +256,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
}
|
||||
|
||||
//init teach spells
|
||||
tokens = StrSplit(fields[17].GetString(), " ");
|
||||
tokens = StrSplit(fields[15].GetString(), " ");
|
||||
for (iter = tokens.begin(), index = 0; index < 4; ++iter, ++index)
|
||||
{
|
||||
uint32 tmp = atol((*iter).c_str());
|
||||
|
|
@ -300,7 +271,10 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
}
|
||||
|
||||
// since last save (in seconds)
|
||||
uint32 timediff = (time(NULL) - fields[18].GetUInt32());
|
||||
uint32 timediff = (time(NULL) - fields[16].GetUInt32());
|
||||
|
||||
m_resetTalentsCost = fields[17].GetUInt32();
|
||||
m_resetTalentsTime = fields[18].GetUInt64();
|
||||
|
||||
delete result;
|
||||
|
||||
|
|
@ -350,7 +324,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
|
||||
if(owner->GetTypeId() == TYPEID_PLAYER && 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());
|
||||
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)
|
||||
{
|
||||
|
|
@ -408,10 +382,6 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
|||
case PET_SAVE_IN_STABLE_SLOT_2:
|
||||
case PET_SAVE_NOT_IN_SLOT:
|
||||
{
|
||||
uint32 loyalty =1;
|
||||
if(getPetType()!=HUNTER_PET)
|
||||
loyalty = GetLoyaltyLevel();
|
||||
|
||||
uint32 owner = GUID_LOPART(GetOwnerGUID());
|
||||
std::string name = m_name;
|
||||
CharacterDatabase.escape_string(name);
|
||||
|
|
@ -428,7 +398,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
|||
CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3')", owner );
|
||||
// save pet
|
||||
std::ostringstream ss;
|
||||
ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata,TeachSpelldata,savetime,resettalents_cost,resettalents_time,CreatedBySpell,PetType) "
|
||||
ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType) "
|
||||
<< "VALUES ("
|
||||
<< m_charmInfo->GetPetNumber() << ", "
|
||||
<< GetEntry() << ", "
|
||||
|
|
@ -437,9 +407,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
|||
<< getLevel() << ", "
|
||||
<< GetUInt32Value(UNIT_FIELD_PETEXPERIENCE) << ", "
|
||||
<< uint32(m_charmInfo->GetReactState()) << ", "
|
||||
<< m_loyaltyPoints << ", "
|
||||
<< GetLoyaltyLevel() << ", "
|
||||
<< m_TrainingPoints << ", "
|
||||
<< uint32(GetFreeTalentPoints()) << ", "
|
||||
<< uint32(mode) << ", '"
|
||||
<< name.c_str() << "', "
|
||||
<< uint32((GetByteValue(UNIT_FIELD_BYTES_2, 2) == UNIT_RENAME_ALLOWED)?0:1) << ", "
|
||||
|
|
@ -590,14 +558,6 @@ void Pet::Update(uint32 diff)
|
|||
else
|
||||
m_happinessTimer -= diff;
|
||||
|
||||
if(m_loyaltyTimer <= diff)
|
||||
{
|
||||
TickLoyaltyChange();
|
||||
m_loyaltyTimer = 12000;
|
||||
}
|
||||
else
|
||||
m_loyaltyTimer -= diff;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -629,83 +589,12 @@ void Pet::LooseHappiness()
|
|||
uint32 curValue = GetPower(POWER_HAPPINESS);
|
||||
if (curValue <= 0)
|
||||
return;
|
||||
int32 addvalue = (140 >> GetLoyaltyLevel()) * 125; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs)
|
||||
int32 addvalue = 670; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs)
|
||||
if(isInCombat()) //we know in combat happiness fades faster, multiplier guess
|
||||
addvalue = int32(addvalue * 1.5);
|
||||
ModifyPower(POWER_HAPPINESS, -addvalue);
|
||||
}
|
||||
|
||||
void Pet::ModifyLoyalty(int32 addvalue)
|
||||
{
|
||||
uint32 loyaltylevel = GetLoyaltyLevel();
|
||||
|
||||
if(addvalue > 0) //only gain influenced, not loss
|
||||
addvalue = int32((float)addvalue * sWorld.getRate(RATE_LOYALTY));
|
||||
|
||||
if(loyaltylevel >= BEST_FRIEND && (addvalue + m_loyaltyPoints) > int32(GetMaxLoyaltyPoints(loyaltylevel)))
|
||||
return;
|
||||
|
||||
m_loyaltyPoints += addvalue;
|
||||
|
||||
if(m_loyaltyPoints < 0)
|
||||
{
|
||||
if(loyaltylevel > REBELLIOUS)
|
||||
{
|
||||
//level down
|
||||
--loyaltylevel;
|
||||
SetLoyaltyLevel(LoyaltyLevel(loyaltylevel));
|
||||
m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel);
|
||||
SetTP(m_TrainingPoints - int32(getLevel()));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_loyaltyPoints = 0;
|
||||
Unit* owner = GetOwner();
|
||||
if(owner && owner->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
WorldPacket data(SMSG_PET_BROKEN, 0);
|
||||
((Player*)owner)->GetSession()->SendPacket(&data);
|
||||
|
||||
//run away
|
||||
((Player*)owner)->RemovePet(this,PET_SAVE_AS_DELETED);
|
||||
}
|
||||
}
|
||||
}
|
||||
//level up
|
||||
else if(m_loyaltyPoints > int32(GetMaxLoyaltyPoints(loyaltylevel)))
|
||||
{
|
||||
++loyaltylevel;
|
||||
SetLoyaltyLevel(LoyaltyLevel(loyaltylevel));
|
||||
m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel);
|
||||
SetTP(m_TrainingPoints + getLevel());
|
||||
}
|
||||
}
|
||||
|
||||
void Pet::TickLoyaltyChange()
|
||||
{
|
||||
int32 addvalue;
|
||||
|
||||
switch(GetHappinessState())
|
||||
{
|
||||
case HAPPY: addvalue = 20; break;
|
||||
case CONTENT: addvalue = 10; break;
|
||||
case UNHAPPY: addvalue = -20; break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
ModifyLoyalty(addvalue);
|
||||
}
|
||||
|
||||
void Pet::KillLoyaltyBonus(uint32 level)
|
||||
{
|
||||
if(level > 100)
|
||||
return;
|
||||
|
||||
//at lower levels gain is faster | the lower loyalty the more loyalty is gained
|
||||
uint32 bonus = uint32(((100 - level) / 10) + (6 - GetLoyaltyLevel()));
|
||||
ModifyLoyalty(bonus);
|
||||
}
|
||||
|
||||
HappinessState Pet::GetHappinessState()
|
||||
{
|
||||
if(GetPower(POWER_HAPPINESS) < HAPPINESS_LEVEL_SIZE)
|
||||
|
|
@ -716,11 +605,6 @@ HappinessState Pet::GetHappinessState()
|
|||
return CONTENT;
|
||||
}
|
||||
|
||||
void Pet::SetLoyaltyLevel(LoyaltyLevel level)
|
||||
{
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, 1, level);
|
||||
}
|
||||
|
||||
bool Pet::CanTakeMoreActiveSpells(uint32 spellid)
|
||||
{
|
||||
uint8 activecount = 1;
|
||||
|
|
@ -757,82 +641,6 @@ bool Pet::CanTakeMoreActiveSpells(uint32 spellid)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Pet::HasTPForSpell(uint32 spellid)
|
||||
{
|
||||
int32 neededtrainp = GetTPForSpell(spellid);
|
||||
if((m_TrainingPoints - neededtrainp < 0 || neededtrainp < 0) && neededtrainp != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 Pet::GetTPForSpell(uint32 spellid)
|
||||
{
|
||||
uint32 basetrainp = 0;
|
||||
|
||||
SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spellid);
|
||||
SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spellid);
|
||||
for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
|
||||
{
|
||||
if(!_spell_idx->second->reqtrainpoints)
|
||||
return 0;
|
||||
|
||||
basetrainp = _spell_idx->second->reqtrainpoints;
|
||||
break;
|
||||
}
|
||||
|
||||
uint32 spenttrainp = 0;
|
||||
uint32 chainstart = spellmgr.GetFirstSpellInChain(spellid);
|
||||
|
||||
for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
|
||||
{
|
||||
if(itr->second->state == PETSPELL_REMOVED)
|
||||
continue;
|
||||
|
||||
if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart)
|
||||
{
|
||||
SkillLineAbilityMap::const_iterator _lower = spellmgr.GetBeginSkillLineAbilityMap(itr->first);
|
||||
SkillLineAbilityMap::const_iterator _upper = spellmgr.GetEndSkillLineAbilityMap(itr->first);
|
||||
|
||||
for(SkillLineAbilityMap::const_iterator _spell_idx2 = _lower; _spell_idx2 != _upper; ++_spell_idx2)
|
||||
{
|
||||
if(_spell_idx2->second->reqtrainpoints > spenttrainp)
|
||||
{
|
||||
spenttrainp = _spell_idx2->second->reqtrainpoints;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return int32(basetrainp) - int32(spenttrainp);
|
||||
}
|
||||
|
||||
uint32 Pet::GetMaxLoyaltyPoints(uint32 level)
|
||||
{
|
||||
return LevelUpLoyalty[level - 1];
|
||||
}
|
||||
|
||||
uint32 Pet::GetStartLoyaltyPoints(uint32 level)
|
||||
{
|
||||
return LevelStartLoyalty[level - 1];
|
||||
}
|
||||
|
||||
void Pet::SetTP(int32 TP)
|
||||
{
|
||||
m_TrainingPoints = TP;
|
||||
SetUInt32Value(UNIT_TRAINING_POINTS, (uint32)GetDispTP());
|
||||
}
|
||||
|
||||
int32 Pet::GetDispTP()
|
||||
{
|
||||
if(getPetType()!= HUNTER_PET)
|
||||
return(0);
|
||||
if(m_TrainingPoints < 0)
|
||||
return -m_TrainingPoints;
|
||||
else
|
||||
return -(m_TrainingPoints + 1);
|
||||
}
|
||||
|
||||
void Pet::Remove(PetSaveMode mode, bool returnreagent)
|
||||
{
|
||||
Unit* owner = GetOwner();
|
||||
|
|
@ -895,9 +703,6 @@ void Pet::GivePetXP(uint32 xp)
|
|||
}
|
||||
|
||||
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, newXP);
|
||||
|
||||
if(getPetType() == HUNTER_PET)
|
||||
KillLoyaltyBonus(level);
|
||||
}
|
||||
|
||||
void Pet::GivePetLevel(uint32 level)
|
||||
|
|
@ -905,9 +710,7 @@ void Pet::GivePetLevel(uint32 level)
|
|||
if(!level)
|
||||
return;
|
||||
|
||||
InitStatsForLevel( level);
|
||||
|
||||
SetTP(m_TrainingPoints + (GetLoyaltyLevel() - 1));
|
||||
InitStatsForLevel(level);
|
||||
}
|
||||
|
||||
bool Pet::CreateBaseAtCreature(Creature* creature)
|
||||
|
|
@ -949,14 +752,14 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
|
|||
}
|
||||
SetDisplayId(creature->GetDisplayId());
|
||||
SetNativeDisplayId(creature->GetNativeDisplayId());
|
||||
SetMaxPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS));
|
||||
SetPower( POWER_HAPPINESS,166500);
|
||||
SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
|
||||
SetPower(POWER_HAPPINESS, 166500);
|
||||
setPowerType(POWER_FOCUS);
|
||||
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
|
||||
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
|
||||
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
|
||||
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
|
||||
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((MaNGOS::XP::xp_to_level(creature->getLevel()))/4));
|
||||
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||
SetUInt32Value(UNIT_NPC_FLAGS , 0);
|
||||
SetUInt32Value(UNIT_NPC_FLAGS, 0);
|
||||
|
||||
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(creature->GetCreatureInfo()->family);
|
||||
if( char* familyname = cFamily->Name[sWorld.GetDefaultDbcLocale()] )
|
||||
|
|
@ -964,16 +767,12 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
|
|||
else
|
||||
SetName(creature->GetName());
|
||||
|
||||
m_loyaltyPoints = 1000;
|
||||
if(cinfo->type == CREATURE_TYPE_BEAST)
|
||||
{
|
||||
SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100);
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);
|
||||
|
||||
SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED) );
|
||||
SetLoyaltyLevel(REBELLIOUS);
|
||||
SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -992,7 +791,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
|
|||
|
||||
uint32 creature_ID = (getPetType() == HUNTER_PET) ? 1 : cinfo->Entry;
|
||||
|
||||
SetLevel( petlevel);
|
||||
SetLevel(petlevel);
|
||||
|
||||
SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool));
|
||||
|
||||
|
|
@ -1081,7 +880,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
|
|||
|
||||
for(int stat = 0; stat < MAX_STATS; ++stat)
|
||||
{
|
||||
SetCreateStat(Stats(stat),float(pInfo->stats[stat]));
|
||||
SetCreateStat(Stats(stat), float(pInfo->stats[stat]));
|
||||
}
|
||||
}
|
||||
else // not exist in DB, use some default fake data
|
||||
|
|
@ -1092,11 +891,11 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
|
|||
SetCreateHealth(uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel) );
|
||||
SetCreateMana( uint32(((float(cinfo->maxmana) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel) );
|
||||
|
||||
SetCreateStat(STAT_STRENGTH,22);
|
||||
SetCreateStat(STAT_AGILITY,22);
|
||||
SetCreateStat(STAT_STAMINA,25);
|
||||
SetCreateStat(STAT_INTELLECT,28);
|
||||
SetCreateStat(STAT_SPIRIT,27);
|
||||
SetCreateStat(STAT_STRENGTH, 22);
|
||||
SetCreateStat(STAT_AGILITY, 22);
|
||||
SetCreateStat(STAT_STAMINA, 25);
|
||||
SetCreateStat(STAT_INTELLECT, 28);
|
||||
SetCreateStat(STAT_SPIRIT, 27);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1131,34 +930,35 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
|
|||
// remove elite bonuses included in DB values
|
||||
SetCreateHealth( uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel) );
|
||||
|
||||
SetCreateStat(STAT_STRENGTH,22);
|
||||
SetCreateStat(STAT_AGILITY,22);
|
||||
SetCreateStat(STAT_STAMINA,25);
|
||||
SetCreateStat(STAT_INTELLECT,28);
|
||||
SetCreateStat(STAT_SPIRIT,27);
|
||||
SetCreateStat(STAT_STRENGTH, 22);
|
||||
SetCreateStat(STAT_AGILITY, 22);
|
||||
SetCreateStat(STAT_STAMINA, 25);
|
||||
SetCreateStat(STAT_INTELLECT, 28);
|
||||
SetCreateStat(STAT_SPIRIT, 27);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GUARDIAN_PET:
|
||||
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
|
||||
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
|
||||
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
|
||||
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
|
||||
|
||||
SetCreateMana( 28 + 10*petlevel );
|
||||
SetCreateHealth( 28 + 30*petlevel );
|
||||
SetCreateMana(28 + 10*petlevel);
|
||||
SetCreateHealth(28 + 30*petlevel);
|
||||
|
||||
// FIXME: this is wrong formula, possible each guardian pet have own damage formula
|
||||
//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)) );
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)));
|
||||
//damage range is then petlevel / 2
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)) );
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4)));
|
||||
break;
|
||||
default:
|
||||
sLog.outError("Pet have incorrect type (%u) for levelup.",getPetType()); break;
|
||||
sLog.outError("Pet have incorrect type (%u) for levelup.", getPetType());
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
|
||||
SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i]) );
|
||||
SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i]));
|
||||
|
||||
UpdateAllStats();
|
||||
|
||||
|
|
@ -1189,7 +989,7 @@ bool Pet::HaveInDiet(ItemPrototype const* item) const
|
|||
uint32 Pet::GetCurrentFoodBenefitLevel(uint32 itemlevel)
|
||||
{
|
||||
// -5 or greater food level
|
||||
if(getLevel() <= itemlevel +5) //possible to feed level 60 pet with level 55 level food for full effect
|
||||
if(getLevel() <= itemlevel + 5) //possible to feed level 60 pet with level 55 level food for full effect
|
||||
return 35000;
|
||||
// -10..-6
|
||||
else if(getLevel() <= itemlevel + 10) //pure guess, but sounds good
|
||||
|
|
@ -1239,7 +1039,7 @@ void Pet::_LoadSpellCooldowns()
|
|||
|
||||
_AddCreatureSpellCooldown(spell_id,db_time);
|
||||
|
||||
sLog.outDebug("Pet (Number: %u) spell %u cooldown loaded (%u secs).",m_charmInfo->GetPetNumber(),spell_id,uint32(db_time-curTime));
|
||||
sLog.outDebug("Pet (Number: %u) spell %u cooldown loaded (%u secs).", m_charmInfo->GetPetNumber(), spell_id, uint32(db_time-curTime));
|
||||
}
|
||||
while( result->NextRow() );
|
||||
|
||||
|
|
@ -1313,10 +1113,6 @@ void Pet::_LoadAuras(uint32 timediff)
|
|||
for (int i = 0; i < TOTAL_AURAS; i++)
|
||||
m_modAuras[i].clear();
|
||||
|
||||
// all aura related fields
|
||||
for(int i = UNIT_FIELD_AURA; i <= UNIT_FIELD_AURASTATE; ++i)
|
||||
SetUInt32Value(i, 0);
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,amount,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
|
||||
|
||||
if(result)
|
||||
|
|
@ -1382,7 +1178,7 @@ void Pet::_LoadAuras(uint32 timediff)
|
|||
|
||||
void Pet::_SaveAuras()
|
||||
{
|
||||
CharacterDatabase.PExecute("DELETE FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
|
||||
CharacterDatabase.PExecute("DELETE FROM pet_aura WHERE guid = '%u'", m_charmInfo->GetPetNumber());
|
||||
|
||||
AuraMap const& auras = GetAuras();
|
||||
for(AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
|
||||
|
|
@ -1483,7 +1279,7 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
|
|||
}
|
||||
}
|
||||
|
||||
uint16 tmpslot=slot_id;
|
||||
uint16 tmpslot = slot_id;
|
||||
|
||||
if (tmpslot == 0xffff)
|
||||
{
|
||||
|
|
@ -1500,6 +1296,16 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
|
|||
newspell->slotId = tmpslot;
|
||||
m_spells[spell_id] = newspell;
|
||||
|
||||
if(GetOwner()->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if(!IsPassiveSpell(spell_id))
|
||||
{
|
||||
WorldPacket data(SMSG_PET_LEARNED_SPELL, 2);
|
||||
data << uint16(spell_id);
|
||||
((Player*)GetOwner())->GetSession()->SendPacket(&data);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsPassiveSpell(spell_id))
|
||||
CastSpell(this, spell_id, true);
|
||||
else if(state == PETSPELL_NEW)
|
||||
|
|
@ -1518,7 +1324,7 @@ bool Pet::learnSpell(uint16 spell_id)
|
|||
return false;
|
||||
|
||||
Unit* owner = GetOwner();
|
||||
if(owner->GetTypeId()==TYPEID_PLAYER)
|
||||
if(owner->GetTypeId() == TYPEID_PLAYER)
|
||||
((Player*)owner)->PetSpellInitialize();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1541,6 +1347,16 @@ void Pet::removeSpell(uint16 spell_id)
|
|||
itr->second->state = PETSPELL_REMOVED;
|
||||
|
||||
RemoveAurasDueToSpell(spell_id);
|
||||
|
||||
if(GetOwner()->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if(!IsPassiveSpell(spell_id))
|
||||
{
|
||||
WorldPacket data(SMSG_PET_UNLEARNED_SPELL, 2);
|
||||
data << uint16(spell_id);
|
||||
((Player*)GetOwner())->GetSession()->SendPacket(&data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Pet::_removeSpell(uint16 spell_id)
|
||||
|
|
@ -1560,7 +1376,7 @@ void Pet::InitPetCreateSpells()
|
|||
m_charmInfo->InitPetActionBar();
|
||||
|
||||
m_spells.clear();
|
||||
int32 usedtrainpoints = 0, petspellid;
|
||||
int32 petspellid;
|
||||
PetCreateSpellEntry const* CreateSpells = objmgr.GetPetCreateSpellEntry(GetEntry());
|
||||
if(CreateSpells)
|
||||
{
|
||||
|
|
@ -1589,23 +1405,12 @@ void Pet::InitPetCreateSpells()
|
|||
petspellid = learn_spellproto->Id;
|
||||
|
||||
addSpell(petspellid);
|
||||
|
||||
SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]);
|
||||
SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]);
|
||||
|
||||
for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
|
||||
{
|
||||
usedtrainpoints += _spell_idx->second->reqtrainpoints;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LearnPetPassives();
|
||||
|
||||
CastPetAuras(false);
|
||||
|
||||
SetTP(-usedtrainpoints);
|
||||
}
|
||||
|
||||
void Pet::CheckLearning(uint32 spellid)
|
||||
|
|
@ -1693,8 +1498,7 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number)
|
|||
if(!InitEntry(Entry))
|
||||
return false;
|
||||
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
|
||||
|
||||
if(getPetType() == MINI_PET) // always non-attackable
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
|
|
@ -1735,7 +1539,7 @@ void Pet::CastPetAuras(bool current)
|
|||
if(getPetType() != HUNTER_PET && (getPetType() != SUMMON_PET || owner->getClass() != CLASS_WARLOCK))
|
||||
return;
|
||||
|
||||
for(PetAuraSet::iterator itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end(); )
|
||||
for(PetAuraSet::iterator itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end();)
|
||||
{
|
||||
PetAura const* pa = *itr;
|
||||
++itr;
|
||||
|
|
@ -1756,7 +1560,7 @@ void Pet::CastPetAura(PetAura const* aura)
|
|||
if(auraId == 35696) // Demonic Knowledge
|
||||
{
|
||||
int32 basePoints = int32(aura->GetDamage() * (GetStat(STAT_STAMINA) + GetStat(STAT_INTELLECT)) / 100);
|
||||
CastCustomSpell(this,auraId,&basePoints, NULL, NULL, true );
|
||||
CastCustomSpell(this, auraId, &basePoints, NULL, NULL, true);
|
||||
}
|
||||
else
|
||||
CastSpell(this, auraId, true);
|
||||
|
|
|
|||
|
|
@ -50,16 +50,6 @@ enum HappinessState
|
|||
HAPPY = 3
|
||||
};
|
||||
|
||||
enum LoyaltyLevel
|
||||
{
|
||||
REBELLIOUS = 1,
|
||||
UNRULY = 2,
|
||||
SUBMISSIVE = 3,
|
||||
DEPENDABLE = 4,
|
||||
FAITHFUL = 5,
|
||||
BEST_FRIEND = 6
|
||||
};
|
||||
|
||||
enum PetSpellState
|
||||
{
|
||||
PETSPELL_UNCHANGED = 0,
|
||||
|
|
@ -119,9 +109,6 @@ typedef std::vector<uint32> AutoSpellList;
|
|||
|
||||
#define HAPPINESS_LEVEL_SIZE 333000
|
||||
|
||||
extern const uint32 LevelUpLoyalty[6];
|
||||
extern const uint32 LevelStartLoyalty[6];
|
||||
|
||||
#define ACTIVE_SPELLS_MAX 4
|
||||
|
||||
#define OWNER_MAX_DISTANCE 100
|
||||
|
|
@ -144,7 +131,7 @@ class Pet : public Creature
|
|||
bool isTemporarySummoned() const { return m_duration > 0; }
|
||||
|
||||
bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number);
|
||||
bool CreateBaseAtCreature( Creature* creature );
|
||||
bool CreateBaseAtCreature(Creature* creature);
|
||||
bool LoadPetFromDB( Unit* owner,uint32 petentry = 0,uint32 petnumber = 0, bool current = false );
|
||||
void SavePetToDB(PetSaveMode mode);
|
||||
void Remove(PetSaveMode mode, bool returnreagent = false);
|
||||
|
|
@ -164,14 +151,7 @@ class Pet : public Creature
|
|||
|
||||
void RegenerateFocus();
|
||||
void LooseHappiness();
|
||||
void TickLoyaltyChange();
|
||||
void ModifyLoyalty(int32 addvalue);
|
||||
HappinessState GetHappinessState();
|
||||
uint32 GetMaxLoyaltyPoints(uint32 level);
|
||||
uint32 GetStartLoyaltyPoints(uint32 level);
|
||||
void KillLoyaltyBonus(uint32 level);
|
||||
uint32 GetLoyaltyLevel() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); }
|
||||
void SetLoyaltyLevel(LoyaltyLevel level);
|
||||
void GivePetXP(uint32 xp);
|
||||
void GivePetLevel(uint32 level);
|
||||
bool InitStatsForLevel(uint32 level);
|
||||
|
|
@ -191,10 +171,8 @@ class Pet : public Creature
|
|||
void UpdateAttackPowerAndDamage(bool ranged = false);
|
||||
void UpdateDamagePhysical(WeaponAttackType attType);
|
||||
|
||||
bool CanTakeMoreActiveSpells(uint32 SpellIconID);
|
||||
void ToggleAutocast(uint32 spellid, bool apply);
|
||||
bool HasTPForSpell(uint32 spellid);
|
||||
int32 GetTPForSpell(uint32 spellid);
|
||||
bool CanTakeMoreActiveSpells(uint32 SpellIconID);
|
||||
void ToggleAutocast(uint32 spellid, bool apply);
|
||||
|
||||
bool HasSpell(uint32 spell) const;
|
||||
void AddTeachSpell(uint32 learned_id, uint32 source_id) { m_teachspells[learned_id] = source_id; }
|
||||
|
|
@ -222,11 +200,10 @@ class Pet : public Creature
|
|||
void InitPetCreateSpells();
|
||||
void CheckLearning(uint32 spellid);
|
||||
uint32 resetTalentsCost() const;
|
||||
uint8 GetMaxTalentPointsForLevel(uint32 level) { return (level >= 20) ? ((level - 16) / 4) : 0; }
|
||||
uint8 GetFreeTalentPoints() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); }
|
||||
void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); }
|
||||
|
||||
void SetTP(int32 TP);
|
||||
int32 GetDispTP();
|
||||
|
||||
int32 m_TrainingPoints;
|
||||
uint32 m_resetTalentsCost;
|
||||
time_t m_resetTalentsTime;
|
||||
|
||||
|
|
@ -240,10 +217,8 @@ class Pet : public Creature
|
|||
protected:
|
||||
uint32 m_regenTimer;
|
||||
uint32 m_happinessTimer;
|
||||
uint32 m_loyaltyTimer;
|
||||
PetType m_petType;
|
||||
int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets)
|
||||
int32 m_loyaltyPoints;
|
||||
int32 m_bonusdamage;
|
||||
uint64 m_auraUpdateMask;
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
void WorldSession::HandlePetAction( WorldPacket & recv_data )
|
||||
{
|
||||
CHECK_PACKET_SIZE(recv_data,8+2+2+8);
|
||||
CHECK_PACKET_SIZE(recv_data, 8+2+2+8);
|
||||
|
||||
uint64 guid1;
|
||||
uint16 spellid;
|
||||
|
|
@ -46,8 +46,8 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
|
|||
recv_data >> guid2; //tag guid
|
||||
|
||||
// used also for charmed creature
|
||||
Unit* pet= ObjectAccessor::GetUnit(*_player,guid1);
|
||||
sLog.outDetail( "HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.\n", uint32(GUID_LOPART(guid1)), flag, spellid, uint32(GUID_LOPART(guid2)) );
|
||||
Unit* pet= ObjectAccessor::GetUnit(*_player, guid1);
|
||||
sLog.outDetail("HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.\n", uint32(GUID_LOPART(guid1)), flag, spellid, uint32(GUID_LOPART(guid2)) );
|
||||
if(!pet)
|
||||
{
|
||||
sLog.outError( "Pet %u not exist.\n", uint32(GUID_LOPART(guid1)) );
|
||||
|
|
@ -56,7 +56,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
|
|||
|
||||
if(pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm())
|
||||
{
|
||||
sLog.outError( "HandlePetAction.Pet %u isn't pet of player %s .\n", uint32(GUID_LOPART(guid1)),GetPlayer()->GetName() );
|
||||
sLog.outError("HandlePetAction.Pet %u isn't pet of player %s.\n", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName() );
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -234,7 +234,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
|
|||
if(pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
|
||||
{
|
||||
WorldPacket data(SMSG_CAST_FAILED, (4+1+1));
|
||||
data << uint32(spellid) << uint8(2) << uint8(result);
|
||||
data << uint8(0) << uint32(spellid) << uint8(result);
|
||||
switch (result)
|
||||
{
|
||||
case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
|
||||
|
|
@ -304,7 +304,7 @@ void WorldSession::SendPetNameQuery( uint64 petguid, uint32 petnumber)
|
|||
|
||||
void WorldSession::HandlePetSetAction( WorldPacket & recv_data )
|
||||
{
|
||||
CHECK_PACKET_SIZE(recv_data,8+4+2+2);
|
||||
CHECK_PACKET_SIZE(recv_data, 8+4+2+2);
|
||||
|
||||
sLog.outDetail( "HandlePetSetAction. CMSG_PET_SET_ACTION\n" );
|
||||
|
||||
|
|
@ -519,8 +519,6 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket)
|
|||
pet->removeSpell(spell_id);
|
||||
}
|
||||
|
||||
pet->SetTP(pet->getLevel() * (pet->GetLoyaltyLevel() - 1));
|
||||
|
||||
for(uint8 i = 0; i < 10; i++)
|
||||
{
|
||||
if(charmInfo->GetActionBarEntry(i)->SpellOrAction && charmInfo->GetActionBarEntry(i)->Type == ACT_ENABLED || charmInfo->GetActionBarEntry(i)->Type == ACT_DISABLED)
|
||||
|
|
@ -590,11 +588,15 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
|
|||
{
|
||||
sLog.outDetail("WORLD: CMSG_PET_CAST_SPELL");
|
||||
|
||||
CHECK_PACKET_SIZE(recvPacket,8+4);
|
||||
CHECK_PACKET_SIZE(recvPacket,8+1+4+1);
|
||||
uint64 guid;
|
||||
uint32 spellid;
|
||||
uint8 cast_count;
|
||||
uint8 unk_flags; // flags (if 0x02 - some additional data are received)
|
||||
|
||||
recvPacket >> guid >> spellid;
|
||||
recvPacket >> guid >> cast_count >> spellid >> unk_flags;
|
||||
|
||||
sLog.outDebug("WORLD: CMSG_PET_CAST_SPELL, cast_count: %u, spellid %u, unk_flags %u", cast_count, spellid, unk_flags);
|
||||
|
||||
if(!_player->GetPet() && !_player->GetCharm())
|
||||
return;
|
||||
|
|
@ -628,6 +630,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
|
|||
pet->clearUnitState(UNIT_STAT_FOLLOW);
|
||||
|
||||
Spell *spell = new Spell(pet, spellInfo, false);
|
||||
spell->m_cast_count = cast_count; // probably pending spell cast
|
||||
spell->m_targets = targets;
|
||||
|
||||
int16 result = spell->PetCanCast(NULL);
|
||||
|
|
@ -674,3 +677,129 @@ void WorldSession::SendPetNameInvalid(uint32 error, std::string name, DeclinedNa
|
|||
data << uint8(0);
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::HandlePetLearnTalent( WorldPacket & recv_data )
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_PET_LEARN_TALENT");
|
||||
recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 8+4+4);
|
||||
|
||||
uint64 guid;
|
||||
uint32 talent_id, requested_rank;
|
||||
recv_data >> guid >> talent_id >> requested_rank;
|
||||
|
||||
Pet *pet = _player->GetPet();
|
||||
|
||||
if(!pet)
|
||||
return;
|
||||
|
||||
if(guid != pet->GetGUID())
|
||||
return;
|
||||
|
||||
uint32 CurTalentPoints = pet->GetFreeTalentPoints();
|
||||
|
||||
if(CurTalentPoints == 0)
|
||||
return;
|
||||
|
||||
if (requested_rank > 4)
|
||||
return;
|
||||
|
||||
TalentEntry const *talentInfo = sTalentStore.LookupEntry(talent_id);
|
||||
|
||||
if(!talentInfo)
|
||||
return;
|
||||
|
||||
TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab);
|
||||
|
||||
if(!talentTabInfo)
|
||||
return;
|
||||
|
||||
CreatureInfo const *ci = pet->GetCreatureInfo();
|
||||
|
||||
if(!ci)
|
||||
return;
|
||||
|
||||
CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family);
|
||||
|
||||
if(!pet_family)
|
||||
return;
|
||||
|
||||
// prevent learn talent for different family (cheating)
|
||||
if(!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask))
|
||||
return;
|
||||
|
||||
// prevent skip talent ranks (cheating)
|
||||
if(requested_rank > 0 && !pet->HasSpell(talentInfo->RankID[requested_rank-1]))
|
||||
return;
|
||||
|
||||
// Check if it requires another talent
|
||||
if (talentInfo->DependsOn > 0)
|
||||
{
|
||||
if(TalentEntry const *depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn))
|
||||
{
|
||||
bool hasEnoughRank = false;
|
||||
for (int i = talentInfo->DependsOnRank; i <= 4; i++)
|
||||
{
|
||||
if (depTalentInfo->RankID[i] != 0)
|
||||
if (pet->HasSpell(depTalentInfo->RankID[i]))
|
||||
hasEnoughRank = true;
|
||||
}
|
||||
if (!hasEnoughRank)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Find out how many points we have in this field
|
||||
uint32 spentPoints = 0;
|
||||
|
||||
uint32 tTab = talentInfo->TalentTab;
|
||||
if (talentInfo->Row > 0)
|
||||
{
|
||||
unsigned int numRows = sTalentStore.GetNumRows();
|
||||
for (unsigned int i = 0; i < numRows; i++) // Loop through all talents.
|
||||
{
|
||||
// Someday, someone needs to revamp
|
||||
const TalentEntry *tmpTalent = sTalentStore.LookupEntry(i);
|
||||
if (tmpTalent) // the way talents are tracked
|
||||
{
|
||||
if (tmpTalent->TalentTab == tTab)
|
||||
{
|
||||
for (int j = 0; j <= 4; j++)
|
||||
{
|
||||
if (tmpTalent->RankID[j] != 0)
|
||||
{
|
||||
if (pet->HasSpell(tmpTalent->RankID[j]))
|
||||
{
|
||||
spentPoints += j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not have required min points spent in talent tree
|
||||
if(spentPoints < (talentInfo->Row * 3))
|
||||
return;
|
||||
|
||||
// spell not set in talent.dbc
|
||||
uint32 spellid = talentInfo->RankID[requested_rank];
|
||||
if( spellid == 0 )
|
||||
{
|
||||
sLog.outError("Talent.dbc have for talent: %u Rank: %u spell id = 0", talent_id, requested_rank);
|
||||
return;
|
||||
}
|
||||
|
||||
// already known
|
||||
if(pet->HasSpell(spellid))
|
||||
return;
|
||||
|
||||
// learn! (other talent ranks will unlearned at learning)
|
||||
pet->learnSpell(spellid);
|
||||
sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid);
|
||||
|
||||
// update free talent points
|
||||
pet->SetFreeTalentPoints(CurTalentPoints - 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,9 +209,9 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
|
|||
if(!charter)
|
||||
return;
|
||||
|
||||
charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT, charter->GetGUIDLow());
|
||||
// ITEM_FIELD_ENCHANTMENT is guild/arenateam id
|
||||
// ITEM_FIELD_ENCHANTMENT+1 is current signatures count (showed on item)
|
||||
charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow());
|
||||
// ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id
|
||||
// ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item)
|
||||
charter->SetState(ITEM_CHANGED, _player);
|
||||
_player->SendNewItem(charter, 1, true, false);
|
||||
|
||||
|
|
@ -574,7 +574,7 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
|
|||
// update signs count on charter, required testing...
|
||||
//Item *item = _player->GetItemByGuid(petitionguid));
|
||||
//if(item)
|
||||
// item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+1, signs);
|
||||
// item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs);
|
||||
|
||||
// update for owner if online
|
||||
if(Player *owner = objmgr.GetPlayer(ownerguid))
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -540,7 +540,7 @@ enum PlayerSlots
|
|||
// first slot for item stored (in any way in player m_items data)
|
||||
PLAYER_SLOT_START = 0,
|
||||
// last+1 slot for item stored (in any way in player m_items data)
|
||||
PLAYER_SLOT_END = 118,
|
||||
PLAYER_SLOT_END = 200,
|
||||
PLAYER_SLOTS_COUNT = (PLAYER_SLOT_END - PLAYER_SLOT_START)
|
||||
};
|
||||
|
||||
|
|
@ -668,6 +668,24 @@ enum KeyRingSlots
|
|||
KEYRING_SLOT_END = 118
|
||||
};
|
||||
|
||||
enum VanityPetSlots
|
||||
{
|
||||
VANITYPET_SLOT_START = 118,
|
||||
VANITYPET_SLOT_END = 136
|
||||
};
|
||||
|
||||
enum CurrencyTokenSlots
|
||||
{
|
||||
CURRENCYTOKEN_SLOT_START = 136,
|
||||
CURRENCYTOKEN_SLOT_END = 168
|
||||
};
|
||||
|
||||
enum QuestBagSlots
|
||||
{
|
||||
QUESTBAG_SLOT_START = 168,
|
||||
QUESTBAG_SLOT_END = 200
|
||||
};
|
||||
|
||||
struct ItemPosCount
|
||||
{
|
||||
ItemPosCount(uint16 _pos, uint8 _count) : pos(_pos), count(_count) {}
|
||||
|
|
@ -714,14 +732,15 @@ struct MovementInfo
|
|||
{
|
||||
// common
|
||||
//uint32 flags;
|
||||
uint8 unk1;
|
||||
uint16 unk1;
|
||||
uint32 time;
|
||||
float x, y, z, o;
|
||||
// transport
|
||||
uint64 t_guid;
|
||||
float t_x, t_y, t_z, t_o;
|
||||
uint32 t_time;
|
||||
// swimming and unk
|
||||
uint8 t_unk;
|
||||
// swimming and unknown
|
||||
float s_pitch;
|
||||
// last fall time
|
||||
uint32 fallTime;
|
||||
|
|
@ -943,6 +962,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
std::string afkMsg;
|
||||
std::string dndMsg;
|
||||
|
||||
uint32 GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair);
|
||||
|
||||
PlayerSocial *GetSocial() { return m_social; }
|
||||
|
||||
PlayerTaxi m_taxi;
|
||||
|
|
@ -1410,6 +1431,12 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
uint32 resetTalentsCost() const;
|
||||
void InitTalentForLevel();
|
||||
|
||||
void InitGlyphsForLevel();
|
||||
void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); }
|
||||
uint32 GetGlyphSlot(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); }
|
||||
void SetGlyph(uint8 slot, uint32 glyph) { SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph); }
|
||||
uint32 GetGlyph(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot); }
|
||||
|
||||
uint32 GetFreePrimaryProffesionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS2); }
|
||||
void SetFreePrimaryProffesions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS2,profs); }
|
||||
void InitPrimaryProffesions();
|
||||
|
|
@ -1782,7 +1809,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
void SendUpdateWorldState(uint32 Field, uint32 Value);
|
||||
void SendDirectMessage(WorldPacket *data);
|
||||
|
||||
void SendAuraDurationsForTarget(Unit* target);
|
||||
void SendAurasForTarget(Unit *target);
|
||||
|
||||
PlayerMenu* PlayerTalkClass;
|
||||
std::vector<ItemSetEffect *> ItemSetEff;
|
||||
|
|
@ -1930,6 +1957,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
float GetTransOffsetZ() const { return m_movementInfo.t_z; }
|
||||
float GetTransOffsetO() const { return m_movementInfo.t_o; }
|
||||
uint32 GetTransTime() const { return m_movementInfo.t_time; }
|
||||
uint8 GetTransUnk() const { return m_movementInfo.t_unk; }
|
||||
|
||||
uint32 GetSaveTimer() const { return m_nextSave; }
|
||||
void SetSaveTimer(uint32 timer) { m_nextSave = timer; }
|
||||
|
|
|
|||
|
|
@ -183,6 +183,8 @@ Unit::Unit()
|
|||
m_ShapeShiftFormSpellId = 0;
|
||||
m_canModifyStats = false;
|
||||
|
||||
for (int i = 0; i < MAX_AURAS; ++i)
|
||||
m_visibleAuras[i] = 0;
|
||||
for (int i = 0; i < MAX_SPELL_IMMUNITY; i++)
|
||||
m_spellImmune[i].clear();
|
||||
for (int i = 0; i < UNIT_MOD_END; i++)
|
||||
|
|
@ -2124,7 +2126,7 @@ void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDama
|
|||
((*itr).second->GetCasterGUID() == GetGUID() && (!spellCasted || spellCasted->Id == 35395)) )
|
||||
{
|
||||
(*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration());
|
||||
(*itr).second->UpdateAuraDuration();
|
||||
(*itr).second->SendAuraUpdate(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4170,7 +4172,7 @@ void Unit::DelayAura(uint32 spellId, uint32 effindex, int32 delaytime)
|
|||
iter->second->SetAuraDuration(0);
|
||||
else
|
||||
iter->second->SetAuraDuration(iter->second->GetAuraDuration() - delaytime);
|
||||
iter->second->UpdateAuraDuration();
|
||||
iter->second->SendAuraUpdate(false);
|
||||
sLog.outDebug("Aura %u partially interrupted on unit %u, new duration: %u ms",iter->second->GetModifier()->m_auraname, GetGUIDLow(), iter->second->GetAuraDuration());
|
||||
}
|
||||
}
|
||||
|
|
@ -4344,6 +4346,7 @@ void Unit::SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage,
|
|||
data.append(GetPackGUID());
|
||||
data << uint32(SpellID);
|
||||
data << uint32(Damage-AbsorbedDamage-Resist-Blocked);
|
||||
data << uint32(0); // wotlk
|
||||
data << uint8(damageSchoolMask); // spell school
|
||||
data << uint32(AbsorbedDamage); // AbsorbedDamage
|
||||
data << uint32(Resist); // resist
|
||||
|
|
@ -4377,28 +4380,63 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType,
|
|||
data << (uint32)HitInfo;
|
||||
data.append(GetPackGUID());
|
||||
data.append(target->GetPackGUID());
|
||||
data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount);
|
||||
data << uint32(Damage-AbsorbDamage-Resist-BlockedAmount);
|
||||
data << uint32(0); // WotLK
|
||||
|
||||
data << (uint8)SwingType; // count?
|
||||
|
||||
// for(i = 0; i < SwingType; ++i)
|
||||
data << (uint32)damageSchoolMask;
|
||||
data << (float)(Damage-AbsorbDamage-Resist-BlockedAmount);
|
||||
// still need to double check damage
|
||||
data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount);
|
||||
data << (uint32)AbsorbDamage;
|
||||
data << (uint32)Resist;
|
||||
// end loop
|
||||
|
||||
data << (uint32)TargetState;
|
||||
if(HitInfo & (HITINFO_RESIST | HITINFO_ABSORB))
|
||||
{
|
||||
// for(i = 0; i < SwingType; ++i)
|
||||
data << (uint32)Resist;
|
||||
// end loop
|
||||
}
|
||||
|
||||
if( AbsorbDamage == 0 ) //also 0x3E8 = 0x3E8, check when that happens
|
||||
data << (uint32)0;
|
||||
else
|
||||
data << (uint32)-1;
|
||||
if(HitInfo & (HITINFO_CRITICALHIT | HITINFO_UNK2))
|
||||
{
|
||||
// for(i = 0; i < SwingType; ++i)
|
||||
data << uint32(0); // what is it?
|
||||
// end loop
|
||||
}
|
||||
|
||||
data << (uint8)TargetState;
|
||||
data << (uint32)0;
|
||||
data << (uint32)BlockedAmount;
|
||||
data << (uint32)0;
|
||||
|
||||
if(HitInfo & HITINFO_UNK3)
|
||||
{
|
||||
data << uint32(0);
|
||||
}
|
||||
|
||||
/*if(unknown & HitInfo)
|
||||
{
|
||||
data << uint32(0);
|
||||
}*/
|
||||
|
||||
/*if(HitInfo & HITINFO_UNK1)
|
||||
{
|
||||
data << uint32(0);
|
||||
data << float(0);
|
||||
data << float(0);
|
||||
data << float(0);
|
||||
data << float(0);
|
||||
data << float(0);
|
||||
data << float(0);
|
||||
data << float(0);
|
||||
data << float(0);
|
||||
for(uint8 i = 0; i < 5; ++i)
|
||||
{
|
||||
data << float(0);
|
||||
data << float(0);
|
||||
}
|
||||
data << uint32(0);
|
||||
}*/
|
||||
|
||||
SendMessageToSet( &data, true );
|
||||
}
|
||||
|
|
@ -7089,7 +7127,7 @@ Unit* Unit::GetCharm() const
|
|||
|
||||
void Unit::SetPet(Pet* pet)
|
||||
{
|
||||
SetUInt64Value(UNIT_FIELD_SUMMON,pet ? pet->GetGUID() : 0);
|
||||
SetUInt64Value(UNIT_FIELD_SUMMON, pet ? pet->GetGUID() : 0);
|
||||
|
||||
// FIXME: hack, speed must be set only at follow
|
||||
if(pet)
|
||||
|
|
@ -8896,7 +8934,7 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
|
|||
|
||||
data.append(GetPackGUID());
|
||||
data << uint32(0); //movement flags
|
||||
data << uint8(0); //unk
|
||||
data << uint16(0); //unk
|
||||
data << uint32(getMSTime());
|
||||
data << float(GetPositionX());
|
||||
data << float(GetPositionY());
|
||||
|
|
@ -9648,6 +9686,12 @@ void Unit::SetPower(Powers power, uint32 val)
|
|||
|
||||
SetStatInt32Value(UNIT_FIELD_POWER1 + power, val);
|
||||
|
||||
WorldPacket data(SMSG_POWER_UPDATE);
|
||||
data.append(GetPackGUID());
|
||||
data << uint8(power);
|
||||
data << uint32(val);
|
||||
SendMessageToSet(&data, GetTypeId() == TYPEID_PLAYER ? true : false);
|
||||
|
||||
// group update
|
||||
if(GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
|
|
@ -9761,6 +9805,7 @@ uint32 Unit::GetCreatePowers( Powers power ) const
|
|||
case POWER_FOCUS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 100);
|
||||
case POWER_ENERGY: return 100;
|
||||
case POWER_HAPPINESS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 1050000);
|
||||
case POWER_RUNIC_POWER: return 1000;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -10272,8 +10317,11 @@ void Unit::SendPetCastFail(uint32 spellid, uint8 msg)
|
|||
return;
|
||||
|
||||
WorldPacket data(SMSG_PET_CAST_FAILED, (4+1));
|
||||
data << uint8(0); // cast count?
|
||||
data << uint32(spellid);
|
||||
data << uint8(msg);
|
||||
// uint32 for some reason
|
||||
// uint32 for some reason
|
||||
((Player*)owner)->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -413,10 +413,11 @@ enum CombatRating
|
|||
CR_WEAPON_SKILL_MAINHAND = 20,
|
||||
CR_WEAPON_SKILL_OFFHAND = 21,
|
||||
CR_WEAPON_SKILL_RANGED = 22,
|
||||
CR_EXPERTISE = 23
|
||||
CR_EXPERTISE = 23,
|
||||
CR_ARMOR_PENETRATION = 24
|
||||
};
|
||||
|
||||
#define MAX_COMBAT_RATING 24
|
||||
#define MAX_COMBAT_RATING 25
|
||||
|
||||
enum DamageEffectType
|
||||
{
|
||||
|
|
@ -1125,6 +1126,9 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
|||
void removeHatedBy(HostilReference* /*pHostilReference*/ ) { /* nothing to do yet */ }
|
||||
HostilRefManager& getHostilRefManager() { return m_HostilRefManager; }
|
||||
|
||||
uint32 GetVisibleAura(uint32 slot) { return m_visibleAuras[slot]; }
|
||||
void SetVisibleAura(uint32 slot, uint32 spellid) { m_visibleAuras[slot] = spellid; }
|
||||
|
||||
Aura* GetAura(uint32 spellId, uint32 effindex);
|
||||
AuraMap & GetAuras() { return m_Auras; }
|
||||
AuraMap const& GetAuras() const { return m_Auras; }
|
||||
|
|
@ -1297,6 +1301,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
|||
float m_weaponDamage[MAX_ATTACK][2];
|
||||
bool m_canModifyStats;
|
||||
//std::list< spellEffectPair > AuraSpells[TOTAL_AURAS]; // TODO: use this if ok for mem
|
||||
uint32 m_visibleAuras[MAX_AURAS];
|
||||
|
||||
float m_speed_rate[MAX_MOVE_TYPE];
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue