Merge branch 'master' of https://github.com/EQEmu/Server into integration/multi-tenancy-expansions-repository

This commit is contained in:
Akkadius 2020-04-06 02:55:46 -05:00
commit 2b1b786f02
34 changed files with 1497 additions and 144 deletions

17
.gitignore vendored
View File

@ -37,4 +37,19 @@ perl/
submodules/*
cmake-build-debug/
.nfs.*
.nfs.*
# Visual Studio and CMAKE Generated Files
/.vs/
*.vcxproj
*.vcxproj.filters
*.vcxproj.user
*.cmake
*.ilk
*.pdb
*.sln
*.dir/
libs/
bin/
/Win32
/client_files/**/CMakeFiles/

View File

@ -1,7 +1,7 @@
# EQEmulator Core Server
|Travis CI (Linux)|Appveyor w/ Bots (Windows) |Appveyor w/o Bots (Windows) |
|Travis CI (Linux)|Appveyor (Windows x86) |Appveyor (Windows x64) |
|:---:|:---:|:---:|
|[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Build status](https://ci.appveyor.com/api/projects/status/scr25kmntx36c1ub/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server-87crp/branch/master) |[![Build status](https://ci.appveyor.com/api/projects/status/mdwbr4o9l6mxqofj/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server-w0pq2/branch/master) |
|[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Build status](https://ci.appveyor.com/api/projects/status/v3utuu0dttm2cqd0?svg=true)](https://ci.appveyor.com/project/KimLS/server) |[![Build status](https://ci.appveyor.com/api/projects/status/scr25kmntx36c1ub?svg=true)](https://ci.appveyor.com/project/KimLS/server-87crp) |
***

View File

@ -78,6 +78,7 @@ SET(common_sources
unix.cpp
platform.cpp
json/jsoncpp.cpp
namegenerator/namegen.cpp
net/console_server.cpp
net/console_server_connection.cpp
net/crc32.cpp
@ -562,6 +563,7 @@ SET(common_headers
event/timer.h
json/json.h
json/json-forwards.h
namegenerator/namegen.h
net/console_server.h
net/console_server_connection.h
net/crc32.h

View File

@ -870,6 +870,38 @@ void Database::GetCharName(uint32 char_id, char* name) {
}
}
const char* Database::GetCharNameByID(uint32 char_id) {
std::string query = fmt::format("SELECT `name` FROM `character_data` WHERE id = {}", char_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
return "";
}
if (results.RowCount() == 0) {
return "";
}
auto row = results.begin();
return row[0];
}
const char* Database::GetNPCNameByID(uint32 npc_id) {
std::string query = fmt::format("SELECT `name` FROM `npc_types` WHERE id = {}", npc_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
return "";
}
if (results.RowCount() == 0) {
return "";
}
auto row = results.begin();
return row[0];
}
bool Database::LoadVariables() {
auto results = QueryDatabase(StringFormat("SELECT varname, value, unix_timestamp() FROM variables where unix_timestamp(ts) >= %d", varcache.last_update));
@ -2318,3 +2350,4 @@ int Database::GetInstanceID(uint32 char_id, uint32 zone_id) {
return 0;
}

View File

@ -137,6 +137,8 @@ public:
void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0);
void GetCharName(uint32 char_id, char* name);
const char *GetCharNameByID(uint32 char_id);
const char *GetNPCNameByID(uint32 npc_id);
void LoginIP(uint32 AccountID, const char* LoginIP);
/* Instancing */

View File

@ -50,7 +50,11 @@ std::string DatabaseDumpService::execute(const std::string &cmd, bool return_res
const char *file_name = "db-exec-result.txt";
if (return_result) {
#ifdef _WINDOWS
std::system((cmd + " > " + file_name + " 2>&1").c_str());
#else
std::system((cmd + " > " + file_name).c_str());
#endif
}
else {
std::system((cmd).c_str());
@ -95,7 +99,7 @@ bool DatabaseDumpService::IsTarAvailable()
*/
bool DatabaseDumpService::Is7ZipAvailable()
{
std::string version_output = execute("7z -help");
std::string version_output = execute("7z --help");
return version_output.find("7-Zip") != std::string::npos;
}
@ -396,9 +400,8 @@ void DatabaseDumpService::Dump()
else if (Is7ZipAvailable()) {
execute(
fmt::format(
"7z a -t7z {}.zip -C {} {}.sql",
"7z a -t7z {}.zip {}.sql",
GetDumpFileNameWithPath(),
GetSetDumpPath(),
GetDumpFileNameWithPath()
)
);

View File

@ -25,6 +25,10 @@ namespace EQ
uv_run(&m_loop, UV_RUN_DEFAULT);
}
void Shutdown() {
uv_stop(&m_loop);
}
uv_loop_t* Handle() { return &m_loop; }
private:

View File

@ -0,0 +1,522 @@
/**
*
* @file A fantasy name generator library.
* @version 1.0.1
* @license Public Domain
* @author German M. Bravo (Kronuz)
*
*/
#include "namegen.h"
#include <algorithm> // for move, reverse
#include <chrono> // for rng seed
#include <cwchar> // for size_t, mbsrtowcs, wcsrtombs
#include <cwctype> // for towupper
#include <memory> // for make_unique
#include <random> // for mt19937, uniform_real_distribution
#include <stdexcept> // for invalid_argument, out_of_range
using namespace NameGen;
static std::mt19937 rng(std::chrono::high_resolution_clock::now().time_since_epoch().count());
// https://isocpp.org/wiki/faq/ctors#static-init-order
// Avoid the "static initialization order fiasco"
const std::unordered_map<std::string, const std::vector<std::string>>& Generator::SymbolMap()
{
static auto* const symbols = new std::unordered_map<std::string, const std::vector<std::string>>({
{
"s", {
"ach", "ack", "ad", "age", "ald", "ale", "an", "ang", "ar", "ard",
"as", "ash", "at", "ath", "augh", "aw", "ban", "bel", "bur", "cer",
"cha", "che", "dan", "dar", "del", "den", "dra", "dyn", "ech", "eld",
"elm", "em", "en", "end", "eng", "enth", "er", "ess", "est", "et",
"gar", "gha", "hat", "hin", "hon", "ia", "ight", "ild", "im", "ina",
"ine", "ing", "ir", "is", "iss", "it", "kal", "kel", "kim", "kin",
"ler", "lor", "lye", "mor", "mos", "nal", "ny", "nys", "old", "om",
"on", "or", "orm", "os", "ough", "per", "pol", "qua", "que", "rad",
"rak", "ran", "ray", "ril", "ris", "rod", "roth", "ryn", "sam",
"say", "ser", "shy", "skel", "sul", "tai", "tan", "tas", "ther",
"tia", "tin", "ton", "tor", "tur", "um", "und", "unt", "urn", "usk",
"ust", "ver", "ves", "vor", "war", "wor", "yer"
}
},
{
"v", {
"a", "e", "i", "o", "u", "y"
}
},
{
"V", {
"a", "e", "i", "o", "u", "y", "ae", "ai", "au", "ay", "ea", "ee",
"ei", "eu", "ey", "ia", "ie", "oe", "oi", "oo", "ou", "ui"
}
},
{
"c", {
"b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r",
"s", "t", "v", "w", "x", "y", "z"
}
},
{
"B", {
"b", "bl", "br", "c", "ch", "chr", "cl", "cr", "d", "dr", "f", "g",
"h", "j", "k", "l", "ll", "m", "n", "p", "ph", "qu", "r", "rh", "s",
"sch", "sh", "sl", "sm", "sn", "st", "str", "sw", "t", "th", "thr",
"tr", "v", "w", "wh", "y", "z", "zh"
}
},
{
"C", {
"b", "c", "ch", "ck", "d", "f", "g", "gh", "h", "k", "l", "ld", "ll",
"lt", "m", "n", "nd", "nn", "nt", "p", "ph", "q", "r", "rd", "rr",
"rt", "s", "sh", "ss", "st", "t", "th", "v", "w", "y", "z"
}
},
{
"i", {
"air", "ankle", "ball", "beef", "bone", "bum", "bumble", "bump",
"cheese", "clod", "clot", "clown", "corn", "dip", "dolt", "doof",
"dork", "dumb", "face", "finger", "foot", "fumble", "goof",
"grumble", "head", "knock", "knocker", "knuckle", "loaf", "lump",
"lunk", "meat", "muck", "munch", "nit", "numb", "pin", "puff",
"skull", "snark", "sneeze", "thimble", "twerp", "twit", "wad",
"wimp", "wipe"
}
},
{
"m", {
"baby", "booble", "bunker", "cuddle", "cuddly", "cutie", "doodle",
"foofie", "gooble", "honey", "kissie", "lover", "lovey", "moofie",
"mooglie", "moopie", "moopsie", "nookum", "poochie", "poof",
"poofie", "pookie", "schmoopie", "schnoogle", "schnookie",
"schnookum", "smooch", "smoochie", "smoosh", "snoogle", "snoogy",
"snookie", "snookum", "snuggy", "sweetie", "woogle", "woogy",
"wookie", "wookum", "wuddle", "wuddly", "wuggy", "wunny"
}
},
{
"M", {
"boo", "bunch", "bunny", "cake", "cakes", "cute", "darling",
"dumpling", "dumplings", "face", "foof", "goo", "head", "kin",
"kins", "lips", "love", "mush", "pie", "poo", "pooh", "pook", "pums"
}
},
{
"D", {
"b", "bl", "br", "cl", "d", "f", "fl", "fr", "g", "gh", "gl", "gr",
"h", "j", "k", "kl", "m", "n", "p", "th", "w"
}
},
{
"d", {
"elch", "idiot", "ob", "og", "ok", "olph", "olt", "omph", "ong",
"onk", "oo", "oob", "oof", "oog", "ook", "ooz", "org", "ork", "orm",
"oron", "ub", "uck", "ug", "ulf", "ult", "um", "umb", "ump", "umph",
"un", "unb", "ung", "unk", "unph", "unt", "uzz"
}
}
});
return *symbols;
}
Generator::Generator()
{
}
Generator::Generator(std::vector<std::unique_ptr<Generator>>&& generators_) :
generators(std::move(generators_))
{
}
size_t Generator::combinations()
{
size_t total = 1;
for (auto& g : generators) {
total *= g->combinations();
}
return total;
}
size_t Generator::min()
{
size_t final = 0;
for (auto& g : generators) {
final += g->min();
}
return final;
}
size_t Generator::max()
{
size_t final = 0;
for (auto& g : generators) {
final += g->max();
}
return final;
}
std::string Generator::toString() {
std::string str;
for (auto& g : generators) {
str.append(g->toString());
}
return str;
}
void Generator::add(std::unique_ptr<Generator>&& g)
{
generators.push_back(std::move(g));
}
Random::Random()
{
}
Random::Random(std::vector<std::unique_ptr<Generator>>&& generators_) :
Generator(std::move(generators_))
{
}
size_t Random::combinations()
{
size_t total = 0;
for (auto& g : generators) {
total += g->combinations();
}
return total ? total : 1;
}
size_t Random::min()
{
size_t final = -1;
for (auto& g : generators) {
size_t current = g->min();
if (current < final) {
final = current;
}
}
return final;
}
size_t Random::max()
{
size_t final = 0;
for (auto& g : generators) {
size_t current = g->max();
if (current > final) {
final = current;
}
}
return final;
}
std::string Random::toString()
{
if (!generators.size()) {
return "";
}
std::uniform_real_distribution<double> distribution(0, generators.size() - 1);
int rnd = distribution(rng) + 0.5;
return generators[rnd]->toString();
}
Sequence::Sequence()
{
}
Sequence::Sequence(std::vector<std::unique_ptr<Generator>>&& generators_) :
Generator(std::move(generators_))
{
}
Literal::Literal(const std::string &value_) :
value(value_)
{
}
size_t Literal::combinations()
{
return 1;
}
size_t Literal::min()
{
return value.size();
}
size_t Literal::max()
{
return value.size();
}
std::string Literal::toString()
{
return value;
}
Reverser::Reverser(std::unique_ptr<Generator>&& g)
{
add(std::move(g));
}
std::string Reverser::toString()
{
std::wstring str = towstring(Generator::toString());
std::reverse(str.begin(), str.end());
return tostring(str);
}
Capitalizer::Capitalizer(std::unique_ptr<Generator>&& g)
{
add(std::move(g));
}
std::string Capitalizer::toString()
{
std::wstring str = towstring(Generator::toString());
str[0] = std::towupper(str[0]);
return tostring(str);
}
Collapser::Collapser(std::unique_ptr<Generator>&& g)
{
add(std::move(g));
}
std::string Collapser::toString()
{
std::wstring str = towstring(Generator::toString());
std::wstring out;
int cnt = 0;
wchar_t pch = L'\0';
for (auto ch : str) {
if (ch == pch) {
cnt++;
} else {
cnt = 0;
}
int mch = 2;
switch(ch) {
case 'a':
case 'h':
case 'i':
case 'j':
case 'q':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
mch = 1;
}
if (cnt < mch) {
out.push_back(ch);
}
pch = ch;
}
return tostring(out);
}
Generator::Generator(const std::string &pattern, bool collapse_triples) {
std::unique_ptr<Generator> last;
std::stack<std::unique_ptr<Group>> stack;
std::unique_ptr<Group> top = std::unique_ptr<GroupSymbol>();
for (auto c : pattern) {
switch (c) {
case '<':
stack.push(std::move(top));
top = std::unique_ptr<GroupSymbol>();
break;
case '(':
stack.push(std::move(top));
top = std::unique_ptr<GroupLiteral>();
break;
case '>':
case ')':
if (stack.size() == 0) {
throw std::invalid_argument("Unbalanced brackets");
} else if (c == '>' && top->type != group_types::symbol) {
throw std::invalid_argument("Unexpected '>' in pattern");
} else if (c == ')' && top->type != group_types::literal) {
throw std::invalid_argument("Unexpected ')' in pattern");
}
last = top->produce();
top = std::move(stack.top());
stack.pop();
top->add(std::move(last));
break;
case '|':
top->split();
break;
case '!':
if (top->type == group_types::symbol) {
top->wrap(wrappers::capitalizer);
} else {
top->add(c);
}
break;
case '~':
if (top->type == group_types::symbol) {
top->wrap(wrappers::reverser);
} else {
top->add(c);
}
break;
default:
top->add(c);
break;
}
}
if (stack.size() != 0) {
throw std::invalid_argument("Missing closing bracket");
}
std::unique_ptr<Generator> g = top->produce();
if (collapse_triples) {
g = std::unique_ptr<Collapser>(new Collapser(std::move(g)));
}
add(std::move(g));
}
Generator::Group::Group(group_types_t type_) :
type(type_)
{
}
void Generator::Group::add(std::unique_ptr<Generator>&& g)
{
while (!wrappers.empty()) {
switch (wrappers.top()) {
case reverser:
g = std::unique_ptr<Reverser>(new Reverser(std::move(g)));
break;
case capitalizer:
g = std::unique_ptr<Capitalizer>(new Capitalizer(std::move(g)));
break;
}
wrappers.pop();
}
if (set.size() == 0) {
set.push_back(std::unique_ptr<Sequence>());
}
set.back()->add(std::move(g));
}
void Generator::Group::add(char c)
{
std::string value(1, c);
std::unique_ptr<Generator> g = std::unique_ptr<Random>();
g->add(std::unique_ptr<Literal>(new Literal(value)));
Group::add(std::move(g));
}
std::unique_ptr<Generator> Generator::Group::produce()
{
switch (set.size()) {
case 0:
return std::unique_ptr<Literal>(new Literal(""));
case 1:
return std::move(*set.begin());
default:
return std::unique_ptr<Random>(new Random(std::move(set)));
}
}
void Generator::Group::split()
{
if (set.size() == 0) {
set.push_back(std::unique_ptr<Sequence>());
}
set.push_back(std::unique_ptr<Sequence>());
}
void Generator::Group::wrap(wrappers_t type)
{
wrappers.push(type);
}
Generator::GroupSymbol::GroupSymbol() :
Group(group_types::symbol)
{
}
void Generator::GroupSymbol::add(char c)
{
std::string value(1, c);
std::unique_ptr<Generator> g = std::unique_ptr<Random>();
try {
static const auto& symbols = SymbolMap();
for (const auto& s : symbols.at(value)) {
g->add(std::unique_ptr<Literal>(new Literal(s)));
}
} catch (const std::out_of_range&) {
g->add(std::unique_ptr<Literal>(new Literal(value)));
}
Group::add(std::move(g));
}
Generator::GroupLiteral::GroupLiteral() :
Group(group_types::literal)
{
}
std::wstring towstring(const std::string & s)
{
const char *cs = s.c_str();
const size_t wn = std::mbsrtowcs(nullptr, &cs, 0, nullptr);
if (wn == static_cast<size_t>(-1)) {
return L"";
}
std::vector<wchar_t> buf(wn);
cs = s.c_str();
const size_t wn_again = std::mbsrtowcs(buf.data(), &cs, wn, nullptr);
if (wn_again == static_cast<size_t>(-1)) {
return L"";
}
return std::wstring(buf.data(), wn);
}
std::string tostring(const std::wstring & s)
{
const wchar_t *cs = s.c_str();
const size_t wn = std::wcsrtombs(nullptr, &cs, 0, nullptr);
if (wn == static_cast<size_t>(-1)) {
return "";
}
std::vector<char> buf(wn);
const size_t wn_again = std::wcsrtombs(buf.data(), &cs, wn, nullptr);
if (wn_again == static_cast<size_t>(-1)) {
return "";
}
return std::string(buf.data(), wn);
}

View File

@ -0,0 +1,269 @@
/**
*
* @file A fantasy name generator library.
* @version 1.0.1
* @license Public Domain
* @author German M. Bravo (Kronuz)
*
* This library is designed after the RinkWorks Fantasy Name Generator.
* @see http://www.rinkworks.com/namegen/
*
* @example
* NameGen::Generator generator("sV'i");
* generator.toString(); // Returns a new name each call with produce()
* // => "entheu'loaf"
*
* ## Pattern Syntax
*
* The compile() function creates a name generator based on an input
* pattern. The letters s, v, V, c, B, C, i, m, M, D, and d represent
* different types of random replacements. Everything else is produced
* literally.
*
* s - generic syllable
* v - vowel
* V - vowel or vowel combination
* c - consonant
* B - consonant or consonant combination suitable for beginning a word
* C - consonant or consonant combination suitable anywhere in a word
* i - insult
* m - mushy name
* M - mushy name ending
* D - consonant suited for a stupid person's name
* d - syllable suited for a stupid person's name (begins with a vowel)
*
* All characters between parenthesis () are produced literally. For
* example, the pattern "s(dim)", produces a random generic syllable
* followed by "dim".
*
* Characters between angle brackets <> produce patterns from the table
* above. Imagine the entire pattern is wrapped in one of these.
*
* In both types of groupings, a vertical bar | denotes a random
* choice. Empty groups are allowed. For example, "(foo|bar)" produces
* either "foo" or "bar". The pattern "<c|v|>" produces a constant,
* vowel, or nothing at all.
*
* An exclamation point ! means to capitalize the component that
* follows it. For example, "!(foo)" will produce "Foo" and "v!s" will
* produce a lowercase vowel followed by a capitalized syllable, like
* "eRod".
*
* A tilde ~ means to reverse the letters of the component that
* follows it. For example, "~(foo)" will produce "oof". To reverse an
* entire template, wrap it in brackets. For example, to reverse
* "sV'i" as a whole use "~<sV'i>". The template "~sV'i" will only
* reverse the initial syllable.
*
* ## Internals
*
* A name generator is anything with a toString() method, including,
* importantly, strings themselves. The generator constructors
* (Random, Sequence) perform additional optimizations when *not* used
* with the `new` keyword: they may pass through a provided generator,
* combine provided generators, or even return a simple string.
*
* New pattern symbols added to Generator.symbols will automatically
* be used by the compiler.
*/
#pragma once
#include <stddef.h> // for size_t
#include <iosfwd> // for wstring
#include <memory> // for unique_ptr
#include <stack> // for stack
#include <string> // for string
#include <unordered_map> // for unordered_map
#include <vector> // for vector
namespace NameGen {
// Middle Earth
#define MIDDLE_EARTH "(bil|bal|ban|hil|ham|hal|hol|hob|wil|me|or|ol|od|gor|for|fos|tol|ar|fin|ere|leo|vi|bi|bren|thor)(|go|orbis|apol|adur|mos|ri|i|na|ole|n)(|tur|axia|and|bo|gil|bin|bras|las|mac|grim|wise|l|lo|fo|co|ra|via|da|ne|ta|y|wen|thiel|phin|dir|dor|tor|rod|on|rdo|dis)"
// Japanese Names (Constrained)
#define JAPANESE_NAMES_CONSTRAINED "(aka|aki|bashi|gawa|kawa|furu|fuku|fuji|hana|hara|haru|hashi|hira|hon|hoshi|ichi|iwa|kami|kawa|ki|kita|kuchi|kuro|marui|matsu|miya|mori|moto|mura|nabe|naka|nishi|no|da|ta|o|oo|oka|saka|saki|sawa|shita|shima|i|suzu|taka|take|to|toku|toyo|ue|wa|wara|wata|yama|yoshi|kei|ko|zawa|zen|sen|ao|gin|kin|ken|shiro|zaki|yuki|asa)(||||||||||bashi|gawa|kawa|furu|fuku|fuji|hana|hara|haru|hashi|hira|hon|hoshi|chi|wa|ka|kami|kawa|ki|kita|kuchi|kuro|marui|matsu|miya|mori|moto|mura|nabe|naka|nishi|no|da|ta|o|oo|oka|saka|saki|sawa|shita|shima|suzu|taka|take|to|toku|toyo|ue|wa|wara|wata|yama|yoshi|kei|ko|zawa|zen|sen|ao|gin|kin|ken|shiro|zaki|yuki|sa)"
// Japanese Names (Diverse)
#define JAPANESE_NAMES_DIVERSE "(a|i|u|e|o|||||)(ka|ki|ki|ku|ku|ke|ke|ko|ko|sa|sa|sa|shi|shi|shi|su|su|se|so|ta|ta|chi|chi|tsu|te|to|na|ni|ni|nu|nu|ne|no|no|ha|hi|fu|fu|he|ho|ma|ma|ma|mi|mi|mi|mu|mu|mu|mu|me|mo|mo|mo|ya|yu|yu|yu|yo|ra|ra|ra|ri|ru|ru|ru|re|ro|ro|ro|wa|wa|wa|wa|wo|wo)(ka|ki|ki|ku|ku|ke|ke|ko|ko|sa|sa|sa|shi|shi|shi|su|su|se|so|ta|ta|chi|chi|tsu|te|to|na|ni|ni|nu|nu|ne|no|no|ha|hi|fu|fu|he|ho|ma|ma|ma|mi|mi|mi|mu|mu|mu|mu|me|mo|mo|mo|ya|yu|yu|yu|yo|ra|ra|ra|ri|ru|ru|ru|re|ro|ro|ro|wa|wa|wa|wa|wo|wo)(|(ka|ki|ki|ku|ku|ke|ke|ko|ko|sa|sa|sa|shi|shi|shi|su|su|se|so|ta|ta|chi|chi|tsu|te|to|na|ni|ni|nu|nu|ne|no|no|ha|hi|fu|fu|he|ho|ma|ma|ma|mi|mi|mi|mu|mu|mu|mu|me|mo|mo|mo|ya|yu|yu|yu|yo|ra|ra|ra|ri|ru|ru|ru|re|ro|ro|ro|wa|wa|wa|wa|wo|wo)|(ka|ki|ki|ku|ku|ke|ke|ko|ko|sa|sa|sa|shi|shi|shi|su|su|se|so|ta|ta|chi|chi|tsu|te|to|na|ni|ni|nu|nu|ne|no|no|ha|hi|fu|fu|he|ho|ma|ma|ma|mi|mi|mi|mu|mu|mu|mu|me|mo|mo|mo|ya|yu|yu|yu|yo|ra|ra|ra|ri|ru|ru|ru|re|ro|ro|ro|wa|wa|wa|wa|wo|wo)(|(ka|ki|ki|ku|ku|ke|ke|ko|ko|sa|sa|sa|shi|shi|shi|su|su|se|so|ta|ta|chi|chi|tsu|te|to|na|ni|ni|nu|nu|ne|no|no|ha|hi|fu|fu|he|ho|ma|ma|ma|mi|mi|mi|mu|mu|mu|mu|me|mo|mo|mo|ya|yu|yu|yu|yo|ra|ra|ra|ri|ru|ru|ru|re|ro|ro|ro|wa|wa|wa|wa|wo|wo)))(|||n)"
// Chinese Names
#define CHINESE_NAMES "(zh|x|q|sh|h)(ao|ian|uo|ou|ia)(|(l|w|c|p|b|m)(ao|ian|uo|ou|ia)(|n)|-(l|w|c|p|b|m)(ao|ian|uo|ou|ia)(|(d|j|q|l)(a|ai|iu|ao|i)))"
// Greek Names
#define GREEK_NAMES "<s<v|V>(tia)|s<v|V>(os)|B<v|V>c(ios)|B<v|V><c|C>v(ios|os)>"
// Hawaiian Names (1)
#define HAWAIIAN_NAMES_1 "((h|k|l|m|n|p|w|')|)(a|e|i|o|u)((h|k|l|m|n|p|w|')|)(a|e|i|o|u)(((h|k|l|m|n|p|w|')|)(a|e|i|o|u)|)(((h|k|l|m|n|p|w|')|)(a|e|i|o|u)|)(((h|k|l|m|n|p|w|')|)(a|e|i|o|u)|)(((h|k|l|m|n|p|w|')|)(a|e|i|o|u)|)"
// Hawaiian Names (2)
#define HAWAIIAN_NAMES_2 "((h|k|l|m|n|p|w|)(a|e|i|o|u|a'|e'|i'|o'|u'|ae|ai|ao|au|oi|ou|eu|ei)(k|l|m|n|p|)|)(h|k|l|m|n|p|w|)(a|e|i|o|u|a'|e'|i'|o'|u'|ae|ai|ao|au|oi|ou|eu|ei)(k|l|m|n|p|)"
// Old Latin Place Names
#define OLD_LATIN_PLACE_NAMES "sv(nia|lia|cia|sia)"
// Dragons (Pern)
#define DRAGONS_PERN "<<s|ss>|<VC|vC|B|BVs|Vs>><v|V|v|<v(l|n|r)|vc>>(th)"
// Dragon Riders
#define DRAGON_RIDERS "c'<s|cvc>"
// Pokemon
#define POKEMON "<i|s>v(mon|chu|zard|rtle)"
// Fantasy (Vowels, R, etc.)
#define FANTASY_VOWELS_R "(|(<B>|s|h|ty|ph|r))(i|ae|ya|ae|eu|ia|i|eo|ai|a)(lo|la|sri|da|dai|the|sty|lae|due|li|lly|ri|na|ral|sur|rith)(|(su|nu|sti|llo|ria|))(|(n|ra|p|m|lis|cal|deu|dil|suir|phos|ru|dru|rin|raap|rgue))"
// Fantasy (S, A, etc.)
#define FANTASY_S_A "(cham|chan|jisk|lis|frich|isk|lass|mind|sond|sund|ass|chad|lirt|und|mar|lis|il|<BVC>)(jask|ast|ista|adar|irra|im|ossa|assa|osia|ilsa|<vCv>)(|(an|ya|la|sta|sda|sya|st|nya))"
// Fantasy (H, L, etc.)
#define FANTASY_H_L "(ch|ch't|sh|cal|val|ell|har|shar|shal|rel|laen|ral|jh't|alr|ch|ch't|av)(|(is|al|ow|ish|ul|el|ar|iel))(aren|aeish|aith|even|adur|ulash|alith|atar|aia|erin|aera|ael|ira|iel|ahur|ishul)"
// Fantasy (N, L, etc.)
#define FANTASY_N_L "(ethr|qil|mal|er|eal|far|fil|fir|ing|ind|il|lam|quel|quar|quan|qar|pal|mal|yar|um|ard|enn|ey)(|(<vc>|on|us|un|ar|as|en|ir|ur|at|ol|al|an))(uard|wen|arn|on|il|ie|on|iel|rion|rian|an|ista|rion|rian|cil|mol|yon)"
// Fantasy (K, N, etc.)
#define FANTASY_K_N "(taith|kach|chak|kank|kjar|rak|kan|kaj|tach|rskal|kjol|jok|jor|jad|kot|kon|knir|kror|kol|tul|rhaok|rhak|krol|jan|kag|ryr)(<vc>|in|or|an|ar|och|un|mar|yk|ja|arn|ir|ros|ror)(|(mund|ard|arn|karr|chim|kos|rir|arl|kni|var|an|in|ir|a|i|as))"
// Fantasy (J, G, Z, etc.)
#define FANTASY_J_G_Z "(aj|ch|etz|etzl|tz|kal|gahn|kab|aj|izl|ts|jaj|lan|kach|chaj|qaq|jol|ix|az|biq|nam)(|(<vc>|aw|al|yes|il|ay|en|tom||oj|im|ol|aj|an|as))(aj|am|al|aqa|ende|elja|ich|ak|ix|in|ak|al|il|ek|ij|os|al|im)"
// Fantasy (K, J, Y, etc.)
#define FANTASY_K_J_Y "(yi|shu|a|be|na|chi|cha|cho|ksa|yi|shu)(th|dd|jj|sh|rr|mk|n|rk|y|jj|th)(us|ash|eni|akra|nai|ral|ect|are|el|urru|aja|al|uz|ict|arja|ichi|ural|iru|aki|esh)"
// Fantasy (S, E, etc.)
#define FANTASY_S_E "(syth|sith|srr|sen|yth|ssen|then|fen|ssth|kel|syn|est|bess|inth|nen|tin|cor|sv|iss|ith|sen|slar|ssil|sthen|svis|s|ss|s|ss)(|(tys|eus|yn|of|es|en|ath|elth|al|ell|ka|ith|yrrl|is|isl|yr|ast|iy))(us|yn|en|ens|ra|rg|le|en|ith|ast|zon|in|yn|ys)"
class Generator
{
typedef enum wrappers {
capitalizer,
reverser
} wrappers_t;
typedef enum group_types {
symbol,
literal
} group_types_t;
class Group {
std::stack<wrappers_t> wrappers;
std::vector<std::unique_ptr<Generator>> set;
public:
group_types_t type;
Group(group_types_t type_);
virtual ~Group() { }
std::unique_ptr<Generator> produce();
void split();
void wrap(wrappers_t type);
void add(std::unique_ptr<Generator>&& g);
virtual void add(char c);
};
class GroupSymbol : public Group {
public:
GroupSymbol();
void add(char c);
};
class GroupLiteral : public Group {
public:
GroupLiteral();
};
protected:
std::vector<std::unique_ptr<Generator>> generators;
public:
static const std::unordered_map<std::string, const std::vector<std::string>>& SymbolMap();
Generator();
Generator(const std::string& pattern, bool collapse_triples=true);
Generator(std::vector<std::unique_ptr<Generator>>&& generators_);
virtual ~Generator() = default;
virtual size_t combinations();
virtual size_t min();
virtual size_t max();
virtual std::string toString();
void add(std::unique_ptr<Generator>&& g);
};
class Random : public Generator
{
public:
Random();
Random(std::vector<std::unique_ptr<Generator>>&& generators_);
size_t combinations();
size_t min();
size_t max();
std::string toString();
};
class Sequence : public Generator
{
public:
Sequence();
Sequence(std::vector<std::unique_ptr<Generator>>&& generators_);
};
class Literal : public Generator
{
std::string value;
public:
Literal(const std::string& value_);
size_t combinations();
size_t min();
size_t max();
std::string toString();
};
class Reverser : public Generator {
public:
Reverser(std::unique_ptr<Generator>&& g);
std::string toString();
};
class Capitalizer : public Generator
{
public:
Capitalizer(std::unique_ptr<Generator>&& g);
std::string toString();
};
class Collapser : public Generator
{
public:
Collapser(std::unique_ptr<Generator>&& g);
std::string toString();
};
}
std::wstring towstring(const std::string& s);
std::string tostring(const std::wstring& s);

View File

@ -161,6 +161,7 @@ RULE_BOOL(Character, DismountWater, true, "Dismount horses when entering water")
RULE_BOOL(Character, UseNoJunkFishing, false, "Disregards junk items when fishing")
RULE_BOOL(Character, SoftDeletes, true, "When characters are deleted in character select, they are only soft deleted")
RULE_INT(Character, DefaultGuild, 0, "If not 0, new characters placed into the guild # indicated")
RULE_BOOL(Character, ProcessFearedProximity, false, "Processes proximity checks when feared")
RULE_CATEGORY_END()
RULE_CATEGORY(Mercs)

View File

@ -37,7 +37,7 @@
#define CURRENT_BINARY_DATABASE_VERSION 9152
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9026
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9027
#else
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
#endif

View File

@ -52,6 +52,10 @@ if (-e "eqemu_server_skip_update.txt") {
$skip_self_update_check = 1;
}
if (-e "eqemu_server_skip_maps_update.txt") {
$skip_self_maps_update_check = 1;
}
#::: Check for script self update
check_xml_to_json_conversion() if $ARGV[0] eq "convert_xml";
do_self_update_check_routine() if !$skip_self_update_check;
@ -460,7 +464,7 @@ sub do_installer_routines {
get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1);
}
map_files_fetch_bulk();
map_files_fetch_bulk() if !$skip_self_maps_update_check;
opcodes_fetch();
plugins_fetch();
quest_files_fetch();
@ -533,7 +537,10 @@ sub check_for_world_bootup_database_update {
if ($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world") {
print "[Update] Database up to date...\n";
exit;
if (trim($db_version[2]) == 0) {
print "[Update] Continuing bootup\n";
exit;
}
}
else {
#::: We ran world - Database needs to update, lets backup and run updates and continue world bootup
@ -1705,26 +1712,22 @@ sub fetch_server_dlls {
sub fetch_peq_db_full {
print "[Install] Downloading latest PEQ Database... Please wait...\n";
get_remote_file("http://edit.projecteq.net/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1);
get_remote_file("http://db.projecteq.net/api/v1/dump/latest", "updates_staged/peq-latest.zip", 1);
print "[Install] Downloaded latest PEQ Database... Extracting...\n";
unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/');
my $start_dir = "updates_staged/peq_db";
unzip('updates_staged/peq-latest.zip', 'updates_staged/peq_db/');
my $start_dir = "updates_staged/peq_db/peq-dump";
find(
sub { push @files, $File::Find::name unless -d; },
$start_dir
);
for my $file (@files) {
$destination_file = $file;
$destination_file =~ s/updates_staged\/peq_db\///g;
if ($file =~ /peqbeta|player_tables/i) {
$destination_file =~ s/updates_staged\/peq_db\/peq-dump\///g;
if ($file =~ /create_tables_content|create_tables_login|create_tables_player|create_tables_queryserv|create_tables_state|create_tables_system/i) {
print "[Install] DB :: Installing :: " . $destination_file . "\n";
get_mysql_result_from_file($file);
}
}
#::: PEQ DB baseline version
print get_mysql_result("DELETE FROM db_version");
print get_mysql_result("INSERT INTO `db_version` (`version`) VALUES (9130);");
}
sub map_files_fetch_bulk {

View File

@ -25,6 +25,7 @@
9024|2019_06_27_bots_pet_get_lost.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'petgetlost'|empty|
9025|2019_08_26_bots_owner_option_spawn_message.sql|SELECT * FROM db_version WHERE bots_version >= 9025|empty|
9026|2019_09_09_bots_owner_options_rework.sql|SHOW COLUMNS FROM `bot_owner_options` LIKE 'option_type'|empty|
9027|2020_03_30_bots_view_update.sql|SELECT * FROM db_version WHERE bots_version >= 9027|empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not

View File

@ -0,0 +1,24 @@
DROP VIEW IF EXISTS `vw_bot_character_mobs`;
-- Views
CREATE VIEW `vw_bot_character_mobs` AS
SELECT
_utf8'C' AS mob_type,
c.`id`,
c.`name`,
c.`class`,
c.`level`,
c.`last_login`,
c.`zone_id`,
c.`deleted_at`
FROM `character_data` AS c
UNION ALL
SELECT _utf8'B' AS mob_type,
b.`bot_id` AS id,
b.`name`,
b.`class`,
b.`level`,
b.`last_spawn` AS last_login,
b.`zone_id`,
NULL AS `deleted_at`
FROM `bot_data` AS b;

View File

@ -1,7 +1,3 @@
ALTER TABLE `aa_actions` ENGINE=InnoDB;
ALTER TABLE `aa_effects` ENGINE=InnoDB;
ALTER TABLE `aa_required_level_cost` ENGINE=InnoDB;
ALTER TABLE `aa_timers` ENGINE=InnoDB;
ALTER TABLE `account_flags` ENGINE=InnoDB;
ALTER TABLE `account_ip` ENGINE=InnoDB;
ALTER TABLE `account` ENGINE=InnoDB;

View File

@ -46,6 +46,7 @@
#include "clientlist.h"
#include "wguild_mgr.h"
#include "sof_char_create_data.h"
#include "../common/namegenerator/namegen.h"
#include <iostream>
#include <iomanip>
@ -533,80 +534,14 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app)
return true;
}
bool Client::HandleGenerateRandomNamePacket(const EQApplicationPacket *app) {
// creates up to a 10 char name
char vowels[18]="aeiouyaeiouaeioe";
char cons[48]="bcdfghjklmnpqrstvwxzybcdgklmnprstvwbcdgkpstrkd";
char rndname[17]="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
char paircons[33]="ngrkndstshthphsktrdrbrgrfrclcr";
int rndnum=emu_random.Int(0, 75),n=1;
bool dlc=false;
bool vwl=false;
bool dbl=false;
if (rndnum>63)
{ // rndnum is 0 - 75 where 64-75 is cons pair, 17-63 is cons, 0-16 is vowel
rndnum=(rndnum-61)*2; // name can't start with "ng" "nd" or "rk"
rndname[0]=paircons[rndnum];
rndname[1]=paircons[rndnum+1];
n=2;
}
else if (rndnum>16)
{
rndnum-=17;
rndname[0]=cons[rndnum];
}
else
{
rndname[0]=vowels[rndnum];
vwl=true;
}
int namlen=emu_random.Int(5, 10);
for (int i=n;i<namlen;i++)
{
dlc=false;
if (vwl) //last char was a vowel
{ // so pick a cons or cons pair
rndnum=emu_random.Int(0, 62);
if (rndnum>46)
{ // pick a cons pair
if (i>namlen-3) // last 2 chars in name?
{ // name can only end in cons pair "rk" "st" "sh" "th" "ph" "sk" "nd" or "ng"
rndnum=emu_random.Int(0, 7)*2;
}
else
{ // pick any from the set
rndnum=(rndnum-47)*2;
}
rndname[i]=paircons[rndnum];
rndname[i+1]=paircons[rndnum+1];
dlc=true; // flag keeps second letter from being doubled below
i+=1;
}
else
{ // select a single cons
rndname[i]=cons[rndnum];
}
}
else
{ // select a vowel
rndname[i]=vowels[emu_random.Int(0, 16)];
}
vwl=!vwl;
if (!dbl && !dlc)
{ // one chance at double letters in name
if (!emu_random.Int(0, i+9)) // chances decrease towards end of name
{
rndname[i+1]=rndname[i];
dbl=true;
i+=1;
}
}
}
bool Client::HandleGenerateRandomNamePacket(const EQApplicationPacket *app)
{
NameGen::Generator generator("!Bvss");
std::string random_name = generator.toString();
rndname[0]=toupper(rndname[0]);
NameGeneration_Struct* ngs = (NameGeneration_Struct*)app->pBuffer;
memset(ngs->name,0,64);
strcpy(ngs->name,rndname);
auto *ngs = (NameGeneration_Struct *) app->pBuffer;
memset(ngs->name, 0, 64);
strcpy(ngs->name, random_name.c_str());
QueuePacket(app);
return true;

View File

@ -432,6 +432,7 @@ int main(int argc, char** argv) {
RegisterConsoleFunctions(console);
}
zoneserver_list.Init();
std::unique_ptr<EQ::Net::ServertalkServer> server_connection;
server_connection.reset(new EQ::Net::ServertalkServer());

View File

@ -39,7 +39,6 @@ ZSList::ZSList()
{
NextID = 1;
CurGroupID = 1;
LastAllocatedPort = 0;
memset(pLockedZones, 0, sizeof(pLockedZones));
m_tick.reset(new EQ::Timer(5000, true, std::bind(&ZSList::OnTick, this, std::placeholders::_1)));
@ -76,7 +75,12 @@ void ZSList::Remove(const std::string &uuid)
auto iter = zone_server_list.begin();
while (iter != zone_server_list.end()) {
if ((*iter)->GetUUID().compare(uuid) == 0) {
auto port = (*iter)->GetCPort();
zone_server_list.erase(iter);
if (port != 0) {
m_ports_free.push_back(port);
}
return;
}
iter++;
@ -239,6 +243,14 @@ bool ZSList::SetLockedZone(uint16 iZoneID, bool iLock) {
return false;
}
void ZSList::Init()
{
const WorldConfig* Config = WorldConfig::get();
for (uint16 i = Config->ZonePortLow; i <= Config->ZonePortHigh; ++i) {
m_ports_free.push_back(i);
}
}
bool ZSList::IsZoneLocked(uint16 iZoneID) {
for (auto &zone : pLockedZones) {
if (zone == iZoneID)
@ -577,30 +589,15 @@ void ZSList::RebootZone(const char* ip1, uint16 port, const char* ip2, uint32 sk
safe_delete_array(tmp);
}
uint16 ZSList::GetAvailableZonePort()
uint16 ZSList::GetAvailableZonePort()
{
const WorldConfig *Config = WorldConfig::get();
int i;
uint16 port = 0;
if (LastAllocatedPort == 0)
i = Config->ZonePortLow;
else
i = LastAllocatedPort + 1;
while (i != LastAllocatedPort && port == 0) {
if (i>Config->ZonePortHigh)
i = Config->ZonePortLow;
if (!FindByPort(i)) {
port = i;
break;
}
i++;
if (m_ports_free.empty()) {
return 0;
}
LastAllocatedPort = port;
return port;
auto first = m_ports_free.front();
m_ports_free.pop_front();
return first;
}
uint32 ZSList::TriggerBootup(uint32 iZoneID, uint32 iInstanceID) {

View File

@ -7,6 +7,7 @@
#include "../common/event/timer.h"
#include <vector>
#include <memory>
#include <deque>
class WorldTCPConnection;
class ServerPacket;
@ -22,6 +23,7 @@ public:
ZSList();
~ZSList();
void Init();
bool IsZoneLocked(uint16 iZoneID);
bool SendPacket(ServerPacket *pack);
bool SendPacket(uint32 zoneid, ServerPacket *pack);
@ -73,8 +75,7 @@ private:
uint32 NextID;
uint16 pLockedZones[MaxLockedZones];
uint32 CurGroupID;
uint16 LastAllocatedPort;
std::deque<uint16> m_ports_free;
std::unique_ptr<EQ::Timer> m_tick;
std::unique_ptr<EQ::Timer> m_keepalive;

View File

@ -4018,6 +4018,14 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
//Message(Chat::Red, "You cant cast right now, you arent in control of yourself!");
return;
}
// Hack for broken RoF2 which allows casting after a zoned IVU/IVA
if (invisible_undead || invisible_animals) {
BuffFadeByEffect(SE_InvisVsAnimals);
BuffFadeByEffect(SE_InvisVsUndead);
BuffFadeByEffect(SE_InvisVsUndead2);
BuffFadeByEffect(SE_Invisibility); // Included per JJ for completeness - client handles this one atm
}
CastSpell_Struct* castspell = (CastSpell_Struct*)app->pBuffer;

View File

@ -196,6 +196,7 @@ int command_init(void)
command_add("disarmtrap", "Analog for ldon disarm trap for the newer clients since we still don't have it working.", 80, command_disarmtrap) ||
command_add("distance", "- Reports the distance between you and your target.", 80, command_distance) ||
command_add("doanim", "[animnum] [type] - Send an EmoteAnim for you or your target", 50, command_doanim) ||
command_add("editmassrespawn", "[name-search] [second-value] - Mass (Zone wide) NPC respawn timer editing command", 100, command_editmassrespawn) ||
command_add("emote", "['name'/'world'/'zone'] [type] [message] - Send an emote message", 80, command_emote) ||
command_add("emotesearch", "Searches NPC Emotes", 80, command_emotesearch) ||
command_add("emoteview", "Lists all NPC Emotes", 80, command_emoteview) ||
@ -6497,6 +6498,144 @@ void command_doanim(Client *c, const Seperator *sep)
c->DoAnim(atoi(sep->arg[1]),atoi(sep->arg[2]));
}
void command_editmassrespawn(Client* c, const Seperator* sep)
{
if (strcasecmp(sep->arg[1], "usage") == 0) {
c->Message(Chat::White, "#editmassrespawn [exact_match: =]npc_type_name new_respawn_seconds (apply)");
return;
}
std::string search_npc_type;
if (sep->arg[1]) {
search_npc_type = sep->arg[1];
}
int change_respawn_seconds = 0;
if (sep->arg[2] && sep->IsNumber(2)) {
change_respawn_seconds = atoi(sep->arg[2]);
}
bool change_apply = false;
if (sep->arg[3] && strcasecmp(sep->arg[3], "apply") == 0) {
change_apply = true;
}
std::string search_encapsulator = "%";
if (search_npc_type[0] == '=') {
search_npc_type = search_npc_type.substr(1);
search_encapsulator = "";
}
std::string query = fmt::format(
SQL(
SELECT npc_types.id, spawn2.spawngroupID, spawn2.id, npc_types.name, spawn2.respawntime
FROM spawn2
INNER JOIN spawnentry ON spawn2.spawngroupID = spawnentry.spawngroupID
INNER JOIN npc_types ON spawnentry.npcID = npc_types.id
WHERE spawn2.zone LIKE '{}'
AND spawn2.version = '{}'
AND npc_types.name LIKE '{}{}{}'
ORDER BY npc_types.id, spawn2.spawngroupID, spawn2.id
),
zone->GetShortName(),
zone->GetInstanceVersion(),
search_encapsulator,
search_npc_type,
search_encapsulator
);
std::string status = "(Searching)";
if (change_apply) {
status = "(Applying)";
}
int results_count = 0;
auto results = database.QueryDatabase(query);
if (results.Success() && results.RowCount()) {
results_count = results.RowCount();
for (auto row : results) {
c->Message(
Chat::Yellow,
fmt::format(
"NPC (npcid:{}) (sgid:{}) (s2id:{}) [{}] Respawn: Current [{}] New [{}] {}",
row[0],
row[1],
row[2],
row[3],
row[4],
change_respawn_seconds,
status
).c_str()
);
}
c->Message(Chat::Yellow, "Found (%i) NPC's that match this search...", results_count);
if (change_respawn_seconds > 0) {
if (change_apply) {
results = database.QueryDatabase(
fmt::format(
SQL(
UPDATE spawn2
SET respawntime = '{}'
WHERE id IN (
SELECT spawn2.id
FROM spawn2
INNER JOIN spawnentry ON spawn2.spawngroupID = spawnentry.spawngroupID
INNER JOIN npc_types ON spawnentry.npcID = npc_types.id
WHERE spawn2.zone LIKE '{}'
AND spawn2.version = '{}'
AND npc_types.name LIKE '{}{}{}'
)
),
change_respawn_seconds,
zone->GetShortName(),
zone->GetInstanceVersion(),
search_encapsulator,
search_npc_type,
search_encapsulator
)
);
if (results.Success()) {
c->Message(Chat::Yellow, "Changes applied to (%i) NPC 'Spawn2' entries", results_count);
zone->Repop();
}
else {
c->Message(Chat::Yellow, "Found (0) NPC's that match this search...");
}
}
else {
std::string saylink = fmt::format(
"#editmassrespawn {}{} {} apply",
(search_encapsulator.empty() ? "=" : ""),
search_npc_type,
change_respawn_seconds
);
c->Message(
Chat::Yellow, "To apply these changes, click <%s> or type [%s]",
EQEmu::SayLinkEngine::GenerateQuestSaylink(saylink, false, "Apply").c_str(),
saylink.c_str()
);
}
}
}
else {
c->Message(Chat::Yellow, "Found (0) NPC's that match this search...");
}
}
void command_randomfeatures(Client *c, const Seperator *sep)
{
Mob *target=c->GetTarget();
@ -7807,7 +7946,7 @@ void command_npcemote(Client *c, const Seperator *sep)
void command_npceditmass(Client *c, const Seperator *sep)
{
if (strcasecmp(sep->arg[1], "usage") == 0) {
c->Message(Chat::White, "#npceditmass search_column [exact_match: =]search_value change_column change_value");
c->Message(Chat::White, "#npceditmass search_column [exact_match: =]search_value change_column change_value (apply)");
return;
}
@ -7955,7 +8094,7 @@ void command_npceditmass(Client *c, const Seperator *sep)
std::string saylink = fmt::format(
"#npceditmass {} {}{} {} {} apply",
search_column,
(exact_match ? '=' : '\0'),
(exact_match ? "=" : ""),
search_value,
change_column,
change_value

View File

@ -91,6 +91,7 @@ void command_disablerecipe(Client *c, const Seperator *sep);
void command_disarmtrap(Client *c, const Seperator *sep);
void command_distance(Client *c, const Seperator *sep);
void command_doanim(Client *c, const Seperator *sep);
void command_editmassrespawn(Client* c, const Seperator* sep);
void command_emote(Client *c, const Seperator *sep);
void command_emotesearch(Client* c, const Seperator *sep);
void command_emoteview(Client* c, const Seperator *sep);

View File

@ -822,6 +822,54 @@ XS(XS__isdisctome) {
XSRETURN(1);
}
XS(XS__getracename);
XS(XS__getracename) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: quest::getracename(uint16 race_id)");
dXSTARG;
uint16 race_id = (int) SvIV(ST(0));
std::string race_name = quest_manager.getracename(race_id);
sv_setpv(TARG, race_name.c_str());
XSprePUSH;
PUSHTARG;
XSRETURN(1);
}
XS(XS__getspellname);
XS(XS__getspellname) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: quest::getspellname(uint32 spell_id)");
dXSTARG;
uint32 spell_id = (int) SvIV(ST(0));
std::string spell_name = quest_manager.getspellname(spell_id);
sv_setpv(TARG, spell_name.c_str());
XSprePUSH;
PUSHTARG;
XSRETURN(1);
}
XS(XS__getskillname);
XS(XS__getskillname) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: quest::getskillname(int skill_id)");
dXSTARG;
int skill_id = (int) SvIV(ST(0));
std::string skill_name = quest_manager.getskillname(skill_id);
sv_setpv(TARG, skill_name.c_str());
XSprePUSH;
PUSHTARG;
XSRETURN(1);
}
XS(XS__safemove);
XS(XS__safemove) {
dXSARGS;
@ -2342,7 +2390,6 @@ XS(XS__updatetaskactivity) {
XS(XS__resettaskactivity);
XS(XS__resettaskactivity) {
dXSARGS;
unsigned int task, activity;
if (items == 2) {
int task_id = (int) SvIV(ST(0));
int activity_id = (int) SvIV(ST(1));
@ -2613,6 +2660,23 @@ XS(XS__istaskappropriate) {
XSRETURN(1);
}
XS(XS__gettaskname);
XS(XS__gettaskname) {
dXSARGS;
if (items != 1) {
Perl_croak(aTHX_ "Usage: quest::gettaskname(uint32 task_id)");
}
dXSTARG;
uint32 task_id = (int) SvIV(ST(0));
std::string task_name = quest_manager.gettaskname(task_id);
sv_setpv(TARG, task_name.c_str());
XSprePUSH;
PUSHTARG;
XSRETURN(1);
}
XS(XS__popup); // prototype to pass -Wmissing-prototypes
XS(XS__popup) {
dXSARGS;
@ -2797,6 +2861,51 @@ XS(XS__collectitems) {
XSRETURN_IV(quantity);
}
XS(XS__countitem);
XS(XS__countitem) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: quest::countitem(int item_id)");
uint32 item_id = (int) SvIV(ST(0));
int quantity = quest_manager.countitem(item_id);
XSRETURN_IV(quantity);
}
XS(XS__getitemname);
XS(XS__getitemname) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: quest::getitemname(uint32 item_id)");
dXSTARG;
uint32 item_id = (int) SvIV(ST(0));
std::string item_name = quest_manager.getitemname(item_id);
sv_setpv(TARG, item_name.c_str());
XSprePUSH;
PUSHTARG;
XSRETURN(1);
}
XS(XS__getnpcnamebyid);
XS(XS__getnpcnamebyid) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: quest::getnpcnamebyid(uint32 npc_id)");
dXSTARG;
uint32 npc_id = (int) SvIV(ST(0));
const char *npc_name = quest_manager.getnpcnamebyid(npc_id);
sv_setpv(TARG, npc_name);
XSprePUSH;
PUSHTARG;
XSRETURN(1);
}
XS(XS__UpdateSpawnTimer);
XS(XS__UpdateSpawnTimer) {
dXSARGS;
@ -3063,6 +3172,25 @@ XS(XS__RemoveFromInstanceByCharID) {
XSRETURN_EMPTY;
}
XS(XS__CheckInstanceByCharID);
XS(XS__CheckInstanceByCharID) {
dXSARGS;
if (items != 2) {
Perl_croak(aTHX_ "Usage: quest::CheckInstanceByCharID(uint16 instance_id, uint32 char_id)");
}
bool RETVAL;
dXSTARG;
uint16 instance_id = (int) SvUV(ST(0));
uint32 char_id = (int) SvUV(ST(1));
RETVAL = quest_manager.CheckInstanceByCharID(instance_id, char_id);
XSprePUSH;
PUSHu((IV) RETVAL);
XSRETURN(1);
}
XS(XS__RemoveAllFromInstance);
XS(XS__RemoveAllFromInstance) {
dXSARGS;
@ -3151,6 +3279,57 @@ XS(XS__saylink) {
XSRETURN(1);
}
XS(XS__getcharnamebyid);
XS(XS__getcharnamebyid) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: quest::getcharnamebyid(uint32 char_id)");
dXSTARG;
Const_char *RETVAL;
uint32 char_id = (int) SvUV(ST(0));
RETVAL = quest_manager.getcharnamebyid(char_id);
sv_setpv(TARG, RETVAL);
XSprePUSH;
PUSHTARG;
}
XS(XS__getcharidbyname);
XS(XS__getcharidbyname) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: quest::getcharidbyname(string name)");
dXSTARG;
uint32 RETVAL;
const char *name = (const char *) SvPV_nolen(ST(0));
RETVAL = quest_manager.getcharidbyname(name);
XSprePUSH;
PUSHu((UV)RETVAL);
XSRETURN(1);
}
XS(XS__getcurrencyid);
XS(XS__getcurrencyid) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: quest::getcurrencyid(uint32 item_id)");
dXSTARG;
int RETVAL;
uint32 item_id = (int) SvUV(ST(0));;
RETVAL = quest_manager.getcurrencyid(item_id);
XSprePUSH;
PUSHi((IV)RETVAL);
XSRETURN(1);
}
XS(XS__getguildnamebyid);
XS(XS__getguildnamebyid) {
dXSARGS;
@ -3927,6 +4106,7 @@ EXTERN_C XS(boot_quest) {
newXS(strcpy(buf, "RemoveAllFromInstance"), XS__RemoveAllFromInstance, file);
newXS(strcpy(buf, "RemoveFromInstance"), XS__RemoveFromInstance, file);
newXS(strcpy(buf, "RemoveFromInstanceByCharID"), XS__RemoveFromInstanceByCharID, file);
newXS(strcpy(buf, "CheckInstanceByCharID"), XS__CheckInstanceByCharID, file);
newXS(strcpy(buf, "SendMail"), XS__SendMail, file);
newXS(strcpy(buf, "SetRunning"), XS__SetRunning, file);
newXS(strcpy(buf, "activespeakactivity"), XS__activespeakactivity, file);
@ -3951,6 +4131,7 @@ EXTERN_C XS(boot_quest) {
newXS(strcpy(buf, "clearspawntimers"), XS__clearspawntimers, file);
newXS(strcpy(buf, "collectitems"), XS__collectitems, file);
newXS(strcpy(buf, "completedtasksinset"), XS__completedtasksinset, file);
newXS(strcpy(buf, "countitem"), XS__countitem, file);
newXS(strcpy(buf, "createdoor"), XS__CreateDoor, file);
newXS(strcpy(buf, "creategroundobject"), XS__CreateGroundObject, file);
newXS(strcpy(buf, "creategroundobjectfrommodel"), XS__CreateGroundObjectFromModel, file);
@ -3990,18 +4171,27 @@ EXTERN_C XS(boot_quest) {
newXS(strcpy(buf, "follow"), XS__follow, file);
newXS(strcpy(buf, "forcedoorclose"), XS__forcedoorclose, file);
newXS(strcpy(buf, "forcedooropen"), XS__forcedooropen, file);
newXS(strcpy(buf, "getcharidbyname"), XS__getcharidbyname, file);
newXS(strcpy(buf, "getcurrencyid"), XS__getcurrencyid, file);
newXS(strcpy(buf, "getinventoryslotid"), XS__getinventoryslotid, file);
newXS(strcpy(buf, "getitemname"), XS__getitemname, file);
newXS(strcpy(buf, "getItemName"), XS_qc_getItemName, file);
newXS(strcpy(buf, "getnpcnamebyid"), XS__getnpcnamebyid, file);
newXS(strcpy(buf, "get_spawn_condition"), XS__get_spawn_condition, file);
newXS(strcpy(buf, "getcharnamebyid"), XS__getcharnamebyid, file);
newXS(strcpy(buf, "getguildnamebyid"), XS__getguildnamebyid, file);
newXS(strcpy(buf, "getguildidbycharid"), XS__getguildidbycharid, file);
newXS(strcpy(buf, "getgroupidbycharid"), XS__getgroupidbycharid, file);
newXS(strcpy(buf, "getraididbycharid"), XS__getraididbycharid, file);
newXS(strcpy(buf, "getracename"), XS__getracename, file);
newXS(strcpy(buf, "getspellname"), XS__getspellname, file);
newXS(strcpy(buf, "getskillname"), XS__getskillname, file);
newXS(strcpy(buf, "getlevel"), XS__getlevel, file);
newXS(strcpy(buf, "getplayerburiedcorpsecount"), XS__getplayerburiedcorpsecount, file);
newXS(strcpy(buf, "getplayercorpsecount"), XS__getplayercorpsecount, file);
newXS(strcpy(buf, "getplayercorpsecountbyzoneid"), XS__getplayercorpsecountbyzoneid, file);
newXS(strcpy(buf, "gettaskactivitydonecount"), XS__gettaskactivitydonecount, file);
newXS(strcpy(buf, "gettaskname"), XS__gettaskname, file);
newXS(strcpy(buf, "givecash"), XS__givecash, file);
newXS(strcpy(buf, "gmmove"), XS__gmmove, file);
newXS(strcpy(buf, "gmsay"), XS__gmsay, file);

View File

@ -393,6 +393,18 @@ bool lua_is_disc_tome(int item_id) {
return quest_manager.isdisctome(item_id);
}
std::string lua_get_race_name(uint32 race_id) {
return quest_manager.getracename(race_id);
}
std::string lua_get_spell_name(uint32 spell_id) {
return quest_manager.getspellname(spell_id);
}
std::string lua_get_skill_name(int skill_id) {
return quest_manager.getskillname(skill_id);
}
void lua_safe_move() {
quest_manager.safemove();
}
@ -729,6 +741,10 @@ bool lua_is_task_appropriate(int task) {
return quest_manager.istaskappropriate(task);
}
std::string lua_get_task_name(uint32 task_id) {
return quest_manager.gettaskname(task_id);
}
void lua_popup(const char *title, const char *text, uint32 id, uint32 buttons, uint32 duration) {
quest_manager.popup(title, text, id, buttons, duration);
}
@ -781,6 +797,10 @@ int lua_collect_items(uint32 item_id, bool remove) {
return quest_manager.collectitems(item_id, remove);
}
int lua_count_item(uint32 item_id) {
return quest_manager.countitem(item_id);
}
void lua_update_spawn_timer(uint32 id, uint32 new_time) {
quest_manager.UpdateSpawnTimer(id, new_time);
}
@ -803,6 +823,10 @@ std::string lua_item_link(int item_id) {
return quest_manager.varlink(text, item_id);
}
std::string lua_get_item_name(uint32 item_id) {
return quest_manager.getitemname(item_id);
}
std::string lua_say_link(const char *phrase, bool silent, const char *link_name) {
char text[256] = { 0 };
strncpy(text, phrase, 255);
@ -854,6 +878,18 @@ bool lua_delete_data(std::string bucket_key) {
return DataBucket::DeleteData(bucket_key);
}
const char *lua_get_char_name_by_id(uint32 char_id) {
return database.GetCharNameByID(char_id);
}
uint32 lua_get_char_id_by_name(const char* name) {
return quest_manager.getcharidbyname(name);
}
int lua_get_currency_id(uint32 item_id) {
return quest_manager.getcurrencyid(item_id);
}
const char *lua_get_guild_name_by_id(uint32 guild_id) {
return quest_manager.getguildnamebyid(guild_id);
}
@ -866,6 +902,10 @@ int lua_get_group_id_by_char_id(uint32 char_id) {
return database.GetGroupIDByCharID(char_id);
}
const char *lua_get_npc_name_by_id(uint32 npc_id) {
return quest_manager.getnpcnamebyid(npc_id);
}
int lua_get_raid_id_by_char_id(uint32 char_id) {
return database.GetRaidIDByCharID(char_id);
}
@ -922,6 +962,10 @@ void lua_remove_from_instance_by_char_id(uint32 instance_id, uint32 char_id) {
quest_manager.RemoveFromInstanceByCharID(instance_id, char_id);
}
bool lua_check_instance_by_char_id(uint32 instance_id, uint32 char_id) {
return quest_manager.CheckInstanceByCharID(instance_id, char_id);
}
void lua_remove_all_from_instance(uint32 instance_id) {
quest_manager.RemoveAllFromInstance(instance_id);
}
@ -1644,6 +1688,9 @@ luabind::scope lua_register_general() {
luabind::def("depop_zone", &lua_depop_zone),
luabind::def("repop_zone", &lua_repop_zone),
luabind::def("is_disc_tome", &lua_is_disc_tome),
luabind::def("get_race_name", (std::string(*)(uint16))&lua_get_race_name),
luabind::def("get_spell_name", (std::string(*)(uint32))&lua_get_spell_name),
luabind::def("get_skill_name", (std::string(*)(int))&lua_get_skill_name),
luabind::def("safe_move", &lua_safe_move),
luabind::def("rain", &lua_rain),
luabind::def("snow", &lua_snow),
@ -1711,6 +1758,7 @@ luabind::scope lua_register_general() {
luabind::def("active_tasks_in_set", &lua_active_tasks_in_set),
luabind::def("completed_tasks_in_set", &lua_completed_tasks_in_set),
luabind::def("is_task_appropriate", &lua_is_task_appropriate),
luabind::def("get_task_name", (std::string(*)(uint32))&lua_get_task_name),
luabind::def("popup", &lua_popup),
luabind::def("clear_spawn_timers", &lua_clear_spawn_timers),
luabind::def("zone_emote", &lua_zone_emote),
@ -1724,11 +1772,13 @@ luabind::scope lua_register_general() {
luabind::def("create_door", &lua_create_door),
luabind::def("modify_npc_stat", &lua_modify_npc_stat),
luabind::def("collect_items", &lua_collect_items),
luabind::def("count_item", &lua_count_item),
luabind::def("update_spawn_timer", &lua_update_spawn_timer),
luabind::def("merchant_set_item", (void(*)(uint32,uint32))&lua_merchant_set_item),
luabind::def("merchant_set_item", (void(*)(uint32,uint32,uint32))&lua_merchant_set_item),
luabind::def("merchant_count_item", &lua_merchant_count_item),
luabind::def("item_link", &lua_item_link),
luabind::def("get_item_name", (std::string(*)(uint32))&lua_get_item_name),
luabind::def("say_link", (std::string(*)(const char*,bool,const char*))&lua_say_link),
luabind::def("say_link", (std::string(*)(const char*,bool))&lua_say_link),
luabind::def("say_link", (std::string(*)(const char*))&lua_say_link),
@ -1739,9 +1789,13 @@ luabind::scope lua_register_general() {
luabind::def("set_data", (void(*)(std::string, std::string))&lua_set_data),
luabind::def("set_data", (void(*)(std::string, std::string, std::string))&lua_set_data),
luabind::def("delete_data", (bool(*)(std::string))&lua_delete_data),
luabind::def("get_char_name_by_id", &lua_get_char_name_by_id),
luabind::def("get_char_id_by_name", (uint32(*)(const char*))&lua_get_char_id_by_name),
luabind::def("get_currency_id", &lua_get_currency_id),
luabind::def("get_guild_name_by_id", &lua_get_guild_name_by_id),
luabind::def("get_guild_id_by_char_id", &lua_get_guild_id_by_char_id),
luabind::def("get_group_id_by_char_id", &lua_get_group_id_by_char_id),
luabind::def("get_npc_name_by_id", &lua_get_npc_name_by_id),
luabind::def("get_raid_id_by_char_id", &lua_get_raid_id_by_char_id),
luabind::def("create_instance", &lua_create_instance),
luabind::def("destroy_instance", &lua_destroy_instance),
@ -1757,6 +1811,7 @@ luabind::scope lua_register_general() {
luabind::def("assign_raid_to_instance", &lua_assign_raid_to_instance),
luabind::def("remove_from_instance", &lua_remove_from_instance),
luabind::def("remove_from_instance_by_char_id", &lua_remove_from_instance_by_char_id),
luabind::def("check_instance_by_char_id", (bool(*)(uint16, uint32))&lua_check_instance_by_char_id),
luabind::def("remove_all_from_instance", &lua_remove_all_from_instance),
luabind::def("flag_instance_by_group_leader", &lua_flag_instance_by_group_leader),
luabind::def("flag_instance_by_raid_leader", &lua_flag_instance_by_raid_leader),

View File

@ -67,6 +67,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/event/timer.h"
#include "../common/net/eqstream.h"
#include "../common/net/servertalk_server.h"
#include "../common/content/world_content_service.h"
#include <iostream>
#include <string>
@ -93,9 +94,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#endif
#include "../common/content/world_content_service.h"
volatile bool RunLoops = true;
extern volatile bool is_zone_loaded;
@ -609,19 +607,19 @@ int main(int argc, char** argv) {
return 0;
}
void Shutdown()
{
Zone::Shutdown(true);
LogInfo("Shutting down...");
LogSys.CloseFileLogs();
EQ::EventLoop::Get().Shutdown();
}
void CatchSignal(int sig_num) {
#ifdef _WINDOWS
LogInfo("Recieved signal: [{}]", sig_num);
#endif
RunLoops = false;
}
void Shutdown()
{
Zone::Shutdown(true);
RunLoops = false;
LogInfo("Shutting down...");
LogSys.CloseFileLogs();
Shutdown();
}
/* Update Window Title with relevant information */

View File

@ -747,6 +747,13 @@ void Client::AI_Process()
RunTo(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z);
}
}
if (RuleB(Character, ProcessFearedProximity) && proximity_timer.Check()) {
entity_list.ProcessMove(this, glm::vec3(GetX(), GetY(), GetZ()));
if (RuleB(TaskSystem, EnableTaskSystem) && RuleB(TaskSystem, EnableTaskProximity))
ProcessTaskProximities(GetX(), GetY(), GetZ());
m_Proximity = glm::vec3(GetX(), GetY(), GetZ());
}
return;
}

View File

@ -962,7 +962,7 @@ void NPC::Depop(bool StartSpawnTimer) {
}
bool NPC::DatabaseCastAccepted(int spell_id) {
for (int i=0; i < 12; i++) {
for (int i=0; i < EFFECT_COUNT; i++) {
switch(spells[spell_id].effectid[i]) {
case SE_Stamina: {
if(IsEngaged() && GetHPRatio() < 100)

View File

@ -906,6 +906,31 @@ bool QuestManager::isdisctome(int item_id) {
return(true);
}
std::string QuestManager::getracename(uint16 race_id) {
return GetRaceIDName(race_id);
}
std::string QuestManager::getspellname(uint32 spell_id) {
if (!IsValidSpell(spell_id)) {
return "INVALID SPELL ID IN GETSPELLNAME";
}
std::string spell_name = GetSpellName(spell_id);
return spell_name;
}
std::string QuestManager::getskillname(int skill_id) {
if (skill_id >= 0 && skill_id < EQEmu::skills::SkillCount) {
std::map<EQEmu::skills::SkillType, std::string> Skills = EQEmu::skills::GetSkillTypeMap();
for (auto skills_iter : Skills) {
if (skill_id == skills_iter.first) {
return skills_iter.second;
}
}
}
return std::string();
}
void QuestManager::safemove() {
QuestManagerCurrentQuestVars();
if (initiator && initiator->IsClient())
@ -2432,6 +2457,16 @@ bool QuestManager::istaskappropriate(int task) {
return false;
}
std::string QuestManager::gettaskname(uint32 task_id) {
QuestManagerCurrentQuestVars();
if (RuleB(TaskSystem, EnableTaskSystem)) {
return taskmanager->GetTaskName(task_id);
}
return std::string();
}
void QuestManager::clearspawntimers() {
if(!zone)
return;
@ -2580,6 +2615,32 @@ int QuestManager::collectitems(uint32 item_id, bool remove)
return quantity;
}
int QuestManager::countitem(uint32 item_id) {
QuestManagerCurrentQuestVars();
int quantity = 0;
EQEmu::ItemInstance *item = nullptr;
static const int16 slots[][2] = {
{ EQEmu::invslot::POSSESSIONS_BEGIN, EQEmu::invslot::POSSESSIONS_END },
{ EQEmu::invbag::GENERAL_BAGS_BEGIN, EQEmu::invbag::GENERAL_BAGS_END },
{ EQEmu::invbag::CURSOR_BAG_BEGIN, EQEmu::invbag::CURSOR_BAG_END},
{ EQEmu::invslot::BANK_BEGIN, EQEmu::invslot::BANK_END },
{ EQEmu::invbag::BANK_BAGS_BEGIN, EQEmu::invbag::BANK_BAGS_END },
{ EQEmu::invslot::SHARED_BANK_BEGIN, EQEmu::invslot::SHARED_BANK_END },
{ EQEmu::invbag::SHARED_BANK_BAGS_BEGIN, EQEmu::invbag::SHARED_BANK_BAGS_END },
};
const size_t size = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < size; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
item = initiator->GetInv().GetItem(slot_id);
if (item && item->GetID() == item_id) {
quantity += item->IsStackable() ? item->GetCharges() : 1;
}
}
}
return quantity;
}
void QuestManager::UpdateSpawnTimer(uint32 id, uint32 newTime)
{
bool found = false;
@ -2670,6 +2731,23 @@ const char* QuestManager::varlink(char* perltext, int item_id) {
return perltext;
}
std::string QuestManager::getitemname(uint32 item_id) {
const EQEmu::ItemData* item_data = database.GetItem(item_id);
if (!item_data) {
return "INVALID ITEM ID IN GETITEMNAME";
}
std::string item_name = item_data->Name;
return item_name;
}
const char *QuestManager::getnpcnamebyid(uint32 npc_id) {
if (npc_id > 0) {
return database.GetNPCNameByID(npc_id);
}
return "";
}
uint16 QuestManager::CreateInstance(const char *zone, int16 version, uint32 duration)
{
QuestManagerCurrentQuestVars();
@ -2811,6 +2889,10 @@ void QuestManager::RemoveFromInstanceByCharID(uint16 instance_id, uint32 char_id
database.RemoveClientFromInstance(instance_id, char_id);
}
bool QuestManager::CheckInstanceByCharID(uint16 instance_id, uint32 char_id) {
return database.CharacterInInstanceGroup(instance_id, char_id);
}
void QuestManager::RemoveAllFromInstance(uint16 instance_id)
{
QuestManagerCurrentQuestVars();
@ -2869,6 +2951,28 @@ std::string QuestManager::saylink(char *saylink_text, bool silent, const char *l
return EQEmu::SayLinkEngine::GenerateQuestSaylink(saylink_text, silent, link_name);
}
const char* QuestManager::getcharnamebyid(uint32 char_id) {
if (char_id > 0) {
return database.GetCharNameByID(char_id);
}
return "";
}
uint32 QuestManager::getcharidbyname(const char* name) {
return database.GetCharacterID(name);
}
int QuestManager::getcurrencyid(uint32 item_id) {
auto iter = zone->AlternateCurrencies.begin();
while (iter != zone->AlternateCurrencies.end()) {
if (item_id == (*iter).item_id) {
return (*iter).id;
}
++iter;
}
return 0;
}
const char* QuestManager::getguildnamebyid(int guild_id) {
if (guild_id > 0)
return guild_mgr.GetGuildName(guild_id);

View File

@ -107,6 +107,9 @@ public:
void level(int newlevel);
void traindisc(int discipline_tome_item_id);
bool isdisctome(int item_id);
std::string getracename(uint16 race_id);
std::string getspellname(uint32 spell_id);
std::string getskillname(int skill_id);
void safemove();
void rain(int weather);
void snow(int weather);
@ -213,12 +216,15 @@ public:
int activetasksinset(int taskset);
int completedtasksinset(int taskset);
bool istaskappropriate(int task);
std::string gettaskname(uint32 task_id);
void clearspawntimers();
void ze(int type, const char *str);
void we(int type, const char *str);
int getlevel(uint8 type);
int collectitems(uint32 item_id, bool remove);
int collectitems_processSlot(int16 slot_id, uint32 item_id, bool remove);
int countitem(uint32 item_id);
std::string getitemname(uint32 item_id);
void enabletitle(int titleset);
bool checktitle(int titlecheck);
void removetitle(int titlecheck);
@ -242,6 +248,7 @@ public:
void AssignRaidToInstance(uint16 instance_id);
void RemoveFromInstance(uint16 instance_id);
void RemoveFromInstanceByCharID(uint16 instance_id, uint32 char_id);
bool CheckInstanceByCharID(uint16 instance_id, uint32 char_id);
//void RemoveGroupFromInstance(uint16 instance_id); //potentially useful but not implmented at this time.
//void RemoveRaidFromInstance(uint16 instance_id); //potentially useful but not implmented at this time.
void RemoveAllFromInstance(uint16 instance_id);
@ -250,9 +257,13 @@ public:
void FlagInstanceByRaidLeader(uint32 zone, int16 version);
const char* varlink(char* perltext, int item_id);
std::string saylink(char *saylink_text, bool silent, const char *link_name);
const char* getcharnamebyid(uint32 char_id);
uint32 getcharidbyname(const char* name);
int getcurrencyid(uint32 item_id);
const char* getguildnamebyid(int guild_id);
int getguildidbycharid(uint32 char_id);
int getgroupidbycharid(uint32 char_id);
const char* getnpcnamebyid(uint32 npc_id);
int getraididbycharid(uint32 char_id);
void SetRunning(bool val);
bool IsRunning();

View File

@ -3426,6 +3426,8 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
bool isproc, int level_override)
{
bool is_damage_or_lifetap_spell = IsDamageSpell(spell_id) || IsLifetapSpell(spell_id);
// well we can't cast a spell on target without a target
if(!spelltar)
{
@ -3967,9 +3969,6 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
// send to people in the area, ignoring caster and target
//live dosent send this to anybody but the caster
//entity_list.QueueCloseClients(spelltar, action_packet, true, 200, this, true, spelltar->IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS);
// TEMPORARY - this is the message for the spell.
// double message on effects that use ChangeHP - working on this
message_packet = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct));
CombatDamage_Struct *cd = (CombatDamage_Struct *)message_packet->pBuffer;
cd->target = action->target;
@ -3980,7 +3979,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
cd->hit_heading = action->hit_heading;
cd->hit_pitch = action->hit_pitch;
cd->damage = 0;
if(!IsEffectInSpell(spell_id, SE_BindAffinity)){
if(!IsEffectInSpell(spell_id, SE_BindAffinity) && !is_damage_or_lifetap_spell){
entity_list.QueueCloseClients(
spelltar, /* Sender */
message_packet, /* Packet */
@ -3990,6 +3989,19 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
true, /* Packet ACK */
(spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells) /* Message Filter Type: (8 or 9) */
);
} else if (is_damage_or_lifetap_spell &&
(IsClient() ||
(HasOwner() &&
GetOwner()->IsClient()
)
)
) {
(HasOwner() ? GetOwner() : this)->CastToClient()->QueuePacket(
message_packet,
true,
Mob::CLIENT_CONNECTINGALL,
(spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells)
);
}
safe_delete(action_packet);
safe_delete(message_packet);

View File

@ -955,6 +955,17 @@ bool TaskManager::AppropriateLevel(int TaskID, int PlayerLevel) {
}
std::string TaskManager::GetTaskName(uint32 task_id)
{
if (task_id > 0 && task_id < MAXTASKS) {
if (Tasks[task_id] != nullptr) {
return Tasks[task_id]->Title;
}
}
return std::string();
}
int TaskManager::GetTaskMinLevel(int TaskID)
{
if (Tasks[TaskID]->MinLevel)

View File

@ -299,6 +299,7 @@ public:
bool AppropriateLevel(int TaskID, int PlayerLevel);
int GetTaskMinLevel(int TaskID);
int GetTaskMaxLevel(int TaskID);
std::string GetTaskName(uint32 task_id);
void TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID);
void TaskQuestSetSelector(Client *c, ClientTaskState *state, Mob *mob, int count, int *tasks); // task list provided by QuestManager (perl/lua)
void SendActiveTasksToClient(Client *c, bool TaskComplete=false);

View File

@ -57,7 +57,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
extern EntityList entity_list;
extern Zone* zone;
extern volatile bool is_zone_loaded;
extern void CatchSignal(int);
extern void Shutdown();
extern WorldServer worldserver;
extern PetitionList petition_list;
extern uint32 numclients;
@ -192,8 +192,15 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
if (pack->size != sizeof(ServerConnectInfo))
break;
ServerConnectInfo* sci = (ServerConnectInfo*)pack->pBuffer;
LogInfo("World assigned Port: [{}] for this zone", sci->port);
ZoneConfig::SetZonePort(sci->port);
if (sci->port == 0) {
LogCritical("World did not have a port to assign from this server, the port range was not large enough.");
Shutdown();
}
else {
LogInfo("World assigned Port: [{}] for this zone", sci->port);
ZoneConfig::SetZonePort(sci->port);
}
break;
}
case ServerOP_ChannelMessage: {
@ -482,7 +489,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
}
case ServerOP_ShutdownAll: {
entity_list.Save();
CatchSignal(2);
Shutdown();
break;
}
case ServerOP_ZoneShutdown: {

View File

@ -3708,7 +3708,7 @@ void ZoneDatabase::LoadBuffs(Client *client)
if (!IsValidSpell(buffs[index].spellid))
continue;
for (int effectIndex = 0; effectIndex < 12; ++effectIndex) {
for (int effectIndex = 0; effectIndex < EFFECT_COUNT; ++effectIndex) {
if (spells[buffs[index].spellid].effectid[effectIndex] == SE_Charm) {
buffs[index].spellid = SPELL_UNKNOWN;