mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-22 23:41:29 +00:00
Merge branch 'master' into event_loop
This commit is contained in:
commit
8a73f50601
73
README.md
73
README.md
@ -1,54 +1,59 @@
|
|||||||
EQEmu
|
# EQEmulator Core Server
|
||||||
===
|
|Travis CI (Linux)|Appveyor (Windows) |
|
||||||
|
|:---:|:---:|
|
||||||
|
|[](https://travis-ci.org/EQEmu/Server) |[](https://ci.appveyor.com/project/KimLS/server/branch/master) |
|
||||||
|
|
||||||
[](https://travis-ci.org/EQEmu/Server)
|
***
|
||||||
[](https://ci.appveyor.com/project/KimLS/server/branch/master)
|
|
||||||
|
|
||||||
Overview
|
**EQEmulator is a custom completely from-scratch open source server implementation for EverQuest built mostly on C++**
|
||||||
---
|
* MySQL/MariaDB is used as the database engine (over 200+ tables)
|
||||||
|
* Perl and LUA are both supported scripting languages for NPC/Player/Quest oriented events
|
||||||
|
* Open source database (Project EQ) has content up to expansion GoD (included in server installs)
|
||||||
|
* Game server environments and databases can be heavily customized to create all new experiences
|
||||||
|
* Hundreds of Quests/events created and maintained by Project EQ
|
||||||
|
|
||||||
EQEmu is a custom server implementation for EverQuest
|
## Server Installs
|
||||||
|
||Windows|Linux|
|
||||||
|
|:---:|:---:|:---:|
|
||||||
|
|**Install Count**|||
|
||||||
|
### > Windows
|
||||||
|
* [Easy Install](http://wiki.eqemulator.org/p?Akkas_PEQ_Server_Installer&frm=Main#from-scratch-installation-instructions-windows)
|
||||||
|
* [Advanced Setup](http://wiki.eqemulator.org/p?Complete_Windows-based_Server_Setup_Guide)
|
||||||
|
|
||||||
Dependencies
|
### > Debian/Ubuntu
|
||||||
---
|
|
||||||
|
|
||||||
For Windows: http://eqemu.github.io
|
> wget --no-check-certificate https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh -O install.sh && chmod 755 install.sh && ./install.sh
|
||||||
|
|
||||||
Login Server dependencies for Windows/Linux/OSX: http://eqemu.github.io
|
### > CentOS/Fedora
|
||||||
|
|
||||||
For Debian based distros (adjust to your local flavor):
|
> curl -O https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh install.sh && chmod 755 install.sh && ./install.sh
|
||||||
|
|
||||||
- libmysqlclient-dev
|
## Supported Clients
|
||||||
- libperl-dev
|
|
||||||
- liblua5.1-0-dev (5.2 should work as well)
|
|
||||||
- libboost-dev
|
|
||||||
|
|
||||||
Further instructions on building the source can be found on the
|
|Titanium Edition|Secrets of Faydwer|Seeds of Destruction|Underfoot|Rain of Fear|
|
||||||
[wiki](http://wiki.eqemulator.org/i?M=Wiki).
|
|:---:|:---:|:---:|:---:|:---:|
|
||||||
|
|<img src="http://i.imgur.com/hrwDxoM.jpg" height="150">|<img src="http://i.imgur.com/cRDW5tn.png" height="150">|<img src="http://i.imgur.com/V48kuVn.jpg" height="150">|<img src="http://i.imgur.com/IJQ0XMa.jpg" height="150">|<img src="http://i.imgur.com/OMpHkKa.png" height="100">|
|
||||||
|
|
||||||
Bug reports
|
## Bug Reports <img src="http://i.imgur.com/daf1Vjw.png" height="20">
|
||||||
---
|
* Please use the [issue tracker](https://github.com/EQEmu/Server/issues) provided by GitHub to send us bug
|
||||||
|
|
||||||
Please use the [issue tracker](https://github.com/EQEmu/Server/issues) provided by GitHub to send us bug
|
|
||||||
reports or feature requests.
|
reports or feature requests.
|
||||||
|
* The [EQEmu Forums](http://www.eqemulator.org/forums/) are also a place to submit and get help with bugs.
|
||||||
|
|
||||||
The [EQEmu Forums](http://www.eqemulator.org/forums/) also have forums to submit
|
## Contributions <img src="http://image.flaticon.com/icons/png/512/25/25231.png" width="20">
|
||||||
bugs/get help with bugs.
|
|
||||||
|
|
||||||
Contributions
|
* The preferred way to contribute is to fork the repo and submit a pull request on
|
||||||
---
|
|
||||||
|
|
||||||
The preferred way to contribute is to fork the repo and submit a pull request on
|
|
||||||
GitHub. If you need help with your changes, you can always post on the forums or
|
GitHub. If you need help with your changes, you can always post on the forums or
|
||||||
try IRC. You can also post unified diffs (`git diff` should do the trick) on the
|
try Discord. You can also post unified diffs (`git diff` should do the trick) on the
|
||||||
[Server Code Submissions](http://www.eqemulator.org/forums/forumdisplay.php?f=669)
|
[Server Code Submissions](http://www.eqemulator.org/forums/forumdisplay.php?f=669)
|
||||||
forum, although pull requests will be much quicker and easier on all parties.
|
forum, although pull requests will be much quicker and easier on all parties.
|
||||||
|
|
||||||
Contact
|
## Contact <img src="http://gamerescape.com/wp-content/uploads/2015/06/discord.png" height="20">
|
||||||
---
|
|
||||||
- **User IRC Channel**: `#eqemu` on `irc.eqemulator.net`
|
|
||||||
- **Developer IRC Channel**: `#eqemucoders` on `irc.eqemulator.net`
|
|
||||||
|
|
||||||
|
- Discord Channel: https://discord.gg/QHsm7CD
|
||||||
|
- **User Discord Channel**: `#general`
|
||||||
|
- **Developer Discord Channel**: `#eqemucoders`
|
||||||
|
|
||||||
|
Resources
|
||||||
|
---
|
||||||
- [EQEmulator Forums](http://www.eqemulator.org/forums)
|
- [EQEmulator Forums](http://www.eqemulator.org/forums)
|
||||||
- [EQEmulator Wiki](http://wiki.eqemulator.org/i?M=Wiki)
|
- [EQEmulator Wiki](http://wiki.eqemulator.org/i?M=Wiki)
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
== 09/03/2016 ==
|
||||||
|
Uleat: Changed 'Bind Wound' behavior to match the best references that I could find for post-2004 era.
|
||||||
|
Note: If you wish to retain the old method, source in the optional '2016_09_03_old_bind_wound_rule.sql' script file.
|
||||||
|
|
||||||
== 08/27/2016 ==
|
== 08/27/2016 ==
|
||||||
Kinglykrab: Added optional IP-based account exemptions.
|
Kinglykrab: Added optional IP-based account exemptions.
|
||||||
- To use this system simply set World:EnableIPExemptions to true and create an entry in the ip_exemptions table.
|
- To use this system simply set World:EnableIPExemptions to true and create an entry in the ip_exemptions table.
|
||||||
|
|||||||
@ -145,6 +145,8 @@ RULE_BOOL(Character, UseStackablePickPocketing, true) // Allows stackable pickpo
|
|||||||
RULE_BOOL(Character, EnableAvoidanceCap, false)
|
RULE_BOOL(Character, EnableAvoidanceCap, false)
|
||||||
RULE_INT(Character, AvoidanceCap, 750) // 750 Is a pretty good value, seen people dodge all attacks beyond 1,000 Avoidance
|
RULE_INT(Character, AvoidanceCap, 750) // 750 Is a pretty good value, seen people dodge all attacks beyond 1,000 Avoidance
|
||||||
RULE_BOOL(Character, AllowMQTarget, false) // Disables putting players in the 'hackers' list for targeting beyond the clip plane or attempting to target something untargetable
|
RULE_BOOL(Character, AllowMQTarget, false) // Disables putting players in the 'hackers' list for targeting beyond the clip plane or attempting to target something untargetable
|
||||||
|
RULE_BOOL(Character, UseOldBindWound, false) // Uses the original bind wound behavior
|
||||||
|
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Mercs)
|
RULE_CATEGORY(Mercs)
|
||||||
|
|||||||
@ -193,6 +193,7 @@
|
|||||||
#define ServerOP_QSSendQuery 0x5016
|
#define ServerOP_QSSendQuery 0x5016
|
||||||
#define ServerOP_CZSignalNPC 0x5017
|
#define ServerOP_CZSignalNPC 0x5017
|
||||||
#define ServerOP_CZSetEntityVariableByNPCTypeID 0x5018
|
#define ServerOP_CZSetEntityVariableByNPCTypeID 0x5018
|
||||||
|
#define ServerOP_WWMarquee 0x5019
|
||||||
|
|
||||||
/* Query Serv Generic Packet Flag/Type Enumeration */
|
/* Query Serv Generic Packet Flag/Type Enumeration */
|
||||||
enum { QSG_LFGuild = 0 };
|
enum { QSG_LFGuild = 0 };
|
||||||
@ -1254,6 +1255,15 @@ struct CZMessagePlayer_Struct {
|
|||||||
char Message[512];
|
char Message[512];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WWMarquee_Struct {
|
||||||
|
uint32 Type;
|
||||||
|
uint32 Priority;
|
||||||
|
uint32 FadeIn;
|
||||||
|
uint32 FadeOut;
|
||||||
|
uint32 Duration;
|
||||||
|
char Message[512];
|
||||||
|
};
|
||||||
|
|
||||||
struct CZSetEntVarByNPCTypeID_Struct {
|
struct CZSetEntVarByNPCTypeID_Struct {
|
||||||
uint32 npctype_id;
|
uint32 npctype_id;
|
||||||
char id[256];
|
char id[256];
|
||||||
|
|||||||
@ -24,8 +24,22 @@ $eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/
|
|||||||
#::: Globals
|
#::: Globals
|
||||||
$time_stamp = strftime('%m-%d-%Y', gmtime());
|
$time_stamp = strftime('%m-%d-%Y', gmtime());
|
||||||
$db_run_stage = 0; #::: Sets database run stage check
|
$db_run_stage = 0; #::: Sets database run stage check
|
||||||
if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; }
|
if($Config{osname}=~/freebsd|linux/i){
|
||||||
if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; }
|
$OS = "Linux";
|
||||||
|
$os_flavor = "";
|
||||||
|
if(-e "/etc/debian_version"){
|
||||||
|
$os_flavor = "debian";
|
||||||
|
}
|
||||||
|
elsif(-e "/etc/fedora-release"){
|
||||||
|
$os_flavor = "fedora_core";
|
||||||
|
}
|
||||||
|
elsif(-e "/etc/redhat-release"){
|
||||||
|
$os_flavor = "red_hat";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($Config{osname}=~/Win|MS/i){
|
||||||
|
$OS = "Windows";
|
||||||
|
}
|
||||||
$has_internet_connection = check_internet_connection();
|
$has_internet_connection = check_internet_connection();
|
||||||
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime();
|
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime();
|
||||||
|
|
||||||
@ -39,8 +53,6 @@ get_mysql_path();
|
|||||||
if(-e "eqemu_update.pl"){
|
if(-e "eqemu_update.pl"){
|
||||||
unlink("eqemu_update.pl");
|
unlink("eqemu_update.pl");
|
||||||
}
|
}
|
||||||
#::: Create db_update working directory if not created
|
|
||||||
mkdir('db_update');
|
|
||||||
|
|
||||||
print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n" if $ARGV[0] eq "ran_from_world";
|
print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n" if $ARGV[0] eq "ran_from_world";
|
||||||
|
|
||||||
@ -51,103 +63,292 @@ if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne ""
|
|||||||
}
|
}
|
||||||
|
|
||||||
check_db_version_table();
|
check_db_version_table();
|
||||||
|
|
||||||
check_for_world_bootup_database_update();
|
check_for_world_bootup_database_update();
|
||||||
|
|
||||||
if($db){
|
sub urlencode {
|
||||||
print "[Update] MySQL Path/Location: " . $path . "\n";
|
my ($rv) = @_;
|
||||||
print "[Update] Binary Revision / Local: (" . $binary_database_version . " / " . $local_database_version . ")\n";
|
$rv =~ s/([^A-Za-z0-9])/sprintf("%%%2.2X", ord($1))/ge;
|
||||||
|
return $rv;
|
||||||
|
}
|
||||||
|
|
||||||
#::: Bots
|
sub urldecode {
|
||||||
#::: Make sure we're running a bots binary to begin with
|
my ($rv) = @_;
|
||||||
if(trim($db_version[2]) > 0){
|
$rv =~ s/\+/ /g;
|
||||||
$bots_local_db_version = get_bots_db_version();
|
$rv =~ s/%(..)/pack("c",hex($1))/ge;
|
||||||
if($bots_local_db_version > 0){
|
return $rv;
|
||||||
print "[Update] (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n";
|
}
|
||||||
}
|
|
||||||
|
sub analytics_insertion {
|
||||||
|
$event_name = urlencode($_[0]);
|
||||||
|
$event_data = urlencode($_[1]);
|
||||||
|
|
||||||
|
#::: Check for internet connection before doing analytics
|
||||||
|
if(!$has_internet_connection || $can_see_analytics_server == -1){
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#::: If World ran this script, and our version is up to date, continue...
|
#::: Check for analytics server connectivity so that the script doesn't break when its offline
|
||||||
if($binary_database_version <= $local_database_version && $ARGV[0] eq "ran_from_world"){
|
if(!$can_see_analytics_server){
|
||||||
print "[Update] Database up to Date: Continuing World Bootup...\n";
|
if($OS eq "Linux"){
|
||||||
exit;
|
$count = "c";
|
||||||
}
|
}
|
||||||
}
|
if($OS eq "Windows"){
|
||||||
|
$count = "n";
|
||||||
if($ARGV[0] eq "remove_duplicate_rules"){
|
|
||||||
remove_duplicate_rule_values();
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($ARGV[0] eq "map_files_fetch_bulk"){
|
|
||||||
map_files_fetch_bulk();
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($ARGV[0] eq "loginserver_install_linux"){
|
|
||||||
do_linux_login_server_setup();
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($ARGV[0] eq "new_server"){
|
|
||||||
while(1){
|
|
||||||
print "For a new server folder install, we assume Perl and MySQL are configured\n";
|
|
||||||
print "This will install a fresh PEQ Database, with all server assets\n";
|
|
||||||
print "You will need to supply database credentials to get started...\n";
|
|
||||||
|
|
||||||
check_for_input("MySQL User: ");
|
|
||||||
$database_user = trim($input);
|
|
||||||
|
|
||||||
check_for_input("MySQL Password: ");
|
|
||||||
$database_password = trim($input);
|
|
||||||
|
|
||||||
$check_connection = `mysql -u $database_user -p$database_password -N -B -e "SHOW PROCESSLIST" > mysqlcheck.txt`;
|
|
||||||
$mysql_pass = 0;
|
|
||||||
open (MYSQL_CHECK, "mysqlcheck.txt");
|
|
||||||
while (<MYSQL_CHECK>){
|
|
||||||
chomp;
|
|
||||||
$o = $_;
|
|
||||||
if($o=~/Error/i){ $mysql_pass = 0;}
|
|
||||||
if($o=~/SHOW PROCESSLIST/i){ $mysql_pass = 1; }
|
|
||||||
}
|
}
|
||||||
close (MYSQL_CHECK);
|
|
||||||
unlink("mysqlcheck.txt");
|
|
||||||
|
|
||||||
if($mysql_pass == 1){
|
if (`ping analytics.akkadius.com -$count 1 -w 500`=~/Reply from|1 received/i) {
|
||||||
print "Success! We have a database connection\n";
|
$can_see_analytics_server = 1;
|
||||||
|
|
||||||
check_for_input("Specify a database name: ");
|
|
||||||
$database_name = trim($input);
|
|
||||||
|
|
||||||
#::: Write install vars
|
|
||||||
open (INSTALL_VARS, '>', 'install_variables.txt');
|
|
||||||
print INSTALL_VARS "";
|
|
||||||
print INSTALL_VARS "mysql_eqemu_db_name:" . $database_name . "\n";
|
|
||||||
print INSTALL_VARS "mysql_eqemu_user:" . $database_user . "\n";
|
|
||||||
print INSTALL_VARS "mysql_eqemu_password:" . $database_password . "\n";
|
|
||||||
close (INSTALL_VARS);
|
|
||||||
|
|
||||||
do_installer_routines();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print "Authorization failed\n";
|
$can_see_analytics_server = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$server_name = "";
|
||||||
|
if($long_name){
|
||||||
|
$server_name = "&server_name=" . urlencode($long_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$extended_os){
|
||||||
|
if($OS eq "Linux"){
|
||||||
|
$extended_os = `cat /proc/version`;
|
||||||
|
$extended_os = trim($extended_os);
|
||||||
|
}
|
||||||
|
if($OS eq "Windows"){
|
||||||
|
my $output = `ver`;
|
||||||
|
my @os_version = split("\n", $output);
|
||||||
|
foreach my $val (@os_version){
|
||||||
|
if($val=~/Windows/i){
|
||||||
|
$extended_os = trim($val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = "http://analytics.akkadius.com/";
|
||||||
|
$url .= "?api_key=24a0bde2e5bacd65bcab06a9ac40b62c";
|
||||||
|
$url .= "&event=" . $event_name;
|
||||||
|
$url .= "&event_data=" . $event_data;
|
||||||
|
$url .= "&OS=" . urlencode($OS);
|
||||||
|
$url .= "&extended_os=" . urlencode($extended_os);
|
||||||
|
$url .= $server_name;
|
||||||
|
|
||||||
|
# print "Calling url :: '" . $url . "'\n";
|
||||||
|
|
||||||
|
if($OS eq "Windows"){
|
||||||
|
eval('require LWP::UserAgent;');
|
||||||
|
my $ua = LWP::UserAgent->new;
|
||||||
|
$ua->timeout(1);
|
||||||
|
$ua->env_proxy;
|
||||||
|
my $response = $ua->get($url);
|
||||||
|
}
|
||||||
|
if($OS eq "Linux"){
|
||||||
|
$api_call = `curl -s "$url"`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub show_install_summary_info {
|
||||||
|
print "[Install] Installation complete...\n";
|
||||||
|
print "[Install] Server Info (Save somewhere if needed):\n";
|
||||||
|
|
||||||
|
if (-e "install_variables.txt") {
|
||||||
|
$file_to_open = "install_variables.txt";
|
||||||
|
}
|
||||||
|
elsif(-e "../install_variables.txt"){
|
||||||
|
$file_to_open = "../install_variables.txt";
|
||||||
|
}
|
||||||
|
open (INSTALL_VARS, $file_to_open);
|
||||||
|
while (<INSTALL_VARS>){
|
||||||
|
chomp;
|
||||||
|
$o = $_;
|
||||||
|
@data = split(":", $o);
|
||||||
|
print " - " . $data[0] . "\t" . $data[1] . "\n";
|
||||||
|
}
|
||||||
|
close (INSTALL_VARS);
|
||||||
|
|
||||||
|
if($OS eq "Windows"){
|
||||||
|
print "[Install] Windows Utility Scripts:\n";
|
||||||
|
print " - t_start_server.bat Starts EQEmu server with 30 dynamic zones, UCS & Queryserv, dynamic zones\n";
|
||||||
|
print " - t_start_server_with_loginserver.bat Starts EQEmu server with 30 zones with loginserver\n";
|
||||||
|
print " - t_stop_server.bat Stops EQEmu Server (No warning)\n";
|
||||||
|
print " - t_database_backup.bat Backs up the Database to backups/ folder - do not run during server is online\n";
|
||||||
|
print " - t_server_crash_report.pl Will parse any zone crashes for reporting to developers\n";
|
||||||
|
}
|
||||||
|
if($OS eq "Linux"){
|
||||||
|
print "[Install] Linux Utility Scripts:\n";
|
||||||
|
print " - server_start.sh Starts EQEmu server (Quiet) with 30 dynamic zones, UCS & Queryserv, dynamic zones\n";
|
||||||
|
print " - server_start_dev.sh Starts EQEmu server with 10 dynamic zones, UCS & Queryserv, dynamic zones all verbose\n";
|
||||||
|
print " - server_stop.sh Stops EQEmu Server (No warning)\n";
|
||||||
|
print " - server_status.sh Prints the status of the EQEmu Server processes\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
print "[Configure] eqemu_config.xml Edit to change server settings and name\n";
|
||||||
|
|
||||||
|
analytics_insertion("install_complete", "null");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub new_server {
|
||||||
|
$file_count = 0;
|
||||||
|
opendir(DIR, ".") or die $!;
|
||||||
|
while (my $file = readdir(DIR)) {
|
||||||
|
next if ($file =~ m/^\./);
|
||||||
|
$file_count++;
|
||||||
|
}
|
||||||
|
closedir(DIR);
|
||||||
|
|
||||||
|
if($file_count > 1 && (!-e "install_variables.txt" && !-e "../install_variables.txt")){
|
||||||
|
print "[New Server] ERROR: You must run eqemu_server.pl in an empty directory\n";
|
||||||
|
<>;
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(-e "install_variables.txt" || -e "../install_variables.txt"){
|
||||||
|
get_installation_variables();
|
||||||
|
}
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
|
||||||
|
$database_name = $installation_variables{"mysql_eqemu_db_name"};
|
||||||
|
$database_user = $installation_variables{"mysql_eqemu_user"};
|
||||||
|
$database_password = $installation_variables{"mysql_eqemu_password"};
|
||||||
|
|
||||||
|
if($database_name ne ""){
|
||||||
|
$mysql_pass = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
print "\n";
|
||||||
|
print "[New Server] For a new server folder install, we assume Perl and MySQL are configured\n";
|
||||||
|
print "[New Server] This will install a fresh PEQ Database, with all server assets\n";
|
||||||
|
print "[New Server] You will need to supply database credentials to get started...\n\n";
|
||||||
|
|
||||||
|
check_for_input("MySQL User: ");
|
||||||
|
$database_user = trim($input);
|
||||||
|
|
||||||
|
check_for_input("MySQL Password: ");
|
||||||
|
$database_password = trim($input);
|
||||||
|
|
||||||
|
$check_connection = `mysql -u $database_user -p$database_password -N -B -e "SHOW PROCESSLIST" > mysqlcheck.txt`;
|
||||||
|
$mysql_pass = 0;
|
||||||
|
open (MYSQL_CHECK, "mysqlcheck.txt");
|
||||||
|
while (<MYSQL_CHECK>){
|
||||||
|
chomp;
|
||||||
|
$o = $_;
|
||||||
|
if($o=~/Error/i){ $mysql_pass = 0;}
|
||||||
|
if($o=~/SHOW PROCESSLIST/i){ $mysql_pass = 1; }
|
||||||
|
}
|
||||||
|
close (MYSQL_CHECK);
|
||||||
|
unlink("mysqlcheck.txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
if($mysql_pass == 1){
|
||||||
|
|
||||||
|
if((!-e "install_variables.txt" && !-e "../install_variables.txt")){
|
||||||
|
print "[New Server] Success! We have a database connection\n";
|
||||||
|
|
||||||
|
check_for_input("Specify a NEW database name that PEQ will be installed to: ");
|
||||||
|
$database_name = trim($input);
|
||||||
|
|
||||||
|
#::: Write install vars
|
||||||
|
open (INSTALL_VARS, '>', 'install_variables.txt');
|
||||||
|
print INSTALL_VARS "";
|
||||||
|
print INSTALL_VARS "mysql_eqemu_db_name:" . $database_name . "\n";
|
||||||
|
print INSTALL_VARS "mysql_eqemu_user:" . $database_user . "\n";
|
||||||
|
print INSTALL_VARS "mysql_eqemu_password:" . $database_password . "\n";
|
||||||
|
close (INSTALL_VARS);
|
||||||
|
}
|
||||||
|
analytics_insertion("new_server::install", $database_name);
|
||||||
|
|
||||||
|
if($OS eq "Linux"){
|
||||||
|
build_linux_source();
|
||||||
|
}
|
||||||
|
|
||||||
|
do_installer_routines();
|
||||||
|
|
||||||
|
if($OS eq "Linux"){
|
||||||
|
print `chmod 755 *.sh`;
|
||||||
|
}
|
||||||
|
|
||||||
|
analytics_insertion("new_server::install_complete", $database_name . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version);
|
||||||
|
|
||||||
|
print "[New Server] New server folder install complete\n";
|
||||||
|
print "[New Server] Below is your installation info:\n";
|
||||||
|
|
||||||
|
show_install_summary_info();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "[New Server] MySQL authorization failed or no MySQL installed\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($ARGV[0] eq "installer"){
|
sub build_linux_source {
|
||||||
do_installer_routines();
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; }
|
$build_options = $_[0];
|
||||||
if($ARGV[0] eq "login_server_setup"){
|
|
||||||
do_windows_login_server_setup();
|
$cmake_options = "";
|
||||||
exit;
|
$source_folder_post_fix = "";
|
||||||
|
|
||||||
|
if($build_options =~/bots/i){
|
||||||
|
$cmake_options .= " -DEQEMU_ENABLE_BOTS=ON";
|
||||||
|
$source_folder_post_fix = "_bots";
|
||||||
|
}
|
||||||
|
|
||||||
|
$current_directory = `pwd`;
|
||||||
|
@directories = split('/', $current_directory);
|
||||||
|
foreach my $val (@directories){
|
||||||
|
if(trim($val) ne ""){
|
||||||
|
$last_directory = trim($val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
my $eqemu_server_directory = "/home/eqemu";
|
||||||
|
my $source_dir = $eqemu_server_directory . '/' . $last_directory . '_source' . $source_folder_post_fix;
|
||||||
|
|
||||||
|
$current_directory = trim($current_directory);
|
||||||
|
|
||||||
|
mkdir($source_dir) if (!-e $source_dir);
|
||||||
|
|
||||||
|
# print 'server_dir: ' . $eqemu_server_directory . "\n";
|
||||||
|
# print 'source_dir: ' . $source_dir . "\n";
|
||||||
|
# print 'current_dir: \'' . $current_directory . "'\n";
|
||||||
|
|
||||||
|
chdir($source_dir);
|
||||||
|
|
||||||
|
print `git clone https://github.com/EQEmu/Server.git`;
|
||||||
|
|
||||||
|
mkdir ($source_dir . "/Server/build") if (!-e $source_dir . "/Server/build");
|
||||||
|
chdir ($source_dir . "/Server/build");
|
||||||
|
|
||||||
|
print "Generating CMake build files...\n";
|
||||||
|
if($os_flavor eq "fedora_core"){
|
||||||
|
print `cmake $cmake_options -DEQEMU_BUILD_LUA=ON -DLUA_INCLUDE_DIR=/usr/include/lua-5.1/ -G "Unix Makefiles" ..`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print `cmake $cmake_options -DEQEMU_BUILD_LUA=ON -G "Unix Makefiles" ..`;
|
||||||
|
}
|
||||||
|
print "Building EQEmu Server code. This will take a while.";
|
||||||
|
|
||||||
|
#::: Build
|
||||||
|
print `make`;
|
||||||
|
|
||||||
|
chdir ($current_directory);
|
||||||
|
|
||||||
|
print `ln -s -f $source_dir/Server/build/bin/eqlaunch .`;
|
||||||
|
print `ln -s -f $source_dir/Server/build/bin/export_client_files .`;
|
||||||
|
print `ln -s -f $source_dir/Server/build/bin/import_client_files .`;
|
||||||
|
print `ln -s -f $source_dir/Server/build/bin/libcommon.a .`;
|
||||||
|
print `ln -s -f $source_dir/Server/build/bin/libluabind.a .`;
|
||||||
|
print `ln -s -f $source_dir/Server/build/bin/queryserv .`;
|
||||||
|
print `ln -s -f $source_dir/Server/build/bin/shared_memory .`;
|
||||||
|
print `ln -s -f $source_dir/Server/build/bin/ucs .`;
|
||||||
|
print `ln -s -f $source_dir/Server/build/bin/world .`;
|
||||||
|
print `ln -s -f $source_dir/Server/build/bin/zone .`;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub do_installer_routines {
|
sub do_installer_routines {
|
||||||
print "[Install] Running EQEmu Server installer routines...\n";
|
print "[Install] EQEmu Server Installer... LOADING... PLEASE WAIT...\n";
|
||||||
|
|
||||||
#::: Make some local server directories...
|
#::: Make some local server directories...
|
||||||
mkdir('logs');
|
mkdir('logs');
|
||||||
@ -170,6 +371,7 @@ sub do_installer_routines {
|
|||||||
get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1);
|
get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1);
|
||||||
get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1);
|
get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
map_files_fetch_bulk();
|
map_files_fetch_bulk();
|
||||||
opcodes_fetch();
|
opcodes_fetch();
|
||||||
plugins_fetch();
|
plugins_fetch();
|
||||||
@ -198,19 +400,19 @@ sub do_installer_routines {
|
|||||||
print "[Database] Applying Latest Database Updates...\n";
|
print "[Database] Applying Latest Database Updates...\n";
|
||||||
main_db_management();
|
main_db_management();
|
||||||
|
|
||||||
|
remove_duplicate_rule_values();
|
||||||
|
|
||||||
if($OS eq "Windows"){
|
if($OS eq "Windows"){
|
||||||
check_windows_firewall_rules();
|
check_windows_firewall_rules();
|
||||||
do_windows_login_server_setup();
|
do_windows_login_server_setup();
|
||||||
}
|
}
|
||||||
if($OS eq "Linux"){
|
if($OS eq "Linux"){
|
||||||
do_linux_login_server_setup();
|
do_linux_login_server_setup();
|
||||||
|
|
||||||
print "[Install] Installation complete!\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub check_for_input {
|
sub check_for_input {
|
||||||
print $_[0];
|
print "[Input] " . $_[0];
|
||||||
$input = <STDIN>;
|
$input = <STDIN>;
|
||||||
chomp $input;
|
chomp $input;
|
||||||
}
|
}
|
||||||
@ -226,12 +428,35 @@ sub check_for_world_bootup_database_update {
|
|||||||
$binary_database_version = trim($db_version[1]);
|
$binary_database_version = trim($db_version[1]);
|
||||||
$local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1"));
|
$local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1"));
|
||||||
|
|
||||||
|
#::: Bots
|
||||||
|
$bots_binary_version = trim($db_version[2]);
|
||||||
|
if($bots_binary_version > 0){
|
||||||
|
$bots_local_db_version = get_bots_db_version();
|
||||||
|
#::: We ran world - Database needs to update, lets backup and run updates and continue world bootup
|
||||||
|
|
||||||
|
if($bots_local_db_version < $bots_binary_version && $ARGV[0] eq "ran_from_world"){
|
||||||
|
print "[Update] Bots Database not up to date with binaries... Automatically updating...\n";
|
||||||
|
print "[Update] Issuing database backup first...\n";
|
||||||
|
database_dump_compress();
|
||||||
|
print "[Update] Updating bots database...\n";
|
||||||
|
sleep(1);
|
||||||
|
bots_db_management();
|
||||||
|
run_database_check();
|
||||||
|
print "[Update] Continuing bootup\n";
|
||||||
|
analytics_insertion("auto database bots upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version);
|
||||||
|
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "[Update] Bots database up to Date: Continuing World Bootup...\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world"){
|
if($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world"){
|
||||||
print "[Update] Database up to date...\n";
|
print "[Update] Database up to date...\n";
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
#::: We ran world - Database needs to update, lets backup and run updates and continue world bootup
|
#::: We ran world - Database needs to update, lets backup and run updates and continue world bootup
|
||||||
if($local_database_version < $binary_database_version && $ARGV[0] eq "ran_from_world"){
|
if($local_database_version < $binary_database_version && $ARGV[0] eq "ran_from_world"){
|
||||||
print "[Update] Database not up to date with binaries... Automatically updating...\n";
|
print "[Update] Database not up to date with binaries... Automatically updating...\n";
|
||||||
@ -242,11 +467,13 @@ sub check_for_world_bootup_database_update {
|
|||||||
main_db_management();
|
main_db_management();
|
||||||
main_db_management();
|
main_db_management();
|
||||||
print "[Update] Continuing bootup\n";
|
print "[Update] Continuing bootup\n";
|
||||||
|
analytics_insertion("auto database upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version);
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
#::: Make sure that we didn't pass any arugments to the script
|
#::: Make sure that we didn't pass any arugments to the script
|
||||||
if(!$ARGV[0]){
|
else {
|
||||||
if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; }
|
if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; }
|
||||||
show_menu_prompt();
|
show_menu_prompt();
|
||||||
}
|
}
|
||||||
@ -279,7 +506,7 @@ sub get_perl_version {
|
|||||||
#::: Check Perl version
|
#::: Check Perl version
|
||||||
$perl_version = $^V;
|
$perl_version = $^V;
|
||||||
$perl_version =~s/v//g;
|
$perl_version =~s/v//g;
|
||||||
print "[Update] Perl Version is " . $perl_version . "\n";
|
print "[Update] Perl Version is " . $perl_version . "\n" if $debug;
|
||||||
if($perl_version > 5.12){
|
if($perl_version > 5.12){
|
||||||
no warnings 'uninitialized';
|
no warnings 'uninitialized';
|
||||||
}
|
}
|
||||||
@ -287,14 +514,16 @@ sub get_perl_version {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub do_self_update_check_routine {
|
sub do_self_update_check_routine {
|
||||||
#::: Check Version passed from world to update script
|
|
||||||
get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1);
|
|
||||||
|
|
||||||
|
#::: Check for internet connection before updating
|
||||||
if(!$has_internet_connection){
|
if(!$has_internet_connection){
|
||||||
print "[Update] Cannot check update without internet connection...\n";
|
print "[Update] Cannot check update without internet connection...\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#::: Check for script changes :: eqemu_server.pl
|
||||||
|
get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1);
|
||||||
|
|
||||||
if(-e "updates_staged/eqemu_server.pl") {
|
if(-e "updates_staged/eqemu_server.pl") {
|
||||||
|
|
||||||
my $remote_script_size = -s "updates_staged/eqemu_server.pl";
|
my $remote_script_size = -s "updates_staged/eqemu_server.pl";
|
||||||
@ -384,6 +613,11 @@ sub do_install_config_xml {
|
|||||||
$new_key = generate_random_password(30);
|
$new_key = generate_random_password(30);
|
||||||
$o =~ s/$replace_key/$new_key/g;
|
$o =~ s/$replace_key/$new_key/g;
|
||||||
}
|
}
|
||||||
|
if($o=~/\<longname\>/i){
|
||||||
|
my($replace_name) = $o =~ /<longname>(.*)<\/longname>/;
|
||||||
|
$append = '(' . generate_random_password(5) . ')';
|
||||||
|
$o =~ s/$replace_name/Akkas $OS PEQ Installer $append/g;
|
||||||
|
}
|
||||||
if($o=~/\<username\>/i && $in_database_tag){
|
if($o=~/\<username\>/i && $in_database_tag){
|
||||||
my($replace_username) = $o =~ />(\w+)</;
|
my($replace_username) = $o =~ />(\w+)</;
|
||||||
$o =~ s/$replace_username/$installation_variables{"mysql_eqemu_user"}/g;
|
$o =~ s/$replace_username/$installation_variables{"mysql_eqemu_user"}/g;
|
||||||
@ -432,11 +666,30 @@ sub fetch_utility_scripts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub setup_bots {
|
||||||
|
if($OS eq "Windows"){
|
||||||
|
fetch_latest_windows_binaries_bots();
|
||||||
|
}
|
||||||
|
if($OS eq "Linux"){
|
||||||
|
build_linux_source("bots");
|
||||||
|
}
|
||||||
|
bots_db_management();
|
||||||
|
run_database_check();
|
||||||
|
|
||||||
|
print "Bots should be setup, run your server and the #bot command should be available in-game\n";
|
||||||
|
}
|
||||||
|
|
||||||
sub show_menu_prompt {
|
sub show_menu_prompt {
|
||||||
|
|
||||||
$dc = 0;
|
$dc = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
$input = trim($input);
|
|
||||||
|
if($ARGV[0] ne ""){
|
||||||
|
$input = trim($ARGV[0]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$input = trim($input);
|
||||||
|
}
|
||||||
|
|
||||||
$errored_command = 0;
|
$errored_command = 0;
|
||||||
|
|
||||||
@ -491,9 +744,11 @@ sub show_menu_prompt {
|
|||||||
elsif($input eq "windows_server_download_bots"){ fetch_latest_windows_binaries_bots(); $dc = 1; }
|
elsif($input eq "windows_server_download_bots"){ fetch_latest_windows_binaries_bots(); $dc = 1; }
|
||||||
elsif($input eq "fetch_dlls"){ fetch_server_dlls(); $dc = 1; }
|
elsif($input eq "fetch_dlls"){ fetch_server_dlls(); $dc = 1; }
|
||||||
elsif($input eq "utility_scripts"){ fetch_utility_scripts(); $dc = 1; }
|
elsif($input eq "utility_scripts"){ fetch_utility_scripts(); $dc = 1; }
|
||||||
elsif($input eq "check_db_updates"){ main_db_management(); $dc = 1; }
|
elsif($input eq "check_db_updates"){ main_db_management(); main_db_management(); $dc = 1; }
|
||||||
elsif($input eq "check_bot_db_updates"){ bots_db_management(); $dc = 1; }
|
elsif($input eq "check_bot_db_updates"){ bots_db_management(); run_database_check(); $dc = 1; }
|
||||||
elsif($input eq "setup_loginserver"){ do_windows_login_server_setup(); $dc = 1; }
|
elsif($input eq "setup_loginserver"){ do_windows_login_server_setup(); $dc = 1; }
|
||||||
|
elsif($input eq "new_server"){ new_server(); $dc = 1; }
|
||||||
|
elsif($input eq "setup_bots"){ setup_bots(); $dc = 1; }
|
||||||
elsif($input eq "exit"){
|
elsif($input eq "exit"){
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
@ -518,12 +773,21 @@ sub show_menu_prompt {
|
|||||||
$input = $last_menu;
|
$input = $last_menu;
|
||||||
}
|
}
|
||||||
elsif($dc == 1){
|
elsif($dc == 1){
|
||||||
|
analytics_insertion("menu", trim($input));
|
||||||
$dc = 0;
|
$dc = 0;
|
||||||
$input = "";
|
$input = "";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$input = <>;
|
$input = <>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#::: If we're processing a CLI command, kill the loop
|
||||||
|
if($ARGV[0] ne ""){
|
||||||
|
analytics_insertion("cli", trim($input));
|
||||||
|
$input = "";
|
||||||
|
$ARGV[0] = "";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,7 +796,10 @@ sub print_main_menu {
|
|||||||
print ">>> EQEmu Server Main Menu >>>>>>>>>>>>\n";
|
print ">>> EQEmu Server Main Menu >>>>>>>>>>>>\n";
|
||||||
print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n";
|
print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n";
|
||||||
print " [database] Enter database management menu \n";
|
print " [database] Enter database management menu \n";
|
||||||
print " [assets] Manage server assets \n\n";
|
print " [assets] Manage server assets \n";
|
||||||
|
print " [new_server] New folder EQEmu/PEQ install - Assumes MySQL/Perl installed \n";
|
||||||
|
print " [setup_bots] Enables bots on server - builds code and database requirements \n";
|
||||||
|
print "\n";
|
||||||
print " exit \n";
|
print " exit \n";
|
||||||
print "\n";
|
print "\n";
|
||||||
print "Enter a command #> ";
|
print "Enter a command #> ";
|
||||||
@ -568,13 +835,52 @@ sub get_mysql_path {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub check_for_database_dump_script{
|
sub check_for_database_dump_script{
|
||||||
if(`perl db_dumper.pl`=~/Need arguments/i){
|
#::: Check for internet connection before updating
|
||||||
|
if(!$has_internet_connection){
|
||||||
|
print "[Update] Cannot check update without internet connection...\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
print "[Database] db_dumper.pl not found... retrieving...\n";
|
#::: Check for script changes :: db_dumper.pl
|
||||||
get_remote_file($eqemu_repository_request_url . "utils/scripts/db_dumper.pl", "db_dumper.pl");
|
get_remote_file($eqemu_repository_request_url . "utils/scripts/db_dumper.pl", "updates_staged/db_dumper.pl", 0, 1, 1);
|
||||||
|
|
||||||
|
if(-e "updates_staged/db_dumper.pl") {
|
||||||
|
|
||||||
|
my $remote_script_size = -s "updates_staged/db_dumper.pl";
|
||||||
|
my $local_script_size = -s "db_dumper.pl";
|
||||||
|
|
||||||
|
if($remote_script_size != $local_script_size){
|
||||||
|
print "[Update] Script has been updated, updating...\n";
|
||||||
|
|
||||||
|
my @files;
|
||||||
|
my $start_dir = "updates_staged/";
|
||||||
|
find(
|
||||||
|
sub { push @files, $File::Find::name unless -d; },
|
||||||
|
$start_dir
|
||||||
|
);
|
||||||
|
for my $file (@files) {
|
||||||
|
if($file=~/db_dumper/i){
|
||||||
|
$destination_file = $file;
|
||||||
|
$destination_file =~s/updates_staged\///g;
|
||||||
|
print "[Install] Installing :: " . $destination_file . "\n";
|
||||||
|
unlink($destination_file);
|
||||||
|
copy_file($file, $destination_file);
|
||||||
|
if($OS eq "Linux"){
|
||||||
|
system("chmod 755 db_dumper.pl");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print "[Install] Done\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "[Update] No script update necessary...\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink("updates_staged/db_dumper.pl");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub database_dump {
|
sub database_dump {
|
||||||
@ -762,13 +1068,11 @@ sub read_eqemu_config_xml {
|
|||||||
my $indb = 0;
|
my $indb = 0;
|
||||||
while(<F>) {
|
while(<F>) {
|
||||||
s/\r//g;
|
s/\r//g;
|
||||||
if(/<database>/i) { $indb = 1; }
|
|
||||||
next unless($indb == 1);
|
|
||||||
if(/<\/database>/i) { $indb = 0; last; }
|
|
||||||
if(/<host>(.*)<\/host>/i) { $host = $1; }
|
if(/<host>(.*)<\/host>/i) { $host = $1; }
|
||||||
elsif(/<username>(.*)<\/username>/i) { $user = $1; }
|
elsif(/<username>(.*)<\/username>/i) { $user = $1; }
|
||||||
elsif(/<password>(.*)<\/password>/i) { $pass = $1; }
|
elsif(/<password>(.*)<\/password>/i) { $pass = $1; }
|
||||||
elsif(/<db>(.*)<\/db>/i) { $db = $1; }
|
elsif(/<db>(.*)<\/db>/i) { $db = $1; }
|
||||||
|
if(/<longname>(.*)<\/longname>/i) { $long_name = $1; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1016,11 +1320,11 @@ sub add_login_server_firewall_rules {
|
|||||||
$val=~s/Rule Name://g;
|
$val=~s/Rule Name://g;
|
||||||
if($val=~/EQEmu Loginserver/i && $val=~/Titanium/i){
|
if($val=~/EQEmu Loginserver/i && $val=~/Titanium/i){
|
||||||
$has_loginserver_rules_titanium = 1;
|
$has_loginserver_rules_titanium = 1;
|
||||||
print "Found existing rule :: " . trim($val) . "\n";
|
print "[Install] Found existing rule :: " . trim($val) . "\n";
|
||||||
}
|
}
|
||||||
if($val=~/EQEmu Loginserver/i && $val=~/SOD/i){
|
if($val=~/EQEmu Loginserver/i && $val=~/SOD/i){
|
||||||
$has_loginserver_rules_sod = 1;
|
$has_loginserver_rules_sod = 1;
|
||||||
print "Found existing rule :: " . trim($val) . "\n";
|
print "[Install] Found existing rule :: " . trim($val) . "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1619,6 +1923,13 @@ sub get_bots_db_version{
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub bots_db_management{
|
sub bots_db_management{
|
||||||
|
if($OS eq "Windows"){
|
||||||
|
@db_version = split(': ', `world db_version`);
|
||||||
|
}
|
||||||
|
if($OS eq "Linux"){
|
||||||
|
@db_version = split(': ', `./world db_version`);
|
||||||
|
}
|
||||||
|
|
||||||
#::: Main Binary Database version
|
#::: Main Binary Database version
|
||||||
$binary_database_version = trim($db_version[2]);
|
$binary_database_version = trim($db_version[2]);
|
||||||
|
|
||||||
@ -1637,6 +1948,8 @@ sub bots_db_management{
|
|||||||
|
|
||||||
$bots_local_db_version = get_bots_db_version();
|
$bots_local_db_version = get_bots_db_version();
|
||||||
|
|
||||||
|
$local_database_version = $bots_local_db_version;
|
||||||
|
|
||||||
run_database_check();
|
run_database_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1718,13 +2031,13 @@ sub run_database_check{
|
|||||||
@total_updates = ();
|
@total_updates = ();
|
||||||
|
|
||||||
#::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest...
|
#::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest...
|
||||||
if($local_database_version > 9000){
|
if($local_database_version >= 9000){
|
||||||
$revision_check = $local_database_version;
|
$revision_check = $local_database_version;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$revision_check = 1000;
|
$revision_check = 1000;
|
||||||
if(get_mysql_result("SHOW TABLES LIKE 'character_data'") ne ""){
|
if(get_mysql_result("SHOW TABLES LIKE 'character_data'") ne ""){
|
||||||
$revision_check = 9000;
|
$revision_check = 8999;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
202
utils/scripts/linux_installer/install.sh
Normal file
202
utils/scripts/linux_installer/install.sh
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "This script must be run as root" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#::: Determine releases
|
||||||
|
if [[ -f /etc/debian_version ]]; then
|
||||||
|
export OS=Debian
|
||||||
|
elif [[ -f /etc/fedora-release ]]; then
|
||||||
|
export OS=fedora_core
|
||||||
|
elif [[ -f /etc/redhat-release ]]; then
|
||||||
|
export OS=red_hat
|
||||||
|
else
|
||||||
|
echo "This script must be run on a Debian or RedHat derivative"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "######################################################### "
|
||||||
|
echo "#::: EverQuest Emulator Modular Installer "
|
||||||
|
echo "#::: Installer Author: Akkadius "
|
||||||
|
echo "#::: Installer Co-Author(s): N0ctrnl "
|
||||||
|
echo "#::: "
|
||||||
|
echo "#::: EQEmulator Server Software is developed and maintained "
|
||||||
|
echo "#::: by the EQEmulator Developement team "
|
||||||
|
echo "#::: "
|
||||||
|
echo "#::: Everquest is a registered trademark "
|
||||||
|
echo "#::: Daybreak Game Company LLC. "
|
||||||
|
echo "#::: "
|
||||||
|
echo "#::: EQEmulator is not associated or "
|
||||||
|
echo "#::: affiliated in any way with Daybreak Game Company LLC. "
|
||||||
|
echo "######################################################### "
|
||||||
|
echo "#: "
|
||||||
|
echo "######################################################### "
|
||||||
|
echo "#::: To be installed: "
|
||||||
|
echo "######################################################### "
|
||||||
|
echo "- Server running folder - Will be installed to the folder you ran this script "
|
||||||
|
echo "- MariaDB (MySQL) - Database engine "
|
||||||
|
echo "- Perl 5.X :: Scripting language for quest engines "
|
||||||
|
echo "- LUA Configured :: Scripting language for quest engines "
|
||||||
|
echo "- Latest PEQ Database "
|
||||||
|
echo "- Latest PEQ Quests "
|
||||||
|
echo "- Latest Plugins repository "
|
||||||
|
echo "- Maps (Latest V2) formats are loaded "
|
||||||
|
echo "- New Path files are loaded "
|
||||||
|
echo "- Optimized server binaries "
|
||||||
|
echo "######################################################### "
|
||||||
|
|
||||||
|
# Installation variables (Don't need to change, only for advanced users)
|
||||||
|
|
||||||
|
export eqemu_server_directory=/home/eqemu
|
||||||
|
export apt_options="-y -qq" # Set autoconfirm and silent install
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
read -n1 -r -p "Press any key to continue..." key
|
||||||
|
|
||||||
|
#::: Setting up user environment (eqemu)
|
||||||
|
echo "First, we need to set your passwords..."
|
||||||
|
echo "Make sure that you remember these and keep them somewhere"
|
||||||
|
echo ""
|
||||||
|
echo ""
|
||||||
|
groupadd eqemu
|
||||||
|
useradd -g eqemu -d $eqemu_server_directory eqemu
|
||||||
|
passwd eqemu
|
||||||
|
|
||||||
|
#::: Make server directory and go to it
|
||||||
|
mkdir $eqemu_server_directory
|
||||||
|
cd $eqemu_server_directory
|
||||||
|
|
||||||
|
#::: Setup MySQL root user PW
|
||||||
|
read -p "Enter MySQL root (Database) password: " eqemu_db_root_password
|
||||||
|
|
||||||
|
#::: Write install variables (later use)
|
||||||
|
echo "mysql_root:$eqemu_db_root_password" > install_variables.txt
|
||||||
|
|
||||||
|
#::: Setup MySQL server
|
||||||
|
read -p "Enter Database Name (single word, no special characters, lower case):" eqemu_db_name
|
||||||
|
read -p "Enter (Database) MySQL EQEmu Server username: " eqemu_db_username
|
||||||
|
read -p "Enter (Database) MySQL EQEmu Server password: " eqemu_db_password
|
||||||
|
|
||||||
|
#::: Write install variables (later use)
|
||||||
|
echo "mysql_eqemu_db_name:$eqemu_db_name" >> install_variables.txt
|
||||||
|
echo "mysql_eqemu_user:$eqemu_db_username" >> install_variables.txt
|
||||||
|
echo "mysql_eqemu_password:$eqemu_db_password" >> install_variables.txt
|
||||||
|
|
||||||
|
if [[ "$OS" == "Debian" ]]; then
|
||||||
|
# Install pre-req packages
|
||||||
|
apt-get $apt_options install bash
|
||||||
|
apt-get $apt_options install build-essential
|
||||||
|
apt-get $apt_options install cmake
|
||||||
|
apt-get $apt_options install cpp
|
||||||
|
apt-get $apt_options install curl
|
||||||
|
apt-get $apt_options install debconf-utils
|
||||||
|
apt-get $apt_options install g++
|
||||||
|
apt-get $apt_options install gcc
|
||||||
|
apt-get $apt_options install git
|
||||||
|
apt-get $apt_options install git-core
|
||||||
|
apt-get $apt_options install libio-stringy-perl
|
||||||
|
apt-get $apt_options install liblua5.1
|
||||||
|
apt-get $apt_options install liblua5.1-dev
|
||||||
|
apt-get $apt_options install libluabind-dev
|
||||||
|
apt-get $apt_options install libmysql++
|
||||||
|
apt-get $apt_options install libperl-dev
|
||||||
|
apt-get $apt_options install libperl5i-perl
|
||||||
|
apt-get $apt_options install libwtdbomysql-dev
|
||||||
|
apt-get $apt_options install lua5.1
|
||||||
|
apt-get $apt_options install make
|
||||||
|
apt-get $apt_options install mariadb-client
|
||||||
|
apt-get $apt_options install open-vm-tools
|
||||||
|
apt-get $apt_options install unzip
|
||||||
|
apt-get $apt_options install uuid-dev
|
||||||
|
apt-get $apt_options install zlib-bin
|
||||||
|
apt-get $apt_options install zlibc
|
||||||
|
|
||||||
|
#::: Install FTP for remote FTP access
|
||||||
|
echo "proftpd-basic shared/proftpd/inetd_or_standalone select standalone" | debconf-set-selections
|
||||||
|
apt-get -y -q install proftpd
|
||||||
|
|
||||||
|
#::: Install MariaDB Server
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
debconf-set-selections <<< 'mariadb-server-10.0 mysql-server/root_password password PASS'
|
||||||
|
debconf-set-selections <<< 'mariadb-server-10.0 mysql-server/root_password_again password PASS'
|
||||||
|
apt-get install -y mariadb-server
|
||||||
|
mysql -uroot -pPASS -e "SET PASSWORD = PASSWORD('$eqemu_db_root_password');"
|
||||||
|
|
||||||
|
elif [[ "$OS" == "red_hat" ]]; then
|
||||||
|
# Do RedHat / CentOS stuff
|
||||||
|
# Add the MariaDB repository to yum
|
||||||
|
cat <<EOF > /etc/yum.repos.d/mariadb.repo
|
||||||
|
# MariaDB 10.1 CentOS repository list - created 2016-08-20 05:42 UTC
|
||||||
|
# http://downloads.mariadb.org/mariadb/repositories/
|
||||||
|
[mariadb]
|
||||||
|
name = MariaDB
|
||||||
|
baseurl = http://yum.mariadb.org/10.1/centos7-amd64
|
||||||
|
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
|
||||||
|
enabled=1
|
||||||
|
gpgcheck=1
|
||||||
|
EOF
|
||||||
|
# Install prereqs
|
||||||
|
yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
|
||||||
|
yum -y install deltarpm
|
||||||
|
yum -y install open-vm-tools vim cmake boost-* zlib-devel mariadb-server mariadb-client mariadb-devel mariadb-libs mariadb-compat perl-* lua* dos2unix php-mysql proftpd
|
||||||
|
yum -y groupinstall "Development Tools" "Basic Web Server" "Compatibility Libraries"
|
||||||
|
|
||||||
|
elif [[ "$OS" == "fedora_core" ]]; then
|
||||||
|
# Do Fedora stuff
|
||||||
|
dnf -y install open-vm-tools vim cmake boost-devel zlib-devel mariadb-server mariadb-devel mariadb-libs perl perl-DBD-MySQL perl-IO-stringy perl-devel lua-devel lua-sql-mysql dos2unix php-mysql proftpd wget compat-lua-libs compat-lua-devel compat-lua perl-Time-HiRes
|
||||||
|
dnf -y groupinstall "Development Tools" "Basic Web Server" "C Development Tools and Libraries"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$OS" == "fedora_core" ]] || [[ "$OS" == "red_hat" ]]; then
|
||||||
|
# Start MariaDB server and set root password
|
||||||
|
echo "Starting MariaDB server..."
|
||||||
|
systemctl enable mariadb.service
|
||||||
|
systemctl start mariadb.service
|
||||||
|
sleep 5
|
||||||
|
/usr/bin/mysqladmin -u root password $eqemu_db_root_password
|
||||||
|
fi
|
||||||
|
|
||||||
|
#::: Configure game server database user
|
||||||
|
mysql -uroot -p$eqemu_db_root_password -e "CREATE USER '$eqemu_db_username'@'localhost' IDENTIFIED BY '$eqemu_db_password';"
|
||||||
|
mysql -uroot -p$eqemu_db_root_password -e "GRANT GRANT OPTION ON *.* TO '$eqemu_db_username'@'localhost';"
|
||||||
|
mysql -uroot -p$eqemu_db_root_password -e "GRANT ALL ON *.* TO '$eqemu_db_username'@'localhost';"
|
||||||
|
|
||||||
|
#::: Create source and server directories
|
||||||
|
mkdir $eqemu_server_directory/source
|
||||||
|
mkdir $eqemu_server_directory/server
|
||||||
|
mkdir $eqemu_server_directory/server/export
|
||||||
|
mkdir $eqemu_server_directory/server/logs
|
||||||
|
mkdir $eqemu_server_directory/server/shared
|
||||||
|
mkdir $eqemu_server_directory/server/maps
|
||||||
|
|
||||||
|
#::: Grab loginserver dependencies
|
||||||
|
# cd $eqemu_server_directory/source/Server/dependencies
|
||||||
|
# if [[ "$OS" == "Debian" ]]; then
|
||||||
|
# wget http://eqemu.github.io/downloads/ubuntu_LoginServerCrypto_x64.zip
|
||||||
|
# unzip ubuntu_LoginServerCrypto_x64.zip
|
||||||
|
# rm ubuntu_LoginServerCrypto_x64.zip
|
||||||
|
# elif [[ "$OS" == "fedora_core" ]] || [[ "$OS" == "red_hat" ]]; then
|
||||||
|
# wget http://eqemu.github.io/downloads/fedora12_LoginServerCrypto_x64.zip
|
||||||
|
# unzip fedora12_LoginServerCrypto_x64.zip
|
||||||
|
# rm fedora12_LoginServerCrypto_x64.zip
|
||||||
|
# fi
|
||||||
|
# cd $eqemu_server_directory/source/Server/build
|
||||||
|
|
||||||
|
#::: Back to server directory
|
||||||
|
cd $eqemu_server_directory/server
|
||||||
|
wget https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl
|
||||||
|
|
||||||
|
#::: Map lowercase to uppercase to avoid issues
|
||||||
|
ln -s maps Maps
|
||||||
|
|
||||||
|
#::: Notes
|
||||||
|
|
||||||
|
perl $eqemu_server_directory/server/eqemu_server.pl new_server
|
||||||
|
|
||||||
|
#::: Chown files
|
||||||
|
chown eqemu:eqemu $eqemu_server_directory/ -R
|
||||||
|
chmod 755 $eqemu_server_directory/server/*.pl
|
||||||
|
chmod 755 $eqemu_server_directory/server/*.sh
|
||||||
@ -0,0 +1 @@
|
|||||||
|
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Character:UseOldBindWound', 'true', 'Uses the original bind wound behavior');
|
||||||
@ -1312,6 +1312,7 @@ bool ZoneServer::Process() {
|
|||||||
case ServerOP_CZSignalNPC:
|
case ServerOP_CZSignalNPC:
|
||||||
case ServerOP_CZSetEntityVariableByNPCTypeID:
|
case ServerOP_CZSetEntityVariableByNPCTypeID:
|
||||||
case ServerOP_CZSignalClient:
|
case ServerOP_CZSignalClient:
|
||||||
|
case ServerOP_WWMarquee:
|
||||||
case ServerOP_DepopAllPlayersCorpses:
|
case ServerOP_DepopAllPlayersCorpses:
|
||||||
case ServerOP_DepopPlayerCorpse:
|
case ServerOP_DepopPlayerCorpse:
|
||||||
case ServerOP_ReloadTitles:
|
case ServerOP_ReloadTitles:
|
||||||
|
|||||||
@ -2529,6 +2529,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
|||||||
|
|
||||||
case SE_ImmuneFleeing:
|
case SE_ImmuneFleeing:
|
||||||
new_bonus->ImmuneToFlee = true;
|
new_bonus->ImmuneToFlee = true;
|
||||||
|
if (currently_fleeing) // lets update shit now instead of next tick
|
||||||
|
ProcessFlee();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SE_DelayDeath:
|
case SE_DelayDeath:
|
||||||
|
|||||||
148
zone/client.cpp
148
zone/client.cpp
@ -2655,60 +2655,120 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail)
|
|||||||
bind_out->type = 0;
|
bind_out->type = 0;
|
||||||
CheckIncreaseSkill(EQEmu::skills::SkillBindWound, nullptr, 5);
|
CheckIncreaseSkill(EQEmu::skills::SkillBindWound, nullptr, 5);
|
||||||
|
|
||||||
int maxHPBonus = spellbonuses.MaxBindWound + itembonuses.MaxBindWound +
|
if (RuleB(Character, UseOldBindWound)) {
|
||||||
aabonuses.MaxBindWound;
|
int maxHPBonus = spellbonuses.MaxBindWound + itembonuses.MaxBindWound +
|
||||||
|
aabonuses.MaxBindWound;
|
||||||
|
|
||||||
int max_percent = 50 + 10 * maxHPBonus;
|
int max_percent = 50 + maxHPBonus;
|
||||||
|
|
||||||
if (GetClass() == MONK && GetSkill(EQEmu::skills::SkillBindWound) > 200) {
|
if (GetClass() == MONK && GetSkill(EQEmu::skills::SkillBindWound) > 200) {
|
||||||
max_percent = 70 + 10 * maxHPBonus;
|
max_percent = 70 + maxHPBonus;
|
||||||
}
|
|
||||||
|
|
||||||
max_percent = mod_bindwound_percent(max_percent, bindmob);
|
|
||||||
|
|
||||||
int max_hp = bindmob->GetMaxHP() * max_percent / 100;
|
|
||||||
|
|
||||||
// send bindmob new hp's
|
|
||||||
if (bindmob->GetHP() < bindmob->GetMaxHP() && bindmob->GetHP() <= (max_hp)-1) {
|
|
||||||
// 0.120 per skill point, 0.60 per skill level, minimum 3 max 30
|
|
||||||
int bindhps = 3;
|
|
||||||
|
|
||||||
if (GetSkill(EQEmu::skills::SkillBindWound) > 200) {
|
|
||||||
bindhps += GetSkill(EQEmu::skills::SkillBindWound) * 4 / 10;
|
|
||||||
}
|
|
||||||
else if (GetSkill(EQEmu::skills::SkillBindWound) >= 10) {
|
|
||||||
bindhps += GetSkill(EQEmu::skills::SkillBindWound) / 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of aaMithanielsBinding is a guess (the multiplier)
|
max_percent = mod_bindwound_percent(max_percent, bindmob);
|
||||||
int bindBonus = spellbonuses.BindWound + itembonuses.BindWound +
|
|
||||||
|
int max_hp = bindmob->GetMaxHP() * max_percent / 100;
|
||||||
|
|
||||||
|
// send bindmob new hp's
|
||||||
|
if (bindmob->GetHP() < bindmob->GetMaxHP() && bindmob->GetHP() <= (max_hp)-1) {
|
||||||
|
// 0.120 per skill point, 0.60 per skill level, minimum 3 max 30
|
||||||
|
int bindhps = 3;
|
||||||
|
|
||||||
|
if (GetSkill(EQEmu::skills::SkillBindWound) > 200) {
|
||||||
|
bindhps += GetSkill(EQEmu::skills::SkillBindWound) * 4 / 10;
|
||||||
|
}
|
||||||
|
else if (GetSkill(EQEmu::skills::SkillBindWound) >= 10) {
|
||||||
|
bindhps += GetSkill(EQEmu::skills::SkillBindWound) / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementation of aaMithanielsBinding is a guess (the multiplier)
|
||||||
|
int bindBonus = spellbonuses.BindWound + itembonuses.BindWound +
|
||||||
aabonuses.BindWound;
|
aabonuses.BindWound;
|
||||||
|
|
||||||
bindhps += bindhps * bindBonus / 100;
|
bindhps += bindhps * bindBonus / 100;
|
||||||
|
|
||||||
bindhps = mod_bindwound_hp(bindhps, bindmob);
|
bindhps = mod_bindwound_hp(bindhps, bindmob);
|
||||||
|
|
||||||
// if the bind takes them above the max bindable
|
// if the bind takes them above the max bindable
|
||||||
// cap it at that value. Dont know if live does it this way
|
// cap it at that value. Dont know if live does it this way
|
||||||
// but it makes sense to me.
|
// but it makes sense to me.
|
||||||
int chp = bindmob->GetHP() + bindhps;
|
int chp = bindmob->GetHP() + bindhps;
|
||||||
if (chp > max_hp)
|
if (chp > max_hp)
|
||||||
chp = max_hp;
|
chp = max_hp;
|
||||||
|
|
||||||
bindmob->SetHP(chp);
|
bindmob->SetHP(chp);
|
||||||
bindmob->SendHPUpdate();
|
bindmob->SendHPUpdate();
|
||||||
} else {
|
}
|
||||||
// I dont have the real, live
|
else {
|
||||||
Message(15, "You cannot bind wounds above %d%% hitpoints.",
|
// I dont have the real, live
|
||||||
max_percent);
|
Message(15, "You cannot bind wounds above %d%% hitpoints.",
|
||||||
if (bindmob != this && bindmob->IsClient())
|
max_percent);
|
||||||
bindmob->CastToClient()->Message(
|
if (bindmob != this && bindmob->IsClient())
|
||||||
15,
|
bindmob->CastToClient()->Message(
|
||||||
"You cannot have your wounds bound above %d%% hitpoints.",
|
15,
|
||||||
max_percent);
|
"You cannot have your wounds bound above %d%% hitpoints.",
|
||||||
// Too many hp message goes here.
|
max_percent);
|
||||||
|
// Too many hp message goes here.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
else {
|
||||||
|
int percent_base = 50;
|
||||||
|
if (GetRawSkill(EQEmu::skills::SkillBindWound) > 200) {
|
||||||
|
if ((GetClass() == MONK) || (GetClass() == BEASTLORD))
|
||||||
|
percent_base = 70;
|
||||||
|
else if ((GetLevel() > 50) && ((GetClass() == WARRIOR) || (GetClass() == ROGUE) || (GetClass() == CLERIC)))
|
||||||
|
percent_base = 70;
|
||||||
|
}
|
||||||
|
|
||||||
|
int percent_bonus = 0;
|
||||||
|
if (percent_base >= 70)
|
||||||
|
percent_bonus = spellbonuses.MaxBindWound + itembonuses.MaxBindWound + aabonuses.MaxBindWound;
|
||||||
|
|
||||||
|
int max_percent = percent_base + percent_bonus;
|
||||||
|
if (max_percent < 0)
|
||||||
|
max_percent = 0;
|
||||||
|
if (max_percent > 100)
|
||||||
|
max_percent = 100;
|
||||||
|
|
||||||
|
max_percent = mod_bindwound_percent(max_percent, bindmob);
|
||||||
|
|
||||||
|
int max_hp = (bindmob->GetMaxHP() * max_percent) / 100;
|
||||||
|
if (max_hp > bindmob->GetMaxHP())
|
||||||
|
max_hp = bindmob->GetMaxHP();
|
||||||
|
|
||||||
|
if (bindmob->GetHP() < bindmob->GetMaxHP() && bindmob->GetHP() < max_hp) {
|
||||||
|
int bindhps = 3; // base bind hp
|
||||||
|
if (percent_base >= 70)
|
||||||
|
bindhps = (GetSkill(EQEmu::skills::SkillBindWound) * 4) / 10; // 8:5 skill-to-hp ratio
|
||||||
|
else if (GetSkill(EQEmu::skills::SkillBindWound) >= 12)
|
||||||
|
bindhps = GetSkill(EQEmu::skills::SkillBindWound) / 4; // 4:1 skill-to-hp ratio
|
||||||
|
|
||||||
|
int bonus_hp_percent = 0;
|
||||||
|
if (percent_base >= 70)
|
||||||
|
bonus_hp_percent = spellbonuses.BindWound + itembonuses.BindWound + aabonuses.BindWound;
|
||||||
|
|
||||||
|
bindhps += (bindhps * bonus_hp_percent) / 100;
|
||||||
|
|
||||||
|
if (bindhps < 3)
|
||||||
|
bindhps = 3;
|
||||||
|
|
||||||
|
bindhps = mod_bindwound_hp(bindhps, bindmob);
|
||||||
|
|
||||||
|
bindhps += bindmob->GetHP();
|
||||||
|
if (bindhps > max_hp)
|
||||||
|
bindhps = max_hp;
|
||||||
|
|
||||||
|
bindmob->SetHP(bindhps);
|
||||||
|
bindmob->SendHPUpdate();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Message(15, "You cannot bind wounds above %d%% hitpoints", max_percent);
|
||||||
|
if (bindmob != this && bindmob->IsClient())
|
||||||
|
bindmob->CastToClient()->Message(15, "You cannot have your wounds bound above %d%% hitpoints", max_percent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
// Send client bind failed
|
// Send client bind failed
|
||||||
if (bindmob != this)
|
if (bindmob != this)
|
||||||
bind_out->type = 6; // They moved
|
bind_out->type = 6; // They moved
|
||||||
|
|||||||
@ -795,6 +795,7 @@ public:
|
|||||||
void SendClearAA();
|
void SendClearAA();
|
||||||
inline uint32 GetMaxAAXP(void) const { return max_AAXP; }
|
inline uint32 GetMaxAAXP(void) const { return max_AAXP; }
|
||||||
inline uint32 GetAAXP() const { return m_pp.expAA; }
|
inline uint32 GetAAXP() const { return m_pp.expAA; }
|
||||||
|
inline uint32 GetAAPercent() const { return m_epp.perAA; }
|
||||||
int16 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id);
|
int16 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id);
|
||||||
void SetAATitle(const char *Title);
|
void SetAATitle(const char *Title);
|
||||||
void SetTitleSuffix(const char *txt);
|
void SetTitleSuffix(const char *txt);
|
||||||
|
|||||||
@ -3616,6 +3616,26 @@ XS(XS__crosszonesignalnpcbynpctypeid)
|
|||||||
XSRETURN_EMPTY;
|
XSRETURN_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XS(XS__worldwidemarquee);
|
||||||
|
XS(XS__worldwidemarquee)
|
||||||
|
{
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 6)
|
||||||
|
Perl_croak(aTHX_ "Usage: worldwidemarquee(type, priority, fadein, fadeout, duration, message)");
|
||||||
|
|
||||||
|
if (items == 6) {
|
||||||
|
uint32 type = (uint32)SvIV(ST(0));
|
||||||
|
uint32 priority = (uint32)SvIV(ST(1));
|
||||||
|
uint32 fadein = (uint32)SvIV(ST(2));
|
||||||
|
uint32 fadeout = (uint32)SvIV(ST(3));
|
||||||
|
uint32 duration = (uint32)SvIV(ST(4));
|
||||||
|
char* message = (char *)SvPV_nolen(ST(5));
|
||||||
|
quest_manager.WorldWideMarquee(type, priority, fadein, fadeout, duration, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
XSRETURN_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
XS(XS__debug);
|
XS(XS__debug);
|
||||||
XS(XS__debug)
|
XS(XS__debug)
|
||||||
{
|
{
|
||||||
@ -3749,6 +3769,7 @@ EXTERN_C XS(boot_quest)
|
|||||||
newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file);
|
newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file);
|
||||||
newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, file);
|
newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, file);
|
||||||
newXS(strcpy(buf, "crosszonesignalnpcbynpctypeid"), XS__crosszonesignalnpcbynpctypeid, file);
|
newXS(strcpy(buf, "crosszonesignalnpcbynpctypeid"), XS__crosszonesignalnpcbynpctypeid, file);
|
||||||
|
newXS(strcpy(buf, "worldwidemarquee"), XS__worldwidemarquee, file);
|
||||||
newXS(strcpy(buf, "debug"), XS__debug, file);
|
newXS(strcpy(buf, "debug"), XS__debug, file);
|
||||||
newXS(strcpy(buf, "delglobal"), XS__delglobal, file);
|
newXS(strcpy(buf, "delglobal"), XS__delglobal, file);
|
||||||
newXS(strcpy(buf, "depop"), XS__depop, file);
|
newXS(strcpy(buf, "depop"), XS__depop, file);
|
||||||
|
|||||||
@ -185,6 +185,11 @@ uint32 Lua_Client::GetAAExp() {
|
|||||||
return self->GetAAXP();
|
return self->GetAAXP();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 Lua_Client::GetAAPercent() {
|
||||||
|
Lua_Safe_Call_Int();
|
||||||
|
return self->GetAAPercent();
|
||||||
|
}
|
||||||
|
|
||||||
uint32 Lua_Client::GetTotalSecondsPlayed() {
|
uint32 Lua_Client::GetTotalSecondsPlayed() {
|
||||||
Lua_Safe_Call_Int();
|
Lua_Safe_Call_Int();
|
||||||
return self->GetTotalSecondsPlayed();
|
return self->GetTotalSecondsPlayed();
|
||||||
@ -1377,6 +1382,7 @@ luabind::scope lua_register_client() {
|
|||||||
.def("GetWeight", (int(Lua_Client::*)(void))&Lua_Client::GetWeight)
|
.def("GetWeight", (int(Lua_Client::*)(void))&Lua_Client::GetWeight)
|
||||||
.def("GetEXP", (uint32(Lua_Client::*)(void))&Lua_Client::GetEXP)
|
.def("GetEXP", (uint32(Lua_Client::*)(void))&Lua_Client::GetEXP)
|
||||||
.def("GetAAExp", (uint32(Lua_Client::*)(void))&Lua_Client::GetAAExp)
|
.def("GetAAExp", (uint32(Lua_Client::*)(void))&Lua_Client::GetAAExp)
|
||||||
|
.def("GetAAPercent", (uint32(Lua_Client::*)(void))&Lua_Client::GetAAPercent)
|
||||||
.def("GetTotalSecondsPlayed", (uint32(Lua_Client::*)(void))&Lua_Client::GetTotalSecondsPlayed)
|
.def("GetTotalSecondsPlayed", (uint32(Lua_Client::*)(void))&Lua_Client::GetTotalSecondsPlayed)
|
||||||
.def("UpdateLDoNPoints", (void(Lua_Client::*)(int,uint32))&Lua_Client::UpdateLDoNPoints)
|
.def("UpdateLDoNPoints", (void(Lua_Client::*)(int,uint32))&Lua_Client::UpdateLDoNPoints)
|
||||||
.def("SetDeity", (void(Lua_Client::*)(int))&Lua_Client::SetDeity)
|
.def("SetDeity", (void(Lua_Client::*)(int))&Lua_Client::SetDeity)
|
||||||
|
|||||||
@ -63,6 +63,7 @@ public:
|
|||||||
int GetWeight();
|
int GetWeight();
|
||||||
uint32 GetEXP();
|
uint32 GetEXP();
|
||||||
uint32 GetAAExp();
|
uint32 GetAAExp();
|
||||||
|
uint32 GetAAPercent();
|
||||||
uint32 GetTotalSecondsPlayed();
|
uint32 GetTotalSecondsPlayed();
|
||||||
void UpdateLDoNPoints(int points, uint32 theme);
|
void UpdateLDoNPoints(int points, uint32 theme);
|
||||||
void SetDeity(int v);
|
void SetDeity(int v);
|
||||||
|
|||||||
@ -892,6 +892,10 @@ void lua_cross_zone_message_player_by_name(uint32 type, const char *player, cons
|
|||||||
quest_manager.CrossZoneMessagePlayerByName(type, player, message);
|
quest_manager.CrossZoneMessagePlayerByName(type, player, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lua_world_wide_marquee(uint32 type, uint32 priority, uint32 fadein, uint32 fadeout, uint32 duration, const char *message) {
|
||||||
|
quest_manager.WorldWideMarquee(type, priority, fadein, fadeout, duration, message);
|
||||||
|
}
|
||||||
|
|
||||||
luabind::adl::object lua_get_qglobals(lua_State *L, Lua_NPC npc, Lua_Client client) {
|
luabind::adl::object lua_get_qglobals(lua_State *L, Lua_NPC npc, Lua_Client client) {
|
||||||
luabind::adl::object ret = luabind::newtable(L);
|
luabind::adl::object ret = luabind::newtable(L);
|
||||||
|
|
||||||
@ -1613,6 +1617,7 @@ luabind::scope lua_register_general() {
|
|||||||
luabind::def("cross_zone_signal_client_by_char_id", &lua_cross_zone_signal_client_by_char_id),
|
luabind::def("cross_zone_signal_client_by_char_id", &lua_cross_zone_signal_client_by_char_id),
|
||||||
luabind::def("cross_zone_signal_client_by_name", &lua_cross_zone_signal_client_by_name),
|
luabind::def("cross_zone_signal_client_by_name", &lua_cross_zone_signal_client_by_name),
|
||||||
luabind::def("cross_zone_message_player_by_name", &lua_cross_zone_message_player_by_name),
|
luabind::def("cross_zone_message_player_by_name", &lua_cross_zone_message_player_by_name),
|
||||||
|
luabind::def("world_wide_marquee", &lua_world_wide_marquee),
|
||||||
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC,Lua_Client))&lua_get_qglobals),
|
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC,Lua_Client))&lua_get_qglobals),
|
||||||
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_Client))&lua_get_qglobals),
|
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_Client))&lua_get_qglobals),
|
||||||
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC))&lua_get_qglobals),
|
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC))&lua_get_qglobals),
|
||||||
|
|||||||
@ -871,6 +871,32 @@ XS(XS_Client_GetAAExp)
|
|||||||
XSRETURN(1);
|
XSRETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XS(XS_Client_GetAAPercent);
|
||||||
|
XS(XS_Client_GetAAPercent)
|
||||||
|
{
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 1)
|
||||||
|
Perl_croak(aTHX_ "Usage: Client::GetAAPercent(THIS)");
|
||||||
|
{
|
||||||
|
Client* THIS;
|
||||||
|
uint32 RETVAL;
|
||||||
|
dXSTARG;
|
||||||
|
|
||||||
|
if (sv_derived_from(ST(0), "Client")) {
|
||||||
|
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||||
|
THIS = INT2PTR(Client *,tmp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Perl_croak(aTHX_ "THIS is not of type Client");
|
||||||
|
if(THIS == nullptr)
|
||||||
|
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||||
|
|
||||||
|
RETVAL = THIS->GetAAPercent();
|
||||||
|
XSprePUSH; PUSHu((UV)RETVAL);
|
||||||
|
}
|
||||||
|
XSRETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
XS(XS_Client_GetTotalSecondsPlayed); /* prototype to pass -Wmissing-prototypes */
|
XS(XS_Client_GetTotalSecondsPlayed); /* prototype to pass -Wmissing-prototypes */
|
||||||
XS(XS_Client_GetTotalSecondsPlayed)
|
XS(XS_Client_GetTotalSecondsPlayed)
|
||||||
{
|
{
|
||||||
@ -6465,6 +6491,7 @@ XS(boot_Client)
|
|||||||
newXSproto(strcpy(buf, "GetWeight"), XS_Client_GetWeight, file, "$");
|
newXSproto(strcpy(buf, "GetWeight"), XS_Client_GetWeight, file, "$");
|
||||||
newXSproto(strcpy(buf, "GetEXP"), XS_Client_GetEXP, file, "$");
|
newXSproto(strcpy(buf, "GetEXP"), XS_Client_GetEXP, file, "$");
|
||||||
newXSproto(strcpy(buf, "GetAAExp"), XS_Client_GetAAExp, file, "$");
|
newXSproto(strcpy(buf, "GetAAExp"), XS_Client_GetAAExp, file, "$");
|
||||||
|
newXSproto(strcpy(buf, "GetAAPercent"), XS_Client_GetAAPercent, file, "$");
|
||||||
newXSproto(strcpy(buf, "GetTotalSecondsPlayed"), XS_Client_GetTotalSecondsPlayed, file, "$");
|
newXSproto(strcpy(buf, "GetTotalSecondsPlayed"), XS_Client_GetTotalSecondsPlayed, file, "$");
|
||||||
newXSproto(strcpy(buf, "UpdateLDoNPoints"), XS_Client_UpdateLDoNPoints, file, "$$$");
|
newXSproto(strcpy(buf, "UpdateLDoNPoints"), XS_Client_UpdateLDoNPoints, file, "$$$");
|
||||||
newXSproto(strcpy(buf, "SetDeity"), XS_Client_SetDeity, file, "$$");
|
newXSproto(strcpy(buf, "SetDeity"), XS_Client_SetDeity, file, "$$");
|
||||||
|
|||||||
@ -3017,6 +3017,20 @@ void QuestManager::CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, cons
|
|||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QuestManager::WorldWideMarquee(uint32 Type, uint32 Priority, uint32 FadeIn, uint32 FadeOut, uint32 Duration, const char *Message) {
|
||||||
|
uint32 message_len = strlen(Message) + 1;
|
||||||
|
auto pack = new ServerPacket(ServerOP_WWMarquee, sizeof(WWMarquee_Struct) + message_len);
|
||||||
|
WWMarquee_Struct* WWMS = (WWMarquee_Struct*) pack->pBuffer;
|
||||||
|
WWMS->Type = Type;
|
||||||
|
WWMS->Priority = Priority;
|
||||||
|
WWMS->FadeIn = FadeIn;
|
||||||
|
WWMS->FadeOut = FadeOut;
|
||||||
|
WWMS->Duration = Duration;
|
||||||
|
strn0cpy(WWMS->Message, Message, 512);
|
||||||
|
worldserver.SendPacket(pack);
|
||||||
|
safe_delete(pack);
|
||||||
|
}
|
||||||
|
|
||||||
bool QuestManager::EnableRecipe(uint32 recipe_id)
|
bool QuestManager::EnableRecipe(uint32 recipe_id)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|||||||
@ -252,6 +252,7 @@ public:
|
|||||||
void CrossZoneSignalPlayerByName(const char *CharName, uint32 data);
|
void CrossZoneSignalPlayerByName(const char *CharName, uint32 data);
|
||||||
void CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var);
|
void CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var);
|
||||||
void CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message);
|
void CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message);
|
||||||
|
void WorldWideMarquee(uint32 Type, uint32 Priority, uint32 FadeIn, uint32 FadeOut, uint32 Duration, const char *Message);
|
||||||
bool EnableRecipe(uint32 recipe_id);
|
bool EnableRecipe(uint32 recipe_id);
|
||||||
bool DisableRecipe(uint32 recipe_id);
|
bool DisableRecipe(uint32 recipe_id);
|
||||||
void ClearNPCTypeCache(int npctype_id);
|
void ClearNPCTypeCache(int npctype_id);
|
||||||
|
|||||||
@ -5458,8 +5458,10 @@ void Mob::SendBuffsToClient(Client *c)
|
|||||||
EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target)
|
EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target)
|
||||||
{
|
{
|
||||||
uint32 count = 0;
|
uint32 count = 0;
|
||||||
uint32 buff_count = GetMaxTotalSlots();
|
// for self we want all buffs, for target, we want to skip song window buffs
|
||||||
for(unsigned int i = 0; i < buff_count; ++i)
|
// since NPCs and pets don't have a song window, we still see it for them :P
|
||||||
|
uint32 buff_count = for_target ? GetMaxBuffSlots() : GetMaxTotalSlots();
|
||||||
|
for(int i = 0; i < buff_count; ++i)
|
||||||
{
|
{
|
||||||
if(buffs[i].spellid != SPELL_UNKNOWN)
|
if(buffs[i].spellid != SPELL_UNKNOWN)
|
||||||
{
|
{
|
||||||
@ -5491,7 +5493,7 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target)
|
|||||||
buff->type = 0;
|
buff->type = 0;
|
||||||
|
|
||||||
uint32 index = 0;
|
uint32 index = 0;
|
||||||
for(unsigned int i = 0; i < buff_count; ++i)
|
for(int i = 0; i < buff_count; ++i)
|
||||||
{
|
{
|
||||||
if(buffs[i].spellid != SPELL_UNKNOWN)
|
if(buffs[i].spellid != SPELL_UNKNOWN)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1838,6 +1838,19 @@ void WorldServer::Process() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ServerOP_WWMarquee:
|
||||||
|
{
|
||||||
|
WWMarquee_Struct* WWMS = (WWMarquee_Struct*) pack->pBuffer;
|
||||||
|
std::list<Client*> client_list;
|
||||||
|
entity_list.GetClientList(client_list);
|
||||||
|
auto iter = client_list.begin();
|
||||||
|
std::string Message = WWMS->Message;
|
||||||
|
while (iter != client_list.end()) {
|
||||||
|
Client* client = (*iter);
|
||||||
|
client->SendMarqueeMessage(WWMS->Type, WWMS->Priority, WWMS->FadeIn, WWMS->FadeOut, WWMS->Duration, Message);
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
case ServerOP_ReloadWorld:
|
case ServerOP_ReloadWorld:
|
||||||
{
|
{
|
||||||
ReloadWorld_Struct* RW = (ReloadWorld_Struct*) pack->pBuffer;
|
ReloadWorld_Struct* RW = (ReloadWorld_Struct*) pack->pBuffer;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user