Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2025-01-23 23:23:53 +08:00
77 changed files with 1682 additions and 1680 deletions

View File

@@ -1001,43 +1001,25 @@ void GameObject::Delete()
AddObjectToRemoveList();
}
void GameObject::GetFishLoot(Loot* fishloot, Player* loot_owner)
void GameObject::GetFishLoot(Loot* fishLoot, Player* lootOwner, bool junk /*= false*/)
{
fishloot->clear();
fishLoot->clear();
uint32 zone, subzone;
uint32 defaultzone = 1;
GetZoneAndAreaId(zone, subzone);
uint32 zone, area;
uint32 defaultZone = 1;
GetZoneAndAreaId(zone, area);
// if subzone loot exist use it
fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, true);
if (fishloot->empty()) //use this becase if zone or subzone has set LOOT_MODE_JUNK_FISH,Even if no normal drop, fishloot->FillLoot return true. it wrong.
uint16 lootMode = junk ? LOOT_MODE_JUNK_FISH : LOOT_MODE_DEFAULT;
// Check to fill loot in the order area - zone - defaultZone.
// This is because area and zone is not set in some places, like Off the coast of Storm Peaks.
uint32 lootZones[] = { area, zone, defaultZone };
for (uint32 fillZone : lootZones)
{
//subzone no result,use zone loot
fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner, true, true);
//use zone 1 as default, somewhere fishing got nothing,becase subzone and zone not set, like Off the coast of Storm Peaks.
if (fishloot->empty())
fishloot->FillLoot(defaultzone, LootTemplates_Fishing, loot_owner, true, true);
}
}
fishLoot->FillLoot(fillZone, LootTemplates_Fishing, lootOwner, true, true, lootMode);
void GameObject::GetFishLootJunk(Loot* fishloot, Player* loot_owner)
{
fishloot->clear();
uint32 zone, subzone;
uint32 defaultzone = 1;
GetZoneAndAreaId(zone, subzone);
// if subzone loot exist use it
fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH);
if (fishloot->empty()) //use this becase if zone or subzone has normal mask drop, then fishloot->FillLoot return true.
{
//use zone loot
fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH);
if (fishloot->empty())
//use zone 1 as default
fishloot->FillLoot(defaultzone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH);
// If the loot is filled and the loot is eligible, then we break out of the loop.
if (!fishLoot->empty() && !fishLoot->isLooted())
break;
}
}

View File

@@ -198,8 +198,7 @@ public:
void Refresh();
void DespawnOrUnsummon(Milliseconds delay = 0ms, Seconds forcedRespawnTime = 0s);
void Delete();
void GetFishLoot(Loot* loot, Player* loot_owner);
void GetFishLootJunk(Loot* loot, Player* loot_owner);
void GetFishLoot(Loot* fishLoot, Player* lootOwner, bool junk = false);
[[nodiscard]] GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); }
void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); }
[[nodiscard]] GOState GetGoState() const { return GOState(GetByteValue(GAMEOBJECT_BYTES_1, 0)); }

View File

@@ -7896,7 +7896,7 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
if (loot_type == LOOT_FISHING)
go->GetFishLoot(loot, this);
else if (loot_type == LOOT_FISHING_JUNK)
go->GetFishLootJunk(loot, this);
go->GetFishLoot(loot, this, true);
if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_CHEST && go->GetGOInfo()->chest.groupLootRules)
{
@@ -13111,7 +13111,7 @@ PartyResult Player::CanUninviteFromGroup(ObjectGuid targetPlayerGUID) const
return ERR_PARTY_RESULT_OK;
}
bool Player::isUsingLfg()
bool Player::IsUsingLfg()
{
return sLFGMgr->GetState(GetGUID()) != lfg::LFG_STATE_NONE;
}

View File

@@ -2062,6 +2062,7 @@ public:
bool IsInChannel(const Channel* c);
void CleanupChannels();
void ClearChannelWatch();
void UpdateLFGChannel();
void UpdateLocalChannels(uint32 newZone);
void UpdateDefense();
@@ -2397,7 +2398,7 @@ public:
void SetAtLoginFlag(AtLoginFlags f) { m_atLoginFlags |= f; }
void RemoveAtLoginFlag(AtLoginFlags flags, bool persist = false);
bool isUsingLfg();
bool IsUsingLfg();
bool inRandomLfgDungeon();
typedef std::set<uint32> DFQuestsDoneList;

View File

@@ -5687,7 +5687,8 @@ void Player::_LoadActions(PreparedQueryResult result)
ab->uState = ACTIONBUTTON_UNCHANGED;
else
{
LOG_ERROR("entities.player", "ActionButton loading problem, will be deleted from db...");
LOG_ERROR("entities.player", "ActionButton loading problem, will be deleted from db. player: {}, guid: {}, button: {}, action: {}, type: {}", GetName(), GetGUID().GetCounter(), button, action, type);
// Will deleted in DB at next save (it can create data until save but marked as deleted)
m_actionButtons[button].uState = ACTIONBUTTON_DELETED;

View File

@@ -462,6 +462,44 @@ void Player::UpdateNextMailTimeAndUnreads()
}
}
void Player::UpdateLFGChannel()
{
if (!sWorld->getBoolConfig(CONFIG_RESTRICTED_LFG_CHANNEL))
return;
ChannelMgr* cMgr = ChannelMgr::forTeam(GetTeamId());
if (!cMgr)
return;
ChatChannelsEntry const* cce = sChatChannelsStore.LookupEntry(26); /*LookingForGroup*/
Channel* cLFG = cMgr->GetJoinChannel(cce->pattern[m_session->GetSessionDbcLocale()], cce->ChannelID);
if (!cLFG)
return;
Channel* cUsed = nullptr;
for (Channel* channel : m_channels)
if (channel && channel->GetChannelId() == cce->ChannelID)
{
cUsed = cLFG;
break;
}
if (IsUsingLfg())
{
if (cUsed == cLFG)
return;
cLFG->JoinChannel(this, "");
}
else
{
if (cLFG != cUsed)
return;
cLFG->LeaveChannel(this, true);
}
}
void Player::UpdateLocalChannels(uint32 newZone)
{
// pussywizard: mutex needed (tc changed opcode to THREAD UNSAFE)

View File

@@ -10401,6 +10401,10 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
if (meleeAttack)
AddUnitState(UNIT_STATE_MELEE_ATTACKING);
// Update leash timer when attacking creatures
if (victim->IsCreature())
victim->ToCreature()->UpdateLeashExtensionTime();
// set position before any AI calls/assistance
//if (IsCreature())
// ToCreature()->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
@@ -10410,6 +10414,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
SetInCombatWith(victim);
if (victim->IsPlayer())
victim->SetInCombatWith(this);
AddThreat(victim, 0.0f);
creature->SendAIReaction(AI_REACTION_HOSTILE);
@@ -13640,9 +13645,6 @@ void Unit::SetInCombatWith(Unit* enemy, uint32 duration)
}
}
if (Creature* pCreature = ToCreature())
pCreature->UpdateLeashExtensionTime();
SetInCombatState(false, enemy, duration);
}
@@ -13717,6 +13719,10 @@ void Unit::CombatStart(Unit* victim, bool initialAggro)
SetInCombatWith(victim);
victim->SetInCombatWith(this);
// Update leash timer when attacking creatures
if (victim->IsCreature())
victim->ToCreature()->UpdateLeashExtensionTime();
// Xinef: If pet started combat - put owner in combat
if (!alreadyInCombat && IsInCombat())
{
@@ -13753,6 +13759,12 @@ void Unit::CombatStartOnCast(Unit* target, bool initialAggro, uint32 duration)
// Xinef: If pet started combat - put owner in combat
if (Unit* owner = GetOwner())
owner->SetInCombatWith(target, duration);
// Update leash timer when attacking creatures
if (target->IsCreature())
target->ToCreature()->UpdateLeashExtensionTime();
else if (ToCreature()) // Reset leash if it is a spell caster, else it may evade inbetween casts
ToCreature()->UpdateLeashExtensionTime();
}
Unit* who = target->GetCharmerOrOwnerOrSelf();