1
0

Added CreateChoiceWindow, ClearChoice and GetChoiceSpawnID lua functions, added base of tracking for min, max, avg, first level for raid/group into instances... more work to complete tomorrow

This commit is contained in:
Emagi 2024-12-04 21:53:57 -05:00
parent 48b2b1cc4d
commit c17b4d5588
19 changed files with 613 additions and 174 deletions

View File

@ -5595,7 +5595,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
case COMMAND_SET_GUILD_MEMBER_NOTE : { Command_SetGuildMemberNote(client, sep); break; } case COMMAND_SET_GUILD_MEMBER_NOTE : { Command_SetGuildMemberNote(client, sep); break; }
case COMMAND_SET_GUILD_OFFICER_NOTE : { Command_SetGuildOfficerNote(client, sep); break; } case COMMAND_SET_GUILD_OFFICER_NOTE : { Command_SetGuildOfficerNote(client, sep); break; }
case COMMAND_GUILD : { Command_Guild(client, sep); break; } case COMMAND_GUILD : { Command_Guild(client, sep); break; }
case COMMAND_CREATE_GUILD : { Command_CreateGuild(client); break; } case COMMAND_CREATE_GUILD : { Command_CreateGuild(client, sep); break; }
case COMMAND_GUILDS : { Command_Guilds(client); break; } case COMMAND_GUILDS : { Command_Guilds(client); break; }
case COMMAND_GUILDS_ADD : { Command_GuildsAdd(client, sep); break; } case COMMAND_GUILDS_ADD : { Command_GuildsAdd(client, sep); break; }
case COMMAND_GUILDS_CREATE : { Command_GuildsCreate(client, sep); break; } case COMMAND_GUILDS_CREATE : { Command_GuildsCreate(client, sep); break; }
@ -6541,9 +6541,9 @@ void Commands::Command_Guild(Client* client, Seperator* sep)
Purpose : Display's in-game Guild Creation window Purpose : Display's in-game Guild Creation window
Dev : Scatman Dev : Scatman
*/ */
void Commands::Command_CreateGuild(Client* client) void Commands::Command_CreateGuild(Client* client, Seperator* sep)
{ {
client->SendGuildCreateWindow(); Command_GuildsCreate(client, sep, true);
} }
/* /*
@ -6692,11 +6692,33 @@ void Commands::Command_GuildsAdd(Client* client, Seperator* sep)
Dev : Scatman Dev : Scatman
Example : /guilds create [guild name] (player name) Example : /guilds create [guild name] (player name)
*/ */
void Commands::Command_GuildsCreate(Client* client, Seperator* sep) void Commands::Command_GuildsCreate(Client* client, Seperator* sep, bool prompted_dialog)
{ {
Spawn* npc = nullptr;
if(prompted_dialog) {
auto target_npc = client->dialog_manager.getAcceptValue("create guild");
if(!target_npc) {
// well this is not acceptable!! CHEATER! :D
return;
}
else {
if(!client->GetPlayer()->GetZone()){
// player isn't in a zone? eh..
return;
}
npc = client->GetPlayer()->GetZone()->GetSpawnByID(target_npc);
if(!npc) {
client->Message(CHANNEL_COLOR_RED, "Did not find guild registrar, please re-initiate dialog with them.");
return;
}
}
}
if (sep && sep->arg[0]) if (sep && sep->arg[0])
{ {
const char* guild_name = sep->arg[0]; const char* guild_name = sep->arg[0];
if(prompted_dialog)
guild_name = sep->argplus[0];
int8 resp = database.CheckNameFilter(guild_name, 4, 41); int8 resp = database.CheckNameFilter(guild_name, 4, 41);
if(!guild_name || resp == BADNAMELENGTH_REPLY) { if(!guild_name || resp == BADNAMELENGTH_REPLY) {
client->Message(CHANNEL_COLOR_YELLOW, "Guild name is too short."); client->Message(CHANNEL_COLOR_YELLOW, "Guild name is too short.");
@ -6708,7 +6730,7 @@ void Commands::Command_GuildsCreate(Client* client, Seperator* sep)
{ {
bool ret = false; bool ret = false;
if (sep->arg[1] && strlen(sep->arg[1]) > 0 && client->GetAdminStatus() > 0) if (!prompted_dialog && sep->arg[1] && strlen(sep->arg[1]) > 0 && client->GetAdminStatus() > 0)
{ {
Client* to_client = zone_list.GetClientByCharName(string(sep->arg[1])); Client* to_client = zone_list.GetClientByCharName(string(sep->arg[1]));
@ -6728,7 +6750,7 @@ void Commands::Command_GuildsCreate(Client* client, Seperator* sep)
client->Message(CHANNEL_COLOR_YELLOW, "Could not find target %s or target is already in a guild.", sep->arg[1]); client->Message(CHANNEL_COLOR_YELLOW, "Could not find target %s or target is already in a guild.", sep->arg[1]);
} }
} }
else if (client->GetAdminStatus() > 0 && client->GetPlayer()->GetTarget() && client->GetPlayer()->GetTarget()->IsPlayer()) else if (!prompted_dialog && client->GetAdminStatus() > 0 && client->GetPlayer()->GetTarget() && client->GetPlayer()->GetTarget()->IsPlayer())
{ {
Client* to_client = ((Player*)client->GetPlayer()->GetTarget())->GetClient(); Client* to_client = ((Player*)client->GetPlayer()->GetTarget())->GetClient();
@ -6752,27 +6774,38 @@ void Commands::Command_GuildsCreate(Client* client, Seperator* sep)
{ {
if(client->GetPlayer()->GetGuild()) { if(client->GetPlayer()->GetGuild()) {
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "You are already in a guild."); client->SimpleMessage(CHANNEL_COLOR_YELLOW, "You are already in a guild.");
if(client->GetAdminStatus() < 1)
return;
} }
else if(net.is_primary) { else if(net.is_primary) {
int32 guildID = world.CreateGuild(guild_name); Client* leader = nullptr;
if(guildID > 0) if(prompted_dialog || client->GetAdminStatus() < 1)
leader = client;
int32 guildID = world.CreateGuild(guild_name, leader);
if(guildID > 0) {
peer_manager.sendPeersCreateGuild(guildID); peer_manager.sendPeersCreateGuild(guildID);
}
else {
peer_manager.sendPrimaryCreateGuildRequest(std::string(guild_name), "");
}
ret = true; ret = true;
} }
}
else {
peer_manager.sendPrimaryCreateGuildRequest(std::string(guild_name), "", prompted_dialog, npc->GetID());
return;
}
}
if (ret) if (ret) {
client->Message(CHANNEL_COLOR_YELLOW, "Guild '%s' was successfully created.", guild_name); client->Message(CHANNEL_COLOR_YELLOW, "Guild '%s' was successfully created.", guild_name);
if(prompted_dialog) { // prompted dialog requires npc be defined
client->GetCurrentZone()->CallSpawnScript(npc, SPAWN_SCRIPT_CASTED_ON, client->GetPlayer(), guild_name);
}
}
else else
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "There was an error creating the guild."); client->SimpleMessage(CHANNEL_COLOR_YELLOW, "There was an error creating the guild.");
} }
else else
client->Message(CHANNEL_COLOR_YELLOW, "Guild '%s' already exists.", guild_name); client->Message(CHANNEL_COLOR_YELLOW, "Guild '%s' already exists.", guild_name);
} }
else else if(!prompted_dialog)
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Usage: /guilds create [guild name] (player name). If no player is specified, the player's target will be used. If the player has no target, a guild with no members will be created."); client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Usage: /guilds create [guild name] (player name). If no player is specified, the player's target will be used. If the player has no target, a guild with no members will be created.");
} }

View File

@ -311,14 +311,14 @@ public:
void Command_StopFollow(Client* client, Seperator* sep); void Command_StopFollow(Client* client, Seperator* sep);
void Command_Grid(Client* client, Seperator* sep); void Command_Grid(Client* client, Seperator* sep);
void Command_Guild(Client* client, Seperator* sep); void Command_Guild(Client* client, Seperator* sep);
void Command_CreateGuild(Client* client); void Command_CreateGuild(Client* client, Seperator* sep);
void Command_SetGuildOfficerNote(Client* client, Seperator* sep); void Command_SetGuildOfficerNote(Client* client, Seperator* sep);
void Command_SetGuildMemberNote(Client* client, Seperator* sep); void Command_SetGuildMemberNote(Client* client, Seperator* sep);
void Command_OfficerSay(Client* client, Seperator* sep); void Command_OfficerSay(Client* client, Seperator* sep);
void Command_GuildSay(Client* client, Seperator* sep); void Command_GuildSay(Client* client, Seperator* sep);
void Command_Guilds(Client* client); void Command_Guilds(Client* client);
void Command_GuildsAdd(Client* client, Seperator* sep); void Command_GuildsAdd(Client* client, Seperator* sep);
void Command_GuildsCreate(Client* client, Seperator* sep); void Command_GuildsCreate(Client* client, Seperator* sep, bool prompted_dialog = false);
void Command_GuildsDelete(Client* client, Seperator* sep); void Command_GuildsDelete(Client* client, Seperator* sep);
void Command_GuildsList(Client* client); void Command_GuildsList(Client* client);
void Command_GuildsRemove(Client* client, Seperator* sep); void Command_GuildsRemove(Client* client, Seperator* sep);

View File

@ -14313,3 +14313,104 @@ int EQ2Emu_lua_CreatePersistedRespawn(lua_State* state) {
return 1; return 1;
} }
int EQ2Emu_lua_CreateChoiceWindow(lua_State* state) {
if (!lua_interface)
return 0;
Spawn* npc = lua_interface->GetSpawn(state);
Spawn* spawn = lua_interface->GetSpawn(state, 2);
std::string windowTextPrompt = lua_interface->GetStringValue(state, 3);
std::string acceptText = lua_interface->GetStringValue(state, 4);
std::string acceptCommand = lua_interface->GetStringValue(state, 5);
std::string declineText = lua_interface->GetStringValue(state, 6);
std::string declineCommand = lua_interface->GetStringValue(state, 7);
int32 time = lua_interface->GetInt32Value(state, 8);
int8 textBox = lua_interface->GetInt8Value(state, 9);
int8 textBoxRequired = lua_interface->GetInt8Value(state, 10);
int32 maxLength = lua_interface->GetInt32Value(state, 11);
lua_interface->ResetFunctionStack(state);
if(!npc || !npc->IsNPC())
{
lua_interface->LogError("%s: LUA CreateChoiceWindow command error: npc is not valid, either does not exist or is not a npc", lua_interface->GetScriptName(state));
lua_interface->SetBooleanValue(state, false);
return 1;
}
if(!spawn || !spawn->IsPlayer())
{
lua_interface->LogError("%s: LUA CreateChoiceWindow command error: spawn is not valid, either does not exist or is not a player", lua_interface->GetScriptName(state));
lua_interface->SetBooleanValue(state, false);
return 1;
}
Client* client = ((Player*)spawn)->GetClient();
if(client) {
bool success = client->SendDialogChoice(npc->GetID(), windowTextPrompt, acceptText, acceptCommand, declineText, declineCommand, time, textBox, textBoxRequired, maxLength);
lua_interface->SetBooleanValue(state, success);
return 1;
}
lua_interface->SetBooleanValue(state, false);
return 1;
}
int EQ2Emu_lua_ClearChoice(lua_State* state) {
if (!lua_interface)
return 0;
Spawn* spawn = lua_interface->GetSpawn(state);
std::string commandToClear = lua_interface->GetStringValue(state, 2);
int8 clearDecline = lua_interface->GetInt8Value(state, 3);
lua_interface->ResetFunctionStack(state);
if(!spawn || !spawn->IsPlayer())
{
lua_interface->LogError("%s: LUA ClearChoice command error: spawn is not valid, either does not exist or is not a player", lua_interface->GetScriptName(state));
lua_interface->SetBooleanValue(state, false);
return 1;
}
Client* client = ((Player*)spawn)->GetClient();
if(client) {
bool success = false;
if(clearDecline) {
success = client->dialog_manager.clearDecline(commandToClear);
}
else {
success = client->dialog_manager.clearAccept(commandToClear);
}
lua_interface->SetBooleanValue(state, success);
return 1;
}
lua_interface->SetBooleanValue(state, false);
return 1;
}
int EQ2Emu_lua_GetChoiceSpawnID(lua_State* state) {
if (!lua_interface)
return 0;
Spawn* spawn = lua_interface->GetSpawn(state);
std::string commandMatch = lua_interface->GetStringValue(state, 2);
int8 declineValue = lua_interface->GetInt8Value(state, 3);
lua_interface->ResetFunctionStack(state);
if(!spawn || !spawn->IsPlayer())
{
lua_interface->LogError("%s: LUA GetChoiceSpawnID command error: spawn is not valid, either does not exist or is not a player", lua_interface->GetScriptName(state));
lua_interface->SetInt32Value(state, 0);
return 1;
}
Client* client = ((Player*)spawn)->GetClient();
int32 spawn_id = 0;
if(client) {
if(declineValue) {
spawn_id = client->dialog_manager.getDeclineValue(commandMatch);
}
else {
spawn_id = client->dialog_manager.getAcceptValue(commandMatch);
}
}
lua_interface->SetInt32Value(state, spawn_id);
return 1;
}

View File

@ -663,4 +663,8 @@ int EQ2Emu_lua_DespawnByLocationID(lua_State* state);
int EQ2Emu_lua_AddRespawn(lua_State* state); int EQ2Emu_lua_AddRespawn(lua_State* state);
int EQ2Emu_lua_CreatePersistedRespawn(lua_State* state); int EQ2Emu_lua_CreatePersistedRespawn(lua_State* state);
int EQ2Emu_lua_CreateChoiceWindow(lua_State* state);
int EQ2Emu_lua_ClearChoice(lua_State* state);
int EQ2Emu_lua_GetChoiceSpawnID(lua_State* state);
#endif #endif

View File

@ -1568,6 +1568,10 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
lua_register(state,"AddRespawn", EQ2Emu_lua_AddRespawn); lua_register(state,"AddRespawn", EQ2Emu_lua_AddRespawn);
lua_register(state,"CreatePersistedRespawn", EQ2Emu_lua_CreatePersistedRespawn); lua_register(state,"CreatePersistedRespawn", EQ2Emu_lua_CreatePersistedRespawn);
lua_register(state,"CreateChoiceWindow", EQ2Emu_lua_CreateChoiceWindow);
lua_register(state,"ClearChoice", EQ2Emu_lua_ClearChoice);
lua_register(state,"GetChoiceSpawnID", EQ2Emu_lua_GetChoiceSpawnID);
} }
void LuaInterface::LogError(const char* error, ...) { void LuaInterface::LogError(const char* error, ...) {

View File

@ -1977,7 +1977,81 @@ void PlayerGroupManager::ClearGroupRaidLooterFlag(int32 groupID) {
} }
} }
void PlayerGroupManager::EstablishRaidLevelRange(Client* client, int32* min_level, int32* max_level, int32* avg_level, int32* first_level) {
std::shared_lock lock(MGroups);
if(!client)
return;
if (!client->GetPlayer()->GetGroupMemberInfo()) {
*min_level = *max_level = *avg_level = *first_level = client->GetPlayer()->GetLevel();
return;
}
int32 groupID = client->GetPlayer()->GetGroupMemberInfo()->group_id;
if (m_groups.count(groupID) < 1) {
*min_level = *max_level = *avg_level = *first_level = client->GetPlayer()->GetLevel();
return;
}
PlayerGroup* group = m_groups[groupID];
if (group) {
bool isInRaid = group->IsInRaidGroup(group->GetID());
std::vector<int32> raidGroups;
group->GetRaidGroups(&raidGroups);
if (!isInRaid && raidGroups.size() < 1) {
raidGroups.push_back(group->GetID());
}
// Initialize tracking variables
int32 local_min_level = INT32_MAX;
int32 local_max_level = INT32_MIN;
int32 total_levels = 0;
int8 level_count = 0;
// Get the first player's level
*first_level = client->GetPlayer()->GetLevel();
for (auto& groupID : raidGroups) {
group = m_groups[groupID];
if (!group)
continue;
group->MGroupMembers.readlock(__FUNCTION__, __LINE__);
deque<GroupMemberInfo*>* members = group->GetMembers();
for (auto& memberInfo : *members) {
Entity* member = memberInfo->member;
if (!member || !member->IsPlayer())
continue;
if (member->GetZone() != client->GetPlayer()->GetZone())
continue;
int32 member_level = member->GetLevel();
local_min_level = std::min(local_min_level, member_level);
local_max_level = std::max(local_max_level, member_level);
total_levels += member_level;
level_count++;
}
group->MGroupMembers.releasereadlock(__FUNCTION__, __LINE__);
}
// Finalize values with divide-by-zero protection
if (level_count > 0) {
*min_level = local_min_level;
*max_level = local_max_level;
*avg_level = total_levels / level_count;
}
else {
*min_level = *max_level = *avg_level = *first_level = client->GetPlayer()->GetLevel();
}
}
else {
*min_level = *max_level = *avg_level = *first_level = client->GetPlayer()->GetLevel();
}
}
Entity* PlayerGroup::GetGroupMemberByPosition(Entity* seeker, int32 mapped_position) { Entity* PlayerGroup::GetGroupMemberByPosition(Entity* seeker, int32 mapped_position) {
Entity* ret = nullptr; Entity* ret = nullptr;

View File

@ -255,6 +255,7 @@ public:
void SplitWithGroupOrRaid(Client* client, int32 coin_plat, int32 coin_gold, int32 coin_silver, int32 coin_copper); void SplitWithGroupOrRaid(Client* client, int32 coin_plat, int32 coin_gold, int32 coin_silver, int32 coin_copper);
bool IdentifyMemberInGroupOrRaid(ZoneChangeDetails* details, Client* client, int32 zoneID, int32 instanceID = 0); bool IdentifyMemberInGroupOrRaid(ZoneChangeDetails* details, Client* client, int32 zoneID, int32 instanceID = 0);
void ClearGroupRaidLooterFlag(int32 groupID); void ClearGroupRaidLooterFlag(int32 groupID);
void EstablishRaidLevelRange(Client* client, int32* min_level, int32* max_level, int32* avg_level, int32* first_level);
private: private:
int32 m_nextGroupID; // Used to generate a new unique id for new groups int32 m_nextGroupID; // Used to generate a new unique id for new groups

View File

@ -295,6 +295,8 @@ void HandleCreateGuild(boost::property_tree::ptree tree) {
bool success = false; bool success = false;
int32 guildID = 0; int32 guildID = 0;
std::string leaderName(""); std::string leaderName("");
bool promptedDialog = false;
int32 spawnID = 0;
if (auto successful = tree.get_optional<bool>("success")) { if (auto successful = tree.get_optional<bool>("success")) {
success = successful.get(); success = successful.get();
} }
@ -307,6 +309,14 @@ void HandleCreateGuild(boost::property_tree::ptree tree) {
leaderName = name.get(); leaderName = name.get();
} }
if (auto prompt = tree.get_optional<bool>("prompted_dialog")) {
promptedDialog = prompt.get();
}
if (auto spawnid = tree.get_optional<int32>("spawn_id")) {
spawnID = spawnid.get();
}
if (net.is_primary) { if (net.is_primary) {
// we send out to peers // we send out to peers
} }
@ -315,6 +325,12 @@ void HandleCreateGuild(boost::property_tree::ptree tree) {
Guild* guild = guild_list.GetGuild(guildID); Guild* guild = guild_list.GetGuild(guildID);
Client* leader = zone_list.GetClientByCharName(leaderName.c_str()); Client* leader = zone_list.GetClientByCharName(leaderName.c_str());
if (leader && guild && !leader->GetPlayer()->GetGuild()) { if (leader && guild && !leader->GetPlayer()->GetGuild()) {
if(spawnID) {
Spawn* npc = leader->GetPlayer()->GetZone()->GetSpawnByID(spawnID);
if(promptedDialog && npc && npc->IsNPC()) {
leader->GetCurrentZone()->CallSpawnScript(npc, SPAWN_SCRIPT_CASTED_ON, leader->GetPlayer(), guild->GetName());
}
}
guild->AddNewGuildMember(leader, 0, GUILD_RANK_LEADER); guild->AddNewGuildMember(leader, 0, GUILD_RANK_LEADER);
database.SaveGuildMembers(guild); database.SaveGuildMembers(guild);
if (leader && leader->GetPlayer()->GetGroupMemberInfo()) { if (leader && leader->GetPlayer()->GetGroupMemberInfo()) {

View File

@ -619,7 +619,7 @@ void PeerManager::sendPeersDisbandGroup(int32 group_id) {
} }
} }
bool PeerManager::sendPrimaryCreateGuildRequest(std::string guild_name, std::string leader_name) { bool PeerManager::sendPrimaryCreateGuildRequest(std::string guild_name, std::string leader_name, bool prompted_dialog, int32 spawnID) {
std::shared_ptr<Peer> primary = getHealthyPrimaryPeerPtr(); std::shared_ptr<Peer> primary = getHealthyPrimaryPeerPtr();
if (primary) { if (primary) {
boost::property_tree::ptree root; boost::property_tree::ptree root;
@ -628,6 +628,8 @@ bool PeerManager::sendPrimaryCreateGuildRequest(std::string guild_name, std::str
root.put("peer_web_port", std::to_string(net.GetWebWorldPort())); root.put("peer_web_port", std::to_string(net.GetWebWorldPort()));
root.put("guild_name", guild_name); root.put("guild_name", guild_name);
root.put("leader_name", leader_name); root.put("leader_name", leader_name);
root.put("prompted_dialog", prompted_dialog);
root.put("spawn_id", spawnID);
std::ostringstream jsonStream; std::ostringstream jsonStream;
boost::property_tree::write_json(jsonStream, root); boost::property_tree::write_json(jsonStream, root);

View File

@ -206,7 +206,7 @@ public:
std::string peerId = "", std::vector<int32>* raidGroups = nullptr, bool is_update = false); std::string peerId = "", std::vector<int32>* raidGroups = nullptr, bool is_update = false);
void sendPeersDisbandGroup(int32 group_id); void sendPeersDisbandGroup(int32 group_id);
bool sendPrimaryCreateGuildRequest(std::string guild_name, std::string leader_name); bool sendPrimaryCreateGuildRequest(std::string guild_name, std::string leader_name, bool prompted_dialog = false, int32 spawnID = 0);
void sendPeersAddGuildMember(int32 character_id, int32 guild_id, std::string invited_by, int32 join_timestamp, int8 rank); void sendPeersAddGuildMember(int32 character_id, int32 guild_id, std::string invited_by, int32 join_timestamp, int8 rank);
void sendPeersRemoveGuildMember(int32 character_id, int32 guild_id, std::string removed_by); void sendPeersRemoveGuildMember(int32 character_id, int32 guild_id, std::string removed_by);
void sendPeersCreateGuild(int32 guild_id); void sendPeersCreateGuild(int32 guild_id);

View File

@ -618,6 +618,7 @@ void World::Web_worldhandle_startzone(const http::request<http::string_body>& re
int32 zoneId = 0; int32 zoneId = 0;
std::string zoneName(""); std::string zoneName("");
bool alwaysLoaded = false; bool alwaysLoaded = false;
int32 minLevel = 0, maxLevel = 0, avgLevel = 0, firstLevel = 0;
if (auto inst_id = json_tree.get_optional<int32>("instance_id")) { if (auto inst_id = json_tree.get_optional<int32>("instance_id")) {
instanceId = inst_id.get(); instanceId = inst_id.get();
} }
@ -634,6 +635,22 @@ void World::Web_worldhandle_startzone(const http::request<http::string_body>& re
alwaysLoaded = always_loaded.get(); alwaysLoaded = always_loaded.get();
} }
if (auto level = json_tree.get_optional<int32>("min_level")) {
minLevel = level.get();
}
if (auto level = json_tree.get_optional<int32>("max_level")) {
maxLevel = level.get();
}
if (auto level = json_tree.get_optional<int32>("avg_level")) {
avgLevel = level.get();
}
if (auto level = json_tree.get_optional<int32>("first_level")) {
firstLevel = level.get();
}
sint32 success = 0; sint32 success = 0;
ZoneChangeDetails details; ZoneChangeDetails details;
if (instanceId || zoneId || zoneName.length() > 0) { if (instanceId || zoneId || zoneName.length() > 0) {
@ -642,7 +659,7 @@ void World::Web_worldhandle_startzone(const http::request<http::string_body>& re
success = 1; success = 1;
} }
else { else {
if ((zone_list.GetZoneByInstance(&details, instanceId, zoneId, true, false, false, false))) if ((zone_list.GetZoneByInstance(&details, instanceId, zoneId, true, false, false, false, minLevel, maxLevel, avgLevel, firstLevel)))
success = 1; success = 1;
} }
} }

View File

@ -684,7 +684,7 @@ void ZoneList::Remove(ZoneServer* zone) {
} }
} }
bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::string opt_zone_name, bool loadZone, bool skip_existing_zones, bool increment_zone, bool check_peers, bool check_instances, bool only_always_loaded, bool skip_self) { bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::string opt_zone_name, bool loadZone, bool skip_existing_zones, bool increment_zone, bool check_peers, bool check_instances, bool only_always_loaded, bool skip_self, int32 minLevel, int32 maxLevel, int32 avgLevel, int32 firstLevel) {
list<ZoneServer*>::iterator zone_iter; list<ZoneServer*>::iterator zone_iter;
ZoneServer* tmp = 0; ZoneServer* tmp = 0;
ZoneServer* ret = 0; ZoneServer* ret = 0;
@ -736,6 +736,11 @@ bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::
root.put("zone_name", opt_zone_name); root.put("zone_name", opt_zone_name);
root.put("zone_id", std::to_string(opt_zone_id)); root.put("zone_id", std::to_string(opt_zone_id));
root.put("always_loaded", only_always_loaded); root.put("always_loaded", only_always_loaded);
root.put("min_level", minLevel);
root.put("max_level", maxLevel);
root.put("avg_level", avgLevel);
root.put("first_level", firstLevel);
std::ostringstream jsonStream; std::ostringstream jsonStream;
boost::property_tree::write_json(jsonStream, root); boost::property_tree::write_json(jsonStream, root);
std::string jsonPayload = jsonStream.str(); std::string jsonPayload = jsonStream.str();
@ -751,7 +756,7 @@ bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::
} }
else { else {
tmp = new ZoneServer(opt_zone_name.c_str()); tmp = new ZoneServer(opt_zone_name.c_str());
database.LoadZoneInfo(tmp); database.LoadZoneInfo(tmp, minLevel, maxLevel, avgLevel, firstLevel);
tmp->Init(); tmp->Init();
tmp->SetAlwaysLoaded(only_always_loaded); tmp->SetAlwaysLoaded(only_always_loaded);
} }
@ -771,7 +776,8 @@ bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::
return (tmp != nullptr) ? true : false; return (tmp != nullptr) ? true : false;
} }
bool ZoneList::GetZoneByInstance(ZoneChangeDetails* zone_details, int32 instance_id, int32 zone_id, bool loadZone, bool skip_existing_zones, bool increment_zone, bool check_peers) { bool ZoneList::GetZoneByInstance(ZoneChangeDetails* zone_details, int32 instance_id, int32 zone_id, bool loadZone, bool skip_existing_zones, bool increment_zone, bool check_peers,
int32 minLevel, int32 maxLevel, int32 avgLevel, int32 firstLevel) {
list<ZoneServer*>::iterator zone_iter; list<ZoneServer*>::iterator zone_iter;
ZoneServer* tmp = 0; ZoneServer* tmp = 0;
ZoneServer* ret = 0; ZoneServer* ret = 0;
@ -814,6 +820,12 @@ bool ZoneList::GetZoneByInstance(ZoneChangeDetails* zone_details, int32 instance
root.put("zone_name", zonename); root.put("zone_name", zonename);
root.put("zone_id", std::to_string(zone_id)); root.put("zone_id", std::to_string(zone_id));
root.put("always_loaded", false); root.put("always_loaded", false);
root.put("min_level", minLevel);
root.put("max_level", maxLevel);
root.put("avg_level", avgLevel);
root.put("first_level", firstLevel);
std::ostringstream jsonStream; std::ostringstream jsonStream;
boost::property_tree::write_json(jsonStream, root); boost::property_tree::write_json(jsonStream, root);
std::string jsonPayload = jsonStream.str(); std::string jsonPayload = jsonStream.str();
@ -834,7 +846,7 @@ bool ZoneList::GetZoneByInstance(ZoneChangeDetails* zone_details, int32 instance
if ( instance_id > 0 ) if ( instance_id > 0 )
tmp->SetupInstance(instance_id); tmp->SetupInstance(instance_id);
database.LoadZoneInfo(tmp); database.LoadZoneInfo(tmp, minLevel, maxLevel, avgLevel, firstLevel);
tmp->Init(); tmp->Init();
} }
} }

View File

@ -419,8 +419,8 @@ class ZoneList {
void Add(ZoneServer* zone); void Add(ZoneServer* zone);
void Remove(ZoneServer* zone); void Remove(ZoneServer* zone);
bool GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::string opt_zone_name = "", bool loadZone = true, bool skip_existing_zones = false, bool increment_zone = true, bool check_peers = true, bool check_instances = false, bool only_always_loaded = false, bool skip_self = false); bool GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::string opt_zone_name = "", bool loadZone = true, bool skip_existing_zones = false, bool increment_zone = true, bool check_peers = true, bool check_instances = false, bool only_always_loaded = false, bool skip_self = false, int32 minLevel = 0, int32 maxLevel = 0, int32 avgLevel = 0, int32 firstLevel = 0);
bool GetZoneByInstance(ZoneChangeDetails* zone_details, int32 instance_id, int32 zone_id = 0, bool loadZone = true, bool skip_existing_zones = false, bool increment_zone = true, bool check_peers = true); bool GetZoneByInstance(ZoneChangeDetails* zone_details, int32 instance_id, int32 zone_id = 0, bool loadZone = true, bool skip_existing_zones = false, bool increment_zone = true, bool check_peers = true, int32 minLevel = 0, int32 maxLevel = 0, int32 avgLevel = 0, int32 firstLevel = 0);
bool IsClientConnectedPeer(int32 account_id); bool IsClientConnectedPeer(int32 account_id);
//ZoneServer* Get(int32 id, bool loadZone = true, bool skip_existing_zones = false, bool increment_zone = true); //ZoneServer* Get(int32 id, bool loadZone = true, bool skip_existing_zones = false, bool increment_zone = true);

View File

@ -2954,9 +2954,11 @@ void WorldDatabase::LoadCharacterFriendsIgnoreList(Player* player) {
} }
} }
void WorldDatabase::LoadZoneInfo(ZoneServer* zone){ void WorldDatabase::LoadZoneInfo(ZoneServer* zone, int32 minLevel, int32 maxLevel, int32 avgLevel, int32 firstLevel){
Query query; Query query;
int32 ruleset_id; int32 ruleset_id;
zone->setGroupRaidLevels(minLevel, maxLevel, avgLevel, firstLevel);
char* escaped = getEscapeString(zone->GetZoneName()); char* escaped = getEscapeString(zone->GetZoneName());
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT id, file, description, underworld, safe_x, safe_y, safe_z, min_status, min_level, max_level, instance_type+0, shutdown_timer, zone_motd, default_reenter_time, default_reset_time, default_lockout_time, force_group_to_zone, safe_heading, xp_modifier, ruleset_id, expansion_id, weather_allowed, sky_file, can_bind, can_gate, city_zone, can_evac FROM zones where name='%s'",escaped); MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT id, file, description, underworld, safe_x, safe_y, safe_z, min_status, min_level, max_level, instance_type+0, shutdown_timer, zone_motd, default_reenter_time, default_reset_time, default_lockout_time, force_group_to_zone, safe_heading, xp_modifier, ruleset_id, expansion_id, weather_allowed, sky_file, can_bind, can_gate, city_zone, can_evac FROM zones where name='%s'",escaped);
if(result && mysql_num_rows(result) > 0) { if(result && mysql_num_rows(result) > 0) {
@ -2999,8 +3001,10 @@ void WorldDatabase::LoadZoneInfo(ZoneServer* zone){
if (zone->IsInstanceZone()) if (zone->IsInstanceZone())
{ {
if ( zone->GetInstanceID() < 1 ) if ( zone->GetInstanceID() < 1 ) {
zone->SetupInstance(CreateNewInstance(zone->GetZoneID())); zone->SetupInstance(CreateNewInstance(zone->GetZoneID(), minLevel, maxLevel, avgLevel, firstLevel));
zone->setGroupRaidLevels(minLevel, maxLevel, avgLevel, firstLevel);
}
else else
zone->SetupInstance(zone->GetInstanceID()); zone->SetupInstance(zone->GetInstanceID());
} }
@ -4085,7 +4089,6 @@ void WorldDatabase::UpdateStartingZone(int32 char_id, int8 class_id, int8 race_i
instance_id = CreateNewInstance(zone_id); instance_id = CreateNewInstance(zone_id);
tmp->SetInstanceID(instance_id); tmp->SetInstanceID(instance_id);
LoadZoneInfo(tmp); LoadZoneInfo(tmp);
instance_id = CreateNewInstance(zone_id);
AddCharacterInstance(char_id, instance_id, string(tmp->GetZoneName()), tmp->GetInstanceType(), Timer::GetUnixTimeStamp(), 0, tmp->GetDefaultLockoutTime(), tmp->GetDefaultReenterTime()); AddCharacterInstance(char_id, instance_id, string(tmp->GetZoneName()), tmp->GetInstanceType(), Timer::GetUnixTimeStamp(), 0, tmp->GetDefaultLockoutTime(), tmp->GetDefaultReenterTime());
safe_delete(tmp); safe_delete(tmp);
} }
@ -5935,13 +5938,13 @@ bool WorldDatabase::UpdateInstancedSpawnRemoved(int32 spawn_location_entry_id, i
return false; return false;
} }
int32 WorldDatabase::CreateNewInstance(int32 zone_id) int32 WorldDatabase::CreateNewInstance(int32 zone_id, int32 playersMinLevel, int32 playersMaxLevel, int32 playersavgLevel, int32 playersfirstLevel)
{ {
int32 ret = 0; int32 ret = 0;
LogWrite(INSTANCE__DEBUG, 0, "Instance", "Creating new instance for zone: %u ", zone_id); LogWrite(INSTANCE__DEBUG, 0, "Instance", "Creating new instance for zone: %u ", zone_id);
if( !database_new.Query("INSERT INTO instances (zone_id) VALUES (%u)", zone_id) ) if( !database_new.Query("INSERT INTO instances (zone_id, player_minlevel, player_maxlevel, player_avglevel, player_firstlevel) VALUES (%u, %u, %u, %u, %u)", zone_id, playersMinLevel, playersMaxLevel, playersavgLevel, playersfirstLevel) )
LogWrite(INSTANCE__ERROR, 0, "Instance", "Error in CreateNewInstance() '%s': %i", database_new.GetErrorMsg(), database_new.GetError()); LogWrite(INSTANCE__ERROR, 0, "Instance", "Error in CreateNewInstance() '%s': %i", database_new.GetErrorMsg(), database_new.GetError());
else else
ret = database_new.LastInsertID(); ret = database_new.LastInsertID();

View File

@ -217,7 +217,7 @@ public:
void LoadPlayerAA(Player *player); void LoadPlayerAA(Player *player);
void LoadCharacterQuestProgress(Client* client); void LoadCharacterQuestProgress(Client* client);
void LoadCharacterFriendsIgnoreList(Player* player); void LoadCharacterFriendsIgnoreList(Player* player);
void LoadZoneInfo(ZoneServer* zone); void LoadZoneInfo(ZoneServer* zone, int32 minLevel=0, int32 maxLevel=0, int32 avgLevel=0, int32 firstLevel=0);
void LoadZoneInfo(ZoneInfo* zone_info); void LoadZoneInfo(ZoneInfo* zone_info);
int32 GetZoneID(const char* name); int32 GetZoneID(const char* name);
void SaveZoneInfo(int32 zone_id, const char* field, sint32 value); void SaveZoneInfo(int32 zone_id, const char* field, sint32 value);
@ -398,7 +398,7 @@ public:
// Zone Instance DB Functions // Zone Instance DB Functions
map<int32,int32>* GetInstanceRemovedSpawns(int32 instance_id, int8 type); map<int32,int32>* GetInstanceRemovedSpawns(int32 instance_id, int8 type);
int32 CreateNewInstance(int32 zone_id); int32 CreateNewInstance(int32 zone_id, int32 playersMinLevel=0, int32 playersMaxLevel=0, int32 playersavgLevel=0, int32 playersfirstLevel=0);
//int32 AddCharacterInstance(int32 char_id, int32 instance_id, int32 grant_reenter_time_left=0, int32 grant_reset_time_left=0, int32 lockout_time=0); //int32 AddCharacterInstance(int32 char_id, int32 instance_id, int32 grant_reenter_time_left=0, int32 grant_reset_time_left=0, int32 lockout_time=0);
int32 AddCharacterInstance(int32 char_id, int32 instance_id, string zone_name, int8 instance_type, int32 last_success, int32 last_failure, int32 success_lockout, int32 failure_lockout); int32 AddCharacterInstance(int32 char_id, int32 instance_id, string zone_name, int8 instance_type, int32 last_success, int32 last_failure, int32 success_lockout, int32 failure_lockout);
bool UpdateCharacterInstanceTimers(int32 char_id, int32 instance_id, int32 lockout_time=0, int32 reset_time=0, int32 reenter_time=0 ); bool UpdateCharacterInstanceTimers(int32 char_id, int32 instance_id, int32 lockout_time=0, int32 reset_time=0, int32 reenter_time=0 );

View File

@ -4152,7 +4152,9 @@ void Client::SetCurrentZoneByInstanceID(int32 id, int32 zoneid) {
current_zone->RemoveSpawn(player, false, true, true, true, true); current_zone->RemoveSpawn(player, false, true, true, true, true);
} }
ZoneChangeDetails zone_details; ZoneChangeDetails zone_details;
if (zone_list.GetZoneByInstance(&zone_details, id, zoneid, true, false, true, false)) { int32 minLevel = 0, maxLevel = 0, avgLevel = 0, firstLevel = 0;
world.GetGroupManager()->EstablishRaidLevelRange(this, &minLevel, &maxLevel, &avgLevel, &firstLevel);
if (zone_list.GetZoneByInstance(&zone_details, id, zoneid, true, false, true, false, minLevel, maxLevel, avgLevel, firstLevel)) {
SetCurrentZone((ZoneServer*)zone_details.zonePtr); SetCurrentZone((ZoneServer*)zone_details.zonePtr);
} }
else { else {
@ -4649,6 +4651,9 @@ bool Client::IdentifyInstance(ZoneChangeDetails* zone_details, int32 zoneID) {
if (instanceType < 1) if (instanceType < 1)
return false; return false;
int32 minLevel = 0, maxLevel = 0, avgLevel = 0, firstLevel = 0;
world.GetGroupManager()->EstablishRaidLevelRange(this, &minLevel, &maxLevel, &avgLevel, &firstLevel);
bool foundZone = false; bool foundZone = false;
InstanceData* data = GetPlayer()->GetCharacterInstances()->FindInstanceByZoneID(zoneID); InstanceData* data = GetPlayer()->GetCharacterInstances()->FindInstanceByZoneID(zoneID);
if (data) { if (data) {
@ -4659,7 +4664,7 @@ bool Client::IdentifyInstance(ZoneChangeDetails* zone_details, int32 zoneID) {
} }
// Need to update `character_instances` table with new timestamps (for persistent) and instance id's // Need to update `character_instances` table with new timestamps (for persistent) and instance id's
foundZone = zone_list.GetZoneByInstance(zone_details, data->instance_id, zoneID, true, false, false); foundZone = zone_list.GetZoneByInstance(zone_details, data->instance_id, zoneID, true, false, false, true, minLevel, maxLevel, avgLevel, firstLevel);
// if we got an instance_zone and the instance_id from the data is 0 or data instance id is not the same as the zone instance id then update values // if we got an instance_zone and the instance_id from the data is 0 or data instance id is not the same as the zone instance id then update values
if (foundZone && (data->instance_id == 0 || data->instance_id != zone_details->instanceId)) { if (foundZone && (data->instance_id == 0 || data->instance_id != zone_details->instanceId)) {
@ -4685,6 +4690,9 @@ bool Client::TryZoneInstance(int32 zoneID, bool zone_coords_valid) {
// determine if this is a group instanced zone that already exists // determine if this is a group instanced zone that already exists
foundZone = world.GetGroupManager()->IdentifyMemberInGroupOrRaid(&zone_details, this, zoneID); foundZone = world.GetGroupManager()->IdentifyMemberInGroupOrRaid(&zone_details, this, zoneID);
int32 minLevel = 0, maxLevel = 0, avgLevel = 0, firstLevel = 0;
world.GetGroupManager()->EstablishRaidLevelRange(this, &minLevel, &maxLevel, &avgLevel, &firstLevel);
if (foundZone) { if (foundZone) {
InstanceData* data = nullptr; InstanceData* data = nullptr;
if (zone_details.instanceId) if (zone_details.instanceId)
@ -4720,7 +4728,7 @@ bool Client::TryZoneInstance(int32 zoneID, bool zone_coords_valid) {
case GROUP_LOCKOUT_INSTANCE: case GROUP_LOCKOUT_INSTANCE:
case RAID_LOCKOUT_INSTANCE: case RAID_LOCKOUT_INSTANCE:
{ {
if ((foundZone = zone_list.GetZoneByInstance(&zone_details, 0, zoneID))) { if ((foundZone = zone_list.GetZoneByInstance(&zone_details, 0, zoneID, true, false, true, true, minLevel, maxLevel, avgLevel, firstLevel))) {
// once lockout instance zone shuts down you can't renenter if you have a lockout or if you don't you get a new zone // once lockout instance zone shuts down you can't renenter if you have a lockout or if you don't you get a new zone
// so delete `instances` entry for the zone when it shuts down. // so delete `instances` entry for the zone when it shuts down.
int32 db_id = database.AddCharacterInstance(GetPlayer()->GetCharacterID(), zone_details.instanceId, zone_details.zoneName, zone_details.instanceType, 0, 0, zone_details.defaultLockoutTime, zone_details.defaultReenterTime); int32 db_id = database.AddCharacterInstance(GetPlayer()->GetCharacterID(), zone_details.instanceId, zone_details.zoneName, zone_details.instanceType, 0, 0, zone_details.defaultLockoutTime, zone_details.defaultReenterTime);
@ -4734,7 +4742,7 @@ bool Client::TryZoneInstance(int32 zoneID, bool zone_coords_valid) {
case GROUP_PERSIST_INSTANCE: case GROUP_PERSIST_INSTANCE:
case RAID_PERSIST_INSTANCE: case RAID_PERSIST_INSTANCE:
{ {
if ((foundZone = zone_list.GetZoneByInstance(&zone_details, 0, zoneID))) { if ((foundZone = zone_list.GetZoneByInstance(&zone_details, 0, zoneID, true, false, true, true, minLevel, maxLevel, avgLevel, firstLevel))) {
int32 db_id = database.AddCharacterInstance(GetPlayer()->GetCharacterID(), zone_details.instanceId, zone_details.zoneName, zone_details.instanceType, Timer::GetUnixTimeStamp(), 0, zone_details.defaultLockoutTime, zone_details.defaultReenterTime); int32 db_id = database.AddCharacterInstance(GetPlayer()->GetCharacterID(), zone_details.instanceId, zone_details.zoneName, zone_details.instanceType, Timer::GetUnixTimeStamp(), 0, zone_details.defaultLockoutTime, zone_details.defaultReenterTime);
if (db_id > 0) if (db_id > 0)
@ -4750,7 +4758,7 @@ bool Client::TryZoneInstance(int32 zoneID, bool zone_coords_valid) {
if (instance_zone) { if (instance_zone) {
// Check the current population against the max population, if greater or equal start a new version // Check the current population against the max population, if greater or equal start a new version
if (instance_zone->GetClientCount() >= rule_manager.GetZoneRule(GetCurrentZoneID(), R_Zone, MaxPlayers)->GetInt32()) { if (instance_zone->GetClientCount() >= rule_manager.GetZoneRule(GetCurrentZoneID(), R_Zone, MaxPlayers)->GetInt32()) {
foundZone = zone_list.GetZoneByInstance(&zone_details, 0, zoneID); foundZone = zone_list.GetZoneByInstance(&zone_details, 0, zoneID, true, false, true, true, minLevel, maxLevel, avgLevel, firstLevel);
} }
else { else {
peer_manager.setZonePeerDataSelf(&zone_details, std::string(instance_zone->GetZoneFile()), std::string(instance_zone->GetZoneName()), peer_manager.setZonePeerDataSelf(&zone_details, std::string(instance_zone->GetZoneFile()), std::string(instance_zone->GetZoneName()),
@ -4762,7 +4770,7 @@ bool Client::TryZoneInstance(int32 zoneID, bool zone_coords_valid) {
} }
} }
else { else {
foundZone = zone_list.GetZoneByInstance(&zone_details, 0, zoneID); foundZone = zone_list.GetZoneByInstance(&zone_details, 0, zoneID, true, false, true, true, minLevel, maxLevel, avgLevel, firstLevel);
} }
break; break;
@ -4779,7 +4787,7 @@ bool Client::TryZoneInstance(int32 zoneID, bool zone_coords_valid) {
case QUEST_INSTANCE: case QUEST_INSTANCE:
{ {
foundZone = zone_list.GetZoneByInstance(&zone_details, 0, zoneID); foundZone = zone_list.GetZoneByInstance(&zone_details, 0, zoneID, true, false, true, true, minLevel, maxLevel, avgLevel, firstLevel);
break; break;
/* /*
ALTER TABLE `zones` CHANGE COLUMN `instance_type` `instance_type` ENUM('NONE','GROUP_LOCKOUT_INSTANCE','GROUP_PERSIST_INSTANCE','RAID_LOCKOUT_INSTANCE','RAID_PERSIST_INSTANCE','SOLO_LOCKOUT_INSTANCE','SOLO_PERSIST_INSTANCE','TRADESKILL_INSTANCE','PUBLIC_INSTANCE','PERSONAL_HOUSE_INSTANCE','GUILD_HOUSE_INSTANCE','QUEST_INSTANCE') NOT NULL DEFAULT 'NONE' COLLATE 'latin1_general_ci' AFTER `start_zone`; ALTER TABLE `zones` CHANGE COLUMN `instance_type` `instance_type` ENUM('NONE','GROUP_LOCKOUT_INSTANCE','GROUP_PERSIST_INSTANCE','RAID_LOCKOUT_INSTANCE','RAID_PERSIST_INSTANCE','SOLO_LOCKOUT_INSTANCE','SOLO_PERSIST_INSTANCE','TRADESKILL_INSTANCE','PUBLIC_INSTANCE','PERSONAL_HOUSE_INSTANCE','GUILD_HOUSE_INSTANCE','QUEST_INSTANCE') NOT NULL DEFAULT 'NONE' COLLATE 'latin1_general_ci' AFTER `start_zone`;
@ -4938,7 +4946,9 @@ bool Client::CheckZoneAccess(const char* zoneName) {
void Client::Zone(int32 instanceid, bool set_coords, bool byInstanceID, bool is_spell) { void Client::Zone(int32 instanceid, bool set_coords, bool byInstanceID, bool is_spell) {
ZoneChangeDetails zone_details; ZoneChangeDetails zone_details;
if (zone_list.GetZoneByInstance(&zone_details, instanceid, 0)) { int32 minLevel = 0, maxLevel = 0, avgLevel = 0, firstLevel = 0;
world.GetGroupManager()->EstablishRaidLevelRange(this, &minLevel, &maxLevel, &avgLevel, &firstLevel);
if (zone_list.GetZoneByInstance(&zone_details, instanceid, 0, true, false, true, true, minLevel, maxLevel, avgLevel, firstLevel)) {
Zone(&zone_details, (ZoneServer*)zone_details.zonePtr, set_coords, is_spell); Zone(&zone_details, (ZoneServer*)zone_details.zonePtr, set_coords, is_spell);
} }
@ -5102,7 +5112,11 @@ void Client::Zone(const char* new_zone, bool set_coords, bool is_spell)
std::string camelCaseName = database.GetZoneName(zone_id); std::string camelCaseName = database.GetZoneName(zone_id);
InstanceData* data = GetPlayer()->GetCharacterInstances()->FindInstanceByZoneID(zone_id); InstanceData* data = GetPlayer()->GetCharacterInstances()->FindInstanceByZoneID(zone_id);
if ((data && zone_list.GetZoneByInstance(&zone_details, data->instance_id, zone_id)) || zone_list.GetZone(&zone_details, 0, camelCaseName)) {
int32 minLevel = 0, maxLevel = 0, avgLevel = 0, firstLevel = 0;
world.GetGroupManager()->EstablishRaidLevelRange(this, &minLevel, &maxLevel, &avgLevel, &firstLevel);
if ((data && zone_list.GetZoneByInstance(&zone_details, data->instance_id, zone_id, true, false, true, true, minLevel, maxLevel, avgLevel, firstLevel)) || zone_list.GetZone(&zone_details, 0, camelCaseName)) {
Zone(&zone_details, (ZoneServer*)zone_details.zonePtr, set_coords, is_spell); Zone(&zone_details, (ZoneServer*)zone_details.zonePtr, set_coords, is_spell);
} }
} }
@ -13403,3 +13417,40 @@ void Client::SendReceiveOffer(Client* target_client, int8 type, std::string name
} }
safe_delete(packet); safe_delete(packet);
} }
bool Client::SendDialogChoice(int32 spawnID, const std::string& windowTextPrompt, const std::string& acceptText, const std::string& acceptCommand, const std::string& declineText, const std::string& declineCommand, int32 time, int8 textBox, int8 textBoxRequired, int32 maxLength) {
PacketStruct* p = configReader.getStruct("WS_ChoiceWindow", GetVersion());
if (!p) {
LogWrite(CCLIENT__ERROR, 0, "Client", "CreateChoiceWindow command error: WS_ChoiceWindow packet does not exist for client version %u", GetVersion());
return false;
}
bool successAccept = true;
bool successDecline = true;
if(acceptCommand.size() > 0)
successAccept = dialog_manager.addAccept(acceptCommand, spawnID, time);
if(declineCommand.size() > 0)
successDecline = dialog_manager.addDecline(declineCommand, spawnID, time);
if(!successAccept || !successDecline) { // failed to successfully add command
LogWrite(CCLIENT__ERROR, 0, "Client", "CreateChoiceWindow command error: Window has a conflict with accept (%s) %u or decline (%s) %u. Call ClearChoice(Player, Command, x) x being 0 for accept 1 for decline commands.", acceptCommand.c_str(), successAccept, declineCommand.c_str(), successDecline);
return false;
}
p->setMediumStringByName("text", windowTextPrompt.c_str());
p->setMediumStringByName("accept_text", acceptText.c_str());
p->setMediumStringByName("accept_command", acceptCommand.c_str());
p->setMediumStringByName("cancel_text", declineText.c_str());
p->setMediumStringByName("cancel_command", declineCommand.c_str());
p->setDataByName("time", time);
p->setDataByName("text_box", textBox);
p->setDataByName("text_required", textBoxRequired);
p->setDataByName("max_length", maxLength);
QueuePacket(p->serialize());
safe_delete(p);
return true;
}

View File

@ -24,6 +24,12 @@
#include <atomic> #include <atomic>
#include <mutex> #include <mutex>
#include <shared_mutex> #include <shared_mutex>
#include <iostream>
#include <map>
#include <string>
#include <thread>
#include <chrono>
#include <condition_variable>
#include "../common/EQStream.h" #include "../common/EQStream.h"
#include "../common/timer.h" #include "../common/timer.h"
@ -61,13 +67,13 @@ struct GroupOptions;
#define MAIL_TYPE_SPAM 1 #define MAIL_TYPE_SPAM 1
#define MAIL_TYPE_GM 2 #define MAIL_TYPE_GM 2
struct QueuedQuest{ struct QueuedQuest {
int32 quest_id; int32 quest_id;
int32 step; int32 step;
bool display_quest_helper; bool display_quest_helper;
}; };
struct BuyBackItem{ struct BuyBackItem {
int32 item_id; int32 item_id;
int32 unique_id; int32 unique_id;
int16 quantity; int16 quantity;
@ -75,7 +81,7 @@ struct BuyBackItem{
bool save_needed; bool save_needed;
}; };
struct MacroData{ struct MacroData {
string name; string name;
string text; string text;
int16 icon; int16 icon;
@ -150,6 +156,85 @@ struct WaypointInfo {
}; };
class DialogManager {
public:
// Add accept string with int32 id and a timer
bool addAccept(const std::string& key, int32 id, int32 seconds) {
std::lock_guard<std::mutex> lock(mutex_);
if (acceptMap_.count(key) == 0) {
acceptMap_[key] = id;
if (seconds)
startTimer(key, seconds, true); // true indicates it's an accept key
return true;
}
return false; // Duplicate found in either map
}
// Add decline string with int32 id and a timer
bool addDecline(const std::string& key, int32 id, int32 seconds) {
std::lock_guard<std::mutex> lock(mutex_);
if (declineMap_.count(key) == 0) {
declineMap_[key] = id;
if (seconds)
startTimer(key, seconds, false); // false indicates it's a decline key
return true;
}
return false; // Duplicate found in either map
}
// Clear a specific accept string
bool clearAccept(const std::string& key) {
std::lock_guard<std::mutex> lock(mutex_);
return acceptMap_.erase(key) > 0;
}
// Clear a specific decline string
bool clearDecline(const std::string& key) {
std::lock_guard<std::mutex> lock(mutex_);
return declineMap_.erase(key) > 0;
}
int32 getAcceptValue(const std::string& key) {
std::lock_guard<std::mutex> lock(mutex_);
if (acceptMap_.count(key)) {
return acceptMap_.at(key);
}
return 0; // Key not found
}
int32 getDeclineValue(const std::string& key) {
std::lock_guard<std::mutex> lock(mutex_);
if (declineMap_.count(key)) {
return declineMap_.at(key);
}
return 0; // Key not found
}
// Check if a dialog is active
bool isDialogActive(const std::string& key) {
std::lock_guard<std::mutex> lock(mutex_);
return acceptMap_.count(key) > 0 || declineMap_.count(key) > 0;
}
private:
std::map<std::string, int32> acceptMap_;
std::map<std::string, int32> declineMap_;
std::mutex mutex_;
void startTimer(const std::string& key, int32 seconds, bool isAccept) {
std::thread([this, key, seconds, isAccept]() {
std::this_thread::sleep_for(std::chrono::seconds(seconds));
std::lock_guard<std::mutex> lock(mutex_);
if (isAccept) {
acceptMap_.erase(key);
}
else {
declineMap_.erase(key);
}
}).detach();
}
};
class Client { class Client {
public: public:
Client(EQStream* ieqs); Client(EQStream* ieqs);
@ -158,14 +243,14 @@ public:
void RemoveClientFromZone(); void RemoveClientFromZone();
bool Process(bool zone_process = false); bool Process(bool zone_process = false);
void Disconnect(bool send_disconnect = true); void Disconnect(bool send_disconnect = true);
void SetConnected(bool val){ connected = val; } void SetConnected(bool val) { connected = val; }
bool IsConnected(){ return connected; } bool IsConnected() { return connected; }
bool IsReadyForSpawns(){ return ready_for_spawns; } bool IsReadyForSpawns() { return ready_for_spawns; }
bool IsReadyForUpdates() { return ready_for_updates; } bool IsReadyForUpdates() { return ready_for_updates; }
bool IsZoning(){ return client_zoning; } bool IsZoning() { return client_zoning; }
void SetReadyForUpdates(); void SetReadyForUpdates();
void SetReadyForSpawns(bool val); void SetReadyForSpawns(bool val);
void QueuePacket(EQ2Packet* app, bool attemptedCombine=false); void QueuePacket(EQ2Packet* app, bool attemptedCombine = false);
void SendLoginInfo(); void SendLoginInfo();
int8 GetMessageChannelColor(int8 channel_type); int8 GetMessageChannelColor(int8 channel_type);
void HandleTellMessage(const char* fromName, const char* message, const char* to, int32 current_language_id); void HandleTellMessage(const char* fromName, const char* message, const char* to, int32 current_language_id);
@ -174,12 +259,12 @@ public:
void SendSpellUpdate(Spell* spell, bool add_silently = false, bool add_to_hotbar = true); void SendSpellUpdate(Spell* spell, bool add_silently = false, bool add_to_hotbar = true);
void Zone(ZoneChangeDetails* new_zone, ZoneServer* opt_zone = nullptr, bool set_coords = true, bool is_spell = false); void Zone(ZoneChangeDetails* new_zone, ZoneServer* opt_zone = nullptr, bool set_coords = true, bool is_spell = false);
void Zone(const char* new_zone, bool set_coords = true, bool is_spell = false); void Zone(const char* new_zone, bool set_coords = true, bool is_spell = false);
void Zone(int32 instanceid, bool set_coords = true, bool byInstanceID=false, bool is_spell = false); void Zone(int32 instanceid, bool set_coords = true, bool byInstanceID = false, bool is_spell = false);
void ApproveZone(); void ApproveZone();
void SendZoneInfo(); void SendZoneInfo();
void SendZoneSpawns(); void SendZoneSpawns();
void HandleVerbRequest(EQApplicationPacket* app); void HandleVerbRequest(EQApplicationPacket* app);
void SendControlGhost(int32 send_id=0xFFFFFFFF, int8 unknown2=0); void SendControlGhost(int32 send_id = 0xFFFFFFFF, int8 unknown2 = 0);
void SendCharInfo(); void SendCharInfo();
void SendLoginDeniedBadVersion(); void SendLoginDeniedBadVersion();
void SendCharPOVGhost(); void SendCharPOVGhost();
@ -187,7 +272,7 @@ public:
float DistanceFrom(Client* client); float DistanceFrom(Client* client);
void SendDefaultGroupOptions(); void SendDefaultGroupOptions();
bool HandleLootItemByID(Spawn* entity, int32 item_id, Spawn* target); bool HandleLootItemByID(Spawn* entity, int32 item_id, Spawn* target);
bool HandleLootItem(Spawn* entity, Item* item, Spawn* target=nullptr, bool overrideLootRestrictions = false); bool HandleLootItem(Spawn* entity, Item* item, Spawn* target = nullptr, bool overrideLootRestrictions = false);
void HandleLootItemRequestPacket(EQApplicationPacket* app); void HandleLootItemRequestPacket(EQApplicationPacket* app);
void HandleSkillInfoRequest(EQApplicationPacket* app); void HandleSkillInfoRequest(EQApplicationPacket* app);
void HandleExamineInfoRequest(EQApplicationPacket* app); void HandleExamineInfoRequest(EQApplicationPacket* app);
@ -199,8 +284,8 @@ public:
bool Summon(const char* search_name); bool Summon(const char* search_name);
std::string IdentifyInstanceLockout(int32 zoneID, bool displayClient = true); std::string IdentifyInstanceLockout(int32 zoneID, bool displayClient = true);
bool IdentifyInstance(ZoneChangeDetails* zone_details, int32 zoneID); bool IdentifyInstance(ZoneChangeDetails* zone_details, int32 zoneID);
bool TryZoneInstance(int32 zoneID, bool zone_coords_valid=false); bool TryZoneInstance(int32 zoneID, bool zone_coords_valid = false);
bool GotoSpawn(const char* search_name, bool forceTarget=false); bool GotoSpawn(const char* search_name, bool forceTarget = false);
void DisplayDeadWindow(); void DisplayDeadWindow();
void HandlePlayerRevive(int32 point_id); void HandlePlayerRevive(int32 point_id);
void Bank(Spawn* banker, bool cancel = false); void Bank(Spawn* banker, bool cancel = false);
@ -215,7 +300,7 @@ public:
bool AddItemToBank(int32 item_id, int16 quantity = 0); bool AddItemToBank(int32 item_id, int16 quantity = 0);
bool AddItemToBank(Item* item); bool AddItemToBank(Item* item);
void UnequipItem(int16 index, sint32 bag_id = -999, int8 to_slot = 255, int8 appearance_equip = 0); void UnequipItem(int16 index, sint32 bag_id = -999, int8 to_slot = 255, int8 appearance_equip = 0);
bool RemoveItem(Item *item, int16 quantity, bool force_override_no_delete = false); bool RemoveItem(Item* item, int16 quantity, bool force_override_no_delete = false);
void ProcessTeleport(Spawn* spawn, vector<TransportDestination*>* destinations, int32 transport_id = 0, bool is_spell = false); void ProcessTeleport(Spawn* spawn, vector<TransportDestination*>* destinations, int32 transport_id = 0, bool is_spell = false);
void ProcessTeleportLocation(EQApplicationPacket* app); void ProcessTeleportLocation(EQApplicationPacket* app);
@ -235,9 +320,9 @@ public:
zoning_destination = zone; zoning_destination = zone;
} }
ZoneServer* GetZoningDestination() { return zoning_destination; } ZoneServer* GetZoningDestination() { return zoning_destination; }
Player* GetPlayer(){ return player; } Player* GetPlayer() { return player; }
EQStream* getConnection(){ return eqs; } EQStream* getConnection() { return eqs; }
void setConnection(EQStream* ieqs){ eqs = ieqs; } void setConnection(EQStream* ieqs) { eqs = ieqs; }
inline int32 GetIP() { return ip; } inline int32 GetIP() { return ip; }
inline int16 GetPort() { return port; } inline int16 GetPort() { return port; }
@ -247,34 +332,34 @@ public:
inline const char* GetAccountName() { return account_name; } inline const char* GetAccountName() { return account_name; }
inline sint16 GetAdminStatus() { return admin_status; } inline sint16 GetAdminStatus() { return admin_status; }
inline int16 GetVersion() { return version; } inline int16 GetVersion() { return version; }
void SetNameCRC(int32 val){ name_crc = val; } void SetNameCRC(int32 val) { name_crc = val; }
int32 GetNameCRC(){ return name_crc; } int32 GetNameCRC() { return name_crc; }
void SetVersion(int16 new_version){ version = new_version; } void SetVersion(int16 new_version) { version = new_version; }
void SetAccountID(int32 in_accountid) { account_id = in_accountid; } void SetAccountID(int32 in_accountid) { account_id = in_accountid; }
void SetCharacterID(int32 in_characterid) { character_id = in_characterid; } void SetCharacterID(int32 in_characterid) { character_id = in_characterid; }
void SetAdminStatus(sint16 in_status) { admin_status = in_status; } void SetAdminStatus(sint16 in_status) { admin_status = in_status; }
void DetermineCharacterUpdates ( ); void DetermineCharacterUpdates();
void UpdateTimeStampFlag ( int8 flagType ) void UpdateTimeStampFlag(int8 flagType)
{ {
if(! (timestamp_flag & flagType ) ) if (!(timestamp_flag & flagType))
timestamp_flag |= flagType; timestamp_flag |= flagType;
} }
int8 GetTimeStampFlag ( ) { return timestamp_flag; } int8 GetTimeStampFlag() { return timestamp_flag; }
bool UpdateQuickbarNeeded(); bool UpdateQuickbarNeeded();
void Save(); void Save();
bool remove_from_list; bool remove_from_list;
void CloseLoot(int32 spawn_id); void CloseLoot(int32 spawn_id);
void SendLootResponsePacket(int32 total_coins, vector<Item*>* items, Spawn* entity, bool ignore_loot_tier = false); void SendLootResponsePacket(int32 total_coins, vector<Item*>* items, Spawn* entity, bool ignore_loot_tier = false);
void LootSpawnRequest(Spawn* entity, bool attemptDisarm=true); void LootSpawnRequest(Spawn* entity, bool attemptDisarm = true);
bool LootSpawnByMethod(Spawn* entity); bool LootSpawnByMethod(Spawn* entity);
void OpenChest(Spawn* entity, bool attemptDisarm=true); void OpenChest(Spawn* entity, bool attemptDisarm = true);
void CastGroupOrSelf(Entity* source, uint32 spellID, uint32 spellTier=1, float restrictiveRadius=0.0f); void CastGroupOrSelf(Entity* source, uint32 spellID, uint32 spellTier = 1, float restrictiveRadius = 0.0f);
void CheckPlayerQuestsKillUpdate(Spawn* spawn); void CheckPlayerQuestsKillUpdate(Spawn* spawn);
void CheckPlayerQuestsChatUpdate(Spawn* spawn); void CheckPlayerQuestsChatUpdate(Spawn* spawn);
void CheckPlayerQuestsItemUpdate(Item* item); void CheckPlayerQuestsItemUpdate(Item* item);
@ -291,8 +376,8 @@ public:
void SendQuestFailure(Quest* quest); void SendQuestFailure(Quest* quest);
void SendQuestUpdateStep(Quest* quest, int32 step, bool display_quest_helper = true); void SendQuestUpdateStep(Quest* quest, int32 step, bool display_quest_helper = true);
void SendQuestUpdateStepImmediately(Quest* quest, int32 step, bool display_quest_helper = true); void SendQuestUpdateStepImmediately(Quest* quest, int32 step, bool display_quest_helper = true);
void DisplayQuestRewards(Quest* quest, int64 coin, vector<Item*>* rewards=0, vector<Item*>* selectable_rewards=0, map<int32, sint32>* factions=0, const char* header="Quest Reward!", int32 status_points=0, const char* text=0, bool was_displayed = false); void DisplayQuestRewards(Quest* quest, int64 coin, vector<Item*>* rewards = 0, vector<Item*>* selectable_rewards = 0, map<int32, sint32>* factions = 0, const char* header = "Quest Reward!", int32 status_points = 0, const char* text = 0, bool was_displayed = false);
void PopulateQuestRewardItems(vector <Item*>* items, PacketStruct* packet, std::string num_rewards_str = "num_rewards", std::string reward_id_str = "reward_id" , std::string item_str = "item"); void PopulateQuestRewardItems(vector <Item*>* items, PacketStruct* packet, std::string num_rewards_str = "num_rewards", std::string reward_id_str = "reward_id", std::string item_str = "item");
void DisplayQuestComplete(Quest* quest, bool tempReward = false, std::string customDescription = string(""), bool was_displayed = false); void DisplayQuestComplete(Quest* quest, bool tempReward = false, std::string customDescription = string(""), bool was_displayed = false);
void DisplayRandomizeFeatures(int32 features); void DisplayRandomizeFeatures(int32 features);
void AcceptQuestReward(Quest* quest, int32 item_id); void AcceptQuestReward(Quest* quest, int32 item_id);
@ -310,7 +395,7 @@ public:
bool ShouldTarget(); bool ShouldTarget();
void TargetSpawn(Spawn* spawn); void TargetSpawn(Spawn* spawn);
void ReloadQuests(); void ReloadQuests();
int32 GetCurrentQuestID(){ return current_quest_id; } int32 GetCurrentQuestID() { return current_quest_id; }
void SetLuaDebugClient(bool val); void SetLuaDebugClient(bool val);
void SetMerchantTransaction(Spawn* spawn); void SetMerchantTransaction(Spawn* spawn);
Spawn* GetMerchantTransaction(); Spawn* GetMerchantTransaction();
@ -360,9 +445,9 @@ public:
void SetPlayer(Player* new_player); void SetPlayer(Player* new_player);
void AddPendingQuestAcceptReward(Quest* quest); void AddPendingQuestAcceptReward(Quest* quest);
void AddPendingQuestReward(Quest* quest, bool update=true, bool is_temporary = false, std::string description = std::string("")); void AddPendingQuestReward(Quest* quest, bool update = true, bool is_temporary = false, std::string description = std::string(""));
bool HasQuestRewardQueued(int32 quest_id, bool is_temporary, bool is_collection); bool HasQuestRewardQueued(int32 quest_id, bool is_temporary, bool is_collection);
void QueueQuestReward(int32 quest_id, bool is_temporary, bool is_collection, bool has_displayed, int64 tmp_coin, int32 tmp_status, std::string description, bool db_saved=false, int32 index=0); void QueueQuestReward(int32 quest_id, bool is_temporary, bool is_collection, bool has_displayed, int64 tmp_coin, int32 tmp_status, std::string description, bool db_saved = false, int32 index = 0);
void RemoveQueuedQuestReward(); void RemoveQueuedQuestReward();
void AddPendingQuestUpdate(int32 quest_id, int32 step_id, int32 progress = 0xFFFFFFFF); void AddPendingQuestUpdate(int32 quest_id, int32 step_id, int32 progress = 0xFFFFFFFF);
void ProcessQuestUpdates(); void ProcessQuestUpdates();
@ -370,19 +455,19 @@ public:
void BeginWaypoint(const char* waypoint_name, float x, float y, float z); void BeginWaypoint(const char* waypoint_name, float x, float y, float z);
void InspectPlayer(Player* player_to_inspect); void InspectPlayer(Player* player_to_inspect);
void SetPendingGuildInvite(Guild* guild, Player* invited_by = 0); void SetPendingGuildInvite(Guild* guild, Player* invited_by = 0);
PendingGuildInvite* GetPendingGuildInvite() {return &pending_guild_invite;} PendingGuildInvite* GetPendingGuildInvite() { return &pending_guild_invite; }
void ShowClaimWindow(); void ShowClaimWindow();
void ShowGuildSearchWindow(); void ShowGuildSearchWindow();
void CheckQuestQueue(); void CheckQuestQueue();
void ShowDressingRoom(Item *item, sint32 crc); void ShowDressingRoom(Item* item, sint32 crc);
void SendCollectionList(); void SendCollectionList();
bool SendCollectionsForItem(Item *item); bool SendCollectionsForItem(Item* item);
void HandleCollectionAddItem(int32 collection_id, Item *item); void HandleCollectionAddItem(int32 collection_id, Item* item);
void DisplayCollectionComplete(Collection *collection); void DisplayCollectionComplete(Collection* collection);
void HandInCollections(); void HandInCollections();
void AcceptCollectionRewards(Collection *collection, int32 selectable_item_id = 0); void AcceptCollectionRewards(Collection* collection, int32 selectable_item_id = 0);
void SendRecipeList(); void SendRecipeList();
void PopulateRecipeData(Recipe* recipe, PacketStruct* packet, int i=0); void PopulateRecipeData(Recipe* recipe, PacketStruct* packet, int i = 0);
int32 GetRecipeCRC(Recipe* recipe); int32 GetRecipeCRC(Recipe* recipe);
void SendRecipeDetails(vector<int32>* recipes); void SendRecipeDetails(vector<int32>* recipes);
void SendTitleUpdate(); void SendTitleUpdate();
@ -398,7 +483,7 @@ public:
bool IsCrafting(); bool IsCrafting();
void SetRecipeListSent(bool val) {m_recipeListSent = val; } void SetRecipeListSent(bool val) { m_recipeListSent = val; }
bool GetRecipeListSent() { return m_recipeListSent; } bool GetRecipeListSent() { return m_recipeListSent; }
void ShowRecipeBook(); void ShowRecipeBook();
PendingResurrection* GetCurrentRez(); PendingResurrection* GetCurrentRez();
@ -415,7 +500,7 @@ public:
bool GetInitialSpawnsSent() { return initial_spawns_sent; } bool GetInitialSpawnsSent() { return initial_spawns_sent; }
void SendQuestJournalUpdate(Quest* quest, bool updated=true); void SendQuestJournalUpdate(Quest* quest, bool updated = true);
void AddQuestTimer(int32 quest_id); void AddQuestTimer(int32 quest_id);
@ -461,9 +546,9 @@ public:
// finalize the spawn-in of the object in world, remove the item from player inventory, set the spawned in object item id (for future pickup) // finalize the spawn-in of the object in world, remove the item from player inventory, set the spawned in object item id (for future pickup)
bool PopulateHouseSpawnFinalize(); bool PopulateHouseSpawnFinalize();
void SendMoveObjectMode(Spawn* spawn, uint8 placementMode, float unknown2_3=0.0f); void SendMoveObjectMode(Spawn* spawn, uint8 placementMode, float unknown2_3 = 0.0f);
void SendFlightAutoMount(int32 path_id, int16 mount_id = 0, int8 mount_red_color = 0xFF, int8 mount_green_color = 0xFF, int8 mount_blue_color=0xFF); void SendFlightAutoMount(int32 path_id, int16 mount_id = 0, int8 mount_red_color = 0xFF, int8 mount_green_color = 0xFF, int8 mount_blue_color = 0xFF);
void SendShowBook(Spawn* sender, string title, int8 language, int8 num_pages, ...); void SendShowBook(Spawn* sender, string title, int8 language, int8 num_pages, ...);
void SendShowBook(Spawn* sender, string title, int8 language, vector<Item::BookPage*> pages); void SendShowBook(Spawn* sender, string title, int8 language, vector<Item::BookPage*> pages);
@ -480,7 +565,7 @@ public:
void AddWaypoint(string name, int8 type); void AddWaypoint(string name, int8 type);
void RemoveWaypoint(string name) { void RemoveWaypoint(string name) {
if (waypoints.count(name) > 0){ if (waypoints.count(name) > 0) {
waypoints.erase(name); waypoints.erase(name);
} }
} }
@ -531,7 +616,7 @@ public:
bool res = false; bool res = false;
MSpellDetails.readlock(__FUNCTION__, __LINE__); MSpellDetails.readlock(__FUNCTION__, __LINE__);
std::map<int32, int32>::iterator itr = sent_spell_details.find(id); std::map<int32, int32>::iterator itr = sent_spell_details.find(id);
if(itr != sent_spell_details.end() && itr->second == tier) if (itr != sent_spell_details.end() && itr->second == tier)
res = true; res = true;
MSpellDetails.releasereadlock(__FUNCTION__, __LINE__); MSpellDetails.releasereadlock(__FUNCTION__, __LINE__);
return res; return res;
@ -585,13 +670,13 @@ public:
void GiveQuestReward(Quest* quest, bool has_displayed = false); void GiveQuestReward(Quest* quest, bool has_displayed = false);
void SendReplaceWidget(int32 widget_id, bool delete_widget, float x=0.0f, float y=0.0f, float z=0.0f, int32 grid_id=0); void SendReplaceWidget(int32 widget_id, bool delete_widget, float x = 0.0f, float y = 0.0f, float z = 0.0f, int32 grid_id = 0);
void ProcessZoneIgnoreWidgets(); void ProcessZoneIgnoreWidgets();
void SendHearCast(Spawn* caster, Spawn* target, int32 spell_visual, int16 cast_time); void SendHearCast(Spawn* caster, Spawn* target, int32 spell_visual, int16 cast_time);
int32 GetSpellVisualOverride(int32 spell_visual); int32 GetSpellVisualOverride(int32 spell_visual);
sint16 GetClientItemPacketOffset() { sint16 offset = -1; if(GetVersion() <= 373) { offset = -2; } return offset; } sint16 GetClientItemPacketOffset() { sint16 offset = -1; if (GetVersion() <= 373) { offset = -2; } return offset; }
int32 GetZoningID() { return zoning_id; } int32 GetZoningID() { return zoning_id; }
int32 GetZoningInstanceID() { return zoning_instance_id; } int32 GetZoningInstanceID() { return zoning_instance_id; }
@ -601,6 +686,9 @@ public:
void HandleGroupAcceptResponse(int8 result); void HandleGroupAcceptResponse(int8 result);
void SetGroupOptionsReference(GroupOptions* options); void SetGroupOptionsReference(GroupOptions* options);
void SendReceiveOffer(Client* client_target, int8 type, std::string name, int8 unknown2); void SendReceiveOffer(Client* client_target, int8 type, std::string name, int8 unknown2);
bool SendDialogChoice(int32 spawnID, const std::string& windowTextPrompt, const std::string& acceptText, const std::string& acceptCommand, const std::string& declineText, const std::string& declineCommand, int32 time, int8 textBox, int8 textBoxRequired, int32 maxLength);
DialogManager dialog_manager;
private: private:
void AddRecipeToPlayerPack(Recipe* recipe, PacketStruct* packet, int16* i); void AddRecipeToPlayerPack(Recipe* recipe, PacketStruct* packet, int16* i);
void SavePlayerImages(); void SavePlayerImages();
@ -694,7 +782,7 @@ private:
std::atomic<int8> player_pos_change_count; std::atomic<int8> player_pos_change_count;
int32 player_pos_timer; int32 player_pos_timer;
bool enabled_player_pos_timer; bool enabled_player_pos_timer;
bool HandlePacket(EQApplicationPacket *app); bool HandlePacket(EQApplicationPacket* app);
EQStream* eqs; EQStream* eqs;
bool quickbar_changed; bool quickbar_changed;
ZoneServer* current_zone; ZoneServer* current_zone;

View File

@ -177,6 +177,11 @@ ZoneServer::ZoneServer(const char* name) {
lifetime_client_count = 0; lifetime_client_count = 0;
groupraidMinLevel = 0;
groupraidMaxLevel = 0;
groupraidAvgLevel = 0;
groupraidFirstLevel = 0;
is_initialized = false; is_initialized = false;
} }

View File

@ -1036,6 +1036,11 @@ private:
mutable std::shared_mutex MIgnoredWidgets; mutable std::shared_mutex MIgnoredWidgets;
std::map<int32, bool> ignored_widgets; std::map<int32, bool> ignored_widgets;
Map* default_zone_map; // this is the map that npcs, ground spawns, so on use. May not be the same as the clients! Map* default_zone_map; // this is the map that npcs, ground spawns, so on use. May not be the same as the clients!
int32 groupraidMinLevel;
int32 groupraidMaxLevel;
int32 groupraidAvgLevel;
int32 groupraidFirstLevel;
public: public:
Spawn* GetSpawn(int32 id); Spawn* GetSpawn(int32 id);
@ -1168,6 +1173,29 @@ public:
void SendStateCommand(Spawn* spawn, int32 state); void SendStateCommand(Spawn* spawn, int32 state);
int32 getGroupraidMinLevel() const {
return groupraidMinLevel;
}
int32 getGroupraidMaxLevel() const {
return groupraidMaxLevel;
}
int32 getGroupraidAvgLevel() const {
return groupraidAvgLevel;
}
int32 getGroupraidFirstLevel() const {
return groupraidFirstLevel;
}
void setGroupRaidLevels(int32 min_level, int32 max_level, int32 avg_level, int32 first_level) {
groupraidMinLevel = min_level;
groupraidMaxLevel = max_level;
groupraidAvgLevel = avg_level;
groupraidFirstLevel = first_level;
}
int32 lifetime_client_count; int32 lifetime_client_count;
int32 incoming_clients; int32 incoming_clients;
}; };