Compare commits

...

37 Commits

Author SHA1 Message Date
JJ 7c3481daf9 [Release] 22.39.1 (#3834) 2023-12-31 18:39:07 -05:00
Alex King b93dec357f [Quest API] Fix issue with death events. (#3823)
# Notes
- Death events were happening too early so stuff checking for dead NPCs was non-functional.
2023-12-31 17:37:26 -05:00
Alex King 2f4af4f0c2 [Bug Fix] Fix crash in Client::Handle_OP_GMGoto (#3832)
# Notes
- Logic was incorrect.
2023-12-31 15:45:08 -05:00
Chris Miles a0f2a8a743 [Database] Database update improvements, content db and terminal checks (#3814)
* [Database] Database update improvements, content db and terminal checks

* Update manifest entries with content flag

* Update database_update_manifest.cpp
2023-12-30 22:15:01 -06:00
Chris Miles 4c7016bd7b [Repositories] Protected extended repositories from being overwritten if exists (#3815) 2023-12-30 22:14:46 -06:00
Alex King 6c18cd0bee [Quest API] Add HasItemOnCorpse() to Perl/Lua (#3824)
# Perl
- Add `$client->HasItemOnCorpse(item_id)`.

# Lua
- Add `client:HasItemOnCorpse(item_id)`.

# Notes
- Allows operators to see if a player has an item on any of their corpses.
- May need to address having to allocate and deallocate memory for every corpse that could possibly exist for a player.
2023-12-30 22:09:48 -06:00
Alex King 87e63e1e36 [Cleanup] Remove unused PlotPosition methods from mob.cpp/mob.h (#3820)
# Notes
- These are unused.
2023-12-30 22:07:02 -06:00
Alex King a771882cff [Cleanup] Remove SendStunAppearance from mob.cpp/mob.h (#3818)
# Notes
- This is unused.
2023-12-30 22:06:46 -06:00
Alex King b3f6a8c55f [Cleanup] Remove MakeSpawnUpdateNoDelta from mob.cpp/mob.h (#3816)
# Notes
- This is unused.
2023-12-30 22:06:33 -06:00
Fryguy 605502cd9d [Bug Fix] Client:SetBucket Overload Incorrectly Named (#3825)
There was an issue with Client:SetBucket when attempting to use an expiration date. Looks like a lua def was mistakenly named SetBucketExpires.
2023-12-30 15:31:04 -05:00
Alex King 4712ca471b [Cleanup] Gender constants cleanup (#3817)
* [Cleanup] Gender constants cleanup

# Notes
- Convert to a `Gender` namespace using `constexpr`.
- Cleanup spots where we were using magic numbers for gender values.

* Cleanup
2023-12-30 11:22:09 -05:00
Alex King 836c3d6596 [Cleanup] Appearance not appearence (#3819)
# Notes
- These were misspelled.
2023-12-30 11:22:02 -05:00
Alex King 53169ae217 [Cleanup] Delete errmsg.h in common and zone (#3821)
* [Cleanup] Delete errmsg.h in common and zone

# Notes
- These files were mostly unused.
- Moved the stuff that was used to the `dbcore.h` file since it's already used.

* Remove references
2023-12-30 11:21:57 -05:00
Chris Miles fd31915fae [Release] 22.39.0 (#3812) 2023-12-27 20:09:21 -06:00
Chris Miles 52763b6dd2 [Character] Fix character copier due to schema change (#3805)
* [Character] Fix character copier due to schema change

* Tweak
2023-12-27 20:04:46 -06:00
Chris Miles 51cd43b4ea [Player Events] Bulk replace settings on boot (#3806) 2023-12-27 20:04:29 -06:00
Chris Miles 2db84f5a4f [MySQL] Fix MySQL Query error formatting (#3808) 2023-12-27 20:04:18 -06:00
Chris Miles 79cc2d5351 [Logs] Reclassify unhelpful Info message (#3809) 2023-12-27 20:04:11 -06:00
Chris Miles d31cb09214 [Logs] Bulk insert new log settings (#3810) 2023-12-27 20:04:01 -06:00
Chris Miles 8bedcd8751 [Tasks] Add enabled column (#3804)
* [Tasks] Add enabled column

* Update task_manager.cpp

* Update task_manager.cpp

* Update base_tasks_repository.h
2023-12-27 20:03:53 -06:00
Chris Miles 473c5096f6 [Objects] Remove "No objects to load for zone" error message (#3807) 2023-12-27 21:03:08 -05:00
Paul Coene 0b181d5048 [Combat] Disarm was not dropping item to ground due to bug (#3811) 2023-12-27 10:19:09 -05:00
Chris Miles a7e9af2d27 [Release] 22.38.0 (#3803) 2023-12-26 16:30:09 -05:00
Chris Miles 7a72d5d67e [Repositories] Add ReplaceOne and ReplaceMany (#3802) 2023-12-25 20:53:44 -05:00
regneq 25872203ff [NPC] Support for multiple emotes per type, emote variables (#3801)
* [forage rule feature] add a rule to disabled using common_food_ids from the list in forage.cpp.  currently set to enabled.

* NPC database emotes now supports basic variables. More than one variable can be used at a time.

* Format manifest

* Formatting

* Formatting

* Formatting

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-12-24 23:28:57 -06:00
Alex King 6396a6fbef [Cleanup] Consolidate GetHateRandom(), GetHateRandomBot(), GetHateRandomClient(), and GetHateRandomNPC() (#3794)
* [Cleanup] Consolidate GetHateRandomBot(), GetHateRandomClient(), and GetHateRandomNPC()

# Notes
- These were separate methods and duplicated a lot of code, consolidated into the singular method using the `EntityFilterType`.

* Simplify random logic. Use filtered hate list.

* D

* D
2023-12-24 23:28:47 -06:00
Chris Miles 6db0a5c3f0 [Database] Fix issue with saylinks query in MySQL 8.0+ (#3800) 2023-12-24 09:43:31 -06:00
Chris Miles 4fa9e1d66f [Code Cleanup] Race constants refactor (#3782)
* [Code Cleanup] Race constants refactor

* Update races.h
2023-12-22 21:34:55 -06:00
JJ 556af8c5e9 [Database] Update faction mods with Live data (#3799)
Optional update to bring database up-to-date with Live data which includes Froglok and Drakkin data which was previously missing.
Raw data can be found in the Live client at Resources\Faction\FactionAssociations.txt
See discussion at #3678
2023-12-22 21:34:35 -06:00
Alex King f3ef8a0993 [Quest API] Add SummonItemIntoInventory() to Perl/Lua (#3797)
* [Quest API] Add SummonItemIntoInventory() to Perl/Lua

# Perl
- Add `$client->SummonItemIntoInventory(item_data)`.

## Example
```pl
sub EVENT_SAY {
	if ($text=~/#a/i) {
		my %item_data = (
			"item_id" => 32557,
			"charges" => 1
		);
		$client->SummonItemIntoInventory(\%item_data);
	}
}
```

# Lua
- Add `client:SummonItemIntoInventory(item_data)`.

## Example
```lua
function event_say(e)
	if e.message:find("#a") then
		local item_data = {
			"item_id" = 32557,
			"charges" = 1
		}
		e.self:SummonItemIntoInventory(item_data)
	end
end
```

* Update effects.cpp
2023-12-22 02:45:40 -06:00
regneq 267c280db8 [forage rule feature] add a rule to disabled using common_food_ids from the list in forage.cpp. currently set to enabled. (#3796) 2023-12-22 02:43:17 -06:00
Alex King e06c7d7735 [Quest API] Add GetHateTopBot(), GetHateTopClient(), and GetHateTopNPC() to Perl/Lua (#3793)
# Perl
- Add `$mob->GetHateTopBot()`.
- Add `$mob->GetHateTopClient()`.
- Add `$mob->GetHateTopNPC()`.

# Lua
- Add `mob:GetHateTopBot()`.
- Add `mob:GetHateTopClient()`.
- Add `mob:GetHateTopNPC()`.
2023-12-22 02:41:32 -06:00
nytmyr 028ebc3a0c [Bots] Remove unnecessary error on SetItemReuse (#3795)
This error is not necessary as it can be triggered when clicked spells have secondary effects that run through the same spell checks for clicked items but aren't actually clicked by the item. Spells that trigger other spell effects and some Bard scaling songs could trigger this after the initial click.
2023-12-20 10:01:54 -05:00
Alex King b3bd44cd76 [Bug Fix] Fix can_riposte parameter in DoMeleeSkillAttackDmg (#3792)
# Note
- `can_riposte` logic was reverse, setting to `true` caused the attack to not be able to be riposted, the opposite of the intended functionality.
2023-12-18 22:27:58 -05:00
Alex King 75a627a3a2 [Bug Fix] Disable Hide/Improved Hide on Trap damage (#3791)
# Notes
- Further fixes an issue where traps don't drop hide/invisible.
2023-12-18 22:24:03 -05:00
dependabot[bot] 0194aedc92 Bump golang.org/x/crypto in /utils/scripts/build/should-release (#3790)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.14.0 to 0.17.0.
- [Commits](https://github.com/golang/crypto/compare/v0.14.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-18 18:10:48 -06:00
Alex King 5cc87cbda7 [Bug Fix] Fix Bard Invisibility Songs breaking every 4 ticks (#3783)
# Notes
- Fixes #2361.
2023-12-18 18:10:28 -06:00
100 changed files with 13249 additions and 3381 deletions
+99
View File
@@ -1,3 +1,102 @@
## [22.39.1] - 12/31/2023
### Code
* Appearance not appearence ([#3819](https://github.com/EQEmu/Server/pull/3819)) @Kinglykrab 2023-12-30
* Delete errmsg.h in common and zone ([#3821](https://github.com/EQEmu/Server/pull/3821)) @Kinglykrab 2023-12-30
* Gender constants cleanup ([#3817](https://github.com/EQEmu/Server/pull/3817)) @Kinglykrab 2023-12-30
* Remove MakeSpawnUpdateNoDelta from mob.cpp/mob.h ([#3816](https://github.com/EQEmu/Server/pull/3816)) @Kinglykrab 2023-12-31
* Remove SendStunAppearance from mob.cpp/mob.h ([#3818](https://github.com/EQEmu/Server/pull/3818)) @Kinglykrab 2023-12-31
* Remove unused PlotPosition methods from mob.cpp/mob.h ([#3820](https://github.com/EQEmu/Server/pull/3820)) @Kinglykrab 2023-12-31
### Database
* Database update improvements, content db and terminal checks ([#3814](https://github.com/EQEmu/Server/pull/3814)) @Akkadius 2023-12-31
### Fixes
* Client:SetBucket Overload Incorrectly Named ([#3825](https://github.com/EQEmu/Server/pull/3825)) @fryguy503 2023-12-30
* Fix crash in Client::Handle_OP_GMGoto ([#3832](https://github.com/EQEmu/Server/pull/3832)) @Kinglykrab 2023-12-31
### Quest API
* Add HasItemOnCorpse() to Perl/Lua ([#3824](https://github.com/EQEmu/Server/pull/3824)) @Kinglykrab 2023-12-31
* Fix issue with death events. ([#3823](https://github.com/EQEmu/Server/pull/3823)) @Kinglykrab 2023-12-31
### Repositories
* Protected extended repositories from being overwritten if exists ([#3815](https://github.com/EQEmu/Server/pull/3815)) @Akkadius 2023-12-31
## [22.39.0] - 12/27/2023
### Character
* Fix character copier due to schema change ([#3805](https://github.com/EQEmu/Server/pull/3805)) @Akkadius 2023-12-28
### Combat
* Disarm was not dropping item to ground due to bug ([#3811](https://github.com/EQEmu/Server/pull/3811)) @noudess 2023-12-27
### Logs
* Bulk insert new log settings ([#3810](https://github.com/EQEmu/Server/pull/3810)) @Akkadius 2023-12-28
* Reclassify unhelpful Info message ([#3809](https://github.com/EQEmu/Server/pull/3809)) @Akkadius 2023-12-28
### MySQL
* Fix MySQL Query error formatting ([#3808](https://github.com/EQEmu/Server/pull/3808)) @Akkadius 2023-12-28
### Objects
* Remove "No objects to load for zone" error message ([#3807](https://github.com/EQEmu/Server/pull/3807)) @Akkadius 2023-12-28
### Player Events
* Bulk replace settings on boot ([#3806](https://github.com/EQEmu/Server/pull/3806)) @Akkadius 2023-12-28
### Tasks
* Add enabled column ([#3804](https://github.com/EQEmu/Server/pull/3804)) @Akkadius 2023-12-28
## [22.38.0] - 12/26/2023
### Bots
* Remove unnecessary error on SetItemReuse ([#3795](https://github.com/EQEmu/Server/pull/3795)) @nytmyr 2023-12-20
### Code
* Consolidate GetHateRandom(), GetHateRandomBot(), GetHateRandomClient(), and GetHateRandomNPC() ([#3794](https://github.com/EQEmu/Server/pull/3794)) @Kinglykrab 2023-12-25
* Race constants refactor ([#3782](https://github.com/EQEmu/Server/pull/3782)) @Akkadius 2023-12-23
### Database
* Fix issue with saylinks query in MySQL 8.0+ ([#3800](https://github.com/EQEmu/Server/pull/3800)) @Akkadius 2023-12-24
* Update faction mods with Live data ([#3799](https://github.com/EQEmu/Server/pull/3799)) @joligario 2023-12-23
### Fixes
* Disable Hide/Improved Hide on Trap damage ([#3791](https://github.com/EQEmu/Server/pull/3791)) @Kinglykrab 2023-12-19
* Fix Bard Invisibility Songs breaking every 4 ticks ([#3783](https://github.com/EQEmu/Server/pull/3783)) @Kinglykrab 2023-12-19
* Fix can_riposte parameter in DoMeleeSkillAttackDmg ([#3792](https://github.com/EQEmu/Server/pull/3792)) @Kinglykrab 2023-12-19
### Forage
* Add a rule to disabled using common_food_ids from the list in forage.cpp. currently set to enabled. ([#3796](https://github.com/EQEmu/Server/pull/3796)) @regneq 2023-12-22
### NPC
* Support for multiple emotes per type, emote variables ([#3801](https://github.com/EQEmu/Server/pull/3801)) @regneq 2023-12-25
### Quest API
* Add GetHateTopBot(), GetHateTopClient(), and GetHateTopNPC() to Perl/Lua ([#3793](https://github.com/EQEmu/Server/pull/3793)) @Kinglykrab 2023-12-22
* Add SummonItemIntoInventory() to Perl/Lua ([#3797](https://github.com/EQEmu/Server/pull/3797)) @Kinglykrab 2023-12-22
### Repositories
* Add ReplaceOne and ReplaceMany ([#3802](https://github.com/EQEmu/Server/pull/3802)) @Akkadius 2023-12-26
## [22.37.0] - 12/18/2023
### Bots
-2
View File
@@ -13,7 +13,6 @@ SET(common_sources
crc32.cpp
database/database_dump_service.cpp
database.cpp
database_conversions.cpp
database_instances.cpp
database/database_update_manifest.cpp
database/database_update_manifest_bots.cpp
@@ -541,7 +540,6 @@ SET(common_headers
events/player_event_logs.h
events/player_event_discord_formatter.h
events/player_events.h
errmsg.h
event_sub.h
expedition_lockout_timer.h
extprofile.h
+9 -1
View File
@@ -2246,6 +2246,11 @@ bool Database::CopyCharacter(
row = results.begin();
std::string new_character_id = row[0];
std::vector<std::string> tables_to_zero_id = {
"keyring",
"data_buckets",
};
TransactionBegin();
for (const auto &iter : DatabaseSchema::GetCharacterTables()) {
std::string table_name = iter.first;
@@ -2279,6 +2284,10 @@ bool Database::CopyCharacter(
std::string column = columns[column_index];
std::string value = row[column_index] ? row[column_index] : "null";
if (column == "id" && Strings::Contains(tables_to_zero_id, table_name)) {
value = "0";
}
if (column == character_id_column_name) {
value = new_character_id;
}
@@ -2326,7 +2335,6 @@ bool Database::CopyCharacter(
if (!insert.ErrorMessage().empty()) {
TransactionRollback();
return false;
break;
}
}
}
-5
View File
@@ -226,11 +226,6 @@ public:
void PurgeAllDeletedDataBuckets();
/* Database Conversions 'database_conversions.cpp' */
bool CheckDatabaseConversions();
bool CheckDatabaseConvertCorpseDeblob();
bool CheckDatabaseConvertPPDeblob();
/* Database Variables */
+49 -25
View File
@@ -76,9 +76,9 @@ void DatabaseUpdate::CheckDbUpdates()
}
}
std::string DatabaseUpdate::GetQueryResult(std::string query)
std::string DatabaseUpdate::GetQueryResult(const ManifestEntry& e)
{
auto results = m_database->QueryDatabase(query);
auto results = (e.content_schema_update ? m_content_database : m_database)->QueryDatabase(e.check);
std::vector<std::string> result_lines = {};
@@ -121,6 +121,16 @@ bool DatabaseUpdate::ShouldRunMigration(ManifestEntry &e, std::string query_resu
return false;
}
// check if we are running in a terminal
bool is_atty()
{
#ifdef _WINDOWS
return ::_isatty(_fileno(stdin));
#else
return isatty(fileno(stdin));
#endif
}
// return true if we ran updates
bool DatabaseUpdate::UpdateManifest(
std::vector<ManifestEntry> entries,
@@ -136,7 +146,7 @@ bool DatabaseUpdate::UpdateManifest(
for (auto &e: entries) {
if (e.version == version) {
bool has_migration = true;
std::string r = GetQueryResult(e.check);
std::string r = GetQueryResult(e);
if (ShouldRunMigration(e, r)) {
has_migration = false;
missing_migrations.emplace_back(e.version);
@@ -179,7 +189,7 @@ bool DatabaseUpdate::UpdateManifest(
if (e.version == m) {
bool errored_migration = false;
auto r = m_database->QueryDatabaseMulti(e.sql);
auto r = (e.content_schema_update ? m_content_database : m_database)->QueryDatabaseMulti(e.sql);
// ignore empty query result "errors"
if (r.ErrorNumber() != 1065 && !r.ErrorMessage().empty()) {
@@ -187,31 +197,38 @@ bool DatabaseUpdate::UpdateManifest(
errored_migration = true;
LogInfo("Required database update failed. This could be a problem");
LogInfo("Would you like to skip this update? [y/n] (Timeout 60s)");
// user input
std::string input;
bool gave_input = false;
time_t start_time = time(nullptr);
time_t wait_time_seconds = 60;
// if terminal attached then prompt for skip
if (is_atty()) {
LogInfo("Would you like to skip this update? [y/n] (Timeout 60s)");
// spawn a concurrent thread that waits for input from std::cin
std::thread t1(
[&]() {
std::cin >> input;
gave_input = true;
// user input
std::string input;
bool gave_input = false;
time_t start_time = time(nullptr);
time_t wait_time_seconds = 60;
// spawn a concurrent thread that waits for input from std::cin
std::thread t1(
[&]() {
std::cin >> input;
gave_input = true;
}
);
t1.detach();
// check the inputReceived flag once every 50ms for 10 seconds
while (time(nullptr) < start_time + wait_time_seconds && !gave_input) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
);
t1.detach();
// check the inputReceived flag once every 50ms for 10 seconds
while (time(nullptr) < start_time + wait_time_seconds && !gave_input) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
// prompt for user skip
if (Strings::Trim(input) == "y") {
errored_migration = false;
// prompt for user skip
if (Strings::Trim(input) == "y") {
errored_migration = false;
LogInfo("Skipping update [{}] [{}]", e.version, e.description);
}
} else {
errored_migration = true;
LogInfo("Skipping update [{}] [{}]", e.version, e.description);
}
}
@@ -247,6 +264,13 @@ DatabaseUpdate *DatabaseUpdate::SetDatabase(Database *db)
return this;
}
DatabaseUpdate *DatabaseUpdate::SetContentDatabase(Database *db)
{
m_content_database = db;
return this;
}
bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
{
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
+4 -1
View File
@@ -10,6 +10,7 @@ struct ManifestEntry {
std::string condition{}; // condition or "match_type" - Possible values [contains|match|missing|empty|not_empty]
std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
std::string sql{}; // the SQL DDL that gets ran when the condition is true
bool content_schema_update{}; // if true, this migration is a content schema update and should be ran against the content database
};
struct DatabaseVersion {
@@ -22,14 +23,16 @@ public:
DatabaseVersion GetDatabaseVersions();
DatabaseVersion GetBinaryDatabaseVersions();
void CheckDbUpdates();
std::string GetQueryResult(std::string query);
std::string GetQueryResult(const ManifestEntry& e);
static bool ShouldRunMigration(ManifestEntry &e, std::string query_result);
bool UpdateManifest(std::vector<ManifestEntry> entries, int version_low, int version_high);
DatabaseUpdate *SetDatabase(Database *db);
DatabaseUpdate *SetContentDatabase(Database *db);
bool HasPendingUpdates();
private:
Database *m_database;
Database *m_content_database;
static bool CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b);
void InjectBotsVersionColumn();
};
+34 -6
View File
@@ -5016,7 +5016,7 @@ CREATE TABLE `spawn2_disabled` (
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
INSERT INTO spawn2_disabled (spawn2_id, disabled) SELECT id, 1 FROM spawn2 WHERE enabled = 0;
ALTER TABLE `spawn2` DROP COLUMN `enabled`;
)"
)",
},
ManifestEntry{
.version = 9242,
@@ -5028,7 +5028,8 @@ ALTER TABLE `spawn2` DROP COLUMN `enabled`;
ALTER TABLE `spawnentry`
ADD COLUMN `min_time` smallint(4) NOT NULL DEFAULT 0 AFTER `condition_value_filter`,
ADD COLUMN `max_time` smallint(4) NOT NULL DEFAULT 0 AFTER `min_time`;
)"
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9243,
@@ -5082,7 +5083,8 @@ INSERT INTO
DROP TABLE `starting_items`;
RENAME TABLE `starting_items_new` TO `starting_items`;
)"
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9244,
@@ -5092,7 +5094,8 @@ RENAME TABLE `starting_items_new` TO `starting_items`;
.match = "0000-00-00 00:00:00",
.sql = R"(
ALTER TABLE `items` MODIFY COLUMN `updated` datetime NULL DEFAULT NULL;
)"
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9245,
@@ -5104,7 +5107,8 @@ ALTER TABLE `items` MODIFY COLUMN `updated` datetime NULL DEFAULT NULL;
ALTER TABLE `object` CHANGE COLUMN `unknown08` `size_percentage` float NOT NULL DEFAULT 0 AFTER `icon`;
ALTER TABLE `object` CHANGE COLUMN `unknown10` `solid_type` mediumint(5) NOT NULL DEFAULT 0 AFTER `size`;
ALTER TABLE `object` CHANGE COLUMN `unknown20` `incline` int(11) NOT NULL DEFAULT 0 AFTER `solid_type`;
)"
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9246,
@@ -5133,7 +5137,31 @@ CHANGE COLUMN `slot` `inventory_slot` mediumint(9) NOT NULL DEFAULT -1 AFTER `st
ALTER TABLE `starting_items`
CHANGE COLUMN `temporary` `class_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `id`;
)"
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9248,
.description = "2023_12_22_drop_npc_emotes_index.sql",
.check = "show index from npc_emotes where key_name = 'emoteid'",
.condition = "not_empty",
.match = "",
.sql = R"(
ALTER TABLE `npc_emotes` DROP INDEX `emoteid`;
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9249,
.description = "2023_12_26_add_tasks_enabled_column.sql",
.check = "SHOW COLUMNS FROM `tasks` LIKE 'enabled'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `tasks`
ADD COLUMN `enabled` smallint NULL DEFAULT 1 AFTER `faction_amount`
)",
.content_schema_update = true
}
// -- template; copy/paste this when you need to create a new entry
-39
View File
@@ -1,39 +0,0 @@
#include "../common/global_define.h"
#include "../common/rulesys.h"
#include "../common/strings.h"
#include "database.h"
#include "database/database_update.h"
// Disgrace: for windows compile
#ifdef _WINDOWS
#include <windows.h>
#define snprintf _snprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#else
#include "unix.h"
#include <netinet/in.h>
#include <sys/time.h>
#endif
#pragma pack(1)
DatabaseUpdate database_update;
bool Database::CheckDatabaseConversions()
{
auto *r = RuleManager::Instance();
r->LoadRules(this, "default", false);
if (!RuleB(Bots, Enabled) && DoesTableExist("bot_data")) {
LogInfo("Bot tables found but rule not enabled, enabling");
r->SetRule("Bots:Enabled", "true", this, true, true);
}
database_update.SetDatabase(this)->CheckDbUpdates();
return true;
}
+1 -1
View File
@@ -71,7 +71,7 @@ namespace DatabaseSchema {
{"character_tasks", "charid"},
{"character_tribute", "character_id"},
{"completed_tasks", "charid"},
{"data_buckets", "id"},
{"data_buckets", "character_id"},
{"faction_values", "char_id"},
{"friends", "charid"},
{"guild_members", "char_id"},
+1 -2
View File
@@ -8,7 +8,6 @@
#include "dbcore.h"
#include <errmsg.h>
#include <fstream>
#include <iostream>
#include <mysqld_error.h>
@@ -138,7 +137,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
* Error logging
*/
if (mysql_errno(mysql) > 0 && query[0] != '\0') {
LogMySQLError("[{}] [{}]\n[{}]", mysql_errno(mysql), mysql_error(mysql), query);
LogMySQLError("MySQL Error ({}) [{}] Query [{}]", mysql_errno(mysql), mysql_error(mysql), query);
}
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(mysql), errorBuffer);
+3
View File
@@ -14,6 +14,9 @@
#include <string.h>
#include <mutex>
#define CR_SERVER_GONE_ERROR 2006
#define CR_SERVER_LOST 2013
class DBcore {
public:
enum eStatus {
+11 -7
View File
@@ -651,6 +651,9 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
}
// Auto inject categories that don't exist in the database...
std::vector<LogsysCategoriesRepository::LogsysCategories> db_categories_to_add{};
for (int i = Logs::AA; i != Logs::MaxCategoryID; i++) {
bool is_missing_in_database = std::find(db_categories.begin(), db_categories.end(), i) == db_categories.end();
@@ -665,11 +668,7 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
}
if (is_missing_in_database && !is_deprecated_category) {
LogInfo(
"Automatically adding new log category [{}] ({})",
Logs::LogCategoryName[i],
i
);
LogInfo("Automatically adding new log category [{}] ({})", Logs::LogCategoryName[i], i);
auto new_category = LogsysCategoriesRepository::NewEntity();
new_category.log_category_id = i;
@@ -678,11 +677,16 @@ EQEmuLogSys *EQEmuLogSys::LoadLogDatabaseSettings()
new_category.log_to_gmsay = log_settings[i].log_to_gmsay;
new_category.log_to_file = log_settings[i].log_to_file;
new_category.log_to_discord = log_settings[i].log_to_discord;
LogsysCategoriesRepository::InsertOne(*m_database, new_category);
db_categories_to_add.emplace_back(new_category);
}
}
if (!db_categories_to_add.empty()) {
LogsysCategoriesRepository::ReplaceMany(*m_database, db_categories_to_add);
LoadLogDatabaseSettings();
return this;
}
LogInfo("Loaded [{}] log categories", categories.size());
auto webhooks = DiscordWebhooksRepository::GetWhere(*m_database, fmt::format("id < {}", MAX_DISCORD_WEBHOOK_ID));
-59
View File
@@ -1,59 +0,0 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA */
/* Error messages for mysql clients */
/* error messages for the demon is in share/language/errmsg.sys */
#ifdef __cplusplus
extern "C" {
#endif
void init_client_errs(void);
extern const char *client_errors[]; /* Error messages */
#ifdef __cplusplus
}
#endif
#define CR_MIN_ERROR 2000 /* For easier client code */
#define CR_MAX_ERROR 2999
#if defined(OS2) && defined( MYSQL_SERVER)
#define CER(X) client_errors[(X)-CR_MIN_ERROR]
#else
#define ER(X) client_errors[(X)-CR_MIN_ERROR]
#endif
#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */
#define CR_UNKNOWN_ERROR 2000
#define CR_SOCKET_CREATE_ERROR 2001
#define CR_CONNECTION_ERROR 2002
#define CR_CONN_HOST_ERROR 2003
#define CR_IPSOCK_ERROR 2004
#define CR_UNKNOWN_HOST 2005
#define CR_SERVER_GONE_ERROR 2006
#define CR_VERSION_ERROR 2007
#define CR_OUT_OF_MEMORY 2008
#define CR_WRONG_HOST_INFO 2009
#define CR_LOCALHOST_CONNECTION 2010
#define CR_TCP_CONNECTION 2011
#define CR_SERVER_HANDSHAKE_ERR 2012
#define CR_SERVER_LOST 2013
#define CR_COMMANDS_OUT_OF_SYNC 2014
#define CR_NAMEDPIPE_CONNECTION 2015
#define CR_NAMEDPIPEWAIT_ERROR 2016
#define CR_NAMEDPIPEOPEN_ERROR 2017
#define CR_NAMEDPIPESETSTATE_ERROR 2018
#define CR_CANT_READ_CHARSET 2019
#define CR_NET_PACKET_TOO_LARGE 2020
+9 -7
View File
@@ -37,6 +37,8 @@ void PlayerEventLogs::Init()
db.emplace_back(e.id);
}
std::vector<PlayerEventLogSettingsRepository::PlayerEventLogSettings> settings_to_insert{};
// insert entries that don't exist in database
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
bool is_in_database = std::find(db.begin(), db.end(), i) != db.end();
@@ -56,21 +58,21 @@ void PlayerEventLogs::Init()
bool is_missing_in_database = std::find(db.begin(), db.end(), i) == db.end();
if (is_missing_in_database && is_implemented && !is_deprecated) {
LogInfo(
"[New] PlayerEvent [{}] ({})",
PlayerEvent::EventName[i],
i
);
LogInfo("[New] PlayerEvent [{}] ({})", PlayerEvent::EventName[i], i);
auto c = PlayerEventLogSettingsRepository::NewEntity();
c.id = i;
c.event_name = PlayerEvent::EventName[i];
c.event_enabled = m_settings[i].event_enabled;
c.retention_days = m_settings[i].retention_days;
PlayerEventLogSettingsRepository::InsertOne(*m_database, c);
settings_to_insert.emplace_back(c);
}
}
if (!settings_to_insert.empty()) {
PlayerEventLogSettingsRepository::ReplaceMany(*m_database, settings_to_insert);
}
bool processing_in_world = !RuleB(Logging, PlayerEventsQSProcess) && IsWorld();
bool processing_in_qs = RuleB(Logging, PlayerEventsQSProcess) && IsQueryServ();
@@ -611,7 +613,7 @@ void PlayerEventLogs::Process()
void PlayerEventLogs::ProcessRetentionTruncation()
{
LogInfo("Running truncation");
LogPlayerEvents("Running truncation");
for (int i = PlayerEvent::GM_COMMAND; i != PlayerEvent::MAX; i++) {
if (m_settings[i].retention_days > 0) {
+2 -2
View File
@@ -96,12 +96,12 @@ bool IsOfEqualRace(int r1, int r2)
// TODO: add more values
switch (r1) {
case DARK_ELF:
if (r2 == RACE_NERIAK_CITIZEN_77) {
if (r2 == Race::NeriakCitizen) {
return true;
}
break;
case BARBARIAN:
if (r2 == RACE_HALAS_CITIZEN_90) {
if (r2 == Race::HalasCitizen) {
return true;
}
}
+19 -18
View File
@@ -801,34 +801,35 @@ int16 EQ::InventoryProfile::HasItemByLoreGroup(uint32 loregroup, uint8 where)
// Returns slot_id when there's one available, else SLOT_INVALID
int16 EQ::InventoryProfile::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow)
{
// Check basic inventory
for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) {
if ((((uint64)1 << i) & m_lookup->PossessionsBitmask) == 0)
continue;
const int16 last_bag_slot = RuleI(World, ExpansionSettings) & EQ::expansions::bitHoT ? EQ::invslot::slotGeneral10 : EQ::invslot::slotGeneral8;
if (!GetItem(i))
// Found available slot in personal inventory
return i;
for (int16 i = invslot::GENERAL_BEGIN; i <= last_bag_slot; i++) { // Check basic inventory
if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) {
continue;
}
if (!GetItem(i)) {
return i; // Found available slot in personal inventory
}
}
if (!for_bag) {
for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) {
if ((((uint64)1 << i) & m_lookup->PossessionsBitmask) == 0)
for (int16 i = invslot::GENERAL_BEGIN; i <= last_bag_slot; i++) {
if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) {
continue;
}
const ItemInstance* inst = GetItem(i);
if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size)
{
if (inst->GetItem()->BagType == item::BagTypeQuiver && inst->GetItem()->ItemType != item::ItemTypeArrow)
{
const auto *inst = GetItem(i);
if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size) {
if (inst->GetItem()->BagType == item::BagTypeQuiver &&
inst->GetItem()->ItemType != item::ItemTypeArrow) {
continue;
}
int16 base_slot_id = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN);
const int16 base_slot_id = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN);
uint8 slots = inst->GetItem()->BagSlots;
uint8 j;
for (j = invbag::SLOT_BEGIN; j<slots; j++) {
const uint8 slots = inst->GetItem()->BagSlots;
for (uint8 j = invbag::SLOT_BEGIN; j < slots; j++) {
if (!GetItem(base_slot_id + j)) {
// Found available slot within bag
return (base_slot_id + j);
+1 -1
View File
@@ -132,7 +132,7 @@ namespace EQ
// Swap items in inventory
enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel };
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = RACE_DOUG_0, uint8 class_id = Class::None, uint16 deity_id = deity::DeityType::DeityUnknown, uint8 level = 0);
bool SwapItem(int16 source_slot, int16 destination_slot, SwapItemFailState& fail_state, uint16 race_id = Race::Doug, uint8 class_id = Class::None, uint16 deity_id = deity::DeityType::DeityUnknown, uint8 level = 0);
// Remove item from inventory
bool DeleteItem(int16 slot_id, int16 quantity = 0);
+1 -1
View File
@@ -1273,7 +1273,7 @@ int EQ::ItemInstance::GetItemBaneDamageBody(bool augments) const
int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
{
int race = RACE_DOUG_0;
int race = Race::Doug;
const auto item = GetItem();
if (item) {
race = item->BaneDmgRace;
+4 -4
View File
@@ -3868,8 +3868,8 @@ namespace RoF
}
float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
if (!((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin))
)
{
PacketSize += 60;
@@ -4002,8 +4002,8 @@ namespace RoF
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)
)
{
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
+4 -4
View File
@@ -4007,8 +4007,8 @@ namespace RoF2
}
float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
if (!((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin))
)
{
PacketSize += 60;
@@ -4212,8 +4212,8 @@ namespace RoF2
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // These do something with OP_WeaponEquip1
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)
)
{
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
+6 -6
View File
@@ -2507,8 +2507,8 @@ namespace SoD
}
float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
if (!((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin))
)
{
PacketSize -= (sizeof(structs::Texture_Struct) * EQ::textures::materialCount);
@@ -2706,8 +2706,8 @@ namespace SoD
Buffer += sizeof(structs::Spawn_Struct_Position);
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)
)
{
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
@@ -2733,8 +2733,8 @@ namespace SoD
}
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)
)
{
structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer;
+6 -6
View File
@@ -2779,8 +2779,8 @@ namespace UF
}
float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
if (!((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin))
)
{
PacketSize -= (sizeof(structs::Texture_Struct) * EQ::textures::materialCount);
@@ -2982,8 +2982,8 @@ namespace UF
Buffer += sizeof(structs::Spawn_Struct_Position);
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)
)
{
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
@@ -3018,8 +3018,8 @@ namespace UF
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
}
if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)
)
{
structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer;
+791 -791
View File
File diff suppressed because it is too large Load Diff
+744 -1474
View File
File diff suppressed because it is too large Load Diff
@@ -6,7 +6,7 @@
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_LOGSYS_CATEGORIES_REPOSITORY_H
@@ -16,6 +16,7 @@
#include "../../strings.h"
#include <ctime>
class BaseLogsysCategoriesRepository {
public:
struct LogsysCategories {
@@ -128,8 +129,9 @@ public:
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
logsys_categories_id
)
);
@@ -378,6 +380,74 @@ public:
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const LogsysCategories &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.log_category_id));
v.push_back("'" + Strings::Escape(e.log_category_description) + "'");
v.push_back(std::to_string(e.log_to_console));
v.push_back(std::to_string(e.log_to_file));
v.push_back(std::to_string(e.log_to_gmsay));
v.push_back(std::to_string(e.log_to_discord));
v.push_back(std::to_string(e.discord_webhook_id));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<LogsysCategories> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.log_category_id));
v.push_back("'" + Strings::Escape(e.log_category_description) + "'");
v.push_back(std::to_string(e.log_to_console));
v.push_back(std::to_string(e.log_to_file));
v.push_back(std::to_string(e.log_to_gmsay));
v.push_back(std::to_string(e.log_to_discord));
v.push_back(std::to_string(e.discord_webhook_id));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_LOGSYS_CATEGORIES_REPOSITORY_H
@@ -16,6 +16,7 @@
#include "../../strings.h"
#include <ctime>
class BaseNpcEmotesRepository {
public:
struct NpcEmotes {
@@ -120,8 +121,9 @@ public:
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
npc_emotes_id
)
);
@@ -6,7 +6,7 @@
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H
@@ -16,6 +16,7 @@
#include "../../strings.h"
#include <ctime>
class BasePlayerEventLogSettingsRepository {
public:
struct PlayerEventLogSettings {
@@ -359,6 +360,70 @@ public:
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const PlayerEventLogSettings &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.event_name) + "'");
v.push_back(std::to_string(e.event_enabled));
v.push_back(std::to_string(e.retention_days));
v.push_back(std::to_string(e.discord_webhook_id));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<PlayerEventLogSettings> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back("'" + Strings::Escape(e.event_name) + "'");
v.push_back(std::to_string(e.event_enabled));
v.push_back(std::to_string(e.retention_days));
v.push_back(std::to_string(e.discord_webhook_id));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_PLAYER_EVENT_LOG_SETTINGS_REPOSITORY_H
@@ -6,7 +6,7 @@
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_PLAYER_EVENT_LOGS_REPOSITORY_H
@@ -240,8 +240,8 @@ public:
v.push_back(columns[7] + " = " + std::to_string(e.z));
v.push_back(columns[8] + " = " + std::to_string(e.heading));
v.push_back(columns[9] + " = " + std::to_string(e.event_type_id));
v.push_back(columns[10] + " = '" + db.Escape(e.event_type_name) + "'");
v.push_back(columns[11] + " = '" + db.Escape(e.event_data) + "'");
v.push_back(columns[10] + " = '" + Strings::Escape(e.event_type_name) + "'");
v.push_back(columns[11] + " = '" + Strings::Escape(e.event_data) + "'");
v.push_back(columns[12] + " = FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
auto results = db.QueryDatabase(
@@ -274,8 +274,8 @@ public:
v.push_back(std::to_string(e.z));
v.push_back(std::to_string(e.heading));
v.push_back(std::to_string(e.event_type_id));
v.push_back("'" + db.Escape(e.event_type_name) + "'");
v.push_back("'" + db.Escape(e.event_data) + "'");
v.push_back("'" + Strings::Escape(e.event_type_name) + "'");
v.push_back("'" + Strings::Escape(e.event_data) + "'");
v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
auto results = db.QueryDatabase(
@@ -316,8 +316,8 @@ public:
v.push_back(std::to_string(e.z));
v.push_back(std::to_string(e.heading));
v.push_back(std::to_string(e.event_type_id));
v.push_back("'" + db.Escape(e.event_type_name) + "'");
v.push_back("'" + db.Escape(e.event_data) + "'");
v.push_back("'" + Strings::Escape(e.event_type_name) + "'");
v.push_back("'" + Strings::Escape(e.event_data) + "'");
v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
@@ -460,6 +460,86 @@ public:
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const PlayerEventLogs &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.account_id));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.instance_id));
v.push_back(std::to_string(e.x));
v.push_back(std::to_string(e.y));
v.push_back(std::to_string(e.z));
v.push_back(std::to_string(e.heading));
v.push_back(std::to_string(e.event_type_id));
v.push_back("'" + Strings::Escape(e.event_type_name) + "'");
v.push_back("'" + Strings::Escape(e.event_data) + "'");
v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<PlayerEventLogs> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.account_id));
v.push_back(std::to_string(e.character_id));
v.push_back(std::to_string(e.zone_id));
v.push_back(std::to_string(e.instance_id));
v.push_back(std::to_string(e.x));
v.push_back(std::to_string(e.y));
v.push_back(std::to_string(e.z));
v.push_back(std::to_string(e.heading));
v.push_back(std::to_string(e.event_type_id));
v.push_back("'" + Strings::Escape(e.event_type_name) + "'");
v.push_back("'" + Strings::Escape(e.event_data) + "'");
v.push_back("FROM_UNIXTIME(" + (e.created_at > 0 ? std::to_string(e.created_at) : "null") + ")");
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_PLAYER_EVENT_LOGS_REPOSITORY_H
@@ -6,7 +6,7 @@
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_TASKS_REPOSITORY_H
@@ -16,6 +16,7 @@
#include "../../strings.h"
#include <ctime>
class BaseTasksRepository {
public:
struct Tasks {
@@ -47,6 +48,7 @@ public:
uint32_t dz_template_id;
int32_t lock_activity_id;
int32_t faction_amount;
int16_t enabled;
};
static std::string PrimaryKey()
@@ -85,6 +87,7 @@ public:
"dz_template_id",
"lock_activity_id",
"faction_amount",
"enabled",
};
}
@@ -119,6 +122,7 @@ public:
"dz_template_id",
"lock_activity_id",
"faction_amount",
"enabled",
};
}
@@ -187,6 +191,7 @@ public:
e.dz_template_id = 0;
e.lock_activity_id = -1;
e.faction_amount = 0;
e.enabled = 1;
return e;
}
@@ -212,8 +217,9 @@ public:
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
tasks_id
)
);
@@ -250,6 +256,7 @@ public:
e.dz_template_id = static_cast<uint32_t>(strtoul(row[25], nullptr, 10));
e.lock_activity_id = static_cast<int32_t>(atoi(row[26]));
e.faction_amount = static_cast<int32_t>(atoi(row[27]));
e.enabled = static_cast<int16_t>(atoi(row[28]));
return e;
}
@@ -311,6 +318,7 @@ public:
v.push_back(columns[25] + " = " + std::to_string(e.dz_template_id));
v.push_back(columns[26] + " = " + std::to_string(e.lock_activity_id));
v.push_back(columns[27] + " = " + std::to_string(e.faction_amount));
v.push_back(columns[28] + " = " + std::to_string(e.enabled));
auto results = db.QueryDatabase(
fmt::format(
@@ -360,6 +368,7 @@ public:
v.push_back(std::to_string(e.dz_template_id));
v.push_back(std::to_string(e.lock_activity_id));
v.push_back(std::to_string(e.faction_amount));
v.push_back(std::to_string(e.enabled));
auto results = db.QueryDatabase(
fmt::format(
@@ -417,6 +426,7 @@ public:
v.push_back(std::to_string(e.dz_template_id));
v.push_back(std::to_string(e.lock_activity_id));
v.push_back(std::to_string(e.faction_amount));
v.push_back(std::to_string(e.enabled));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
@@ -478,6 +488,7 @@ public:
e.dz_template_id = static_cast<uint32_t>(strtoul(row[25], nullptr, 10));
e.lock_activity_id = static_cast<int32_t>(atoi(row[26]));
e.faction_amount = static_cast<int32_t>(atoi(row[27]));
e.enabled = static_cast<int16_t>(atoi(row[28]));
all_entries.push_back(e);
}
@@ -530,6 +541,7 @@ public:
e.dz_template_id = static_cast<uint32_t>(strtoul(row[25], nullptr, 10));
e.lock_activity_id = static_cast<int32_t>(atoi(row[26]));
e.faction_amount = static_cast<int32_t>(atoi(row[27]));
e.enabled = static_cast<int16_t>(atoi(row[28]));
all_entries.push_back(e);
}
@@ -588,6 +600,118 @@ public:
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const Tasks &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.duration));
v.push_back(std::to_string(e.duration_code));
v.push_back("'" + Strings::Escape(e.title) + "'");
v.push_back("'" + Strings::Escape(e.description) + "'");
v.push_back("'" + Strings::Escape(e.reward_text) + "'");
v.push_back("'" + Strings::Escape(e.reward_id_list) + "'");
v.push_back(std::to_string(e.cash_reward));
v.push_back(std::to_string(e.exp_reward));
v.push_back(std::to_string(e.reward_method));
v.push_back(std::to_string(e.reward_points));
v.push_back(std::to_string(e.reward_point_type));
v.push_back(std::to_string(e.min_level));
v.push_back(std::to_string(e.max_level));
v.push_back(std::to_string(e.level_spread));
v.push_back(std::to_string(e.min_players));
v.push_back(std::to_string(e.max_players));
v.push_back(std::to_string(e.repeatable));
v.push_back(std::to_string(e.faction_reward));
v.push_back("'" + Strings::Escape(e.completion_emote) + "'");
v.push_back(std::to_string(e.replay_timer_group));
v.push_back(std::to_string(e.replay_timer_seconds));
v.push_back(std::to_string(e.request_timer_group));
v.push_back(std::to_string(e.request_timer_seconds));
v.push_back(std::to_string(e.dz_template_id));
v.push_back(std::to_string(e.lock_activity_id));
v.push_back(std::to_string(e.faction_amount));
v.push_back(std::to_string(e.enabled));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<Tasks> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.id));
v.push_back(std::to_string(e.type));
v.push_back(std::to_string(e.duration));
v.push_back(std::to_string(e.duration_code));
v.push_back("'" + Strings::Escape(e.title) + "'");
v.push_back("'" + Strings::Escape(e.description) + "'");
v.push_back("'" + Strings::Escape(e.reward_text) + "'");
v.push_back("'" + Strings::Escape(e.reward_id_list) + "'");
v.push_back(std::to_string(e.cash_reward));
v.push_back(std::to_string(e.exp_reward));
v.push_back(std::to_string(e.reward_method));
v.push_back(std::to_string(e.reward_points));
v.push_back(std::to_string(e.reward_point_type));
v.push_back(std::to_string(e.min_level));
v.push_back(std::to_string(e.max_level));
v.push_back(std::to_string(e.level_spread));
v.push_back(std::to_string(e.min_players));
v.push_back(std::to_string(e.max_players));
v.push_back(std::to_string(e.repeatable));
v.push_back(std::to_string(e.faction_reward));
v.push_back("'" + Strings::Escape(e.completion_emote) + "'");
v.push_back(std::to_string(e.replay_timer_group));
v.push_back(std::to_string(e.replay_timer_seconds));
v.push_back(std::to_string(e.request_timer_group));
v.push_back(std::to_string(e.request_timer_seconds));
v.push_back(std::to_string(e.dz_template_id));
v.push_back(std::to_string(e.lock_activity_id));
v.push_back(std::to_string(e.faction_amount));
v.push_back(std::to_string(e.enabled));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_TASKS_REPOSITORY_H
@@ -6,7 +6,7 @@
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_{{TABLE_NAME_UPPER}}_REPOSITORY_H
@@ -319,6 +319,62 @@ public:
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const {{TABLE_NAME_STRUCT}} &e
)
{
std::vector<std::string> v;
{{INSERT_ONE_ENTRIES}}
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<{{TABLE_NAME_STRUCT}}> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
{{INSERT_MANY_ENTRIES}}
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_{{TABLE_NAME_UPPER}}_REPOSITORY_H
+1
View File
@@ -215,6 +215,7 @@ RULE_BOOL(Character, EnableRaidEXPModifier, true, "Enable or disable the raid ex
RULE_BOOL(Character, EnableRaidMemberEXPModifier, true, "Enable or disable the raid experience modifier based on members in raid, default is true")
RULE_BOOL(Character, LeaveCursorMoneyOnCorpse, false, "Enable or disable leaving cursor money on player corpses")
RULE_BOOL(Character, ItemExtraSkillDamageCalcAsPercent, false, "If enabled, apply Item Extra Skill Damage as Percentage-based modifiers")
RULE_BOOL(Character, UseForageCommonFood, true, "If enabled, use the common foods specified in the code.")
RULE_CATEGORY_END()
RULE_CATEGORY(Mercs)
+1 -1
View File
@@ -376,7 +376,7 @@ std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message)
void EQ::SayLinkEngine::LoadCachedSaylinks()
{
auto saylinks = SaylinkRepository::GetWhere(database, "phrase not REGEXP BINARY '[A-Z]' and phrase not REGEXP '[0-9]'");
auto saylinks = SaylinkRepository::GetWhere(database, "phrase not REGEXP '[A-Z]' and phrase not REGEXP '[0-9]'");
LogSaylink("Loaded [{}] saylinks into cache", saylinks.size());
g_cached_saylinks = saylinks;
}
+2 -2
View File
@@ -25,7 +25,7 @@
// Build variables
// these get injected during the build pipeline
#define CURRENT_VERSION "22.37.0-dev" // always append -dev to the current version for custom-builds
#define CURRENT_VERSION "22.39.1-dev" // always append -dev to the current version for custom-builds
#define LOGIN_VERSION "0.8.0"
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
@@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9247
#define CURRENT_BINARY_DATABASE_VERSION 9249
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9041
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "22.37.0",
"version": "22.39.1",
"repository": {
"type": "git",
"url": "https://github.com/EQEmu/Server.git"
-1
View File
@@ -24,7 +24,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errmsg.h>
#include <mysqld_error.h>
#include <limits.h>
#include <ctype.h>
+1 -2
View File
@@ -24,7 +24,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errmsg.h>
#include <mysqld_error.h>
#include <limits.h>
#include <ctype.h>
@@ -160,7 +159,7 @@ bool UCSDatabase::VerifyMailKey(const std::string& characterName, int IPAddress,
LogInfo("No mailkeys found for [{}].", characterName.c_str());
return false;
}
auto row = results.begin();
// The key is the client's IP address (expressed as 8 hex digits) and an 8 hex digit random string generated
+8
View File
@@ -0,0 +1,8 @@
module constantconvert
go 1.18
require (
github.com/gammazero/deque v0.2.0 // indirect
github.com/gammazero/workerpool v1.1.3 // indirect
)
+4
View File
@@ -0,0 +1,4 @@
github.com/gammazero/deque v0.2.0 h1:SkieyNB4bg2/uZZLxvya0Pq6diUlwx7m2TeT7GAIWaA=
github.com/gammazero/deque v0.2.0/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU=
github.com/gammazero/workerpool v1.1.3 h1:WixN4xzukFoN0XSeXF6puqEqFTl2mECI9S6W44HWy9Q=
github.com/gammazero/workerpool v1.1.3/go.mod h1:wPjyBLDbyKnUn2XwwyD3EEwo9dHutia9/fwNmSHWACc=
+313
View File
@@ -0,0 +1,313 @@
package main
import (
"fmt"
"github.com/gammazero/workerpool"
"io/fs"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
)
func main() {
loadDefinitions()
// get processor count
wp := workerpool.New(runtime.NumCPU())
// loop through all files in current dir that are cpp files or h files
err := filepath.WalkDir("../../", func(path string, d fs.DirEntry, err error) error {
if d.IsDir() {
return nil
}
if !strings.Contains(path, ".cpp") && !strings.Contains(path, ".h") {
return nil
}
// if file ends with ".o" skip it
if strings.HasSuffix(path, ".o") {
return nil
}
var ignoreFiles = []string{
"submodules", "/libs", "utils/", "races.h", "backward", "database_update_manifest.cpp", "zonedb.h",
}
ignore := false
for _, ignoreString := range ignoreFiles {
if strings.Contains(path, ignoreString) {
ignore = true
break
}
}
if ignore {
return nil
}
wp.Submit(func() {
// open file for reading
// get file contents
contents, err := os.ReadFile(path)
if err != nil {
log.Fatalf("impossible to read file: %s", err)
}
content := string(contents)
wroteChanges := false
var newLines []string
for _, line := range strings.Split(content, "\n") {
newLine := line
// loop through oldDefs and see if any of them are in contents
for key, value := range oldDefs {
// combine all of the above contains into a slice
// loop through slice and if any of them are in line, continue
var ignoreMatches = []string{
"#define ", "MALE", "FEMALE", "_BIT", "LANG_",
}
ignore := false
for _, ignoreString := range ignoreMatches {
if strings.Contains(newLine, ignoreString) && !strings.Contains(newLine, "NPC_") {
ignore = true
break
}
}
if ignore {
continue
}
// below we hackishly use a series of specific string contains to avoid
// making blind and wrong replacements
// but hey - at least its 100% accurate :)
if strings.Contains(line, "case "+key+":") {
for key2, value2 := range newDefs {
if value == value2 {
newLine = strings.ReplaceAll(newLine, " "+key+":", " "+key2+":")
wroteChanges = true
break
}
}
}
if strings.Contains(line, "\t"+key) {
for key2, value2 := range newDefs {
if value == value2 {
newLine = strings.ReplaceAll(newLine, "\t"+key, "\t"+key2)
wroteChanges = true
break
}
}
}
if strings.Contains(line, key+",") {
for key2, value2 := range newDefs {
if value == value2 {
newLine = strings.ReplaceAll(newLine, key+",", key2+",")
wroteChanges = true
break
}
}
}
if strings.Contains(line, ", "+key) {
for key2, value2 := range newDefs {
if value == value2 {
newLine = strings.ReplaceAll(newLine, ", "+key, ", "+key2)
wroteChanges = true
break
}
}
}
if strings.Contains(line, "= "+key+" ") {
for key2, value2 := range newDefs {
if value == value2 {
newLine = strings.ReplaceAll(newLine, "= "+key+" ", "= "+key2+" ")
wroteChanges = true
break
}
}
}
if strings.Contains(line, "= "+key+")") {
for key2, value2 := range newDefs {
if value == value2 {
newLine = strings.ReplaceAll(newLine, "= "+key+")", "= "+key2+")")
wroteChanges = true
break
}
}
}
if strings.Contains(line, "= "+key+";") {
for key2, value2 := range newDefs {
if value == value2 {
newLine = strings.ReplaceAll(newLine, "= "+key+";", "= "+key2+";")
wroteChanges = true
break
}
}
}
if strings.Contains(line, "= "+key+" ||") {
for key2, value2 := range newDefs {
if value == value2 {
newLine = strings.ReplaceAll(newLine, "= "+key+" ||", "= "+key2+" ||")
wroteChanges = true
break
}
}
}
// match cases where our match is on the last line and last column
// we need to be exact in the last column and not do a partial because we can
// accidentally rename say OGRE to OGRE2 mistakenly
if strings.Contains(line, key) {
columns := strings.Split(line, " ")
// get the last column
lastColumn := strings.TrimSpace(columns[len(columns)-1])
if lastColumn == key {
for key2, value2 := range newDefs {
if value == value2 {
newLine = strings.ReplaceAll(newLine, lastColumn, key2)
wroteChanges = true
break
}
}
}
}
//if strings.Contains(line, "race == "+key) {
// for key2, value2 := range newDefs {
// if value == value2 {
// newLine = strings.ReplaceAll(newLine, "race == "+key, "race == "+key2)
// wroteChanges = true
// break
// }
// }
//}
}
newLines = append(newLines, newLine)
}
// write contents back to file
if wroteChanges {
fmt.Printf("wrote changes to file [%v]\n", path)
err = os.WriteFile(path, []byte(strings.Join(newLines, "\n")), 0644)
if err != nil {
log.Fatalf("impossible to write file: %s", err)
}
}
return
})
return nil
})
if err != nil {
log.Fatalf("impossible to walk directories: %s", err)
}
wp.StopWait()
}
var newDefs = make(map[string]int)
var oldDefs = make(map[string]int)
func loadDefinitions() {
// git show master:common/races.h
cmd := exec.Command("git", "show", "master:common/races.h")
out, err := cmd.Output()
if err != nil {
println(err.Error())
return
}
// load into a string -> int map
for _, line := range strings.Split(string(out), "\n") {
if strings.Contains(line, "#define ") {
if len(strings.Split(line, " ")) <= 2 {
continue
}
// ignore
// #define MALE 0
// #define FEMALE 1
// #define NEUTER 2
if strings.Contains(line, "#define MALE") {
continue
}
if strings.Contains(line, "#define FEMALE") {
continue
}
if strings.Contains(line, "#define NEUTER") {
continue
}
// load "#define RACE_FLYING_CARPET_720 720" into map
key := strings.Split(line, " ")[1]
value := strings.Split(line, " ")[2]
value = strings.ReplaceAll(value, "//", "")
value = strings.TrimSpace(value)
//fmt.Printf("key [%v] value [%v]\n", key, value)
if !strings.HasPrefix(key, "RACE_") && !strings.HasPrefix(key, "RT_") {
continue
}
// convert value to int
intValue, err := strconv.Atoi(value)
if err != nil {
println(err.Error())
return
}
oldDefs[key] = intValue
fmt.Printf("oldDefs key [%v] value [%v]\n", key, intValue)
}
}
// cleanup/races_cpp_h
cmd = exec.Command("git", "show", "cleanup/races_cpp_h:common/races.h")
out, err = cmd.Output()
if err != nil {
println(err.Error())
return
}
// load into a string -> int map
for _, line := range strings.Split(string(out), "\n") {
if strings.Contains(line, "constexpr uint16") {
if len(strings.Split(line, " ")) <= 2 {
continue
}
// remove all extra spaces in between characters in line
line = strings.Join(strings.Fields(line), " ")
// load " constexpr uint16 Doug = 0;" into map
key := strings.Split(line, " ")[2]
value := strings.Split(line, " ")[4]
value = strings.ReplaceAll(value, "//", "")
value = strings.ReplaceAll(value, ";", "")
value = strings.TrimSpace(value)
// convert value to int
intValue, err := strconv.Atoi(value)
if err != nil {
println(err.Error())
return
}
mapKey := "Race::" + key
newDefs[mapKey] = intValue
fmt.Printf("newDefs key [%v] value [%v]\n", mapKey, value)
}
}
}
+1 -1
View File
@@ -10,7 +10,7 @@ require (
require (
github.com/golang/protobuf v1.3.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/net v0.17.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
)
+2 -2
View File
@@ -10,8 +10,8 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
@@ -513,6 +513,13 @@ foreach my $table_to_generate (@tables) {
#############################################
if ($repository_generation_option eq "all" || $repository_generation_option eq "extended") {
my $generated_repository = './common/repositories/' . $table_to_generate . '_repository.h';
# check if file exists firsts
if (-e $generated_repository) {
print "File [$generated_repository] already exists! Can't overwrite extended once created!\n";
next;
}
my $cmake_generated_reference = $generated_repository;
$cmake_generated_reference =~ s/.\/common\///g;
$generated_repository_files .= $cmake_generated_reference . "\n";
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -9,5 +9,7 @@ void WorldserverCLI::DatabaseUpdates(int argc, char **argv, argh::parser &cmd, s
}
DatabaseUpdate update;
update.SetDatabase(&database)->CheckDbUpdates();
update.SetDatabase(&database)
->SetContentDatabase(&content_db)
->CheckDbUpdates();
}
+1 -1
View File
@@ -460,7 +460,7 @@ void SharedTaskManager::LoadSharedTaskState()
SharedTaskManager *SharedTaskManager::LoadTaskData()
{
m_task_data = TasksRepository::All(*m_content_database);
m_task_data = TasksRepository::GetWhere(*m_content_database, "enabled = 1");
m_task_activity_data = TaskActivitiesRepository::All(*m_content_database);
LogTasks("Loaded tasks [{}] activities [{}]", m_task_data.size(), m_task_activity_data.size());
+13 -1
View File
@@ -26,6 +26,7 @@
#include "../common/ip_util.h"
#include "../common/zone_store.h"
#include "../common/path_manager.h"
#include "../common/database/database_update.h"
extern ZSList zoneserver_list;
extern WorldConfig Config;
@@ -293,7 +294,18 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
const auto c = EQEmuConfig::get();
if (c->auto_database_updates) {
LogInfo("Checking Database Conversions");
database.CheckDatabaseConversions();
auto *r = RuleManager::Instance();
r->LoadRules(&database, "default", false);
if (!RuleB(Bots, Enabled) && database.DoesTableExist("bot_data")) {
LogInfo("Bot tables found but rule not enabled, enabling");
r->SetRule("Bots:Enabled", "true", &database, true, true);
}
DatabaseUpdate update{};
update.SetDatabase(&database)
->SetContentDatabase(&content_db)
->CheckDbUpdates();
}
if (RuleB(Logging, WorldGMSayLogging)) {
-1
View File
@@ -191,7 +191,6 @@ SET(zone_headers
embperl.h
encounter.h
entity.h
errmsg.h
event_codes.h
expedition.h
expedition_database.h
+4 -4
View File
@@ -983,14 +983,14 @@ bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage, ExtraAtt
float size_mod = GetSize();
float other_size_mod = other->GetSize();
if (GetRace() == RACE_LAVA_DRAGON_49 || GetRace() == RACE_WURM_158 || GetRace() == RACE_GHOST_DRAGON_196) { //For races with a fixed size
if (GetRace() == Race::LavaDragon || GetRace() == Race::Wurm || GetRace() == Race::GhostDragon) { //For races with a fixed size
size_mod = 60.0f;
}
else if (size_mod < 6.0) {
size_mod = 8.0f;
}
if (other->GetRace() == RACE_LAVA_DRAGON_49 || other->GetRace() == RACE_WURM_158 || other->GetRace() == RACE_GHOST_DRAGON_196) { //For races with a fixed size
if (other->GetRace() == Race::LavaDragon || other->GetRace() == Race::Wurm || other->GetRace() == Race::GhostDragon) { //For races with a fixed size
other_size_mod = 60.0f;
}
else if (other_size_mod < 6.0) {
@@ -1011,11 +1011,11 @@ bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage, ExtraAtt
size_mod *= size_mod * 4;
}
if (other->GetRace() == RACE_VELIOUS_DRAGON_184) // Lord Vyemm and other velious dragons
if (other->GetRace() == Race::VeliousDragon) // Lord Vyemm and other velious dragons
{
size_mod *= 1.75;
}
if (other->GetRace() == RACE_DRAGON_SKELETON_122) // Dracoliche in Fear. Skeletal Dragon
if (other->GetRace() == Race::DragonSkeleton) // Dracoliche in Fear. Skeletal Dragon
{
size_mod *= 2.25;
}
+72 -67
View File
@@ -1820,7 +1820,7 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill
auto emote_id = killerMob->GetEmoteID();
if (emote_id) {
killerMob->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledPC, emoteid);
killerMob->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledPC, emoteid, this);
}
killerMob->TrySpellOnKill(killed_level, spell);
@@ -2705,68 +2705,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
Corpse* corpse = nullptr;
// Parse quests even if we're killed by an NPC
if (oos) {
if (IsNPC()) {
auto emote_id = GetEmoteID();
if (emote_id) {
DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emoteid);
}
}
if (oos->IsNPC()) {
if (parse->HasQuestSub(oos->GetNPCTypeID(), EVENT_NPC_SLAY)) {
parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0);
}
auto emote_id = oos->GetEmoteID();
if (emote_id) {
oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id);
}
if (killer_mob) {
killer_mob->TrySpellOnKill(killed_level, spell);
}
}
}
if (killer_mob && killer_mob->IsBot()) {
if (parse->BotHasQuestSub(EVENT_NPC_SLAY)) {
parse->EventBot(EVENT_NPC_SLAY, killer_mob->CastToBot(), this, "", 0);
}
killer_mob->TrySpellOnKill(killed_level, spell);
}
m_combat_record.Stop();
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) {
const auto& export_string = fmt::format(
"{} {} {} {}",
killer_mob ? killer_mob->GetID() : 0,
damage,
spell,
static_cast<int>(attack_skill)
);
std::vector<std::any> args = { corpse };
parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0, &args);
}
/* Zone controller process EVENT_DEATH_ZONE (Death events) */
if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DEATH_ZONE)) {
const auto& export_string = fmt::format(
"{} {} {} {}",
killer_mob ? killer_mob->GetID() : 0,
damage,
spell,
static_cast<int>(attack_skill)
);
std::vector<std::any> args = { corpse, this };
DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args);
}
const uint16 entity_id = GetID();
if (!HasOwner() && !IsMerc() && !GetSwarmInfo() && (!is_merchant || allow_merchant_corpse) &&
((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) ||
@@ -2799,7 +2738,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
ApplyIllusionToCorpse(illusion_spell_id, corpse);
if (killer != 0 && emoteid != 0)
corpse->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::AfterDeath, emoteid);
corpse->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::AfterDeath, emoteid, killer);
if (killer != 0 && killer->IsClient()) {
corpse->AllowPlayerLoot(killer, 0);
if (killer->IsGrouped()) {
@@ -2877,6 +2816,39 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
entity_list.RemoveFromXTargets(this);
}
// Parse quests even if we're killed by an NPC
if (oos) {
if (IsNPC()) {
auto emote_id = GetEmoteID();
if (emote_id) {
DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emoteid, killer_mob);
}
}
if (oos->IsNPC()) {
if (parse->HasQuestSub(oos->GetNPCTypeID(), EVENT_NPC_SLAY)) {
parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0);
}
auto emote_id = oos->GetEmoteID();
if (emote_id) {
oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id, this);
}
if (killer_mob) {
killer_mob->TrySpellOnKill(killed_level, spell);
}
}
}
if (killer_mob && killer_mob->IsBot()) {
if (parse->BotHasQuestSub(EVENT_NPC_SLAY)) {
parse->EventBot(EVENT_NPC_SLAY, killer_mob->CastToBot(), this, "", 0);
}
killer_mob->TrySpellOnKill(killed_level, spell);
}
WipeHateList();
p_depop = true;
@@ -2885,6 +2857,39 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
entity_list.UpdateFindableNPCState(this, true);
m_combat_record.Stop();
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) {
const auto& export_string = fmt::format(
"{} {} {} {} {}",
killer_mob ? killer_mob->GetID() : 0,
damage,
spell,
static_cast<int>(attack_skill),
entity_id
);
std::vector<std::any> args = { corpse };
parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0, &args);
}
// Zone controller process EVENT_DEATH_ZONE (Death events)
if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DEATH_ZONE)) {
const auto& export_string = fmt::format(
"{} {} {} {} {}",
killer_mob ? killer_mob->GetID() : 0,
damage,
spell,
static_cast<int>(attack_skill),
entity_id
);
std::vector<std::any> args = { corpse, this };
DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args);
}
return true;
}
@@ -4087,7 +4092,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
IsPlayerRace(GetBaseRace()) &&
RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace())
) ||
GetBaseRace() == RACE_OGGOK_CITIZEN_93
GetBaseRace() == Race::OggokCitizen
) {
is_immune_to_frontal_stun = true;
}
@@ -4107,7 +4112,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
IsPlayerRace(GetBaseRace()) &&
RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace())
) ||
GetBaseRace() == RACE_OGGOK_CITIZEN_93
GetBaseRace() == Race::OggokCitizen
)
) {
is_immune_to_frontal_stun = true;
@@ -5015,7 +5020,7 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
hit.damage_done = (hit.damage_done * SlayDmgBonus) / 100;
/* Female */
if (GetGender() == 1) {
if (GetGender() == Gender::Female) {
entity_list.FilteredMessageCloseString(
this, /* Sender */
false, /* Skip Sender */
+3 -3
View File
@@ -49,9 +49,9 @@ Beacon::Beacon(const glm::vec4 &in_pos, int lifetime) : Mob(
nullptr, // in_lastname
0, // in_cur_hp
0, // in_max_hp
MALE, // in_gender
INVISIBLE_MAN, // in_race
0, // in_class
Gender::Male, // in_gender
Race::InvisibleMan, // in_race
Class::None, // in_class
BT_NoTarget, // in_bodytype
0, // in_deity
0, // in_level
+8 -8
View File
@@ -281,10 +281,10 @@ Bot::Bot(
case SE_IllusionCopy:
case SE_Illusion: {
if (spell.base_value[x1] == -1) {
if (gender == FEMALE) {
gender = MALE;
} else if (gender == MALE) {
gender = FEMALE;
if (gender == Gender::Female) {
gender = Gender::Male;
} else if (gender == Gender::Male) {
gender = Gender::Female;
}
SendIllusionPacket(
@@ -2681,7 +2681,7 @@ void Bot::CalcMeleeDistances(const Mob* tar, const EQ::ItemInstance* const& p_it
float other_size_mod = tar->GetSize();
// For races with a fixed size
if (GetRace() == RT_DRAGON || GetRace() == RT_WURM || GetRace() == RT_DRAGON_7) {
if (GetRace() == Race::LavaDragon || GetRace() == Race::Wurm || GetRace() == Race::GhostDragon) {
// size_mod = 60.0f;
}
@@ -2690,7 +2690,7 @@ void Bot::CalcMeleeDistances(const Mob* tar, const EQ::ItemInstance* const& p_it
}
// For races with a fixed size
if (tar->GetRace() == RT_DRAGON || tar->GetRace() == RT_WURM || tar->GetRace() == RT_DRAGON_7) {
if (tar->GetRace() == Race::LavaDragon || tar->GetRace() == Race::Wurm || tar->GetRace() == Race::GhostDragon) {
other_size_mod = 60.0f;
}
@@ -2902,12 +2902,12 @@ void Bot::AcquireBotTarget(Group* bot_group, Raid* raid, Client* leash_owner, fl
}
} else {
// This will keep bots on target for now..but, future updates will allow for rooting/stunning
if (auto escaping = hate_list.GetEscapingEntOnHateList(leash_owner, leash_distance)) {
if (auto escaping = hate_list.GetEscapingMobOnHateList(leash_owner, leash_distance)) {
SetTarget(escaping);
}
if (!GetTarget()) {
auto most_hate = hate_list.GetEntWithMostHateOnList(this, nullptr, true);
auto most_hate = hate_list.GetMobWithMostHateOnList(this, nullptr, true);
if (most_hate) {
SetTarget(most_hate);
}
+23 -23
View File
@@ -2870,7 +2870,7 @@ void bot_command_apply_poison(Client *c, const Seperator *sep)
}
if (my_rogue_bot->GetLevel() < 18) {
c->Message(Chat::White, "Your rogue bot must be level 18 before %s can apply poison!", (my_rogue_bot->GetGender() == 1 ? "she" : "he"));
c->Message(Chat::White, "Your rogue bot must be level 18 before %s can apply poison!", (my_rogue_bot->GetGender() == Gender::Female ? "she" : "he"));
return;
}
@@ -5633,7 +5633,7 @@ void bot_subcommand_bot_beard_color(Client *c, const Seperator *sep)
uint8 uvalue = Strings::ToInt(sep->arg[1]);
auto fail_type = BCEnum::AFT_None;
if (my_bot->GetGender() != MALE && my_bot->GetRace() != DWARF)
if (my_bot->GetGender() != Gender::Male && my_bot->GetRace() != DWARF)
fail_type = BCEnum::AFT_GenderRace;
else if (!PlayerAppearance::IsValidBeardColor(my_bot->GetRace(), my_bot->GetGender(), uvalue))
fail_type = BCEnum::AFT_Value;
@@ -5670,7 +5670,7 @@ void bot_subcommand_bot_beard_style(Client *c, const Seperator *sep)
uint8 uvalue = Strings::ToInt(sep->arg[1]);
auto fail_type = BCEnum::AFT_None;
if (my_bot->GetGender() != MALE && my_bot->GetRace() != DWARF)
if (my_bot->GetGender() != Gender::Male && my_bot->GetRace() != DWARF)
fail_type = BCEnum::AFT_GenderRace;
else if (!PlayerAppearance::IsValidBeard(my_bot->GetRace(), my_bot->GetGender(), uvalue))
fail_type = BCEnum::AFT_Value;
@@ -5913,11 +5913,11 @@ void bot_command_view_combos(Client *c, const Seperator *sep)
};
const uint16 race_values[17] = {
RACE_DOUG_0,
RACE_HUMAN_1, RACE_BARBARIAN_2, RACE_ERUDITE_3, RACE_WOOD_ELF_4,
RACE_HIGH_ELF_5, RACE_DARK_ELF_6, RACE_HALF_ELF_7, RACE_DWARF_8,
RACE_TROLL_9, RACE_OGRE_10, RACE_HALFLING_11, RACE_GNOME_12,
RACE_IKSAR_128, RACE_VAH_SHIR_130, RACE_FROGLOK_330, RACE_DRAKKIN_522
Race::Doug,
Race::Human, Race::Barbarian, Race::Erudite, Race::WoodElf,
Race::HighElf, Race::DarkElf, Race::HalfElf, Race::Dwarf,
Race::Troll, Race::Ogre, Race::Halfling, Race::Gnome,
Race::Iksar, Race::VahShir, Race::Froglok2, Race::Drakkin
};
if (helper_command_alias_fail(c, "bot_command_view_combos", sep->arg[0], "viewcombos")) {
@@ -6028,11 +6028,11 @@ void bot_subcommand_bot_create(Client *c, const Seperator *sep)
};
const uint16 race_values[17] = {
RACE_DOUG_0,
RACE_HUMAN_1, RACE_BARBARIAN_2, RACE_ERUDITE_3, RACE_WOOD_ELF_4,
RACE_HIGH_ELF_5, RACE_DARK_ELF_6, RACE_HALF_ELF_7, RACE_DWARF_8,
RACE_TROLL_9, RACE_OGRE_10, RACE_HALFLING_11, RACE_GNOME_12,
RACE_IKSAR_128, RACE_VAH_SHIR_130, RACE_FROGLOK_330, RACE_DRAKKIN_522
Race::Doug,
Race::Human, Race::Barbarian, Race::Erudite, Race::WoodElf,
Race::HighElf, Race::DarkElf, Race::HalfElf, Race::Dwarf,
Race::Troll, Race::Ogre, Race::Halfling, Race::Gnome,
Race::Iksar, Race::VahShir, Race::Froglok2, Race::Drakkin
};
const std::string gender_substrs[2] = {
@@ -6171,18 +6171,18 @@ void bot_subcommand_bot_create(Client *c, const Seperator *sep)
return;
}
auto bot_gender = MALE;
auto bot_gender = Gender::Male;
if (sep->IsNumber(4)) {
bot_gender = static_cast<uint8>(Strings::ToUnsignedInt(sep->arg[4]));
if (bot_gender == NEUTER) {
bot_gender = MALE;
if (bot_gender == Gender::Neuter) {
bot_gender = Gender::Male;
}
} else {
if (!strcasecmp(sep->arg[4], "m") || !strcasecmp(sep->arg[4], "male")) {
bot_gender = MALE;
bot_gender = Gender::Male;
} else if (!strcasecmp(sep->arg[4], "f") || !strcasecmp(sep->arg[4], "female")) {
bot_gender = FEMALE;
bot_gender = Gender::Female;
}
}
@@ -9561,15 +9561,15 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas
return bot_id;
}
if (!EQ::ValueWithin(bot_gender, MALE, FEMALE)) {
if (!EQ::ValueWithin(bot_gender, Gender::Male, Gender::Female)) {
bot_owner->Message(
Chat::White,
fmt::format(
"Gender: {} ({}) or {} ({})",
GetGenderName(MALE),
MALE,
GetGenderName(FEMALE),
FEMALE
GetGenderName(Gender::Male),
Gender::Male,
GetGenderName(Gender::Female),
Gender::Female
).c_str()
);
return bot_id;
+46 -46
View File
@@ -86,9 +86,9 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
"", // in_lastname
0, // in_cur_hp
0, // in_max_hp
0, // in_gender
0, // in_race
0, // in_class
Gender::Male, // in_gender
Race::Doug, // in_race
Class::None, // in_class
BT_Humanoid, // in_bodytype
0, // in_deity
0, // in_level
@@ -6172,7 +6172,7 @@ void Client::CheckEmoteHail(NPC* n, const char* message)
const auto emote_id = n->GetEmoteID();
if (emote_id) {
n->DoNPCEmote(EQ::constants::EmoteEventTypes::Hailed, emote_id);
n->DoNPCEmote(EQ::constants::EmoteEventTypes::Hailed, emote_id, this);
}
}
@@ -8632,8 +8632,8 @@ void Client::InitInnates()
m_pp.InnateSkills[InnateInspect] = InnateEnabled;
m_pp.InnateSkills[InnateOpen] = InnateEnabled;
if (race >= RT_FROGLOK_3) {
if (race == RT_SKELETON_2 || race == RT_FROGLOK_3) {
if (race >= Race::Froglok2) {
if (race == Race::Skeleton2 || race == Race::Froglok2) {
m_pp.InnateSkills[InnateUltraVision] = InnateEnabled;
} else {
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
@@ -8641,75 +8641,75 @@ void Client::InitInnates()
}
switch (race) {
case RT_BARBARIAN:
case RT_BARBARIAN_2:
case Race::Barbarian:
case Race::HalasCitizen:
m_pp.InnateSkills[InnateSlam] = InnateEnabled;
break;
case RT_ERUDITE:
case RT_ERUDITE_2:
case Race::Erudite:
case Race::EruditeCitizen:
m_pp.InnateSkills[InnateLore] = InnateEnabled;
break;
case RT_WOOD_ELF:
case RT_GUARD_3:
case Race::WoodElf:
case Race::Fayguard:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
break;
case RT_GNOME:
case RT_HIGH_ELF:
case RT_GUARD_2:
case Race::Gnome:
case Race::HighElf:
case Race::Felguard:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
m_pp.InnateSkills[InnateLore] = InnateEnabled;
break;
case RT_TROLL:
case RT_TROLL_2:
case Race::Troll:
case Race::GrobbCitizen:
m_pp.InnateSkills[InnateRegen] = InnateEnabled;
m_pp.InnateSkills[InnateSlam] = InnateEnabled;
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
break;
case RT_DWARF:
case RT_DWARF_2:
case Race::Dwarf:
case Race::KaladimCitizen:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
break;
case RT_OGRE:
case RT_OGRE_2:
case Race::Ogre:
case Race::OggokCitizen:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
m_pp.InnateSkills[InnateSlam] = InnateEnabled;
m_pp.InnateSkills[InnateNoBash] = InnateEnabled;
m_pp.InnateSkills[InnateBashDoor] = InnateEnabled;
break;
case RT_HALFLING:
case RT_HALFLING_2:
case Race::Halfling:
case Race::RivervaleCitizen:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
break;
case RT_IKSAR:
case Race::Iksar:
m_pp.InnateSkills[InnateRegen] = InnateEnabled;
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
break;
case RT_VAH_SHIR:
case Race::VahShir:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
break;
case RT_DARK_ELF:
case RT_DARK_ELF_2:
case RT_VAMPIRE_2:
case RT_FROGLOK_2:
case RT_GHOST:
case RT_GHOUL:
case RT_SKELETON:
case RT_VAMPIRE:
case RT_WILL_O_WISP:
case RT_ZOMBIE:
case RT_SPECTRE:
case RT_GHOST_2:
case RT_GHOST_3:
case RT_DRAGON_2:
case RT_INNORUUK:
case Race::DarkElf:
case Race::NeriakCitizen:
case Race::ElfVampire:
case Race::FroglokGhoul:
case Race::Ghost:
case Race::Ghoul:
case Race::Skeleton:
case Race::Vampire:
case Race::Wisp:
case Race::Zombie:
case Race::Spectre:
case Race::DwarfGhost:
case Race::EruditeGhost:
case Race::DragonSkeleton:
case Race::Innoruuk:
m_pp.InnateSkills[InnateUltraVision] = InnateEnabled;
break;
case RT_HUMAN:
case RT_GUARD:
case RT_BEGGAR:
case RT_HUMAN_2:
case RT_HUMAN_3:
case RT_FROGLOK_3: // client does froglok weird, but this should work out fine
case Race::Human:
case Race::FreeportGuard:
case Race::HumanBeggar:
case Race::HighpassCitizen:
case Race::QeynosCitizen:
case Race::Froglok2: // client does froglok weird, but this should work out fine
break;
default:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
+2
View File
@@ -982,11 +982,13 @@ public:
void PutLootInInventory(int16 slot_id, const EQ::ItemInstance &inst, ServerLootItem_Struct** bag_item_data = 0);
bool AutoPutLootInInventory(EQ::ItemInstance& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0);
bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = EQ::invslot::slotCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0);
void SummonItemIntoInventory(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool is_attuned = false);
void SummonBaggedItems(uint32 bag_item_id, const std::vector<ServerLootItem_Struct>& bag_items);
void SetStats(uint8 type,int16 set_val);
void IncStats(uint8 type,int16 increase_val);
void DropItem(int16 slot_id, bool recurse = true);
void DropItemQS(EQ::ItemInstance* inst, bool pickup);
bool HasItemOnCorpse(uint32 item_id);
bool IsAugmentRestricted(uint8 item_type, uint32 augment_restriction);
+16 -6
View File
@@ -6287,6 +6287,7 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
if (ed->dmgtype == EQ::constants::EnvironmentalDamage::Trap) {
BreakInvisibleSpells();
CancelSneakHide();
}
}
@@ -6597,17 +6598,26 @@ void Client::Handle_OP_GMGoto(const EQApplicationPacket *app)
auto *gmg = (GMSummon_Struct *) app->pBuffer;
Mob *gt = entity_list.GetMob(gmg->charname);
if (!gt) {
MovePC(zone->GetZoneID(), zone->GetInstanceID(), gt->GetX(), gt->GetY(), gt->GetZ(), gt->GetHeading());
if (gt) {
MovePC(
zone->GetZoneID(),
zone->GetInstanceID(),
gt->GetX(),
gt->GetY(),
gt->GetZ(),
gt->GetHeading()
);
} else if (!worldserver.Connected()) {
Message(Chat::Red, "Error: World server disconnected.");
} else {
auto pack = new ServerPacket(ServerOP_GMGoto, sizeof(ServerGMGoto_Struct));
memset(pack->pBuffer, 0, pack->size);
ServerGMGoto_Struct *wsgmg = (ServerGMGoto_Struct *) pack->pBuffer;
strcpy(wsgmg->myname, GetName());
strcpy(wsgmg->gotoname, gmg->charname);
wsgmg->admin = admin;
auto* g = (ServerGMGoto_Struct *) pack->pBuffer;
strcpy(g->myname, GetName());
strcpy(g->gotoname, gmg->charname);
g->admin = admin;
worldserver.SendPacket(pack);
safe_delete(pack);
}
+1 -1
View File
@@ -1891,6 +1891,7 @@ void PerlembParser::ExportEventVariables(
ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]);
ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]);
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
ExportVar(package_name.c_str(), "killed_entity_id", sep.arg[4]);
if (extra_pointers && extra_pointers->size() >= 1) {
Corpse *corpse = std::any_cast<Corpse *>(extra_pointers->at(0));
@@ -1902,7 +1903,6 @@ void PerlembParser::ExportEventVariables(
if (extra_pointers && extra_pointers->size() >= 2) {
NPC *killed = std::any_cast<NPC *>(extra_pointers->at(1));
if (killed) {
ExportVar(package_name.c_str(), "killed_entity_id", killed->GetID());
ExportVar(package_name.c_str(), "killed_bot_id", killed->IsBot() ? killed->CastToBot()->GetBotID() : 0);
ExportVar(package_name.c_str(), "killed_npc_id", killed->IsNPC() ? killed->GetNPCTypeID() : 0);
ExportVar(package_name.c_str(), "killed_x", killed->GetX());
+3 -3
View File
@@ -37,9 +37,9 @@ Encounter::Encounter(const char *enc_name) : Mob(
nullptr, // in_lastname
0, // in_cur_hp
0, // in_max_hp
MALE, // in_gender
INVISIBLE_MAN, // in_race
0, // in_class
Gender::Male, // in_gender
Race::InvisibleMan, // in_race
Class::None, // in_class
BT_NoTarget, // in_bodytype
0, // in_deity
0, // in_level
+3 -3
View File
@@ -4781,7 +4781,7 @@ void EntityList::SendAppearanceEffects(Client *c)
++it;
continue;
}
cur->SendSavedAppearenceEffects(c);
cur->SendSavedAppearanceEffects(c);
}
++it;
}
@@ -4920,7 +4920,7 @@ void EntityList::ZoneWho(Client *c, Who_All_Struct *Who)
FormatMSGID = 5023; // 5023 %T1[ANONYMOUS] %2 %3 %4
uint32 PlayerClass = Class::None;
uint32 PlayerLevel = 0;
uint32 PlayerRace = RACE_DOUG_0;
uint32 PlayerRace = Race::Doug;
uint32 ZoneMSGID = 0xFFFFFFFF;
if (ClientEntry->GetAnon()==0) {
@@ -5750,7 +5750,7 @@ void EntityList::DespawnGridNodes(int32 grid_id) {
Mob *mob = m.second;
if (
mob->IsNPC() &&
mob->GetRace() == RACE_NODE_2254 &&
mob->GetRace() == Race::Node &&
mob->EntityVariableExists("grid_id") &&
Strings::ToInt(mob->GetEntityVariable("grid_id")) == grid_id)
{
-60
View File
@@ -1,60 +0,0 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA */
/* Error messages for mysql clients */
/* error messages for the demon is in share/language/errmsg.sys */
#ifdef __cplusplus
extern "C" {
#endif
void init_client_errs(void);
extern const char *client_errors[]; /* Error messages */
#ifdef __cplusplus
}
#endif
#define CR_MIN_ERROR 2000 /* For easier client code */
#define CR_MAX_ERROR 2999
#if defined(OS2) && defined( MYSQL_SERVER)
#define CER(X) client_errors[(X)-CR_MIN_ERROR]
#else
#define ER(X) client_errors[(X)-CR_MIN_ERROR]
#endif
#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */
#define CR_UNKNOWN_ERROR 2000
#define CR_SOCKET_CREATE_ERROR 2001
#define CR_CONNECTION_ERROR 2002
#define CR_CONN_HOST_ERROR 2003
#define CR_IPSOCK_ERROR 2004
#define CR_UNKNOWN_HOST 2005
#define CR_SERVER_GONE_ERROR 2006
#define CR_VERSION_ERROR 2007
#define CR_OUT_OF_MEMORY 2008
#define CR_WRONG_HOST_INFO 2009
#define CR_LOCALHOST_CONNECTION 2010
#define CR_TCP_CONNECTION 2011
#define CR_SERVER_HANDSHAKE_ERR 2012
#define CR_SERVER_LOST 2013
#define CR_COMMANDS_OUT_OF_SYNC 2014
#define CR_NAMEDPIPE_CONNECTION 2015
#define CR_NAMEDPIPEWAIT_ERROR 2016
#define CR_NAMEDPIPEOPEN_ERROR 2017
#define CR_NAMEDPIPESETSTATE_ERROR 2018
#define CR_CANT_READ_CHARSET 2019
#define CR_NET_PACKET_TOO_LARGE 2020
+1 -1
View File
@@ -456,7 +456,7 @@ void Client::ForageItem(bool guarantee) {
}
//not an else in case theres no DB food
if (foragedfood == 0) {
if (foragedfood == 0 && RuleB(Character, UseForageCommonFood)) {
uint8 index = 0;
index = zone->random.Int(0, MAX_COMMON_FOOD_IDS-1);
foragedfood = common_food_ids[index];
+1 -1
View File
@@ -86,7 +86,7 @@ void command_appearanceeffects(Client *c, const Seperator *sep)
.texture = t->GetTexture(),
}
);
t->ClearAppearenceEffects();
t->ClearAppearanceEffects();
c->Message(
Chat::White,
fmt::format(
+2 -10
View File
@@ -7,10 +7,7 @@ void FindEmote(Client *c, const Seperator *sep)
if (sep->IsNumber(2)) {
auto emote_id = Strings::ToUnsignedInt(sep->arg[2]);
LinkedListIterator<NPC_Emote_Struct *> iterator(zone->NPCEmoteList);
iterator.Reset();
while (iterator.MoreElements()) {
auto &e = iterator.GetData();
for (auto& e : zone->npc_emote_list) {
if (emote_id == e->emoteid) {
c->Message(
Chat::White,
@@ -40,7 +37,6 @@ void FindEmote(Client *c, const Seperator *sep)
break;
}
iterator.Advance();
}
if (found_count == 50) {
@@ -70,10 +66,7 @@ void FindEmote(Client *c, const Seperator *sep)
const std::string& search_criteria = sep->argplus[2];
LinkedListIterator<NPC_Emote_Struct *> iterator(zone->NPCEmoteList);
iterator.Reset();
while (iterator.MoreElements()) {
auto &e = iterator.GetData();
for (auto& e : zone->npc_emote_list) {
const std::string& current_text = Strings::ToLower(e->text);
@@ -106,7 +99,6 @@ void FindEmote(Client *c, const Seperator *sep)
break;
}
iterator.Advance();
}
if (found_count == 50) {
+2 -2
View File
@@ -5,7 +5,7 @@ void FindRace(Client *c, const Seperator *sep)
if (sep->IsNumber(2)) {
const auto race_id = static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[2]));
const std::string& race_name = GetRaceIDName(race_id);
if (EQ::ValueWithin(race_id, RACE_HUMAN_1, RACE_PEGASUS_732)) {
if (EQ::ValueWithin(race_id, Race::Human, Race::Pegasus3)) {
c->Message(
Chat::White,
fmt::format(
@@ -41,7 +41,7 @@ void FindRace(Client *c, const Seperator *sep)
auto found_count = 0;
for (uint16 race_id = RACE_HUMAN_1; race_id <= RACE_PEGASUS_732; race_id++) {
for (uint16 race_id = Race::Human; race_id <= Race::Pegasus3; race_id++) {
std::string race_name = GetRaceIDName(race_id);
auto race_name_lower = Strings::ToLower(race_name);
if (!Strings::Contains(race_name_lower, search_criteria)) {
+4 -4
View File
@@ -60,11 +60,11 @@ void command_fixmob(Client *c, const Seperator *sep)
ChangeSetting = Race;
}
else if (strcasecmp(command, "gender") == 0) {
if (Gender == MALE && codeMove == 'p') {
Gender = NEUTER;
if (Gender == Gender::Male && codeMove == 'p') {
Gender = Gender::Neuter;
}
else if (Gender >= NEUTER && codeMove != 'p') {
Gender = MALE;
else if (Gender >= Gender::Neuter && codeMove != 'p') {
Gender = Gender::Male;
}
else {
Gender += Adjustment;
+1 -1
View File
@@ -15,7 +15,7 @@ void SetGender(Client *c, const Seperator *sep)
}
const uint8 gender_id = Strings::ToUnsignedInt(sep->arg[2]);
if (!EQ::ValueWithin(gender_id, MALE, NEUTER)) {
if (!EQ::ValueWithin(gender_id, Gender::Male, Gender::Neuter)) {
c->Message(Chat::White, "Usage: #set gender [Gender ID]");
c->Message(Chat::White, "Genders: 0 = Male, 1 = Female, 2 = Neuter");
return;
+1 -1
View File
@@ -15,7 +15,7 @@ void SetGenderPermanent(Client *c, const Seperator *sep)
}
const uint8 gender_id = Strings::ToInt(sep->arg[2]);
if (!EQ::ValueWithin(gender_id, MALE, NEUTER)) {
if (!EQ::ValueWithin(gender_id, Gender::Male, Gender::Neuter)) {
c->Message(Chat::White, "Usage: #set gender_permanent [Gender ID]");
c->Message(Chat::White, "Genders: 0 = Male, 1 = Female, 2 = Neuter");
return;
+1 -1
View File
@@ -23,7 +23,7 @@ void SetRace(Client *c, const Seperator *sep)
const uint16 race_id = Strings::ToUnsignedInt(sep->arg[2]);
if (
!EQ::ValueWithin(race_id, RACE_DOUG_0, RuleI(NPC, MaxRaceID)) &&
!EQ::ValueWithin(race_id, Race::Doug, RuleI(NPC, MaxRaceID)) &&
!EQ::ValueWithin(race_id, 2253, 2259)
) {
c->Message(
+1 -5
View File
@@ -12,10 +12,7 @@ void ShowEmotes(Client *c, const Seperator *sep)
uint32 emote_count = 0;
const uint32 emote_id = t->GetEmoteID();
LinkedListIterator<NPC_Emote_Struct *> iterator(zone->NPCEmoteList);
iterator.Reset();
while (iterator.MoreElements()) {
const auto& e = iterator.GetData();
for (auto& e : zone->npc_emote_list) {
if (emote_id == e->emoteid) {
c->Message(
Chat::White,
@@ -41,7 +38,6 @@ void ShowEmotes(Client *c, const Seperator *sep)
emote_count++;
}
iterator.Advance();
}
c->Message(
+1 -1
View File
@@ -4,7 +4,7 @@ void ShowZonePoints(Client *c, const Seperator *sep)
{
for (const auto& m : entity_list.GetMobList()) {
Mob* mob = m.second;
if (mob->IsNPC() && mob->GetRace() == RACE_NODE_2254) {
if (mob->IsNPC() && mob->GetRace() == Race::Node) {
mob->Depop();
}
}
+126 -257
View File
@@ -149,7 +149,7 @@ Mob* HateList::GetDamageTopOnHateList(Mob* hater)
return current;
}
Mob* HateList::GetClosestEntOnHateList(Mob *hater, bool skip_mezzed, EntityFilterType entity_type) {
Mob* HateList::GetClosestEntOnHateList(Mob *hater, bool skip_mezzed, EntityFilterType filter_type) {
Mob* close_entity = nullptr;
float close_distance = 99999.9f;
float this_distance;
@@ -163,7 +163,7 @@ Mob* HateList::GetClosestEntOnHateList(Mob *hater, bool skip_mezzed, EntityFilte
continue;
}
switch (entity_type) {
switch (filter_type) {
case EntityFilterType::Bots:
if (!e->entity_on_hatelist->IsBot()) {
continue;
@@ -344,191 +344,215 @@ int HateList::GetHateRatio(Mob *top, Mob *other)
// skip is used to ignore a certain mob on the list
// Currently used for getting 2nd on list for aggro meter
Mob *HateList::GetEntWithMostHateOnList(Mob *center, Mob *skip, bool skip_mezzed)
Mob *HateList::GetMobWithMostHateOnList(
Mob *center,
Mob *skip,
bool skip_mezzed,
EntityFilterType filter_type
)
{
// hack fix for zone shutdown crashes on some servers
if (!zone->IsLoaded())
if (!zone->IsLoaded()) { // hack fix for zone shutdown crashes on some servers
return nullptr;
}
Mob* top_hate = nullptr;
int64 hate = -1;
Mob *top_hate = nullptr;
int64 hate = -1;
if (center == nullptr)
if (!center) {
return nullptr;
}
if (RuleB(Aggro, SmartAggroList)){
Mob* top_client_type_in_range = nullptr;
if (RuleB(Aggro, SmartAggroList)) {
Mob *top_client_type_in_range = nullptr;
int64 hate_client_type_in_range = -1;
int skipped_count = 0;
int skipped_count = 0;
auto iterator = list.begin();
while (iterator != list.end())
{
struct_HateList *cur = (*iterator);
int16 aggro_mod = 0;
while (iterator != list.end()) {
struct_HateList *cur = (*iterator);
int16 aggro_mod = 0;
if (!cur){
if (!cur) {
++iterator;
continue;
}
if (!cur->entity_on_hatelist){
Mob *m = cur->entity_on_hatelist;
if (!m) {
++iterator;
continue;
}
if (cur->entity_on_hatelist == skip) {
if (m == skip) {
++iterator;
continue;
}
if (skip_mezzed && cur->entity_on_hatelist->IsMezzed()) {
if (skip_mezzed && m->IsMezzed()) {
++iterator;
continue;
}
if (cur->entity_on_hatelist->Sanctuary()) {
if (hate == -1)
{
top_hate = cur->entity_on_hatelist;
hate = 1;
if (
(filter_type == EntityFilterType::Bots && !m->IsBot()) ||
(filter_type == EntityFilterType::Clients && !m->IsClient()) ||
(filter_type == EntityFilterType::NPCs && !m->IsNPC())
) {
++iterator;
continue;
}
if (m->Sanctuary()) {
if (hate == -1) {
top_hate = m;
hate = 1;
}
++iterator;
continue;
}
if (cur->entity_on_hatelist->DivineAura() || cur->entity_on_hatelist->IsMezzed() || cur->entity_on_hatelist->IsFeared()){
if (hate == -1)
{
top_hate = cur->entity_on_hatelist;
hate = 0;
if (m->DivineAura() || m->IsMezzed() || m->IsFeared()) {
if (hate == -1) {
top_hate = m;
hate = 0;
}
++iterator;
continue;
}
int64 current_hate = cur->stored_hate_amount;
if (cur->entity_on_hatelist->IsClient() || cur->entity_on_hatelist->IsBot()){
if (cur->entity_on_hatelist->IsClient() && cur->entity_on_hatelist->CastToClient()->IsSitting()){
if (m->IsOfClientBot()) {
if (m->IsClient() && m->CastToClient()->IsSitting()) {
aggro_mod += RuleI(Aggro, SittingAggroMod);
}
if (center){
if (center->GetTarget() == cur->entity_on_hatelist)
if (center) {
if (center->GetTarget() == m) {
aggro_mod += RuleI(Aggro, CurrentTargetAggroMod);
if (RuleI(Aggro, MeleeRangeAggroMod) != 0)
{
if (center->CombatRange(cur->entity_on_hatelist)){
}
if (RuleI(Aggro, MeleeRangeAggroMod) != 0) {
if (center->CombatRange(m)) {
aggro_mod += RuleI(Aggro, MeleeRangeAggroMod);
if (current_hate > hate_client_type_in_range || cur->is_entity_frenzy){
if (current_hate > hate_client_type_in_range || cur->is_entity_frenzy) {
hate_client_type_in_range = current_hate;
top_client_type_in_range = cur->entity_on_hatelist;
top_client_type_in_range = m;
}
}
}
}
}
else{
if (center){
if (center->GetTarget() == cur->entity_on_hatelist)
} else {
if (center) {
if (center->GetTarget() == m) {
aggro_mod += RuleI(Aggro, CurrentTargetAggroMod);
if (RuleI(Aggro, MeleeRangeAggroMod) != 0)
{
if (center->CombatRange(cur->entity_on_hatelist)){
}
if (RuleI(Aggro, MeleeRangeAggroMod) != 0) {
if (center->CombatRange(m)) {
aggro_mod += RuleI(Aggro, MeleeRangeAggroMod);
}
}
}
}
if (cur->entity_on_hatelist->GetMaxHP() != 0 && ((cur->entity_on_hatelist->GetHP() * 100 / cur->entity_on_hatelist->GetMaxHP()) < 20)){
if (m->GetMaxHP() != 0 && ((m->GetHP() * 100 / m->GetMaxHP()) < 20)) {
aggro_mod += RuleI(Aggro, CriticallyWoundedAggroMod);
}
if (aggro_mod){
if (aggro_mod) {
current_hate += (current_hate * aggro_mod / 100);
}
if (current_hate > hate || cur->is_entity_frenzy){
hate = current_hate;
top_hate = cur->entity_on_hatelist;
if (current_hate > hate || cur->is_entity_frenzy) {
hate = current_hate;
top_hate = m;
}
++iterator;
}
if (top_client_type_in_range != nullptr && top_hate != nullptr) {
bool isTopClientType = top_hate->IsClient();
if (!isTopClientType) {
if (top_client_type_in_range && top_hate) {
bool is_top_client_type = top_hate->IsClient();
if (!is_top_client_type) {
if (top_hate->IsBot()) {
isTopClientType = true;
is_top_client_type = true;
top_client_type_in_range = top_hate;
}
}
if (!isTopClientType) {
if (!is_top_client_type) {
if (top_hate->IsMerc()) {
isTopClientType = true;
is_top_client_type = true;
top_client_type_in_range = top_hate;
}
}
if (!isTopClientType) {
if (top_hate->GetSpecialAbility(ALLOW_TO_TANK)){
isTopClientType = true;
if (!is_top_client_type) {
if (top_hate->GetSpecialAbility(ALLOW_TO_TANK)) {
is_top_client_type = true;
top_client_type_in_range = top_hate;
}
}
if (!isTopClientType)
if (!is_top_client_type) {
return top_client_type_in_range ? top_client_type_in_range : nullptr;
}
return top_hate ? top_hate : nullptr;
}
else {
if (top_hate == nullptr && skipped_count > 0) {
} else {
if (!top_hate && skipped_count > 0) {
return center->GetTarget() ? center->GetTarget() : nullptr;
}
return top_hate ? top_hate : nullptr;
}
}
else{
auto iterator = list.begin();
int skipped_count = 0;
while (iterator != list.end())
{
} else {
auto iterator = list.begin();
int skipped_count = 0;
while (iterator != list.end()) {
struct_HateList *cur = (*iterator);
if (cur) {
if (cur->entity_on_hatelist == skip) {
Mob *m = cur->entity_on_hatelist;
if (!m) {
++iterator;
continue;
}
if (skip_mezzed && cur->entity_on_hatelist->IsMezzed()) {
if (m == skip) {
++iterator;
continue;
}
if (cur->entity_on_hatelist != nullptr && ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy))
{
top_hate = cur->entity_on_hatelist;
hate = cur->stored_hate_amount;
if (skip_mezzed && m->IsMezzed()) {
++iterator;
continue;
}
if ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy) {
top_hate = m;
hate = cur->stored_hate_amount;
}
}
++iterator;
}
if (top_hate == nullptr && skipped_count > 0) {
if (!top_hate && skipped_count > 0) {
return center->GetTarget() ? center->GetTarget() : nullptr;
}
return top_hate ? top_hate : nullptr;
}
return nullptr;
}
Mob *HateList::GetEntWithMostHateOnList(bool skip_mezzed){
Mob *HateList::GetMobWithMostHateOnList(bool skip_mezzed){
Mob* top = nullptr;
int64 hate = -1;
@@ -539,7 +563,7 @@ Mob *HateList::GetEntWithMostHateOnList(bool skip_mezzed){
if (cur) {
LogHateDetail(
"Looping GetEntWithMostHateOnList1 [{}] cur [{}] hate [{}] calc [{}]",
"Looping GetMobWithMostHateOnList1 [{}] cur [{}] hate [{}] calc [{}]",
cur->entity_on_hatelist->GetMobDescription(),
cur->stored_hate_amount,
hate,
@@ -549,7 +573,7 @@ Mob *HateList::GetEntWithMostHateOnList(bool skip_mezzed){
if (cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate))
{
LogHateDetail(
"Looping GetEntWithMostHateOnList2 [{}]",
"Looping GetMobWithMostHateOnList2 [{}]",
cur->entity_on_hatelist->GetMobDescription()
);
@@ -565,53 +589,45 @@ Mob *HateList::GetEntWithMostHateOnList(bool skip_mezzed){
}
Mob *HateList::GetRandomEntOnHateList(bool skip_mezzed)
Mob *HateList::GetRandomMobOnHateList(EntityFilterType filter_type)
{
int count = list.size();
if (count <= 0) //If we don't have any entries it'll crash getting a random 0, -1 position.
return nullptr;
if (count == 1) //No need to do all that extra work if we only have one hate entry
{
if (*list.begin() && (!skip_mezzed || !(*list.begin())->entity_on_hatelist->IsMezzed())) // Just in case tHateEntry is invalidated somehow...
return (*list.begin())->entity_on_hatelist;
const auto &l = GetFilteredHateList(filter_type);
int count = l.size();
if (count <= 0) { // If we don't have any entries it'll crash getting a random 0, -1 position.
return nullptr;
}
if (skip_mezzed) {
for (auto iter : list) {
if (iter->entity_on_hatelist->IsMezzed()) {
--count;
if (count == 1) { // No need to do all that extra work if we only have one hate entry
auto c = *l.begin();
if (c) {
Mob *m = c->entity_on_hatelist;
if (!m) {
return nullptr;
}
return m;
}
if (count <= 0) {
return nullptr;
}
return nullptr;
}
int random = zone->random.Int(0, count - 1);
int counter = 0;
auto r = l.begin();
int random_index = rand() % count;
for (auto iter : list) {
std::advance(r, random_index);
if (skip_mezzed && iter->entity_on_hatelist->IsMezzed()) {
continue;
}
if (counter < random) {
auto e = *r;
++counter;
continue;
}
return iter->entity_on_hatelist;
Mob *m = e->entity_on_hatelist;
if (m) {
return m;
}
return nullptr;
}
Mob *HateList::GetEscapingEntOnHateList(Mob *center, float range, bool first) {
Mob *HateList::GetEscapingMobOnHateList(Mob *center, float range, bool first) {
// function is still in design stage
if (!center)
@@ -853,153 +869,6 @@ void HateList::RemoveStaleEntries(int time_ms, float dist)
}
}
Bot* HateList::GetRandomBotOnHateList(bool skip_mezzed)
{
int count = list.size();
if (count <= 0) { //If we don't have any entries it'll crash getting a random 0, -1 position.
return nullptr;
}
if (count == 1) { //No need to do all that extra work if we only have one hate entry
if (*list.begin() && (*list.begin())->entity_on_hatelist->IsBot() && (!skip_mezzed || !(*list.begin())->entity_on_hatelist->IsMezzed())) {
return (*list.begin())->entity_on_hatelist->CastToBot();
}
return nullptr;
}
if (skip_mezzed) {
for (auto iter : list) {
if (iter->entity_on_hatelist->IsMezzed()) {
--count;
}
}
if (count <= 0) {
return nullptr;
}
}
int random = zone->random.Int(0, count - 1);
int counter = 0;
for (auto iter : list) {
if (!iter->entity_on_hatelist->IsBot()) {
continue;
}
if (skip_mezzed && iter->entity_on_hatelist->IsMezzed()) {
continue;
}
if (counter < random) {
++counter;
continue;
}
return iter->entity_on_hatelist->CastToBot();
}
return nullptr;
}
Client* HateList::GetRandomClientOnHateList(bool skip_mezzed)
{
int count = list.size();
if (count <= 0) { //If we don't have any entries it'll crash getting a random 0, -1 position.
return nullptr;
}
if (count == 1) { //No need to do all that extra work if we only have one hate entry
if (*list.begin() && (*list.begin())->entity_on_hatelist->IsClient() && (!skip_mezzed || !(*list.begin())->entity_on_hatelist->IsMezzed())) {
return (*list.begin())->entity_on_hatelist->CastToClient();
}
return nullptr;
}
if (skip_mezzed) {
for (auto iter : list) {
if (iter->entity_on_hatelist->IsMezzed()) {
--count;
}
}
if (count <= 0) {
return nullptr;
}
}
int random = zone->random.Int(0, count - 1);
int counter = 0;
for (auto iter : list) {
if (!iter->entity_on_hatelist->IsClient()) {
continue;
}
if (skip_mezzed && iter->entity_on_hatelist->IsMezzed()) {
continue;
}
if (counter < random) {
++counter;
continue;
}
return iter->entity_on_hatelist->CastToClient();
}
return nullptr;
}
NPC* HateList::GetRandomNPCOnHateList(bool skip_mezzed)
{
int count = list.size();
if (count <= 0) { //If we don't have any entries it'll crash getting a random 0, -1 position.
return nullptr;
}
if (count == 1) { //No need to do all that extra work if we only have one hate entry
if (*list.begin() && (*list.begin())->entity_on_hatelist->IsNPC() && (!skip_mezzed || !(*list.begin())->entity_on_hatelist->IsMezzed())) {
return (*list.begin())->entity_on_hatelist->CastToNPC();
}
return nullptr;
}
if (skip_mezzed) {
for (auto iter : list) {
if (iter->entity_on_hatelist->IsMezzed()) {
--count;
}
}
if (count <= 0) {
return nullptr;
}
}
int random = zone->random.Int(0, count - 1);
int counter = 0;
for (auto iter : list) {
if (!iter->entity_on_hatelist->IsNPC()) {
continue;
}
if (skip_mezzed && iter->entity_on_hatelist->IsMezzed()) {
continue;
}
if (counter < random) {
++counter;
continue;
}
return iter->entity_on_hatelist->CastToNPC();
}
return nullptr;
}
void HateList::DamageHateList(int64 damage, uint32 distance, EntityFilterType filter_type, bool is_percentage)
{
if (damage <= 0) {
+5 -9
View File
@@ -41,16 +41,12 @@ public:
HateList();
~HateList();
Mob *GetClosestEntOnHateList(Mob *hater, bool skip_mezzed = false, EntityFilterType entity_type = EntityFilterType::All);
Mob *GetClosestEntOnHateList(Mob *hater, bool skip_mezzed = false, EntityFilterType filter_type = EntityFilterType::All);
Mob *GetDamageTopOnHateList(Mob *hater); // didn't add 'skip_mezzed' due to calls being in ::Death()
Mob *GetEntWithMostHateOnList(Mob *center, Mob *skip = nullptr, bool skip_mezzed = false);
Mob *GetRandomEntOnHateList(bool skip_mezzed = false);
Mob *GetEntWithMostHateOnList(bool skip_mezzed = false);
Mob *GetEscapingEntOnHateList(Mob *center, float range = 0.0f, bool first = false);
Bot* GetRandomBotOnHateList(bool skip_mezzed = false);
Client *GetRandomClientOnHateList(bool skip_mezzed = false);
NPC *GetRandomNPCOnHateList(bool skip_mezzed = false);
Mob *GetMobWithMostHateOnList(Mob *center, Mob *skip = nullptr, bool skip_mezzed = false, EntityFilterType filter_type = EntityFilterType::All);
Mob *GetRandomMobOnHateList(EntityFilterType filter_type = EntityFilterType::All);
Mob *GetMobWithMostHateOnList(bool skip_mezzed = false);
Mob *GetEscapingMobOnHateList(Mob *center, float range = 0.0f, bool first = false);
bool IsEntOnHateList(Mob *mob);
bool IsHateListEmpty();
+78
View File
@@ -4739,3 +4739,81 @@ bool Client::IsAugmentRestricted(uint8 item_type, uint32 augment_restriction)
return false;
}
void Client::SummonItemIntoInventory(
uint32 item_id,
int16 charges,
uint32 aug1,
uint32 aug2,
uint32 aug3,
uint32 aug4,
uint32 aug5,
uint32 aug6,
bool is_attuned
)
{
auto *inst = database.CreateItem(
item_id,
charges,
aug1,
aug2,
aug3,
aug4,
aug5,
aug6,
is_attuned
);
if (!inst) {
return;
}
const bool is_arrow = inst->GetItem()->ItemType == EQ::item::ItemTypeArrow;
const int16 slot_id = m_inv.FindFreeSlot(
inst->IsClassBag(),
true,
inst->GetItem()->Size,
is_arrow
);
SummonItem(
item_id,
charges,
aug1,
aug2,
aug3,
aug4,
aug5,
aug6,
is_attuned,
slot_id
);
}
bool Client::HasItemOnCorpse(uint32 item_id)
{
const uint32 corpse_count = GetCorpseCount();
if (!corpse_count) {
return EQ::invslot::SLOT_INVALID;
}
for (int i = 0; i < corpse_count; i++) {
const uint32 corpse_id = GetCorpseID(i);
for (int16 slot_id = EQ::invslot::POSSESSIONS_BEGIN; slot_id < EQ::invslot::POSSESSIONS_END; slot_id++) {
const uint32 current_item_id = GetCorpseItemAt(corpse_id, slot_id);
if (current_item_id && current_item_id == item_id) {
return true;
}
}
for (int16 slot_id = EQ::invbag::GENERAL_BAGS_BEGIN; slot_id < EQ::invbag::GENERAL_BAGS_END; slot_id++) {
const uint32 current_item_id = GetCorpseItemAt(corpse_id, slot_id);
if (current_item_id && current_item_id == item_id) {
return true;
}
}
}
return false;
}
+38 -1
View File
@@ -3217,6 +3217,41 @@ void Lua_Client::RemoveRadiantCrystals(uint32 amount)
self->RemoveRadiantCrystals(amount);
}
void Lua_Client::SummonItemIntoInventory(luabind::object item_table) {
Lua_Safe_Call_Void();
if (luabind::type(item_table) != LUA_TTABLE) {
return;
}
const uint32 item_id = luabind::object_cast<uint32>(item_table["item_id"]);
const int16 charges = luabind::object_cast<uint32>(item_table["charges"]);
const uint32 augment_one = luabind::type(item_table["augment_one"]) != LUA_TNIL ? luabind::object_cast<uint32>(item_table["augment_one"]) : 0;
const uint32 augment_two = luabind::type(item_table["augment_two"]) != LUA_TNIL ? luabind::object_cast<uint32>(item_table["augment_two"]) : 0;
const uint32 augment_three = luabind::type(item_table["augment_three"]) != LUA_TNIL ? luabind::object_cast<uint32>(item_table["augment_three"]) : 0;
const uint32 augment_four = luabind::type(item_table["augment_four"]) != LUA_TNIL ? luabind::object_cast<uint32>(item_table["augment_four"]) : 0;
const uint32 augment_five = luabind::type(item_table["augment_five"]) != LUA_TNIL ? luabind::object_cast<uint32>(item_table["augment_five"]) : 0;
const uint32 augment_six = luabind::type(item_table["augment_six"]) != LUA_TNIL ? luabind::object_cast<uint32>(item_table["augment_six"]) : 0;
const bool attuned = luabind::type(item_table["attuned"]) != LUA_TNIL ? luabind::object_cast<bool>(item_table["attuned"]) : false;
self->SummonItemIntoInventory(
item_id,
charges,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six,
attuned
);
}
bool Lua_Client::HasItemOnCorpse(uint32 item_id)
{
Lua_Safe_Call_Bool();
return self->HasItemOnCorpse(item_id);
}
luabind::scope lua_register_client() {
return luabind::class_<Lua_Client, Lua_Mob>("Client")
.def(luabind::constructor<>())
@@ -3479,6 +3514,7 @@ luabind::scope lua_register_client() {
.def("HasDisciplineLearned", (bool(Lua_Client::*)(uint16))&Lua_Client::HasDisciplineLearned)
.def("HasExpeditionLockout", (bool(Lua_Client::*)(std::string, std::string))&Lua_Client::HasExpeditionLockout)
.def("HasItemEquippedByID", (bool(Lua_Client::*)(uint32))&Lua_Client::HasItemEquippedByID)
.def("HasItemOnCorpse", (bool(Lua_Client::*)(uint32))&Lua_Client::HasItemOnCorpse)
.def("HasPEQZoneFlag", (bool(Lua_Client::*)(uint32))&Lua_Client::HasPEQZoneFlag)
.def("HasRecipeLearned", (bool(Lua_Client::*)(uint32))&Lua_Client::HasRecipeLearned)
.def("HasSkill", (bool(Lua_Client::*)(int))&Lua_Client::HasSkill)
@@ -3650,7 +3686,7 @@ luabind::scope lua_register_client() {
.def("SetBotSpawnLimit", (void(Lua_Client::*)(int))&Lua_Client::SetBotSpawnLimit)
.def("SetBotSpawnLimit", (void(Lua_Client::*)(int,uint8))&Lua_Client::SetBotSpawnLimit)
.def("SetBucket", (void(Lua_Client::*)(std::string,std::string))&Lua_Client::SetBucket)
.def("SetBucketExpires", (void(Lua_Client::*)(std::string,std::string,std::string))&Lua_Client::SetBucket)
.def("SetBucket", (void(Lua_Client::*)(std::string,std::string,std::string))&Lua_Client::SetBucket)
.def("SetClientMaxLevel", (void(Lua_Client::*)(int))&Lua_Client::SetClientMaxLevel)
.def("SetConsumption", (void(Lua_Client::*)(int, int))&Lua_Client::SetConsumption)
.def("SetDeity", (void(Lua_Client::*)(int))&Lua_Client::SetDeity)
@@ -3723,6 +3759,7 @@ luabind::scope lua_register_client() {
.def("SummonItem", (void(Lua_Client::*)(uint32,int,uint32,uint32,uint32,uint32,uint32))&Lua_Client::SummonItem)
.def("SummonItem", (void(Lua_Client::*)(uint32,int,uint32,uint32,uint32,uint32,uint32,bool))&Lua_Client::SummonItem)
.def("SummonItem", (void(Lua_Client::*)(uint32,int,uint32,uint32,uint32,uint32,uint32,bool,int))&Lua_Client::SummonItem)
.def("SummonItemIntoInventory", (void(Lua_Client::*)(luabind::adl::object))&Lua_Client::SummonItemIntoInventory)
.def("TGB", (bool(Lua_Client::*)(void))&Lua_Client::TGB)
.def("TakeMoneyFromPP", (bool(Lua_Client::*)(uint64))&Lua_Client::TakeMoneyFromPP)
.def("TakeMoneyFromPP", (bool(Lua_Client::*)(uint64,bool))&Lua_Client::TakeMoneyFromPP)
+2
View File
@@ -486,6 +486,8 @@ public:
void AddRadiantCrystals(uint32 amount);
void RemoveEbonCrystals(uint32 amount);
void RemoveRadiantCrystals(uint32 amount);
void SummonItemIntoInventory(luabind::object item_table);
bool HasItemOnCorpse(uint32 item_id);
void ApplySpell(int spell_id);
void ApplySpell(int spell_id, int duration);
+18
View File
@@ -1015,6 +1015,21 @@ Lua_Mob Lua_Mob::GetHateTop() {
return Lua_Mob(self->GetHateTop());
}
Lua_Bot Lua_Mob::GetHateTopBot() {
Lua_Safe_Call_Class(Lua_Bot);
return Lua_Bot(self->GetHateTopBot());
}
Lua_Client Lua_Mob::GetHateTopClient() {
Lua_Safe_Call_Class(Lua_Client);
return Lua_Client(self->GetHateTopClient());
}
Lua_NPC Lua_Mob::GetHateTopNPC() {
Lua_Safe_Call_Class(Lua_NPC);
return Lua_NPC(self->GetHateTopNPC());
}
Lua_Mob Lua_Mob::GetHateDamageTop(Lua_Mob other) {
Lua_Safe_Call_Class(Lua_Mob);
return Lua_Mob(self->GetHateDamageTop(other));
@@ -3456,6 +3471,9 @@ luabind::scope lua_register_mob() {
.def("GetHateRandomClient", (Lua_Client(Lua_Mob::*)(void))&Lua_Mob::GetHateRandomClient)
.def("GetHateRandomNPC", (Lua_NPC(Lua_Mob::*)(void))&Lua_Mob::GetHateRandomNPC)
.def("GetHateTop", (Lua_Mob(Lua_Mob::*)(void))&Lua_Mob::GetHateTop)
.def("GetHateTopBot", (Lua_Bot(Lua_Mob::*)(void))&Lua_Mob::GetHateTopBot)
.def("GetHateTopClient", (Lua_Client(Lua_Mob::*)(void))&Lua_Mob::GetHateTopClient)
.def("GetHateTopNPC", (Lua_NPC(Lua_Mob::*)(void))&Lua_Mob::GetHateTopNPC)
.def("GetHeading", &Lua_Mob::GetHeading)
.def("GetHelmTexture", &Lua_Mob::GetHelmTexture)
.def("GetHerosForgeModel", (int32(Lua_Mob::*)(uint8))&Lua_Mob::GetHerosForgeModel)
+3
View File
@@ -225,6 +225,9 @@ public:
Lua_HateList GetHateListByDistance();
Lua_HateList GetHateListByDistance(uint32 distance);
Lua_Mob GetHateTop();
Lua_Bot GetHateTopBot();
Lua_Client GetHateTopClient();
Lua_NPC GetHateTopNPC();
Lua_Mob GetHateDamageTop(Lua_Mob other);
Lua_Mob GetHateRandom();
Lua_Bot GetHateRandomBot();
+19 -6
View File
@@ -289,12 +289,13 @@ void handle_npc_death(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
Lua_Mob l_mob(init);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
lua_setfield(L, -2, "other");
Seperator sep(data.c_str());
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "killer_id");
@@ -317,6 +318,9 @@ void handle_npc_death(
lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "skill_id");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[4]));
lua_setfield(L, -2, "killed_entity_id");
if (extra_pointers && extra_pointers->size() >= 1) {
Lua_Corpse l_corpse(std::any_cast<Corpse*>(extra_pointers->at(0)));
luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse);
@@ -600,14 +604,14 @@ void handle_player_death(
l_mob_o.push(L);
lua_setfield(L, -2, "other");
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[0]));
lua_setfield(L, -2, "killer_id");
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "damage");
int spell_id = Strings::ToInt(sep.arg[3]);
if(IsValidSpell(spell_id)) {
const uint32 spell_id = Strings::ToUnsignedInt(sep.arg[2]);
if (IsValidSpell(spell_id)) {
Lua_Spell l_spell(&spells[spell_id]);
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
l_spell_o.push(L);
@@ -619,8 +623,11 @@ void handle_player_death(
lua_setfield(L, -2, "spell");
}
lua_pushinteger(L, Strings::ToInt(sep.arg[4]));
lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "skill");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[4]));
lua_setfield(L, -2, "killed_entity_id");
}
void handle_player_timer(
@@ -2136,6 +2143,9 @@ void handle_bot_death(
l_mob_o.push(L);
lua_setfield(L, -2, "other");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[0]));
lua_setfield(L, -2, "killer_id");
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "damage");
@@ -2154,6 +2164,9 @@ void handle_bot_death(
lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "skill");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[4]));
lua_setfield(L, -2, "killed_entity_id");
}
void handle_bot_popup_response(
+4 -4
View File
@@ -3933,14 +3933,14 @@ float Merc::GetMaxMeleeRangeToTarget(Mob* target) {
float size_mod = GetSize();
float other_size_mod = target->GetSize();
if (GetRace() == RACE_LAVA_DRAGON_49 || GetRace() == RACE_WURM_158 || GetRace() == RACE_GHOST_DRAGON_196) //For races with a fixed size
if (GetRace() == Race::LavaDragon || GetRace() == Race::Wurm || GetRace() == Race::GhostDragon) //For races with a fixed size
{
size_mod = 60.0f;
} else if (size_mod < 6.0) {
size_mod = 8.0f;
}
if (target->GetRace() == RACE_LAVA_DRAGON_49 || target->GetRace() == RACE_WURM_158 || target->GetRace() == RACE_GHOST_DRAGON_196) //For races with a fixed size
if (target->GetRace() == Race::LavaDragon || target->GetRace() == Race::Wurm || target->GetRace() == Race::GhostDragon) //For races with a fixed size
{
other_size_mod = 60.0f;
} else if (other_size_mod < 6.0) {
@@ -4323,7 +4323,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
npc_type->race = merc_template->RaceID;
// Use the Gender and Size of the Merchant if possible
uint8 tmpgender = MALE;
uint8 tmpgender = Gender::Male;
float tmpsize = 6.0f;
if(merchant_id > 0)
{
@@ -5624,7 +5624,7 @@ void Client::SetMerc(Merc* newmerc) {
GetMercInfo().myTemplate = nullptr;
GetMercInfo().IsSuspended = false;
GetMercInfo().SuspendedTime = 0;
GetMercInfo().Gender = MALE;
GetMercInfo().Gender = Gender::Male;
GetMercInfo().State = 0;
memset(GetMercInfo().merc_name, 0, 64);
Log(Logs::General, Logs::Mercenaries, "SetMerc No Merc for %s.", GetName());
+134 -185
View File
@@ -1599,21 +1599,6 @@ void Mob::SentPositionPacket(float dx, float dy, float dz, float dh, int anim, b
entity_list.QueueClients(this, &outapp, send_to_self == false, false);
}
// this is for SendPosition()
void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu) {
memset(spu, 0xff, sizeof(PlayerPositionUpdateServer_Struct));
spu->spawn_id = GetID();
spu->x_pos = FloatToEQ19(m_Position.x);
spu->y_pos = FloatToEQ19(m_Position.y);
spu->z_pos = FloatToEQ19(m_Position.z);
spu->delta_x = FloatToEQ13(0);
spu->delta_y = FloatToEQ13(0);
spu->delta_z = FloatToEQ13(0);
spu->heading = FloatToEQ12(m_Position.w);
spu->animation = 0;
spu->delta_heading = FloatToEQ10(0);
}
// this is for SendPosUpdate()
void Mob::MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu) {
spu->spawn_id = GetID();
@@ -2867,7 +2852,7 @@ void Mob::ShowStats(Client* c)
);
// Drakkin Features
if (t->GetRace() == RACE_DRAKKIN_522) {
if (t->GetRace() == Race::Drakkin) {
c->Message(
Chat::White,
fmt::format(
@@ -3526,7 +3511,7 @@ void Mob::GMMove(const glm::vec4 &position, bool save_guard_spot) {
void Mob::SendIllusionPacket(const AppearanceStruct& a)
{
uint16 new_race = (
a.race_id != RACE_DOUG_0 ?
a.race_id != Race::Doug ?
a.race_id :
(use_model ? use_model : GetBaseRace())
);
@@ -3558,7 +3543,7 @@ void Mob::SendIllusionPacket(const AppearanceStruct& a)
uint32 new_drakkin_tattoo = a.drakkin_tattoo == UINT32_MAX ? GetDrakkinTattoo() : a.drakkin_tattoo;
// Reset features to Base from the Player Profile
if (IsClient() && a.race_id == RACE_DOUG_0) {
if (IsClient() && a.race_id == Race::Doug) {
new_beard = CastToClient()->GetBaseBeard();
new_beard_color = CastToClient()->GetBaseBeardColor();
new_drakkin_details = CastToClient()->GetBaseDetails();
@@ -3632,7 +3617,7 @@ void Mob::SendIllusionPacket(const AppearanceStruct& a)
SendArmorAppearance();
if (a.send_effects) {
SendSavedAppearenceEffects(nullptr);
SendSavedAppearanceEffects(nullptr);
}
LogSpells(
@@ -3703,11 +3688,11 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
case HUMAN:
new_hair_color = zone->random.Int(0, 19);
if (current_gender == MALE) {
if (current_gender == Gender::Male) {
new_beard_color = new_hair_color;
new_hair_style = zone->random.Int(0, 3);
new_beard = zone->random.Int(0, 5);
} else if (current_gender == FEMALE) {
} else if (current_gender == Gender::Female) {
new_hair_style = zone->random.Int(0, 2);
}
@@ -3716,21 +3701,21 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
new_hair_color = zone->random.Int(0, 19);
new_luclin_face = zone->random.Int(0, 87);
if (current_gender == MALE) {
if (current_gender == Gender::Male) {
new_beard_color = new_hair_color;
new_hair_style = zone->random.Int(0, 3);
new_beard = zone->random.Int(0, 5);
} else if (current_gender == FEMALE) {
} else if (current_gender == Gender::Female) {
new_hair_style = zone->random.Int(0, 2);
}
break;
case ERUDITE:
if (current_gender == MALE) {
if (current_gender == Gender::Male) {
new_beard_color = zone->random.Int(0, 19);
new_beard = zone->random.Int(0, 5);
new_luclin_face = zone->random.Int(0, 57);
} else if (current_gender == FEMALE) {
} else if (current_gender == Gender::Female) {
new_luclin_face = zone->random.Int(0, 87);
}
@@ -3738,9 +3723,9 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
case WOOD_ELF:
new_hair_color = zone->random.Int(0, 19);
if (current_gender == MALE) {
if (current_gender == Gender::Male) {
new_hair_style = zone->random.Int(0, 3);
} else if (current_gender == FEMALE) {
} else if (current_gender == Gender::Female) {
new_hair_style = zone->random.Int(0, 2);
}
@@ -3748,11 +3733,11 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
case HIGH_ELF:
new_hair_color = zone->random.Int(0, 14);
if (current_gender == MALE) {
if (current_gender == Gender::Male) {
new_hair_style = zone->random.Int(0, 3);
new_luclin_face = zone->random.Int(0, 37);
new_beard_color = new_hair_color;
} else if (current_gender == FEMALE) {
} else if (current_gender == Gender::Female) {
new_hair_style = zone->random.Int(0, 2);
}
@@ -3760,11 +3745,11 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
case DARK_ELF:
new_hair_color = zone->random.Int(13, 18);
if (current_gender == MALE) {
if (current_gender == Gender::Male) {
new_hair_style = zone->random.Int(0, 3);
new_luclin_face = zone->random.Int(0, 37);
new_beard_color = new_hair_color;
} else if (current_gender == FEMALE) {
} else if (current_gender == Gender::Female) {
new_hair_style = zone->random.Int(0, 2);
}
@@ -3772,11 +3757,11 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
case HALF_ELF:
new_hair_color = zone->random.Int(0, 19);
if (current_gender == MALE) {
if (current_gender == Gender::Male) {
new_hair_style = zone->random.Int(0, 3);
new_luclin_face = zone->random.Int(0, 37);
new_beard_color = new_hair_color;
} else if (current_gender == FEMALE) {
} else if (current_gender == Gender::Female) {
new_hair_style = zone->random.Int(0, 2);
}
@@ -3785,10 +3770,10 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
new_hair_color = zone->random.Int(0, 19);
new_beard_color = new_hair_color;
if (current_gender == MALE) {
if (current_gender == Gender::Male) {
new_hair_style = zone->random.Int(0, 3);
new_beard = zone->random.Int(0, 5);
} else if (current_gender == FEMALE) {
} else if (current_gender == Gender::Female) {
new_hair_style = zone->random.Int(0, 2);
new_luclin_face = zone->random.Int(0, 17);
}
@@ -3798,14 +3783,14 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
new_eye_color_one = zone->random.Int(0, 10);
new_eye_color_two = zone->random.Int(0, 10);
if (current_gender == FEMALE) {
if (current_gender == Gender::Female) {
new_hair_style = zone->random.Int(0, 3);
new_hair_color = zone->random.Int(0, 23);
}
break;
case OGRE:
if (current_gender == FEMALE) {
if (current_gender == Gender::Female) {
new_hair_style = zone->random.Int(0, 3);
new_hair_color = zone->random.Int(0, 23);
}
@@ -3814,11 +3799,11 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
case HALFLING:
new_hair_color = zone->random.Int(0, 19);
if (current_gender == MALE) {
if (current_gender == Gender::Male) {
new_beard_color = new_hair_color;
new_hair_style = zone->random.Int(0, 3);
new_beard = zone->random.Int(0, 5);
} else if (current_gender == FEMALE) {
} else if (current_gender == Gender::Female) {
new_hair_style = zone->random.Int(0, 2);
}
@@ -3826,11 +3811,11 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
case GNOME:
new_hair_color = zone->random.Int(0, 24);
if (current_gender == MALE) {
if (current_gender == Gender::Male) {
new_beard_color = new_hair_color;
new_hair_style = zone->random.Int(0, 3);
new_beard = zone->random.Int(0, 5);
} else if (current_gender == FEMALE) {
} else if (current_gender == Gender::Female) {
new_hair_style = zone->random.Int(0, 2);
}
@@ -3852,10 +3837,10 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables)
new_drakkin_tattoo = zone->random.Int(0, 7);
new_drakkin_details = zone->random.Int(0, 7);
if (current_gender == MALE) {
if (current_gender == Gender::Male) {
new_beard = zone->random.Int(0, 12);
new_hair_style = zone->random.Int(0, 8);
} else if (current_gender == FEMALE) {
} else if (current_gender == Gender::Female) {
new_beard = zone->random.Int(0, 3);
new_hair_style = zone->random.Int(0, 7);
}
@@ -3918,86 +3903,86 @@ uint16 Mob::GetFactionRace() {
uint8 Mob::GetDefaultGender(uint16 in_race, uint8 in_gender) {
if (
IsPlayerRace(in_race) ||
in_race == RACE_BROWNIE_15 ||
in_race == RACE_KERRAN_23 ||
in_race == RACE_LION_50 ||
in_race == RACE_DRACNID_57 ||
in_race == RACE_ZOMBIE_70 ||
in_race == RACE_QEYNOS_CITIZEN_71 ||
in_race == RACE_RIVERVALE_CITIZEN_81 ||
in_race == RACE_HALAS_CITIZEN_90 ||
in_race == RACE_GROBB_CITIZEN_92 ||
in_race == RACE_OGGOK_CITIZEN_93 ||
in_race == RACE_KALADIM_CITIZEN_94 ||
in_race == RACE_ELF_VAMPIRE_98 ||
in_race == RACE_FELGUARD_106 ||
in_race == RACE_FAYGUARD_112 ||
in_race == RACE_ERUDITE_GHOST_118 ||
in_race == RACE_IKSAR_CITIZEN_139 ||
in_race == RACE_SHADE_224 ||
in_race == RACE_TROLL_CREW_MEMBER_331 ||
in_race == RACE_PIRATE_DECKHAND_332 ||
in_race == RACE_GNOME_PIRATE_338 ||
in_race == RACE_DARK_ELF_PIRATE_339 ||
in_race == RACE_OGRE_PIRATE_340 ||
in_race == RACE_HUMAN_PIRATE_341 ||
in_race == RACE_ERUDITE_PIRATE_342 ||
in_race == RACE_UNDEAD_PIRATE_344 ||
in_race == RACE_KNIGHT_OF_HATE_351 ||
in_race == RACE_WARLOCK_OF_HATE_352 ||
in_race == RACE_UNDEAD_VAMPIRE_359 ||
in_race == RACE_VAMPIRE_360 ||
in_race == RACE_SAND_ELF_364 ||
in_race == RACE_TAELOSIAN_NATIVE_385 ||
in_race == RACE_TAELOSIAN_EVOKER_386 ||
in_race == RACE_DRACHNID_461 ||
in_race == RACE_ZOMBIE_471 ||
in_race == RACE_ELDDAR_489 ||
in_race == RACE_VAMPIRE_497 ||
in_race == RACE_KERRAN_562 ||
in_race == RACE_BROWNIE_568 ||
in_race == RACE_HUMAN_566 ||
in_race == RACE_ELVEN_GHOST_587 ||
in_race == RACE_HUMAN_GHOST_588 ||
in_race == RACE_COLDAIN_645
in_race == Race::Brownie ||
in_race == Race::Kerran ||
in_race == Race::Lion ||
in_race == Race::Drachnid ||
in_race == Race::Zombie ||
in_race == Race::QeynosCitizen ||
in_race == Race::RivervaleCitizen ||
in_race == Race::HalasCitizen ||
in_race == Race::GrobbCitizen ||
in_race == Race::OggokCitizen ||
in_race == Race::KaladimCitizen ||
in_race == Race::ElfVampire ||
in_race == Race::Felguard ||
in_race == Race::Fayguard ||
in_race == Race::EruditeGhost ||
in_race == Race::IksarCitizen ||
in_race == Race::Shade ||
in_race == Race::TrollCrewMember ||
in_race == Race::PirateDeckhand ||
in_race == Race::GnomePirate ||
in_race == Race::DarkElfPirate ||
in_race == Race::OgrePirate ||
in_race == Race::HumanPirate ||
in_race == Race::EruditePirate ||
in_race == Race::TrollZombie ||
in_race == Race::KnightOfHate ||
in_race == Race::ArcanistOfHate ||
in_race == Race::UndeadVampire ||
in_race == Race::Vampire3 ||
in_race == Race::SandElf ||
in_race == Race::Nihil ||
in_race == Race::Trusik ||
in_race == Race::Drachnid2 ||
in_race == Race::Zombie2 ||
in_race == Race::Elddar ||
in_race == Race::Vampire4 ||
in_race == Race::Kerran2 ||
in_race == Race::Brownie2 ||
in_race == Race::Human2 ||
in_race == Race::ElvenGhost ||
in_race == Race::HumanGhost ||
in_race == Race::Coldain2
) {
if (in_gender >= 2) { // Male default for PC Races
return 0;
if (in_gender >= Gender::Neuter) { // Male default for PC Races
return Gender::Male;
} else {
return in_gender;
}
} else if (
in_race == RACE_FREEPORT_GUARD_44 ||
in_race == RACE_MIMIC_52 ||
in_race == RACE_HUMAN_BEGGAR_55 ||
in_race == RACE_VAMPIRE_65 ||
in_race == RACE_HIGHPASS_CITIZEN_67 ||
in_race == RACE_NERIAK_CITIZEN_77 ||
in_race == RACE_ERUDITE_CITIZEN_78 ||
in_race == RACE_CLOCKWORK_GNOME_88 ||
in_race == RACE_DWARF_GHOST_117 ||
in_race == RACE_SPECTRAL_IKSAR_147 ||
in_race == RACE_INVISIBLE_MAN_127 ||
in_race == RACE_VAMPYRE_208 ||
in_race == RACE_RECUSO_237 ||
in_race == RACE_BROKEN_SKULL_PIRATE_333 ||
in_race == RACE_INVISIBLE_MAN_OF_ZOMM_600 ||
in_race == RACE_OGRE_NPC_MALE_624 ||
in_race == RACE_BEEFEATER_667 ||
in_race == RACE_ERUDITE_678
in_race == Race::FreeportGuard ||
in_race == Race::Mimic ||
in_race == Race::HumanBeggar ||
in_race == Race::Vampire ||
in_race == Race::HighpassCitizen ||
in_race == Race::NeriakCitizen ||
in_race == Race::EruditeCitizen ||
in_race == Race::ClockworkGnome ||
in_race == Race::DwarfGhost ||
in_race == Race::IksarSpirit ||
in_race == Race::InvisibleMan ||
in_race == Race::Vampire2 ||
in_race == Race::Recuso ||
in_race == Race::BrokenSkullPirate ||
in_race == Race::InvisibleManOfZomm ||
in_race == Race::Ogre2 ||
in_race == Race::RoyalGuard ||
in_race == Race::Erudite2
) { // Male only races
return 0;
return Gender::Male;
} else if (
in_race == RACE_FAIRY_25 ||
in_race == RACE_PIXIE_56 ||
in_race == RACE_BANSHEE_487 ||
in_race == RACE_BANSHEE_488 ||
in_race == RACE_AYONAE_RO_498 ||
in_race == RACE_SULLON_ZEK_499
in_race == Race::Fairy ||
in_race == Race::Pixie ||
in_race == Race::Banshee2 ||
in_race == Race::Banshee3 ||
in_race == Race::AyonaeRo ||
in_race == Race::SullonZek
) { // Female only races
return 1;
return Gender::Female;
} else { // Neutral default for NPC Races
return 2;
return Gender::Neuter;
}
}
@@ -4038,21 +4023,6 @@ void Mob::SendLevelAppearance(){
safe_delete(outapp);
}
void Mob::SendStunAppearance()
{
auto outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct));
LevelAppearance_Struct* la = (LevelAppearance_Struct*)outapp->pBuffer;
la->parm1 = 58;
la->parm2 = 60;
la->spawn_id = GetID();
la->value1a = 2;
la->value1b = 0;
la->value2a = 2;
la->value2b = 0;
entity_list.QueueCloseClients(this,outapp);
safe_delete(outapp);
}
void Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target,
uint32 value1slot, uint32 value1ground, uint32 value2slot, uint32 value2ground, uint32 value3slot, uint32 value3ground,
uint32 value4slot, uint32 value4ground, uint32 value5slot, uint32 value5ground){
@@ -4092,19 +4062,19 @@ void Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32
}
if (!value1ground && parm1) {
SetAppearenceEffects(value1slot, parm1);
SetAppearanceEffects(value1slot, parm1);
}
if (!value2ground && parm2) {
SetAppearenceEffects(value2slot, parm2);
SetAppearanceEffects(value2slot, parm2);
}
if (!value3ground && parm3) {
SetAppearenceEffects(value3slot, parm3);
SetAppearanceEffects(value3slot, parm3);
}
if (!value4ground && parm4) {
SetAppearenceEffects(value4slot, parm4);
SetAppearanceEffects(value4slot, parm4);
}
if (!value5ground && parm5) {
SetAppearenceEffects(value5slot, parm5);
SetAppearanceEffects(value5slot, parm5);
}
LevelAppearance_Struct* la = (LevelAppearance_Struct*)outapp->pBuffer;
@@ -4135,7 +4105,7 @@ void Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32
safe_delete(outapp);
}
void Mob::SetAppearenceEffects(int32 slot, int32 value)
void Mob::SetAppearanceEffects(int32 slot, int32 value)
{
for (int i = 0; i < MAX_APPEARANCE_EFFECTS; i++) {
if (!appearance_effects_id[i]) {
@@ -4173,7 +4143,7 @@ void Mob::ListAppearanceEffects(Client* c)
}
}
void Mob::ClearAppearenceEffects()
void Mob::ClearAppearanceEffects()
{
for (int i = 0; i < MAX_APPEARANCE_EFFECTS; i++) {
appearance_effects_id[i] = 0;
@@ -4181,7 +4151,7 @@ void Mob::ClearAppearenceEffects()
}
}
void Mob::SendSavedAppearenceEffects(Client *receiver = nullptr)
void Mob::SendSavedAppearanceEffects(Client *receiver = nullptr)
{
if (!appearance_effects_id[0]) {
return;
@@ -4722,27 +4692,6 @@ bool Mob::PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, fl
return Result;
}
bool Mob::PlotPositionOnArcInFrontOfTarget(Mob* target, float& x_dest, float& y_dest, float& z_dest, float distance, float min_deg, float max_deg)
{
return false;
}
bool Mob::PlotPositionOnArcBehindTarget(Mob* target, float& x_dest, float& y_dest, float& z_dest, float distance)
{
return false;
}
bool Mob::PlotPositionBehindMeFacingTarget(Mob* target, float& x_dest, float& y_dest, float& z_dest, float min_dist, float max_dist)
{
return false;
}
bool Mob::HateSummon() {
// check if mob has ability to summon
// 97% is the offical % that summoning starts on live, not 94
@@ -4883,7 +4832,7 @@ bool Mob::RemoveFromHateList(Mob* mob)
}
if(GetTarget() == mob)
{
SetTarget(hate_list.GetEntWithMostHateOnList(this));
SetTarget(hate_list.GetMobWithMostHateOnList(this));
}
return bFound;
@@ -6867,22 +6816,22 @@ void Mob::RemoveAllNimbusEffects()
bool Mob::IsBoat() const {
return (
race == RACE_SHIP_72 ||
race == RACE_LAUNCH_73 ||
race == RACE_GHOST_SHIP_114 ||
race == RACE_SHIP_404 ||
race == RACE_MERCHANT_SHIP_550 ||
race == RACE_PIRATE_SHIP_551 ||
race == RACE_GHOST_SHIP_552 ||
race == RACE_BOAT_533
race == Race::Ship ||
race == Race::Launch ||
race == Race::GhostShip ||
race == Race::DiscordShip ||
race == Race::MerchantShip ||
race == Race::PirateShip ||
race == Race::GhostShip2 ||
race == Race::Boat2
);
}
bool Mob::IsControllableBoat() const {
return (
race == RACE_BOAT_141 ||
race == RACE_ROWBOAT_502
race == Race::Boat ||
race == Race::Rowboat
);
}
@@ -8218,37 +8167,37 @@ int Mob::DispatchZoneControllerEvent(
std::string Mob::GetRacePlural()
{
switch (GetBaseRace()) {
case RACE_HUMAN_1:
case Race::Human:
return "Humans";
case RACE_BARBARIAN_2:
case Race::Barbarian:
return "Barbarians";
case RACE_ERUDITE_3:
case Race::Erudite:
return "Erudites";
case RACE_WOOD_ELF_4:
case Race::WoodElf:
return "Wood Elves";
case RACE_HIGH_ELF_5:
case Race::HighElf:
return "High Elves";
case RACE_DARK_ELF_6:
case Race::DarkElf:
return "Dark Elves";
case RACE_HALF_ELF_7:
case Race::HalfElf:
return "Half Elves";
case RACE_DWARF_8:
case Race::Dwarf:
return "Dwarves";
case RACE_TROLL_9:
case Race::Troll:
return "Trolls";
case RACE_OGRE_10:
case Race::Ogre:
return "Ogres";
case RACE_HALFLING_11:
case Race::Halfling:
return "Halflings";
case RACE_GNOME_12:
case Race::Gnome:
return "Gnomes";
case RACE_IKSAR_128:
case Race::Iksar:
return "Iksar";
case RACE_VAH_SHIR_130:
case Race::VahShir:
return "Vah Shir";
case RACE_FROGLOK_330:
case Race::Froglok2:
return "Frogloks";
case RACE_DRAKKIN_522:
case Race::Drakkin:
return "Drakkin";
default:
return "Races";
+15 -17
View File
@@ -83,7 +83,7 @@ struct AppearanceStruct {
uint8 hair = UINT8_MAX;
uint8 hair_color = UINT8_MAX;
uint8 helmet_texture = UINT8_MAX;
uint16 race_id = RACE_DOUG_0;
uint16 race_id = Race::Doug;
bool send_effects = true;
float size = -1.0f;
Client *target = nullptr;
@@ -330,7 +330,6 @@ public:
void SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target=nullptr, uint32 value1slot = 1, uint32 value1ground = 1, uint32 value2slot = 1, uint32 value2ground = 1,
uint32 value3slot = 1, uint32 value3ground = 1, uint32 value4slot = 1, uint32 value4ground = 1, uint32 value5slot = 1, uint32 value5ground = 1);
void SendLevelAppearance();
void SendStunAppearance();
void SendTargetable(bool on, Client *specific_target = nullptr);
void SetMobTextureProfile(uint8 material_slot, uint32 texture, uint32 color = 0, uint32 hero_forge_model = 0);
@@ -495,10 +494,10 @@ public:
inline bool HasEndurUpkeep() const { return endur_upkeep; }
inline void SetEndurUpkeep(bool val) { endur_upkeep = val; }
bool HasBuffWithSpellGroup(int spell_group);
void SetAppearenceEffects(int32 slot, int32 value);
void SetAppearanceEffects(int32 slot, int32 value);
void ListAppearanceEffects(Client* c);
void ClearAppearenceEffects();
void SendSavedAppearenceEffects(Client *receiver);
void ClearAppearanceEffects();
void SendSavedAppearanceEffects(Client *receiver);
void SetBuffDuration(int spell_id, int duration = 0, int level_override = -1);
void ApplySpellBuff(int spell_id, int duration = 0, int level_override = -1);
int GetBuffStatValueBySpell(int32 spell_id, const char* stat_identifier);
@@ -716,7 +715,6 @@ public:
virtual void GMMove(float x, float y, float z, float heading = 0.01, bool save_guard_spot = true);
virtual void GMMove(const glm::vec4 &position, bool save_guard_spot = true);
void SetDelta(const glm::vec4& delta);
void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu);
void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu);
void SentPositionPacket(float dx, float dy, float dz, float dh, int anim, bool send_to_self = false);
virtual void StopMoving();
@@ -748,14 +746,17 @@ public:
int64 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHateAmount(tmob,is_dam);}
int64 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHateAmount(tmob, true);}
int GetHateRatio(Mob *first, Mob *with) { return hate_list.GetHateRatio(first, with); }
Mob* GetHateTop() { return hate_list.GetEntWithMostHateOnList(this);}
Mob* GetSecondaryHate(Mob *skip) { return hate_list.GetEntWithMostHateOnList(this, skip); }
Mob* GetHateTop() { return hate_list.GetMobWithMostHateOnList(this);}
Bot* GetHateTopBot() { return hate_list.GetMobWithMostHateOnList(this, nullptr, false, EntityFilterType::Bots)->CastToBot();}
Client* GetHateTopClient() { return hate_list.GetMobWithMostHateOnList(this, nullptr, false, EntityFilterType::Clients)->CastToClient();}
NPC* GetHateTopNPC() { return hate_list.GetMobWithMostHateOnList(this, nullptr, false, EntityFilterType::NPCs)->CastToNPC();}
Mob* GetSecondaryHate(Mob *skip) { return hate_list.GetMobWithMostHateOnList(this, skip); }
Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTopOnHateList(other);}
Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();}
Client* GetHateRandomClient() { return hate_list.GetRandomClientOnHateList(); }
NPC* GetHateRandomNPC() { return hate_list.GetRandomNPCOnHateList(); }
Bot* GetHateRandomBot() { return hate_list.GetRandomBotOnHateList(); }
Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();}
Mob* GetHateRandom() { return hate_list.GetRandomMobOnHateList(); }
Bot* GetHateRandomBot() { return hate_list.GetRandomMobOnHateList(EntityFilterType::Bots)->CastToBot(); }
Client* GetHateRandomClient() { return hate_list.GetRandomMobOnHateList(EntityFilterType::Clients)->CastToClient(); }
NPC* GetHateRandomNPC() { return hate_list.GetRandomMobOnHateList(EntityFilterType::NPCs)->CastToNPC(); }
Mob* GetHateMost() { return hate_list.GetMobWithMostHateOnList();}
Mob* GetHateClosest(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed); }
Bot* GetHateClosestBot(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed, EntityFilterType::Bots)->CastToBot(); }
Client* GetHateClosestClient(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed, EntityFilterType::Clients)->CastToClient(); }
@@ -837,9 +838,6 @@ public:
void ShowStats(Client* client);
void ShowBuffs(Client* c);
bool PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, float &z_dest, bool lookForAftArc = true);
bool PlotPositionOnArcInFrontOfTarget(Mob *target, float &x_dest, float &y_dest, float &z_dest, float distance, float min_deg = 5.0f, float max_deg = 150.0f);
bool PlotPositionOnArcBehindTarget(Mob *target, float &x_dest, float &y_dest, float &z_dest, float distance);
bool PlotPositionBehindMeFacingTarget(Mob *target, float &x_dest, float &y_dest, float &z_dest, float min_dist = 1.0f, float max_dist = 5.0f);
virtual int GetKillExpMod() const { return 100; }
// aura functions
@@ -1121,7 +1119,7 @@ public:
void DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int base_damage, int min_damage = 0, int32 hate_override = -1, int ReuseTime = 10);
void DoThrowingAttackDmg(Mob* other, const EQ::ItemInstance* RangeWeapon = nullptr, const EQ::ItemData* AmmoItem = nullptr, int32 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, int AmmoSlot = 0, float speed = 4.0f, bool DisableProcs = false);
void DoMeleeSkillAttackDmg(Mob* other, int32 weapon_damage, EQ::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool CanRiposte = false, int ReuseTime = 0);
void DoMeleeSkillAttackDmg(Mob* other, int32 weapon_damage, EQ::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool can_riposte = false, int ReuseTime = 0);
void DoArcheryAttackDmg(Mob* other, const EQ::ItemInstance* RangeWeapon = nullptr, const EQ::ItemInstance* Ammo = nullptr, int32 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, uint32 ammo_id = 0, const EQ::ItemData *AmmoItem = nullptr, int AmmoSlot = 0, float speed = 4.0f, bool DisableProcs = false);
bool TryProjectileAttack(Mob* other, const EQ::ItemData *item, EQ::skills::SkillType skillInUse, uint64 weapon_dmg, const EQ::ItemInstance* RangeWeapon, const EQ::ItemInstance* Ammo, int AmmoSlot, float speed, bool DisableProcs = false);
void ProjectileAttack();
+4 -4
View File
@@ -769,7 +769,7 @@ void Client::AI_Process()
{
if(AI_target_check_timer->Check())
{
SetTarget(hate_list.GetEntWithMostHateOnList(this));
SetTarget(hate_list.GetMobWithMostHateOnList(this));
}
}
@@ -1073,12 +1073,12 @@ void Mob::AI_Process() {
if (IsFocused()) {
if (!target) {
SetTarget(hate_list.GetEntWithMostHateOnList(this));
SetTarget(hate_list.GetMobWithMostHateOnList(this));
}
}
else {
if (!ImprovedTaunt())
SetTarget(hate_list.GetEntWithMostHateOnList(this));
SetTarget(hate_list.GetMobWithMostHateOnList(this));
}
}
@@ -1800,7 +1800,7 @@ void Mob::AI_Event_Engaged(Mob *attacker, bool yell_for_help)
auto emote_id = GetEmoteID();
if (emote_id) {
CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::EnterCombat, emoteid);
CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::EnterCombat, emoteid, attacker);
}
std::string mob_name = GetCleanName();
+71 -41
View File
@@ -155,10 +155,10 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi
// lava dragon is a fixed size model and should always use its default
// otherwise pathing issues
if (race == RACE_LAVA_DRAGON_49) {
if (race == Race::LavaDragon) {
size = 5;
}
if (race == RACE_WURM_158) {
if (race == Race::Wurm) {
size = 15;
}
@@ -1058,7 +1058,7 @@ bool NPC::Process()
NPCAssistCap() < RuleI(Combat, NPCAssistCap)) {
// Some cases like flash of light used for aggro haven't set target
if (!GetTarget()) {
SetTarget(hate_list.GetEntWithMostHateOnList(this));
SetTarget(hate_list.GetMobWithMostHateOnList(this));
}
AIYellForHelp(this, GetTarget());
if (NPCAssistCap() > 0 && !assist_cap_timer.Enabled())
@@ -1220,7 +1220,7 @@ void NPC::SpawnGridNodeNPC(const glm::vec4 &position, int32 grid_id, int32 grid_
npc_type->current_hp = 4000000;
npc_type->max_hp = 4000000;
npc_type->race = 2254;
npc_type->gender = NEUTER;
npc_type->gender = Gender::Neuter;
npc_type->class_ = 9;
npc_type->deity = 1;
npc_type->level = 200;
@@ -1997,7 +1997,7 @@ void NPC::Disarm(Client* client, int chance) {
if (zone->random.Int(0, 1000) <= chance) {
weapon = database.GetItem(equipment[eslot]);
if (weapon) {
if (!weapon->Magic && weapon->NoDrop == 255) {
if (!weapon->Magic && weapon->NoDrop != 0) {
int16 charges = -1;
ItemList::iterator cur, end;
cur = itemlist.begin();
@@ -3046,42 +3046,72 @@ void NPC::SendPayload(int payload_id, std::string payload_value)
}
NPC_Emote_Struct* NPC::GetNPCEmote(uint32 emoteid, uint8 event_) {
LinkedListIterator<NPC_Emote_Struct*> iterator(zone->NPCEmoteList);
iterator.Reset();
while(iterator.MoreElements())
{
NPC_Emote_Struct* nes = iterator.GetData();
std::vector<NPC_Emote_Struct *> emotes;
for (auto &e: zone->npc_emote_list) {
NPC_Emote_Struct *nes = e;
if (emoteid == nes->emoteid && event_ == nes->event_) {
return nes;
emotes.push_back(e);
}
iterator.Advance();
}
return nullptr;
if (emotes.empty()) {
return nullptr;
}
else if (emotes.size() == 1) {
return emotes[0];
}
int index = zone->random.Roll0(emotes.size());
return emotes[index];
}
void NPC::DoNPCEmote(uint8 event_, uint32 emoteid)
void NPC::DoNPCEmote(uint8 event_, uint32 emoteid, Mob* target)
{
if (emoteid == 0)
{
if (emoteid == 0) {
return;
}
NPC_Emote_Struct* nes = GetNPCEmote(emoteid,event_);
if(nes == nullptr)
{
NPC_Emote_Struct *nes = GetNPCEmote(emoteid, event_);
if (nes == nullptr) {
return;
}
if(emoteid == nes->emoteid)
{
if(nes->type == 1)
Emote("%s",nes->text);
else if(nes->type == 2)
Shout("%s",nes->text);
else if(nes->type == 3)
entity_list.MessageCloseString(this, true, 200, 10, GENERIC_STRING, nes->text);
else
Say("%s",nes->text);
std::string processed = nes->text;
Strings::FindReplace(processed, "$mname", GetCleanName());
Strings::FindReplace(processed, "$mracep", GetRacePlural() = GetClass());
Strings::FindReplace(processed, "$mrace", GetPlayerRaceName(GetRace()));
Strings::FindReplace(processed, "$mclass", GetClassIDName(GetClass()));
if (target) {
Strings::FindReplace(processed, "$name", target->GetCleanName());
Strings::FindReplace(processed, "$racep", GetRacePlural() = target->GetClass());
Strings::FindReplace(processed, "$race", GetPlayerRaceName(target->GetRace()));
Strings::FindReplace(processed, "$class", GetClassIDName(target->GetClass()));
}
else {
Strings::FindReplace(processed, "$name", "foe");
Strings::FindReplace(processed, "$race", "race");
Strings::FindReplace(processed, "$racep", "races");
Strings::FindReplace(processed, "$class", "class");
}
if (emoteid == nes->emoteid) {
if (event_ == EQ::constants::EmoteEventTypes::Hailed && target) {
DoQuestPause(target);
}
if (nes->type == 1) {
Emote("%s", processed.c_str());
}
else if (nes->type == 2) {
Shout("%s", processed.c_str());
}
else if (nes->type == 3) {
entity_list.MessageCloseString(this, true, 200, 10, GENERIC_STRING, processed.c_str());
}
else {
Say("%s", processed.c_str());
}
}
}
@@ -3691,25 +3721,25 @@ void NPC::ScaleNPC(uint8 npc_level, bool always_scale, bool override_special_abi
bool NPC::IsGuard()
{
switch (GetRace()) {
case RT_GUARD:
case Race::FreeportGuard:
if (GetTexture() == 1 || GetTexture() == 2)
return true;
break;
case RT_IKSAR_2:
case Race::IksarCitizen:
if (GetTexture() == 1)
return true;
break;
case RT_GUARD_2:
case RT_GUARD_3:
case RT_GUARD_4:
case RT_HUMAN_3:
case RT_HALFLING_2:
case RT_ERUDITE_2:
case RT_BARBARIAN_2:
case RT_DARK_ELF_2:
case RT_TROLL_2:
case Race::Felguard:
case Race::Fayguard:
case Race::VahShirGuard:
case Race::QeynosCitizen:
case Race::RivervaleCitizen:
case Race::EruditeCitizen:
case Race::HalasCitizen:
case Race::NeriakCitizen:
case Race::GrobbCitizen:
case OGGOK_CITIZEN:
case RT_DWARF_2:
case Race::KaladimCitizen:
return true;
default:
break;
+1 -1
View File
@@ -476,7 +476,7 @@ public:
const uint32 GetAltCurrencyType() const { return NPCTypedata->alt_currency_type; }
NPC_Emote_Struct* GetNPCEmote(uint32 emoteid, uint8 event_);
void DoNPCEmote(uint8 event_, uint32 emoteid);
void DoNPCEmote(uint8 event_, uint32 emoteid, Mob* target = nullptr);
bool CanTalk();
void DoQuestPause(Mob *other);
+1 -1
View File
@@ -529,7 +529,7 @@ void PathfinderWaypoint::ShowNode(const Node &n) {
npc_type->current_hp = 4000000;
npc_type->max_hp = 4000000;
npc_type->race = 2254;
npc_type->gender = NEUTER;
npc_type->gender = Gender::Neuter;
npc_type->class_ = 9;
npc_type->deity = 1;
npc_type->level = 75;
+37
View File
@@ -3028,6 +3028,41 @@ void Perl_Client_RemoveRadiantCrystals(Client* self, uint32 amount)
self->RemoveRadiantCrystals(amount);
}
void Perl_Client_SummonItemIntoInventory(Client* self, perl::reference table_ref)
{
perl::hash table = table_ref;
if (!table.exists("item_id") || !table.exists("charges")) {
return;
}
const uint32 item_id = table["item_id"];
const int16 charges = table["charges"];
const uint32 augment_one = table.exists("augment_one") ? table["augment_one"] : 0;
const uint32 augment_two = table.exists("augment_two") ? table["augment_two"] : 0;
const uint32 augment_three = table.exists("augment_three") ? table["augment_three"] : 0;
const uint32 augment_four = table.exists("augment_four") ? table["augment_four"] : 0;
const uint32 augment_five = table.exists("augment_five") ? table["augment_five"] : 0;
const uint32 augment_six = table.exists("augment_six") ? table["augment_six"] : 0;
const bool attuned = table.exists("attuned") ? table["attuned"] : false;
self->SummonItemIntoInventory(
item_id,
charges,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six,
attuned
);
}
bool Perl_Client_HasItemOnCorpse(Client* self, uint32 item_id)
{
return self->HasItemOnCorpse(item_id);
}
void perl_register_client()
{
perl::interpreter perl(PERL_GET_THX);
@@ -3290,6 +3325,7 @@ void perl_register_client()
package.add("HasDisciplineLearned", &Perl_Client_HasDisciplineLearned);
package.add("HasExpeditionLockout", &Perl_Client_HasExpeditionLockout);
package.add("HasItemEquippedByID", &Perl_Client_HasItemEquippedByID);
package.add("HasItemOnCorpse", &Perl_Client_HasItemOnCorpse);
package.add("HasPEQZoneFlag", &Perl_Client_HasPEQZoneFlag);
package.add("HasRecipeLearned", &Perl_Client_HasRecipeLearned);
package.add("HasSkill", &Perl_Client_HasSkill);
@@ -3535,6 +3571,7 @@ void perl_register_client()
package.add("SummonItem", (void(*)(Client*, uint32, int16, bool, uint32, uint32, uint32, uint32))&Perl_Client_SummonItem);
package.add("SummonItem", (void(*)(Client*, uint32, int16, bool, uint32, uint32, uint32, uint32, uint32))&Perl_Client_SummonItem);
package.add("SummonItem", (void(*)(Client*, uint32, int16, bool, uint32, uint32, uint32, uint32, uint32, uint16))&Perl_Client_SummonItem);
package.add("SummonItemIntoInventory", &Perl_Client_SummonItemIntoInventory);
package.add("TGB", &Perl_Client_TGB);
package.add("TakeMoneyFromPP", (bool(*)(Client*, uint64_t))&Perl_Client_TakeMoneyFromPP);
package.add("TakeMoneyFromPP", (bool(*)(Client*, uint64_t, bool))&Perl_Client_TakeMoneyFromPP);
+19 -1
View File
@@ -1344,6 +1344,21 @@ Mob* Perl_Mob_GetHateTop(Mob* self) // @categories Hate and Aggro
return self->GetHateTop();
}
Bot* Perl_Mob_GetHateTopBot(Mob* self) // @categories Hate and Aggro
{
return self->GetHateTopBot();
}
Client* Perl_Mob_GetHateTopClient(Mob* self) // @categories Hate and Aggro
{
return self->GetHateTopClient();
}
NPC* Perl_Mob_GetHateTopNPC(Mob* self) // @categories Hate and Aggro
{
return self->GetHateTopNPC();
}
Mob* Perl_Mob_GetHateDamageTop(Mob* self, Mob* other) // @categories Hate and Aggro
{
return self->GetHateDamageTop(other);
@@ -1844,7 +1859,7 @@ void Perl_Mob_RemoveAllAppearanceEffects(Mob* self) // @categories Script Utilit
.texture = self->GetTexture(),
}
);
self->ClearAppearenceEffects();
self->ClearAppearanceEffects();
}
void Perl_Mob_SetFlyMode(Mob* self, int flymode) // @categories Script Utility
@@ -3581,6 +3596,9 @@ void perl_register_mob()
package.add("GetHateRandomClient", &Perl_Mob_GetHateRandomClient);
package.add("GetHateRandomNPC", &Perl_Mob_GetHateRandomNPC);
package.add("GetHateTop", &Perl_Mob_GetHateTop);
package.add("GetHateTopBot", &Perl_Mob_GetHateTopBot);
package.add("GetHateTopClient", &Perl_Mob_GetHateTopClient);
package.add("GetHateTopNPC", &Perl_Mob_GetHateTopNPC);
package.add("GetHeading", &Perl_Mob_GetHeading);
package.add("GetHelmTexture", &Perl_Mob_GetHelmTexture);
package.add("GetHerosForgeModel", &Perl_Mob_GetHerosForgeModel);
+1 -1
View File
@@ -71,7 +71,7 @@ Petition::Petition(uint32 id)
{
petid = id;
charclass = Class::None;
charrace = RACE_DOUG_0;
charrace = Race::Doug;
charlevel = 0;
checkouts = 0;
unavailables = 0;
+8 -9
View File
@@ -2385,7 +2385,7 @@ int Mob::TryAssassinate(Mob *defender, EQ::skills::SkillType skillInUse)
}
void Mob::DoMeleeSkillAttackDmg(Mob *other, int32 weapon_damage, EQ::skills::SkillType skillinuse, int16 chance_mod,
int16 focus, bool CanRiposte, int ReuseTime)
int16 focus, bool can_riposte, int ReuseTime)
{
if (!CanDoSpecialAttack(other)) {
return;
@@ -2425,15 +2425,14 @@ void Mob::DoMeleeSkillAttackDmg(Mob *other, int32 weapon_damage, EQ::skills::Ski
}
DamageHitInfo my_hit {};
my_hit.base_damage = weapon_damage;
my_hit.min_damage = 0;
my_hit.damage_done = 1;
my_hit.skill = skillinuse;
my_hit.offense = offense(my_hit.skill);
my_hit.tohit = GetTotalToHit(my_hit.skill, chance_mod);
// slot range exclude ripe etc ...
my_hit.hand = CanRiposte ? EQ::invslot::slotRange : EQ::invslot::slotPrimary;
my_hit.base_damage = weapon_damage;
my_hit.min_damage = 0;
my_hit.damage_done = 1;
my_hit.skill = skillinuse;
my_hit.offense = offense(my_hit.skill);
my_hit.tohit = GetTotalToHit(my_hit.skill, chance_mod);
my_hit.hand = can_riposte ? EQ::invslot::slotPrimary : EQ::invslot::slotRange;
if (IsNPC()) {
my_hit.min_damage = CastToNPC()->GetMinDamage();
+24 -24
View File
@@ -7430,42 +7430,42 @@ bool Mob::PassCastRestriction(int value)
case IS_BIXIE:
case IS_BIXIE2:
if ((GetRace() == RT_BIXIE) ||(GetRace() == RT_BIXIE_2))
if ((GetRace() == Race::Bixie) ||(GetRace() == Race::Bixie2))
return true;
break;
case IS_HARPY:
if ((GetRace() == RT_HARPY) ||(GetRace() == RT_HARPY_2))
if ((GetRace() == Race::Harpy) ||(GetRace() == Race::Harpy2))
return true;
break;
case IS_GNOLL:
if ((GetRace() == RT_GNOLL) || (GetRace() == RT_GNOLL_2) || (GetRace() == RT_GNOLL_3))
if ((GetRace() == Race::Gnoll) || (GetRace() == Race::Gnoll2) || (GetRace() == Race::Gnoll3))
return true;
break;
case IS_SPORALI:
if ((GetRace() == RT_SPORALI) ||(GetRace() == RT_FUNGUSMAN))
if ((GetRace() == Race::Sporali) ||(GetRace() == Race::Fungusman))
return true;
break;
case IS_KOBOLD:
if ((GetRace() == RT_KOBOLD) ||(GetRace() == RT_KOBOLD_2))
if ((GetRace() == Race::Kobold) ||(GetRace() == Race::Kobold2))
return true;
break;
case IS_FROSTCRYPT_SHADE:
if (GetRace() == RT_GIANT_SHADE)
if (GetRace() == Race::GiantShade)
return true;
break;
case IS_DRAKKIN:
if (GetRace() == RT_DRAKKIN)
if (GetRace() == Race::Drakkin)
return true;
break;
case IS_UNDEAD_OR_VALDEHOLM_GIANT:
if (GetBodyType() == BT_Undead || GetRace() == RT_GIANT_12 || GetRace() == RT_GIANT_13)
if (GetBodyType() == BT_Undead || GetRace() == Race::Giant2 || GetRace() == Race::Giant3)
return true;
break;
@@ -7496,7 +7496,7 @@ bool Mob::PassCastRestriction(int value)
break;
case IS_FAE_OR_PIXIE:
if ((GetRace() == RT_PIXIE) || (GetRace() == RT_FAY_DRAKE))
if ((GetRace() == Race::Pixie) || (GetRace() == Race::FayDrake))
return true;
break;
@@ -7511,12 +7511,12 @@ bool Mob::PassCastRestriction(int value)
break;
case IS_CLOCKWORK_AND_HP_LESS_THAN_45_PCT:
if ((GetRace() == RT_GNOMEWORK || GetRace() == RACE_CLOCKWORK_GNOME_88) && (GetHPRatio() < 45))
if ((GetRace() == Race::Gnomework || GetRace() == Race::ClockworkGnome) && (GetHPRatio() < 45))
return true;
break;
case IS_WISP_AND_HP_LESS_THAN_10_PCT:
if ((GetRace() == RT_WILL_O_WISP) && (GetHPRatio() < 10))
if ((GetRace() == Race::Wisp) && (GetHPRatio() < 10))
return true;
break;
@@ -7889,12 +7889,12 @@ bool Mob::PassCastRestriction(int value)
break;
case IS_TREANT:
if (GetRace() == RT_TREANT || GetRace() == RT_TREANT_2 || GetRace() == RT_TREANT_3)
if (GetRace() == Race::Treant || GetRace() == Race::Treant2 || GetRace() == Race::Treant3)
return true;
break;
case IS_SCARECROW:
if (GetRace() == RT_SCARECROW || GetRace() == RT_SCARECROW_2)
if (GetRace() == Race::Scarecrow || GetRace() == Race::Scarecrow2)
return true;
break;
@@ -8077,33 +8077,33 @@ bool Mob::PassCastRestriction(int value)
}
case IS_CLIENT_AND_MALE_PLATE_USER:
if (IsClient() && GetGender() == MALE && IsPlateClass(GetClass()))
if (IsClient() && GetGender() == Gender::Male && IsPlateClass(GetClass()))
return true;
break;
case IS_CLEINT_AND_MALE_DRUID_ENCHANTER_MAGICIAN_NECROANCER_SHAMAN_OR_WIZARD:
if (IsClient() && GetGender() == MALE && (IsCasterClass(GetClass()) && GetClass() != Class::Cleric))
if (IsClient() && GetGender() == Gender::Male && (IsCasterClass(GetClass()) && GetClass() != Class::Cleric))
return true;
break;
case IS_CLIENT_AND_MALE_BEASTLORD_BERSERKER_MONK_RANGER_OR_ROGUE:
if (IsClient() && GetGender() == MALE &&
if (IsClient() && GetGender() == Gender::Male &&
(GetClass() == Class::Beastlord || GetClass() == Class::Berserker || GetClass() == Class::Monk || GetClass() == Class::Ranger || GetClass() == Class::Rogue))
return true;
break;
case IS_CLIENT_AND_FEMALE_PLATE_USER:
if (IsClient() && GetGender() == FEMALE && IsPlateClass(GetClass()))
if (IsClient() && GetGender() == Gender::Female && IsPlateClass(GetClass()))
return true;
break;
case IS_CLIENT_AND_FEMALE_DRUID_ENCHANTER_MAGICIAN_NECROANCER_SHAMAN_OR_WIZARD:
if (IsClient() && GetGender() == FEMALE && (IsCasterClass(GetClass()) && GetClass() != Class::Cleric))
if (IsClient() && GetGender() == Gender::Female && (IsCasterClass(GetClass()) && GetClass() != Class::Cleric))
return true;
break;
case IS_CLIENT_AND_FEMALE_BEASTLORD_BERSERKER_MONK_RANGER_OR_ROGUE:
if (IsClient() && GetGender() == FEMALE &&
if (IsClient() && GetGender() == Gender::Female &&
(GetClass() == Class::Beastlord || GetClass() == Class::Berserker || GetClass() == Class::Monk || GetClass() == Class::Ranger || GetClass() == Class::Rogue))
return true;
break;
@@ -10219,7 +10219,7 @@ void Mob::ApplySpellEffectIllusion(int32 spell_id, Mob *caster, int buffslot, in
if (base == -1) {
// Specific Gender Illusions
if (spell_id == SPELL_ILLUSION_MALE || spell_id == SPELL_ILLUSION_FEMALE) {
uint8 specific_gender = spell_id == SPELL_ILLUSION_MALE ? MALE : FEMALE;
uint8 specific_gender = spell_id == SPELL_ILLUSION_MALE ? Gender::Male : Gender::Female;
if (caster && caster->GetTarget()) {
SendIllusionPacket(
@@ -10234,7 +10234,7 @@ void Mob::ApplySpellEffectIllusion(int32 spell_id, Mob *caster, int buffslot, in
// Change Gender Illusions
else {
if (caster && caster->GetTarget()) {
uint8 opposite_gender = caster->GetTarget()->GetGender() == MALE ? FEMALE : MALE;
uint8 opposite_gender = caster->GetTarget()->GetGender() == Gender::Male ? Gender::Female : Gender::Male;
SendIllusionPacket(
AppearanceStruct{
@@ -10263,7 +10263,7 @@ void Mob::ApplySpellEffectIllusion(int32 spell_id, Mob *caster, int buffslot, in
gender_id
);
if (base != RACE_ELEMENTAL_75 && base != RACE_DRAKKIN_522) {
if (base != Race::Elemental && base != Race::Drakkin) {
if (max > 0) {
if (limit == 0) {
SendIllusionPacket(
@@ -10303,7 +10303,7 @@ void Mob::ApplySpellEffectIllusion(int32 spell_id, Mob *caster, int buffslot, in
}
);
}
} else if (base == RACE_ELEMENTAL_75){
} else if (base == Race::Elemental){
SendIllusionPacket(
AppearanceStruct{
.gender_id = static_cast<uint8>(gender_id),
@@ -10311,7 +10311,7 @@ void Mob::ApplySpellEffectIllusion(int32 spell_id, Mob *caster, int buffslot, in
.texture = static_cast<uint8>(limit),
}
);
} else if (base == RACE_DRAKKIN_522) {
} else if (base == Race::Drakkin) {
FaceChange_Struct f{
.haircolor = GetHairColor(),
.beardcolor = GetBeardColor(),
+1 -4
View File
@@ -2765,9 +2765,6 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, in
CastToBot()->SetItemReuseTimer(item->ID);
CastToBot()->SetIsUsingItemClick(false);
}
else {
GetOwner()->Message(Chat::Red, "%s says, 'Failed to set item reuse timer for %s.", GetCleanName());
}
}
if (IsNPC()) {
@@ -3885,7 +3882,7 @@ bool Mob::SpellOnTarget(
// Prevent double invising, which made you uninvised
// Not sure if all 3 should be stacking
//This is not live like behavior (~Kayen confirmed 2/2/22)
if (!RuleB(Spells, AllowDoubleInvis)) {
if (!RuleB(Spells, AllowDoubleInvis) && !IsActiveBardSong(spell_id)) {
if (IsEffectInSpell(spell_id, SE_Invisibility)) {
if (spelltar->invisible) {
spelltar->MessageString(Chat::SpellFailure, ALREADY_INVIS, GetCleanName());
+4 -2
View File
@@ -52,6 +52,8 @@ bool TaskManager::LoadTasks(int single_task)
task_query_filter = fmt::format("id > 0");
}
task_query_filter += " AND enabled = 1";
// load task level data
auto repo_tasks = TasksRepository::GetWhere(content_db, task_query_filter);
m_task_data.reserve(repo_tasks.size());
@@ -127,7 +129,7 @@ bool TaskManager::LoadTasks(int single_task)
);
}
LogTasks("Loaded [{}] Tasks", repo_tasks.size());
LogInfo("Loaded [{}] task(s)", repo_tasks.size());
std::string activities_query_filter = fmt::format(
"taskid = {} and activityid < {} ORDER BY taskid, activityid ASC",
@@ -256,7 +258,7 @@ bool TaskManager::LoadTasks(int single_task)
task_data->activity_count++;
}
LogTasks("Loaded [{}] Task Activities", task_activities.size());
LogInfo("Loaded [{}] task activities", task_activities.size());
return true;
}
+2 -2
View File
@@ -152,11 +152,11 @@ bool TitleManager::IsClientEligibleForTitle(Client *client, TitleEntry title)
return false;
}
if (title.gender_id >= 0 && client->GetBaseGender() != title.gender_id) {
if (title.gender_id >= Gender::Male && client->GetBaseGender() != title.gender_id) {
return false;
}
if (title.class_id >= 0 && client->GetBaseClass() != title.class_id) {
if (title.class_id >= Class::None && client->GetBaseClass() != title.class_id) {
return false;
}
+1 -1
View File
@@ -1147,7 +1147,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) {
LogTradeskills("Tradeskill failed");
if (GetGroup())
{
entity_list.MessageGroup(this, true, Chat::Skills,"%s was unsuccessful in %s tradeskill attempt.",GetName(),GetGender() == 0 ? "his" : GetGender() == 1 ? "her" : "its");
entity_list.MessageGroup(this, true, Chat::Skills,"%s was unsuccessful in %s tradeskill attempt.",GetName(),GetGender() == Gender::Male ? "his" : GetGender() == Gender::Female ? "her" : "its");
}
+1 -1
View File
@@ -510,7 +510,7 @@ void Trap::CreateHiddenTrigger()
make_npc->runspeed = 0.0f;
make_npc->bodytype = BT_Special;
make_npc->race = 127;
make_npc->gender = MALE;
make_npc->gender = Gender::Male;
make_npc->loottable_id = 0;
make_npc->npc_spells_id = 0;
make_npc->d_melee_texture1 = 0;
+46 -46
View File
@@ -880,118 +880,118 @@ float Mob::GetZOffset() const {
float offset = 3.125f;
switch (GetModel()) {
case RACE_BASILISK_436:
case Race::Basilisk:
offset = 0.577f;
break;
case RACE_DRAKE_430:
case Race::Drake2:
offset = 0.5f;
break;
case RACE_DRAKE_432:
case Race::Drake3:
offset = 1.9f;
break;
case RACE_DRAGON_435:
case Race::Dragon:
offset = 0.93f;
break;
case RACE_LAVA_SPIDER_450:
case Race::LavaSpider:
offset = 0.938f;
break;
case RACE_ALLIGATOR_479:
case Race::Alligator2:
offset = 0.8f;
break;
case RACE_LAVA_SPIDER_QUEEN_451:
case Race::LavaSpiderQueen:
offset = 0.816f;
break;
case RACE_DRAGON_437:
case Race::Dragon2:
offset = 0.527f;
break;
case RACE_PUMA_439:
case Race::Puma2:
offset = 1.536f;
break;
case RACE_RAT_415:
case Race::Rat:
offset = 1.0f;
break;
case RACE_DRAGON_438:
case RACE_DRAGON_452:
case Race::Dragon3:
case Race::Dragon4:
offset = 0.776f;
break;
case RACE_SPIDER_QUEEN_441:
case Race::SpiderQueen:
offset = 0.816f;
break;
case RACE_SPIDER_440:
case Race::Spider:
offset = 0.938f;
break;
case RACE_IMP_46:
case RACE_SNAKE_468:
case RACE_CORATHUS_459:
case Race::Imp:
case Race::Snake:
case Race::Corathus:
offset = 1.0f;
break;
case RACE_DRACHNID_COCOON_462:
case Race::DrachnidCocoon:
offset = 1.5f;
break;
case RACE_DRAGON_530:
case Race::Dragon5:
offset = 1.2f;
break;
case RACE_GOO_549:
case RACE_GOO_548:
case Race::Goo4:
case Race::Goo3:
offset = 0.5f;
break;
case RACE_GOO_547:
case Race::Goo2:
offset = 0.5f;
break;
case RACE_DRACOLICH_604:
case Race::Dracolich:
offset = 1.2f;
break;
case RACE_TELMIRA_653:
case Race::Telmira:
offset = 5.9f;
break;
case RACE_MORELL_THULE_658:
case Race::MorellThule:
offset = 4.0f;
break;
case RACE_ARMOR_OF_MARR_323:
case RACE_AMYGDALAN_663:
case Race::AnimatedArmor:
case Race::Amygdalan:
offset = 5.0f;
break;
case RACE_SPECTRAL_IKSAR_147:
case RACE_SANDMAN_664:
case Race::IksarSpirit:
case Race::Sandman:
offset = 4.0f;
break;
case RACE_LAVA_DRAGON_49:
case RACE_ALARAN_SENTRY_STONE_703:
case Race::LavaDragon:
case Race::AlaranSentryStone:
offset = 9.0f;
break;
case RACE_RABBIT_668:
case Race::Rabbit:
offset = 5.0f;
break;
case RACE_WURM_158:
case RACE_BLIND_DREAMER_669:
case Race::Wurm:
case Race::BlindDreamer:
offset = 7.0f;
break;
case RACE_SIREN_187:
case RACE_HALAS_CITIZEN_90:
case RACE_OTTERMAN_190:
case Race::Siren:
case Race::HalasCitizen:
case Race::Othmir:
offset = .5f;
break;
case RACE_COLDAIN_183:
case Race::Coldain:
offset = .6f;
break;
case RACE_WEREWOLF_14:
case Race::Werewolf:
offset = 1.2f;
break;
case RACE_DWARF_8:
case Race::Dwarf:
offset = .7f;
break;
case RACE_HORSE_216:
case Race::Horse:
offset = 1.4f;
break;
case RACE_ENCHANTED_ARMOR_175:
case RACE_TIGER_63:
case Race::EnchantedArmor:
case Race::Tiger:
offset = 1.75f;
break;
case RACE_STATUE_OF_RALLOS_ZEK_66:
case Race::StatueOfRallosZek:
offset = 1.0f;
break;
case RACE_GORAL_687:
case RACE_SELYRAH_686:
case Race::Goral:
case Race::Selyrah:
offset = 2.0f;
break;
default:
+1 -1
View File
@@ -2015,7 +2015,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
{
if (zone && zone->IsLoaded()) {
zone->SendReloadMessage("NPC Emotes");
zone->LoadNPCEmotes(&zone->NPCEmoteList);
zone->LoadNPCEmotes(&zone->npc_emote_list);
}
break;
}
+7 -11
View File
@@ -182,10 +182,6 @@ bool Zone::LoadZoneObjects()
ContentFilterCriteria::apply()
)
);
if (l.empty()) {
LogWarning("No Objects to load for Zone [{}] Version [{}]", zoneid, instanceversion);
return false;
}
for (const auto &e : l) {
if (e.type == ObjectTypes::StaticLocked) {
@@ -1056,7 +1052,7 @@ Zone::~Zone() {
safe_delete_array(short_name);
safe_delete_array(long_name);
safe_delete(Weather_Timer);
NPCEmoteList.Clear();
npc_emote_list.clear();
zone_point_list.Clear();
entity_list.Clear();
ClearBlockedSpells();
@@ -1152,7 +1148,7 @@ bool Zone::Init(bool is_static) {
LoadLDoNTrapEntries();
LoadVeteranRewards();
LoadAlternateCurrencies();
LoadNPCEmotes(&NPCEmoteList);
LoadNPCEmotes(&npc_emote_list);
LoadAlternateAdvancement();
@@ -1233,8 +1229,8 @@ void Zone::ReloadStaticData() {
LoadVeteranRewards();
LoadAlternateCurrencies();
NPCEmoteList.Clear();
LoadNPCEmotes(&NPCEmoteList);
npc_emote_list.clear();
LoadNPCEmotes(&npc_emote_list);
//load the zone config file.
if (!LoadZoneCFG(GetShortName(), GetInstanceVersion())) { // try loading the zone name...
@@ -2548,10 +2544,10 @@ void Zone::DoAdventureActions()
}
void Zone::LoadNPCEmotes(LinkedList<NPC_Emote_Struct*>* NPCEmoteList)
void Zone::LoadNPCEmotes(std::vector<NPC_Emote_Struct*>* NPCEmoteList)
{
NPCEmoteList->Clear();
NPCEmoteList->clear();
const std::string query = "SELECT emoteid, event_, type, text FROM npc_emotes";
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
@@ -2565,7 +2561,7 @@ void Zone::LoadNPCEmotes(LinkedList<NPC_Emote_Struct*>* NPCEmoteList)
nes->event_ = Strings::ToInt(row[1]);
nes->type = Strings::ToInt(row[2]);
strn0cpy(nes->text, row[3], sizeof(nes->text));
NPCEmoteList->Insert(nes);
NPCEmoteList->push_back(nes);
}
LogInfo("Loaded [{}] npc emotes", Strings::Commify(results.RowCount()));
+2 -2
View File
@@ -185,7 +185,7 @@ public:
DynamicZone *GetDynamicZone();
IPathfinder *pathing;
LinkedList<NPC_Emote_Struct *> NPCEmoteList;
std::vector<NPC_Emote_Struct *> npc_emote_list;
LinkedList<Spawn2 *> spawn2_list;
LinkedList<ZonePoint *> zone_point_list;
std::vector<ZonePointsRepository::ZonePoints> virtual_zone_point_list;
@@ -282,7 +282,7 @@ public:
void LoadMercSpells();
void LoadMercTemplates();
void LoadNewMerchantData(uint32 merchantid);
void LoadNPCEmotes(LinkedList<NPC_Emote_Struct *> *NPCEmoteList);
void LoadNPCEmotes(std::vector<NPC_Emote_Struct *> *NPCEmoteList);
void LoadTempMerchantData();
void LoadTickItems();
void LoadVeteranRewards();
+8 -7
View File
@@ -4123,15 +4123,16 @@ uint32 ZoneDatabase::GetCharacterCorpseID(uint32 char_id, uint8 corpse) {
return 0;
}
uint32 ZoneDatabase::GetCharacterCorpseItemAt(uint32 corpse_id, uint16 slotid) {
Corpse* tmp = LoadCharacterCorpse(corpse_id);
uint32 itemid = 0;
uint32 ZoneDatabase::GetCharacterCorpseItemAt(uint32 corpse_id, uint16 slot_id) {
Corpse* c = LoadCharacterCorpse(corpse_id);
uint32 item_id = 0;
if (tmp) {
itemid = tmp->GetWornItem(slotid);
tmp->DepopPlayerCorpse();
if (c) {
item_id = c->GetWornItem(slot_id);
c->DepopPlayerCorpse();
}
return itemid;
return item_id;
}
bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, CharacterCorpseEntry& corpse){
+2 -2
View File
@@ -340,7 +340,7 @@ namespace BeastlordPetData {
uint16 race_id = WOLF;
uint8 texture = 0;
uint8 helm_texture = 0;
uint8 gender = NEUTER;
uint8 gender = Gender::Neuter;
float size_modifier = 1.0f;
uint8 face = 0;
};
@@ -498,7 +498,7 @@ public:
uint32 GetFirstCorpseID(uint32 char_id);
uint32 GetCharacterCorpseCount(uint32 char_id);
uint32 GetCharacterCorpseID(uint32 char_id, uint8 corpse);
uint32 GetCharacterCorpseItemAt(uint32 corpse_id, uint16 slotid);
uint32 GetCharacterCorpseItemAt(uint32 corpse_id, uint16 slot_id);
uint32 GetPlayerCorpseTimeLeft(uint8 corpse, uint8 type);
void SendCharacterCorpseToNonInstance(uint32 corpse_db_id);