From c078257f7077f39e206d7ee873912a0b485dc50f Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Sun, 5 Sep 2021 20:29:21 -0500 Subject: [PATCH] [Quest API] Port DiaWind Plugin to Native Quest API (#1521) * Port DiaWind plugin to native Quest API * Add no logging aliases --- common/eqemu_logsys.h | 2 + common/eqemu_logsys_log_aliases.h | 16 ++ common/string_util.cpp | 45 ++++ common/string_util.h | 3 + zone/CMakeLists.txt | 2 + zone/client.h | 4 +- zone/client_packet.cpp | 8 + zone/dialogue_window.cpp | 338 +++++++++++++++++++++++++ zone/dialogue_window.h | 394 ++++++++++++++++++++++++++++++ zone/lua_client.cpp | 9 + zone/lua_client.h | 2 + zone/perl_client.cpp | 54 +++- zone/questmgr.cpp | 324 +----------------------- 13 files changed, 874 insertions(+), 327 deletions(-) create mode 100644 zone/dialogue_window.cpp create mode 100644 zone/dialogue_window.h diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index c5ced8925..6990764a4 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -124,6 +124,7 @@ namespace Logs { Scheduler, Cheat, ClientList, + DiaWind, MaxCategoryID /* Don't Remove this */ }; @@ -206,6 +207,7 @@ namespace Logs { "Scheduler", "Cheat", "ClientList", + "DialogueWindow", }; } diff --git a/common/eqemu_logsys_log_aliases.h b/common/eqemu_logsys_log_aliases.h index c5f7cd422..10358b572 100644 --- a/common/eqemu_logsys_log_aliases.h +++ b/common/eqemu_logsys_log_aliases.h @@ -666,6 +666,16 @@ OutF(LogSys, Logs::Detail, Logs::ClientList, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) +#define LogDiaWind(message, ...) do {\ + if (LogSys.log_settings[Logs::DiaWind].is_category_enabled == 1)\ + OutF(LogSys, Logs::General, Logs::DiaWind, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogDiaWindDetail(message, ...) do {\ + if (LogSys.log_settings[Logs::DiaWind].is_category_enabled == 1)\ + OutF(LogSys, Logs::Detail, Logs::DiaWind, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + #define Log(debug_level, log_category, message, ...) do {\ if (LogSys.log_settings[log_category].is_category_enabled == 1)\ LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ @@ -1050,6 +1060,12 @@ #define LogClientListDetail(message, ...) do {\ } while (0) +#define LogDiaWind(message, ...) do {\ +} while (0) + +#define LogDiaWindDetail(message, ...) do {\ +} while (0) + #define Log(debug_level, log_category, message, ...) do {\ } while (0) diff --git a/common/string_util.cpp b/common/string_util.cpp index 6c97dd076..65a35a0d7 100644 --- a/common/string_util.cpp +++ b/common/string_util.cpp @@ -116,6 +116,42 @@ std::vector SplitString(const std::string &str, const char delim) { return ret; } +// this one takes delimiter length into consideration +std::vector split_string(std::string s, std::string delimiter) +{ + size_t pos_start = 0, pos_end, delim_len = delimiter.length(); + std::string token; + std::vector res; + + while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) { + token = s.substr(pos_start, pos_end - pos_start); + pos_start = pos_end + delim_len; + res.push_back(token); + } + + res.push_back(s.substr(pos_start)); + return res; +} + +std::string get_between(const std::string &s, std::string start_delim, std::string stop_delim) +{ + if (s.find(start_delim) == std::string::npos && s.find(stop_delim) == std::string::npos) { + return ""; + } + + auto first_split = split_string(s, start_delim); + if (!first_split.empty()) { + std::string remaining_block = first_split[1]; + auto second_split = split_string(remaining_block, stop_delim); + if (!second_split.empty()) { + std::string between = second_split[0]; + return between; + } + } + + return ""; +} + std::string::size_type search_deliminated_string(const std::string &haystack, const std::string &needle, const char deliminator) { // this shouldn't go out of bounds, even without obvious bounds checks @@ -280,7 +316,16 @@ void find_replace(std::string &string_subject, const std::string &search_string, string_subject.replace(start_pos, search_string.length(), replace_string); start_pos += replace_string.length(); } +} +std::string replace_string(std::string subject, const std::string &search, const std::string &replace) +{ + size_t pos = 0; + while ((pos = subject.find(search, pos)) != std::string::npos) { + subject.replace(pos, search.length(), replace); + pos += replace.length(); + } + return subject; } void ParseAccountString(const std::string &s, std::string &account, std::string &loginserver) diff --git a/common/string_util.h b/common/string_util.h index 8c4a6878f..b6718172a 100644 --- a/common/string_util.h +++ b/common/string_util.h @@ -177,6 +177,8 @@ std::vector join_tuple(const std::string &glue, const std::pair SplitString(const std::string &s, const char delim = ','); +std::vector split_string(std::string s, std::string delimiter); +std::string get_between(const std::string &s, std::string start_delim, std::string stop_delim); std::string::size_type search_deliminated_string(const std::string &haystack, const std::string &needle, const char deliminator = ','); std::string EscapeString(const char *src, size_t sz); std::string EscapeString(const std::string &s); @@ -185,6 +187,7 @@ void ToLowerString(std::string &s); void ToUpperString(std::string &s); std::string JoinString(const std::vector& ar, const std::string &delim); void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string); +std::string replace_string(std::string subject, const std::string &search, const std::string &replace); void ParseAccountString(const std::string &s, std::string &account, std::string &loginserver); //const char based diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 909c88e77..184b7d318 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -23,6 +23,7 @@ SET(zone_sources corpse.cpp data_bucket.cpp doors.cpp + dialogue_window.cpp dynamic_zone.cpp effects.cpp embparser.cpp @@ -182,6 +183,7 @@ SET(zone_headers corpse.h data_bucket.h doors.h + dialogue_window.h dynamic_zone.h embparser.h embperl.h diff --git a/zone/client.h b/zone/client.h index dcc177e20..cb39637a1 100644 --- a/zone/client.h +++ b/zone/client.h @@ -203,7 +203,9 @@ enum eInnateSkill { InnateDisabled = 255 }; -const uint32 POPUPID_UPDATE_SHOWSTATSWINDOW = 1000000; +const std::string DIAWIND_RESPONSE_KEY = "diawind_npcresponse"; +const uint32 POPUPID_DIAWIND = 999; +const uint32 POPUPID_UPDATE_SHOWSTATSWINDOW = 1000000; struct ClientReward { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 1365dbd56..dd22111fa 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -11132,6 +11132,7 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app) /** * Handle any EQEmu defined popup Ids first */ + std::string response; switch (popup_response->popupid) { case POPUPID_UPDATE_SHOWSTATSWINDOW: if (GetTarget() && GetTarget()->IsClient()) { @@ -11143,6 +11144,13 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app) return; break; + case POPUPID_DIAWIND: + response = GetEntityVariable(DIAWIND_RESPONSE_KEY.c_str()); + if (!response.empty()) { + ChannelMessageReceived(8, 0, 100, response.c_str()); + } + break; + case EQ::popupresponse::MOB_INFO_DISMISS: SetDisplayMobInfoWindow(false); Message(Chat::Yellow, "[DevTools] Window snoozed in this zone..."); diff --git a/zone/dialogue_window.cpp b/zone/dialogue_window.cpp new file mode 100644 index 000000000..99c8944da --- /dev/null +++ b/zone/dialogue_window.cpp @@ -0,0 +1,338 @@ +#include "dialogue_window.h" + +void DialogueWindow::Render(Client *c, std::string markdown) +{ + std::string output = markdown; + + // this is the NPC that the client is interacting with if there is dialogue going on + Mob *target; + if (c->GetTarget()) { + target = c->GetTarget(); + } + + // zero this out + c->SetEntityVariable(DIAWIND_RESPONSE_KEY.c_str(), ""); + + // simple find and replace for the markdown + find_replace(output, "~", ""); + find_replace(output, "{y}", ""); + find_replace(output, "{lb}", ""); + find_replace(output, "{r}", ""); + find_replace(output, "{g}", ""); + find_replace(output, "{gold}", ""); + find_replace(output, "{orange}", ""); + find_replace(output, "{gray}", ""); + find_replace(output, "{tan}", ""); + find_replace(output, "{bullet}", "•"); + find_replace(output, "{name}", "$name"); + find_replace(output, "{linebreak}", "--------------------------------------------------------------------"); + find_replace(output, "{rowpad}", R"({tdpad}<"td>{tdpad}<"td><"tr>)"); + find_replace(output, "{tdpad}", "----------------------"); + find_replace(output, "{in}", "        "); + + // mysterious voice + bool render_mysterious_voice = false; + if (markdown.find("mysterious") != std::string::npos) { + render_mysterious_voice = true; + LogDiaWind("Client [{}] Rendering mysterious voice", c->GetCleanName()); + find_replace(output, "mysterious", ""); + } + + // noquotes + bool render_noquotes = false; + if (markdown.find("noquotes") != std::string::npos) { + render_noquotes = true; + LogDiaWind("Client [{}] Rendering noquotes", c->GetCleanName()); + find_replace(output, "noquotes", ""); + } + + // nobracket + bool render_nobracket = false; + if (markdown.find("nobracket") != std::string::npos) { + render_nobracket = true; + LogDiaWind("Client [{}] Rendering nobracket", c->GetCleanName()); + find_replace(output, "nobracket", ""); + } + + // animations + std::string animation = get_between(output, "+", "+"); + if (!animation.empty()) { + LogDiaWind("Client [{}] Animation is not empty, contents are [{}]", c->GetCleanName(), animation); + find_replace(output, fmt::format("+{}+", animation), ""); + + // we treat the animation field differently if it is a number + if (StringIsNumber(animation)) { + LogDiaWindDetail("Client [{}] Animation is a number, firing animation [{}]", c->GetCleanName(), animation); + target->DoAnim(std::stoi(animation)); + } + else { + for (auto &a: animations) { + if (a.first.find(str_tolower(animation)) != std::string::npos) { + LogDiaWindDetail( + "Client [{}] Animation is a string, firing animation [{}] [{}]", + c->GetCleanName(), + a.second, + a.first + ); + target->DoAnim(a.second); + } + } + } + } + + // window expire time + std::string expire_time = get_between(output, "=", "="); + uint32 window_expire_seconds = 0; + if (!expire_time.empty()) { + LogDiaWind("Client [{}] Window expire time is not empty, contents are [{}]", c->GetCleanName(), expire_time); + find_replace(output, fmt::format("={}=", expire_time), ""); + + // we treat the animation field differently if it is a number + if (StringIsNumber(expire_time)) { + LogDiaWindDetail( + "Client [{}] Window expire time is a number, setting expiration to [{}]", + c->GetCleanName(), + expire_time + ); + window_expire_seconds = std::stoi(expire_time); + } + } + + uint32 popup_id = POPUPID_DIAWIND; + uint32 negative_id = 0; + char *button_name_0 = nullptr; + char *button_name_1 = nullptr; + uint32 sound_controls = 0; + + // window type + std::string wintype; + if (markdown.find("wintype") != std::string::npos) { + LogDiaWind("Client [{}] Rendering wintype option", c->GetCleanName()); + + auto first_split = split_string(output, "wintype:"); + if (!first_split.empty()) { + + // assumed that there is more after the wintype declaration + // wintype:0 +animation+ etc. + auto second_split = split_string(first_split[1], " "); + if (!second_split.empty()) { + wintype = second_split[0]; + LogDiaWindDetail("Client [{}] Rendering wintype option wintype [{}]", c->GetCleanName(), wintype); + } + + // if we're dealing with a string that is at the end + // example wintype:0"); + if (first_split[1].length() == 1) { + wintype = first_split[1]; + LogDiaWindDetail( + "Client [{}] Rendering wintype (end) option wintype [{}]", + c->GetCleanName(), + wintype + ); + } + + find_replace(output, fmt::format("wintype:{}", wintype), ""); + } + } + + // popupid + std::string popupid; + if (markdown.find("popupid") != std::string::npos) { + LogDiaWind("Client [{}] Rendering popupid option", c->GetCleanName()); + + auto first_split = split_string(output, "popupid:"); + if (!first_split.empty()) { + + // assumed that there is more after the popupid declaration + // popupid:0 +animation+ etc. + auto second_split = split_string(first_split[1], " "); + if (!second_split.empty()) { + popupid = second_split[0]; + LogDiaWindDetail("Client [{}] Rendering popupid option popupid [{}]", c->GetCleanName(), popupid); + } + + // if we're dealing with a string that is at the end + // example popupid:0"); + if (first_split[1].length() == 1) { + popupid = first_split[1]; + LogDiaWindDetail( + "Client [{}] Rendering popupid (end) option popupid [{}]", + c->GetCleanName(), + popupid + ); + } + + find_replace(output, fmt::format("popupid:{}", popupid), ""); + + // set the popup id + if (!popupid.empty()) { + popup_id = (StringIsNumber(popupid) ? std::atoi(popupid.c_str()) : 0); + } + } + } + + // bracket responses + std::vector responses; + std::vector bracket_responses; + if (markdown.find('[') != std::string::npos && markdown.find(']') != std::string::npos) { + // copy + std::string content = output; + + // while brackets still exist + int response_index = 0; + while (content.find('[') != std::string::npos && content.find(']') != std::string::npos) { + std::string bracket_message = get_between(content, "[", "]"); + + LogDiaWindDetail( + "Client [{}] Rendering responses ({}) [{}]", + c->GetCleanName(), + response_index, + bracket_message + ); + + // pop message onto responses + responses.emplace_back(bracket_message); + + // pop the response off of the message + find_replace(content, fmt::format("[{}]", bracket_message), ""); + + response_index++; + } + } + + // build saylinks + if (responses.size() > 1) { + for (auto &r: responses) { + bracket_responses.emplace_back( + fmt::format("[{}]", EQ::SayLinkEngine::GenerateQuestSaylink(r, false, r)) + ); + } + } + + // handle silent prompts from the [> silent syntax + std::string silent_message; + if (responses.empty() && markdown.find('[') != std::string::npos && markdown.find('>') != std::string::npos) { + silent_message = get_between(output, "[", ">"); + + // temporary and used during the response + c->SetEntityVariable(DIAWIND_RESPONSE_KEY.c_str(), silent_message.c_str()); + + // pop the silent message off + find_replace(output, fmt::format("[{}>", silent_message), ""); + } + else if (!responses.empty()) { + // handle silent prompts from the single respond bracket syntax [] + silent_message = responses[0]; + + // temporary and used during the response + c->SetEntityVariable(DIAWIND_RESPONSE_KEY.c_str(), silent_message.c_str()); + + // pop the silent message off + find_replace(output, fmt::format("[{}]", silent_message), ""); + } + + // strip brackets + if (render_nobracket) { + find_replace(output, "[", ""); + find_replace(output, "]", ""); + } + + // render title + std::string title; + std::string speaking; + if (target) { + speaking = fmt::format("{} says", target->GetCleanName()); + } + + if (render_mysterious_voice) { + speaking = "A Mysterious Voice says"; + } + + title = fmt::format("Dialogue [{}]", speaking); + + // render quotes + std::string quote_string = "'"; + if (render_noquotes) { + quote_string = ""; + } + + // click response + // window type response + uint32 window_type = (StringIsNumber(wintype) ? std::atoi(wintype.c_str()) : 0); + std::string click_response_button = (window_type == 1 ? "Yes" : "OK"); + std::string click_response = fmt::format( + "Click [{}] to continue...", + click_response_button + ); + + // different response when a timer is set + if (window_expire_seconds > 0) { + click_response = fmt::format( + "This message will disappear in {} second(s)...", + window_expire_seconds + ); + } + + // respond with silent message + if (!silent_message.empty()) { + click_response = fmt::format( + "Click [{}] to respond with [{}]...", + click_response_button, + silent_message + ); + } + + // post processing of color markdowns + // {spring_green_1} = + if (markdown.find('{') != std::string::npos && markdown.find('}') != std::string::npos) { + + // while brackets still exist + int tag_index = 0; + while (output.find('{') != std::string::npos && output.find('}') != std::string::npos) { + std::string color_tag = get_between(output, "{", "}"); + + LogDiaWindDetail( + "Client [{}] Rendering color tags ({}) [{}]", + c->GetCleanName(), + tag_index, + color_tag + ); + + std::string html_tag; + for (const auto& color : html_colors) { + if (color_tag.find(color.first) != std::string::npos) { + // build html tag + html_tag = fmt::format("", color.second); + // pop the response off of the message + find_replace(output, fmt::format("{{{}}}", color.first), html_tag); + } + } + + tag_index++; + } + } + + + // build the final output string + std::string final_output; + final_output = fmt::format("{}{}{}

{}", quote_string, output, quote_string, click_response); + + // send popup + c->SendFullPopup( + title.c_str(), + final_output.c_str(), + popup_id, + negative_id, + window_type, + window_expire_seconds, + button_name_0, + button_name_1, + sound_controls + ); + + // if multiple brackets are presented, send message + if (!bracket_responses.empty()) { + c->Message(Chat::White, " --- Select Response from Options --- "); + c->Message(Chat::White, implode(" ", bracket_responses).c_str()); + } +} diff --git a/zone/dialogue_window.h b/zone/dialogue_window.h new file mode 100644 index 000000000..7b0137550 --- /dev/null +++ b/zone/dialogue_window.h @@ -0,0 +1,394 @@ +#ifndef EQEMU_DIALOGUE_WINDOW_H +#define EQEMU_DIALOGUE_WINDOW_H + + +#include +#include "client.h" + +static const std::map html_colors = { + {"black", "#000000"}, + {"brown", "#804000"}, + {"burgundy", "#800000"}, + {"cadet_blue", "#77BFC7"}, + {"cadet_blue_1", "#4C787E"}, + {"chartreuse", "#8AFB17"}, + {"chartreuse_1", "#7FE817"}, + {"chartreuse_2", "#6CC417"}, + {"chartreuse_3", "#437C17"}, + {"chocolate", "#C85A17"}, + {"coral", "#F76541"}, + {"coral_1", "#E55B3C"}, + {"coral_2", "#C34A2C"}, + {"cornflower_blue", "#151B8D"}, + {"cyan", "#00FFFF"}, + {"cyan_1", "#57FEFF"}, + {"cyan_2", "#50EBEC"}, + {"cyan_3", "#46C7C7"}, + {"cyan_4", "#307D7E"}, + {"dark_blue", "#0000A0"}, + {"dark_goldenrod", "#AF7817"}, + {"dark_goldenrod_1", "#FBB117"}, + {"dark_goldenrod_2", "#E8A317"}, + {"dark_goldenrod_3", "#C58917"}, + {"dark_goldenrod_4", "#7F5217"}, + {"dark_green", "#254117"}, + {"dark_grey", "#808080"}, + {"dark_olive_green", "#CCFB5D"}, + {"dark_olive_green_2", "#BCE954"}, + {"dark_olive_green_3", "#A0C544"}, + {"dark_olive_green_4", "#667C26"}, + {"dark_orange", "#F88017"}, + {"dark_orange_1", "#F87217"}, + {"dark_orange_2", "#E56717"}, + {"dark_orange_3", "#7E3117"}, + {"dark_orange_3", "#C35617"}, + {"dark_orchid", "#7D1B7E"}, + {"dark_orchid_1", "#B041FF"}, + {"dark_orchid_2", "#A23BEC"}, + {"dark_orchid_3", "#8B31C7"}, + {"dark_orchid_4", "#571B7e"}, + {"dark_purple", "#800080"}, + {"dark_salmon", "#E18B6B"}, + {"dark_sea_green", "#8BB381"}, + {"dark_sea_green_1", "#C3FDB8"}, + {"dark_sea_green_2", "#B5EAAA"}, + {"dark_sea_green_3", "#99C68E"}, + {"dark_sea_green_4", "#617C58"}, + {"dark_slate_blue", "#2B3856"}, + {"dark_slate_gray", "#25383C"}, + {"dark_slate_gray_1", "#9AFEFF"}, + {"dark_slate_gray_2", "#8EEBEC"}, + {"dark_slate_gray_3", "#78c7c7"}, + {"dark_slate_gray_4", "#4C7D7E"}, + {"dark_turquoise", "#3B9C9C"}, + {"dark_violet", "#842DCE"}, + {"deep_pink", "#F52887"}, + {"deep_pink_1", "#E4287C"}, + {"deep_pink_2", "#C12267"}, + {"deep_pink_3", "#7D053F"}, + {"deep_sky_blue", "#3BB9FF"}, + {"deep_sky_blue_1", "#38ACEC"}, + {"deep_sky_blue_2", "#3090C7"}, + {"deep_sky_blue_3", "#25587E"}, + {"dim_gray", "#463E41"}, + {"dodger_blue", "#1589FF"}, + {"dodger_blue_1", "#157DEC"}, + {"dodger_blue_2", "#1569C7"}, + {"dodger_blue_3", "#153E7E"}, + {"firebrick", "#800517"}, + {"firebrick_1", "#F62817"}, + {"firebrick_2", "#E42217"}, + {"firebrick_3", "#C11B17"}, + {"forest_green", "#4E9258"}, + {"forest_green_1", "#808000"}, + {"gold", "#D4A017"}, + {"gold_1", "#FDD017"}, + {"gold_2", "#EAC117"}, + {"gold_3", "#C7A317"}, + {"gold_4", "#806517"}, + {"goldenrod", "#EDDA74"}, + {"goldenrod_1", "#FBB917"}, + {"goldenrod_2", "#E9AB17"}, + {"goldenrod_3", "#C68E17"}, + {"goldenrod_4", "#805817"}, + {"grass_green", "#408080"}, + {"gray", "#736F6E"}, + {"gray_1", "#150517"}, + {"gray_2", "#250517"}, + {"gray_3", "#2B1B17"}, + {"gray_4", "#302217"}, + {"gray_5", "#302226"}, + {"gray_6", "#342826"}, + {"gray_7", "#34282C"}, + {"gray_8", "#382D2C"}, + {"gray_9", "#3b3131"}, + {"gray_10", "#3E3535"}, + {"gray_11", "#413839"}, + {"gray_12", "#41383C"}, + {"gray_13", "#463E3F"}, + {"gray_14", "#4A4344"}, + {"gray_15", "#4C4646"}, + {"gray_16", "#4E4848"}, + {"gray_17", "#504A4B"}, + {"gray_18", "#544E4F"}, + {"gray_19", "#565051"}, + {"gray_19", "#595454"}, + {"gray_20", "#5C5858"}, + {"gray_21", "#5F5A59"}, + {"gray_22", "#625D5D"}, + {"gray_23", "#646060"}, + {"gray_24", "#666362"}, + {"gray_25", "#696565"}, + {"gray_26", "#6D6968"}, + {"gray_27", "#6E6A6B"}, + {"gray_28", "#726E6D"}, + {"gray_29", "#747170"}, + {"green", "#00FF00"}, + {"green_1", "#5FFB17"}, + {"green_2", "#59E817"}, + {"green_3", "#4CC417"}, + {"green_4", "#347C17"}, + {"green_yellow", "#B1FB17"}, + {"hot_pink", "#F660AB"}, + {"hot_pink_1", "#F665AB"}, + {"hot_pink_2", "#E45E9D"}, + {"hot_pink_3", "#C25283"}, + {"hot_pink_4", "#7D2252"}, + {"indian_red", "#F75D59"}, + {"indian_red_2", "#E55451"}, + {"indian_red_3", "#C24641"}, + {"indian_red_4", "#7E2217"}, + {"khaki", "#ADA96E"}, + {"khaki_1", "#FFF380"}, + {"khaki_2", "#EDE275"}, + {"khaki_3", "#C9BE62"}, + {"khaki_4", "#827839"}, + {"lavender", "#E3E4FA"}, + {"lavender_blush", "#FDEEF4"}, + {"lavender_blush_1", "#EBDDE2"}, + {"lavender_blush_2", "#C8BBBE"}, + {"lavender_blush_3", "#817679"}, + {"lawn_green", "#87F717"}, + {"lemon_chiffon", "#FFF8C6"}, + {"lemon_chiffon_1", "#ECE5B6"}, + {"lemon_chiffon_2", "#C9C299"}, + {"lemon_chiffon_3", "#827B60"}, + {"light_blue", "#0000FF"}, + {"light_blue_1", "#ADDFFF"}, + {"light_blue_2", "#BDEDFF"}, + {"light_blue_3", "#AFDCEC"}, + {"light_blue_4", "#95B9C7"}, + {"light_blue_5", "#5E767E"}, + {"light_coral", "#E77471"}, + {"light_cyan", "#E0FFFF"}, + {"light_cyan_1", "#CFECEC"}, + {"light_cyan_2", "#AFC7C7"}, + {"light_cyan_3", "#717D7D"}, + {"light_golden", "#ECD672"}, + {"light_goldenrod", "#ECD872"}, + {"light_goldenrod_1", "#FFE87C"}, + {"light_goldenrod_2", "#C8B560"}, + {"light_goldenrod_3", "#817339"}, + {"light_goldenrod_yellow", "#FAF8CC"}, + {"light_grey", "#C0C0C0"}, + {"light_pink", "#FAAFBA"}, + {"light_pink_1", "#F9A7B0"}, + {"light_pink_2", "#E799A3"}, + {"light_pink_3", "#C48189"}, + {"light_pink_4", "#7F4E52"}, + {"light_purple", "#FF0080"}, + {"light_salmon", "#F9966B"}, + {"light_salmon_1", "#E78A61"}, + {"light_salmon_2", "#C47451"}, + {"light_salmon_3", "#7F462C"}, + {"light_sea_green", "#3EA99F"}, + {"light_sky_blue", "#82CAFA"}, + {"light_sky_blue_1", "#A0CFEC"}, + {"light_sky_blue_2", "#87AFC7"}, + {"light_sky_blue_3", "#566D7E"}, + {"light_slate_blue", "#736AFF"}, + {"light_slate_gray", "#6D7B8D"}, + {"light_steel_blue", "#728FCE"}, + {"light_steel_blue_1", "#C6DEFF"}, + {"light_steel_blue_2", "#B7CEEC"}, + {"light_steel_blue_3", "#646D7E"}, + {"lime_green", "#41A317"}, + {"magenta", "#FF00FF"}, + {"magenta_1", "#F433FF"}, + {"magenta_2", "#E238EC"}, + {"magenta_3", "#C031C7"}, + {"maroon", "#810541"}, + {"maroon_1", "#F535AA"}, + {"maroon_2", "#E3319D"}, + {"maroon_3", "#C12283"}, + {"maroon_4", "#7D0552"}, + {"medium_aquamarine", "#348781"}, + {"medium_forest_green", "#347235"}, + {"medium_orchid", "#B048B5"}, + {"medium_orchid_1", "#D462FF"}, + {"medium_orchid_2", "#C45AEC"}, + {"medium_orchid_3", "#A74AC7"}, + {"medium_orchid_4", "#6A287E"}, + {"medium_purple", "#8467D7"}, + {"medium_purple_1", "#9E7BFF"}, + {"medium_purple_2", "#9172EC"}, + {"medium_purple_3", "#7A5DC7"}, + {"medium_purple_4", "#4E387E"}, + {"medium_sea_green", "#306754"}, + {"medium_slate_blue", "#5E5A80"}, + {"medium_spring_green", "#348017"}, + {"medium_turquoise", "#48CCCD"}, + {"medium_violet_red", "#CA226B"}, + {"midnight_blue", "#151B54"}, + {"orange", "#FF8040"}, + {"pale_turquoise", "#92C7C7"}, + {"pale_turquoise_1", "#5E7D7E"}, + {"pale_violet_red", "#D16587"}, + {"pale_violet_red_1", "#F778A1"}, + {"pale_violet_red_2", "#E56E94"}, + {"pale_violet_red_3", "#C25A7C"}, + {"pale_violet_red_4", "#7E354D"}, + {"pastel_green", "#00FF00"}, + {"pink", "#FAAFBE"}, + {"pink_1", "#FF00FF"}, + {"pink_2", "#E7A1B0"}, + {"pink_3", "#C48793"}, + {"pink_4", "#7F525D"}, + {"plum", "#B93B8F"}, + {"plum_1", "#F9B7FF"}, + {"plum_2", "#E6A9EC"}, + {"plum_3", "#C38EC7"}, + {"plum_4", "#7E587E"}, + {"purple", "#8E35EF"}, + {"purple_1", "#893BFF"}, + {"purple_2", "#7F38EC"}, + {"purple_3", "#6C2DC7"}, + {"purple_4", "#461B7E"}, + {"red", "#FF0000"}, + {"red_1", "#F62217"}, + {"red_2", "#E41B17"}, + {"rosy_brown", "#B38481"}, + {"rosy_brown_1", "#FBBBB9"}, + {"rosy_brown_2", "#E8ADAA"}, + {"rosy_brown_3", "#C5908E"}, + {"rosy_brown_4", "#7F5A58"}, + {"royal_blue", "#2B60DE"}, + {"royal_blue_1", "#306EFF"}, + {"royal_blue_2", "#2B65EC"}, + {"royal_blue_3", "#2554C7"}, + {"royal_blue_4", "#15317E"}, + {"salmon_1", "#F88158"}, + {"salmon_2", "#E67451"}, + {"salmon_3", "#C36241"}, + {"salmon_4", "#7E3817"}, + {"sandy_brown", "#EE9A4D"}, + {"sea_green", "#4E8975"}, + {"sea_green_1", "#6AFB92"}, + {"sea_green_2", "#64E986"}, + {"sea_green_3", "#54C571"}, + {"sea_green_4", "#387C44"}, + {"sienna", "#8A4117"}, + {"sienna_1", "#F87431"}, + {"sienna_2", "#E66C2C"}, + {"sienna_3", "#C35817"}, + {"sienna_4", "#7E3517"}, + {"sky_blue", "#82CAFF"}, + {"sky_blue_1", "#6698FF"}, + {"sky_blue_2", "#79BAEC"}, + {"sky_blue_3", "#659EC7"}, + {"sky_blue_4", "#41627E"}, + {"slate_blue", "#357EC7"}, + {"slate_blue_1", "#737CA1"}, + {"slate_blue_2", "#6960EC"}, + {"slate_blue_3", "#342D7E"}, + {"slate_gray", "#657383"}, + {"slate_gray_1", "#C2DFFF"}, + {"slate_gray_2", "#B4CFEC"}, + {"slate_gray_3", "#98AFC7"}, + {"slate_gray_4", "#616D7E"}, + {"spring_green", "#4AA02C"}, + {"spring_green_1", "#5EFB6E"}, + {"spring_green_2", "#57E964"}, + {"spring_green_3", "#4CC552"}, + {"spring_green_4", "#347C2C"}, + {"steel_blue", "#4863A0"}, + {"steel_blue_1", "#5CB3FF"}, + {"steel_blue_2", "#56A5EC"}, + {"steel_blue_3", "#488AC7"}, + {"steel_blue_4", "#2B547E"}, + {"thistle", "#D2B9D3"}, + {"thistle_1", "#FCDFFF"}, + {"thistle_2", "#E9CFEC"}, + {"thistle_3", "#C6AEC7"}, + {"thistle_4", "#806D7E"}, + {"turquoise", "#00FFFF"}, + {"turquoise_1", "#43C6DB"}, + {"turquoise_2", "#52F3FF"}, + {"turquoise_3", "#4EE2EC"}, + {"turquoise_4", "#43BFC7"}, + {"violet", "#8D38C9"}, + {"violet_red", "#F6358A"}, + {"violet_red_1", "#F6358A"}, + {"violet_red_2", "#E4317F"}, + {"violet_red_3", "#C12869"}, + {"violet_red_4", "#7D0541"}, + {"white", "#FFFFFF"}, + {"yellow", "#FFFF00"}, + {"yellow_1", "#FFFC17"}, + {"yellow_green", "#52D017"} +}; + +const std::map animations = { + {"kick", 1}, + {"pierce", 2}, + {"2hslash", 3}, + {"2hblunt", 4}, + {"2hpierce", 4}, + {"throw", 5}, + {"offhand", 6}, + {"bash", 7}, + {"mainhand", 8}, + {"bow", 9}, + {"swim", 10}, + {"roundkick", 11}, + {"gethit", 12}, + {"gethit2", 13}, + {"falling", 14}, + {"drowning", 15}, + {"death", 16}, + {"standby", 17}, + {"standby2", 18}, + {"lunge", 19}, + {"jump", 20}, + {"falling2", 21}, + {"duckwalk", 22}, + {"ladderclimb", 23}, + {"crouch", 24}, + {"swim2", 25}, + {"idle", 26}, + {"cheer", 27}, + {"disgusted", 28}, + {"wave", 29}, + {"rude", 30}, + {"yawn", 31}, + {"movetoside", 33}, + {"iceslide", 35}, + {"kneel", 36}, + {"swim3", 37}, + {"sit", 38}, + {"cast", 42}, + {"cast2", 43}, + {"cast3", 44}, + {"flykick", 45}, + {"tigerclaw", 46}, + {"eaglestrike", 47}, + {"nodyes", 48}, + {"shakeno", 49}, + {"plead", 50}, + {"clap", 51}, + {"blush", 52}, + {"chuckle", 54}, + {"headtilt", 57}, + {"dance", 58}, + {"disagree", 59}, + {"glare", 60}, + {"peer", 61}, + {"kneel", 62}, + {"laugh", 63}, + {"point", 64}, + {"shrug", 65}, + {"handraise", 66}, + {"salute", 67}, + {"shiver", 68}, + {"tapfoot", 69}, + {"bowto", 70}, + }; + + +class DialogueWindow { +public: + static void Render(Client *c, std::string markdown); +}; + + +#endif //EQEMU_DIALOGUE_WINDOW_H diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 6dc02bd66..d758dc6c8 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -15,6 +15,7 @@ #include "lua_group.h" #include "lua_raid.h" #include "lua_packet.h" +#include "dialogue_window.h" #include "../common/expedition_lockout_timer.h" struct InventoryWhere { }; @@ -1824,6 +1825,11 @@ int Lua_Client::GetClientMaxLevel() { return self->GetClientMaxLevel(); } +void Lua_Client::DialogueWindow(std::string markdown) { + Lua_Safe_Call_Void(); + DialogueWindow::Render(self, std::move(markdown)); +} + DynamicZoneLocation GetDynamicZoneLocationFromTable(const luabind::object& lua_table) { DynamicZoneLocation zone_location; @@ -2496,6 +2502,9 @@ luabind::scope lua_register_client() { .def("GetAlternateCurrencyValue", (int(Lua_Client::*)(uint32))&Lua_Client::GetAlternateCurrencyValue) .def("SendWebLink", (void(Lua_Client::*)(const char *))&Lua_Client::SendWebLink) .def("HasSpellScribed", (bool(Lua_Client::*)(int))&Lua_Client::HasSpellScribed) + .def("DiaWind", (void(Lua_Client::*)(std::string))&Lua_Client::DialogueWindow) + .def("DialogueWindow", (void(Lua_Client::*)(std::string))&Lua_Client::DialogueWindow) + .def("SetAccountFlag", (void(Lua_Client::*)(std::string,std::string))&Lua_Client::SetAccountFlag) .def("SetAccountFlag", (void(Lua_Client::*)(std::string,std::string))&Lua_Client::SetAccountFlag) .def("GetAccountFlag", (std::string(Lua_Client::*)(std::string))&Lua_Client::GetAccountFlag) .def("GetGroup", (Lua_Group(Lua_Client::*)(void))&Lua_Client::GetGroup) diff --git a/zone/lua_client.h b/zone/lua_client.h index 3cc2a5c94..985939834 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -379,6 +379,8 @@ public: void SetClientMaxLevel(int value); int GetClientMaxLevel(); + void DialogueWindow(std::string markdown); + Lua_Expedition CreateExpedition(luabind::object expedition_info); Lua_Expedition CreateExpedition(std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players); Lua_Expedition CreateExpedition(std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players, bool disable_messages); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index e1aab97fc..8cb3d56e9 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -39,6 +39,7 @@ #include "client.h" #include "expedition.h" #include "titles.h" +#include "dialogue_window.h" #ifdef THIS /* this macro seems to leak out on some systems */ #undef THIS @@ -2111,11 +2112,11 @@ XS(XS_Client_IsStanding) XSRETURN(1); } -XS(XS_Client_Sit); +XS(XS_Client_Sit); XS(XS_Client_Sit) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: Client::Sit(THIS)"); + Perl_croak(aTHX_ "Usage: Client::Sit(THIS)"); { Client *THIS; VALIDATE_THIS_IS_CLIENT; @@ -5052,7 +5053,7 @@ XS(XS_Client_Fling) { VALIDATE_THIS_IS_CLIENT; if (items > 5) ignore_los = (bool) SvTRUE(ST(5)); - + if (items > 6) clipping = (bool) SvTRUE(ST(6)); @@ -5124,7 +5125,7 @@ XS(XS_Client_GetLearnableDisciplines) { min_level = (uint8)SvUV(ST(1)); if (items > 2) max_level = (uint8)SvUV(ST(2)); - + Client* THIS; VALIDATE_THIS_IS_CLIENT; auto learnable_disciplines = THIS->GetLearnableDisciplines(min_level, max_level); @@ -5146,7 +5147,7 @@ XS(XS_Client_GetLearnedDisciplines) { dXSARGS; if (items != 1) Perl_croak(aTHX_ "Usage: Client::GetLearnedDisciplines(THIS)"); - + Client* THIS; VALIDATE_THIS_IS_CLIENT; auto learned_disciplines = THIS->GetLearnedDisciplines(); @@ -5168,7 +5169,7 @@ XS(XS_Client_GetMemmedSpells) { dXSARGS; if (items != 1) Perl_croak(aTHX_ "Usage: Client::GetMemmedSpells(THIS)"); - + Client* THIS; VALIDATE_THIS_IS_CLIENT; auto memmed_spells = THIS->GetMemmedSpells(); @@ -5190,7 +5191,7 @@ XS(XS_Client_GetScribeableSpells) { dXSARGS; if (items < 1 || items > 3) Perl_croak(aTHX_ "Usage: Client::GetScribeableSpells(THIS, [uint8 min_level, uint8 max_level])"); - + uint8 min_level = 1; uint8 max_level = 0; if (items > 1) @@ -5219,7 +5220,7 @@ XS(XS_Client_GetScribedSpells) { dXSARGS; if (items != 1) Perl_croak(aTHX_ "Usage: Client::GetScribedSpells(THIS)"); - + Client* THIS; VALIDATE_THIS_IS_CLIENT; auto scribed_spells = THIS->GetScribedSpells(); @@ -5262,7 +5263,7 @@ XS(XS_Client_GetAAEXPModifier) { double aa_modifier = 1.0f; uint32 zone_id = (uint32)SvUV(ST(1)); dXSTARG; - VALIDATE_THIS_IS_CLIENT; + VALIDATE_THIS_IS_CLIENT; aa_modifier = THIS->GetAAEXPModifier(zone_id); XSprePUSH; PUSHn((double) aa_modifier); @@ -5432,6 +5433,39 @@ XS(XS_Client_RemoveItem) { XSRETURN_EMPTY; } +XS(XS_Client_DialogueWindow); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_DialogueWindow) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Client::DialogueWindow(THIS, string window_markdown)"); // @categories Script Utility + { + Client *THIS; + dXSTARG; + VALIDATE_THIS_IS_CLIENT; + + std::string window_markdown(SvPV_nolen(ST(1))); + DialogueWindow::Render(THIS, window_markdown); + } + XSRETURN_EMPTY; +} + +XS(XS_Client_DiaWind); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_DiaWind) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Client::DiaWind(THIS, string window_markdown)"); // @categories Script Utility + { + Client *THIS; + dXSTARG; + VALIDATE_THIS_IS_CLIENT; + + std::string window_markdown(SvPV_nolen(ST(1))); + DialogueWindow::Render(THIS, window_markdown); + + } + XSRETURN_EMPTY; +} + #ifdef __cplusplus extern "C" #endif @@ -5486,6 +5520,8 @@ XS(boot_Client) { newXSproto(strcpy(buf, "DecreaseByID"), XS_Client_DecreaseByID, file, "$$$"); newXSproto(strcpy(buf, "DeleteItemInInventory"), XS_Client_DeleteItemInInventory, file, "$$;$$"); newXSproto(strcpy(buf, "Disconnect"), XS_Client_Disconnect, file, "$"); + newXSproto(strcpy(buf, "DiaWind"), XS_Client_DiaWind, file, "$$"); + newXSproto(strcpy(buf, "DialogueWindow"), XS_Client_DialogueWindow, file, "$$"); newXSproto(strcpy(buf, "DropItem"), XS_Client_DropItem, file, "$$"); newXSproto(strcpy(buf, "Duck"), XS_Client_Duck, file, "$"); newXSproto(strcpy(buf, "DyeArmorBySlot"), XS_Client_DyeArmorBySlot, file, "$$$$$;$"); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 4a92b76f9..cac4c34a8 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -36,6 +36,7 @@ #include "zone.h" #include "zonedb.h" #include "zone_store.h" +#include "dialogue_window.h" #include #include @@ -1118,17 +1119,17 @@ uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) { int spells_learned = 0; if (spell_count > 0) { for (auto spell_id : spell_ids) { - if (book_slot == -1) { + if (book_slot == -1) { initiator->Message( Chat::Red, "Unable to scribe spell %s (%i) to Spell Book: Spell Book is Full.", spells[spell_id].name, spell_id ); break; } - + if (initiator->HasSpellScribed(spell_id)) continue; - + initiator->ScribeSpell(spell_id, book_slot); book_slot = initiator->GetNextAvailableSpellBookSlot(book_slot); spells_learned++; @@ -2506,7 +2507,7 @@ void QuestManager::message(int color, const char *message) { QuestManagerCurrentQuestVars(); if (!initiator) return; - + initiator->Message(color, message); } @@ -4277,319 +4278,8 @@ std::string QuestManager::secondstotime(int duration) { } std::string QuestManager::gethexcolorcode(std::string color_name) { - static const std::map colors = { - { "Black", "#000000" }, - { "Brown", "#804000" }, - { "Burgundy", "#800000" }, - { "Cadet Blue", "#77BFC7" }, - { "Cadet Blue1", "#4C787E" }, - { "Chartreuse", "#8AFB17" }, - { "Chartreuse1", "#7FE817" }, - { "Chartreuse2", "#6CC417" }, - { "Chartreuse3", "#437C17" }, - { "Chocolate", "#C85A17" }, - { "Coral", "#F76541" }, - { "Coral1", "#E55B3C" }, - { "Coral2", "#C34A2C" }, - { "Cornflower Blue", "#151B8D" }, - { "Cyan", "#00FFFF" }, - { "Cyan1", "#57FEFF" }, - { "Cyan2", "#50EBEC" }, - { "Cyan3", "#46C7C7" }, - { "Cyan4", "#307D7E" }, - { "Dark Blue", "#0000A0" }, - { "Dark Goldenrod", "#AF7817" }, - { "Dark Goldenrod1", "#FBB117" }, - { "Dark Goldenrod2", "#E8A317" }, - { "Dark Goldenrod3", "#C58917" }, - { "Dark Goldenrod4", "#7F5217" }, - { "Dark Green", "#254117" }, - { "Dark Grey", "#808080" }, - { "Dark Olive Green", "#CCFB5D" }, - { "Dark Olive Green2", "#BCE954" }, - { "Dark Olive Green3", "#A0C544" }, - { "Dark Olive Green4", "#667C26" }, - { "Dark Orange", "#F88017" }, - { "Dark Orange1", "#F87217" }, - { "Dark Orange2", "#E56717" }, - { "Dark Orange3", "#7E3117" }, - { "Dark Orange3", "#C35617" }, - { "Dark Orchid", "#7D1B7E" }, - { "Dark Orchid1", "#B041FF" }, - { "Dark Orchid2", "#A23BEC" }, - { "Dark Orchid3", "#8B31C7" }, - { "Dark Orchid4", "#571B7e" }, - { "Dark Purple", "#800080" }, - { "Dark Salmon", "#E18B6B" }, - { "Dark Sea Green", "#8BB381" }, - { "Dark Sea Green1", "#C3FDB8" }, - { "Dark Sea Green2", "#B5EAAA" }, - { "Dark Sea Green3", "#99C68E" }, - { "Dark Sea Green4", "#617C58" }, - { "Dark Slate Blue", "#2B3856" }, - { "Dark Slate Gray", "#25383C" }, - { "Dark Slate Gray1", "#9AFEFF" }, - { "Dark Slate Gray2", "#8EEBEC" }, - { "Dark Slate Gray3", "#78c7c7" }, - { "Dark Slate Gray4", "#4C7D7E" }, - { "Dark Turquoise", "#3B9C9C" }, - { "Dark Violet", "#842DCE" }, - { "Deep Pink", "#F52887" }, - { "Deep Pink1", "#E4287C" }, - { "Deep Pink2", "#C12267" }, - { "Deep Pink3", "#7D053F" }, - { "Deep Sky Blue", "#3BB9FF" }, - { "Deep Sky Blue1", "#38ACEC" }, - { "Deep Sky Blue2", "#3090C7" }, - { "Deep Sky Blue3", "#25587E" }, - { "Dim Gray", "#463E41" }, - { "Dodger Blue", "#1589FF" }, - { "Dodger Blue1", "#157DEC" }, - { "Dodger Blue2", "#1569C7" }, - { "Dodger Blue3", "#153E7E" }, - { "Firebrick", "#800517" }, - { "Firebrick1", "#F62817" }, - { "Firebrick2", "#E42217" }, - { "Firebrick3", "#C11B17" }, - { "Forest Green", "#4E9258" }, - { "Forest Green1", "#808000" }, - { "Gold", "#D4A017" }, - { "Gold1", "#FDD017" }, - { "Gold2", "#EAC117" }, - { "Gold3", "#C7A317" }, - { "Gold4", "#806517" }, - { "Goldenrod", "#EDDA74" }, - { "Goldenrod1", "#FBB917" }, - { "Goldenrod2", "#E9AB17" }, - { "Goldenrod3", "#C68E17" }, - { "Goldenrod4", "#805817" }, - { "Grass Green", "#408080" }, - { "Gray", "#736F6E" }, - { "Gray1", "#150517" }, - { "Gray2", "#250517" }, - { "Gray3", "#2B1B17" }, - { "Gray4", "#302217" }, - { "Gray5", "#302226" }, - { "Gray6", "#342826" }, - { "Gray7", "#34282C" }, - { "Gray8", "#382D2C" }, - { "Gray9", "#3b3131" }, - { "Gray10", "#3E3535" }, - { "Gray11", "#413839" }, - { "Gray12", "#41383C" }, - { "Gray13", "#463E3F" }, - { "Gray14", "#4A4344" }, - { "Gray15", "#4C4646" }, - { "Gray16", "#4E4848" }, - { "Gray17", "#504A4B" }, - { "Gray18", "#544E4F" }, - { "Gray19", "#565051" }, - { "Gray19", "#595454" }, - { "Gray20", "#5C5858" }, - { "Gray21", "#5F5A59" }, - { "Gray22", "#625D5D" }, - { "Gray23", "#646060" }, - { "Gray24", "#666362" }, - { "Gray25", "#696565" }, - { "Gray26", "#6D6968" }, - { "Gray27", "#6E6A6B" }, - { "Gray28", "#726E6D" }, - { "Gray29", "#747170" }, - { "Green", "#00FF00" }, - { "Green1", "#5FFB17" }, - { "Green2", "#59E817" }, - { "Green3", "#4CC417" }, - { "Green4", "#347C17" }, - { "Green Yellow", "#B1FB17" }, - { "Hot Pink", "#F660AB" }, - { "Hot Pink1", "#F665AB" }, - { "Hot Pink2", "#E45E9D" }, - { "Hot Pink3", "#C25283" }, - { "Hot Pink4", "#7D2252" }, - { "Indian Red", "#F75D59" }, - { "Indian Red2", "#E55451" }, - { "Indian Red3", "#C24641" }, - { "Indian Red4", "#7E2217" }, - { "Khaki", "#ADA96E" }, - { "Khaki1", "#FFF380" }, - { "Khaki2", "#EDE275" }, - { "Khaki3", "#C9BE62" }, - { "Khaki4", "#827839" }, - { "Lavender", "#E3E4FA" }, - { "Lavender Blush", "#FDEEF4" }, - { "Lavender Blush1", "#EBDDE2" }, - { "Lavender Blush2", "#C8BBBE" }, - { "Lavender Blush3", "#817679" }, - { "Lawn Green", "#87F717" }, - { "Lemon Chiffon", "#FFF8C6" }, - { "Lemon Chiffon1", "#ECE5B6" }, - { "Lemon Chiffon2", "#C9C299" }, - { "Lemon Chiffon3", "#827B60" }, - { "Light Blue", "#0000FF" }, - { "Light Blue1", "#ADDFFF" }, - { "Light Blue2", "#BDEDFF" }, - { "Light Blue3", "#AFDCEC" }, - { "Light Blue4", "#95B9C7" }, - { "Light Blue5", "#5E767E" }, - { "Light Coral", "#E77471" }, - { "Light Cyan", "#E0FFFF" }, - { "Light Cyan1", "#CFECEC" }, - { "Light Cyan2", "#AFC7C7" }, - { "Light Cyan3", "#717D7D" }, - { "Light Golden", "#ECD672" }, - { "Light Goldenrod", "#ECD872" }, - { "Light Goldenrod1", "#FFE87C" }, - { "Light Goldenrod2", "#C8B560" }, - { "Light Goldenrod3", "#817339" }, - { "Light Goldenrod Yellow", "#FAF8CC" }, - { "Light Grey", "#C0C0C0" }, - { "Light Pink", "#FAAFBA" }, - { "Light Pink1", "#F9A7B0" }, - { "Light Pink2", "#E799A3" }, - { "Light Pink3", "#C48189" }, - { "Light Pink4", "#7F4E52" }, - { "Light Purple", "#FF0080" }, - { "Light Salmon", "#F9966B" }, - { "Light Salmon1", "#E78A61" }, - { "Light Salmon2", "#C47451" }, - { "Light Salmon3", "#7F462C" }, - { "Light Sea Green", "#3EA99F" }, - { "Light Sky Blue", "#82CAFA" }, - { "Light Sky Blue1", "#A0CFEC" }, - { "Light Sky Blue2", "#87AFC7" }, - { "Light Sky Blue3", "#566D7E" }, - { "Light Slate Blue", "#736AFF" }, - { "Light Slate Gray", "#6D7B8D" }, - { "Light Steel Blue", "#728FCE" }, - { "Light Steel Blue1", "#C6DEFF" }, - { "Light Steel Blue2", "#B7CEEC" }, - { "Light Steel Blue3", "#646D7E" }, - { "Lime Green", "#41A317" }, - { "Magenta", "#FF00FF" }, - { "Magenta1", "#F433FF" }, - { "Magenta2", "#E238EC" }, - { "Magenta3", "#C031C7" }, - { "Maroon", "#810541" }, - { "Maroon1", "#F535AA" }, - { "Maroon2", "#E3319D" }, - { "Maroon3", "#C12283" }, - { "Maroon4", "#7D0552" }, - { "Medium Aquamarine", "#348781" }, - { "Medium Forest Green", "#347235" }, - { "Medium Orchid", "#B048B5" }, - { "Medium Orchid1", "#D462FF" }, - { "Medium Orchid2", "#C45AEC" }, - { "Medium Orchid3", "#A74AC7" }, - { "Medium Orchid4", "#6A287E" }, - { "Medium Purple", "#8467D7" }, - { "Medium Purple1", "#9E7BFF" }, - { "Medium Purple2", "#9172EC" }, - { "Medium Purple3", "#7A5DC7" }, - { "Medium Purple4", "#4E387E" }, - { "Medium Sea Green", "#306754" }, - { "Medium Slate Blue", "#5E5A80" }, - { "Medium Spring Green", "#348017" }, - { "Medium Turquoise", "#48CCCD" }, - { "Medium Violet Red", "#CA226B" }, - { "Midnight Blue", "#151B54" }, - { "Orange", "#FF8040" }, - { "Pale Turquoise", "#92C7C7" }, - { "Pale Turquoise1", "#5E7D7E" }, - { "Pale Violet Red", "#D16587" }, - { "Pale Violet Red1", "#F778A1" }, - { "Pale Violet Red2", "#E56E94" }, - { "Pale Violet Red3", "#C25A7C" }, - { "Pale Violet Red4", "#7E354D" }, - { "Pastel Green", "#00FF00" }, - { "Pink", "#FAAFBE" }, - { "Pink1", "#FF00FF" }, - { "Pink2", "#E7A1B0" }, - { "Pink3", "#C48793" }, - { "Pink4", "#7F525D" }, - { "Plum", "#B93B8F" }, - { "Plum1", "#F9B7FF" }, - { "Plum2", "#E6A9EC" }, - { "Plum3", "#C38EC7" }, - { "Plum4", "#7E587E" }, - { "Purple", "#8E35EF" }, - { "Purple1", "#893BFF" }, - { "Purple2", "#7F38EC" }, - { "Purple3", "#6C2DC7" }, - { "Purple4", "#461B7E" }, - { "Red", "#FF0000" }, - { "Red1", "#F62217" }, - { "Red2", "#E41B17" }, - { "Rosy Brown", "#B38481" }, - { "Rosy Brown1", "#FBBBB9" }, - { "Rosy Brown2", "#E8ADAA" }, - { "Rosy Brown3", "#C5908E" }, - { "Rosy Brown4", "#7F5A58" }, - { "Royal Blue", "#2B60DE" }, - { "Royal Blue1", "#306EFF" }, - { "Royal Blue2", "#2B65EC" }, - { "Royal Blue3", "#2554C7" }, - { "Royal Blue4", "#15317E" }, - { "Salmon1", "#F88158" }, - { "Salmon2", "#E67451" }, - { "Salmon3", "#C36241" }, - { "Salmon4", "#7E3817" }, - { "Sandy Brown", "#EE9A4D" }, - { "Sea Green", "#4E8975" }, - { "Sea Green1", "#6AFB92" }, - { "Sea Green2", "#64E986" }, - { "Sea Green3", "#54C571" }, - { "Sea Green4", "#387C44" }, - { "Sienna", "#8A4117" }, - { "Sienna1", "#F87431" }, - { "Sienna2", "#E66C2C" }, - { "Sienna3", "#C35817" }, - { "Sienna4", "#7E3517" }, - { "Sky Blue", "#82CAFF" }, - { "Sky Blue1", "#6698FF" }, - { "Sky Blue2", "#79BAEC" }, - { "Sky Blue3", "#659EC7" }, - { "Sky Blue4", "#41627E" }, - { "Slate Blue", "#357EC7" }, - { "Slate Blue1", "#737CA1" }, - { "Slate Blue2", "#6960EC" }, - { "Slate Blue3", "#342D7E" }, - { "Slate Gray", "#657383" }, - { "Slate Gray1", "#C2DFFF" }, - { "Slate Gray2", "#B4CFEC" }, - { "Slate Gray3", "#98AFC7" }, - { "Slate Gray4", "#616D7E" }, - { "Spring Green", "#4AA02C" }, - { "Spring Green1", "#5EFB6E" }, - { "Spring Green2", "#57E964" }, - { "Spring Green3", "#4CC552" }, - { "Spring Green4", "#347C2C" }, - { "Steel Blue", "#4863A0" }, - { "Steel Blue1", "#5CB3FF" }, - { "Steel Blue2", "#56A5EC" }, - { "Steel Blue3", "#488AC7" }, - { "Steel Blue4", "#2B547E" }, - { "Thistle", "#D2B9D3" }, - { "Thistle1", "#FCDFFF" }, - { "Thistle2", "#E9CFEC" }, - { "Thistle3", "#C6AEC7" }, - { "Thistle4", "#806D7E" }, - { "Turquoise", "#00FFFF" }, - { "Turquoise1", "#43C6DB" }, - { "Turquoise2", "#52F3FF" }, - { "Turquoise3", "#4EE2EC" }, - { "Turquoise4", "#43BFC7" }, - { "Violet", "#8D38C9" }, - { "Violet Red", "#F6358A" }, - { "Violet Red1", "#F6358A" }, - { "Violet Red2", "#E4317F" }, - { "Violet Red3", "#C12869" }, - { "Violet Red4", "#7D0541" }, - { "White", "#FFFFFF" }, - { "Yellow", "#FFFF00" }, - { "Yellow1", "#FFFC17" }, - { "Yellow Green", "#52D017" } - }; - for (auto color : colors) { + + for (auto color : html_colors) { if (!strcasecmp(color.first.c_str(), color_name.c_str())) { return color.second; }