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);
ret = true;
}
} }
else { else {
peer_manager.sendPrimaryCreateGuildRequest(std::string(guild_name), ""); peer_manager.sendPrimaryCreateGuildRequest(std::string(guild_name), "", prompted_dialog, npc->GetID());
return;
} }
ret = true;
} }
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

@ -1,21 +1,21 @@
/* /*
EQ2Emulator: Everquest II Server Emulator EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net) Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator. This file is part of EQ2Emulator.
EQ2Emulator is free software: you can redistribute it and/or modify EQ2Emulator is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
EQ2Emulator is distributed in the hope that it will be useful, EQ2Emulator is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>. along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef CLIENT_H #ifndef CLIENT_H
#define CLIENT_H #define CLIENT_H
@ -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;
@ -107,7 +113,7 @@ struct MailWindow {
int32 coin_silver; int32 coin_silver;
int32 coin_gold; int32 coin_gold;
int32 coin_plat; int32 coin_plat;
Item* item; Item* item;
int32 char_item_id; int32 char_item_id;
int32 stack; int32 stack;
}; };
@ -150,22 +156,101 @@ 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);
~Client(); ~Client();
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);
@ -208,14 +293,14 @@ public:
bool BankWithdrawalNoBanker(int64 amount); bool BankWithdrawalNoBanker(int64 amount);
bool BankHasCoin(int64 amount); bool BankHasCoin(int64 amount);
void BankDeposit(int64 amount); void BankDeposit(int64 amount);
Spawn* GetBanker(); Spawn* GetBanker();
void SetBanker(Spawn* in_banker); void SetBanker(Spawn* in_banker);
bool AddItem(int32 item_id, int16 quantity = 0, AddItemType type = AddItemType::NOT_SET); bool AddItem(int32 item_id, int16 quantity = 0, AddItemType type = AddItemType::NOT_SET);
bool AddItem(Item* item, bool* item_deleted = 0, AddItemType type = AddItemType::NOT_SET); bool AddItem(Item* item, bool* item_deleted = 0, AddItemType type = AddItemType::NOT_SET);
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,46 +320,46 @@ 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; }
inline int32 WaitingForBootup() { return pwaitingforbootup; } inline int32 WaitingForBootup() { return pwaitingforbootup; }
inline int32 GetCharacterID() { return character_id; } inline int32 GetCharacterID() { return character_id; }
inline int32 GetAccountID() { return account_id; } inline int32 GetAccountID() { return account_id; }
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,12 +376,12 @@ 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);
Quest* GetPendingQuestAcceptance(int32 item_id); Quest* GetPendingQuestAcceptance(int32 item_id);
void DisplayConversation(int32 conversation_id, int32 spawn_id, vector<ConversationOption>* conversations, const char* text, const char* mp3, int32 key1, int32 key2, int8 language = 0, int8 can_close = 1); void DisplayConversation(int32 conversation_id, int32 spawn_id, vector<ConversationOption>* conversations, const char* text, const char* mp3, int32 key1, int32 key2, int8 language = 0, int8 can_close = 1);
void DisplayConversation(Item* item, vector<ConversationOption>* conversations, const char* text, int8 type, const char* mp3 = 0, int32 key1 = 0, int32 key2 = 0, int8 language = 0, int8 can_close = 1); void DisplayConversation(Item* item, vector<ConversationOption>* conversations, const char* text, int8 type, const char* mp3 = 0, int32 key1 = 0, int32 key2 = 0, int8 language = 0, int8 can_close = 1);
void DisplayConversation(Spawn* src, int8 type, vector<ConversationOption>* conversations, const char* text, const char* mp3 = 0, int32 key1 = 0, int32 key2 = 0, int8 language = 0, int8 can_close = 1); void DisplayConversation(Spawn* src, int8 type, vector<ConversationOption>* conversations, const char* text, const char* mp3 = 0, int32 key1 = 0, int32 key2 = 0, int8 language = 0, int8 can_close = 1);
@ -306,16 +391,16 @@ public:
void AddCombineSpawn(Spawn* spawn); void AddCombineSpawn(Spawn* spawn);
void RemoveCombineSpawn(Spawn* spawn); void RemoveCombineSpawn(Spawn* spawn);
void SaveCombineSpawns(const char* name = 0); void SaveCombineSpawns(const char* name = 0);
Spawn* GetCombineSpawn(); Spawn* GetCombineSpawn();
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();
void SetMailTransaction(Spawn* spawn); void SetMailTransaction(Spawn* spawn);
Spawn* GetMailTransaction(); Spawn* GetMailTransaction();
void PlaySound(const char* name); void PlaySound(const char* name);
void SendBuyMerchantList(bool sell = false); void SendBuyMerchantList(bool sell = false);
void SendSellMerchantList(bool sell = false); void SendSellMerchantList(bool sell = false);
@ -332,7 +417,7 @@ public:
void RepairItem(int32 item_id); void RepairItem(int32 item_id);
void RepairAllItems(); void RepairAllItems();
void AddBuyBack(int32 unique_id, int32 item_id, int16 quantity, int32 price, bool save_needed = true); void AddBuyBack(int32 unique_id, int32 item_id, int16 quantity, int32 price, bool save_needed = true);
deque<BuyBackItem*>* GetBuyBacks(); deque<BuyBackItem*>* GetBuyBacks();
vector<Item*>* GetRepairableItems(); vector<Item*>* GetRepairableItems();
vector<Item*>* GetItemsByEffectType(ItemEffectType type, ItemEffectType secondary_effect = NO_EFFECT_TYPE); vector<Item*>* GetItemsByEffectType(ItemEffectType type, ItemEffectType secondary_effect = NO_EFFECT_TYPE);
void SendMailList(); void SendMailList();
@ -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();
@ -622,16 +710,16 @@ private:
vector<Item*>* search_items; vector<Item*>* search_items;
int32 waypoint_id = 0; int32 waypoint_id = 0;
map<string, WaypointInfo> waypoints; map<string, WaypointInfo> waypoints;
Spawn* transport_spawn; Spawn* transport_spawn;
Mutex MBuyBack; Mutex MBuyBack;
deque<BuyBackItem*> buy_back_items; deque<BuyBackItem*> buy_back_items;
Spawn* merchant_transaction; Spawn* merchant_transaction;
Spawn* mail_transaction; Spawn* mail_transaction;
mutable std::shared_mutex MPendingQuestAccept; mutable std::shared_mutex MPendingQuestAccept;
vector<int32> pending_quest_accept; vector<int32> pending_quest_accept;
bool lua_debug; bool lua_debug;
bool should_target; bool should_target;
Spawn* combine_spawn; Spawn* combine_spawn;
int8 num_active_failures; int8 num_active_failures;
int32 next_conversation_id; int32 next_conversation_id;
map<int32, int32> conversation_spawns; map<int32, int32> conversation_spawns;
@ -639,10 +727,10 @@ private:
mutable std::shared_mutex MConversation; mutable std::shared_mutex MConversation;
map<int32, map<int8, string> > conversation_map; map<int32, map<int8, string> > conversation_map;
int32 current_quest_id; int32 current_quest_id;
Spawn* banker; Spawn* banker;
map<int32, int32> sent_spell_details; map<int32, int32> sent_spell_details;
map<int32, bool> sent_item_details; map<int32, bool> sent_item_details;
Player* player; Player* player;
int16 version; int16 version;
int8 timestamp_flag; int8 timestamp_flag;
int32 ip; int32 ip;
@ -654,16 +742,16 @@ private:
char zone_name[64]; char zone_name[64];
int32 zoneID; int32 zoneID;
int32 instanceID; int32 instanceID;
Timer* autobootup_timeout; Timer* autobootup_timeout;
int32 pwaitingforbootup; int32 pwaitingforbootup;
int32 last_update_time; int32 last_update_time;
int32 last_saved_timestamp; int32 last_saved_timestamp;
Timer* CLE_keepalive_timer; Timer* CLE_keepalive_timer;
Timer* connect; Timer* connect;
Timer* camp_timer; Timer* camp_timer;
Timer* linkdead_timer; Timer* linkdead_timer;
bool connected; bool connected;
std::atomic<bool> ready_for_spawns; std::atomic<bool> ready_for_spawns;
std::atomic<bool> ready_for_updates; std::atomic<bool> ready_for_updates;
@ -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;
@ -766,7 +854,7 @@ public:
~ClientList(); ~ClientList();
bool ContainsStream(EQStream* eqs); bool ContainsStream(EQStream* eqs);
void Add(Client* client); void Add(Client* client);
Client* Get(int32 ip, int16 port); Client* Get(int32 ip, int16 port);
Client* FindByAccountID(int32 account_id); Client* FindByAccountID(int32 account_id);
Client* FindByName(char* charname); Client* FindByName(char* charname);
void Remove(Client* client, bool delete_data = false); void Remove(Client* client, bool delete_data = false);

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;
}; };