RMDC Donator
Регистрация: 07.03.2010
Адрес: Кыргызстан
Сообщений: 52
Сказал(а) спасибо: 18
Поблагодарили 45 раз(а) в 11 сообщениях
|
Код:
diff --git a/src/game/Cell.h b/src/game/Cell.h
index 10ec221..d12f346 100644
--- a/src/game/Cell.h
+++ b/src/game/Cell.h
@@ -160,8 +160,10 @@ struct MANGOS_DLL_DECL Cell
template<class T, class CONTAINER> void Visit(const CellPair &cellPair, TypeContainerVisitor<T, CONTAINER> &visitor, Map &) const;
template<class T, class CONTAINER> void Visit(const CellPair &cellPair, TypeContainerVisitor<T, CONTAINER> &visitor, Map &m, const WorldObject &obj, float radius) const;
+ template<class T, class CONTAINER> void Visit(const CellPair &cellPair, TypeContainerVisitor<T, CONTAINER> &visitor, Map &, float radius, float x_off, float y_off) const;
static CellArea CalculateCellArea(const WorldObject &obj, float radius);
+ static CellArea CalculateCellArea(float x, float y, float radius);
private:
template<class T, class CONTAINER> void VisitCircle(const CellPair &cellPair, TypeContainerVisitor<T, CONTAINER> &, Map &, const CellPair& , const CellPair& ) const;
diff --git a/src/game/CellImpl.h b/src/game/CellImpl.h
index a6be9f0..c8400bb 100644
--- a/src/game/CellImpl.h
+++ b/src/game/CellImpl.h
@@ -279,4 +279,49 @@ Cell::VisitCircle(const CellPair &standing_cell, TypeContainerVisitor<T, CONTAIN
}
}
+template<class T, class CONTAINER>
+inline void
+Cell::Visit(const CellPair &standing_cell, TypeContainerVisitor<T, CONTAINER> &visitor, Map &m, float radius, float x_off, float y_off) const
+{
+ if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
+ return;
+
+ int left = 0, right = 0, upper = 0, lower = 0;
+
+ // Origin = (CENTER_GRID_CELL_OFFSET, CENTER_GRID_CELL_OFFSET)
+ if(CENTER_GRID_CELL_OFFSET - x_off < radius)
+ ++right;
+ if(CENTER_GRID_CELL_OFFSET + x_off < radius)
+ ++left;
+ if(CENTER_GRID_CELL_OFFSET - y_off < radius)
+ ++upper;
+ if(CENTER_GRID_CELL_OFFSET + y_off < radius)
+ ++lower;
+
+ if(!left && !right && !upper && !lower)
+ {
+ m.Visit(*this, visitor);
+ return;
+ }
+
+ CellPair begin_cell = standing_cell;
+ CellPair end_cell = standing_cell;
+
+ begin_cell << left; //note: need change << if left > 1
+ begin_cell -= lower;
+ end_cell >> right;
+ end_cell += upper;
+
+ // loop the cell range
+ for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; x++)
+ {
+ for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; y++)
+ {
+ CellPair cell_pair(x,y);
+ Cell r_zone(cell_pair);
+ r_zone.data.Part.nocreate = data.Part.nocreate;
+ m.Visit(r_zone, visitor);
+ }
+ }
+}
#endif
diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h
index 30d000f..fbede52 100644
--- a/src/game/DBCStructure.h
+++ b/src/game/DBCStructure.h
@@ -844,9 +844,14 @@ struct GameObjectDisplayInfoEntry
{
uint32 Displayid; // 0 m_ID
// char* filename; // 1
- // uint32 unknown2[10]; // 2-11 unknown data
- // float unknown12[6]; // 12-17 unknown data
- // uint32 unknown18; // 18 unknown data
+ //uint32 unk1[10]; //2-11
+ float minX;
+ float minY;
+ float minZ;
+ float maxX;
+ float maxY;
+ float maxZ;
+ //uint32 transport; //18
};
struct GemPropertiesEntry
diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp
index b75076a..5a784f5 100644
--- a/src/game/GameObject.cpp
+++ b/src/game/GameObject.cpp
@@ -151,6 +151,9 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMa
SetGoArtKit(0); // unknown what this is
SetGoAnimProgress(animprogress);
+ if(goinfo->type == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
+ m_health = goinfo->destructibleBuilding.damagedHealth;
+
//Notify the map's instance data.
//Only works if you create the object in it, not if it is moves to that map.
//Normally non-players do not teleport to other maps.
@@ -1000,6 +1003,11 @@ void GameObject::Use(Unit* user)
{
sLog.outDebug("Goober ScriptStart id %u for GO entry %u (GUID %u).", info->goober.eventId, GetEntry(), GetDBTableGUIDLow());
GetMap()->ScriptsStart(sEventScripts, info->goober.eventId, player, this);
+ ////////////////// Strand of the Ancients ///////////////////
+ /*if (player->CanUseBattleGroundObject())
+ if (BattleGround *bg = player->GetBattleGround())
+ if (bg->GetTypeID() == BATTLEGROUND_SA)
+ bg->EventPlayerDamegeGO(player, this, info->goober.eventId);*/
}
// possible quest objective for active quests
@@ -1349,6 +1357,120 @@ void GameObject::Use(Unit* user)
spell->prepare(&targets);
}
+bool GameObject::IsInRange(float x, float y, float z, float radius) const
+{
+ GameObjectDisplayInfoEntry const * info = sGameObjectDisplayInfoStore.LookupEntry(GetUInt32Value(GAMEOBJECT_DISPLAYID));
+ if(!info)
+ return IsWithinDist3d(x, y, z, radius);
+
+ float sinA = sin(GetOrientation());
+ float cosA = cos(GetOrientation());
+ float dx = x - GetPositionX();
+ float dy = y - GetPositionY();
+ float dz = z - GetPositionZ();
+ float dist = sqrt(dx*dx + dy*dy);
+ float sinB = dx / dist;
+ float cosB = dy / dist;
+ dx = dist * (cosA * cosB + sinA * sinB);
+ dy = dist * (cosA * sinB - sinA * cosB);
+ return dx < info->maxX + radius && dx > info->minX - radius
+ && dy < info->maxY + radius && dy > info->minY - radius
+ && dz < info->maxZ + radius && dz > info->minZ - radius;
+}
+
+void GameObject::TakenDamage(uint32 damage, Unit* pKiller)
+{
+ if(!m_health)
+ return;
+
+ if(m_health > damage)
+ {
+ m_health -= damage;
+ return;
+ }
+
+ m_health = 0;
+
+ if (HasFlag(GAMEOBJECT_FLAGS,GO_FLAG_DAMAGED) && !HasFlag(GAMEOBJECT_FLAGS,GO_FLAG_DESTROYED)) // from damaged to destroyed
+ {
+ RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED);
+ SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED);
+ SetUInt32Value(GAMEOBJECT_DISPLAYID, m_goInfo->destructibleBuilding.destroyedDisplayId);
+ m_health = 0;
+ }
+ else if(!HasFlag(GAMEOBJECT_FLAGS,GO_FLAG_DAMAGED) && !HasFlag(GAMEOBJECT_FLAGS,GO_FLAG_DESTROYED))
+ {
+ SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED);
+ SetUInt32Value(GAMEOBJECT_DISPLAYID, m_goInfo->destructibleBuilding.damagedDisplayId);
+ if(m_goInfo->destructibleBuilding.destroyedDisplayId)
+ {
+ m_health = m_goInfo->destructibleBuilding.destroyedHealth;
+ if(!m_health)
+ m_health = 1;
+ }
+ else
+ m_health = 0;
+ }
+}
+
+void GameObject::Rebuild(Unit* pKiller)
+{
+ RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED + GO_FLAG_DESTROYED);
+ SetUInt32Value(GAMEOBJECT_DISPLAYID, m_goInfo->displayId);
+ m_health = m_goInfo->destructibleBuilding.damagedHealth;
+ if (!pKiller)
+ return;
+ Player* unitPlayer;
+ if(pKiller->GetTypeId() == TYPEID_PLAYER)
+ unitPlayer = (Player*)pKiller;
+ else if(((Creature*)pKiller)->isVehicle())
+ unitPlayer = (Player*)pKiller->GetCharmerOrOwnerOrSelf();
+ else
+ unitPlayer = NULL;
+
+ if (unitPlayer->CanUseBattleGroundObject())
+ EventInform(m_goInfo->destructibleBuilding.rebuildingEvent, unitPlayer);
+}
+
// overwrite WorldObject function for proper name localization
const char* GameObject::GetNameForLocaleIdx(int32 loc_idx) const
{
diff --git a/src/game/GameObject.h b/src/game/GameObject.h
index d92da00..c2ae485 100644
--- a/src/game/GameObject.h
+++ b/src/game/GameObject.h
@@ -356,17 +356,17 @@ struct GameObjectInfo
//33 GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING
struct
{
- uint32 intactNumHits; //0
+ uint32 damagedHealth; //0
uint32 creditProxyCreature; //1
uint32 empty1; //2
uint32 intactEvent; //3
- uint32 empty2; //4
- uint32 damagedNumHits; //5
+ uint32 damagedDisplayId; //4
+ uint32 destroyedHealth; //5
uint32 empty3; //6
uint32 empty4; //7
uint32 empty5; //8
uint32 damagedEvent; //9
- uint32 empty6; //10
+ uint32 destroyedDisplayId; //10
uint32 empty7; //11
uint32 empty8; //12
uint32 empty9; //13
@@ -687,6 +687,12 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
bool isActiveObject() const { return false; }
uint64 GetRotation() const { return m_rotation; }
+
+ bool IsInRange(float x, float y, float z, float radius) const;
+ void TakenDamage(uint32 damage, Unit* pKiller);
+ void Rebuild(Unit* pKiller);
+
protected:
uint32 m_spellId;
time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),
@@ -694,6 +700,7 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
LootState m_lootState;
bool m_spawnedByDefault;
time_t m_cooldownTime; // used as internal reaction delay time store (not state change reaction).
+ uint32 m_health;
// For traps this: spell casting cooldown, for doors/buttons: reset time.
std::list<uint32> m_SkillupList;
diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h
index 5c132e6..dacaed5 100644
--- a/src/game/GridNotifiers.h
+++ b/src/game/GridNotifiers.h
@@ -654,6 +654,24 @@ namespace MaNGOS
NearestGameObjectFishingHole(NearestGameObjectFishingHole const&);
};
+ class NearestGameObjectCheck
+ {
+ public:
+ NearestGameObjectCheck(WorldObject const& obj) : i_obj(obj), i_range(999) {}
+ bool operator()(GameObject* go)
+ {
+ i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check
+ return true;
+ }
+ float GetLastRange() const { return i_range; }
+ private:
+ WorldObject const& i_obj;
+ float i_range;
+
+ // prevent clone this object
+ NearestGameObjectCheck(NearestGameObjectCheck const&);
+ };
+
// Success at unit in range, range update for next check (this can be use with GameobjectLastSearcher to find nearest GO)
class NearestGameObjectEntryInObjectRangeCheck
{
@@ -1027,6 +1045,18 @@ namespace MaNGOS
NearestCreatureEntryWithLiveStateInObjectRangeCheck(NearestCreatureEntryWithLiveStateInObjectRangeCheck const&);
};
+ class GameObjectInRangeCheck
+ {
+ public:
+ GameObjectInRangeCheck(float _x, float _y, float _z, float _range) : x(_x), y(_y), z(_z), range(_range) {}
+ bool operator() (GameObject* go)
+ {
+ return go->IsInRange(x, y, z, range);
+ }
+ private:
+ float x, y, z, range;
+ };
+
class AnyPlayerInObjectRangeCheck
{
public:
diff --git a/src/game/Map.h b/src/game/Map.h
index 6e68529..0ff3799 100644
--- a/src/game/Map.h
+++ b/src/game/Map.h
@@ -406,6 +406,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
void RemoveFromActive(T* obj) { RemoveFromActiveHelper(obj); }
void RemoveFromActive(Creature* obj);
+
+ template<class NOTIFIER> void VisitGrid(const float &x, const float &y, float radius, NOTIFIER ¬ifier);
Creature* GetCreature(uint64 guid);
Vehicle* GetVehicle(uint64 guid);
@@ -629,4 +631,17 @@ Map::Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER> &visitor)
getNGrid(x, y)->Visit(cell_x, cell_y, visitor);
}
}
-#endif
+
+template<class NOTIFIER>
+inline void
+Map::VisitGrid(const float &x, const float &y, float radius, NOTIFIER ¬ifier)
+{
+ CellPair p(MaNGOS::ComputeCellPair(x, y));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ TypeContainerVisitor<NOTIFIER, GridTypeMapContainer > grid_object_notifier(notifier);
+ cell.Visit(p, grid_object_notifier, *this, radius, x, y);
+}
+#endif
\ No newline at end of file
diff --git a/src/game/Object.cpp b/src/game/Object.cpp
index 6d1a2b2..64f27d7 100644
--- a/src/game/Object.cpp
+++ b/src/game/Object.cpp
@@ -733,7 +733,7 @@ void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *
if( updateMask->GetBit( index ) )
{
// send in current format (float as float, uint32 as uint32)
- if ( index == GAMEOBJECT_DYNAMIC )
+ if (/*false && */index == GAMEOBJECT_DYNAMIC )
{
if(IsActivateToQuest )
{
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
index db31834..61d06d5 100644
--- a/src/game/SharedDefines.h
+++ b/src/game/SharedDefines.h
@@ -1070,6 +1070,7 @@ enum Targets
TARGET_DYNAMIC_OBJECT_BEHIND = 48,
TARGET_DYNAMIC_OBJECT_LEFT_SIDE = 49,
TARGET_DYNAMIC_OBJECT_RIGHT_SIDE = 50,
+ TARGET_OBJECT_AREA_SRC = 51,
TARGET_AREAEFFECT_CUSTOM_2 = 52,
TARGET_CURRENT_ENEMY_COORDINATES = 53, // set unit coordinates as dest, only 16 target B imlemented
TARGET_LARGE_FRONTAL_CONE = 54,
@@ -1197,8 +1198,8 @@ enum GameObjectFlags
GO_FLAG_TRIGGERED = 0x00000040, //typically, summoned objects. Triggered by spell or other events
GO_FLAG_UNK_8 = 0x00000080,
GO_FLAG_UNK_9 = 0x00000100, //? Seen on type 33, possible meaning "destruct in progress"
- GO_FLAG_UNK_10 = 0x00000200, //? Seen on type 33
- GO_FLAG_UNK_11 = 0x00000400 //? Seen on type 33, possibly meaning "destructed"
+ GO_FLAG_DAMAGED = 0x00000200, //? Seen on type 33
+ GO_FLAG_DESTROYED = 0x00000400 //? Seen on type 33, possibly meaning "destructed"
};
enum TextEmotes
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 0c80e73..6c9552f 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -1429,9 +1429,38 @@ void Spell::SetTargetMap(uint32 effIndex, uint32 targetMode, UnitList& targetUni
case TARGET_SELF:
case TARGET_SELF2:
case TARGET_AREAEFFECT_CUSTOM:
- case TARGET_AREAEFFECT_CUSTOM_2:
targetUnitMap.push_back(m_caster);
break;
+ case TARGET_AREAEFFECT_CUSTOM_2:
+ {
+ float x, y, z;
+ if(targetMode == TARGET_OBJECT_AREA_SRC)
+ {
+ if(m_targets.HasSrc())
+ {
+ x = m_targets.m_srcX;
+ y = m_targets.m_srcY;
+ z = m_targets.m_srcZ;
+ }
+ else
+ break;
+ }
+ else if(m_targets.HasDst())
+ {
+ x = m_targets.m_destX;
+ y = m_targets.m_destY;
+ z = m_targets.m_destZ;
+ }
+ else
+ break;
+
+ MaNGOS::GameObjectInRangeCheck check(x, y, z, radius + 15);
+ std::list<GameObject*> goList;
+ MaNGOS::GameObjectListSearcher<MaNGOS::GameObjectInRangeCheck> searcher(m_caster, goList, check);
+ m_caster->GetMap()->VisitGrid(x, y, radius, searcher);
+ for(std::list<GameObject*>::iterator itr = goList.begin(); itr != goList.end(); ++itr)
+ AddGOTarget(*itr, effIndex);
+ }
case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA:
{
m_targets.m_targetMask = 0;
diff --git a/src/game/Spell.h b/src/game/Spell.h
index 00878b4..058c8a9 100644
--- a/src/game/Spell.h
+++ b/src/game/Spell.h
@@ -164,6 +164,8 @@ class SpellCastTargets
}
bool IsEmpty() const { return m_GOTargetGUID==0 && m_unitTargetGUID==0 && m_itemTarget==0 && m_CorpseTargetGUID==0; }
+ bool HasSrc() const { return m_targetMask & TARGET_FLAG_SOURCE_LOCATION; }
+ bool HasDst() const { return m_targetMask & TARGET_FLAG_DEST_LOCATION; }
void Update(Unit* caster);
@@ -323,6 +325,8 @@ class Spell
void EffectKillCreditPersonal(uint32 i);
void EffectKillCredit(uint32 i);
void EffectQuestFail(uint32 i);
+ void EffectWMODamage(uint32 i);
+ void EffectWMORepair(uint32 i);
void EffectActivateRune(uint32 i);
void EffectTitanGrip(uint32 i);
void EffectEnchantItemPrismatic(uint32 i);
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index 5e18c1b..6ad6932 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -144,8 +144,8 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
&Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
&Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
- &Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE
- &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
+ &Spell::EffectWMODamage, // 87 SPELL_EFFECT_WMO_DAMAGE
+ &Spell::EffectWMORepair, // 88 SPELL_EFFECT_WMO_REPAIR
&Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
&Spell::EffectKillCreditPersonal, // 90 SPELL_EFFECT_KILL_CREDIT Kill credit but only for single person
&Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
@@ -3158,7 +3158,7 @@ void Spell::EffectOpenLock(uint32 effIndex)
if (BattleGround *bg = player->GetBattleGround())
{
// check if it's correct bg
- if (bg->GetTypeID() == BATTLEGROUND_AB || bg->GetTypeID() == BATTLEGROUND_AV)
+ if (bg->GetTypeID() == BATTLEGROUND_AB || bg->GetTypeID() == BATTLEGROUND_AV || bg->GetTypeID() == BATTLEGROUND_SA)
bg->EventPlayerClickedOnFlag(player, gameObjTarget);
return;
}
@@ -6965,3 +6965,15 @@ void Spell::EffectPlayMusic(uint32 i)
data << uint32(soundid);
((Player*)unitTarget)->GetSession()->SendPacket(&data);
}
+
+void Spell::EffectWMODamage(uint32 /*i*/)
+{
+ if(gameObjTarget && gameObjTarget->GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
+ gameObjTarget->TakenDamage((uint32)damage,m_caster);
+}
+
+void Spell::EffectWMORepair(uint32 /*i*/)
+{
+ if(gameObjTarget && gameObjTarget->GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING)
+ gameObjTarget->Rebuild(m_caster);
+}
Патч на ядро,
автор: Rage Hunter.
Однако надо его чуть чуть переписать, ибо 9245 коммит
Цитата:
[9245] Remove CellLock class and all cell-level thread locking.
* CellLock was just a 'proxy' between Cell and CellPair and in some cases carried redundant data.
|
|