Pet Battles: Fix weather/environment effects not showing in client UI
SetWeather() updated internal state but never emitted round effects, so the client never knew weather was applied. Weather expiry also had no AURA_CANCEL, leaving stale icons. InitialUpdate Enviros array was never populated with active weather data. - SetWeather() now emits AURA_APPLY targeting environment PBOID (6+) - Previous weather is cancelled before new weather is applied - Cleansing weather emits AURA_CANCEL for all active environment auras - TickWeather() emits AURA_CANCEL when weather duration expires - BuildPetBattleEnviros() populates InitialUpdate Enviros in all paths - Added PBOID_ENVIRONMENT_BASE constant and TargetEnvSlot field for environment-targeted round effects
This commit is contained in:
@@ -1669,27 +1669,64 @@ namespace PetBattles
|
||||
{
|
||||
if (weatherType == PET_BATTLE_WEATHER_CLEANSING)
|
||||
{
|
||||
// Clear all weather
|
||||
for (auto& env : _environments)
|
||||
// Clear all weather ? emit AURA_CANCEL for any active environment auras
|
||||
for (uint8 i = 0; i < MAX_PET_BATTLE_ENVIRONMENTS; ++i)
|
||||
{
|
||||
env.WeatherType = PET_BATTLE_WEATHER_NONE;
|
||||
env.AbilityID = 0;
|
||||
env.RemainingRounds = 0;
|
||||
if (_environments[i].WeatherType != PET_BATTLE_WEATHER_NONE && _environments[i].AuraInstanceID != 0)
|
||||
{
|
||||
PetBattleRoundEffect cancelEffect;
|
||||
cancelEffect.EffectType = PET_BATTLE_EFFECT_AURA_CANCEL;
|
||||
cancelEffect.TargetEnvSlot = static_cast<int8>(i);
|
||||
cancelEffect.Param1 = _environments[i].AuraInstanceID;
|
||||
cancelEffect.Param2 = _environments[i].AbilityID;
|
||||
_roundEffects.push_back(cancelEffect);
|
||||
}
|
||||
_environments[i].WeatherType = PET_BATTLE_WEATHER_NONE;
|
||||
_environments[i].AbilityID = 0;
|
||||
_environments[i].RemainingRounds = 0;
|
||||
_environments[i].AuraInstanceID = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancel existing weather on slot 0 if any
|
||||
if (_environments[0].WeatherType != PET_BATTLE_WEATHER_NONE && _environments[0].AuraInstanceID != 0)
|
||||
{
|
||||
PetBattleRoundEffect cancelEffect;
|
||||
cancelEffect.EffectType = PET_BATTLE_EFFECT_AURA_CANCEL;
|
||||
cancelEffect.TargetEnvSlot = 0;
|
||||
cancelEffect.Param1 = _environments[0].AuraInstanceID;
|
||||
cancelEffect.Param2 = _environments[0].AbilityID;
|
||||
_roundEffects.push_back(cancelEffect);
|
||||
}
|
||||
|
||||
// Slot 0 is the shared battlefield weather
|
||||
_environments[0].AbilityID = abilityID;
|
||||
_environments[0].WeatherType = weatherType;
|
||||
_environments[0].RemainingRounds = duration;
|
||||
_environments[0].CasterTeam = casterTeam;
|
||||
_environments[0].AuraInstanceID = _nextAuraInstanceID++;
|
||||
_environments[0].CurrentRound = _currentRound;
|
||||
|
||||
// Emit AURA_APPLY targeting environment PBOID so client shows weather
|
||||
PetBattleRoundEffect applyEffect;
|
||||
applyEffect.AbilityEffectID = abilityID;
|
||||
applyEffect.EffectType = PET_BATTLE_EFFECT_AURA_APPLY;
|
||||
applyEffect.SourceTeam = casterTeam;
|
||||
applyEffect.SourcePet = _teams[casterTeam].FrontPetIndex;
|
||||
applyEffect.TargetEnvSlot = 0; // Environment slot 0 = shared battlefield weather
|
||||
applyEffect.Param1 = _environments[0].AuraInstanceID;
|
||||
applyEffect.Param2 = abilityID;
|
||||
applyEffect.Param3 = duration;
|
||||
applyEffect.Param4 = _currentRound;
|
||||
_roundEffects.push_back(applyEffect);
|
||||
}
|
||||
|
||||
void PetBattle::TickWeather()
|
||||
{
|
||||
for (auto& env : _environments)
|
||||
for (uint8 envSlot = 0; envSlot < MAX_PET_BATTLE_ENVIRONMENTS; ++envSlot)
|
||||
{
|
||||
PetBattleEnvironment& env = _environments[envSlot];
|
||||
if (env.WeatherType == PET_BATTLE_WEATHER_NONE)
|
||||
continue;
|
||||
|
||||
@@ -1726,8 +1763,19 @@ namespace PetBattles
|
||||
|
||||
if (env.RemainingRounds <= 0)
|
||||
{
|
||||
// Emit AURA_CANCEL so client removes the weather icon
|
||||
if (env.AuraInstanceID != 0)
|
||||
{
|
||||
PetBattleRoundEffect cancelEffect;
|
||||
cancelEffect.EffectType = PET_BATTLE_EFFECT_AURA_CANCEL;
|
||||
cancelEffect.TargetEnvSlot = static_cast<int8>(envSlot);
|
||||
cancelEffect.Param1 = env.AuraInstanceID;
|
||||
cancelEffect.Param2 = env.AbilityID;
|
||||
_roundEffects.push_back(cancelEffect);
|
||||
}
|
||||
env.WeatherType = PET_BATTLE_WEATHER_NONE;
|
||||
env.AbilityID = 0;
|
||||
env.AuraInstanceID = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@ namespace PetBattles
|
||||
PetBattleWeatherType WeatherType = PET_BATTLE_WEATHER_NONE;
|
||||
int8 RemainingRounds = 0;
|
||||
uint8 CasterTeam = 0;
|
||||
uint32 AuraInstanceID = 0; // Unique ID for the environment aura (sent to client)
|
||||
int32 CurrentRound = 0; // Round when weather was applied
|
||||
};
|
||||
|
||||
struct PetBattlePetData
|
||||
@@ -214,6 +216,7 @@ namespace PetBattles
|
||||
int32 Param2 = 0;
|
||||
int32 Param3 = 0; // For aura effects: RoundsRemaining (captured at creation time)
|
||||
int32 Param4 = 0; // For aura effects: CurrentRound (captured at creation time)
|
||||
int8 TargetEnvSlot = -1; // >= 0: target is environment slot (PBOID = PBOID_ENVIRONMENT_BASE + slot)
|
||||
};
|
||||
|
||||
class TC_GAME_API PetBattle
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
#define TRINITYCORE_PET_BATTLE_DEFINES_H
|
||||
|
||||
#include "Define.h"
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
namespace PetBattles
|
||||
{
|
||||
@@ -34,6 +34,7 @@ namespace PetBattles
|
||||
static constexpr uint32 PET_BATTLE_TRAP_ABILITY_ID = 427; // "Trap" ability used for capture
|
||||
static constexpr uint32 MAX_PET_BATTLE_AURAS = 10; // max auras on a single pet
|
||||
static constexpr uint32 MAX_PET_BATTLE_ENVIRONMENTS = 3; // battlefield + per-team
|
||||
static constexpr uint32 PBOID_ENVIRONMENT_BASE = MAX_PET_BATTLE_PLAYERS * MAX_PET_BATTLE_TEAM_SIZE; // PBOID 6 = environment slot 0
|
||||
static constexpr float PASSIVE_HUMANOID_HEAL_PCT = 0.04f; // 4% max HP each round
|
||||
static constexpr float PASSIVE_DRAGONKIN_DAMAGE_BONUS = 0.50f;
|
||||
static constexpr float PASSIVE_FLYING_SPEED_BONUS = 0.50f;
|
||||
@@ -350,6 +351,7 @@ namespace PetBattles
|
||||
float baseChance = 0.20f + (trapLevel - 1) * 0.05f;
|
||||
// Lower HP = higher capture chance
|
||||
float hpModifier = 2.0f - (healthPct / 100.0f) * 1.5f;
|
||||
|
||||
// Quality modifier: lower quality = easier to catch
|
||||
float qualityMod = 1.0f;
|
||||
switch (quality)
|
||||
|
||||
@@ -255,6 +255,26 @@ static void BuildPetBattlePlayerUpdate(WorldPackets::BattlePet::PetBattlePlayerU
|
||||
}
|
||||
}
|
||||
|
||||
static void BuildPetBattleEnviros(std::array<WorldPackets::BattlePet::PetBattleEnviroInfo, 3>& enviros,
|
||||
PetBattles::PetBattle const* battle)
|
||||
{
|
||||
for (uint8 i = 0; i < PetBattles::MAX_PET_BATTLE_ENVIRONMENTS; ++i)
|
||||
{
|
||||
PetBattles::PetBattleEnvironment const& env = battle->GetEnvironment(i);
|
||||
if (env.WeatherType != PetBattles::PET_BATTLE_WEATHER_NONE && env.AuraInstanceID != 0)
|
||||
{
|
||||
WorldPackets::BattlePet::PetBattleAuraInfo auraInfo;
|
||||
auraInfo.AbilityID = env.AbilityID;
|
||||
auraInfo.InstanceID = env.AuraInstanceID;
|
||||
auraInfo.RoundsRemaining = env.RemainingRounds;
|
||||
auraInfo.CurrentRound = env.CurrentRound;
|
||||
auraInfo.CasterPBOID = env.CasterTeam * PetBattles::MAX_PET_BATTLE_TEAM_SIZE
|
||||
+ battle->GetTeam(env.CasterTeam).FrontPetIndex;
|
||||
enviros[i].Auras.push_back(auraInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void BuildPetBattleRoundPlayerData(WorldPackets::BattlePet::PetBattleRoundPlayerData& roundData,
|
||||
PetBattles::PetBattleTeamData const& team, PetBattles::PetBattle const* battle, uint8 teamIdx)
|
||||
{
|
||||
@@ -320,7 +340,11 @@ static void BuildRoundEffects(std::vector<WorldPackets::BattlePet::PetBattleEffe
|
||||
effect.StackDepth = 0;
|
||||
|
||||
WorldPackets::BattlePet::PetBattleEffectTargetInfo target;
|
||||
target.Remaining = static_cast<int32>(roundEffect.TargetTeam * PetBattles::MAX_PET_BATTLE_TEAM_SIZE + roundEffect.TargetPet);
|
||||
// Environment targets use PBOID_ENVIRONMENT_BASE + slot; pet targets use team * TEAM_SIZE + pet
|
||||
if (roundEffect.TargetEnvSlot >= 0)
|
||||
target.Remaining = static_cast<int32>(PetBattles::PBOID_ENVIRONMENT_BASE + roundEffect.TargetEnvSlot);
|
||||
else
|
||||
target.Remaining = static_cast<int32>(roundEffect.TargetTeam * PetBattles::MAX_PET_BATTLE_TEAM_SIZE + roundEffect.TargetPet);
|
||||
|
||||
// Map effect type to target type and variable-length params
|
||||
// Target types: 0=none, 1=aura(4 i32), 2=state(2 i32), 3=health(1 i32),
|
||||
@@ -493,6 +517,7 @@ void WorldSession::HandlePetBattleRequestWild(WorldPackets::BattlePet::PetBattle
|
||||
|
||||
BuildPetBattlePlayerUpdate(initialUpdate.Players[0], battle->GetTeam(PetBattles::PET_BATTLE_TEAM_1), false, battle, PetBattles::PET_BATTLE_TEAM_1);
|
||||
BuildPetBattlePlayerUpdate(initialUpdate.Players[1], battle->GetTeam(PetBattles::PET_BATTLE_TEAM_2), true, battle, PetBattles::PET_BATTLE_TEAM_2);
|
||||
BuildPetBattleEnviros(initialUpdate.Enviros, battle);
|
||||
|
||||
initialUpdate.CurRound = battle->GetCurrentRound();
|
||||
initialUpdate.CurPetBattleState = static_cast<int8>(battle->GetBattleState());
|
||||
@@ -653,6 +678,7 @@ void WorldSession::StartNPCPetBattle(Creature* trainer)
|
||||
|
||||
BuildPetBattlePlayerUpdate(initialUpdate.Players[0], battle->GetTeam(PetBattles::PET_BATTLE_TEAM_1), false, battle, PetBattles::PET_BATTLE_TEAM_1);
|
||||
BuildPetBattlePlayerUpdate(initialUpdate.Players[1], battle->GetTeam(PetBattles::PET_BATTLE_TEAM_2), false, battle, PetBattles::PET_BATTLE_TEAM_2);
|
||||
BuildPetBattleEnviros(initialUpdate.Enviros, battle);
|
||||
|
||||
initialUpdate.CurRound = battle->GetCurrentRound();
|
||||
initialUpdate.CurPetBattleState = static_cast<int8>(battle->GetBattleState());
|
||||
@@ -1056,6 +1082,7 @@ void WorldSession::HandlePetBattleRequestUpdate(WorldPackets::BattlePet::PetBatt
|
||||
WorldPackets::BattlePet::PetBattleInitialUpdate initialUpdate;
|
||||
BuildPetBattlePlayerUpdate(initialUpdate.Players[0], battle->GetTeam(PetBattles::PET_BATTLE_TEAM_1), false, battle, PetBattles::PET_BATTLE_TEAM_1);
|
||||
BuildPetBattlePlayerUpdate(initialUpdate.Players[1], battle->GetTeam(PetBattles::PET_BATTLE_TEAM_2), false, battle, PetBattles::PET_BATTLE_TEAM_2);
|
||||
BuildPetBattleEnviros(initialUpdate.Enviros, battle);
|
||||
initialUpdate.CurRound = battle->GetCurrentRound();
|
||||
initialUpdate.CurPetBattleState = static_cast<int8>(battle->GetBattleState());
|
||||
initialUpdate.IsPVP = true;
|
||||
|
||||
Reference in New Issue
Block a user