diff --git a/BindingMap.h b/BindingMap.h index 94c4e72..7ad9218 100644 --- a/BindingMap.h +++ b/BindingMap.h @@ -31,16 +31,16 @@ private: struct Binding { uint64 id; - int functionReference; - uint32 remainingShots; lua_State* L; + uint32 remainingShots; + int functionReference; Binding(lua_State* L, uint64 id, int functionReference, uint32 remainingShots) : - L(L), id(id), - functionReference(functionReference), - remainingShots(remainingShots) - {} + L(L), + remainingShots(remainingShots), + functionReference(functionReference) + { } ~Binding() { diff --git a/CMakeLists.txt b/CMakeLists.txt index 460216a..586dbda 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,7 +138,6 @@ if( ${CMAKE_PROJECT_NAME} STREQUAL "TrinityCore" ) ${CMAKE_SOURCE_DIR}/src/server/game/Weather ${CMAKE_SOURCE_DIR}/src/server/game/World ${CMAKE_SOURCE_DIR}/src/server/scripts/PrecompiledHeaders - ${Boost_LIBRARIES} ) find_package(Boost COMPONENTS system filesystem REQUIRED) diff --git a/ElunaIncludes.h b/ElunaIncludes.h index 09f8da1..16ad3d1 100644 --- a/ElunaIncludes.h +++ b/ElunaIncludes.h @@ -40,6 +40,7 @@ #ifdef TRINITY #include "Config.h" +#include "GroupMgr.h" #include "ScriptedCreature.h" #include "SpellInfo.h" #include "WeatherMgr.h" diff --git a/GroupMethods.h b/GroupMethods.h index 28edb77..98e3acb 100644 --- a/GroupMethods.h +++ b/GroupMethods.h @@ -10,7 +10,7 @@ namespace LuaGroup { /** - * Returns 'true' if the player is the [Group] leader + * Returns 'true' if the [Player] is the [Group] leader * * @param uint64 guid : guid of a possible leader * @return bool isLeader @@ -58,27 +58,26 @@ namespace LuaGroup /** * Returns 'true' if the [Player] is a member of this [Group] * - * @param [Player] player : [Player] to check + * @param uint64 guid : guid of a player * @return bool isMember */ int IsMember(Eluna* /*E*/, lua_State* L, Group* group) { - Player* player = Eluna::CHECKOBJ(L, 2); - Eluna::Push(L, group->IsMember(player->GET_GUID())); + uint64 guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->IsMember(ObjectGuid(guid))); return 1; } /** * Returns 'true' if the [Player] is an assistant of this [Group] * - * @param [Player] player : [Player] to check + * @param uint64 guid : guid of a player * @return bool isAssistant */ int IsAssistant(Eluna* /*E*/, lua_State* L, Group* group) { - Player* player = Eluna::CHECKOBJ(L, 2); - - Eluna::Push(L, group->IsAssistant(player->GET_GUID())); + uint64 guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->IsAssistant(ObjectGuid(guid))); return 1; } @@ -106,21 +105,45 @@ namespace LuaGroup int HasFreeSlotSubGroup(Eluna* /*E*/, lua_State* L, Group* group) { uint8 subGroup = Eluna::CHECKVAL(L, 2); + + if (subGroup >= MAX_RAID_SUBGROUPS) + { + luaL_argerror(L, 2, "valid subGroup ID expected"); + return 0; + } + Eluna::Push(L, group->HasFreeSlotSubGroup(subGroup)); return 1; } /** - * Returns 'true' if the [Group] invite was successful + * Adds a new member to the [Group] * - * @param [Player] player : [Player] to invite - * @return bool invited + * @param [Player] player : [Player] to add to the group + * @return bool added : true if member was added */ - int AddInvite(Eluna* /*E*/, lua_State* L, Group* group) + int AddMember(Eluna* /*E*/, lua_State* L, Group* group) { Player* player = Eluna::CHECKOBJ(L, 2); - Eluna::Push(L, group->AddInvite(player)); + if (player->GetGroup() || !group->IsCreated() || group->IsFull()) + { + Eluna::Push(L, false); + return 1; + } + + if (Group* invitedgroup = player->GetGroupInvite()) + player->UninviteFromGroup(); + +#ifdef TRINITY + bool success = group->AddMember(player); + if (success) + group->BroadcastGroupUpdate(); +#else + bool success = group->AddMember(player->GetObjectGuid(), player->GetName()); +#endif + + Eluna::Push(L, success); return 1; } @@ -183,21 +206,6 @@ namespace LuaGroup return 1; } - /** - * Finds and returns a [Group] leader by their GUID if logged in - * - * @return [Player] leader - */ - int GetLeader(Eluna* /*E*/, lua_State* L, Group* group) - { -#ifndef TRINITY - Eluna::Push(L, eObjectAccessor->FindPlayer(group->GetLeaderGuid())); -#else - Eluna::Push(L, eObjectAccessor->FindPlayer(group->GetLeaderGUID())); -#endif - return 1; - } - /** * Returns the [Group]'s GUID * @@ -244,27 +252,26 @@ namespace LuaGroup /** * Returns the [Player]'s subgroup ID of this [Group] * - * @param [Player] player : the [Player] to check - * @return uint8 subGroupID + * @param uint64 guid : guid of the player + * @return uint8 subGroupID : a valid subgroup ID or MAX_RAID_SUBGROUPS+1 */ int GetMemberGroup(Eluna* /*E*/, lua_State* L, Group* group) { - Player* player = Eluna::CHECKOBJ(L, 2); - - Eluna::Push(L, group->GetMemberGroup(player->GET_GUID())); + uint64 guid = Eluna::CHECKVAL(L, 2); + Eluna::Push(L, group->GetMemberGroup(ObjectGuid(guid))); return 1; } /** * Sets the leader of this [Group] * - * @param [Player] leader : the [Player] leader to change + * @param uint64 guid : guid of the new leader */ int SetLeader(Eluna* /*E*/, lua_State* L, Group* group) { - Player* leader = Eluna::CHECKOBJ(L, 2); - - group->ChangeLeader(leader->GET_GUID()); + uint64 guid = Eluna::CHECKVAL(L, 2); + group->ChangeLeader(ObjectGuid(guid)); + group->SendUpdate(); return 0; } @@ -286,7 +293,7 @@ namespace LuaGroup } /** - * Removes a member from this [Group] and returns 'true' if successful + * Removes a [Player] from this [Group] and returns 'true' if successful * *
      * enum RemoveMethod
@@ -298,19 +305,19 @@ namespace LuaGroup
      * };
      * 
* - * @param [Player] player : the [Player] to remove + * @param uint64 guid : guid of the player to remove * @param [RemoveMethod] method : method used to remove the player * @return bool removed */ int RemoveMember(Eluna* /*E*/, lua_State* L, Group* group) { - Player* player = Eluna::CHECKOBJ(L, 2); + uint64 guid = Eluna::CHECKVAL(L, 2); uint32 method = Eluna::CHECKVAL(L, 3, 0); #ifndef TRINITY - Eluna::Push(L, group->RemoveMember(player->GET_GUID(), method)); + Eluna::Push(L, group->RemoveMember(ObjectGuid(guid), method)); #else - Eluna::Push(L, group->RemoveMember(player->GET_GUID(), (RemoveMethod)method)); + Eluna::Push(L, group->RemoveMember(ObjectGuid(guid), (RemoveMethod)method)); #endif return 1; } @@ -338,15 +345,24 @@ namespace LuaGroup /** * Sets the member's subGroup * - * @param [Player] player : [Player] to move + * @param uint64 guid : guid of the player to move * @param uint8 groupID : the subGroup's ID */ int SetMembersGroup(Eluna* /*E*/, lua_State* L, Group* group) { - Player* player = Eluna::CHECKOBJ(L, 2); - uint8 groupID = Eluna::CHECKVAL(L, 3); + uint64 guid = Eluna::CHECKVAL(L, 2); + uint8 subGroup = Eluna::CHECKVAL(L, 3); - group->ChangeMembersGroup(player->GET_GUID(), groupID); + if (subGroup >= MAX_RAID_SUBGROUPS) + { + luaL_argerror(L, 3, "valid subGroup ID expected"); + return 0; + } + + if (!group->HasFreeSlotSubGroup(subGroup)) + return 0; + + group->ChangeMembersGroup(ObjectGuid(guid), subGroup); return 0; } diff --git a/LuaFunctions.cpp b/LuaFunctions.cpp index 303bba4..e5f38c4 100644 --- a/LuaFunctions.cpp +++ b/LuaFunctions.cpp @@ -736,6 +736,8 @@ ElunaRegister PlayerMethods[] = { "Mute", &LuaPlayer::Mute }, // :Mute(time[, reason]) - Mutes the player for given time in seconds. { "SummonPlayer", &LuaPlayer::SummonPlayer }, // :SummonPlayer(player, map, x, y, z, zoneId[, delay]) - Sends a popup to the player asking if he wants to be summoned if yes, teleported to coords. ZoneID defines the location name shown in the popup Delay is the time until the popup closes automatically. { "SaveToDB", &LuaPlayer::SaveToDB }, // :SaveToDB() - Saves to database + { "GroupInvite", &LuaPlayer::GroupInvite }, + { "GroupCreate", &LuaPlayer::GroupCreate }, #ifdef CLASSIC { "UpdateHonor", &LuaPlayer::UpdateHonor }, // :UpdateHonor() - Updates Player Honor { "ResetHonor", &LuaPlayer::ResetHonor }, // :ResetHonor() - Resets Player Honor @@ -1031,7 +1033,6 @@ ElunaRegister GroupMethods[] = // Getters { "GetMembers", &LuaGroup::GetMembers }, { "GetLeaderGUID", &LuaGroup::GetLeaderGUID }, - { "GetLeader", &LuaGroup::GetLeader }, { "GetGUID", &LuaGroup::GetGUID }, { "GetMemberGroup", &LuaGroup::GetMemberGroup }, { "GetMemberGUID", &LuaGroup::GetMemberGUID }, @@ -1044,7 +1045,7 @@ ElunaRegister GroupMethods[] = // Boolean { "IsLeader", &LuaGroup::IsLeader }, - { "AddInvite", &LuaGroup::AddInvite }, + { "AddMember", &LuaGroup::AddMember }, { "RemoveMember", &LuaGroup::RemoveMember }, { "Disband", &LuaGroup::Disband }, { "IsFull", &LuaGroup::IsFull }, diff --git a/PlayerMethods.h b/PlayerMethods.h index 9344c5d..e9e0148 100644 --- a/PlayerMethods.h +++ b/PlayerMethods.h @@ -2266,7 +2266,7 @@ namespace LuaPlayer /** * Unbinds the [Player] from his instances except the one he currently is in. */ - int UnbindAllInstances(Eluna* /*E*/, lua_State* L, Player* player) + int UnbindAllInstances(Eluna* /*E*/, lua_State* /*L*/, Player* player) { #ifdef CLASSIC Player::BoundInstancesMap& binds = player->GetBoundInstances(); @@ -3137,11 +3137,11 @@ namespace LuaPlayer bool update = Eluna::CHECKVAL(L, 3, true); #ifdef TRINITY - player->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool + player->GetSpellHistory()->ResetCooldowns([category](SpellHistory::CooldownStorageType::iterator itr) -> bool { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); - return spellInfo && spellInfo->GetCategory() == 1248; - }, true); + return spellInfo && spellInfo->GetCategory() == category; + }, update); #else player->RemoveSpellCategoryCooldown(category, update); #endif @@ -3509,6 +3509,114 @@ namespace LuaPlayer return 0; } + /** + * Makes the [Player] invite another player to a group. + * + * @param [Player] invited : player to invite to group + * @return bool success : true if the player was invited to a group + */ + int GroupInvite(Eluna* /*E*/, lua_State* L, Player* player) + { + Player* invited = Eluna::CHECKOBJ(L, 2); + + if (invited->GetGroup() || invited->GetGroupInvite()) + { + Eluna::Push(L, false); + return 1; + } + + // Get correct existing group if any + Group* group = player->GetGroup(); + if (group && group->isBGGroup()) + group = player->GetOriginalGroup(); + + bool success = false; + + // Try invite if group found + if (group) + success = !group->IsFull() && group->AddInvite(invited); + else + { + // Create new group if one not found + group = new Group; + success = group->AddLeaderInvite(player) && group->AddInvite(invited); + if (!success) + delete group; + } + + if (success) + { +#if defined(CLASSIC) || defined(TBC) + WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size + data << player->GetName(); + invited->GetSession()->SendPacket(&data); +#else + WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size + data << uint8(1); // invited/already in group flag + data << player->GetName(); // max len 48 + data << uint32(0); // unk + data << uint8(0); // count + data << uint32(0); // unk + invited->GetSession()->SendPacket(&data); +#endif + } + + Eluna::Push(L, success); + return 1; + } + + /** + * Creates a new [Group] with the creator [Player] as leader. + * + * @param [Player] invited : player to add to group + * @return [Group] createdGroup : the created group or nil + */ + int GroupCreate(Eluna* /*E*/, lua_State* L, Player* player) + { + Player* invited = Eluna::CHECKOBJ(L, 2); + + if (player->GetGroup() || invited->GetGroup()) + return 0; + + if (Group* invitedgroup = player->GetGroupInvite()) + player->UninviteFromGroup(); + if (Group* invitedgroup = invited->GetGroupInvite()) + invited->UninviteFromGroup(); + + // Try create new group + Group* group = new Group; + if (!group->AddLeaderInvite(player)) + { + delete group; + return 0; + } + + // Forming a new group, create it + if (!group->IsCreated()) + { + group->RemoveInvite(player); +#ifdef TRINITY + group->Create(player); + sGroupMgr->AddGroup(group); +#else + if (!group->Create(group->GetLeaderGuid(), group->GetLeaderName())) + return 0; + sObjectMgr.AddGroup(group); +#endif + } + +#ifdef TRINITY + if (!group->AddMember(invited)) + return 0; + group->BroadcastGroupUpdate(); +#else + if (!group->AddMember(invited->GetObjectGuid(), invited->GetName())) + return 0; +#endif + Eluna::Push(L, group); + return 1; + } + /*int BindToInstance(Eluna* E, lua_State* L, Player* player) { player->BindToInstance(); diff --git a/UnitMethods.h b/UnitMethods.h index 5f59326..ab2195c 100644 --- a/UnitMethods.h +++ b/UnitMethods.h @@ -1755,7 +1755,7 @@ namespace LuaUnit * * @param bool apply = true */ - int SetRooted(Eluna* E, lua_State* L, Unit* unit) + int SetRooted(Eluna* /*E*/, lua_State* L, Unit* unit) { bool apply = Eluna::CHECKVAL(L, 2, true); #ifndef TRINITY @@ -1771,7 +1771,7 @@ namespace LuaUnit * * @param bool apply = true */ - int SetConfused(Eluna* E, lua_State* L, Unit* unit) + int SetConfused(Eluna* /*E*/, lua_State* L, Unit* unit) { bool apply = Eluna::CHECKVAL(L, 2, true); #ifndef TRINITY @@ -1787,7 +1787,7 @@ namespace LuaUnit * * @param bool apply = true */ - int SetFeared(Eluna* E, lua_State* L, Unit* unit) + int SetFeared(Eluna* /*E*/, lua_State* L, Unit* unit) { bool apply = Eluna::CHECKVAL(L, 2, true); #ifndef TRINITY