mirror of
https://github.com/mangosfour/server.git
synced 2025-12-15 19:37:02 +00:00
[c12553] Correct DestructibleModelDataEntry and fix ingame destructible go display
This commit is contained in:
parent
456de16b5e
commit
2be2854ff2
4 changed files with 323 additions and 116 deletions
|
|
@ -396,7 +396,6 @@ struct AchievementCriteriaEntry
|
||||||
uint32 goldInCopper; // 4
|
uint32 goldInCopper; // 4
|
||||||
} quest_reward_money;
|
} quest_reward_money;
|
||||||
|
|
||||||
|
|
||||||
// ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67
|
// ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|
@ -535,7 +534,7 @@ struct AreaTableEntry
|
||||||
int32 area_level; // 10 m_ExplorationLevel
|
int32 area_level; // 10 m_ExplorationLevel
|
||||||
DBCString area_name; // 11 m_AreaName_lang
|
DBCString area_name; // 11 m_AreaName_lang
|
||||||
uint32 team; // 12 m_factionGroupMask
|
uint32 team; // 12 m_factionGroupMask
|
||||||
// 13-16 m_liquidTypeID[4]
|
uint32 LiquidTypeOverride[4]; // 13-16 m_liquidTypeID[4]
|
||||||
// 17 m_minElevation
|
// 17 m_minElevation
|
||||||
// 18 m_ambient_multiplier
|
// 18 m_ambient_multiplier
|
||||||
// 19 m_lightid
|
// 19 m_lightid
|
||||||
|
|
@ -685,9 +684,9 @@ struct ChrClassesEntry
|
||||||
//uint32 flags2; // 8 m_flags (0x08 HasRelicSlot)
|
//uint32 flags2; // 8 m_flags (0x08 HasRelicSlot)
|
||||||
uint32 CinematicSequence; // 9 m_cinematicSequenceID
|
uint32 CinematicSequence; // 9 m_cinematicSequenceID
|
||||||
uint32 expansion; // 10 m_required_expansion
|
uint32 expansion; // 10 m_required_expansion
|
||||||
//uint32 // 11
|
uint32 apPerStr; // 11 attack power per strength
|
||||||
//uint32 // 12
|
uint32 apPerAgi; // 12 attack power per agility
|
||||||
//uint32 // 13
|
uint32 rapPerAgi; // 13 ranged attack power per agility
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ChrRacesEntry
|
struct ChrRacesEntry
|
||||||
|
|
@ -833,6 +832,34 @@ struct CurrencyTypesEntry
|
||||||
float GetPrecision() const { return HasPrecision() ? CURRENCY_PRECISION : 1.0f; }
|
float GetPrecision() const { return HasPrecision() ? CURRENCY_PRECISION : 1.0f; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DestructibleModelDataEntry
|
||||||
|
{
|
||||||
|
uint32 m_ID; // 0 m_ID
|
||||||
|
uint32 intactDisplayId; // 1
|
||||||
|
// uint32 unk2; // 2
|
||||||
|
// uint32 unk3; // 3
|
||||||
|
// uint32 unk4; // 4
|
||||||
|
uint32 damagedDisplayId; // 5
|
||||||
|
// uint32 unk6; // 6
|
||||||
|
// uint32 unk7; // 7
|
||||||
|
// uint32 unk8; // 8
|
||||||
|
// uint32 unk9; // 9
|
||||||
|
uint32 destroyedDisplayId; // 10
|
||||||
|
// uint32 unk11; // 11
|
||||||
|
// uint32 unk12; // 12
|
||||||
|
// uint32 unk13; // 13
|
||||||
|
// uint32 unk14; // 14
|
||||||
|
uint32 rebuildingDisplayId; // 15
|
||||||
|
// uint32 unk16; // 16
|
||||||
|
// uint32 unk17; // 17
|
||||||
|
// uint32 unk18; // 18
|
||||||
|
// uint32 unk19; // 19
|
||||||
|
//uint32 smokeDisplayId; // 20
|
||||||
|
// uint32 unk21; // 21
|
||||||
|
// uint32 unk22; // 22
|
||||||
|
// uint32 unk23; // 23
|
||||||
|
};
|
||||||
|
|
||||||
struct DungeonEncounterEntry
|
struct DungeonEncounterEntry
|
||||||
{
|
{
|
||||||
uint32 Id; // 0 m_ID
|
uint32 Id; // 0 m_ID
|
||||||
|
|
@ -961,15 +988,15 @@ struct FactionTemplateEntry
|
||||||
|
|
||||||
struct GameObjectDisplayInfoEntry
|
struct GameObjectDisplayInfoEntry
|
||||||
{
|
{
|
||||||
uint32 Displayid; // 0 m_ID
|
uint32 Displayid; // 0 m_ID
|
||||||
//DBCString filename; // 1
|
char* filename; // 1 m_modelName
|
||||||
//uint32 unk1[10]; // 2-11
|
// uint32 unknown2[10]; // 2-11 m_Sound
|
||||||
float minX; // 1
|
float geoBoxMinX; // 12 m_geoBoxMinX (use first value as interact dist, mostly in hacks way)
|
||||||
float minY; // 13
|
float geoBoxMinY; // 13 m_geoBoxMinY
|
||||||
float minZ; // 14
|
float geoBoxMinZ; // 14 m_geoBoxMinZ
|
||||||
float maxX; // 15
|
float geoBoxMaxX; // 15 m_geoBoxMaxX
|
||||||
float maxY; // 16
|
float geoBoxMaxY; // 16 m_geoBoxMaxY
|
||||||
float maxZ; // 17
|
float geoBoxMaxZ; // 17 m_geoBoxMaxZ
|
||||||
//uint32 transport; // 18
|
//uint32 transport; // 18
|
||||||
//uint32 unk; // 19
|
//uint32 unk; // 19
|
||||||
//uint32 unk1; // 20
|
//uint32 unk1; // 20
|
||||||
|
|
@ -1249,6 +1276,29 @@ struct ItemSetEntry
|
||||||
m_target_level_max
|
m_target_level_max
|
||||||
};*/
|
};*/
|
||||||
|
|
||||||
|
struct LiquidTypeEntry
|
||||||
|
{
|
||||||
|
uint32 Id; // 0
|
||||||
|
//char* Name; // 1
|
||||||
|
//uint32 Flags; // 2 Water: 1|2|4|8, Magma: 8|16|32|64, Slime: 2|64|256, WMO Ocean: 1|2|4|8|512
|
||||||
|
uint32 Type; // 3 0: Water, 1: Ocean, 2: Magma, 3: Slime
|
||||||
|
//uint32 SoundId; // 4 Reference to SoundEntries.dbc
|
||||||
|
uint32 SpellId; // 5 Reference to Spell.dbc
|
||||||
|
//float MaxDarkenDepth; // 6 Only oceans got values here!
|
||||||
|
//float FogDarkenIntensity; // 7 Only oceans got values here!
|
||||||
|
//float AmbDarkenIntensity; // 8 Only oceans got values here!
|
||||||
|
//float DirDarkenIntensity; // 9 Only oceans got values here!
|
||||||
|
//uint32 LightID; // 10 Only Slime (6) and Magma (7)
|
||||||
|
//float ParticleScale; // 11 0: Slime, 1: Water/Ocean, 4: Magma
|
||||||
|
//uint32 ParticleMovement; // 12
|
||||||
|
//uint32 ParticleTexSlots; // 13
|
||||||
|
//uint32 LiquidMaterialID; // 14
|
||||||
|
//char* Texture[6]; // 15-20
|
||||||
|
//uint32 Color[2]; // 21-22
|
||||||
|
//float Unk1[18]; // 23-40 Most likely these are attributes for the shaders. Water: (23, TextureTilesPerBlock),(24, Rotation) Magma: (23, AnimationX),(24, AnimationY)
|
||||||
|
//uint32 Unk2[4]; // 41-44
|
||||||
|
};
|
||||||
|
|
||||||
#define MAX_LOCK_CASE 8
|
#define MAX_LOCK_CASE 8
|
||||||
|
|
||||||
struct LockEntry
|
struct LockEntry
|
||||||
|
|
@ -1496,13 +1546,6 @@ struct ScalingStatValuesEntry
|
||||||
return spellBonus;
|
return spellBonus;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 getFeralBonus(uint32 mask) const // removed in 3.2.x?
|
|
||||||
{
|
|
||||||
if (mask & 0x00010000) // not used?
|
|
||||||
return 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*struct SkillLineCategoryEntry{
|
/*struct SkillLineCategoryEntry{
|
||||||
|
|
@ -1732,7 +1775,7 @@ struct SpellEffectEntry
|
||||||
int32 EffectMiscValueB; // 118-120 m_effectMiscValueB
|
int32 EffectMiscValueB; // 118-120 m_effectMiscValueB
|
||||||
float EffectPointsPerComboPoint; // 124-126 m_effectPointsPerCombo
|
float EffectPointsPerComboPoint; // 124-126 m_effectPointsPerCombo
|
||||||
uint32 EffectRadiusIndex; // 94-96 m_effectRadiusIndex - spellradius.dbc
|
uint32 EffectRadiusIndex; // 94-96 m_effectRadiusIndex - spellradius.dbc
|
||||||
//uint32 EffectRadiusMaxIndex; // 97-99 4.0.0
|
uint32 EffectRadiusMaxIndex; // 97-99 4.0.0
|
||||||
float EffectRealPointsPerLevel; // 79-81 m_effectRealPointsPerLevel
|
float EffectRealPointsPerLevel; // 79-81 m_effectRealPointsPerLevel
|
||||||
ClassFamilyMask EffectSpellClassMask; // 127-129 m_effectSpellClassMask
|
ClassFamilyMask EffectSpellClassMask; // 127-129 m_effectSpellClassMask
|
||||||
uint32 EffectTriggerSpell; // 121-123 m_effectTriggerSpell
|
uint32 EffectTriggerSpell; // 121-123 m_effectTriggerSpell
|
||||||
|
|
@ -1745,6 +1788,14 @@ struct SpellEffectEntry
|
||||||
// helpers
|
// helpers
|
||||||
|
|
||||||
int32 CalculateSimpleValue() const { return EffectBasePoints; }
|
int32 CalculateSimpleValue() const { return EffectBasePoints; }
|
||||||
|
|
||||||
|
uint32 GetRadiusIndex() const
|
||||||
|
{
|
||||||
|
if (EffectRadiusIndex != 0)
|
||||||
|
return EffectRadiusIndex;
|
||||||
|
|
||||||
|
return EffectRadiusMaxIndex;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// SpellEquippedItems.dbc
|
// SpellEquippedItems.dbc
|
||||||
|
|
@ -1800,16 +1851,18 @@ struct SpellReagentsEntry
|
||||||
// SpellScaling.dbc
|
// SpellScaling.dbc
|
||||||
struct SpellScalingEntry
|
struct SpellScalingEntry
|
||||||
{
|
{
|
||||||
//uint32 Id; // 0 m_ID
|
//uint32 Id; // 0 m_ID
|
||||||
uint32 castTimeMin; // 1
|
int32 castTimeMin; // 1
|
||||||
uint32 castTimeMax; // 2
|
int32 castTimeMax; // 2
|
||||||
uint32 castScalingMaxLevel; // 3
|
int32 castScalingMaxLevel; // 3
|
||||||
int32 playerClass; // 4 (index * 100) + charLevel => gtSpellScaling.dbc
|
int32 playerClass; // 4 (index * 100) + charLevel => gtSpellScaling.dbc
|
||||||
float coeff1[3]; // 5-7
|
float coeff1[3]; // 5-7
|
||||||
float coeff2[3]; // 8-10
|
float coeff2[3]; // 8-10
|
||||||
float coeff3[3]; // 11-13
|
float coeff3[3]; // 11-13
|
||||||
float unkMult; // 14 some coefficient, mostly 1.0f
|
float coefBase; // 14 some coefficient, mostly 1.0f
|
||||||
uint32 unkLevel; // 15 some level
|
int32 coefLevelBase; // 15 some level
|
||||||
|
|
||||||
|
bool IsScalableEffect(SpellEffectIndex i) const { return coeff1[i] != 0.0f; };
|
||||||
};
|
};
|
||||||
|
|
||||||
// SpellShapeshift.dbc
|
// SpellShapeshift.dbc
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
const char Achievementfmt[]="niiissiiiiisii";
|
const char Achievementfmt[]="niiissiiiiisii";
|
||||||
const char AchievementCriteriafmt[]="niiiiiiiixsiiiiixxxxxxx";
|
const char AchievementCriteriafmt[]="niiiiiiiixsiiiiixxxxxxx";
|
||||||
const char AreaTableEntryfmt[]="iiinixxxxxisixxxxxxxxxxxxx";
|
const char AreaTableEntryfmt[]="iiinixxxxxisiiiiixxxxxxxxx";
|
||||||
const char AreaGroupEntryfmt[]="niiiiiii";
|
const char AreaGroupEntryfmt[]="niiiiiii";
|
||||||
const char AreaTriggerEntryfmt[]="nifffxxxfffff";
|
const char AreaTriggerEntryfmt[]="nifffxxxfffff";
|
||||||
const char ArmorLocationfmt[]="nfffff";
|
const char ArmorLocationfmt[]="nfffff";
|
||||||
|
|
@ -33,7 +33,7 @@ const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxx
|
||||||
const char CharTitlesEntryfmt[]="nxsxix";
|
const char CharTitlesEntryfmt[]="nxsxix";
|
||||||
const char ChatChannelsEntryfmt[]="iixsx";
|
const char ChatChannelsEntryfmt[]="iixsx";
|
||||||
// ChatChannelsEntryfmt, index not used (more compact store)
|
// ChatChannelsEntryfmt, index not used (more compact store)
|
||||||
const char ChrClassesEntryfmt[]="nixsxxxixiixxx";
|
const char ChrClassesEntryfmt[]="nixsxxxixiiiii";
|
||||||
const char ChrRacesEntryfmt[]="nxixiixixxxxixsxxxxxixxx";
|
const char ChrRacesEntryfmt[]="nxixiixixxxxixsxxxxxixxx";
|
||||||
const char ChrClassesXPowerTypesfmt[]="nii";
|
const char ChrClassesXPowerTypesfmt[]="nii";
|
||||||
const char CinematicSequencesEntryfmt[]="nxxxxxxxxx";
|
const char CinematicSequencesEntryfmt[]="nxxxxxxxxx";
|
||||||
|
|
@ -41,6 +41,7 @@ const char CreatureDisplayInfofmt[]="nxxifxxxxxxxxxxxx";
|
||||||
const char CreatureDisplayInfoExtrafmt[]="nixxxxxxxxxxxxxxxxxxx";
|
const char CreatureDisplayInfoExtrafmt[]="nixxxxxxxxxxxxxxxxxxx";
|
||||||
const char CreatureFamilyfmt[]="nfifiiiiixsx";
|
const char CreatureFamilyfmt[]="nfifiiiiixsx";
|
||||||
const char CreatureSpellDatafmt[]="niiiixxxx";
|
const char CreatureSpellDatafmt[]="niiiixxxx";
|
||||||
|
const char DestructibleModelDataFmt[] = "nixxxixxxxixxxxixxxxxxxx";
|
||||||
const char DungeonEncounterfmt[]="niiiisxx";
|
const char DungeonEncounterfmt[]="niiiisxx";
|
||||||
const char CreatureTypefmt[]="nxx";
|
const char CreatureTypefmt[]="nxx";
|
||||||
const char CurrencyTypesfmt[]="nisxxxxiiix";
|
const char CurrencyTypesfmt[]="nisxxxxiiix";
|
||||||
|
|
@ -50,7 +51,7 @@ const char EmotesEntryfmt[]="nxxiiixx";
|
||||||
const char EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx";
|
const char EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx";
|
||||||
const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiiffixsxx";
|
const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiiffixsxx";
|
||||||
const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii";
|
const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii";
|
||||||
const char GameObjectDisplayInfofmt[]="nxxxxxxxxxxxffffffxxx";
|
const char GameObjectDisplayInfofmt[]="nsxxxxxxxxxxffffffxxx";
|
||||||
const char GemPropertiesEntryfmt[]="nixxix";
|
const char GemPropertiesEntryfmt[]="nixxix";
|
||||||
const char GlyphPropertiesfmt[]="niii";
|
const char GlyphPropertiesfmt[]="niii";
|
||||||
const char GlyphSlotfmt[]="nii";
|
const char GlyphSlotfmt[]="nii";
|
||||||
|
|
@ -81,6 +82,7 @@ const char ItemLimitCategoryEntryfmt[]="nxii";
|
||||||
const char ItemRandomPropertiesfmt[]="nxiiiiis";
|
const char ItemRandomPropertiesfmt[]="nxiiiiis";
|
||||||
const char ItemRandomSuffixfmt[]="nsxiiiiiiiiii";
|
const char ItemRandomSuffixfmt[]="nsxiiiiiiiiii";
|
||||||
const char ItemSetEntryfmt[]="dsxxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiiiii";
|
const char ItemSetEntryfmt[]="dsxxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiiiii";
|
||||||
|
const char LiquidTypefmt[] = "nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||||
const char LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx";
|
const char LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx";
|
||||||
const char MailTemplateEntryfmt[]="nxs";
|
const char MailTemplateEntryfmt[]="nxs";
|
||||||
const char MapEntryfmt[]="nsiiiisissififfiiiii";
|
const char MapEntryfmt[]="nsiiiisissififfiiiii";
|
||||||
|
|
@ -110,7 +112,7 @@ const char SpellCastingRequirementsEntryfmt[]="dixxixi";
|
||||||
const char SpellCategoriesEntryfmt[]="diiiiii";
|
const char SpellCategoriesEntryfmt[]="diiiiii";
|
||||||
const char SpellClassOptionsEntryfmt[]="dxiiiix";
|
const char SpellClassOptionsEntryfmt[]="dxiiiix";
|
||||||
const char SpellCooldownsEntryfmt[]="diii";
|
const char SpellCooldownsEntryfmt[]="diii";
|
||||||
const char SpellEffectEntryfmt[]="difiiixfiiiiiifixfiiiiiiiix";
|
const char SpellEffectEntryfmt[]="difiiixfiiiiiifiifiiiiiiiix";
|
||||||
const char SpellEquippedItemsEntryfmt[]="diii";
|
const char SpellEquippedItemsEntryfmt[]="diii";
|
||||||
const char SpellInterruptsEntryfmt[]="dixixi";
|
const char SpellInterruptsEntryfmt[]="dixixi";
|
||||||
const char SpellLevelsEntryfmt[]="diii";
|
const char SpellLevelsEntryfmt[]="diii";
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,13 @@
|
||||||
#include "OutdoorPvP/OutdoorPvP.h"
|
#include "OutdoorPvP/OutdoorPvP.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "ScriptMgr.h"
|
#include "ScriptMgr.h"
|
||||||
|
#include "vmap/GameObjectModel.h"
|
||||||
#include "SQLStorages.h"
|
#include "SQLStorages.h"
|
||||||
#include <G3D/Quat.h>
|
#include <G3D/Quat.h>
|
||||||
|
|
||||||
GameObject::GameObject() : WorldObject(),
|
GameObject::GameObject() : WorldObject(),
|
||||||
|
loot(this),
|
||||||
|
m_model(NULL),
|
||||||
m_goInfo(NULL),
|
m_goInfo(NULL),
|
||||||
m_displayInfo(NULL)
|
m_displayInfo(NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -54,7 +57,7 @@ GameObject::GameObject() : WorldObject(),
|
||||||
m_valuesCount = GAMEOBJECT_END;
|
m_valuesCount = GAMEOBJECT_END;
|
||||||
m_respawnTime = 0;
|
m_respawnTime = 0;
|
||||||
m_respawnDelayTime = 25;
|
m_respawnDelayTime = 25;
|
||||||
m_lootState = GO_NOT_READY;
|
m_lootState = GO_READY;
|
||||||
m_spawnedByDefault = true;
|
m_spawnedByDefault = true;
|
||||||
m_useTimes = 0;
|
m_useTimes = 0;
|
||||||
m_spellId = 0;
|
m_spellId = 0;
|
||||||
|
|
@ -70,6 +73,7 @@ GameObject::GameObject() : WorldObject(),
|
||||||
|
|
||||||
GameObject::~GameObject()
|
GameObject::~GameObject()
|
||||||
{
|
{
|
||||||
|
delete m_model;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameObject::AddToWorld()
|
void GameObject::AddToWorld()
|
||||||
|
|
@ -78,7 +82,13 @@ void GameObject::AddToWorld()
|
||||||
if (!IsInWorld())
|
if (!IsInWorld())
|
||||||
GetMap()->GetObjectsStore().insert<GameObject>(GetObjectGuid(), (GameObject*)this);
|
GetMap()->GetObjectsStore().insert<GameObject>(GetObjectGuid(), (GameObject*)this);
|
||||||
|
|
||||||
|
if (m_model)
|
||||||
|
GetMap()->InsertGameObjectModel(*m_model);
|
||||||
|
|
||||||
Object::AddToWorld();
|
Object::AddToWorld();
|
||||||
|
|
||||||
|
// After Object::AddToWorld so that for initial state the GO is added to the world (and hence handled correctly)
|
||||||
|
UpdateCollisionState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameObject::RemoveFromWorld()
|
void GameObject::RemoveFromWorld()
|
||||||
|
|
@ -102,6 +112,9 @@ void GameObject::RemoveFromWorld()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_model && GetMap()->ContainsGameObjectModel(*m_model))
|
||||||
|
GetMap()->RemoveGameObjectModel(*m_model);
|
||||||
|
|
||||||
GetMap()->GetObjectsStore().erase<GameObject>(GetObjectGuid(), (GameObject*)NULL);
|
GetMap()->GetObjectsStore().erase<GameObject>(GetObjectGuid(), (GameObject*)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,6 +175,18 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
|
||||||
SetGoArtKit(0); // unknown what this is
|
SetGoArtKit(0); // unknown what this is
|
||||||
SetGoAnimProgress(animprogress);
|
SetGoAnimProgress(animprogress);
|
||||||
|
|
||||||
|
switch (GetGoType())
|
||||||
|
{
|
||||||
|
case GAMEOBJECT_TYPE_TRAP:
|
||||||
|
case GAMEOBJECT_TYPE_FISHINGNODE:
|
||||||
|
m_lootState = GO_NOT_READY; // Initialize Traps and Fishingnode delayed in ::Update
|
||||||
|
break;
|
||||||
|
case GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING:
|
||||||
|
ForceGameObjectHealth(GetMaxHealth(), NULL);
|
||||||
|
SetUInt32Value(GAMEOBJECT_PARENTROTATION, m_goInfo->destructibleBuilding.destructibleData);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Notify the battleground or outdoor pvp script
|
// Notify the battleground or outdoor pvp script
|
||||||
if (map->IsBattleGroundOrArena())
|
if (map->IsBattleGroundOrArena())
|
||||||
((BattleGroundMap*)map)->GetBG()->HandleGameObjectCreate(this);
|
((BattleGroundMap*)map)->GetBG()->HandleGameObjectCreate(this);
|
||||||
|
|
@ -191,16 +216,16 @@ void GameObject::Update(uint32 update_diff, uint32 p_time)
|
||||||
{
|
{
|
||||||
switch (GetGoType())
|
switch (GetGoType())
|
||||||
{
|
{
|
||||||
case GAMEOBJECT_TYPE_TRAP:
|
case GAMEOBJECT_TYPE_TRAP: // Initialized delayed to be able to use GetOwner()
|
||||||
{
|
{
|
||||||
// Arming Time for GAMEOBJECT_TYPE_TRAP (6)
|
// Arming Time for GAMEOBJECT_TYPE_TRAP (6)
|
||||||
Unit* owner = GetOwner();
|
Unit* owner = GetOwner();
|
||||||
if (owner && ((Player*)owner)->isInCombat())
|
if (owner && owner->isInCombat())
|
||||||
m_cooldownTime = time(NULL) + GetGOInfo()->trap.startDelay;
|
m_cooldownTime = time(NULL) + GetGOInfo()->trap.startDelay;
|
||||||
m_lootState = GO_READY;
|
m_lootState = GO_READY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GAMEOBJECT_TYPE_FISHINGNODE:
|
case GAMEOBJECT_TYPE_FISHINGNODE: // Keep not ready for some delay
|
||||||
{
|
{
|
||||||
// fishing code (bobber ready)
|
// fishing code (bobber ready)
|
||||||
if (time(NULL) > m_respawnTime - FISHING_BOBBER_READY_TIME)
|
if (time(NULL) > m_respawnTime - FISHING_BOBBER_READY_TIME)
|
||||||
|
|
@ -219,13 +244,10 @@ void GameObject::Update(uint32 update_diff, uint32 p_time)
|
||||||
|
|
||||||
m_lootState = GO_READY; // can be successfully open with some chance
|
m_lootState = GO_READY; // can be successfully open with some chance
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
m_lootState = GO_READY; // for other GO is same switched without delay to GO_READY
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// NO BREAK for switch (m_lootState)
|
break;
|
||||||
}
|
}
|
||||||
case GO_READY:
|
case GO_READY:
|
||||||
{
|
{
|
||||||
|
|
@ -305,32 +327,17 @@ void GameObject::Update(uint32 update_diff, uint32 p_time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: this hack with search required until GO casting not implemented
|
// Should trap trigger?
|
||||||
// search unfriendly creature
|
MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, radius);
|
||||||
if (owner && goInfo->trap.charges > 0) // hunter trap
|
MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck> checker(ok, u_check);
|
||||||
{
|
Cell::VisitAllObjects(this, checker, radius);
|
||||||
MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, owner, radius);
|
|
||||||
MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck> checker(ok, u_check);
|
|
||||||
Cell::VisitGridObjects(this, checker, radius);
|
|
||||||
if (!ok)
|
|
||||||
Cell::VisitWorldObjects(this, checker, radius);
|
|
||||||
}
|
|
||||||
else // environmental trap
|
|
||||||
{
|
|
||||||
// environmental damage spells already have around enemies targeting but this not help in case nonexistent GO casting support
|
|
||||||
|
|
||||||
// affect only players
|
|
||||||
Player* p_ok = NULL;
|
|
||||||
MaNGOS::AnyPlayerInObjectRangeCheck p_check(this, radius);
|
|
||||||
MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck> checker(p_ok, p_check);
|
|
||||||
Cell::VisitWorldObjects(this, checker, radius);
|
|
||||||
ok = p_ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
Unit* caster = owner ? owner : ok;
|
Unit* caster = owner ? owner : ok;
|
||||||
|
|
||||||
|
// Code below should be refactored into GO::Use, but not clear how to handle caster/victim for non AoE spells
|
||||||
|
|
||||||
caster->CastSpell(ok, goInfo->trap.spellId, true, NULL, NULL, GetObjectGuid());
|
caster->CastSpell(ok, goInfo->trap.spellId, true, NULL, NULL, GetObjectGuid());
|
||||||
// use template cooldown if provided
|
// use template cooldown if provided
|
||||||
m_cooldownTime = time(NULL) + (goInfo->trap.cooldown ? goInfo->trap.cooldown : uint32(4));
|
m_cooldownTime = time(NULL) + (goInfo->trap.cooldown ? goInfo->trap.cooldown : uint32(4));
|
||||||
|
|
@ -506,7 +513,6 @@ void GameObject::AddUniqueUse(Player* player)
|
||||||
m_firstUser = player->GetObjectGuid();
|
m_firstUser = player->GetObjectGuid();
|
||||||
|
|
||||||
m_UniqueUsers.insert(player->GetObjectGuid());
|
m_UniqueUsers.insert(player->GetObjectGuid());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameObject::Delete()
|
void GameObject::Delete()
|
||||||
|
|
@ -522,19 +528,6 @@ void GameObject::Delete()
|
||||||
AddObjectToRemoveList();
|
AddObjectToRemoveList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameObject::getFishLoot(Loot* fishloot, Player* loot_owner)
|
|
||||||
{
|
|
||||||
fishloot->clear();
|
|
||||||
|
|
||||||
uint32 zone, subzone;
|
|
||||||
GetZoneAndAreaId(zone, subzone);
|
|
||||||
|
|
||||||
// if subzone loot exist use it
|
|
||||||
if (!fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, (subzone != zone)) && subzone != zone)
|
|
||||||
// else use zone loot (if zone diff. from subzone, must exist in like case)
|
|
||||||
fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameObject::SaveToDB()
|
void GameObject::SaveToDB()
|
||||||
{
|
{
|
||||||
// this should only be used when the gameobject has already been loaded
|
// this should only be used when the gameobject has already been loaded
|
||||||
|
|
@ -672,7 +665,6 @@ struct GameObjectRespawnDeleteWorker
|
||||||
uint32 i_guid;
|
uint32 i_guid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void GameObject::DeleteFromDB()
|
void GameObject::DeleteFromDB()
|
||||||
{
|
{
|
||||||
if (!HasStaticDBSpawnData())
|
if (!HasStaticDBSpawnData())
|
||||||
|
|
@ -938,6 +930,23 @@ GameObject* GameObject::LookupFishingHoleAround(float range)
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GameObject::IsCollisionEnabled() const
|
||||||
|
{
|
||||||
|
if (!isSpawned())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// TODO: Possible that this function must consider multiple checks
|
||||||
|
switch (GetGoType())
|
||||||
|
{
|
||||||
|
case GAMEOBJECT_TYPE_DOOR:
|
||||||
|
case GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING:
|
||||||
|
return GetGoState() != GO_STATE_ACTIVE && GetGoState() != GO_STATE_ACTIVE_ALTERNATIVE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GameObject::ResetDoorOrButton()
|
void GameObject::ResetDoorOrButton()
|
||||||
{
|
{
|
||||||
if (m_lootState == GO_READY || m_lootState == GO_JUST_DEACTIVATED)
|
if (m_lootState == GO_READY || m_lootState == GO_JUST_DEACTIVATED)
|
||||||
|
|
@ -1048,10 +1057,8 @@ void GameObject::Use(Unit* user)
|
||||||
// TODO: possible must be moved to loot release (in different from linked triggering)
|
// TODO: possible must be moved to loot release (in different from linked triggering)
|
||||||
if (GetGOInfo()->chest.eventId)
|
if (GetGOInfo()->chest.eventId)
|
||||||
{
|
{
|
||||||
DEBUG_LOG("Chest ScriptStart id %u for GO %u", GetGOInfo()->chest.eventId, GetGUIDLow());
|
DEBUG_LOG("Chest ScriptStart id %u for %s (opened by %s)", GetGOInfo()->chest.eventId, GetGuidStr().c_str(), user->GetGuidStr().c_str());
|
||||||
|
StartEvents_Event(GetMap(), GetGOInfo()->chest.eventId, user, this);
|
||||||
if (!sScriptMgr.OnProcessEvent(GetGOInfo()->chest.eventId, user, this, true))
|
|
||||||
GetMap()->ScriptsStart(sEventScripts, GetGOInfo()->chest.eventId, user, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -1200,10 +1207,8 @@ void GameObject::Use(Unit* user)
|
||||||
|
|
||||||
if (info->goober.eventId)
|
if (info->goober.eventId)
|
||||||
{
|
{
|
||||||
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Goober ScriptStart id %u for GO entry %u (GUID %u).", info->goober.eventId, GetEntry(), GetGUIDLow());
|
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Goober ScriptStart id %u for %s (Used by %s).", info->goober.eventId, GetGuidStr().c_str(), player->GetGuidStr().c_str());
|
||||||
|
StartEvents_Event(GetMap(), info->goober.eventId, player, this);
|
||||||
if (!sScriptMgr.OnProcessEvent(info->goober.eventId, player, this, true))
|
|
||||||
GetMap()->ScriptsStart(sEventScripts, info->goober.eventId, player, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// possible quest objective for active quests
|
// possible quest objective for active quests
|
||||||
|
|
@ -1250,10 +1255,7 @@ void GameObject::Use(Unit* user)
|
||||||
player->SendCinematicStart(info->camera.cinematicId);
|
player->SendCinematicStart(info->camera.cinematicId);
|
||||||
|
|
||||||
if (info->camera.eventID)
|
if (info->camera.eventID)
|
||||||
{
|
StartEvents_Event(GetMap(), info->camera.eventID, player, this);
|
||||||
if (!sScriptMgr.OnProcessEvent(info->camera.eventID, player, this, true))
|
|
||||||
GetMap()->ScriptsStart(sEventScripts, info->camera.eventID, player, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1711,9 +1713,9 @@ bool GameObject::IsHostileTo(Unit const* unit) const
|
||||||
if (Unit const* targetOwner = unit->GetCharmerOrOwner())
|
if (Unit const* targetOwner = unit->GetCharmerOrOwner())
|
||||||
return IsHostileTo(targetOwner);
|
return IsHostileTo(targetOwner);
|
||||||
|
|
||||||
// for not set faction case (wild object) use hostile case
|
// for not set faction case: be hostile towards player, not hostile towards not-players
|
||||||
if (!GetGOInfo()->faction)
|
if (!GetGOInfo()->faction)
|
||||||
return true;
|
return unit->IsControlledByPlayer();
|
||||||
|
|
||||||
// faction base cases
|
// faction base cases
|
||||||
FactionTemplateEntry const* tester_faction = sFactionTemplateStore.LookupEntry(GetGOInfo()->faction);
|
FactionTemplateEntry const* tester_faction = sFactionTemplateStore.LookupEntry(GetGOInfo()->faction);
|
||||||
|
|
@ -1784,10 +1786,48 @@ bool GameObject::IsFriendlyTo(Unit const* unit) const
|
||||||
return tester_faction->IsFriendlyTo(*target_faction);
|
return tester_faction->IsFriendlyTo(*target_faction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameObject::SetLootState(LootState state)
|
||||||
|
{
|
||||||
|
m_lootState = state;
|
||||||
|
UpdateCollisionState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameObject::SetGoState(GOState state)
|
||||||
|
{
|
||||||
|
SetByteValue(GAMEOBJECT_BYTES_1, 0, state);
|
||||||
|
UpdateCollisionState();
|
||||||
|
}
|
||||||
|
|
||||||
void GameObject::SetDisplayId(uint32 modelId)
|
void GameObject::SetDisplayId(uint32 modelId)
|
||||||
{
|
{
|
||||||
SetUInt32Value(GAMEOBJECT_DISPLAYID, modelId);
|
SetUInt32Value(GAMEOBJECT_DISPLAYID, modelId);
|
||||||
m_displayInfo = sGameObjectDisplayInfoStore.LookupEntry(modelId);
|
m_displayInfo = sGameObjectDisplayInfoStore.LookupEntry(modelId);
|
||||||
|
UpdateModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameObject::SetPhaseMask(uint32 newPhaseMask, bool update)
|
||||||
|
{
|
||||||
|
WorldObject::SetPhaseMask(newPhaseMask, update);
|
||||||
|
UpdateCollisionState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameObject::UpdateCollisionState() const
|
||||||
|
{
|
||||||
|
if (!m_model || !IsInWorld())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_model->enable(IsCollisionEnabled() ? GetPhaseMask() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameObject::UpdateModel()
|
||||||
|
{
|
||||||
|
if (m_model && IsInWorld() && GetMap()->ContainsGameObjectModel(*m_model))
|
||||||
|
GetMap()->RemoveGameObjectModel(*m_model);
|
||||||
|
delete m_model;
|
||||||
|
|
||||||
|
m_model = GameObjectModel::construct(this);
|
||||||
|
if (m_model)
|
||||||
|
GetMap()->InsertGameObjectModel(*m_model);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameObject::StartGroupLoot(Group* group, uint32 timer)
|
void GameObject::StartGroupLoot(Group* group, uint32 timer)
|
||||||
|
|
@ -1872,11 +1912,14 @@ void GameObject::SetLootRecipient(Unit* pUnit)
|
||||||
|
|
||||||
float GameObject::GetObjectBoundingRadius() const
|
float GameObject::GetObjectBoundingRadius() const
|
||||||
{
|
{
|
||||||
// FIXME:
|
if (m_displayInfo)
|
||||||
// 1. This is clearly hack way because GameObjectDisplayInfoEntry have 6 floats related to GO sizes, but better that use DEFAULT_WORLD_OBJECT_SIZE
|
{
|
||||||
// 2. In some cases this must be only interactive size, not GO size, current way can affect creature target point auto-selection in strange ways for big underground/virtual GOs
|
float dx = m_displayInfo->geoBoxMaxX - m_displayInfo->geoBoxMinX;
|
||||||
/*if (m_displayInfo)
|
float dy = m_displayInfo->geoBoxMaxY - m_displayInfo->geoBoxMinY;
|
||||||
return fabs(m_displayInfo->unknown12) * GetObjectScale();*/
|
float dz = m_displayInfo->geoBoxMaxZ - m_displayInfo->geoBoxMinZ;
|
||||||
|
|
||||||
|
return (std::abs(dx) + std::abs(dy) + std::abs(dz)) / 2 * GetObjectScale();
|
||||||
|
}
|
||||||
|
|
||||||
return DEFAULT_WORLD_OBJECT_SIZE;
|
return DEFAULT_WORLD_OBJECT_SIZE;
|
||||||
}
|
}
|
||||||
|
|
@ -2150,23 +2193,132 @@ void GameObject::TickCapturePoint()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventId)
|
if (eventId)
|
||||||
{
|
StartEvents_Event(GetMap(), eventId, this, this, true, *capturingPlayers.begin());
|
||||||
// Notify the battleground or outdoor pvp script
|
}
|
||||||
if (BattleGround* bg = (*capturingPlayers.begin())->GetBattleGround())
|
|
||||||
{
|
// ////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Allow only certain events to be handled by other script engines
|
// Destructible GO handling
|
||||||
if (bg->HandleEvent(eventId, this))
|
// ////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
return;
|
void GameObject::DealGameObjectDamage(uint32 damage, uint32 spell, Unit* caster)
|
||||||
}
|
{
|
||||||
else if (OutdoorPvP* outdoorPvP = sOutdoorPvPMgr.GetScript((*capturingPlayers.begin())->GetCachedZoneId()))
|
MANGOS_ASSERT(GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING);
|
||||||
{
|
MANGOS_ASSERT(spell && sSpellStore.LookupEntry(spell) && caster);
|
||||||
// Allow only certain events to be handled by other script engines
|
|
||||||
if (outdoorPvP->HandleEvent(eventId, this))
|
if (!damage)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
ForceGameObjectHealth(-int32(damage), caster);
|
||||||
// Send script event to SD2 and database as well - this can be used for summoning creatures, casting specific spells or spawning GOs
|
|
||||||
if (!sScriptMgr.OnProcessEvent(eventId, this, this, true))
|
WorldPacket data(SMSG_DESTRUCTIBLE_BUILDING_DAMAGE, 9+9+9+4+4);
|
||||||
GetMap()->ScriptsStart(sEventScripts, eventId, this, this);
|
data << GetPackGUID();
|
||||||
}
|
data << caster->GetPackGUID();
|
||||||
|
data << caster->GetCharmerOrOwnerOrSelf()->GetPackGUID();
|
||||||
|
data << uint32(damage);
|
||||||
|
data << uint32(spell);
|
||||||
|
SendMessageToSet(&data, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameObject::RebuildGameObject(uint32 spell, Unit* caster)
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING);
|
||||||
|
MANGOS_ASSERT(caster);
|
||||||
|
|
||||||
|
ForceGameObjectHealth(0, caster);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameObject::ForceGameObjectHealth(int32 diff, Unit* caster)
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING);
|
||||||
|
MANGOS_ASSERT(caster || diff >= 0);
|
||||||
|
|
||||||
|
if (diff < 0) // Taken damage
|
||||||
|
{
|
||||||
|
DEBUG_FILTER_LOG(LOG_FILTER_DAMAGE, "DestructibleGO: %s taken damage %u dealt by %s", GetGuidStr().c_str(), uint32(-diff), caster->GetGuidStr().c_str());
|
||||||
|
|
||||||
|
if (m_useTimes > uint32(-diff))
|
||||||
|
m_useTimes += diff;
|
||||||
|
else
|
||||||
|
m_useTimes = 0;
|
||||||
|
}
|
||||||
|
else if (diff == 0 && GetMaxHealth()) // Rebuild - TODO: Rebuilding over time with special display-id?
|
||||||
|
{
|
||||||
|
DEBUG_FILTER_LOG(LOG_FILTER_DAMAGE, "DestructibleGO: %s start rebuild by %s", GetGuidStr().c_str(), caster->GetGuidStr().c_str());
|
||||||
|
|
||||||
|
m_useTimes = GetMaxHealth();
|
||||||
|
// Start Event if exist
|
||||||
|
if (caster && m_goInfo->destructibleBuilding.rebuildingEvent)
|
||||||
|
StartEvents_Event(GetMap(), m_goInfo->destructibleBuilding.rebuildingEvent, this, caster->GetCharmerOrOwnerOrSelf(), true, caster->GetCharmerOrOwnerOrSelf());
|
||||||
|
}
|
||||||
|
else // Set to value
|
||||||
|
m_useTimes = uint32(diff);
|
||||||
|
|
||||||
|
uint32 newDisplayId = 0xFFFFFFFF; // Set to invalid -1 to track if we switched to a change state
|
||||||
|
DestructibleModelDataEntry const* destructibleInfo = sDestructibleModelDataStore.LookupEntry(m_goInfo->destructibleBuilding.destructibleData);
|
||||||
|
|
||||||
|
// Get Current State - Note about order: Important for GetMaxHealth() == 0
|
||||||
|
if (m_useTimes == GetMaxHealth()) // Full Health
|
||||||
|
{
|
||||||
|
DEBUG_FILTER_LOG(LOG_FILTER_DAMAGE, "DestructibleGO: %s set to full health %u", GetGuidStr().c_str(), m_useTimes);
|
||||||
|
|
||||||
|
RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK_9 | GO_FLAG_UNK_10 | GO_FLAG_UNK_11);
|
||||||
|
newDisplayId = m_goInfo->displayId;
|
||||||
|
|
||||||
|
// Start Event if exist
|
||||||
|
if (caster && m_goInfo->destructibleBuilding.intactEvent)
|
||||||
|
StartEvents_Event(GetMap(), m_goInfo->destructibleBuilding.intactEvent, this, caster->GetCharmerOrOwnerOrSelf(), true, caster->GetCharmerOrOwnerOrSelf());
|
||||||
|
}
|
||||||
|
else if (m_useTimes == 0) // Destroyed
|
||||||
|
{
|
||||||
|
if (!HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK_11)) // Was not destroyed before
|
||||||
|
{
|
||||||
|
DEBUG_FILTER_LOG(LOG_FILTER_DAMAGE, "DestructibleGO: %s got destroyed", GetGuidStr().c_str());
|
||||||
|
|
||||||
|
RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK_9 | GO_FLAG_UNK_10);
|
||||||
|
SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK_11);
|
||||||
|
|
||||||
|
// Get destroyed DisplayId
|
||||||
|
if ((!m_goInfo->destructibleBuilding.destroyedDisplayId || m_goInfo->destructibleBuilding.destroyedDisplayId == 1) && destructibleInfo)
|
||||||
|
newDisplayId = destructibleInfo->destroyedDisplayId;
|
||||||
|
else
|
||||||
|
newDisplayId = m_goInfo->destructibleBuilding.destroyedDisplayId;
|
||||||
|
|
||||||
|
if (!newDisplayId) // No proper destroyed display ID exists, fetch damaged
|
||||||
|
{
|
||||||
|
if ((!m_goInfo->destructibleBuilding.damagedDisplayId || m_goInfo->destructibleBuilding.damagedDisplayId == 1) && destructibleInfo)
|
||||||
|
newDisplayId = destructibleInfo->damagedDisplayId;
|
||||||
|
else
|
||||||
|
newDisplayId = m_goInfo->destructibleBuilding.damagedDisplayId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start Event if exist
|
||||||
|
if (caster && m_goInfo->destructibleBuilding.destroyedEvent)
|
||||||
|
StartEvents_Event(GetMap(), m_goInfo->destructibleBuilding.destroyedEvent, this, caster->GetCharmerOrOwnerOrSelf(), true, caster->GetCharmerOrOwnerOrSelf());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_useTimes <= m_goInfo->destructibleBuilding.damagedNumHits) // Damaged
|
||||||
|
{
|
||||||
|
if (!HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK_10)) // Was not damaged before
|
||||||
|
{
|
||||||
|
DEBUG_FILTER_LOG(LOG_FILTER_DAMAGE, "DestructibleGO: %s got damaged (health now %u)", GetGuidStr().c_str(), m_useTimes);
|
||||||
|
|
||||||
|
SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK_10);
|
||||||
|
|
||||||
|
// Get damaged DisplayId
|
||||||
|
if ((!m_goInfo->destructibleBuilding.damagedDisplayId || m_goInfo->destructibleBuilding.damagedDisplayId == 1) && destructibleInfo)
|
||||||
|
newDisplayId = destructibleInfo->damagedDisplayId;
|
||||||
|
else
|
||||||
|
newDisplayId = m_goInfo->destructibleBuilding.damagedDisplayId;
|
||||||
|
|
||||||
|
// Start Event if exist
|
||||||
|
if (caster && m_goInfo->destructibleBuilding.damagedEvent)
|
||||||
|
StartEvents_Event(GetMap(), m_goInfo->destructibleBuilding.damagedEvent, this, caster->GetCharmerOrOwnerOrSelf(), true, caster->GetCharmerOrOwnerOrSelf());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set display Id
|
||||||
|
if (newDisplayId != 0xFFFFFFFF && newDisplayId != GetDisplayId() && newDisplayId)
|
||||||
|
SetDisplayId(newDisplayId);
|
||||||
|
|
||||||
|
// Set health
|
||||||
|
SetGoAnimProgress(GetMaxHealth() ? m_useTimes * 255 / GetMaxHealth() : 255);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "12552"
|
#define REVISION_NR "12553"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue