[11878] Add group looting rules for gameobjects (chests)

Patch based on original work by Wowka321

Signed-off-by: Schmoozerd <schmoozerd@scriptdev2.com>
This commit is contained in:
darkstalker 2011-06-17 01:18:27 +03:00 committed by Schmoozerd
parent 16b244373a
commit 461be74c3a
7 changed files with 209 additions and 26 deletions

View file

@ -59,6 +59,9 @@ GameObject::GameObject() : WorldObject(),
m_cooldownTime = 0; m_cooldownTime = 0;
m_packedRotation = 0; m_packedRotation = 0;
m_groupLootTimer = 0;
m_groupLootId = 0;
m_lootGroupRecipientId = 0;
} }
GameObject::~GameObject() GameObject::~GameObject()
@ -352,6 +355,15 @@ void GameObject::Update(uint32 update_diff, uint32 /*p_time*/)
if (GetGOInfo()->GetAutoCloseTime() && (m_cooldownTime < time(NULL))) if (GetGOInfo()->GetAutoCloseTime() && (m_cooldownTime < time(NULL)))
ResetDoorOrButton(); ResetDoorOrButton();
break; break;
case GAMEOBJECT_TYPE_CHEST:
if (m_groupLootTimer)
{
if (m_groupLootTimer <= update_diff)
StopGroupLoot();
else
m_groupLootTimer -= update_diff;
}
break;
case GAMEOBJECT_TYPE_GOOBER: case GAMEOBJECT_TYPE_GOOBER:
if (m_cooldownTime < time(NULL)) if (m_cooldownTime < time(NULL))
{ {
@ -415,6 +427,7 @@ void GameObject::Update(uint32 update_diff, uint32 /*p_time*/)
} }
loot.clear(); loot.clear();
SetLootRecipient(NULL);
SetLootState(GO_READY); SetLootState(GO_READY);
if (!m_respawnDelayTime) if (!m_respawnDelayTime)
@ -1804,6 +1817,86 @@ void GameObject::SetDisplayId(uint32 modelId)
m_displayInfo = sGameObjectDisplayInfoStore.LookupEntry(modelId); m_displayInfo = sGameObjectDisplayInfoStore.LookupEntry(modelId);
} }
void GameObject::StartGroupLoot(Group* group, uint32 timer)
{
m_groupLootId = group->GetId();
m_groupLootTimer = timer;
}
void GameObject::StopGroupLoot()
{
if (!m_groupLootId)
return;
if (Group* group = sObjectMgr.GetGroupById(m_groupLootId))
group->EndRoll();
m_groupLootTimer = 0;
m_groupLootId = 0;
}
Player* GameObject::GetOriginalLootRecipient() const
{
return m_lootRecipientGuid ? ObjectAccessor::FindPlayer(m_lootRecipientGuid) : NULL;
}
Group* GameObject::GetGroupLootRecipient() const
{
// original recipient group if set and not disbanded
return m_lootGroupRecipientId ? sObjectMgr.GetGroupById(m_lootGroupRecipientId) : NULL;
}
Player* GameObject::GetLootRecipient() const
{
// original recipient group if set and not disbanded
Group* group = GetGroupLootRecipient();
// original recipient player if online
Player* player = GetOriginalLootRecipient();
// if group not set or disbanded return original recipient player if any
if (!group)
return player;
// group case
// return player if it still be in original recipient group
if (player && player->GetGroup() == group)
return player;
// find any in group
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
if (Player* newPlayer = itr->getSource())
return newPlayer;
return NULL;
}
void GameObject::SetLootRecipient(Unit* pUnit)
{
// set the player whose group should receive the right
// to loot the gameobject after its used
// should be set to NULL after the loot disappears
if (!pUnit)
{
m_lootRecipientGuid.Clear();
m_lootGroupRecipientId = 0;
return;
}
Player* player = pUnit->GetCharmerOrOwnerPlayerOrPlayerItself();
if (!player) // normal creature, no player involved
return;
// set player for non group case or if group will disbanded
m_lootRecipientGuid = player->GetObjectGuid();
// set group for group existed case including if player will leave group at loot time
if (Group* group = player->GetGroup())
m_lootGroupRecipientId = group->GetId();
}
float GameObject::GetObjectBoundingRadius() const float GameObject::GetObjectBoundingRadius() const
{ {
//FIXME: //FIXME:

View file

@ -681,7 +681,6 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
static void AddToRemoveListInMaps(uint32 db_guid, GameObjectData const* data); static void AddToRemoveListInMaps(uint32 db_guid, GameObjectData const* data);
static void SpawnInMaps(uint32 db_guid, GameObjectData const* data); static void SpawnInMaps(uint32 db_guid, GameObjectData const* data);
void getFishLoot(Loot *loot, Player* loot_owner);
GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); } GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); }
void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); } void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); }
GOState GetGoState() const { return GOState(GetByteValue(GAMEOBJECT_BYTES_1, 0)); } GOState GetGoState() const { return GOState(GetByteValue(GAMEOBJECT_BYTES_1, 0)); }
@ -719,7 +718,19 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
void SaveRespawnTime(); void SaveRespawnTime();
// Loot System
Loot loot; Loot loot;
void getFishLoot(Loot* loot, Player* loot_owner);
void StartGroupLoot(Group* group, uint32 timer);
ObjectGuid GetLootRecipientGuid() const { return m_lootRecipientGuid; }
uint32 GetLootGroupRecipientId() const { return m_lootGroupRecipientId; }
Player* GetLootRecipient() const; // use group cases as prefered
Group* GetGroupLootRecipient() const;
bool HasLootRecipient() const { return m_lootGroupRecipientId || !m_lootRecipientGuid.IsEmpty(); }
bool IsGroupLootRecipient() const { return m_lootGroupRecipientId; }
void SetLootRecipient(Unit* pUnit);
Player* GetOriginalLootRecipient() const; // ignore group changes/etc, not for looting
bool HasQuest(uint32 quest_id) const; bool HasQuest(uint32 quest_id) const;
bool HasInvolvedQuest(uint32 quest_id) const; bool HasInvolvedQuest(uint32 quest_id) const;
@ -763,6 +774,14 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
GameObjectDisplayInfoEntry const* m_displayInfo; GameObjectDisplayInfoEntry const* m_displayInfo;
int64 m_packedRotation; int64 m_packedRotation;
QuaternionData m_worldRotation; QuaternionData m_worldRotation;
// Loot System
uint32 m_groupLootTimer; // (msecs)timer used for group loot
uint32 m_groupLootId; // used to find group which is looting
void StopGroupLoot();
ObjectGuid m_lootRecipientGuid; // player who will have rights for looting if m_lootGroupRecipient==0 or group disbanded
uint32 m_lootGroupRecipientId; // group who will have rights for looting if set and exist
private: private:
void SwitchDoorOrButton(bool activate, bool alternative = false); void SwitchDoorOrButton(bool activate, bool alternative = false);

View file

@ -585,7 +585,7 @@ void Group::SendLootAllPassed(Roll const& r)
} }
} }
void Group::GroupLoot(Creature *creature, Loot *loot) void Group::GroupLoot(WorldObject* pSource, Loot* loot)
{ {
uint32 maxEnchantingSkill = GetMaxSkillValueForGroup(SKILL_ENCHANTING); uint32 maxEnchantingSkill = GetMaxSkillValueForGroup(SKILL_ENCHANTING);
@ -601,13 +601,13 @@ void Group::GroupLoot(Creature *creature, Loot *loot)
//roll for over-threshold item if it's one-player loot //roll for over-threshold item if it's one-player loot
if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall) if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall)
StartLootRool(creature, GROUP_LOOT, loot, itemSlot, maxEnchantingSkill); StartLootRool(pSource, GROUP_LOOT, loot, itemSlot, maxEnchantingSkill);
else else
lootItem.is_underthreshold = 1; lootItem.is_underthreshold = 1;
} }
} }
void Group::NeedBeforeGreed(Creature *creature, Loot *loot) void Group::NeedBeforeGreed(WorldObject* pSource, Loot* loot)
{ {
uint32 maxEnchantingSkill = GetMaxSkillValueForGroup(SKILL_ENCHANTING); uint32 maxEnchantingSkill = GetMaxSkillValueForGroup(SKILL_ENCHANTING);
@ -623,13 +623,13 @@ void Group::NeedBeforeGreed(Creature *creature, Loot *loot)
//only roll for one-player items, not for ones everyone can get //only roll for one-player items, not for ones everyone can get
if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall) if (itemProto->Quality >= uint32(m_lootThreshold) && !lootItem.freeforall)
StartLootRool(creature, NEED_BEFORE_GREED, loot, itemSlot, maxEnchantingSkill); StartLootRool(pSource, NEED_BEFORE_GREED, loot, itemSlot, maxEnchantingSkill);
else else
lootItem.is_underthreshold = 1; lootItem.is_underthreshold = 1;
} }
} }
void Group::MasterLoot(Creature *creature, Loot* loot) void Group::MasterLoot(WorldObject* pSource, Loot* loot)
{ {
for (LootItemList::iterator i=loot->items.begin(); i != loot->items.end(); ++i) for (LootItemList::iterator i=loot->items.begin(); i != loot->items.end(); ++i)
{ {
@ -651,7 +651,7 @@ void Group::MasterLoot(Creature *creature, Loot* loot)
if (!looter->IsInWorld()) if (!looter->IsInWorld())
continue; continue;
if (looter->IsWithinDist(creature, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false)) if (looter->IsWithinDist(pSource, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false))
{ {
data << looter->GetObjectGuid(); data << looter->GetObjectGuid();
++real_count; ++real_count;
@ -663,7 +663,7 @@ void Group::MasterLoot(Creature *creature, Loot* loot)
for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{ {
Player *looter = itr->getSource(); Player *looter = itr->getSource();
if (looter->IsWithinDist(creature, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false)) if (looter->IsWithinDist(pSource, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false))
looter->GetSession()->SendPacket(&data); looter->GetSession()->SendPacket(&data);
} }
} }
@ -743,7 +743,7 @@ bool Group::CountRollVote(ObjectGuid const& playerGUID, Rolls::iterator& rollI,
return false; return false;
} }
void Group::StartLootRool(Creature* lootTarget, LootMethod method, Loot* loot, uint8 itemSlot, uint32 maxEnchantingSkill) void Group::StartLootRool(WorldObject* lootTarget, LootMethod method, Loot* loot, uint8 itemSlot, uint32 maxEnchantingSkill)
{ {
if (itemSlot >= loot->items.size()) if (itemSlot >= loot->items.size())
return; return;
@ -778,11 +778,15 @@ void Group::StartLootRool(Creature* lootTarget, LootMethod method, Loot* loot, u
r->playerVote.begin()->second = ROLL_NEED; r->playerVote.begin()->second = ROLL_NEED;
else else
{ {
// Only GO-group looting and NPC-group looting possible
MANGOS_ASSERT(lootTarget->isType(TYPEMASK_CREATURE_OR_GAMEOBJECT));
r->CalculateCommonVoteMask(maxEnchantingSkill); // dependent from item and possible skill r->CalculateCommonVoteMask(maxEnchantingSkill); // dependent from item and possible skill
SendLootStartRoll(LOOT_ROLL_TIMEOUT, lootTarget->GetMapId(), *r); SendLootStartRoll(LOOT_ROLL_TIMEOUT, lootTarget->GetMapId(), *r);
loot->items[itemSlot].is_blocked = true; loot->items[itemSlot].is_blocked = true;
lootTarget->StartGroupLoot(this,LOOT_ROLL_TIMEOUT);
lootTarget->StartGroupLoot(this, LOOT_ROLL_TIMEOUT);
} }
RollId.push_back(r); RollId.push_back(r);
@ -1488,7 +1492,7 @@ uint32 Group::GetMaxSkillValueForGroup( SkillType skill )
return maxvalue; return maxvalue;
} }
void Group::UpdateLooterGuid( Creature* creature, bool ifneed ) void Group::UpdateLooterGuid(WorldObject* pSource, bool ifneed)
{ {
switch (GetLootMethod()) switch (GetLootMethod())
{ {
@ -1508,7 +1512,7 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed )
{ {
// not update if only update if need and ok // not update if only update if need and ok
Player* looter = ObjectAccessor::FindPlayer(guid_itr->guid); Player* looter = ObjectAccessor::FindPlayer(guid_itr->guid);
if (looter && looter->IsWithinDist(creature, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false)) if (looter && looter->IsWithinDist(pSource, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false))
return; return;
} }
++guid_itr; ++guid_itr;
@ -1521,16 +1525,16 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed )
{ {
if (Player* pl = ObjectAccessor::FindPlayer(itr->guid)) if (Player* pl = ObjectAccessor::FindPlayer(itr->guid))
{ {
if (pl->IsWithinDist(creature, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false)) if (pl->IsWithinDist(pSource, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false))
{ {
bool refresh = pl->GetLootGuid() == creature->GetObjectGuid(); bool refresh = pl->GetLootGuid() == pSource->GetObjectGuid();
//if(refresh) // update loot for new looter //if(refresh) // update loot for new looter
// pl->GetSession()->DoLootRelease(pl->GetLootGUID()); // pl->GetSession()->DoLootRelease(pl->GetLootGUID());
SetLooterGuid(pl->GetObjectGuid()); SetLooterGuid(pl->GetObjectGuid());
SendUpdate(); SendUpdate();
if (refresh) // update loot for new looter if (refresh) // update loot for new looter
pl->SendLoot(creature->GetObjectGuid(), LOOT_CORPSE); pl->SendLoot(pSource->GetObjectGuid(), LOOT_CORPSE);
return; return;
} }
} }
@ -1542,16 +1546,16 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed )
{ {
if (Player* pl = ObjectAccessor::FindPlayer(itr->guid)) if (Player* pl = ObjectAccessor::FindPlayer(itr->guid))
{ {
if (pl->IsWithinDist(creature, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false)) if (pl->IsWithinDist(pSource, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false))
{ {
bool refresh = pl->GetLootGuid() == creature->GetObjectGuid(); bool refresh = pl->GetLootGuid() == pSource->GetObjectGuid();
//if(refresh) // update loot for new looter //if(refresh) // update loot for new looter
// pl->GetSession()->DoLootRelease(pl->GetLootGUID()); // pl->GetSession()->DoLootRelease(pl->GetLootGUID());
SetLooterGuid(pl->GetObjectGuid()); SetLooterGuid(pl->GetObjectGuid());
SendUpdate(); SendUpdate();
if (refresh) // update loot for new looter if (refresh) // update loot for new looter
pl->SendLoot(creature->GetObjectGuid(), LOOT_CORPSE); pl->SendLoot(pSource->GetObjectGuid(), LOOT_CORPSE);
return; return;
} }
} }

View file

@ -223,7 +223,7 @@ class MANGOS_DLL_SPEC Group
void ChangeLeader(ObjectGuid guid); void ChangeLeader(ObjectGuid guid);
void SetLootMethod(LootMethod method) { m_lootMethod = method; } void SetLootMethod(LootMethod method) { m_lootMethod = method; }
void SetLooterGuid(ObjectGuid guid) { m_looterGuid = guid; } void SetLooterGuid(ObjectGuid guid) { m_looterGuid = guid; }
void UpdateLooterGuid( Creature* creature, bool ifneed = false ); void UpdateLooterGuid(WorldObject* pSource, bool ifneed = false);
void SetLootThreshold(ItemQualities threshold) { m_lootThreshold = threshold; } void SetLootThreshold(ItemQualities threshold) { m_lootThreshold = threshold; }
void Disband(bool hideDestroy=false); void Disband(bool hideDestroy=false);
@ -347,11 +347,11 @@ class MANGOS_DLL_SPEC Group
void SendLootRoll(ObjectGuid const& targetGuid, uint8 rollNumber, uint8 rollType, const Roll &r); void SendLootRoll(ObjectGuid const& targetGuid, uint8 rollNumber, uint8 rollType, const Roll &r);
void SendLootRollWon(ObjectGuid const& targetGuid, uint8 rollNumber, RollVote rollType, const Roll &r); void SendLootRollWon(ObjectGuid const& targetGuid, uint8 rollNumber, RollVote rollType, const Roll &r);
void SendLootAllPassed(const Roll &r); void SendLootAllPassed(const Roll &r);
void GroupLoot(Creature *creature, Loot *loot); void GroupLoot(WorldObject* pSource, Loot* loot);
void NeedBeforeGreed(Creature *creature, Loot *loot); void NeedBeforeGreed(WorldObject* pSource, Loot* loot);
void MasterLoot(Creature *creature, Loot *loot); void MasterLoot(WorldObject* pSource, Loot* loot);
bool CountRollVote(Player* player, ObjectGuid const& lootedTarget, uint32 itemSlot, RollVote vote); bool CountRollVote(Player* player, ObjectGuid const& lootedTarget, uint32 itemSlot, RollVote vote);
void StartLootRool(Creature* lootTarget, LootMethod method, Loot* loot, uint8 itemSlot, uint32 maxEnchantingSkill); void StartLootRool(WorldObject* lootTarget, LootMethod method, Loot* loot, uint8 itemSlot, uint32 maxEnchantingSkill);
void EndRoll(); void EndRoll();
void LinkMember(GroupReference *pRef) { m_memberMgr.insertFirst(pRef); } void LinkMember(GroupReference *pRef) { m_memberMgr.insertFirst(pRef); }

View file

@ -66,6 +66,7 @@ class WorldSession;
class Creature; class Creature;
class Player; class Player;
class Unit; class Unit;
class Group;
class Map; class Map;
class UpdateMask; class UpdateMask;
class InstanceData; class InstanceData;
@ -356,6 +357,7 @@ class MANGOS_DLL_SPEC Object
virtual bool HasQuest(uint32 /* quest_id */) const { return false; } virtual bool HasQuest(uint32 /* quest_id */) const { return false; }
virtual bool HasInvolvedQuest(uint32 /* quest_id */) const { return false; } virtual bool HasInvolvedQuest(uint32 /* quest_id */) const { return false; }
protected: protected:
Object ( ); Object ( );
@ -586,6 +588,9 @@ class MANGOS_DLL_SPEC WorldObject : public Object
// ASSERT print helper // ASSERT print helper
bool PrintCoordinatesError(float x, float y, float z, char const* descr) const; bool PrintCoordinatesError(float x, float y, float z, char const* descr) const;
virtual void StartGroupLoot(Group* group, uint32 timer) {}
protected: protected:
explicit WorldObject(); explicit WorldObject();
@ -595,6 +600,8 @@ class MANGOS_DLL_SPEC WorldObject : public Object
void SetLocationMapId(uint32 _mapId) { m_mapId = _mapId; } void SetLocationMapId(uint32 _mapId) { m_mapId = _mapId; }
void SetLocationInstanceId(uint32 _instanceId) { m_InstanceId = _instanceId; } void SetLocationInstanceId(uint32 _instanceId) { m_InstanceId = _instanceId; }
virtual void StopGroupLoot() {}
std::string m_name; std::string m_name;
private: private:

View file

@ -7976,7 +7976,7 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
if (ObjectGuid lootGuid = GetLootGuid()) if (ObjectGuid lootGuid = GetLootGuid())
m_session->DoLootRelease(lootGuid); m_session->DoLootRelease(lootGuid);
Loot *loot = 0; Loot* loot = NULL;
PermissionTypes permission = ALL_PERMISSION; PermissionTypes permission = ALL_PERMISSION;
DEBUG_LOG("Player::SendLoot"); DEBUG_LOG("Player::SendLoot");
@ -7997,6 +7997,13 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
loot = &go->loot; loot = &go->loot;
Player* recipient = go->GetLootRecipient();
if (!recipient)
{
go->SetLootRecipient(this);
recipient = this;
}
// generate loot only if ready for open and spawned in world // generate loot only if ready for open and spawned in world
if (go->getLootState() == GO_READY && go->isSpawned()) if (go->getLootState() == GO_READY && go->isSpawned())
{ {
@ -8020,12 +8027,65 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
loot->clear(); loot->clear();
loot->FillLoot(lootid, LootTemplates_Gameobject, this, false); loot->FillLoot(lootid, LootTemplates_Gameobject, this, false);
loot->generateMoneyLoot(go->GetGOInfo()->MinMoneyLoot, go->GetGOInfo()->MaxMoneyLoot); loot->generateMoneyLoot(go->GetGOInfo()->MinMoneyLoot, go->GetGOInfo()->MaxMoneyLoot);
if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST && go->GetGOInfo()->chest.groupLootRules)
{
if (Group* group = go->GetGroupLootRecipient())
{
group->UpdateLooterGuid(go, true);
switch (group->GetLootMethod())
{
case GROUP_LOOT:
// GroupLoot delete items over threshold (threshold even not implemented), and roll them. Items with quality<threshold, round robin
group->GroupLoot(go, loot);
permission = GROUP_PERMISSION;
break;
case NEED_BEFORE_GREED:
group->NeedBeforeGreed(go, loot);
permission = GROUP_PERMISSION;
break;
case MASTER_LOOT:
group->MasterLoot(go, loot);
permission = MASTER_PERMISSION;
break;
default:
break;
}
}
}
} }
else if (loot_type == LOOT_FISHING) else if (loot_type == LOOT_FISHING)
go->getFishLoot(loot,this); go->getFishLoot(loot,this);
go->SetLootState(GO_ACTIVATED); go->SetLootState(GO_ACTIVATED);
} }
if (go->getLootState() == GO_ACTIVATED && go->GetGoType() == GAMEOBJECT_TYPE_CHEST && go->GetGOInfo()->chest.groupLootRules)
{
if (Group* group = go->GetGroupLootRecipient())
{
if (group == GetGroup())
{
if (group->GetLootMethod() == FREE_FOR_ALL)
permission = ALL_PERMISSION;
else if (group->GetLooterGuid() == GetObjectGuid())
{
if (group->GetLootMethod() == MASTER_LOOT)
permission = MASTER_PERMISSION;
else
permission = ALL_PERMISSION;
}
else
permission = GROUP_PERMISSION;
}
else
permission = NONE_PERMISSION;
}
else if (recipient == this)
permission = ALL_PERMISSION;
else
permission = NONE_PERMISSION;
}
break; break;
} }
case HIGHGUID_ITEM: case HIGHGUID_ITEM:

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "11877" #define REVISION_NR "11878"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__