Compare commits

..

20 Commits

Author SHA1 Message Date
Akkadius c0a88de4fb pch 2023-12-16 21:03:58 -06:00
Akkadius 5117843089 Incremental 2023-12-16 19:44:33 -06:00
Akkadius 77c7ea191a Win gate 2023-12-16 19:36:42 -06:00
Akkadius 527798db92 Pull out includes in common 2023-12-16 19:28:55 -06:00
Akkadius 3ea644b732 Remove header only 2023-12-16 19:23:08 -06:00
Akkadius 3850343254 Update eqemu_logsys.h 2023-12-16 19:15:06 -06:00
Akkadius 77597c7868 !!!!! 2023-12-16 19:03:39 -06:00
Akkadius 8a0ef65373 WHAT 2023-12-16 18:59:11 -06:00
Akkadius 75d9e6ffaf FMT test 2023-12-16 18:54:25 -06:00
Akkadius e9ca2b4202 Without lua ? 2023-12-16 18:42:11 -06:00
Akkadius a29a2321f1 Without fmt ? 2023-12-16 18:33:15 -06:00
Akkadius 5ff9407e26 Test 2023-12-16 18:13:43 -06:00
Akkadius 20e135fbc4 PCH main zone primitives 2023-12-16 18:05:20 -06:00
Akkadius e21c386bda Lua headers 2023-12-16 18:00:04 -06:00
Akkadius 73a85135b2 Another one 2023-12-16 17:55:02 -06:00
Akkadius 87b1dc4b03 Another one 2023-12-16 17:48:22 -06:00
Akkadius b2bf1d2b6f Different test 2023-12-16 17:37:58 -06:00
Akkadius 4a8b89f93a GCC test 2023-12-16 17:28:31 -06:00
Akkadius 1cccca45a0 Another run 2023-12-16 17:18:54 -06:00
Akkadius 8af4fb2330 Experiment with PCH 2023-12-16 17:11:23 -06:00
136 changed files with 3715 additions and 15095 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ volumes:
steps: steps:
- name: Build Linux X64 - name: Build Linux X64
image: akkadius/eqemu-server:v14 image: akkadius/eqemu-server:v13
environment: environment:
GITHUB_TOKEN: GITHUB_TOKEN:
from_secret: GH_RELEASE_GITHUB_API_TOKEN from_secret: GH_RELEASE_GITHUB_API_TOKEN
-76
View File
@@ -1,79 +1,3 @@
## [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
* Add ScanCloseMobs support to fix AEs ([#3786](https://github.com/EQEmu/Server/pull/3786)) @nytmyr 2023-12-18
* Expand ^itemuse options ([#3756](https://github.com/EQEmu/Server/pull/3756)) @nytmyr 2023-12-17
* Fix ^defensive from checking aggressive disciplines. ([#3787](https://github.com/EQEmu/Server/pull/3787)) @nytmyr 2023-12-18
* Fix ^oo autodefend from sending bots/pets to invalid haters ([#3772](https://github.com/EQEmu/Server/pull/3772)) @nytmyr 2023-12-16
* Fix unnecessary failed to save timer error ([#3788](https://github.com/EQEmu/Server/pull/3788)) @nytmyr 2023-12-18
* [Quest API] Add ^clickitem, ^timer, fix GetBestBotSpellForCure ([#3755](https://github.com/EQEmu/Server/pull/3755)) @nytmyr 2023-12-17
### CI
* Switch to use clang for Linux builds (speed) ([#3777](https://github.com/EQEmu/Server/pull/3777)) @Akkadius 2023-12-17
### Compilation
* Use pre-compiled headers for Windows (speed) ([#3778](https://github.com/EQEmu/Server/pull/3778)) @Akkadius 2023-12-18
### Fixes
* Drop Invisibility when hit by traps ([#3785](https://github.com/EQEmu/Server/pull/3785)) @Kinglykrab 2023-12-18
* Fix NPCs routing to 0.0, 0.0 on #summon ([#3780](https://github.com/EQEmu/Server/pull/3780)) @Kinglykrab 2023-12-18
* Fix bad merge @Akkadius 2023-12-17
* Fix issue with HOTBonusHealingSplitOverDuration Rule ([#3776](https://github.com/EQEmu/Server/pull/3776)) @Kinglykrab 2023-12-17
* Fixed the discrepacy with time using command #time and in quests. ([#3767](https://github.com/EQEmu/Server/pull/3767)) @regneq 2023-12-17
* Send Entity ID in Death Events to resolve #3721 ([#3779](https://github.com/EQEmu/Server/pull/3779)) @Kinglykrab 2023-12-18
### Quest API
* Add EVENT_ALT_CURRENCY_GAIN and EVENT_ALT_CURRENCY_LOSS to Perl/Lua ([#3734](https://github.com/EQEmu/Server/pull/3734)) @Kinglykrab 2023-12-17
* Add EVENT_CRYSTAL_GAIN and EVENT_CRYSTAL_LOSS to Perl/Lua ([#3735](https://github.com/EQEmu/Server/pull/3735)) @Kinglykrab 2023-12-17
* Add EVENT_LDON_POINTS_GAIN and EVENT_LDON_POINTS_LOSS to Perl/Lua ([#3742](https://github.com/EQEmu/Server/pull/3742)) @Kinglykrab 2023-12-17
* Add EVENT_LEVEL_UP and EVENT_LEVEL_DOWN to Bots ([#3750](https://github.com/EQEmu/Server/pull/3750)) @Kinglykrab 2023-12-17
* Add EVENT_LOOT_ADDED to Perl/Lua ([#3739](https://github.com/EQEmu/Server/pull/3739)) @Kinglykrab 2023-12-17
* Add GetNPCAggro() and SetNPCAggro() to Perl/Lua ([#3781](https://github.com/EQEmu/Server/pull/3781)) @Kinglykrab 2023-12-18
## [22.36.0] - 12/16/2023 ## [22.36.0] - 12/16/2023
### Bots ### Bots
-1
View File
@@ -17,7 +17,6 @@ SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF) SET(CMAKE_CXX_EXTENSIONS OFF)
OPTION(EQEMU_BUILD_STATIC "Build with static linking" OFF) OPTION(EQEMU_BUILD_STATIC "Build with static linking" OFF)
OPTION(EQEMU_BUILD_PCH "Build with precompiled headers (Windows)" ON)
IF (EQEMU_BUILD_STATIC) IF (EQEMU_BUILD_STATIC)
SET(BUILD_SHARED_LIBS OFF) SET(BUILD_SHARED_LIBS OFF)
+4 -3
View File
@@ -787,13 +787,14 @@ INCLUDE_DIRECTORIES(Patches SocketLib StackWalker)
ADD_LIBRARY(common ${common_sources} ${common_headers} ${repositories}) ADD_LIBRARY(common ${common_sources} ${common_headers} ${repositories})
IF(WIN32)
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch.h)
ENDIF(WIN32)
IF (UNIX) IF (UNIX)
SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result)
SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0) SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0)
ENDIF (UNIX) ENDIF (UNIX)
IF (WIN32 AND EQEMU_BUILD_PCH)
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch.h)
ENDIF()
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
+1 -1
View File
@@ -15,7 +15,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <fmt/format.h> #include <fmt/core.h>
#include "../common/global_define.h" #include "../common/global_define.h"
#include "../common/classes.h" #include "../common/classes.h"
#include "data_verification.h" #include "data_verification.h"
+1 -1
View File
@@ -18,7 +18,7 @@
* *
*/ */
#include <fmt/format.h> #include <fmt/core.h>
#include "eqemu_command_handler.h" #include "eqemu_command_handler.h"
#include "terminal_color.hpp" #include "terminal_color.hpp"
#include "../platform.h" #include "../platform.h"
@@ -5133,16 +5133,6 @@ CHANGE COLUMN `slot` `inventory_slot` mediumint(9) NOT NULL DEFAULT -1 AFTER `st
ALTER TABLE `starting_items` ALTER TABLE `starting_items`
CHANGE COLUMN `temporary` `class_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `id`; CHANGE COLUMN `temporary` `class_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `id`;
)"
},
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`;
)" )"
} }
@@ -82,28 +82,6 @@ CREATE TABLE `bot_starting_items` (
`content_flags_disabled` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL, `content_flags_disabled` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci; ) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci;
)",
},
ManifestEntry{
.version = 9041,
.description = "2023_12_04_bot_timers.sql",
.check = "SHOW COLUMNS FROM `bot_timers` LIKE 'recast_time'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `bot_timers`
ADD COLUMN `recast_time` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `timer_value`,
ADD COLUMN `is_spell` TINYINT(2) UNSIGNED NOT NULL DEFAULT 0 AFTER `recast_time`,
ADD COLUMN `is_disc` TINYINT(2) UNSIGNED NOT NULL DEFAULT 0 AFTER `is_spell`,
ADD COLUMN `spell_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `is_disc`,
ADD COLUMN `is_item` TINYINT(2) UNSIGNED NOT NULL DEFAULT 0 AFTER `spell_id`,
ADD COLUMN `item_id` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `is_item`;
ALTER TABLE `bot_timers`
DROP FOREIGN KEY `FK_bot_timers_1`;
ALTER TABLE `bot_timers`
DROP PRIMARY KEY;
ALTER TABLE `bot_timers`
ADD PRIMARY KEY (`bot_id`, `timer_id`, `spell_id`, `item_id`);
)" )"
} }
// -- template; copy/paste this when you need to create a new entry // -- template; copy/paste this when you need to create a new entry
-6
View File
@@ -124,12 +124,6 @@ struct LDoNTrapTemplate
uint8 locked; uint8 locked;
}; };
enum CrystalReclaimTypes
{
Ebon = 5,
Radiant = 4,
};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
+1 -1
View File
@@ -22,7 +22,7 @@
#include "linked_list.h" #include "linked_list.h"
#include "path_manager.h" #include "path_manager.h"
#include <fstream> #include <fstream>
#include <fmt/format.h> #include <fmt/core.h>
struct LoginConfig { struct LoginConfig {
std::string LoginHost; std::string LoginHost;
+2 -1
View File
@@ -33,7 +33,8 @@
#endif #endif
#endif #endif
#include <fmt/format.h> #undef FMT_HEADER_ONLY
#include <fmt/core.h>
#include "types.h" #include "types.h"
namespace Logs { namespace Logs {
@@ -2,7 +2,7 @@
#include "../repositories/character_data_repository.h" #include "../repositories/character_data_repository.h"
#include "../json/json_archive_single_line.h" #include "../json/json_archive_single_line.h"
#include <vector> #include <vector>
#include <fmt/format.h> #include <fmt/core.h>
#include <cereal/archives/json.hpp> #include <cereal/archives/json.hpp>
#include <cereal/types/vector.hpp> #include <cereal/types/vector.hpp>
+1
View File
@@ -22,6 +22,7 @@
#include "../common/strings.h" #include "../common/strings.h"
#include "../common/rulesys.h" #include "../common/rulesys.h"
#include "../common/util/uuid.h" #include "../common/util/uuid.h"
#include <fmt/core.h>
#include <fmt/format.h> #include <fmt/format.h>
const char* const DZ_REPLAY_TIMER_NAME = "Replay Timer"; // see December 14, 2016 patch notes const char* const DZ_REPLAY_TIMER_NAME = "Replay Timer"; // see December 14, 2016 patch notes
+2 -2
View File
@@ -96,12 +96,12 @@ bool IsOfEqualRace(int r1, int r2)
// TODO: add more values // TODO: add more values
switch (r1) { switch (r1) {
case DARK_ELF: case DARK_ELF:
if (r2 == Race::NeriakCitizen) { if (r2 == RACE_NERIAK_CITIZEN_77) {
return true; return true;
} }
break; break;
case BARBARIAN: case BARBARIAN:
if (r2 == Race::HalasCitizen) { if (r2 == RACE_HALAS_CITIZEN_90) {
return true; return true;
} }
} }
+1 -1
View File
@@ -35,7 +35,7 @@
#endif #endif
#include <fmt/format.h> #include <fmt/core.h>
#include <filesystem> #include <filesystem>
#include <iostream> #include <iostream>
+17 -18
View File
@@ -801,35 +801,34 @@ int16 EQ::InventoryProfile::HasItemByLoreGroup(uint32 loregroup, uint8 where)
// Returns slot_id when there's one available, else SLOT_INVALID // 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) int16 EQ::InventoryProfile::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow)
{ {
const int16 last_bag_slot = RuleI(World, ExpansionSettings) & EQ::expansions::bitHoT ? EQ::invslot::slotGeneral10 : EQ::invslot::slotGeneral8; // Check basic inventory
for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) {
for (int16 i = invslot::GENERAL_BEGIN; i <= last_bag_slot; i++) { // Check basic inventory if ((((uint64)1 << i) & m_lookup->PossessionsBitmask) == 0)
if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) {
continue; continue;
}
if (!GetItem(i)) { if (!GetItem(i))
return i; // Found available slot in personal inventory // Found available slot in personal inventory
} return i;
} }
if (!for_bag) { if (!for_bag) {
for (int16 i = invslot::GENERAL_BEGIN; i <= last_bag_slot; i++) { for (int16 i = invslot::GENERAL_BEGIN; i <= invslot::GENERAL_END; i++) {
if ((((uint64) 1 << i) & m_lookup->PossessionsBitmask) == 0) { if ((((uint64)1 << i) & m_lookup->PossessionsBitmask) == 0)
continue; continue;
}
const auto *inst = GetItem(i); const ItemInstance* inst = GetItem(i);
if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size) { if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size)
if (inst->GetItem()->BagType == item::BagTypeQuiver && {
inst->GetItem()->ItemType != item::ItemTypeArrow) { if (inst->GetItem()->BagType == item::BagTypeQuiver && inst->GetItem()->ItemType != item::ItemTypeArrow)
{
continue; continue;
} }
const int16 base_slot_id = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN); int16 base_slot_id = InventoryProfile::CalcSlotId(i, invbag::SLOT_BEGIN);
const uint8 slots = inst->GetItem()->BagSlots; uint8 slots = inst->GetItem()->BagSlots;
for (uint8 j = invbag::SLOT_BEGIN; j < slots; j++) { uint8 j;
for (j = invbag::SLOT_BEGIN; j<slots; j++) {
if (!GetItem(base_slot_id + j)) { if (!GetItem(base_slot_id + j)) {
// Found available slot within bag // Found available slot within bag
return (base_slot_id + j); return (base_slot_id + j);
+1 -1
View File
@@ -132,7 +132,7 @@ namespace EQ
// Swap items in inventory // Swap items in inventory
enum SwapItemFailState : int8 { swapInvalid = -1, swapPass = 0, swapNotAllowed, swapNullData, swapRaceClass, swapDeity, swapLevel }; 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, 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_0, uint8 class_id = Class::None, uint16 deity_id = deity::DeityType::DeityUnknown, uint8 level = 0);
// Remove item from inventory // Remove item from inventory
bool DeleteItem(int16 slot_id, int16 quantity = 0); bool DeleteItem(int16 slot_id, int16 quantity = 0);
+1 -1
View File
@@ -19,7 +19,7 @@
*/ */
#include <cstring> #include <cstring>
#include <fmt/format.h> #include <fmt/core.h>
#include <csignal> #include <csignal>
#include <vector> #include <vector>
#include "ip_util.h" #include "ip_util.h"
+1 -1
View File
@@ -1273,7 +1273,7 @@ int EQ::ItemInstance::GetItemBaneDamageBody(bool augments) const
int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const int EQ::ItemInstance::GetItemBaneDamageRace(bool augments) const
{ {
int race = Race::Doug; int race = RACE_DOUG_0;
const auto item = GetItem(); const auto item = GetItem();
if (item) { if (item) {
race = item->BaneDmgRace; race = item->BaneDmgRace;
+1 -1
View File
@@ -1,6 +1,6 @@
#include "console_server.h" #include "console_server.h"
#include "../strings.h" #include "../strings.h"
#include <fmt/format.h> #include <fmt/core.h>
EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port) EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port)
{ {
+1 -1
View File
@@ -4,7 +4,7 @@
#include "../eqemu_logsys.h" #include "../eqemu_logsys.h"
#include "../servertalk.h" #include "../servertalk.h"
#include "../rulesys.h" #include "../rulesys.h"
#include <fmt/format.h> #include <fmt/core.h>
EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr<TCPConnection> connection) EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr<TCPConnection> connection)
{ {
+1 -1
View File
@@ -5,7 +5,7 @@
#include "crc32.h" #include "crc32.h"
#include "../eqemu_logsys.h" #include "../eqemu_logsys.h"
#include <zlib.h> #include <zlib.h>
#include <fmt/format.h> #include <fmt/core.h>
#include <sstream> #include <sstream>
EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager() EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager()
+1 -1
View File
@@ -1,7 +1,7 @@
#include "packet.h" #include "packet.h"
#include "endian.h" #include "endian.h"
#include <cctype> #include <cctype>
#include <fmt/format.h> #include <fmt/core.h>
void EQ::Net::Packet::PutInt8(size_t offset, int8_t value) void EQ::Net::Packet::PutInt8(size_t offset, int8_t value)
{ {
+1 -1
View File
@@ -1,7 +1,7 @@
#include "websocket_server.h" #include "websocket_server.h"
#include "../event/event_loop.h" #include "../event/event_loop.h"
#include "../event/timer.h" #include "../event/timer.h"
#include <fmt/format.h> #include <fmt/core.h>
#include <map> #include <map>
#include <unordered_set> #include <unordered_set>
#include <array> #include <array>
+1 -1
View File
@@ -3,7 +3,7 @@
#include "../timer.h" #include "../timer.h"
#include "../util/uuid.h" #include "../util/uuid.h"
#include <sstream> #include <sstream>
#include <fmt/format.h> #include <fmt/core.h>
struct EQ::Net::WebsocketServerConnection::Impl { struct EQ::Net::WebsocketServerConnection::Impl {
WebsocketServer *parent; WebsocketServer *parent;
+4 -4
View File
@@ -3868,8 +3868,8 @@ namespace RoF
} }
float SpawnSize = emu->size; float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) || if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)) (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
) )
{ {
PacketSize += 60; PacketSize += 60;
@@ -4002,8 +4002,8 @@ namespace RoF
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) || if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin) (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
) )
{ {
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k) for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
+4 -4
View File
@@ -4007,8 +4007,8 @@ namespace RoF2
} }
float SpawnSize = emu->size; float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) || if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)) (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
) )
{ {
PacketSize += 60; 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); // These do something with OP_WeaponEquip1
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^ VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) || if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin) (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
) )
{ {
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k) for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
+6 -6
View File
@@ -2507,8 +2507,8 @@ namespace SoD
} }
float SpawnSize = emu->size; float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) || if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)) (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
) )
{ {
PacketSize -= (sizeof(structs::Texture_Struct) * EQ::textures::materialCount); PacketSize -= (sizeof(structs::Texture_Struct) * EQ::textures::materialCount);
@@ -2706,8 +2706,8 @@ namespace SoD
Buffer += sizeof(structs::Spawn_Struct_Position); Buffer += sizeof(structs::Spawn_Struct_Position);
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) || if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin) (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
) )
{ {
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k) for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
@@ -2733,8 +2733,8 @@ namespace SoD
} }
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) || if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin) (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
) )
{ {
structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer;
+6 -6
View File
@@ -2779,8 +2779,8 @@ namespace UF
} }
float SpawnSize = emu->size; float SpawnSize = emu->size;
if (!((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) || if (!((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin)) (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522))
) )
{ {
PacketSize -= (sizeof(structs::Texture_Struct) * EQ::textures::materialCount); PacketSize -= (sizeof(structs::Texture_Struct) * EQ::textures::materialCount);
@@ -2982,8 +2982,8 @@ namespace UF
Buffer += sizeof(structs::Spawn_Struct_Position); Buffer += sizeof(structs::Spawn_Struct_Position);
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) || if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin) (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
) )
{ {
for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k) for (k = EQ::textures::textureBegin; k < EQ::textures::materialCount; ++k)
@@ -3018,8 +3018,8 @@ namespace UF
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
} }
if ((emu->NPC == 0) || (emu->race <= Race::Gnome) || (emu->race == Race::Iksar) || if ((emu->NPC == 0) || (emu->race <= RACE_GNOME_12) || (emu->race == RACE_IKSAR_128) ||
(emu->race == Race::VahShir) || (emu->race == Race::Froglok2) || (emu->race == Race::Drakkin) (emu->race == RACE_VAH_SHIR_130) || (emu->race == RACE_FROGLOK_330) || (emu->race == RACE_DRAKKIN_522)
) )
{ {
structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer;
-5
View File
@@ -27,8 +27,3 @@
// fmt // fmt
#include <fmt/format.h> #include <fmt/format.h>
// lua
#include "lua.hpp"
#include <luabind/luabind.hpp>
#include <luabind/object.hpp>
+1 -1
View File
@@ -22,7 +22,7 @@
#include <string> #include <string>
#include <list> #include <list>
#include <fmt/format.h> #include <fmt/core.h>
class DBcore; class DBcore;
+755 -755
View File
File diff suppressed because it is too large Load Diff
+1471 -739
View File
File diff suppressed because it is too large Load Diff
@@ -16,19 +16,12 @@
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
class BaseBotTimersRepository { class BaseBotTimersRepository {
public: public:
struct BotTimers { struct BotTimers {
uint32_t bot_id; uint32_t bot_id;
uint32_t timer_id; uint32_t timer_id;
uint32_t timer_value; uint32_t timer_value;
uint32_t recast_time;
uint8_t is_spell;
uint8_t is_disc;
uint32_t spell_id;
uint8_t is_item;
uint32_t item_id;
}; };
static std::string PrimaryKey() static std::string PrimaryKey()
@@ -42,12 +35,6 @@ public:
"bot_id", "bot_id",
"timer_id", "timer_id",
"timer_value", "timer_value",
"recast_time",
"is_spell",
"is_disc",
"spell_id",
"is_item",
"item_id",
}; };
} }
@@ -57,12 +44,6 @@ public:
"bot_id", "bot_id",
"timer_id", "timer_id",
"timer_value", "timer_value",
"recast_time",
"is_spell",
"is_disc",
"spell_id",
"is_item",
"item_id",
}; };
} }
@@ -106,12 +87,6 @@ public:
e.bot_id = 0; e.bot_id = 0;
e.timer_id = 0; e.timer_id = 0;
e.timer_value = 0; e.timer_value = 0;
e.recast_time = 0;
e.is_spell = 0;
e.is_disc = 0;
e.spell_id = 0;
e.is_item = 0;
e.item_id = 0;
return e; return e;
} }
@@ -137,9 +112,8 @@ public:
{ {
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
"{} WHERE {} = {} LIMIT 1", "{} WHERE id = {} LIMIT 1",
BaseSelect(), BaseSelect(),
PrimaryKey(),
bot_timers_id bot_timers_id
) )
); );
@@ -151,12 +125,6 @@ public:
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10)); e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.timer_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10)); e.timer_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.timer_value = static_cast<uint32_t>(strtoul(row[2], nullptr, 10)); e.timer_value = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.recast_time = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.is_spell = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.is_disc = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.spell_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.is_item = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.item_id = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
return e; return e;
} }
@@ -193,12 +161,6 @@ public:
v.push_back(columns[0] + " = " + std::to_string(e.bot_id)); v.push_back(columns[0] + " = " + std::to_string(e.bot_id));
v.push_back(columns[1] + " = " + std::to_string(e.timer_id)); v.push_back(columns[1] + " = " + std::to_string(e.timer_id));
v.push_back(columns[2] + " = " + std::to_string(e.timer_value)); v.push_back(columns[2] + " = " + std::to_string(e.timer_value));
v.push_back(columns[3] + " = " + std::to_string(e.recast_time));
v.push_back(columns[4] + " = " + std::to_string(e.is_spell));
v.push_back(columns[5] + " = " + std::to_string(e.is_disc));
v.push_back(columns[6] + " = " + std::to_string(e.spell_id));
v.push_back(columns[7] + " = " + std::to_string(e.is_item));
v.push_back(columns[8] + " = " + std::to_string(e.item_id));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -223,12 +185,6 @@ public:
v.push_back(std::to_string(e.bot_id)); v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.timer_id)); v.push_back(std::to_string(e.timer_id));
v.push_back(std::to_string(e.timer_value)); v.push_back(std::to_string(e.timer_value));
v.push_back(std::to_string(e.recast_time));
v.push_back(std::to_string(e.is_spell));
v.push_back(std::to_string(e.is_disc));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.is_item));
v.push_back(std::to_string(e.item_id));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -261,12 +217,6 @@ public:
v.push_back(std::to_string(e.bot_id)); v.push_back(std::to_string(e.bot_id));
v.push_back(std::to_string(e.timer_id)); v.push_back(std::to_string(e.timer_id));
v.push_back(std::to_string(e.timer_value)); v.push_back(std::to_string(e.timer_value));
v.push_back(std::to_string(e.recast_time));
v.push_back(std::to_string(e.is_spell));
v.push_back(std::to_string(e.is_disc));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.is_item));
v.push_back(std::to_string(e.item_id));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
} }
@@ -303,12 +253,6 @@ public:
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10)); e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.timer_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10)); e.timer_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.timer_value = static_cast<uint32_t>(strtoul(row[2], nullptr, 10)); e.timer_value = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.recast_time = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.is_spell = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.is_disc = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.spell_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.is_item = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.item_id = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -336,12 +280,6 @@ public:
e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10)); e.bot_id = static_cast<uint32_t>(strtoul(row[0], nullptr, 10));
e.timer_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10)); e.timer_id = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
e.timer_value = static_cast<uint32_t>(strtoul(row[2], nullptr, 10)); e.timer_value = static_cast<uint32_t>(strtoul(row[2], nullptr, 10));
e.recast_time = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
e.is_spell = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.is_disc = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.spell_id = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.is_item = static_cast<uint8_t>(strtoul(row[7], nullptr, 10));
e.item_id = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -15,6 +15,7 @@
#include "../../database.h" #include "../../database.h"
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
#include <fmt/format.h>
class BaseCharacterExpeditionLockoutsRepository { class BaseCharacterExpeditionLockoutsRepository {
public: public:
@@ -16,7 +16,6 @@
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
class BaseNpcEmotesRepository { class BaseNpcEmotesRepository {
public: public:
struct NpcEmotes { struct NpcEmotes {
@@ -121,9 +120,8 @@ public:
{ {
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
"{} WHERE {} = {} LIMIT 1", "{} WHERE id = {} LIMIT 1",
BaseSelect(), BaseSelect(),
PrimaryKey(),
npc_emotes_id npc_emotes_id
) )
); );
@@ -6,7 +6,7 @@
* Any modifications to base repositories are to be made by the generator only * Any modifications to base repositories are to be made by the generator only
* *
* @generator ./utils/scripts/generators/repository-generator.pl * @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://docs.eqemu.io/developer/repositories * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories
*/ */
#ifndef EQEMU_BASE_{{TABLE_NAME_UPPER}}_REPOSITORY_H #ifndef EQEMU_BASE_{{TABLE_NAME_UPPER}}_REPOSITORY_H
@@ -319,62 +319,6 @@ public:
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); 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 #endif //EQEMU_BASE_{{TABLE_NAME_UPPER}}_REPOSITORY_H
+1 -1
View File
@@ -22,7 +22,7 @@
#include "strings.h" #include "strings.h"
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <fmt/format.h> #include <fmt/core.h>
#include "../common/repositories/rule_sets_repository.h" #include "../common/repositories/rule_sets_repository.h"
#include "../common/repositories/rule_values_repository.h" #include "../common/repositories/rule_values_repository.h"
-4
View File
@@ -215,7 +215,6 @@ 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, 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, 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, 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_END()
RULE_CATEGORY(Mercs) RULE_CATEGORY(Mercs)
@@ -657,9 +656,6 @@ RULE_BOOL(Bots, AllowPickpocketCommand, true, "Allows the use of the bot command
RULE_BOOL(Bots, BotHealOnLevel, false, "Setting whether a bot should heal completely when leveling. Default FALSE.") RULE_BOOL(Bots, BotHealOnLevel, false, "Setting whether a bot should heal completely when leveling. Default FALSE.")
RULE_INT(Bots, AutosaveIntervalSeconds, 300, "Number of seconds after which a timer is triggered which stores the bot data. The value 0 means no periodic automatic saving.") RULE_INT(Bots, AutosaveIntervalSeconds, 300, "Number of seconds after which a timer is triggered which stores the bot data. The value 0 means no periodic automatic saving.")
RULE_BOOL(Bots, CazicTouchBotsOwner, true, "Default True. Cazic Touch/DT will hit bot owner rather than bot.") RULE_BOOL(Bots, CazicTouchBotsOwner, true, "Default True. Cazic Touch/DT will hit bot owner rather than bot.")
RULE_INT(Bots, BotsClickItemsMinLvl, 1, "Minimum level for bots to be able to use ^clickitem. Default 1.")
RULE_BOOL(Bots, BotsCanClickItems, true, "Enabled the ability for bots to click items they have equipped. Default TRUE")
RULE_BOOL(Bots, CanClickMageEpicV1, true, "Whether or not bots are allowed to click Mage Epic 1.0. Default TRUE")
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Chat) RULE_CATEGORY(Chat)
+1 -1
View File
@@ -376,7 +376,7 @@ std::string EQ::SayLinkEngine::InjectSaylinksIfNotExist(const char *message)
void EQ::SayLinkEngine::LoadCachedSaylinks() void EQ::SayLinkEngine::LoadCachedSaylinks()
{ {
auto saylinks = SaylinkRepository::GetWhere(database, "phrase not REGEXP '[A-Z]' and phrase not REGEXP '[0-9]'"); auto saylinks = SaylinkRepository::GetWhere(database, "phrase not REGEXP BINARY '[A-Z]' and phrase not REGEXP '[0-9]'");
LogSaylink("Loaded [{}] saylinks into cache", saylinks.size()); LogSaylink("Loaded [{}] saylinks into cache", saylinks.size());
g_cached_saylinks = saylinks; g_cached_saylinks = saylinks;
} }
+1 -1
View File
@@ -18,7 +18,7 @@
#include <iostream> #include <iostream>
#include <cstring> #include <cstring>
#include <fmt/format.h> #include <fmt/core.h>
#if defined(_MSC_VER) && _MSC_VER >= 1800 #if defined(_MSC_VER) && _MSC_VER >= 1800
#include <algorithm> #include <algorithm>
+1 -1
View File
@@ -34,7 +34,7 @@
*/ */
#include "strings.h" #include "strings.h"
#include <fmt/format.h> #include <fmt/core.h>
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
+3 -3
View File
@@ -44,7 +44,7 @@
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
#include <fmt/format.h> #include <fmt/core.h>
#ifndef _WIN32 #ifndef _WIN32
// this doesn't appear to affect linux-based systems..need feedback for _WIN64 // this doesn't appear to affect linux-based systems..need feedback for _WIN64
@@ -206,7 +206,7 @@ const std::string NUM_TO_ENGLISH_Y[] = {
"Fifty ", "Sixty ", "Seventy ", "Eighty ", "Ninety " "Fifty ", "Sixty ", "Seventy ", "Eighty ", "Ninety "
}; };
// _WIN32 builds require that #include<fmt/format.h> be included in whatever code file the invocation is made from (no header files) // _WIN32 builds require that #include<fmt/core.h> be included in whatever code file the invocation is made from (no header files)
template<typename T1, typename T2> template<typename T1, typename T2>
std::vector<std::string> join_pair( std::vector<std::string> join_pair(
const std::string &glue, const std::string &glue,
@@ -239,7 +239,7 @@ std::vector<std::string> join_pair(
return output; return output;
} }
// _WIN32 builds require that #include<fmt/format.h> be included in whatever code file the invocation is made from (no header files) // _WIN32 builds require that #include<fmt/core.h> be included in whatever code file the invocation is made from (no header files)
template<typename T1, typename T2, typename T3, typename T4> template<typename T1, typename T2, typename T3, typename T4>
std::vector<std::string> join_tuple( std::vector<std::string> join_tuple(
const std::string &glue, const std::string &glue,
+1 -1
View File
@@ -1,6 +1,6 @@
#include <cstring> #include <cstring>
#include "strings.h" #include "strings.h"
#include <fmt/format.h> #include <fmt/core.h>
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <cinttypes> #include <cinttypes>
+1 -1
View File
@@ -1,6 +1,6 @@
#include <cstring> #include <cstring>
#include "strings.h" #include "strings.h"
#include <fmt/format.h> #include <fmt/core.h>
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
+1 -1
View File
@@ -1,7 +1,7 @@
#include "uuid.h" #include "uuid.h"
#include <ios> #include <ios>
#include <fmt/format.h> #include <fmt/core.h>
#ifdef _WIN32 #ifdef _WIN32
#include <objbase.h> #include <objbase.h>
+3 -3
View File
@@ -25,7 +25,7 @@
// Build variables // Build variables
// these get injected during the build pipeline // these get injected during the build pipeline
#define CURRENT_VERSION "22.38.0-dev" // always append -dev to the current version for custom-builds #define CURRENT_VERSION "22.36.0-dev" // always append -dev to the current version for custom-builds
#define LOGIN_VERSION "0.8.0" #define LOGIN_VERSION "0.8.0"
#define COMPILE_DATE __DATE__ #define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__ #define COMPILE_TIME __TIME__
@@ -42,9 +42,9 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/ */
#define CURRENT_BINARY_DATABASE_VERSION 9248 #define CURRENT_BINARY_DATABASE_VERSION 9247
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9041 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9040
#endif #endif
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "eqemu-server", "name": "eqemu-server",
"version": "22.38.0", "version": "22.36.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/EQEmu/Server.git" "url": "https://github.com/EQEmu/Server.git"
-8
View File
@@ -1,8 +0,0 @@
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
@@ -1,4 +0,0 @@
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
@@ -1,313 +0,0 @@
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)
}
}
}
+2 -2
View File
@@ -15,8 +15,8 @@ mkdir -p build && cd build && \
-DEQEMU_BUILD_LOGIN=ON \ -DEQEMU_BUILD_LOGIN=ON \
-DEQEMU_BUILD_LUA=ON \ -DEQEMU_BUILD_LUA=ON \
-DEQEMU_BUILD_PERL=ON \ -DEQEMU_BUILD_PERL=ON \
-DCMAKE_CXX_FLAGS:STRING="-O1 -g -Wno-everything" \ -DCMAKE_CXX_FLAGS:STRING="-O1 -g" \
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-O1 -g -Wno-everything" \ -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING="-O1 -g" \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-G 'Unix Makefiles' \ -G 'Unix Makefiles' \
.. && make -j$((`nproc`-4)) .. && make -j$((`nproc`-4))
+1 -1
View File
@@ -10,7 +10,7 @@ require (
require ( require (
github.com/golang/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.3.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
golang.org/x/crypto v0.17.0 // indirect golang.org/x/crypto v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect golang.org/x/net v0.17.0 // indirect
google.golang.org/appengine v1.6.7 // 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= 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-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.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 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.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
File diff suppressed because it is too large Load Diff
+1 -3
View File
@@ -78,9 +78,7 @@ ADD_EXECUTABLE(world ${world_sources} ${world_headers})
INSTALL(TARGETS world RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) INSTALL(TARGETS world RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
IF (WIN32 AND EQEMU_BUILD_PCH) TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/pch.h)
TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/pch.h)
ENDIF ()
ADD_DEFINITIONS(-DWORLD) ADD_DEFINITIONS(-DWORLD)
+1
View File
@@ -35,6 +35,7 @@
#include "wguild_mgr.h" #include "wguild_mgr.h"
#include "../common/zone_store.h" #include "../common/zone_store.h"
#include <set> #include <set>
#include <fmt/format.h>
extern WebInterfaceList web_interface; extern WebInterfaceList web_interface;
+1 -1
View File
@@ -31,7 +31,7 @@
#include "../common/md5.h" #include "../common/md5.h"
#include "eqemu_api_world_data_service.h" #include "eqemu_api_world_data_service.h"
#include "../common/zone_store.h" #include "../common/zone_store.h"
#include <fmt/format.h> #include <fmt/core.h>
extern ClientList client_list; extern ClientList client_list;
extern ZSList zoneserver_list; extern ZSList zoneserver_list;
+1
View File
@@ -7,6 +7,7 @@
#include "zoneserver.h" #include "zoneserver.h"
#include "../common/eqemu_logsys.h" #include "../common/eqemu_logsys.h"
#include "../common/repositories/instance_list_repository.h" #include "../common/repositories/instance_list_repository.h"
#include <fmt/format.h>
extern ClientList client_list; extern ClientList client_list;
extern ZSList zoneserver_list; extern ZSList zoneserver_list;
+1 -1
View File
@@ -18,7 +18,7 @@
* *
*/ */
#include <fmt/format.h> #include <fmt/core.h>
#include "clientlist.h" #include "clientlist.h"
#include "cliententry.h" #include "cliententry.h"
#include "eqemu_api_world_data_service.h" #include "eqemu_api_world_data_service.h"
+1
View File
@@ -23,6 +23,7 @@
#include "../common/repositories/expeditions_repository.h" #include "../common/repositories/expeditions_repository.h"
#include "../common/repositories/expedition_lockouts_repository.h" #include "../common/repositories/expedition_lockouts_repository.h"
#include "../common/repositories/dynamic_zone_members_repository.h" #include "../common/repositories/dynamic_zone_members_repository.h"
#include <fmt/format.h>
void ExpeditionDatabase::PurgeExpiredExpeditions() void ExpeditionDatabase::PurgeExpiredExpeditions()
{ {
+1 -1
View File
@@ -434,7 +434,7 @@ int main(int argc, char **argv)
tod.year, tod.year,
tod.month, tod.month,
tod.day, tod.day,
tod.hour - 1, tod.hour,
tod.minute tod.minute
); );
} }
+1
View File
@@ -16,6 +16,7 @@
#include "../common/repositories/completed_shared_task_activity_state_repository.h" #include "../common/repositories/completed_shared_task_activity_state_repository.h"
#include "../common/repositories/shared_task_dynamic_zones_repository.h" #include "../common/repositories/shared_task_dynamic_zones_repository.h"
#include <ctime> #include <ctime>
#include <fmt/format.h>
extern ClientList client_list; extern ClientList client_list;
extern ZSList zoneserver_list; extern ZSList zoneserver_list;
+1
View File
@@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/event_sub.h" #include "../common/event_sub.h"
#include "web_interface.h" #include "web_interface.h"
#include "../common/zone_store.h" #include "../common/zone_store.h"
#include <fmt/format.h>
extern uint32 numzones; extern uint32 numzones;
extern EQ::Random emu_random; extern EQ::Random emu_random;
+38 -33
View File
@@ -204,33 +204,6 @@ SET(zone_headers
hate_list.h hate_list.h
heal_rotation.h heal_rotation.h
horse.h horse.h
lua_bot.h
lua_bit.h
lua_client.h
lua_corpse.h
lua_door.h
lua_encounter.h
lua_entity.h
lua_entity_list.h
lua_expedition.h
lua_general.h
lua_group.h
lua_hate_list.h
lua_inventory.h
lua_item.h
lua_iteminst.h
lua_mob.h
lua_mod.h
lua_npc.h
lua_object.h
lua_packet.h
lua_parser.h
lua_parser_events.h
lua_ptr.h
lua_raid.h
lua_spawn.h
lua_spell.h
lua_stat_bonuses.h
map.h map.h
masterentity.h masterentity.h
merc.h merc.h
@@ -280,15 +253,47 @@ SET(zone_headers
zone_reload.h zone_reload.h
zone_cli.cpp) zone_cli.cpp)
ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers}) SET (lua_headers
lua_bot.h
lua_bit.h
lua_client.h
lua_corpse.h
lua_door.h
lua_encounter.h
lua_entity.h
lua_entity_list.h
lua_expedition.h
lua_general.h
lua_group.h
lua_hate_list.h
lua_inventory.h
lua_item.h
lua_iteminst.h
lua_mob.h
lua_mod.h
lua_npc.h
lua_object.h
lua_packet.h
lua_parser.h
lua_parser_events.h
lua_ptr.h
lua_raid.h
lua_spawn.h
lua_spell.h
lua_stat_bonuses.h
)
ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers} ${lua_headers})
INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
IF (WIN32 AND EQEMU_BUILD_PCH) IF(WIN32)
TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/pch/pch.h) TARGET_PRECOMPILE_HEADERS(zone PRIVATE pch.h)
TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/types.h ../common/eqemu_logsys.h ../common/eqemu_logsys_log_aliases.h ../common/features.h ../common/global_define.h) ENDIF(WIN32)
TARGET_PRECOMPILE_HEADERS(zone PRIVATE mob.h npc.h corpse.h doors.h bot.h entity.h client.h zone.h)
ENDIF() #TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/types.h ../common/eqemu_logsys.h ../common/eqemu_logsys_log_aliases.h ../common/features.h ../common/global_define.h)
#TARGET_PRECOMPILE_HEADERS(zone PRIVATE mob.h npc.h corpse.h doors.h bot.h entity.h client.h zone.h)
#TARGET_PRECOMPILE_HEADERS(zone PRIVATE ${lua_headers})
ADD_DEFINITIONS(-DZONE) ADD_DEFINITIONS(-DZONE)
+5 -5
View File
@@ -46,7 +46,7 @@ void EntityList::DescribeAggro(Client *to_who, NPC *from_who, float d, bool verb
); );
bool is_engaged = from_who->IsEngaged(); bool is_engaged = from_who->IsEngaged();
bool will_aggro_npcs = from_who->GetNPCAggro(); bool will_aggro_npcs = from_who->WillAggroNPCs();
if (is_engaged) { if (is_engaged) {
Mob *top = from_who->GetHateTop(); Mob *top = from_who->GetHateTop();
to_who->Message( to_who->Message(
@@ -983,14 +983,14 @@ bool Mob::CombatRange(Mob* other, float fixed_size_mod, bool aeRampage, ExtraAtt
float size_mod = GetSize(); float size_mod = GetSize();
float other_size_mod = other->GetSize(); float other_size_mod = other->GetSize();
if (GetRace() == Race::LavaDragon || GetRace() == Race::Wurm || GetRace() == Race::GhostDragon) { //For races with a fixed size if (GetRace() == RACE_LAVA_DRAGON_49 || GetRace() == RACE_WURM_158 || GetRace() == RACE_GHOST_DRAGON_196) { //For races with a fixed size
size_mod = 60.0f; size_mod = 60.0f;
} }
else if (size_mod < 6.0) { else if (size_mod < 6.0) {
size_mod = 8.0f; size_mod = 8.0f;
} }
if (other->GetRace() == Race::LavaDragon || other->GetRace() == Race::Wurm || other->GetRace() == Race::GhostDragon) { //For races with a fixed size if (other->GetRace() == RACE_LAVA_DRAGON_49 || other->GetRace() == RACE_WURM_158 || other->GetRace() == RACE_GHOST_DRAGON_196) { //For races with a fixed size
other_size_mod = 60.0f; other_size_mod = 60.0f;
} }
else if (other_size_mod < 6.0) { 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; size_mod *= size_mod * 4;
} }
if (other->GetRace() == Race::VeliousDragon) // Lord Vyemm and other velious dragons if (other->GetRace() == RACE_VELIOUS_DRAGON_184) // Lord Vyemm and other velious dragons
{ {
size_mod *= 1.75; size_mod *= 1.75;
} }
if (other->GetRace() == Race::DragonSkeleton) // Dracoliche in Fear. Skeletal Dragon if (other->GetRace() == RACE_DRAGON_SKELETON_122) // Dracoliche in Fear. Skeletal Dragon
{ {
size_mod *= 2.25; size_mod *= 2.25;
} }
+1 -1
View File
@@ -245,7 +245,7 @@ Json::Value ApiGetNpcListDetail(EQ::Net::WebsocketServerConnection *connection,
row["swarm_owner"] = npc->GetSwarmOwner(); row["swarm_owner"] = npc->GetSwarmOwner();
row["swarm_target"] = npc->GetSwarmTarget(); row["swarm_target"] = npc->GetSwarmTarget();
row["waypoint_max"] = npc->GetWaypointMax(); row["waypoint_max"] = npc->GetWaypointMax();
row["npc_aggro"] = npc->GetNPCAggro(); row["will_aggro_npcs"] = npc->WillAggroNPCs();
response.append(row); response.append(row);
} }
+67 -67
View File
@@ -1820,7 +1820,7 @@ bool Client::Death(Mob* killerMob, int64 damage, uint16 spell, EQ::skills::Skill
auto emote_id = killerMob->GetEmoteID(); auto emote_id = killerMob->GetEmoteID();
if (emote_id) { if (emote_id) {
killerMob->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledPC, emoteid, this); killerMob->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledPC, emoteid);
} }
killerMob->TrySpellOnKill(killed_level, spell); killerMob->TrySpellOnKill(killed_level, spell);
@@ -2705,69 +2705,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
Corpse* corpse = nullptr; 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, 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);
}
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);
}
if (!HasOwner() && !IsMerc() && !GetSwarmInfo() && (!is_merchant || allow_merchant_corpse) && if (!HasOwner() && !IsMerc() && !GetSwarmInfo() && (!is_merchant || allow_merchant_corpse) &&
((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) || ((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) ||
(killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient()))) (killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient())))
@@ -2799,7 +2736,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
ApplyIllusionToCorpse(illusion_spell_id, corpse); ApplyIllusionToCorpse(illusion_spell_id, corpse);
if (killer != 0 && emoteid != 0) if (killer != 0 && emoteid != 0)
corpse->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::AfterDeath, emoteid, killer); corpse->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::AfterDeath, emoteid);
if (killer != 0 && killer->IsClient()) { if (killer != 0 && killer->IsClient()) {
corpse->AllowPlayerLoot(killer, 0); corpse->AllowPlayerLoot(killer, 0);
if (killer->IsGrouped()) { if (killer->IsGrouped()) {
@@ -2877,6 +2814,38 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
entity_list.RemoveFromXTargets(this); 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);
}
}
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);
}
WipeHateList(); WipeHateList();
p_depop = true; p_depop = true;
@@ -2885,6 +2854,37 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
entity_list.UpdateFindableNPCState(this, true); 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)
);
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);
}
return true; return true;
} }
@@ -4087,7 +4087,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
IsPlayerRace(GetBaseRace()) && IsPlayerRace(GetBaseRace()) &&
RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace()) RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace())
) || ) ||
GetBaseRace() == Race::OggokCitizen GetBaseRace() == RACE_OGGOK_CITIZEN_93
) { ) {
is_immune_to_frontal_stun = true; is_immune_to_frontal_stun = true;
} }
@@ -4107,7 +4107,7 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
IsPlayerRace(GetBaseRace()) && IsPlayerRace(GetBaseRace()) &&
RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace()) RuleI(Combat, FrontalStunImmunityRaces) & GetPlayerRaceBit(GetBaseRace())
) || ) ||
GetBaseRace() == Race::OggokCitizen GetBaseRace() == RACE_OGGOK_CITIZEN_93
) )
) { ) {
is_immune_to_frontal_stun = true; is_immune_to_frontal_stun = true;
+44 -671
View File
@@ -94,7 +94,6 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm
SetPullFlag(false); SetPullFlag(false);
SetPullingFlag(false); SetPullingFlag(false);
SetReturningFlag(false); SetReturningFlag(false);
SetIsUsingItemClick(false);
m_previous_pet_order = SPO_Guard; m_previous_pet_order = SPO_Guard;
rest_timer.Disable(); rest_timer.Disable();
@@ -108,8 +107,6 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm
// Do this once and only in this constructor // Do this once and only in this constructor
GenerateAppearance(); GenerateAppearance();
GenerateBaseStats(); GenerateBaseStats();
bot_timers.clear();
// Calculate HitPoints Last As It Uses Base Stats // Calculate HitPoints Last As It Uses Base Stats
current_hp = GenerateBaseHitPoints(); current_hp = GenerateBaseHitPoints();
current_mana = GenerateBaseManaPoints(); current_mana = GenerateBaseManaPoints();
@@ -117,6 +114,8 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm
hp_regen = CalcHPRegen(); hp_regen = CalcHPRegen();
mana_regen = CalcManaRegen(); mana_regen = CalcManaRegen();
end_regen = CalcEnduranceRegen(); end_regen = CalcEnduranceRegen();
for (int i = 0; i < MaxTimer; i++)
timers[i] = 0;
strcpy(name, GetCleanName()); strcpy(name, GetCleanName());
memset(&_botInspectMessage, 0, sizeof(InspectMessage_Struct)); memset(&_botInspectMessage, 0, sizeof(InspectMessage_Struct));
@@ -214,7 +213,6 @@ Bot::Bot(
SetPullFlag(false); SetPullFlag(false);
SetPullingFlag(false); SetPullingFlag(false);
SetReturningFlag(false); SetReturningFlag(false);
SetIsUsingItemClick(false);
m_previous_pet_order = SPO_Guard; m_previous_pet_order = SPO_Guard;
rest_timer.Disable(); rest_timer.Disable();
@@ -240,6 +238,9 @@ Bot::Bot(
error_message.clear(); error_message.clear();
} }
for (int i = 0; i < MaxTimer; i++)
timers[i] = 0;
if (GetClass() == Class::Rogue) { if (GetClass() == Class::Rogue) {
m_evade_timer.Start(); m_evade_timer.Start();
} }
@@ -251,10 +252,8 @@ Bot::Bot(
GenerateBaseStats(); GenerateBaseStats();
bot_timers.clear(); if (!database.botdb.LoadTimers(this) && bot_owner)
if (!database.botdb.LoadTimers(this) && bot_owner) {
bot_owner->Message(Chat::White, "%s for '%s'", BotDatabase::fail::LoadTimers(), GetCleanName()); bot_owner->Message(Chat::White, "%s for '%s'", BotDatabase::fail::LoadTimers(), GetCleanName());
}
LoadAAs(); LoadAAs();
@@ -1669,7 +1668,7 @@ bool Bot::Process()
mob_close_scan_timer.GetDuration() mob_close_scan_timer.GetDuration()
); );
entity_list.ScanCloseMobs(close_mobs, this, IsMoving()); entity_list.ScanCloseClientMobs(close_mobs, this);
} }
SpellProcess(); SpellProcess();
@@ -2681,7 +2680,7 @@ void Bot::CalcMeleeDistances(const Mob* tar, const EQ::ItemInstance* const& p_it
float other_size_mod = tar->GetSize(); float other_size_mod = tar->GetSize();
// For races with a fixed size // For races with a fixed size
if (GetRace() == Race::LavaDragon || GetRace() == Race::Wurm || GetRace() == Race::GhostDragon) { if (GetRace() == RT_DRAGON || GetRace() == RT_WURM || GetRace() == RT_DRAGON_7) {
// size_mod = 60.0f; // size_mod = 60.0f;
} }
@@ -2690,7 +2689,7 @@ void Bot::CalcMeleeDistances(const Mob* tar, const EQ::ItemInstance* const& p_it
} }
// For races with a fixed size // For races with a fixed size
if (tar->GetRace() == Race::LavaDragon || tar->GetRace() == Race::Wurm || tar->GetRace() == Race::GhostDragon) { if (tar->GetRace() == RT_DRAGON || tar->GetRace() == RT_WURM || tar->GetRace() == RT_DRAGON_7) {
other_size_mod = 60.0f; other_size_mod = 60.0f;
} }
@@ -2902,12 +2901,12 @@ void Bot::AcquireBotTarget(Group* bot_group, Raid* raid, Client* leash_owner, fl
} }
} else { } else {
// This will keep bots on target for now..but, future updates will allow for rooting/stunning // This will keep bots on target for now..but, future updates will allow for rooting/stunning
if (auto escaping = hate_list.GetEscapingMobOnHateList(leash_owner, leash_distance)) { if (auto escaping = hate_list.GetEscapingEntOnHateList(leash_owner, leash_distance)) {
SetTarget(escaping); SetTarget(escaping);
} }
if (!GetTarget()) { if (!GetTarget()) {
auto most_hate = hate_list.GetMobWithMostHateOnList(this, nullptr, true); auto most_hate = hate_list.GetEntWithMostHateOnList(this, nullptr, true);
if (most_hate) { if (most_hate) {
SetTarget(most_hate); SetTarget(most_hate);
} }
@@ -3639,45 +3638,41 @@ uint32 Bot::SpawnedBotCount(const uint32 owner_id, uint8 class_id) {
return spawned_bot_count; return spawned_bot_count;
} }
void Bot::LevelBotWithClient(Client* c, uint8 new_level, bool send_appearance) { void Bot::LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp) {
// This essentially performs a '#bot update,' with appearance packets, based on the current methods. // This essentially performs a '#bot update,' with appearance packets, based on the current methods.
// This should not be called outside of Client::SetEXP() due to its lack of rule checks. // This should not be called outside of Client::SetEXP() due to it's lack of rule checks.
if (client) {
std::list<Bot*> blist = entity_list.GetBotsByBotOwnerCharacterID(client->CharacterID());
if (c) { for (auto biter = blist.begin(); biter != blist.end(); ++biter) {
const auto &l = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); Bot* bot = *biter;
for (const auto &e : l) { if (bot && (bot->GetLevel() != client->GetLevel())) {
if (e && (e->GetLevel() != c->GetLevel())) { bot->SetPetChooser(false); // not sure what this does, but was in bot 'update' code
int levels_change = (new_level - e->GetLevel()); bot->CalcBotStats(client->GetBotOption(Client::booStatsUpdate));
if (levels_change < 0) { if (sendlvlapp) {
parse->EventBot(EVENT_LEVEL_DOWN, e, nullptr, std::to_string(std::abs(levels_change)), 0); bot->SendLevelAppearance();
} else {
parse->EventBot(EVENT_LEVEL_UP, e, nullptr, std::to_string(levels_change), 0);
} }
// modified from Client::SetLevel()
e->SetPetChooser(false); // not sure what this does, but was in bot 'update' code
e->CalcBotStats(c->GetBotOption(Client::booStatsUpdate));
if (send_appearance) {
e->SendLevelAppearance();
}
if (!RuleB(Bots, BotHealOnLevel)) { if (!RuleB(Bots, BotHealOnLevel)) {
const int64 max_hp = e->CalcMaxHP(); int mhp = bot->CalcMaxHP();
if (e->GetHP() > max_hp) { if (bot->GetHP() > mhp) {
e->SetHP(max_hp); bot->SetHP(mhp);
} }
} else { }
e->SetHP(e->CalcMaxHP()); else {
e->SetMana(e->CalcMaxMana()); bot->SetHP(bot->CalcMaxHP());
bot->SetMana(bot->CalcMaxMana());
} }
e->SendHPUpdate(); bot->SendHPUpdate();
e->SendAppearancePacket(AT_WhoLevel, new_level, true, true); // who level change bot->SendAppearancePacket(AT_WhoLevel, level, true, true); // who level change
e->AI_AddBotSpells(e->GetBotSpellID()); bot->AI_AddBotSpells(bot->GetBotSpellID());
} }
} }
blist.clear();
} }
} }
@@ -7917,17 +7912,18 @@ bool Bot::UseDiscipline(uint32 spell_id, uint32 target) {
return false; return false;
if (spell.recast_time > 0) { if (spell.recast_time > 0) {
if (CheckDisciplineReuseTimer(spell_id)) { if (CheckDisciplineRecastTimers(this, spells[spell_id].timer_id)) {
if (spells[spell_id].timer_id > 0) { if (spells[spell_id].timer_id > 0 && spells[spell_id].timer_id < MAX_DISCIPLINE_TIMERS)
SetDisciplineReuseTimer(spell_id); SetDisciplineRecastTimer(spells[spell_id].timer_id, spell.recast_time);
}
} else { } else {
uint32 remaining_time = (GetDisciplineReuseRemainingTime(spell_id) / 1000); uint32 remaining_time = (GetDisciplineRemainingTime(this, spells[spell_id].timer_id) / 1000);
OwnerMessage( GetOwner()->Message(
Chat::White,
fmt::format( fmt::format(
"I can use this discipline in {}.", "{} can use this discipline in {}.",
GetCleanName(),
Strings::SecondsToTime(remaining_time) Strings::SecondsToTime(remaining_time)
) ).c_str()
); );
return false; return false;
} }
@@ -8810,627 +8806,4 @@ void Bot::AddBotStartingItems(uint16 race_id, uint8 class_id)
} }
} }
void Bot::SetSpellRecastTimer(uint16 spell_id, int32 recast_delay) {
if (!IsValidSpell(spell_id)) {
OwnerMessage("Failed to set spell recast timer.");
return;
}
if (!recast_delay) {
recast_delay = CalcSpellRecastTimer(spell_id);
}
if (CheckSpellRecastTimer(spell_id)) {
BotTimer_Struct t;
t.timer_id = spells[ spell_id ].timer_id;
t.timer_value = (Timer::GetCurrentTime() + recast_delay);
t.recast_time = recast_delay;
t.is_spell = true;
t.is_disc = false;
t.spell_id = spells[ spell_id ].id;
t.is_item = false;
t.item_id = 0;
bot_timers.push_back(t);
} else {
if (!bot_timers.empty()) {
for (int i = 0; i < bot_timers.size(); i++) {
if (
bot_timers[i].is_spell &&
(
(
spells[spell_id].timer_id != 0 &&
spells[spell_id].timer_id == bot_timers[ i ].timer_id
) ||
bot_timers[i].spell_id == spell_id
)
) {
bot_timers[i].timer_value = (Timer::GetCurrentTime() + recast_delay);
bot_timers[i].recast_time = recast_delay;
break;
}
}
}
}
}
uint32 Bot::GetSpellRecastTimer(uint16 spell_id)
{
uint32 result = 0;
if (spell_id && !IsValidSpell(spell_id)) {
OwnerMessage("Failed to get spell recast timer.");
return result;
}
if (!bot_timers.empty()) {
for (int i = 0; i < bot_timers.size(); i++) {
if (
bot_timers[i].is_spell &&
(
!spell_id ||
(
(
spells[spell_id].timer_id != 0 &&
spells[spell_id].timer_id == bot_timers[i].timer_id
) ||
bot_timers[i].spell_id == spell_id
)
)
) {
result = bot_timers[i].timer_value;
break;
}
}
}
return result;
}
uint32 Bot::GetSpellRecastRemainingTime(uint16 spell_id)
{
uint32 result = 0;
if (GetSpellRecastTimer(spell_id) > Timer::GetCurrentTime()) {
result = (GetSpellRecastTimer(spell_id) - Timer::GetCurrentTime());
}
return result;
}
bool Bot::CheckSpellRecastTimer(uint16 spell_id)
{
ClearExpiredTimers();
if (spell_id && !IsValidSpell(spell_id)) {
OwnerMessage("Failed to check spell recast timer.");
return false;
}
if (GetSpellRecastTimer(spell_id) < Timer::GetCurrentTime()) {
return true;
}
return false;
}
void Bot::SetDisciplineReuseTimer(uint16 spell_id, int32 reuse_timer)
{
if (!IsValidSpell(spell_id)) {
OwnerMessage("Failed to set discipline reuse timer.");
return;
}
if (!reuse_timer) {
reuse_timer = CalcSpellRecastTimer(spell_id);
}
if (CheckDisciplineReuseTimer(spell_id)) {
BotTimer_Struct t;
t.timer_id = spells[ spell_id ].timer_id;
t.timer_value = (Timer::GetCurrentTime() + reuse_timer);
t.recast_time = reuse_timer;
t.is_spell = false;
t.is_disc = true;
t.spell_id = spells[ spell_id ].id;
t.is_item = false;
t.item_id = 0;
bot_timers.push_back(t);
} else {
if (!bot_timers.empty()) {
for (int i = 0; i < bot_timers.size(); i++) {
if (
bot_timers[i].is_disc &&
(
(
spells[spell_id].timer_id != 0 &&
spells[spell_id].timer_id == bot_timers[i].timer_id
) ||
bot_timers[i].spell_id == spell_id
)
) {
bot_timers[i].timer_value = (Timer::GetCurrentTime() + reuse_timer);
bot_timers[i].recast_time = reuse_timer;
break;
}
}
}
}
}
uint32 Bot::GetDisciplineReuseTimer(uint16 spell_id)
{
uint32 result = 0;
if (!bot_timers.empty()) {
for (int i = 0; i < bot_timers.size(); i++) {
if (
bot_timers[i].is_disc &&
(
!spell_id ||
(
(
spells[spell_id].timer_id != 0 &&
spells[spell_id].timer_id == bot_timers[i].timer_id
) ||
bot_timers[i].spell_id == spell_id
)
)
) {
result = bot_timers[i].timer_value;
break;
}
}
}
return result;
}
uint32 Bot::GetDisciplineReuseRemainingTime(uint16 spell_id) {
uint32 result = 0;
if (GetDisciplineReuseTimer(spell_id) > Timer::GetCurrentTime()) {
result = (GetDisciplineReuseTimer(spell_id) - Timer::GetCurrentTime());
}
return result;
}
bool Bot::CheckDisciplineReuseTimer(uint16 spell_id)
{
ClearExpiredTimers();
if (GetDisciplineReuseTimer(spell_id) < Timer::GetCurrentTime()) { //checks for spells on the same timer
return true; //can cast spell
}
return false;
}
void Bot::SetItemReuseTimer(uint32 item_id, uint32 reuse_timer)
{
const auto *item = database.GetItem(item_id);
if (!item) {
OwnerMessage("Failed to set item reuse timer.");
return;
}
if (item->RecastDelay <= 0) {
return;
}
if (CheckItemReuseTimer(item_id)) {
BotTimer_Struct t;
t.timer_id = (item->RecastType == NegativeItemReuse ? item->ID : item->RecastType);
t.timer_value = (
reuse_timer != 0 ?
(Timer::GetCurrentTime() + reuse_timer) :
(Timer::GetCurrentTime() + (item->RecastDelay * 1000))
);
t.recast_time = (reuse_timer != 0 ? reuse_timer : (item->RecastDelay * 1000));
t.is_spell = false;
t.is_disc = false;
t.spell_id = 0;
t.is_item = true;
t.item_id = item->ID;
bot_timers.push_back(t);
}
else {
if (!bot_timers.empty()) {
for (int i = 0; i < bot_timers.size(); i++) {
if (
bot_timers[i].is_item &&
(
(
item->RecastType != 0 &&
item->RecastType == bot_timers[i].timer_id
) ||
bot_timers[i].item_id == item_id
)
) {
bot_timers[i].timer_value = (
reuse_timer != 0 ?
(Timer::GetCurrentTime() + reuse_timer) :
(Timer::GetCurrentTime() + (item->RecastDelay * 1000))
);
bot_timers[i].recast_time = (
reuse_timer != 0 ?
reuse_timer :
(item->RecastDelay * 1000)
);
break;
}
}
}
}
}
uint32 Bot::GetItemReuseTimer(uint32 item_id)
{
uint32 result = 0;
const EQ::ItemData* item;
if (item_id) {
item = database.GetItem(item_id);
if (!item) {
OwnerMessage("Failed to get item reuse timer.");
return result;
}
}
if (!bot_timers.empty()) {
for (int i = 0; i < bot_timers.size(); i++) {
if (
bot_timers[i].is_item &&
(
!item_id ||
(
(
item->RecastType != 0 &&
item->RecastType == bot_timers[i].timer_id
) ||
bot_timers[i].item_id == item_id
)
)
) {
result = bot_timers[i].timer_value;
break;
}
}
}
ClearExpiredTimers();
return result;
}
bool Bot::CheckItemReuseTimer(uint32 item_id)
{
ClearExpiredTimers();
if (GetItemReuseTimer(item_id) < Timer::GetCurrentTime()) {
return true;
}
return false;
}
uint32 Bot::GetItemReuseRemainingTime(uint32 item_id)
{
uint32 result = 0;
if (GetItemReuseTimer(item_id) > Timer::GetCurrentTime()) {
result = (GetItemReuseTimer(item_id) - Timer::GetCurrentTime());
}
return result;
}
uint32 Bot::CalcSpellRecastTimer(uint16 spell_id)
{
uint32 result = 0;
if (spells[spell_id].recast_time == 0 && spells[spell_id].recovery_time == 0) {
return result;
} else {
if (spells[spell_id].recovery_time > spells[spell_id].recast_time) {
result = spells[spell_id].recovery_time;
} else {
result = spells[spell_id].recast_time;
}
}
return result;
}
void Bot::ClearDisciplineReuseTimer(uint16 spell_id)
{
if (spell_id && !IsValidSpell(spell_id)) {
OwnerMessage(
fmt::format(
"{} is not a valid spell ID.'",
spell_id
)
);
return;
}
if (!bot_timers.empty()) {
for (int i = 0; i < bot_timers.size(); i++) {
if (
bot_timers[i].is_disc &&
bot_timers[i].timer_value >= Timer::GetCurrentTime()
) {
if (
!spell_id ||
(
(
spells[spell_id].timer_id != 0 &&
spells[spell_id].timer_id == bot_timers[i].timer_id
) ||
bot_timers[i].spell_id == spell_id
)
) {
bot_timers[i].timer_value = 0;
}
}
}
}
ClearExpiredTimers();
}
void Bot::ClearItemReuseTimer(uint32 item_id)
{
const EQ::ItemData* item;
if (item_id) {
item = database.GetItem(item_id);
if (!item) {
OwnerMessage(
fmt::format(
"{} is not a valid item ID.",
item_id
)
);
return;
}
}
if (!bot_timers.empty()) {
for (int i = 0; i < bot_timers.size(); i++) {
if (bot_timers[i].is_item && bot_timers[i].timer_value >= Timer::GetCurrentTime()) {
if (
!item_id ||
(
(
item->RecastType != 0 &&
item->RecastType == bot_timers[i].timer_id
) ||
bot_timers[i].item_id == item_id
)
) {
bot_timers[i].timer_value = 0;
}
}
}
}
ClearExpiredTimers();
}
void Bot::ClearSpellRecastTimer(uint16 spell_id)
{
if (spell_id && !IsValidSpell(spell_id)) {
OwnerMessage(
fmt::format(
"{} is not a valid spell ID.",
spell_id
)
);
return;
}
if (!bot_timers.empty()) {
for (int i = 0; i < bot_timers.size(); i++) {
if (bot_timers[i].is_spell && bot_timers[i].timer_value >= Timer::GetCurrentTime()) {
if (
!spell_id ||
(
(
spells[spell_id].timer_id != 0 &&
spells[spell_id].timer_id == bot_timers[i].timer_id
) ||
bot_timers[i].spell_id == spell_id
)
) {
bot_timers[i].timer_value = 0;
}
}
}
}
ClearExpiredTimers();
}
void Bot::ClearExpiredTimers()
{
if (!bot_timers.empty()) {
int current = 0;
int end = bot_timers.size();
while (current < end) {
if (bot_timers[current].timer_value < Timer::GetCurrentTime()) {
bot_timers.erase(bot_timers.begin() + current);
} else {
current++;
}
end = bot_timers.size();
}
}
}
void Bot::TryItemClick(uint16 slot_id)
{
if (!GetOwner()) {
return;
}
const auto *inst = GetClickItem(slot_id);
if (!inst) {
return;
}
const auto *item = inst->GetItem();
if (!item) {
return;
}
if (!CheckItemReuseTimer(item->ID)) {
uint32 remaining_time = (GetItemReuseRemainingTime(item->ID) / 1000);
OwnerMessage(
fmt::format(
"I can use this item in {}.",
Strings::SecondsToTime(remaining_time)
)
);
return;
}
DoItemClick(item, slot_id);
}
EQ::ItemInstance *Bot::GetClickItem(uint16 slot_id)
{
EQ::ItemInstance* inst = nullptr;
const EQ::ItemData* item = nullptr;
inst = GetBotItem(slot_id);
if (!inst || !inst->GetItem()) {
return nullptr;
}
item = inst->GetItem();
if (item->ID == MAG_EPIC_1_0 && !RuleB(Bots, CanClickMageEpicV1)) {
OwnerMessage(
fmt::format(
"{} is currently disabled for bots to click.",
item->Name
)
);
return nullptr;
}
if (item->Click.Effect <= 0) {
OwnerMessage(
fmt::format(
"{} does not have a clickable effect.",
item->Name
)
);
return nullptr;
}
if (!IsValidSpell(item->Click.Effect)) {
OwnerMessage(
fmt::format(
"{} does not have a valid clickable effect.",
item->Name
)
);
return nullptr;
}
if (item->ReqLevel > GetLevel()) {
OwnerMessage(
fmt::format(
"I am below the level requirement of {} for {}.",
item->ReqLevel,
item->Name
)
);
return nullptr;
}
if (item->Click.Level2 > GetLevel()) {
OwnerMessage(
fmt::format(
"I must be level {} to use {}.",
item->Click.Level2,
item->Name
)
);
return nullptr;
}
if (inst->GetCharges() == 0) {
OwnerMessage(
fmt::format(
"{} is out of charges.",
item->Name
)
);
return nullptr;
}
return inst;
}
void Bot::DoItemClick(const EQ::ItemData *item, uint16 slot_id)
{
bool is_casting_bard_song = false;
Mob* tar = (GetOwner()->GetTarget() ? GetOwner()->GetTarget() : this);
if (IsCasting()) {
InterruptSpell();
}
SetIsUsingItemClick(true);
BotGroupSay(
this,
fmt::format(
"Attempting to cast [{}] on {}.",
spells[item->Click.Effect].name,
tar->GetCleanName()
).c_str()
);
if (!IsCastWhileInvisibleSpell(item->Click.Effect)) {
CommonBreakInvisible();
}
if (GetClass() == Class::Bard && IsCasting() && casting_spell_slot < EQ::spells::CastingSlot::MaxGems) {
is_casting_bard_song = true;
}
if (GetClass() == Class::Bard) {
DoBardCastingFromItemClick(is_casting_bard_song, item->CastTime, item->Click.Effect, tar->GetID(), EQ::spells::CastingSlot::Item, slot_id, item->RecastType, item->RecastDelay);
} else {
if (!CastSpell(item->Click.Effect, tar->GetID(), EQ::spells::CastingSlot::Item, item->CastTime, 0, 0, slot_id)) {
OwnerMessage(
fmt::format(
"Casting failed for {}. This could be due to zone restrictions, target restrictions or other limiting factors.",
item->Name
)
);
}
}
}
uint8 Bot::spell_casting_chances[SPELL_TYPE_COUNT][Class::PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND] = { 0 }; uint8 Bot::spell_casting_chances[SPELL_TYPE_COUNT][Class::PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND] = { 0 };
+13 -30
View File
@@ -42,12 +42,13 @@ constexpr uint32 BOT_FOLLOW_DISTANCE_DEFAULT_MAX = 2500; // as DSq value (50 uni
constexpr uint32 BOT_KEEP_ALIVE_INTERVAL = 5000; // 5 seconds constexpr uint32 BOT_KEEP_ALIVE_INTERVAL = 5000; // 5 seconds
constexpr uint32 MAG_EPIC_1_0 = 28034;
extern WorldServer worldserver; extern WorldServer worldserver;
constexpr int BotAISpellRange = 100; // TODO: Write a method that calcs what the bot's spell range is based on spell, equipment, AA, whatever and replace this constexpr int BotAISpellRange = 100; // TODO: Write a method that calcs what the bot's spell range is based on spell, equipment, AA, whatever and replace this
constexpr int NegativeItemReuse = -1; // Unlinked timer for items constexpr int MaxSpellTimer = 15;
constexpr int MaxDisciplineTimer = 10;
constexpr int DisciplineReuseStart = MaxSpellTimer + 1;
constexpr int MaxTimer = MaxSpellTimer + MaxDisciplineTimer;
// nHSND negative Healer/Slower/Nuker/Doter // nHSND negative Healer/Slower/Nuker/Doter
// pH positive Healer // pH positive Healer
@@ -221,8 +222,6 @@ public:
void SetPullFlag(bool flag = true) { m_pull_flag = flag; } void SetPullFlag(bool flag = true) { m_pull_flag = flag; }
bool GetPullingFlag() const { return m_pulling_flag; } bool GetPullingFlag() const { return m_pulling_flag; }
bool GetReturningFlag() const { return m_returning_flag; } bool GetReturningFlag() const { return m_returning_flag; }
bool GetIsUsingItemClick() { return is_using_item_click; }
void SetIsUsingItemClick(bool flag = true) { is_using_item_click = flag; }
bool UseDiscipline(uint32 spell_id, uint32 target); bool UseDiscipline(uint32 spell_id, uint32 target);
uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets, Raid* raid); uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets, Raid* raid);
uint8 GetNumberNeedingHealedInRaidGroup(uint8& need_healed, uint8 hpr, bool includePets, Raid* raid); uint8 GetNumberNeedingHealedInRaidGroup(uint8& need_healed, uint8 hpr, bool includePets, Raid* raid);
@@ -287,10 +286,6 @@ public:
void SetEndurance(int32 newEnd) override; void SetEndurance(int32 newEnd) override;
void DoEnduranceUpkeep(); void DoEnduranceUpkeep();
void TryItemClick(uint16 slot_id);
EQ::ItemInstance* GetClickItem(uint16 slot_id);
void DoItemClick(const EQ::ItemData* inst, uint16 slot_id);
bool AI_AddBotSpells(uint32 bot_spell_id); bool AI_AddBotSpells(uint32 bot_spell_id);
void AddSpellToBotList( void AddSpellToBotList(
int16 iPriority, int16 iPriority,
@@ -413,6 +408,11 @@ public:
static Bot* GetFirstBotInGroup(Group* group); static Bot* GetFirstBotInGroup(Group* group);
static void ProcessClientZoneChange(Client* botOwner); static void ProcessClientZoneChange(Client* botOwner);
static void ProcessBotOwnerRefDelete(Mob* botOwner); // Removes a Client* reference when the Client object is destroyed static void ProcessBotOwnerRefDelete(Mob* botOwner); // Removes a Client* reference when the Client object is destroyed
static int32 GetSpellRecastTimer(Bot *caster, int timer_index);
static bool CheckSpellRecastTimers(Bot *caster, int SpellIndex);
static int32 GetDisciplineRecastTimer(Bot *caster, int timer_index);
static bool CheckDisciplineRecastTimers(Bot *caster, int timer_index);
static uint32 GetDisciplineRemainingTime(Bot *caster, int timer_index);
//Raid methods //Raid methods
static void ProcessRaidInvite(Mob* invitee, Client* invitor, bool group_invite = false); static void ProcessRaidInvite(Mob* invitee, Client* invitor, bool group_invite = false);
@@ -612,23 +612,8 @@ public:
_botStance = EQ::constants::stancePassive; _botStance = EQ::constants::stancePassive;
} }
void SetBotCasterRange(uint32 bot_caster_range) { m_bot_caster_range = bot_caster_range; } void SetBotCasterRange(uint32 bot_caster_range) { m_bot_caster_range = bot_caster_range; }
uint32 GetSpellRecastTimer(uint16 spell_id = 0); void SetSpellRecastTimer(int timer_index, int32 recast_delay);
bool CheckSpellRecastTimer(uint16 spell_id = 0); void SetDisciplineRecastTimer(int timer_index, int32 recast_delay);
uint32 GetSpellRecastRemainingTime(uint16 spell_id = 0);
void SetSpellRecastTimer(uint16 spell_id, int32 recast_delay = 0);
uint32 CalcSpellRecastTimer(uint16 spell_id);
uint32 GetDisciplineReuseTimer(uint16 spell_id = 0);
bool CheckDisciplineReuseTimer(uint16 spell_id = 0);
uint32 GetDisciplineReuseRemainingTime(uint16 spell_id = 0);
void SetDisciplineReuseTimer(uint16 spell_id, int32 reuse_timer = 0);
uint32 GetItemReuseTimer(uint32 item_id = 0);
bool CheckItemReuseTimer(uint32 item_id = 0);
void SetItemReuseTimer(uint32 item_id, uint32 reuse_timer = 0);
void ClearDisciplineReuseTimer(uint16 spell_id = 0);
void ClearItemReuseTimer(uint32 item_id = 0);
void ClearSpellRecastTimer(uint16 spell_id = 0);
uint32 GetItemReuseRemainingTime(uint32 item_id = 0);
void ClearExpiredTimers();
void SetAltOutOfCombatBehavior(bool behavior_flag) { _altoutofcombatbehavior = behavior_flag;} void SetAltOutOfCombatBehavior(bool behavior_flag) { _altoutofcombatbehavior = behavior_flag;}
void SetShowHelm(bool showhelm) { _showhelm = showhelm; } void SetShowHelm(bool showhelm) { _showhelm = showhelm; }
void SetBeardColor(uint8 value) { beardcolor = value; } void SetBeardColor(uint8 value) { beardcolor = value; }
@@ -728,8 +713,7 @@ public:
// New accessors for BotDatabase access // New accessors for BotDatabase access
bool DeleteBot(); bool DeleteBot();
std::vector<BotTimer_Struct> GetBotTimers() { return bot_timers; } uint32* GetTimers() { return timers; }
void SetBotTimers(std::vector<BotTimer_Struct> timers) { bot_timers = timers; }
uint32 GetLastZoneID() const { return _lastZoneId; } uint32 GetLastZoneID() const { return _lastZoneId; }
int32 GetBaseAC() const { return _baseAC; } int32 GetBaseAC() const { return _baseAC; }
int32 GetBaseATK() const { return _baseATK; } int32 GetBaseATK() const { return _baseATK; }
@@ -844,7 +828,6 @@ protected:
std::vector<BotSpells_Struct> AIBot_spells; std::vector<BotSpells_Struct> AIBot_spells;
std::vector<BotSpells_Struct> AIBot_spells_enforced; std::vector<BotSpells_Struct> AIBot_spells_enforced;
std::vector<BotTimer_Struct> bot_timers;
private: private:
// Class Members // Class Members
@@ -878,6 +861,7 @@ private:
int32 cur_end; int32 cur_end;
int32 max_end; int32 max_end;
int32 end_regen; int32 end_regen;
uint32 timers[MaxTimer];
Timer m_evade_timer; // can be moved to pTimers at some point Timer m_evade_timer; // can be moved to pTimers at some point
Timer m_alt_combat_hate_timer; Timer m_alt_combat_hate_timer;
@@ -891,7 +875,6 @@ private:
bool m_pull_flag; bool m_pull_flag;
bool m_pulling_flag; bool m_pulling_flag;
bool m_returning_flag; bool m_returning_flag;
bool is_using_item_click;
eStandingPetOrder m_previous_pet_order; eStandingPetOrder m_previous_pet_order;
uint32 m_bot_caster_range; uint32 m_bot_caster_range;
BotCastingRoles m_CastingRoles; BotCastingRoles m_CastingRoles;
+18 -355
View File
@@ -65,7 +65,7 @@
#include "dialogue_window.h" #include "dialogue_window.h"
#include "mob.h" #include "mob.h"
#include <fmt/format.h> #include <fmt/core.h>
extern QueryServ* QServ; extern QueryServ* QServ;
extern WorldServer worldserver; extern WorldServer worldserver;
@@ -1375,7 +1375,6 @@ int bot_command_init(void)
bot_command_add("casterrange", "Controls the range casters will try to stay away from a mob (if too far, they will skip spells that are out-of-range)", AccountStatus::Player, bot_command_caster_range) || bot_command_add("casterrange", "Controls the range casters will try to stay away from a mob (if too far, they will skip spells that are out-of-range)", AccountStatus::Player, bot_command_caster_range) ||
bot_command_add("charm", "Attempts to have a bot charm your target", AccountStatus::Player, bot_command_charm) || bot_command_add("charm", "Attempts to have a bot charm your target", AccountStatus::Player, bot_command_charm) ||
bot_command_add("circle", "Orders a Druid bot to open a magical doorway to a specified destination", AccountStatus::Player, bot_subcommand_circle) || bot_command_add("circle", "Orders a Druid bot to open a magical doorway to a specified destination", AccountStatus::Player, bot_subcommand_circle) ||
bot_command_add("clickitem", "Orders your targeted bot to click the item in the provided inventory slot.", AccountStatus::Player, bot_command_click_item) ||
bot_command_add("cure", "Orders a bot to remove any ailments", AccountStatus::Player, bot_command_cure) || bot_command_add("cure", "Orders a bot to remove any ailments", AccountStatus::Player, bot_command_cure) ||
bot_command_add("defensive", "Orders a bot to use a defensive discipline", AccountStatus::Player, bot_command_defensive) || bot_command_add("defensive", "Orders a bot to use a defensive discipline", AccountStatus::Player, bot_command_defensive) ||
bot_command_add("depart", "Orders a bot to open a magical doorway to a specified destination", AccountStatus::Player, bot_command_depart) || bot_command_add("depart", "Orders a bot to open a magical doorway to a specified destination", AccountStatus::Player, bot_command_depart) ||
@@ -1445,7 +1444,6 @@ int bot_command_init(void)
bot_command_add("summoncorpse", "Orders a bot to summon a corpse to its feet", AccountStatus::Player, bot_command_summon_corpse) || bot_command_add("summoncorpse", "Orders a bot to summon a corpse to its feet", AccountStatus::Player, bot_command_summon_corpse) ||
bot_command_add("suspend", "Suspends a bot's AI processing until released", AccountStatus::Player, bot_command_suspend) || bot_command_add("suspend", "Suspends a bot's AI processing until released", AccountStatus::Player, bot_command_suspend) ||
bot_command_add("taunt", "Toggles taunt use by a bot", AccountStatus::Player, bot_command_taunt) || bot_command_add("taunt", "Toggles taunt use by a bot", AccountStatus::Player, bot_command_taunt) ||
bot_command_add("timer", "Checks or clears timers of the chosen type.", AccountStatus::GMMgmt, bot_command_timer) ||
bot_command_add("track", "Orders a capable bot to track enemies", AccountStatus::Player, bot_command_track) || bot_command_add("track", "Orders a capable bot to track enemies", AccountStatus::Player, bot_command_track) ||
bot_command_add("viewcombos", "Views bot race class combinations", AccountStatus::Player, bot_command_view_combos) || bot_command_add("viewcombos", "Views bot race class combinations", AccountStatus::Player, bot_command_view_combos) ||
bot_command_add("waterbreathing", "Orders a bot to cast a water breathing spell", AccountStatus::Player, bot_command_water_breathing) bot_command_add("waterbreathing", "Orders a bot to cast a water breathing spell", AccountStatus::Player, bot_command_water_breathing)
@@ -2834,7 +2832,7 @@ void bot_command_aggressive(Client *c, const Seperator *sep)
} }
} }
c->Message(Chat::White, "%i of %i bots have attempted to use aggressive disciplines", success_count, candidate_count); c->Message(Chat::White, "%i of %i bots have used aggressive disciplines", success_count, candidate_count);
} }
void bot_command_apply_poison(Client *c, const Seperator *sep) void bot_command_apply_poison(Client *c, const Seperator *sep)
@@ -3302,7 +3300,7 @@ void bot_command_defensive(Client *c, const Seperator *sep)
auto local_entry = list_iter->SafeCastToStance(); auto local_entry = list_iter->SafeCastToStance();
if (helper_spell_check_fail(local_entry)) if (helper_spell_check_fail(local_entry))
continue; continue;
if (local_entry->stance_type != BCEnum::StT_Defensive) if (local_entry->stance_type != BCEnum::StT_Aggressive)
continue; continue;
for (auto bot_iter = sbl.begin(); bot_iter != sbl.end(); ) { for (auto bot_iter = sbl.begin(); bot_iter != sbl.end(); ) {
@@ -3334,7 +3332,7 @@ void bot_command_defensive(Client *c, const Seperator *sep)
} }
} }
c->Message(Chat::White, "%i of %i bots have attempted to use defensive disciplines", success_count, candidate_count); c->Message(Chat::White, "%i of %i bots have used defensive disciplines", success_count, candidate_count);
} }
void bot_command_depart(Client *c, const Seperator *sep) void bot_command_depart(Client *c, const Seperator *sep)
@@ -3908,77 +3906,16 @@ void bot_command_invisibility(Client *c, const Seperator *sep)
void bot_command_item_use(Client* c, const Seperator* sep) void bot_command_item_use(Client* c, const Seperator* sep)
{ {
if (helper_is_help_or_usage(sep->arg[1])) { if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: [%s empty] will display only bots that can use the item in an empty slot.", sep->arg[0]); c->Message(Chat::White, "usage: %s ([empty])", sep->arg[0]);
c->Message(Chat::White, "usage: [%s byclass classID] - Example: [%s byclass 7] will display only bots that match the class that can use the item. Example is a Monk, use [^create help] for a list of class IDs.", sep->arg[0], sep->arg[0]);
c->Message(Chat::White, "usage: [%s casteronly] will display only caster bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s hybridonly] will display only hybrid bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s meleeonly] will display only melee bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s wiscasteronly] will display only Wisdom-based Caster bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s intcasteronly] will display only Intelligence-based Caster bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s plateonly] will display only Plate-wearing bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s chainonly] will display only Chain-wearing bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s leatheronly] will display only Leather-wearing bots that can use the item.", sep->arg[0]);
c->Message(Chat::White, "usage: [%s clothonly] will display only Cloth-wearing bots that can use the item.", sep->arg[0]);
return; return;
} }
bool empty_only = false; bool empty_only = false;
int8 class_mask = 0;
bool caster_only = false;
bool hybrid_only = false;
bool melee_only = false;
bool wis_caster_only = false;
bool int_caster_only = false;
bool plate_only = false;
bool chain_only = false;
bool leather_only = false;
bool cloth_only = false;
std::string arg1 = sep->arg[1]; std::string arg1 = sep->arg[1];
std::string arg2 = sep->arg[2];
if (arg1.compare("empty") == 0) { if (arg1.compare("empty") == 0) {
empty_only = true; empty_only = true;
} }
else if (arg1.compare("byclass") == 0) {
if (Strings::IsNumber(sep->arg[2])) {
class_mask = Strings::ToUnsignedInt(sep->arg[2]);
if (!(class_mask >= Class::Warrior && class_mask <= Class::Berserker)) {
c->Message(Chat::White, "Invalid class range, you must choose between 1 (Warrior) and 15 (Beastlord)");
return;
}
}
}
else if (arg1.compare("casteronly") == 0) {
caster_only = true;
}
else if (arg1.compare("hybridonly") == 0) {
hybrid_only = true;
}
else if (arg1.compare("meleeonly") == 0) {
melee_only = true;
}
else if (arg1.compare("wiscasteronly") == 0) {
wis_caster_only = true;
}
else if (arg1.compare("intcasteronly") == 0) {
int_caster_only = true;
}
else if (arg1.compare("plateonly") == 0) {
plate_only = true;
}
else if (arg1.compare("chainonly") == 0) {
chain_only = true;
}
else if (arg1.compare("leatheronly") == 0) {
leather_only = true;
}
else if (arg1.compare("clothonly") == 0) {
cloth_only = true;
}
else if (!arg1.empty()) {
c->Message(Chat::White, "Please choose the correct subtype. For help use %s help.", sep->arg[0]);
return;
}
const auto item_instance = c->GetInv().GetItem(EQ::invslot::slotCursor); const auto item_instance = c->GetInv().GetItem(EQ::invslot::slotCursor);
if (!item_instance) { if (!item_instance) {
c->Message(Chat::White, "No item found on cursor!"); c->Message(Chat::White, "No item found on cursor!");
@@ -4011,41 +3948,11 @@ void bot_command_item_use(Client* c, const Seperator* sep)
std::list<Bot*> sbl; std::list<Bot*> sbl;
MyBots::PopulateSBL_BySpawnedBots(c, sbl); MyBots::PopulateSBL_BySpawnedBots(c, sbl);
if (class_mask) {
ActionableBots::Filter_ByClasses(c, sbl, GetPlayerClassBit(class_mask));
}
for (const auto& bot_iter : sbl) { for (const auto& bot_iter : sbl) {
if (!bot_iter) { if (!bot_iter) {
continue; continue;
} }
if (caster_only && !IsCasterClass(bot_iter->GetClass())) {
continue;
}
if (hybrid_only && !IsSpellFighterClass(bot_iter->GetClass())) {
continue;
}
if (melee_only && !IsNonSpellFighterClass(bot_iter->GetClass())) {
continue;
}
if (wis_caster_only && !IsWISCasterClass(bot_iter->GetClass())) {
continue;
}
if (int_caster_only && !IsINTCasterClass(bot_iter->GetClass())) {
continue;
}
if (plate_only && !IsPlateClass(bot_iter->GetClass())) {
continue;
}
if (chain_only && !IsChainClass(bot_iter->GetClass())) {
continue;
}
if (leather_only && !IsLeatherClass(bot_iter->GetClass())) {
continue;
}
if (cloth_only && !IsClothClass(bot_iter->GetClass())) {
continue;
}
if (((~item_data->Races) & GetPlayerRaceBit(bot_iter->GetRace())) || ((~item_data->Classes) & GetPlayerClassBit(bot_iter->GetClass()))) { if (((~item_data->Races) & GetPlayerRaceBit(bot_iter->GetRace())) || ((~item_data->Classes) & GetPlayerClassBit(bot_iter->GetClass()))) {
continue; continue;
} }
@@ -4090,8 +3997,7 @@ void bot_command_item_use(Client* c, const Seperator* sep)
); );
bot_iter->DoAnim(29); bot_iter->DoAnim(29);
} } else if (!equipped_item) {
else if (!equipped_item) {
c->Message( c->Message(
Chat::Say, Chat::Say,
fmt::format( fmt::format(
@@ -5288,194 +5194,6 @@ void bot_command_taunt(Client *c, const Seperator *sep)
} }
} }
void bot_command_timer(Client* c, const Seperator* sep)
{
if (helper_command_alias_fail(c, "bot_command_timer", sep->arg[0], "timer"))
return;
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: %s [clear | has | set] [disc | item | spell] [timer ID | item ID | spell ID | all] [optional ms for set] [actionable].", sep->arg[0]);
c->Message(Chat::White, "When setting, you can leave the value blank to use the default for the item or specify a value in ms to set the timer to.");
c->Message(Chat::White, "Returns or sets the provided timer(s) for the selected bot(s) or clears the selected timer(s) for the selected bot(s).");
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
std::string arg1 = sep->arg[1];
std::string arg2 = sep->arg[2];
std::string arg3 = sep->arg[3];
int ab_arg = 4;
bool clear = false;
bool has = false;
bool set = false;
bool disc = false;
bool item = false;
bool spell = false;
uint32 timer_id = 0;
uint32 timer_value = 0;
bool all = false;
if (!arg1.compare("clear")) {
clear = true;
}
else if (!arg1.compare("has")) {
has = true;
}
else if (!arg1.compare("set")) {
set = true;
}
else {
c->Message(Chat::White, "Incorrect argument, use %s help for a list of options.", sep->arg[0]);
return;
}
if (!arg2.compare("disc")) {
disc = true;
}
else if (!arg2.compare("item")) {
item = true;
}
else if (!arg2.compare("spell")) {
spell = true;
}
else {
c->Message(Chat::White, "Incorrect timer type, use %s help for a list of options.", sep->arg[0]);
return;
}
if (sep->IsNumber(3)) {
timer_id = atoi(sep->arg[3]);
if (timer_id < 0) {
c->Message(Chat::White, "You cannot use negative numbers.");
return;
}
}
else if (!arg3.compare("all")) {
if (has || set) {
c->Message(Chat::White, "You can only use 'all' for clearing timers.");
return;
}
all = true;
}
else {
c->Message(Chat::White, "Incorrect ID option, use %s help for a list of options.", sep->arg[0]);
return;
}
if (set) {
if (sep->IsNumber(4)) {
ab_arg = 5;
timer_value = atoi(sep->arg[4]);
if (timer_value <= 0) {
c->Message(Chat::White, "You cannot use 0 or negative numbers.");
return;
}
}
}
std::string class_race_arg = sep->arg[ab_arg];
bool class_race_check = false;
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
class_race_check = true;
}
std::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
return;
}
sbl.remove(nullptr);
for (auto my_bot : sbl) {
bool found = false;
if (clear) {
c->Message(
Chat::White,
fmt::format(
"{} says, 'Clearing {} timer{}'",
my_bot->GetCleanName(),
disc ? "Discipline" : item ? "Item" : "Spell",
(all ? "s." : ".")
).c_str()
);
if (disc) {
my_bot->ClearDisciplineReuseTimer(timer_id);
}
else if (item) {
my_bot->ClearItemReuseTimer(timer_id);
}
else if (spell) {
my_bot->ClearSpellRecastTimer(timer_id);
}
}
else if (has) {
uint32 remaining_time;
std::string time_string = "";
if (disc) {
if (!my_bot->CheckDisciplineReuseTimer(timer_id)) {
remaining_time = my_bot->GetDisciplineReuseRemainingTime(timer_id) / 1000;
time_string = Strings::SecondsToTime(remaining_time);
found = true;
}
}
else if (item) {
if (!my_bot->CheckItemReuseTimer(timer_id)) {
remaining_time = my_bot->GetItemReuseRemainingTime(timer_id) / 1000;
time_string = Strings::SecondsToTime(remaining_time);
found = true;
}
}
else if (spell) {
if (!my_bot->CheckSpellRecastTimer(timer_id)) {
remaining_time = my_bot->GetSpellRecastRemainingTime(timer_id) / 1000;
time_string = Strings::SecondsToTime(remaining_time);
found = true;
}
}
c->Message(
Chat::White,
fmt::format(
"{} says, 'I {}{}{}'",
my_bot->GetCleanName(),
(!found ? " do not have that timer currently" : " have "),
(!found ? "" : time_string),
(!found ? "." : " remaining.")
).c_str()
);
}
else if (set) {
c->Message(
Chat::White,
fmt::format(
"{} says, 'Setting {} timer{} for {} to {}.'",
my_bot->GetCleanName(),
disc ? "Discipline" : item ? "Item" : "Spell",
(all ? "s" : ""),
timer_id,
timer_value ? std::to_string(timer_value) : "the default value"
).c_str()
);
if (disc) {
my_bot->ClearDisciplineReuseTimer(timer_id);
my_bot->SetDisciplineReuseTimer(timer_id, timer_value);
}
else if (item) {
my_bot->ClearItemReuseTimer(timer_id);
my_bot->SetItemReuseTimer(timer_id, timer_value);
}
else if (spell) {
my_bot->ClearSpellRecastTimer(timer_id);
my_bot->SetSpellRecastTimer(timer_id, timer_value);
}
}
}
}
void bot_command_track(Client *c, const Seperator *sep) void bot_command_track(Client *c, const Seperator *sep)
{ {
if (helper_command_alias_fail(c, "bot_command_track", sep->arg[0], "track")) if (helper_command_alias_fail(c, "bot_command_track", sep->arg[0], "track"))
@@ -5913,11 +5631,11 @@ void bot_command_view_combos(Client *c, const Seperator *sep)
}; };
const uint16 race_values[17] = { const uint16 race_values[17] = {
Race::Doug, RACE_DOUG_0,
Race::Human, Race::Barbarian, Race::Erudite, Race::WoodElf, RACE_HUMAN_1, RACE_BARBARIAN_2, RACE_ERUDITE_3, RACE_WOOD_ELF_4,
Race::HighElf, Race::DarkElf, Race::HalfElf, Race::Dwarf, RACE_HIGH_ELF_5, RACE_DARK_ELF_6, RACE_HALF_ELF_7, RACE_DWARF_8,
Race::Troll, Race::Ogre, Race::Halfling, Race::Gnome, RACE_TROLL_9, RACE_OGRE_10, RACE_HALFLING_11, RACE_GNOME_12,
Race::Iksar, Race::VahShir, Race::Froglok2, Race::Drakkin RACE_IKSAR_128, RACE_VAH_SHIR_130, RACE_FROGLOK_330, RACE_DRAKKIN_522
}; };
if (helper_command_alias_fail(c, "bot_command_view_combos", sep->arg[0], "viewcombos")) { if (helper_command_alias_fail(c, "bot_command_view_combos", sep->arg[0], "viewcombos")) {
@@ -6028,11 +5746,11 @@ void bot_subcommand_bot_create(Client *c, const Seperator *sep)
}; };
const uint16 race_values[17] = { const uint16 race_values[17] = {
Race::Doug, RACE_DOUG_0,
Race::Human, Race::Barbarian, Race::Erudite, Race::WoodElf, RACE_HUMAN_1, RACE_BARBARIAN_2, RACE_ERUDITE_3, RACE_WOOD_ELF_4,
Race::HighElf, Race::DarkElf, Race::HalfElf, Race::Dwarf, RACE_HIGH_ELF_5, RACE_DARK_ELF_6, RACE_HALF_ELF_7, RACE_DWARF_8,
Race::Troll, Race::Ogre, Race::Halfling, Race::Gnome, RACE_TROLL_9, RACE_OGRE_10, RACE_HALFLING_11, RACE_GNOME_12,
Race::Iksar, Race::VahShir, Race::Froglok2, Race::Drakkin RACE_IKSAR_128, RACE_VAH_SHIR_130, RACE_FROGLOK_330, RACE_DRAKKIN_522
}; };
const std::string gender_substrs[2] = { const std::string gender_substrs[2] = {
@@ -10720,61 +10438,6 @@ void bot_command_caster_range(Client* c, const Seperator* sep)
} }
} }
void bot_command_click_item(Client* c, const Seperator* sep)
{
if (!RuleB(Bots, BotsCanClickItems)) {
c->Message(Chat::White, "The ability for bots to click equipped items is currently disabled.");
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
c->Message(Chat::White, "usage: <slot id> %s ([actionable: target | byname | ownergroup | ownerraid | targetgroup | namesgroup | byclass | byrace | spawned] ([actionable_name]))", sep->arg[0]);
c->Message(Chat::White, "This will cause the selected bots to click the item in the given slot ID.");
c->Message(Chat::White, "Use ^invlist to see their items along with slot IDs.");
return;
}
if (!sep->IsNumber(1)) {
c->Message(Chat::Yellow, "You must specify a slot ID. Use %s help for more information.", sep->arg[0]);
return;
}
const int ab_mask = ActionableBots::ABM_Type1;
int ab_arg = 1;
uint32 slot_id = 0;
if (sep->IsNumber(1)) {
ab_arg = 2;
slot_id = atoi(sep->arg[1]);
if (slot_id < EQ::invslot::EQUIPMENT_BEGIN || slot_id > EQ::invslot::EQUIPMENT_END) {
c->Message(Chat::Yellow, "You must specify a valid inventory slot from 0 to 22. Use %s help for more information", sep->arg[0]);
return;
}
}
std::string class_race_arg = sep->arg[ab_arg];
bool class_race_check = false;
if (!class_race_arg.compare("byclass") || !class_race_arg.compare("byrace")) {
class_race_check = true;
}
std::list<Bot*> sbl;
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, !class_race_check ? sep->arg[ab_arg + 1] : nullptr, class_race_check ? atoi(sep->arg[ab_arg + 1]) : 0) == ActionableBots::ABT_None) {
return;
}
sbl.remove(nullptr);
for (auto my_bot : sbl) {
if (RuleI(Bots, BotsClickItemsMinLvl) > my_bot->GetLevel()) {
c->Message(Chat::White, "%s must be level %i to use clickable items.", my_bot->GetCleanName(), RuleI(Bots, BotsClickItemsMinLvl));
continue;
}
my_bot->TryItemClick(slot_id);
}
}
void bot_command_pickpocket(Client *c, const Seperator *sep) void bot_command_pickpocket(Client *c, const Seperator *sep)
{ {
if (helper_command_disabled(c, RuleB(Bots, AllowPickpocketCommand), "pickpocket")) { if (helper_command_disabled(c, RuleB(Bots, AllowPickpocketCommand), "pickpocket")) {
-2
View File
@@ -554,7 +554,6 @@ void bot_command_bind_affinity(Client *c, const Seperator *sep);
void bot_command_bot(Client *c, const Seperator *sep); void bot_command_bot(Client *c, const Seperator *sep);
void bot_command_caster_range(Client* c, const Seperator* sep); void bot_command_caster_range(Client* c, const Seperator* sep);
void bot_command_charm(Client *c, const Seperator *sep); void bot_command_charm(Client *c, const Seperator *sep);
void bot_command_click_item(Client* c, const Seperator* sep);
void bot_command_cure(Client *c, const Seperator *sep); void bot_command_cure(Client *c, const Seperator *sep);
void bot_command_defensive(Client *c, const Seperator *sep); void bot_command_defensive(Client *c, const Seperator *sep);
void bot_command_depart(Client *c, const Seperator *sep); void bot_command_depart(Client *c, const Seperator *sep);
@@ -596,7 +595,6 @@ void bot_command_enforce_spell_list(Client* c, const Seperator* sep);
void bot_command_summon_corpse(Client *c, const Seperator *sep); void bot_command_summon_corpse(Client *c, const Seperator *sep);
void bot_command_suspend(Client *c, const Seperator *sep); void bot_command_suspend(Client *c, const Seperator *sep);
void bot_command_taunt(Client *c, const Seperator *sep); void bot_command_taunt(Client *c, const Seperator *sep);
void bot_command_timer(Client* c, const Seperator* sep);
void bot_command_track(Client *c, const Seperator *sep); void bot_command_track(Client *c, const Seperator *sep);
void bot_command_view_combos(Client *c, const Seperator *sep); void bot_command_view_combos(Client *c, const Seperator *sep);
void bot_command_water_breathing(Client *c, const Seperator *sep); void bot_command_water_breathing(Client *c, const Seperator *sep);
+54 -77
View File
@@ -24,13 +24,12 @@
#include "../common/repositories/bot_data_repository.h" #include "../common/repositories/bot_data_repository.h"
#include "../common/repositories/bot_inventories_repository.h" #include "../common/repositories/bot_inventories_repository.h"
#include "../common/repositories/bot_timers_repository.h"
#include "zonedb.h" #include "zonedb.h"
#include "bot.h" #include "bot.h"
#include "client.h" #include "client.h"
#include <fmt/format.h> #include <fmt/core.h>
bool BotDatabase::LoadBotCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &bot_command_settings) bool BotDatabase::LoadBotCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &bot_command_settings)
@@ -918,39 +917,45 @@ bool BotDatabase::LoadTimers(Bot* bot_inst)
if (!bot_inst) if (!bot_inst)
return false; return false;
auto timers = BotTimersRepository::GetWhere( query = StringFormat(
database, "SELECT"
fmt::format("bot_id = {}", bot_inst->GetBotID()) " IfNull(bt.`timer_id`, '0') As timer_id,"
" IfNull(bt.`timer_value`, '0') As timer_value,"
" IfNull(MAX(sn.`recast_time`), '0') AS MaxTimer"
" FROM `bot_timers` bt, `spells_new` sn"
" WHERE bt.`bot_id` = '%u' AND sn.`EndurTimerIndex` = ("
"SELECT case"
" WHEN timer_id > '%i' THEN timer_id - '%i'"
" ELSE timer_id END AS timer_id"
" FROM `bot_timers` WHERE `timer_id` = bt.`timer_id` AND `bot_id` = bt.`bot_id`" // double-check validity
")"
" AND sn.`classes%i` <= '%i'",
bot_inst->GetBotID(),
(DisciplineReuseStart - 1),
(DisciplineReuseStart - 1),
bot_inst->GetClass(),
bot_inst->GetLevel()
); );
auto results = database.QueryDatabase(query);
if (!results.Success())
return false;
if (!results.RowCount())
return true;
std::vector<BotTimer_Struct> bot_timers; uint32* bot_timers = bot_inst->GetTimers();
if (!bot_timers)
return false;
BotTimer_Struct t{}; int timer_id = 0;
t.timer_id = 0; uint32 timer_value = 0;
t.timer_value = 0; uint32 max_value = 0;
t.recast_time = 0; for (auto row = results.begin(); row != results.end(); ++row) {
t.is_spell = false; timer_id = Strings::ToInt(row[0]) - 1;
t.is_disc = false; timer_value = Strings::ToInt(row[1]);
t.spell_id = 0; max_value = Strings::ToInt(row[2]);
t.is_item = false;
t.item_id = 0;
for (auto& timer : timers) { if (timer_id >= 0 && timer_id < MaxTimer && timer_value < (Timer::GetCurrentTime() + max_value))
if (t.timer_value < (Timer::GetCurrentTime() + t.recast_time)) { bot_timers[timer_id] = timer_value;
t.timer_id = timer.timer_id;
t.timer_value = timer.timer_value;
t.recast_time = timer.recast_time;
t.is_spell = timer.is_spell ? true : false;
t.is_disc = timer.is_disc ? true : false;
t.spell_id = timer.spell_id;
t.is_item = timer.is_item ? true : false;
t.item_id = timer.item_id;
bot_timers.push_back(t);
}
}
if (!bot_timers.empty()) {
bot_inst->SetBotTimers(bot_timers);
} }
return true; return true;
@@ -958,56 +963,26 @@ bool BotDatabase::LoadTimers(Bot* bot_inst)
bool BotDatabase::SaveTimers(Bot* bot_inst) bool BotDatabase::SaveTimers(Bot* bot_inst)
{ {
if (!bot_inst) { if (!bot_inst)
return false; return false;
}
if (!DeleteTimers(bot_inst->GetBotID())) { if (!DeleteTimers(bot_inst->GetBotID()))
return false; return false;
}
std::vector<BotTimer_Struct> bot_timers = bot_inst->GetBotTimers(); uint32* bot_timers = bot_inst->GetTimers();
if (!bot_timers)
return false;
if (bot_timers.empty()) { for (int timer_index = 0; timer_index < MaxTimer; ++timer_index) {
return true; if (bot_timers[timer_index] <= Timer::GetCurrentTime())
} continue;
std::vector<BotTimersRepository::BotTimers> timers; query = fmt::format(
"REPLACE INTO `bot_timers` (`bot_id`, `timer_id`, `timer_value`) VALUES ('{}', '{}', '{}')",
if (!bot_timers.empty()) { bot_inst->GetBotID(), (timer_index + 1), bot_timers[timer_index]
for (auto & bot_timer : bot_timers) {
if (bot_timer.timer_value <= Timer::GetCurrentTime()) {
continue;
}
auto t = BotTimersRepository::BotTimers{
.bot_id = bot_inst->GetBotID(),
.timer_id = bot_timer.timer_id,
.timer_value = bot_timer.timer_value,
.recast_time = bot_timer.recast_time,
.is_spell = bot_timer.is_spell ? true : false,
.is_disc = bot_timer.is_disc ? true : false,
.spell_id = bot_timer.spell_id,
.is_item = bot_timer.is_item ? true : false,
.item_id = bot_timer.item_id
};
timers.push_back(t);
}
if (timers.empty()) {
return true;
}
// delete existing
BotTimersRepository::DeleteWhere(
database,
fmt::format("bot_id = {}", bot_inst->GetBotID())
); );
auto results = database.QueryDatabase(query);
// bulk insert current if (!results.Success()) {
auto success = BotTimersRepository::InsertMany(database, timers);
if (!success) {
DeleteTimers(bot_inst->GetBotID()); DeleteTimers(bot_inst->GetBotID());
return false; return false;
} }
@@ -1018,11 +993,13 @@ bool BotDatabase::SaveTimers(Bot* bot_inst)
bool BotDatabase::DeleteTimers(const uint32 bot_id) bool BotDatabase::DeleteTimers(const uint32 bot_id)
{ {
if (!bot_id) { if (!bot_id)
return false; return false;
}
BotTimersRepository::DeleteWhere(database, fmt::format("bot_id = {}", bot_id)); query = StringFormat("DELETE FROM `bot_timers` WHERE `bot_id` = '%u'", bot_id);
auto results = database.QueryDatabase(query);
if (!results.Success())
return false;
return true; return true;
} }
-11
View File
@@ -81,15 +81,4 @@ struct BotSpells_Struct {
uint8 bucket_comparison; uint8 bucket_comparison;
}; };
struct BotTimer_Struct {
uint32 timer_id;
uint32 timer_value;
uint32 recast_time;
bool is_spell;
bool is_disc;
uint16 spell_id;
bool is_item;
uint32 item_id;
};
#endif // BOT_STRUCTS #endif // BOT_STRUCTS
+111 -46
View File
@@ -108,7 +108,7 @@ bool Bot::BotCastSong(Mob* tar, uint8 botLevel) {
auto iter : botSongList) { auto iter : botSongList) {
if (!iter.SpellId) if (!iter.SpellId)
continue; continue;
if (!CheckSpellRecastTimer(iter.SpellId)) if (!CheckSpellRecastTimers(this, iter.SpellIndex))
continue; continue;
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType())) if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
continue; continue;
@@ -142,7 +142,7 @@ bool Bot::BotCastCombatSong(Mob* tar, uint8 botLevel) {
auto iter : botSongList) { auto iter : botSongList) {
if (!iter.SpellId) if (!iter.SpellId)
continue; continue;
if (!CheckSpellRecastTimer(iter.SpellId)) if (!CheckSpellRecastTimers(this, iter.SpellIndex))
continue; continue;
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType())) if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
continue; continue;
@@ -174,7 +174,7 @@ bool Bot::BotCastHateReduction(Mob* tar, uint8 botLevel, const BotSpell& botSpel
for (auto iter : botSongList) { for (auto iter : botSongList) {
if (!iter.SpellId) if (!iter.SpellId)
continue; continue;
if (!CheckSpellRecastTimer(iter.SpellId)) if (!CheckSpellRecastTimers(this, iter.SpellIndex))
continue; continue;
if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType())) if (!IsSpellUsableInThisZoneType(iter.SpellId, zone->GetZoneType()))
continue; continue;
@@ -312,7 +312,7 @@ bool Bot::BotCastSlow(Mob* tar, uint8 botLevel, uint8 botClass, BotSpell& botSpe
continue; continue;
} }
if (!CheckSpellRecastTimer(iter.SpellId)) { if (!CheckSpellRecastTimers(this, iter.SpellIndex)) {
continue; continue;
} }
@@ -403,7 +403,7 @@ bool Bot::BotCastDOT(Mob* tar, uint8 botLevel, const BotSpell& botSpell, const b
continue; continue;
} }
if (CheckSpellRecastTimer(s.SpellId)) if (CheckSpellRecastTimers(this, s.SpellIndex))
{ {
if (!(!tar->IsImmuneToSpell(s.SpellId, this) && tar->CanBuffStack(s.SpellId, botLevel, true) >= 0)) { if (!(!tar->IsImmuneToSpell(s.SpellId, this) && tar->CanBuffStack(s.SpellId, botLevel, true) >= 0)) {
@@ -438,7 +438,7 @@ bool Bot::BotCastDOT(Mob* tar, uint8 botLevel, const BotSpell& botSpell, const b
continue; continue;
} }
if (CheckSpellRecastTimer(s.SpellId)) { if (CheckSpellRecastTimers(this, s.SpellIndex)) {
if (!(!tar->IsImmuneToSpell(s.SpellId, this) && if (!(!tar->IsImmuneToSpell(s.SpellId, this) &&
tar->CanBuffStack(s.SpellId, botLevel, true) >= 0)) { tar->CanBuffStack(s.SpellId, botLevel, true) >= 0)) {
@@ -652,7 +652,7 @@ bool Bot::BotCastCombatBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
} }
} }
if (CheckSpellRecastTimer(s.SpellId)) { if (CheckSpellRecastTimers(this, s.SpellIndex)) {
uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore(); uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore();
casted_spell = AIDoSpellCast(s.SpellIndex, tar, s.ManaCost, &TempDontBuffMeBefore); casted_spell = AIDoSpellCast(s.SpellIndex, tar, s.ManaCost, &TempDontBuffMeBefore);
if (TempDontBuffMeBefore != tar->DontBuffMeBefore()) { if (TempDontBuffMeBefore != tar->DontBuffMeBefore()) {
@@ -947,7 +947,7 @@ bool Bot::BotCastBuff(Mob* tar, uint8 botLevel, uint8 botClass) {
} }
} }
if (CheckSpellRecastTimer(s.SpellId)) if (CheckSpellRecastTimers(this, s.SpellIndex))
{ {
uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore(); uint32 TempDontBuffMeBefore = tar->DontBuffMeBefore();
@@ -1306,8 +1306,10 @@ bool Bot::AIDoSpellCast(int32 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain
SetMana(hasMana); SetMana(hasMana);
} }
else { else {
if (CalcSpellRecastTimer(AIBot_spells[i].spellid) > 0) { AIBot_spells[i].time_cancast = Timer::GetCurrentTime() + spells[AIBot_spells[i].spellid].recast_time;
SetSpellRecastTimer(AIBot_spells[i].spellid);
if (spells[AIBot_spells[i].spellid].timer_id > 0) {
SetSpellRecastTimer(spells[AIBot_spells[i].spellid].timer_id, spells[AIBot_spells[i].spellid].recast_time);
} }
} }
@@ -2042,7 +2044,7 @@ BotSpell Bot::GetFirstBotSpellBySpellType(Bot* botCaster, uint32 spellType) {
continue; continue;
} }
if ((botSpellList[i].type & spellType) && botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) { if ((botSpellList[i].type & spellType) && CheckSpellRecastTimers(botCaster, i)) {
result.SpellId = botSpellList[i].spellid; result.SpellId = botSpellList[i].spellid;
result.SpellIndex = i; result.SpellIndex = i;
result.ManaCost = botSpellList[i].manacost; result.ManaCost = botSpellList[i].manacost;
@@ -2067,7 +2069,7 @@ BotSpell Bot::GetBestBotSpellForFastHeal(Bot *botCaster) {
for (auto botSpellListItr : botSpellList) { for (auto botSpellListItr : botSpellList) {
// Assuming all the spells have been loaded into this list by level and in descending order // Assuming all the spells have been loaded into this list by level and in descending order
if (IsFastHealSpell(botSpellListItr.SpellId) && botCaster->CheckSpellRecastTimer(botSpellListItr.SpellId)) { if (IsFastHealSpell(botSpellListItr.SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr.SpellIndex)) {
result.SpellId = botSpellListItr.SpellId; result.SpellId = botSpellListItr.SpellId;
result.SpellIndex = botSpellListItr.SpellIndex; result.SpellIndex = botSpellListItr.SpellIndex;
result.ManaCost = botSpellListItr.ManaCost; result.ManaCost = botSpellListItr.ManaCost;
@@ -2104,7 +2106,7 @@ BotSpell Bot::GetBestBotSpellForHealOverTime(Bot* botCaster) {
if ( if (
botSpellList[i].spellid == botSpellListItr.SpellId && botSpellList[i].spellid == botSpellListItr.SpellId &&
(botSpellList[i].type & SpellType_Heal) && (botSpellList[i].type & SpellType_Heal) &&
botCaster->CheckSpellRecastTimer(botSpellListItr.SpellId) CheckSpellRecastTimers(botCaster, botSpellListItr.SpellIndex)
) { ) {
result.SpellId = botSpellListItr.SpellId; result.SpellId = botSpellListItr.SpellId;
result.SpellIndex = botSpellListItr.SpellIndex; result.SpellIndex = botSpellListItr.SpellIndex;
@@ -2137,7 +2139,7 @@ BotSpell Bot::GetBestBotSpellForPercentageHeal(Bot *botCaster) {
continue; continue;
} }
if (IsCompleteHealSpell(botSpellList[i].spellid) && botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) { if (IsCompleteHealSpell(botSpellList[i].spellid) && CheckSpellRecastTimers(botCaster, i)) {
result.SpellId = botSpellList[i].spellid; result.SpellId = botSpellList[i].spellid;
result.SpellIndex = i; result.SpellIndex = i;
result.ManaCost = botSpellList[i].manacost; result.ManaCost = botSpellList[i].manacost;
@@ -2161,7 +2163,7 @@ BotSpell Bot::GetBestBotSpellForRegularSingleTargetHeal(Bot* botCaster) {
for (std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { for (std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order // Assuming all the spells have been loaded into this list by level and in descending order
if (IsRegularSingleTargetHealSpell(botSpellListItr->SpellId) && botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)) { if (IsRegularSingleTargetHealSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) {
result.SpellId = botSpellListItr->SpellId; result.SpellId = botSpellListItr->SpellId;
result.SpellIndex = botSpellListItr->SpellIndex; result.SpellIndex = botSpellListItr->SpellIndex;
result.ManaCost = botSpellListItr->ManaCost; result.ManaCost = botSpellListItr->ManaCost;
@@ -2190,7 +2192,7 @@ BotSpell Bot::GetFirstBotSpellForSingleTargetHeal(Bot* botCaster) {
IsRegularSingleTargetHealSpell(botSpellListItr->SpellId) || IsRegularSingleTargetHealSpell(botSpellListItr->SpellId) ||
IsFastHealSpell(botSpellListItr->SpellId) IsFastHealSpell(botSpellListItr->SpellId)
) && ) &&
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId) CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
) { ) {
result.SpellId = botSpellListItr->SpellId; result.SpellId = botSpellListItr->SpellId;
result.SpellIndex = botSpellListItr->SpellIndex; result.SpellIndex = botSpellListItr->SpellIndex;
@@ -2217,7 +2219,7 @@ BotSpell Bot::GetBestBotSpellForGroupHeal(Bot* botCaster) {
// Assuming all the spells have been loaded into this list by level and in descending order // Assuming all the spells have been loaded into this list by level and in descending order
if ( if (
IsRegularGroupHealSpell(botSpellListItr->SpellId) && IsRegularGroupHealSpell(botSpellListItr->SpellId) &&
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId) CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
) { ) {
result.SpellId = botSpellListItr->SpellId; result.SpellId = botSpellListItr->SpellId;
result.SpellIndex = botSpellListItr->SpellIndex; result.SpellIndex = botSpellListItr->SpellIndex;
@@ -2255,7 +2257,7 @@ BotSpell Bot::GetBestBotSpellForGroupHealOverTime(Bot* botCaster) {
if ( if (
botSpellList[i].spellid == botSpellListItr->SpellId && botSpellList[i].spellid == botSpellListItr->SpellId &&
(botSpellList[i].type & SpellType_Heal) && (botSpellList[i].type & SpellType_Heal) &&
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId) CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
) { ) {
result.SpellId = botSpellListItr->SpellId; result.SpellId = botSpellListItr->SpellId;
result.SpellIndex = botSpellListItr->SpellIndex; result.SpellIndex = botSpellListItr->SpellIndex;
@@ -2285,7 +2287,7 @@ BotSpell Bot::GetBestBotSpellForGroupCompleteHeal(Bot* botCaster) {
// Assuming all the spells have been loaded into this list by level and in descending order // Assuming all the spells have been loaded into this list by level and in descending order
if ( if (
IsGroupCompleteHealSpell(botSpellListItr->SpellId) && IsGroupCompleteHealSpell(botSpellListItr->SpellId) &&
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId) CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
) { ) {
result.SpellId = botSpellListItr->SpellId; result.SpellId = botSpellListItr->SpellId;
result.SpellIndex = botSpellListItr->SpellIndex; result.SpellIndex = botSpellListItr->SpellIndex;
@@ -2312,7 +2314,7 @@ BotSpell Bot::GetBestBotSpellForMez(Bot* botCaster) {
// Assuming all the spells have been loaded into this list by level and in descending order // Assuming all the spells have been loaded into this list by level and in descending order
if ( if (
IsMesmerizeSpell(botSpellListItr->SpellId) && IsMesmerizeSpell(botSpellListItr->SpellId) &&
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId) CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
) { ) {
result.SpellId = botSpellListItr->SpellId; result.SpellId = botSpellListItr->SpellId;
result.SpellIndex = botSpellListItr->SpellIndex; result.SpellIndex = botSpellListItr->SpellIndex;
@@ -2341,7 +2343,7 @@ BotSpell Bot::GetBestBotSpellForMagicBasedSlow(Bot* botCaster) {
if ( if (
IsSlowSpell(botSpellListItr->SpellId) && IsSlowSpell(botSpellListItr->SpellId) &&
spells[botSpellListItr->SpellId].resist_type == RESIST_MAGIC && spells[botSpellListItr->SpellId].resist_type == RESIST_MAGIC &&
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId) CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
) { ) {
result.SpellId = botSpellListItr->SpellId; result.SpellId = botSpellListItr->SpellId;
result.SpellIndex = botSpellListItr->SpellIndex; result.SpellIndex = botSpellListItr->SpellIndex;
@@ -2369,7 +2371,7 @@ BotSpell Bot::GetBestBotSpellForDiseaseBasedSlow(Bot* botCaster) {
if ( if (
IsSlowSpell(botSpellListItr->SpellId) && IsSlowSpell(botSpellListItr->SpellId) &&
spells[botSpellListItr->SpellId].resist_type == RESIST_DISEASE && spells[botSpellListItr->SpellId].resist_type == RESIST_DISEASE &&
botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId) CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)
) { ) {
result.SpellId = botSpellListItr->SpellId; result.SpellId = botSpellListItr->SpellId;
result.SpellIndex = botSpellListItr->SpellIndex; result.SpellIndex = botSpellListItr->SpellIndex;
@@ -2435,7 +2437,7 @@ BotSpell Bot::GetBestBotMagicianPetSpell(Bot *botCaster) {
for(std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { for(std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order // Assuming all the spells have been loaded into this list by level and in descending order
if (IsSummonPetSpell(botSpellListItr->SpellId) && botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)) { if (IsSummonPetSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) {
if (!strncmp(spells[botSpellListItr->SpellId].teleport_zone, petType.c_str(), petType.length())) { if (!strncmp(spells[botSpellListItr->SpellId].teleport_zone, petType.c_str(), petType.length())) {
result.SpellId = botSpellListItr->SpellId; result.SpellId = botSpellListItr->SpellId;
result.SpellIndex = botSpellListItr->SpellIndex; result.SpellIndex = botSpellListItr->SpellIndex;
@@ -2544,7 +2546,7 @@ BotSpell Bot::GetBestBotSpellForNukeByTargetType(Bot* botCaster, SpellTargetType
for(std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { for(std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order // Assuming all the spells have been loaded into this list by level and in descending order
if ((IsPureNukeSpell(botSpellListItr->SpellId) || IsDamageSpell(botSpellListItr->SpellId)) && botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)) { if ((IsPureNukeSpell(botSpellListItr->SpellId) || IsDamageSpell(botSpellListItr->SpellId)) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) {
result.SpellId = botSpellListItr->SpellId; result.SpellId = botSpellListItr->SpellId;
result.SpellIndex = botSpellListItr->SpellIndex; result.SpellIndex = botSpellListItr->SpellIndex;
result.ManaCost = botSpellListItr->ManaCost; result.ManaCost = botSpellListItr->ManaCost;
@@ -2572,7 +2574,7 @@ BotSpell Bot::GetBestBotSpellForStunByTargetType(Bot* botCaster, SpellTargetType
for(std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) for(std::list<BotSpell>::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr)
{ {
// Assuming all the spells have been loaded into this list by level and in descending order // Assuming all the spells have been loaded into this list by level and in descending order
if (IsStunSpell(botSpellListItr->SpellId) && botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)) if (IsStunSpell(botSpellListItr->SpellId) && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex))
{ {
result.SpellId = botSpellListItr->SpellId; result.SpellId = botSpellListItr->SpellId;
result.SpellIndex = botSpellListItr->SpellIndex; result.SpellIndex = botSpellListItr->SpellIndex;
@@ -2612,7 +2614,7 @@ BotSpell Bot::GetBestBotWizardNukeSpellByTargetResists(Bot* botCaster, Mob* targ
// Assuming all the spells have been loaded into this list by level and in descending order // Assuming all the spells have been loaded into this list by level and in descending order
bool spellSelected = false; bool spellSelected = false;
if (botCaster->CheckSpellRecastTimer(botSpellListItr->SpellId)) { if (CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) {
if (selectLureNuke && (spells[botSpellListItr->SpellId].resist_difficulty < lureResisValue)) { if (selectLureNuke && (spells[botSpellListItr->SpellId].resist_difficulty < lureResisValue)) {
spellSelected = true; spellSelected = true;
} }
@@ -2680,7 +2682,7 @@ BotSpell Bot::GetDebuffBotSpell(Bot* botCaster, Mob *tar) {
if (((botSpellList[i].type & SpellType_Debuff) || IsDebuffSpell(botSpellList[i].spellid)) if (((botSpellList[i].type & SpellType_Debuff) || IsDebuffSpell(botSpellList[i].spellid))
&& (!tar->IsImmuneToSpell(botSpellList[i].spellid, botCaster) && (!tar->IsImmuneToSpell(botSpellList[i].spellid, botCaster)
&& tar->CanBuffStack(botSpellList[i].spellid, botCaster->GetLevel(), true) >= 0) && tar->CanBuffStack(botSpellList[i].spellid, botCaster->GetLevel(), true) >= 0)
&& botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) { && CheckSpellRecastTimers(botCaster, i)) {
result.SpellId = botSpellList[i].spellid; result.SpellId = botSpellList[i].spellid;
result.SpellIndex = i; result.SpellIndex = i;
result.ManaCost = botSpellList[i].manacost; result.ManaCost = botSpellList[i].manacost;
@@ -2733,7 +2735,7 @@ BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar) {
|| (needsDiseaseResistDebuff && (IsEffectInSpell(botSpellList[i].spellid, SE_ResistDisease)) || IsEffectInSpell(botSpellList[i].spellid, SE_ResistAll))) || (needsDiseaseResistDebuff && (IsEffectInSpell(botSpellList[i].spellid, SE_ResistDisease)) || IsEffectInSpell(botSpellList[i].spellid, SE_ResistAll)))
&& (!tar->IsImmuneToSpell(botSpellList[i].spellid, botCaster) && (!tar->IsImmuneToSpell(botSpellList[i].spellid, botCaster)
&& tar->CanBuffStack(botSpellList[i].spellid, botCaster->GetLevel(), true) >= 0) && tar->CanBuffStack(botSpellList[i].spellid, botCaster->GetLevel(), true) >= 0)
&& botCaster->CheckSpellRecastTimer(botSpellList[i].spellid)) { && CheckSpellRecastTimers(botCaster, i)) {
result.SpellId = botSpellList[i].spellid; result.SpellId = botSpellList[i].spellid;
result.SpellIndex = i; result.SpellIndex = i;
result.ManaCost = botSpellList[i].manacost; result.ManaCost = botSpellList[i].manacost;
@@ -2784,31 +2786,31 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) {
for (std::list<BotSpell_wPriority>::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) { for (std::list<BotSpell_wPriority>::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) {
BotSpell selectedBotSpell = *itr; BotSpell selectedBotSpell = *itr;
if (IsGroupSpell(itr->SpellId) && botCaster->CheckSpellRecastTimer(selectedBotSpell.SpellId)) { if (IsGroupSpell(itr->SpellId) && CheckSpellRecastTimers(botCaster, itr->SpellIndex)) {
if (selectedBotSpell.SpellId == 0) if (selectedBotSpell.SpellId == 0)
continue; continue;
if (isPoisoned && IsEffectInSpell(selectedBotSpell.SpellId, SE_PoisonCounter)) { if (isPoisoned && IsEffectInSpell(itr->SpellId, SE_PoisonCounter)) {
spellSelected = true; spellSelected = true;
} }
else if (isDiseased && IsEffectInSpell(selectedBotSpell.SpellId, SE_DiseaseCounter)) { else if (isDiseased && IsEffectInSpell(itr->SpellId, SE_DiseaseCounter)) {
spellSelected = true; spellSelected = true;
} }
else if (isCursed && IsEffectInSpell(selectedBotSpell.SpellId, SE_CurseCounter)) { else if (isCursed && IsEffectInSpell(itr->SpellId, SE_CurseCounter)) {
spellSelected = true; spellSelected = true;
} }
else if (isCorrupted && IsEffectInSpell(selectedBotSpell.SpellId, SE_CorruptionCounter)) { else if (isCorrupted && IsEffectInSpell(itr->SpellId, SE_CorruptionCounter)) {
spellSelected = true; spellSelected = true;
} }
else if (IsEffectInSpell(selectedBotSpell.SpellId, SE_DispelDetrimental)) { else if (IsEffectInSpell(itr->SpellId, SE_DispelDetrimental)) {
spellSelected = true; spellSelected = true;
} }
if (spellSelected) if (spellSelected)
{ {
result.SpellId = selectedBotSpell.SpellId; result.SpellId = itr->SpellId;
result.SpellIndex = selectedBotSpell.SpellIndex; result.SpellIndex = itr->SpellIndex;
result.ManaCost = selectedBotSpell.ManaCost; result.ManaCost = itr->ManaCost;
break; break;
} }
@@ -2821,31 +2823,31 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) {
for(std::list<BotSpell_wPriority>::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) { for(std::list<BotSpell_wPriority>::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) {
BotSpell selectedBotSpell = *itr; BotSpell selectedBotSpell = *itr;
if (botCaster->CheckSpellRecastTimer(selectedBotSpell.SpellId)) { if (CheckSpellRecastTimers(botCaster, itr->SpellIndex)) {
if (selectedBotSpell.SpellId == 0) if (selectedBotSpell.SpellId == 0)
continue; continue;
if (isPoisoned && IsEffectInSpell(selectedBotSpell.SpellId, SE_PoisonCounter)) { if (isPoisoned && IsEffectInSpell(itr->SpellId, SE_PoisonCounter)) {
spellSelected = true; spellSelected = true;
} }
else if (isDiseased && IsEffectInSpell(selectedBotSpell.SpellId, SE_DiseaseCounter)) { else if (isDiseased && IsEffectInSpell(itr->SpellId, SE_DiseaseCounter)) {
spellSelected = true; spellSelected = true;
} }
else if (isCursed && IsEffectInSpell(selectedBotSpell.SpellId, SE_CurseCounter)) { else if (isCursed && IsEffectInSpell(itr->SpellId, SE_CurseCounter)) {
spellSelected = true; spellSelected = true;
} }
else if (isCorrupted && IsEffectInSpell(selectedBotSpell.SpellId, SE_CorruptionCounter)) { else if (isCorrupted && IsEffectInSpell(itr->SpellId, SE_CorruptionCounter)) {
spellSelected = true; spellSelected = true;
} }
else if (IsEffectInSpell(selectedBotSpell.SpellId, SE_DispelDetrimental)) { else if (IsEffectInSpell(itr->SpellId, SE_DispelDetrimental)) {
spellSelected = true; spellSelected = true;
} }
if (spellSelected) if (spellSelected)
{ {
result.SpellId = selectedBotSpell.SpellId; result.SpellId = itr->SpellId;
result.SpellIndex = selectedBotSpell.SpellIndex; result.SpellIndex = itr->SpellIndex;
result.ManaCost = selectedBotSpell.ManaCost; result.ManaCost = itr->ManaCost;
break; break;
} }
@@ -2857,6 +2859,69 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) {
return result; return result;
} }
void Bot::SetSpellRecastTimer(int timer_index, int32 recast_delay) {
if (timer_index > 0 && timer_index <= MaxSpellTimer) {
timers[timer_index - 1] = Timer::GetCurrentTime() + recast_delay;
}
}
int32 Bot::GetSpellRecastTimer(Bot *caster, int timer_index) {
int32 result = 0;
if (caster) {
if (timer_index > 0 && timer_index <= MaxSpellTimer) {
result = caster->timers[timer_index - 1];
}
}
return result;
}
bool Bot::CheckSpellRecastTimers(Bot *caster, int SpellIndex) {
if (caster) {
if (caster->AIBot_spells[SpellIndex].time_cancast < Timer::GetCurrentTime()) { //checks spell recast
if (GetSpellRecastTimer(caster, spells[caster->AIBot_spells[SpellIndex].spellid].timer_id) < Timer::GetCurrentTime()) { //checks for spells on the same timer
return true; //can cast spell
}
}
}
return false;
}
void Bot::SetDisciplineRecastTimer(int timer_index, int32 recast_delay) {
if (timer_index > 0 && timer_index <= MaxDisciplineTimer) {
timers[DisciplineReuseStart + timer_index - 1] = Timer::GetCurrentTime() + recast_delay;
}
}
int32 Bot::GetDisciplineRecastTimer(Bot *caster, int timer_index) {
int32 result = 0;
if (caster) {
if (timer_index > 0 && timer_index <= MaxDisciplineTimer) {
result = caster->timers[DisciplineReuseStart + timer_index - 1];
}
}
return result;
}
uint32 Bot::GetDisciplineRemainingTime(Bot *caster, int timer_index) {
int32 result = 0;
if (caster) {
if (timer_index > 0 && timer_index <= MaxDisciplineTimer) {
if (GetDisciplineRecastTimer(caster, timer_index) > Timer::GetCurrentTime())
result = GetDisciplineRecastTimer(caster, timer_index) - Timer::GetCurrentTime();
}
}
return result;
}
bool Bot::CheckDisciplineRecastTimers(Bot *caster, int timer_index) {
if (caster) {
if (GetDisciplineRecastTimer(caster, timer_index) < Timer::GetCurrentTime()) { //checks for spells on the same timer
return true; //can cast spell
}
}
return false;
}
uint8 Bot::GetChanceToCastBySpellType(uint32 spellType) uint8 Bot::GetChanceToCastBySpellType(uint32 spellType)
{ {
uint8 spell_type_index = SPELL_TYPE_COUNT; uint8 spell_type_index = SPELL_TYPE_COUNT;
+101 -214
View File
@@ -69,6 +69,7 @@ extern volatile bool RunLoops;
#include "../common/events/player_events.h" #include "../common/events/player_events.h"
#include "../common/events/player_event_logs.h" #include "../common/events/player_event_logs.h"
#include "dialogue_window.h" #include "dialogue_window.h"
#include <fmt/format.h>
extern QueryServ* QServ; extern QueryServ* QServ;
@@ -1411,163 +1412,126 @@ void Client::SetMaxHP() {
Save(); Save();
} }
bool Client::UpdateLDoNPoints(uint32 theme_id, int points) bool Client::UpdateLDoNPoints(uint32 theme_id, int points) {
{
if (points < 0) {
if (m_pp.ldon_points_available < (0 - points)) {
return false;
}
}
bool is_loss = false; /* make sure total stays in sync with individual buckets
m_pp.ldon_points_available = m_pp.ldon_points_guk
+m_pp.ldon_points_mir
+m_pp.ldon_points_mmc
+m_pp.ldon_points_ruj
+m_pp.ldon_points_tak; */
if(points < 0) {
if(m_pp.ldon_points_available < (0 - points))
return false;
}
switch (theme_id) { switch (theme_id) {
case LDoNThemes::Unused: { // No theme, so distribute evenly across all case LDoNThemes::Unused: { // No theme, so distribute evenly across all
int split_points = (points / 5); int split_points = (points / 5);
int guk_points = (split_points + (points % 5)); int guk_points = (split_points + (points % 5));
int mir_points = split_points; int mir_points = split_points;
int mmc_points = split_points; int mmc_points = split_points;
int ruj_points = split_points; int ruj_points = split_points;
int tak_points = split_points; int tak_points = split_points;
split_points = 0; split_points = 0;
if(points < 0) {
if (points < 0) { if(m_pp.ldon_points_available < (0 - points)) {
if (m_pp.ldon_points_available < (0 - points)) {
return false; return false;
} }
is_loss = true; if(m_pp.ldon_points_guk < (0 - guk_points)) {
if (m_pp.ldon_points_guk < (0 - guk_points)) {
mir_points += (guk_points + m_pp.ldon_points_guk); mir_points += (guk_points + m_pp.ldon_points_guk);
guk_points = (0 - m_pp.ldon_points_guk); guk_points = (0 - m_pp.ldon_points_guk);
} }
if (m_pp.ldon_points_mir < (0 - mir_points)) { if(m_pp.ldon_points_mir < (0 - mir_points)) {
mmc_points += (mir_points + m_pp.ldon_points_mir); mmc_points += (mir_points + m_pp.ldon_points_mir);
mir_points = (0 - m_pp.ldon_points_mir); mir_points = (0 - m_pp.ldon_points_mir);
} }
if (m_pp.ldon_points_mmc < (0 - mmc_points)) { if(m_pp.ldon_points_mmc < (0 - mmc_points)) {
ruj_points += (mmc_points + m_pp.ldon_points_mmc); ruj_points += (mmc_points + m_pp.ldon_points_mmc);
mmc_points = (0 - m_pp.ldon_points_mmc); mmc_points = (0 - m_pp.ldon_points_mmc);
} }
if (m_pp.ldon_points_ruj < (0 - ruj_points)) { if(m_pp.ldon_points_ruj < (0 - ruj_points)) {
tak_points += (ruj_points + m_pp.ldon_points_ruj); tak_points += (ruj_points + m_pp.ldon_points_ruj);
ruj_points = (0 - m_pp.ldon_points_ruj); ruj_points = (0 - m_pp.ldon_points_ruj);
} }
if (m_pp.ldon_points_tak < (0 - tak_points)) { if(m_pp.ldon_points_tak < (0 - tak_points)) {
split_points = (tak_points + m_pp.ldon_points_tak); split_points = (tak_points + m_pp.ldon_points_tak);
tak_points = (0 - m_pp.ldon_points_tak); tak_points = (0 - m_pp.ldon_points_tak);
} }
} }
m_pp.ldon_points_guk += guk_points; m_pp.ldon_points_guk += guk_points;
m_pp.ldon_points_mir += mir_points; m_pp.ldon_points_mir += mir_points;
m_pp.ldon_points_mmc += mmc_points; m_pp.ldon_points_mmc += mmc_points;
m_pp.ldon_points_ruj += ruj_points; m_pp.ldon_points_ruj += ruj_points;
m_pp.ldon_points_tak += tak_points; m_pp.ldon_points_tak += tak_points;
points -= split_points; points -= split_points;
if (split_points != 0) { // if anything left, recursively loop thru again if (split_points != 0) { // if anything left, recursively loop thru again
UpdateLDoNPoints(LDoNThemes::Unused, split_points); UpdateLDoNPoints(0, split_points);
} }
break; break;
} }
case LDoNThemes::GUK: { case LDoNThemes::GUK: {
if (points < 0) { if(points < 0) {
if (m_pp.ldon_points_guk < (0 - points)) { if(m_pp.ldon_points_guk < (0 - points)) {
return false; return false;
} }
is_loss = true;
} }
m_pp.ldon_points_guk += points; m_pp.ldon_points_guk += points;
break; break;
} }
case LDoNThemes::MIR: { case LDoNThemes::MIR: {
if (points < 0) { if(points < 0) {
if (m_pp.ldon_points_mir < (0 - points)) { if(m_pp.ldon_points_mir < (0 - points)) {
return false; return false;
} }
is_loss = true;
} }
m_pp.ldon_points_mir += points; m_pp.ldon_points_mir += points;
break; break;
} }
case LDoNThemes::MMC: { case LDoNThemes::MMC: {
if (points < 0) { if(points < 0) {
if (m_pp.ldon_points_mmc < (0 - points)) { if(m_pp.ldon_points_mmc < (0 - points)) {
return false; return false;
} }
is_loss = true;
} }
m_pp.ldon_points_mmc += points; m_pp.ldon_points_mmc += points;
break; break;
} }
case LDoNThemes::RUJ: { case LDoNThemes::RUJ: {
if (points < 0) { if(points < 0) {
if (m_pp.ldon_points_ruj < (0 - points)) { if(m_pp.ldon_points_ruj < (0 - points)) {
return false; return false;
} }
is_loss = true;
} }
m_pp.ldon_points_ruj += points; m_pp.ldon_points_ruj += points;
break; break;
} }
case LDoNThemes::TAK: { case LDoNThemes::TAK: {
if (points < 0) { if(points < 0) {
if (m_pp.ldon_points_tak < (0 - points)) { if(m_pp.ldon_points_tak < (0 - points)) {
return false; return false;
} }
is_loss = true;
} }
m_pp.ldon_points_tak += points; m_pp.ldon_points_tak += points;
break; break;
} }
} }
m_pp.ldon_points_available += points; m_pp.ldon_points_available += points;
QuestEventID event_id = is_loss ? EVENT_LDON_POINTS_LOSS : EVENT_LDON_POINTS_GAIN;
if (parse->PlayerHasQuestSub(event_id)) {
const std::string &export_string = fmt::format(
"{} {}",
theme_id,
std::abs(points)
);
parse->EventPlayer(event_id, this, export_string, 0);
}
auto outapp = new EQApplicationPacket(OP_AdventurePointsUpdate, sizeof(AdventurePoints_Update_Struct)); auto outapp = new EQApplicationPacket(OP_AdventurePointsUpdate, sizeof(AdventurePoints_Update_Struct));
auto *apus = (AdventurePoints_Update_Struct *) outapp->pBuffer; AdventurePoints_Update_Struct* apus = (AdventurePoints_Update_Struct*)outapp->pBuffer;
apus->ldon_available_points = m_pp.ldon_points_available; apus->ldon_available_points = m_pp.ldon_points_available;
apus->ldon_guk_points = m_pp.ldon_points_guk; apus->ldon_guk_points = m_pp.ldon_points_guk;
apus->ldon_mirugal_points = m_pp.ldon_points_mir; apus->ldon_mirugal_points = m_pp.ldon_points_mir;
apus->ldon_mistmoore_points = m_pp.ldon_points_mmc; apus->ldon_mistmoore_points = m_pp.ldon_points_mmc;
apus->ldon_rujarkian_points = m_pp.ldon_points_ruj; apus->ldon_rujarkian_points = m_pp.ldon_points_ruj;
apus->ldon_takish_points = m_pp.ldon_points_tak; apus->ldon_takish_points = m_pp.ldon_points_tak;
outapp->priority = 6; outapp->priority = 6;
QueuePacket(outapp); QueuePacket(outapp);
safe_delete(outapp); safe_delete(outapp);
return true; return true;
@@ -5727,89 +5691,26 @@ void Client::AddPVPPoints(uint32 Points)
SendPVPStats(); SendPVPStats();
} }
void Client::AddEbonCrystals(uint32 amount, bool is_reclaim) { void Client::AddCrystals(uint32 radiant, uint32 ebon)
m_pp.currentEbonCrystals += amount; {
m_pp.careerEbonCrystals += amount; m_pp.currentRadCrystals += radiant;
m_pp.careerRadCrystals += radiant;
m_pp.currentEbonCrystals += ebon;
m_pp.careerEbonCrystals += ebon;
SaveCurrency(); SaveCurrency();
SendCrystalCounts(); SendCrystalCounts();
MessageString( // newer clients handle message client side (older clients likely used eqstr 5967 and 5968, this matches live)
Chat::Yellow, if (radiant > 0)
YOU_RECEIVE, {
fmt::format( MessageString(Chat::Yellow, YOU_RECEIVE, fmt::format("{} Radiant Crystals", radiant).c_str());
"{} {}",
amount,
database.CreateItemLink(RuleI(Zone, EbonCrystalItemID))
).c_str()
);
if (parse->PlayerHasQuestSub(EVENT_CRYSTAL_GAIN)) {
const std::string &export_string = fmt::format(
"{} 0 {}",
amount,
is_reclaim ? 1 : 0
);
parse->EventPlayer(EVENT_CRYSTAL_GAIN, this, export_string, 0);
} }
}
void Client::AddRadiantCrystals(uint32 amount, bool is_reclaim) { if (ebon > 0)
m_pp.currentRadCrystals += amount; {
m_pp.careerRadCrystals += amount; MessageString(Chat::Yellow, YOU_RECEIVE, fmt::format("{} Ebon Crystals", ebon).c_str());
SaveCurrency();
SendCrystalCounts();
MessageString(
Chat::Yellow,
YOU_RECEIVE,
fmt::format(
"{} {}",
amount,
database.CreateItemLink(RuleI(Zone, RadiantCrystalItemID))
).c_str()
);
if (parse->PlayerHasQuestSub(EVENT_CRYSTAL_GAIN)) {
const std::string &export_string = fmt::format(
"0 {} {}",
amount,
is_reclaim ? 1 : 0
);
parse->EventPlayer(EVENT_CRYSTAL_GAIN, this, export_string, 0);
}
}
void Client::RemoveEbonCrystals(uint32 amount, bool is_reclaim) {
m_pp.currentEbonCrystals -= amount;
SaveCurrency();
SendCrystalCounts();
if (parse->PlayerHasQuestSub(EVENT_CRYSTAL_LOSS)) {
const std::string &export_string = fmt::format(
"{} 0 {}",
amount,
is_reclaim ? 1 : 0
);
parse->EventPlayer(EVENT_CRYSTAL_LOSS, this, export_string, 0);
}
}
void Client::RemoveRadiantCrystals(uint32 amount, bool is_reclaim) {
m_pp.currentRadCrystals -= amount;
SaveCurrency();
SendCrystalCounts();
if (parse->PlayerHasQuestSub(EVENT_CRYSTAL_LOSS)) {
const std::string &export_string = fmt::format(
"0 {} {}",
amount,
is_reclaim ? 1 : 0
);
parse->EventPlayer(EVENT_CRYSTAL_LOSS, this, export_string, 0);
} }
} }
@@ -6172,7 +6073,7 @@ void Client::CheckEmoteHail(NPC* n, const char* message)
const auto emote_id = n->GetEmoteID(); const auto emote_id = n->GetEmoteID();
if (emote_id) { if (emote_id) {
n->DoNPCEmote(EQ::constants::EmoteEventTypes::Hailed, emote_id, this); n->DoNPCEmote(EQ::constants::EmoteEventTypes::Hailed, emote_id);
} }
} }
@@ -6554,10 +6455,11 @@ void Client::SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount)
SendAlternateCurrencyValue(currency_id); SendAlternateCurrencyValue(currency_id);
} }
int Client::AddAlternateCurrencyValue(uint32 currency_id, int amount, bool is_scripted) int Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method)
{ {
/* Added via Quest, rest of the logging methods may be done inline due to information available in that area of the code */ /* Added via Quest, rest of the logging methods may be done inline due to information available in that area of the code */
if (is_scripted) { if (method == 1){
/* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */ /* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */
if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){ if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){
std::string event_desc = StringFormat("Added via Quest :: Cursor to Item :: alt_currency_id:%i amount:%i in zoneid:%i instid:%i", currency_id, GetZoneID(), GetInstanceID()); std::string event_desc = StringFormat("Added via Quest :: Cursor to Item :: alt_currency_id:%i amount:%i in zoneid:%i instid:%i", currency_id, GetZoneID(), GetInstanceID());
@@ -6565,47 +6467,32 @@ int Client::AddAlternateCurrencyValue(uint32 currency_id, int amount, bool is_sc
} }
} }
if (!amount) { if(amount == 0) {
return 0; return 0;
} }
if (!alternate_currency_loaded) { if(!alternate_currency_loaded) {
alternate_currency_queued_operations.push(std::make_pair(currency_id, amount)); alternate_currency_queued_operations.push(std::make_pair(currency_id, amount));
return 0; return 0;
} }
int new_value = 0; int new_value = 0;
auto iter = alternate_currency.find(currency_id); auto iter = alternate_currency.find(currency_id);
if (iter == alternate_currency.end()) { if(iter == alternate_currency.end()) {
new_value = amount; new_value = amount;
} else { } else {
new_value = (*iter).second + amount; new_value = (*iter).second + amount;
} }
if (new_value < 0) { if(new_value < 0) {
new_value = 0;
alternate_currency[currency_id] = 0; alternate_currency[currency_id] = 0;
database.UpdateAltCurrencyValue(CharacterID(), currency_id, 0); database.UpdateAltCurrencyValue(CharacterID(), currency_id, 0);
} else { } else {
alternate_currency[currency_id] = new_value; alternate_currency[currency_id] = new_value;
database.UpdateAltCurrencyValue(CharacterID(), currency_id, new_value); database.UpdateAltCurrencyValue(CharacterID(), currency_id, new_value);
} }
SendAlternateCurrencyValue(currency_id); SendAlternateCurrencyValue(currency_id);
QuestEventID event_id = amount > 0 ? EVENT_ALT_CURRENCY_GAIN : EVENT_ALT_CURRENCY_LOSS;
if (parse->PlayerHasQuestSub(event_id)) {
const std::string &export_string = fmt::format(
"{} {} {}",
currency_id,
std::abs(amount),
new_value
);
parse->EventPlayer(event_id, this, export_string, 0);
}
return new_value; return new_value;
} }
@@ -8632,8 +8519,8 @@ void Client::InitInnates()
m_pp.InnateSkills[InnateInspect] = InnateEnabled; m_pp.InnateSkills[InnateInspect] = InnateEnabled;
m_pp.InnateSkills[InnateOpen] = InnateEnabled; m_pp.InnateSkills[InnateOpen] = InnateEnabled;
if (race >= Race::Froglok2) { if (race >= RT_FROGLOK_3) {
if (race == Race::Skeleton2 || race == Race::Froglok2) { if (race == RT_SKELETON_2 || race == RT_FROGLOK_3) {
m_pp.InnateSkills[InnateUltraVision] = InnateEnabled; m_pp.InnateSkills[InnateUltraVision] = InnateEnabled;
} else { } else {
m_pp.InnateSkills[InnateInfravision] = InnateEnabled; m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
@@ -8641,75 +8528,75 @@ void Client::InitInnates()
} }
switch (race) { switch (race) {
case Race::Barbarian: case RT_BARBARIAN:
case Race::HalasCitizen: case RT_BARBARIAN_2:
m_pp.InnateSkills[InnateSlam] = InnateEnabled; m_pp.InnateSkills[InnateSlam] = InnateEnabled;
break; break;
case Race::Erudite: case RT_ERUDITE:
case Race::EruditeCitizen: case RT_ERUDITE_2:
m_pp.InnateSkills[InnateLore] = InnateEnabled; m_pp.InnateSkills[InnateLore] = InnateEnabled;
break; break;
case Race::WoodElf: case RT_WOOD_ELF:
case Race::Fayguard: case RT_GUARD_3:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled; m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
break; break;
case Race::Gnome: case RT_GNOME:
case Race::HighElf: case RT_HIGH_ELF:
case Race::Felguard: case RT_GUARD_2:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled; m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
m_pp.InnateSkills[InnateLore] = InnateEnabled; m_pp.InnateSkills[InnateLore] = InnateEnabled;
break; break;
case Race::Troll: case RT_TROLL:
case Race::GrobbCitizen: case RT_TROLL_2:
m_pp.InnateSkills[InnateRegen] = InnateEnabled; m_pp.InnateSkills[InnateRegen] = InnateEnabled;
m_pp.InnateSkills[InnateSlam] = InnateEnabled; m_pp.InnateSkills[InnateSlam] = InnateEnabled;
m_pp.InnateSkills[InnateInfravision] = InnateEnabled; m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
break; break;
case Race::Dwarf: case RT_DWARF:
case Race::KaladimCitizen: case RT_DWARF_2:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled; m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
break; break;
case Race::Ogre: case RT_OGRE:
case Race::OggokCitizen: case RT_OGRE_2:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled; m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
m_pp.InnateSkills[InnateSlam] = InnateEnabled; m_pp.InnateSkills[InnateSlam] = InnateEnabled;
m_pp.InnateSkills[InnateNoBash] = InnateEnabled; m_pp.InnateSkills[InnateNoBash] = InnateEnabled;
m_pp.InnateSkills[InnateBashDoor] = InnateEnabled; m_pp.InnateSkills[InnateBashDoor] = InnateEnabled;
break; break;
case Race::Halfling: case RT_HALFLING:
case Race::RivervaleCitizen: case RT_HALFLING_2:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled; m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
break; break;
case Race::Iksar: case RT_IKSAR:
m_pp.InnateSkills[InnateRegen] = InnateEnabled; m_pp.InnateSkills[InnateRegen] = InnateEnabled;
m_pp.InnateSkills[InnateInfravision] = InnateEnabled; m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
break; break;
case Race::VahShir: case RT_VAH_SHIR:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled; m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
break; break;
case Race::DarkElf: case RT_DARK_ELF:
case Race::NeriakCitizen: case RT_DARK_ELF_2:
case Race::ElfVampire: case RT_VAMPIRE_2:
case Race::FroglokGhoul: case RT_FROGLOK_2:
case Race::Ghost: case RT_GHOST:
case Race::Ghoul: case RT_GHOUL:
case Race::Skeleton: case RT_SKELETON:
case Race::Vampire: case RT_VAMPIRE:
case Race::Wisp: case RT_WILL_O_WISP:
case Race::Zombie: case RT_ZOMBIE:
case Race::Spectre: case RT_SPECTRE:
case Race::DwarfGhost: case RT_GHOST_2:
case Race::EruditeGhost: case RT_GHOST_3:
case Race::DragonSkeleton: case RT_DRAGON_2:
case Race::Innoruuk: case RT_INNORUUK:
m_pp.InnateSkills[InnateUltraVision] = InnateEnabled; m_pp.InnateSkills[InnateUltraVision] = InnateEnabled;
break; break;
case Race::Human: case RT_HUMAN:
case Race::FreeportGuard: case RT_GUARD:
case Race::HumanBeggar: case RT_BEGGAR:
case Race::HighpassCitizen: case RT_HUMAN_2:
case Race::QeynosCitizen: case RT_HUMAN_3:
case Race::Froglok2: // client does froglok weird, but this should work out fine case RT_FROGLOK_3: // client does froglok weird, but this should work out fine
break; break;
default: default:
m_pp.InnateSkills[InnateInfravision] = InnateEnabled; m_pp.InnateSkills[InnateInfravision] = InnateEnabled;
+2 -6
View File
@@ -611,14 +611,11 @@ public:
void SetPVPPoints(uint32 Points) { m_pp.PVPCurrentPoints = Points; } void SetPVPPoints(uint32 Points) { m_pp.PVPCurrentPoints = Points; }
uint32 GetPVPPoints() { return m_pp.PVPCurrentPoints; } uint32 GetPVPPoints() { return m_pp.PVPCurrentPoints; }
void AddPVPPoints(uint32 Points); void AddPVPPoints(uint32 Points);
void AddEbonCrystals(uint32 amount, bool is_reclaim = false);
void AddRadiantCrystals(uint32 amount, bool is_reclaim = false);
void RemoveEbonCrystals(uint32 amount, bool is_reclaim = false);
void RemoveRadiantCrystals(uint32 amount, bool is_reclaim = false);
uint32 GetRadiantCrystals() { return m_pp.currentRadCrystals; } uint32 GetRadiantCrystals() { return m_pp.currentRadCrystals; }
void SetRadiantCrystals(uint32 value); void SetRadiantCrystals(uint32 value);
uint32 GetEbonCrystals() { return m_pp.currentEbonCrystals; } uint32 GetEbonCrystals() { return m_pp.currentEbonCrystals; }
void SetEbonCrystals(uint32 value); void SetEbonCrystals(uint32 value);
void AddCrystals(uint32 Radiant, uint32 Ebon);
void SendCrystalCounts(); void SendCrystalCounts();
uint64 GetExperienceForKill(Mob *against); uint64 GetExperienceForKill(Mob *against);
@@ -982,7 +979,6 @@ public:
void PutLootInInventory(int16 slot_id, const EQ::ItemInstance &inst, ServerLootItem_Struct** bag_item_data = 0); 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 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); 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 SummonBaggedItems(uint32 bag_item_id, const std::vector<ServerLootItem_Struct>& bag_items);
void SetStats(uint8 type,int16 set_val); void SetStats(uint8 type,int16 set_val);
void IncStats(uint8 type,int16 increase_val); void IncStats(uint8 type,int16 increase_val);
@@ -1497,7 +1493,7 @@ public:
void ConsentCorpses(std::string consent_name, bool deny = false); void ConsentCorpses(std::string consent_name, bool deny = false);
void SendAltCurrencies(); void SendAltCurrencies();
void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount); void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount);
int AddAlternateCurrencyValue(uint32 currency_id, int amount, bool is_scripted = false); int AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0);
void SendAlternateCurrencyValues(); void SendAlternateCurrencyValues();
void SendAlternateCurrencyValue(uint32 currency_id, bool send_if_null = true); void SendAlternateCurrencyValue(uint32 currency_id, bool send_if_null = true);
uint32 GetAlternateCurrencyValue(uint32 currency_id) const; uint32 GetAlternateCurrencyValue(uint32 currency_id) const;
+31 -27
View File
@@ -2626,7 +2626,7 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app)
parse->EventPlayer(EVENT_ALT_CURRENCY_MERCHANT_BUY, this, export_string, 0); parse->EventPlayer(EVENT_ALT_CURRENCY_MERCHANT_BUY, this, export_string, 0);
} }
uint64 current_balance = AddAlternateCurrencyValue(alt_cur_id, -((int) cost)); uint64 current_balance = AddAlternateCurrencyValue(alt_cur_id, -((int32) cost));
int16 charges = 1; int16 charges = 1;
if (item->MaxCharges != 0) { if (item->MaxCharges != 0) {
charges = item->MaxCharges; charges = item->MaxCharges;
@@ -2701,7 +2701,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app)
} }
else { else {
SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor); SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor);
AddAlternateCurrencyValue(reclaim->currency_id, -((int)reclaim->count)); AddAlternateCurrencyValue(reclaim->currency_id, -((int32)reclaim->count));
} }
/* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */ /* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */
if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)) { if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)) {
@@ -5475,50 +5475,59 @@ void Client::Handle_OP_CreateObject(const EQApplicationPacket *app)
void Client::Handle_OP_CrystalCreate(const EQApplicationPacket *app) void Client::Handle_OP_CrystalCreate(const EQApplicationPacket *app)
{ {
VERIFY_PACKET_LENGTH(OP_CrystalCreate, app, CrystalReclaim_Struct); VERIFY_PACKET_LENGTH(OP_CrystalCreate, app, CrystalReclaim_Struct);
auto *cr = (CrystalReclaim_Struct *) app->pBuffer; CrystalReclaim_Struct *cr = (CrystalReclaim_Struct*)app->pBuffer;
const uint32 quantity = cr->amount; const uint32 requestQty = cr->amount;
const bool is_radiant = cr->type == CrystalReclaimTypes::Radiant; const bool isRadiant = cr->type == 4;
const bool is_ebon = cr->type == CrystalReclaimTypes::Ebon; const bool isEbon = cr->type == 5;
if (!is_radiant && !is_ebon) { // Check: Valid type requested.
if (!isRadiant && !isEbon) {
return; return;
} }
// Check: Valid quantity requested.
if (quantity < 1) { if (requestQty < 1) {
return; return;
} }
// Check: Valid client state to make request. // Check: Valid client state to make request.
// In this situation the client is either desynced or attempting an exploit. // In this situation the client is either desynced or attempting an exploit.
const uint32 current_quantity = is_radiant ? GetRadiantCrystals() : GetEbonCrystals(); const uint32 currentQty = isRadiant ? GetRadiantCrystals() : GetEbonCrystals();
if (!current_quantity) { if (currentQty == 0) {
return; return;
} }
// Prevent the client from creating more than they have. // Prevent the client from creating more than they have.
const uint32 amount = EQ::ClampUpper(quantity, current_quantity); const uint32 amount = EQ::ClampUpper(requestQty, currentQty);
const uint32 item_id = is_radiant ? RuleI(Zone, RadiantCrystalItemID) : RuleI(Zone, EbonCrystalItemID); const uint32 itemID = isRadiant ? RuleI(Zone, RadiantCrystalItemID) : RuleI(Zone, EbonCrystalItemID);
// Summon crystals for player.
const bool success = SummonItem(itemID, amount);
const bool success = SummonItem(item_id, amount);
if (!success) { if (!success) {
return; return;
} }
if (is_ebon) { // Deduct crystals from client and update them.
RemoveEbonCrystals(amount, true); if (isRadiant) {
} else if (is_radiant) { m_pp.currentRadCrystals -= amount;
RemoveRadiantCrystals(amount, true); m_pp.careerRadCrystals -= amount;
} }
else if (isEbon) {
m_pp.currentEbonCrystals -= amount;
m_pp.careerEbonCrystals -= amount;
}
SaveCurrency();
SendCrystalCounts();
} }
void Client::Handle_OP_CrystalReclaim(const EQApplicationPacket *app) void Client::Handle_OP_CrystalReclaim(const EQApplicationPacket *app)
{ {
const uint32 ebon = NukeItem(RuleI(Zone, EbonCrystalItemID), invWhereWorn | invWherePersonal | invWhereCursor); uint32 ebon = NukeItem(RuleI(Zone, EbonCrystalItemID), invWhereWorn | invWherePersonal | invWhereCursor);
const uint32 radiant = NukeItem(RuleI(Zone, RadiantCrystalItemID), invWhereWorn | invWherePersonal | invWhereCursor); uint32 radiant = NukeItem(RuleI(Zone, RadiantCrystalItemID), invWhereWorn | invWherePersonal | invWhereCursor);
if ((ebon + radiant) > 0) { if ((ebon + radiant) > 0) {
AddEbonCrystals(ebon, true); AddCrystals(radiant, ebon);
AddRadiantCrystals(radiant, true);
} }
} }
@@ -6284,11 +6293,6 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
); );
parse->EventPlayer(EVENT_ENVIRONMENTAL_DAMAGE, this, export_string, 0); parse->EventPlayer(EVENT_ENVIRONMENTAL_DAMAGE, this, export_string, 0);
} }
if (ed->dmgtype == EQ::constants::EnvironmentalDamage::Trap) {
BreakInvisibleSpells();
CancelSneakHide();
}
} }
if (GetHP() <= 0) { if (GetHP() <= 0) {
+1 -1
View File
@@ -1,7 +1,7 @@
#include <string.h> #include <string.h>
#include <algorithm> #include <algorithm>
#include <thread> #include <thread>
#include <fmt/format.h> #include <fmt/core.h>
#include "../common/repositories/command_subsettings_repository.h" #include "../common/repositories/command_subsettings_repository.h"
#ifdef _WINDOWS #ifdef _WINDOWS
+1
View File
@@ -23,6 +23,7 @@
#include "expedition.h" #include "expedition.h"
#include "string_ids.h" #include "string_ids.h"
#include "worldserver.h" #include "worldserver.h"
#include <fmt/format.h>
extern WorldServer worldserver; extern WorldServer worldserver;
+3 -4
View File
@@ -523,15 +523,14 @@ int64 Mob::GetActSpellHealing(uint16 spell_id, int64 value, Mob* target, bool fr
} }
} }
if (extra_heal) { if (RuleB(Spells, HOTBonusHealingSplitOverDuration)) {
if (RuleB(Spells, HOTBonusHealingSplitOverDuration)) { if (extra_heal) {
const int duration = CalcBuffDuration(this, target, spell_id); const int duration = CalcBuffDuration(this, target, spell_id);
if (duration > 0) { if (duration > 0) {
extra_heal /= duration; extra_heal /= duration;
value += extra_heal;
} }
} }
value += extra_heal;
} }
value *= critical_modifier; value *= critical_modifier;
+10 -60
View File
@@ -186,14 +186,6 @@ const char *QuestEventSubroutines[_LargestEventID] = {
"EVENT_UNMEMORIZE_SPELL", "EVENT_UNMEMORIZE_SPELL",
"EVENT_SCRIBE_SPELL", "EVENT_SCRIBE_SPELL",
"EVENT_UNSCRIBE_SPELL", "EVENT_UNSCRIBE_SPELL",
"EVENT_LOOT_ADDED",
"EVENT_LDON_POINTS_GAIN",
"EVENT_LDON_POINTS_LOSS",
"EVENT_ALT_CURRENCY_GAIN",
"EVENT_ALT_CURRENCY_LOSS",
"EVENT_CRYSTAL_GAIN",
"EVENT_CRYSTAL_LOSS",
// Add new events before these or Lua crashes // Add new events before these or Lua crashes
"EVENT_SPELL_EFFECT_BOT", "EVENT_SPELL_EFFECT_BOT",
"EVENT_SPELL_EFFECT_BUFF_TIC_BOT" "EVENT_SPELL_EFFECT_BUFF_TIC_BOT"
@@ -1891,17 +1883,19 @@ void PerlembParser::ExportEventVariables(
ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]); 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_spell", sep.arg[2]);
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]); ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
if (extra_pointers && extra_pointers->size() >= 1)
if (extra_pointers && extra_pointers->size() >= 1) { {
Corpse *corpse = std::any_cast<Corpse *>(extra_pointers->at(0)); Corpse* corpse = std::any_cast<Corpse*>(extra_pointers->at(0));
if (corpse) { if (corpse)
{
ExportVar(package_name.c_str(), "killed_corpse_id", corpse->GetID()); ExportVar(package_name.c_str(), "killed_corpse_id", corpse->GetID());
} }
} }
if (extra_pointers && extra_pointers->size() >= 2)
if (extra_pointers && extra_pointers->size() >= 2) { {
NPC *killed = std::any_cast<NPC *>(extra_pointers->at(1)); NPC* killed = std::any_cast<NPC*>(extra_pointers->at(1));
if (killed) { if (killed)
{
ExportVar(package_name.c_str(), "killed_entity_id", killed->GetID()); 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_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_npc_id", killed->IsNPC() ? killed->GetNPCTypeID() : 0);
@@ -2247,50 +2241,6 @@ void PerlembParser::ExportEventVariables(
break; break;
} }
case EVENT_LOOT_ADDED: {
if (extra_pointers && extra_pointers->size() == 1) {
auto *inst = std::any_cast<EQ::ItemInstance *>(extra_pointers->at(0));
if (inst) {
ExportVar(package_name.c_str(), "item", "QuestItem", inst);
ExportVar(package_name.c_str(), "item_id", inst->GetID());
ExportVar(package_name.c_str(), "item_name", inst->GetItem()->Name);
ExportVar(package_name.c_str(), "item_charges", inst->GetCharges());
ExportVar(package_name.c_str(), "augment_one", inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN));
ExportVar(package_name.c_str(), "augment_two", inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 1));
ExportVar(package_name.c_str(), "augment_three", inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 2));
ExportVar(package_name.c_str(), "augment_four", inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 3));
ExportVar(package_name.c_str(), "augment_five", inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 4));
ExportVar(package_name.c_str(), "augment_six", inst->GetAugmentItemID(EQ::invaug::SOCKET_END));
}
}
}
case EVENT_LDON_POINTS_GAIN:
case EVENT_LDON_POINTS_LOSS: {
Seperator sep(data);
ExportVar(package_name.c_str(), "theme_id", sep.arg[0]);
ExportVar(package_name.c_str(), "points", sep.arg[1]);
break;
}
case EVENT_ALT_CURRENCY_GAIN:
case EVENT_ALT_CURRENCY_LOSS: {
Seperator sep(data);
ExportVar(package_name.c_str(), "currency_id", sep.arg[0]);
ExportVar(package_name.c_str(), "amount", sep.arg[1]);
ExportVar(package_name.c_str(), "total", sep.arg[2]);
break;
}
case EVENT_CRYSTAL_GAIN:
case EVENT_CRYSTAL_LOSS: {
Seperator sep(data);
ExportVar(package_name.c_str(), "ebon_amount", sep.arg[0]);
ExportVar(package_name.c_str(), "radiant_amount", sep.arg[1]);
ExportVar(package_name.c_str(), "is_reclaim", sep.arg[2]);
break;
}
default: { default: {
break; break;
} }
+2 -2
View File
@@ -4920,7 +4920,7 @@ void EntityList::ZoneWho(Client *c, Who_All_Struct *Who)
FormatMSGID = 5023; // 5023 %T1[ANONYMOUS] %2 %3 %4 FormatMSGID = 5023; // 5023 %T1[ANONYMOUS] %2 %3 %4
uint32 PlayerClass = Class::None; uint32 PlayerClass = Class::None;
uint32 PlayerLevel = 0; uint32 PlayerLevel = 0;
uint32 PlayerRace = Race::Doug; uint32 PlayerRace = RACE_DOUG_0;
uint32 ZoneMSGID = 0xFFFFFFFF; uint32 ZoneMSGID = 0xFFFFFFFF;
if (ClientEntry->GetAnon()==0) { if (ClientEntry->GetAnon()==0) {
@@ -5750,7 +5750,7 @@ void EntityList::DespawnGridNodes(int32 grid_id) {
Mob *mob = m.second; Mob *mob = m.second;
if ( if (
mob->IsNPC() && mob->IsNPC() &&
mob->GetRace() == Race::Node && mob->GetRace() == RACE_NODE_2254 &&
mob->EntityVariableExists("grid_id") && mob->EntityVariableExists("grid_id") &&
Strings::ToInt(mob->GetEntityVariable("grid_id")) == grid_id) Strings::ToInt(mob->GetEntityVariable("grid_id")) == grid_id)
{ {
-8
View File
@@ -128,14 +128,6 @@ typedef enum {
EVENT_UNMEMORIZE_SPELL, EVENT_UNMEMORIZE_SPELL,
EVENT_SCRIBE_SPELL, EVENT_SCRIBE_SPELL,
EVENT_UNSCRIBE_SPELL, EVENT_UNSCRIBE_SPELL,
EVENT_LOOT_ADDED,
EVENT_LDON_POINTS_GAIN,
EVENT_LDON_POINTS_LOSS,
EVENT_ALT_CURRENCY_GAIN,
EVENT_ALT_CURRENCY_LOSS,
EVENT_CRYSTAL_GAIN,
EVENT_CRYSTAL_LOSS,
// Add new events before these or Lua crashes // Add new events before these or Lua crashes
EVENT_SPELL_EFFECT_BOT, EVENT_SPELL_EFFECT_BOT,
EVENT_SPELL_EFFECT_BUFF_TIC_BOT, EVENT_SPELL_EFFECT_BUFF_TIC_BOT,
+1
View File
@@ -36,6 +36,7 @@
#include "bot.h" #include "bot.h"
#include "../common/events/player_event_logs.h" #include "../common/events/player_event_logs.h"
#include "worldserver.h" #include "worldserver.h"
#include <fmt/format.h>
extern WorldServer worldserver; extern WorldServer worldserver;
+1
View File
@@ -26,6 +26,7 @@
#include "worldserver.h" #include "worldserver.h"
#include "zonedb.h" #include "zonedb.h"
#include "../common/repositories/expedition_lockouts_repository.h" #include "../common/repositories/expedition_lockouts_repository.h"
#include <fmt/format.h>
extern WorldServer worldserver; extern WorldServer worldserver;
extern Zone* zone; extern Zone* zone;
+1
View File
@@ -25,6 +25,7 @@
#include "raids.h" #include "raids.h"
#include "string_ids.h" #include "string_ids.h"
#include "../common/repositories/character_expedition_lockouts_repository.h" #include "../common/repositories/character_expedition_lockouts_repository.h"
#include <fmt/format.h>
constexpr char SystemName[] = "expedition"; constexpr char SystemName[] = "expedition";
+1 -1
View File
@@ -456,7 +456,7 @@ void Client::ForageItem(bool guarantee) {
} }
//not an else in case theres no DB food //not an else in case theres no DB food
if (foragedfood == 0 && RuleB(Character, UseForageCommonFood)) { if (foragedfood == 0) {
uint8 index = 0; uint8 index = 0;
index = zone->random.Int(0, MAX_COMMON_FOOD_IDS-1); index = zone->random.Int(0, MAX_COMMON_FOOD_IDS-1);
foragedfood = common_food_ids[index]; foragedfood = common_food_ids[index];
+10 -2
View File
@@ -7,7 +7,10 @@ void FindEmote(Client *c, const Seperator *sep)
if (sep->IsNumber(2)) { if (sep->IsNumber(2)) {
auto emote_id = Strings::ToUnsignedInt(sep->arg[2]); auto emote_id = Strings::ToUnsignedInt(sep->arg[2]);
for (auto& e : zone->npc_emote_list) { LinkedListIterator<NPC_Emote_Struct *> iterator(zone->NPCEmoteList);
iterator.Reset();
while (iterator.MoreElements()) {
auto &e = iterator.GetData();
if (emote_id == e->emoteid) { if (emote_id == e->emoteid) {
c->Message( c->Message(
Chat::White, Chat::White,
@@ -37,6 +40,7 @@ void FindEmote(Client *c, const Seperator *sep)
break; break;
} }
iterator.Advance();
} }
if (found_count == 50) { if (found_count == 50) {
@@ -66,7 +70,10 @@ void FindEmote(Client *c, const Seperator *sep)
const std::string& search_criteria = sep->argplus[2]; const std::string& search_criteria = sep->argplus[2];
for (auto& e : zone->npc_emote_list) { LinkedListIterator<NPC_Emote_Struct *> iterator(zone->NPCEmoteList);
iterator.Reset();
while (iterator.MoreElements()) {
auto &e = iterator.GetData();
const std::string& current_text = Strings::ToLower(e->text); const std::string& current_text = Strings::ToLower(e->text);
@@ -99,6 +106,7 @@ void FindEmote(Client *c, const Seperator *sep)
break; break;
} }
iterator.Advance();
} }
if (found_count == 50) { if (found_count == 50) {
+2 -2
View File
@@ -5,7 +5,7 @@ void FindRace(Client *c, const Seperator *sep)
if (sep->IsNumber(2)) { if (sep->IsNumber(2)) {
const auto race_id = static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[2])); const auto race_id = static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[2]));
const std::string& race_name = GetRaceIDName(race_id); const std::string& race_name = GetRaceIDName(race_id);
if (EQ::ValueWithin(race_id, Race::Human, Race::Pegasus3)) { if (EQ::ValueWithin(race_id, RACE_HUMAN_1, RACE_PEGASUS_732)) {
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
@@ -41,7 +41,7 @@ void FindRace(Client *c, const Seperator *sep)
auto found_count = 0; auto found_count = 0;
for (uint16 race_id = Race::Human; race_id <= Race::Pegasus3; race_id++) { for (uint16 race_id = RACE_HUMAN_1; race_id <= RACE_PEGASUS_732; race_id++) {
std::string race_name = GetRaceIDName(race_id); std::string race_name = GetRaceIDName(race_id);
auto race_name_lower = Strings::ToLower(race_name); auto race_name_lower = Strings::ToLower(race_name);
if (!Strings::Contains(race_name_lower, search_criteria)) { if (!Strings::Contains(race_name_lower, search_criteria)) {
+1 -1
View File
@@ -23,7 +23,7 @@ void SetRace(Client *c, const Seperator *sep)
const uint16 race_id = Strings::ToUnsignedInt(sep->arg[2]); const uint16 race_id = Strings::ToUnsignedInt(sep->arg[2]);
if ( if (
!EQ::ValueWithin(race_id, Race::Doug, RuleI(NPC, MaxRaceID)) && !EQ::ValueWithin(race_id, RACE_DOUG_0, RuleI(NPC, MaxRaceID)) &&
!EQ::ValueWithin(race_id, 2253, 2259) !EQ::ValueWithin(race_id, 2253, 2259)
) { ) {
c->Message( c->Message(
+16 -9
View File
@@ -9,11 +9,17 @@ void SetTime(Client *c, const Seperator *sep)
TimeOfDay_Struct world_time{}; TimeOfDay_Struct world_time{};
zone->zone_time.GetCurrentEQTimeOfDay(time(0), &world_time); zone->zone_time.GetCurrentEQTimeOfDay(time(0), &world_time);
auto time_string = fmt::format(
"{} (Timezone: {})",
Strings::ZoneTime(world_time.hour, world_time.minute),
Strings::ZoneTime(zone->zone_time.getEQTimeZoneHr(), zone->zone_time.getEQTimeZoneHr())
);
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
"It is currently {}.", "It is currently {}.",
Strings::ZoneTime(world_time.hour - 1, world_time.minute) time_string
).c_str() ).c_str()
); );
@@ -21,15 +27,15 @@ void SetTime(Client *c, const Seperator *sep)
} }
uint8 minutes = 0; uint8 minutes = 0;
uint8 hours = Strings::ToUnsignedInt(sep->arg[2]); uint8 hours = Strings::ToUnsignedInt(sep->arg[2]) + 1;
if (hours > 24) { if (hours > 24) {
hours = 24; hours = 24;
} }
uint8 real_hours = ( uint8 real_hours = (
hours > 0 ? (hours - 1) > 0 ?
hours : (hours - 1) :
0 0
); );
@@ -41,20 +47,21 @@ void SetTime(Client *c, const Seperator *sep)
} }
} }
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
"Setting world time to {}.", "Setting world time to {} (Timezone: {}).",
Strings::ZoneTime(hours, minutes) Strings::ZoneTime(hours, minutes),
Strings::ZoneTime(zone->zone_time.getEQTimeZoneHr(), zone->zone_time.getEQTimeZoneHr())
).c_str() ).c_str()
); );
zone->SetTime(real_hours, minutes); zone->SetTime(real_hours, minutes);
LogInfo( LogInfo(
"{} :: Setting world time to {}.", "{} :: Setting world time to {} (Timezone: {})",
c->GetCleanName(), c->GetCleanName(),
Strings::ZoneTime(hours, minutes) Strings::ZoneTime(hours, minutes),
Strings::ZoneTime(zone->zone_time.getEQTimeZoneHr(), zone->zone_time.getEQTimeZoneHr())
); );
} }
+5 -1
View File
@@ -12,7 +12,10 @@ void ShowEmotes(Client *c, const Seperator *sep)
uint32 emote_count = 0; uint32 emote_count = 0;
const uint32 emote_id = t->GetEmoteID(); const uint32 emote_id = t->GetEmoteID();
for (auto& e : zone->npc_emote_list) { LinkedListIterator<NPC_Emote_Struct *> iterator(zone->NPCEmoteList);
iterator.Reset();
while (iterator.MoreElements()) {
const auto& e = iterator.GetData();
if (emote_id == e->emoteid) { if (emote_id == e->emoteid) {
c->Message( c->Message(
Chat::White, Chat::White,
@@ -38,6 +41,7 @@ void ShowEmotes(Client *c, const Seperator *sep)
emote_count++; emote_count++;
} }
iterator.Advance();
} }
c->Message( c->Message(
+1 -1
View File
@@ -4,7 +4,7 @@ void ShowZonePoints(Client *c, const Seperator *sep)
{ {
for (const auto& m : entity_list.GetMobList()) { for (const auto& m : entity_list.GetMobList()) {
Mob* mob = m.second; Mob* mob = m.second;
if (mob->IsNPC() && mob->GetRace() == Race::Node) { if (mob->IsNPC() && mob->GetRace() == RACE_NODE_2254) {
mob->Depop(); mob->Depop();
} }
} }
+19 -14
View File
@@ -3,16 +3,19 @@
extern WorldServer worldserver; extern WorldServer worldserver;
#include "../corpse.h"
void command_summon(Client *c, const Seperator *sep) void command_summon(Client *c, const Seperator *sep)
{ {
const int arguments = sep->argnum; int arguments = sep->argnum;
if (!arguments && !c->GetTarget()) { if (!arguments && !c->GetTarget()) {
c->Message(Chat::White, "Usage: #summon - Summon your target, if you have one, to your position"); c->Message(Chat::White, "Usage: #summon - Summon your target, if you have one, to your position");
c->Message(Chat::White, "Usage: #summon [Character Name] - Summon a character by name to your position"); c->Message(Chat::White, "Usage: #summon [Character Name] - Summon a character by name to your position");
c->Message(Chat::White, "Note: You may also summon your target if you have one.");
return; return;
} }
Mob *t = c; Mob* t = c;
if (arguments == 1) { if (arguments == 1) {
std::string character_name = sep->arg[1]; std::string character_name = sep->arg[1];
@@ -28,9 +31,9 @@ void command_summon(Client *c, const Seperator *sep)
return; return;
} }
Client *s = entity_list.GetClientByName(character_name.c_str()); auto search_client = entity_list.GetClientByName(character_name.c_str());
if (s) { if (search_client) {
t = s->CastToMob(); t = search_client->CastToMob();
} else { } else {
if (!worldserver.Connected()) { if (!worldserver.Connected()) {
c->Message(Chat::White, "World server is currently disconnected."); c->Message(Chat::White, "World server is currently disconnected.");
@@ -39,18 +42,15 @@ void command_summon(Client *c, const Seperator *sep)
auto pack = new ServerPacket(ServerOP_ZonePlayer, sizeof(ServerZonePlayer_Struct)); auto pack = new ServerPacket(ServerOP_ZonePlayer, sizeof(ServerZonePlayer_Struct));
auto szp = (ServerZonePlayer_Struct *) pack->pBuffer; auto szp = (ServerZonePlayer_Struct *) pack->pBuffer;
strn0cpy(szp->adminname, c->GetName(), sizeof(szp->adminname)); strn0cpy(szp->adminname, c->GetName(), sizeof(szp->adminname));
szp->adminrank = c->Admin();
szp->ignorerestrictions = 2;
strn0cpy(szp->name, character_name.c_str(), sizeof(szp->name)); strn0cpy(szp->name, character_name.c_str(), sizeof(szp->name));
strn0cpy(szp->zone, zone->GetShortName(), sizeof(szp->zone)); strn0cpy(szp->zone, zone->GetShortName(), sizeof(szp->zone));
szp->x_pos = c->GetX();
szp->adminrank = c->Admin(); szp->y_pos = c->GetY();
szp->ignorerestrictions = 2; szp->z_pos = c->GetZ();
szp->instance_id = zone->GetInstanceID(); szp->instance_id = zone->GetInstanceID();
szp->x_pos = c->GetX();
szp->y_pos = c->GetY();
szp->z_pos = c->GetZ();
worldserver.SendPacket(pack); worldserver.SendPacket(pack);
safe_delete(pack); safe_delete(pack);
return; return;
@@ -97,4 +97,9 @@ void command_summon(Client *c, const Seperator *sep)
} }
t->GMMove(c->GetPosition()); t->GMMove(c->GetPosition());
if (t->IsNPC()) {
t->CastToNPC()->SaveGuardSpot(glm::vec4(0.0f));
}
} }
+261 -130
View File
@@ -149,7 +149,7 @@ Mob* HateList::GetDamageTopOnHateList(Mob* hater)
return current; return current;
} }
Mob* HateList::GetClosestEntOnHateList(Mob *hater, bool skip_mezzed, EntityFilterType filter_type) { Mob* HateList::GetClosestEntOnHateList(Mob *hater, bool skip_mezzed, EntityFilterType entity_type) {
Mob* close_entity = nullptr; Mob* close_entity = nullptr;
float close_distance = 99999.9f; float close_distance = 99999.9f;
float this_distance; float this_distance;
@@ -163,7 +163,7 @@ Mob* HateList::GetClosestEntOnHateList(Mob *hater, bool skip_mezzed, EntityFilte
continue; continue;
} }
switch (filter_type) { switch (entity_type) {
case EntityFilterType::Bots: case EntityFilterType::Bots:
if (!e->entity_on_hatelist->IsBot()) { if (!e->entity_on_hatelist->IsBot()) {
continue; continue;
@@ -344,215 +344,191 @@ int HateList::GetHateRatio(Mob *top, Mob *other)
// skip is used to ignore a certain mob on the list // skip is used to ignore a certain mob on the list
// Currently used for getting 2nd on list for aggro meter // Currently used for getting 2nd on list for aggro meter
Mob *HateList::GetMobWithMostHateOnList( Mob *HateList::GetEntWithMostHateOnList(Mob *center, Mob *skip, bool skip_mezzed)
Mob *center,
Mob *skip,
bool skip_mezzed,
EntityFilterType filter_type
)
{ {
if (!zone->IsLoaded()) { // hack fix for zone shutdown crashes on some servers // hack fix for zone shutdown crashes on some servers
if (!zone->IsLoaded())
return nullptr; return nullptr;
}
Mob *top_hate = nullptr; Mob* top_hate = nullptr;
int64 hate = -1; int64 hate = -1;
if (!center) { if (center == nullptr)
return nullptr; return nullptr;
}
if (RuleB(Aggro, SmartAggroList)) { if (RuleB(Aggro, SmartAggroList)){
Mob *top_client_type_in_range = nullptr; Mob* top_client_type_in_range = nullptr;
int64 hate_client_type_in_range = -1; int64 hate_client_type_in_range = -1;
int skipped_count = 0; int skipped_count = 0;
auto iterator = list.begin(); auto iterator = list.begin();
while (iterator != list.end()) { while (iterator != list.end())
struct_HateList *cur = (*iterator); {
int16 aggro_mod = 0; struct_HateList *cur = (*iterator);
int16 aggro_mod = 0;
if (!cur) { if (!cur){
++iterator; ++iterator;
continue; continue;
} }
Mob *m = cur->entity_on_hatelist; if (!cur->entity_on_hatelist){
if (!m) {
++iterator; ++iterator;
continue; continue;
} }
if (m == skip) { if (cur->entity_on_hatelist == skip) {
++iterator; ++iterator;
continue; continue;
} }
if (skip_mezzed && m->IsMezzed()) { if (skip_mezzed && cur->entity_on_hatelist->IsMezzed()) {
++iterator; ++iterator;
continue; continue;
} }
if ( if (cur->entity_on_hatelist->Sanctuary()) {
(filter_type == EntityFilterType::Bots && !m->IsBot()) || if (hate == -1)
(filter_type == EntityFilterType::Clients && !m->IsClient()) || {
(filter_type == EntityFilterType::NPCs && !m->IsNPC()) top_hate = cur->entity_on_hatelist;
) { hate = 1;
++iterator;
continue;
}
if (m->Sanctuary()) {
if (hate == -1) {
top_hate = m;
hate = 1;
} }
++iterator; ++iterator;
continue; continue;
} }
if (m->DivineAura() || m->IsMezzed() || m->IsFeared()) { if (cur->entity_on_hatelist->DivineAura() || cur->entity_on_hatelist->IsMezzed() || cur->entity_on_hatelist->IsFeared()){
if (hate == -1) { if (hate == -1)
top_hate = m; {
hate = 0; top_hate = cur->entity_on_hatelist;
hate = 0;
} }
++iterator; ++iterator;
continue; continue;
} }
int64 current_hate = cur->stored_hate_amount; int64 current_hate = cur->stored_hate_amount;
if (m->IsOfClientBot()) { if (cur->entity_on_hatelist->IsClient() || cur->entity_on_hatelist->IsBot()){
if (m->IsClient() && m->CastToClient()->IsSitting()) { if (cur->entity_on_hatelist->IsClient() && cur->entity_on_hatelist->CastToClient()->IsSitting()){
aggro_mod += RuleI(Aggro, SittingAggroMod); aggro_mod += RuleI(Aggro, SittingAggroMod);
} }
if (center) { if (center){
if (center->GetTarget() == m) { if (center->GetTarget() == cur->entity_on_hatelist)
aggro_mod += RuleI(Aggro, CurrentTargetAggroMod); aggro_mod += RuleI(Aggro, CurrentTargetAggroMod);
} if (RuleI(Aggro, MeleeRangeAggroMod) != 0)
{
if (RuleI(Aggro, MeleeRangeAggroMod) != 0) { if (center->CombatRange(cur->entity_on_hatelist)){
if (center->CombatRange(m)) {
aggro_mod += RuleI(Aggro, MeleeRangeAggroMod); 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; hate_client_type_in_range = current_hate;
top_client_type_in_range = m; top_client_type_in_range = cur->entity_on_hatelist;
} }
} }
} }
} }
} else {
if (center) {
if (center->GetTarget() == m) {
aggro_mod += RuleI(Aggro, CurrentTargetAggroMod);
}
if (RuleI(Aggro, MeleeRangeAggroMod) != 0) { }
if (center->CombatRange(m)) { else{
if (center){
if (center->GetTarget() == cur->entity_on_hatelist)
aggro_mod += RuleI(Aggro, CurrentTargetAggroMod);
if (RuleI(Aggro, MeleeRangeAggroMod) != 0)
{
if (center->CombatRange(cur->entity_on_hatelist)){
aggro_mod += RuleI(Aggro, MeleeRangeAggroMod); aggro_mod += RuleI(Aggro, MeleeRangeAggroMod);
} }
} }
} }
} }
if (m->GetMaxHP() != 0 && ((m->GetHP() * 100 / m->GetMaxHP()) < 20)) { if (cur->entity_on_hatelist->GetMaxHP() != 0 && ((cur->entity_on_hatelist->GetHP() * 100 / cur->entity_on_hatelist->GetMaxHP()) < 20)){
aggro_mod += RuleI(Aggro, CriticallyWoundedAggroMod); aggro_mod += RuleI(Aggro, CriticallyWoundedAggroMod);
} }
if (aggro_mod) { if (aggro_mod){
current_hate += (current_hate * aggro_mod / 100); current_hate += (current_hate * aggro_mod / 100);
} }
if (current_hate > hate || cur->is_entity_frenzy) { if (current_hate > hate || cur->is_entity_frenzy){
hate = current_hate; hate = current_hate;
top_hate = m; top_hate = cur->entity_on_hatelist;
} }
++iterator; ++iterator;
} }
if (top_client_type_in_range && top_hate) { if (top_client_type_in_range != nullptr && top_hate != nullptr) {
bool is_top_client_type = top_hate->IsClient(); bool isTopClientType = top_hate->IsClient();
if (!is_top_client_type) { if (!isTopClientType) {
if (top_hate->IsBot()) { if (top_hate->IsBot()) {
is_top_client_type = true; isTopClientType = true;
top_client_type_in_range = top_hate; top_client_type_in_range = top_hate;
} }
} }
if (!is_top_client_type) { if (!isTopClientType) {
if (top_hate->IsMerc()) { if (top_hate->IsMerc()) {
is_top_client_type = true; isTopClientType = true;
top_client_type_in_range = top_hate; top_client_type_in_range = top_hate;
} }
} }
if (!is_top_client_type) { if (!isTopClientType) {
if (top_hate->GetSpecialAbility(ALLOW_TO_TANK)) { if (top_hate->GetSpecialAbility(ALLOW_TO_TANK)){
is_top_client_type = true; isTopClientType = true;
top_client_type_in_range = top_hate; top_client_type_in_range = top_hate;
} }
} }
if (!is_top_client_type) { if (!isTopClientType)
return top_client_type_in_range ? top_client_type_in_range : nullptr; return top_client_type_in_range ? top_client_type_in_range : nullptr;
}
return top_hate ? top_hate : nullptr; return top_hate ? top_hate : nullptr;
} else { }
if (!top_hate && skipped_count > 0) { else {
if (top_hate == nullptr && skipped_count > 0) {
return center->GetTarget() ? center->GetTarget() : nullptr; return center->GetTarget() ? center->GetTarget() : nullptr;
} }
return top_hate ? top_hate : nullptr; return top_hate ? top_hate : nullptr;
} }
} else { }
auto iterator = list.begin(); else{
int skipped_count = 0; auto iterator = list.begin();
while (iterator != list.end()) { int skipped_count = 0;
while (iterator != list.end())
{
struct_HateList *cur = (*iterator); struct_HateList *cur = (*iterator);
if (cur) { if (cur) {
Mob *m = cur->entity_on_hatelist; if (cur->entity_on_hatelist == skip) {
if (!m) {
++iterator; ++iterator;
continue; continue;
} }
if (m == skip) { if (skip_mezzed && cur->entity_on_hatelist->IsMezzed()) {
++iterator; ++iterator;
continue; continue;
} }
if (skip_mezzed && m->IsMezzed()) { if (cur->entity_on_hatelist != nullptr && ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy))
++iterator; {
continue; top_hate = cur->entity_on_hatelist;
} hate = cur->stored_hate_amount;
if ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy) {
top_hate = m;
hate = cur->stored_hate_amount;
} }
} }
++iterator; ++iterator;
} }
if (top_hate == nullptr && skipped_count > 0) {
if (!top_hate && skipped_count > 0) {
return center->GetTarget() ? center->GetTarget() : nullptr; return center->GetTarget() ? center->GetTarget() : nullptr;
} }
return top_hate ? top_hate : nullptr; return top_hate ? top_hate : nullptr;
} }
return nullptr; return nullptr;
} }
Mob *HateList::GetMobWithMostHateOnList(bool skip_mezzed){ Mob *HateList::GetEntWithMostHateOnList(bool skip_mezzed){
Mob* top = nullptr; Mob* top = nullptr;
int64 hate = -1; int64 hate = -1;
@@ -563,7 +539,7 @@ Mob *HateList::GetMobWithMostHateOnList(bool skip_mezzed){
if (cur) { if (cur) {
LogHateDetail( LogHateDetail(
"Looping GetMobWithMostHateOnList1 [{}] cur [{}] hate [{}] calc [{}]", "Looping GetEntWithMostHateOnList1 [{}] cur [{}] hate [{}] calc [{}]",
cur->entity_on_hatelist->GetMobDescription(), cur->entity_on_hatelist->GetMobDescription(),
cur->stored_hate_amount, cur->stored_hate_amount,
hate, hate,
@@ -573,7 +549,7 @@ Mob *HateList::GetMobWithMostHateOnList(bool skip_mezzed){
if (cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate)) if (cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate))
{ {
LogHateDetail( LogHateDetail(
"Looping GetMobWithMostHateOnList2 [{}]", "Looping GetEntWithMostHateOnList2 [{}]",
cur->entity_on_hatelist->GetMobDescription() cur->entity_on_hatelist->GetMobDescription()
); );
@@ -589,45 +565,53 @@ Mob *HateList::GetMobWithMostHateOnList(bool skip_mezzed){
} }
Mob *HateList::GetRandomMobOnHateList(EntityFilterType filter_type) Mob *HateList::GetRandomEntOnHateList(bool skip_mezzed)
{ {
const auto &l = GetFilteredHateList(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;
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; return nullptr;
} }
if (count == 1) { // No need to do all that extra work if we only have one hate entry if (skip_mezzed) {
auto c = *l.begin();
if (c) {
Mob *m = c->entity_on_hatelist;
if (!m) {
return nullptr;
}
return m; 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 (skip_mezzed && iter->entity_on_hatelist->IsMezzed()) {
continue;
}
if (counter < random) {
++counter;
continue;
} }
return nullptr; return iter->entity_on_hatelist;
}
auto r = l.begin();
int random_index = rand() % count;
std::advance(r, random_index);
auto e = *r;
Mob *m = e->entity_on_hatelist;
if (m) {
return m;
} }
return nullptr; return nullptr;
} }
Mob *HateList::GetEscapingMobOnHateList(Mob *center, float range, bool first) { Mob *HateList::GetEscapingEntOnHateList(Mob *center, float range, bool first) {
// function is still in design stage // function is still in design stage
if (!center) if (!center)
@@ -869,6 +853,153 @@ 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) void HateList::DamageHateList(int64 damage, uint32 distance, EntityFilterType filter_type, bool is_percentage)
{ {
if (damage <= 0) { if (damage <= 0) {
+9 -5
View File
@@ -41,12 +41,16 @@ public:
HateList(); HateList();
~HateList(); ~HateList();
Mob *GetClosestEntOnHateList(Mob *hater, bool skip_mezzed = false, EntityFilterType filter_type = EntityFilterType::All); Mob *GetClosestEntOnHateList(Mob *hater, bool skip_mezzed = false, EntityFilterType entity_type = EntityFilterType::All);
Mob *GetDamageTopOnHateList(Mob *hater); // didn't add 'skip_mezzed' due to calls being in ::Death() Mob *GetDamageTopOnHateList(Mob *hater); // didn't add 'skip_mezzed' due to calls being in ::Death()
Mob *GetMobWithMostHateOnList(Mob *center, Mob *skip = nullptr, bool skip_mezzed = false, EntityFilterType filter_type = EntityFilterType::All); Mob *GetEntWithMostHateOnList(Mob *center, Mob *skip = nullptr, bool skip_mezzed = false);
Mob *GetRandomMobOnHateList(EntityFilterType filter_type = EntityFilterType::All); Mob *GetRandomEntOnHateList(bool skip_mezzed = false);
Mob *GetMobWithMostHateOnList(bool skip_mezzed = false); Mob *GetEntWithMostHateOnList(bool skip_mezzed = false);
Mob *GetEscapingMobOnHateList(Mob *center, float range = 0.0f, bool first = 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);
bool IsEntOnHateList(Mob *mob); bool IsEntOnHateList(Mob *mob);
bool IsHateListEmpty(); bool IsHateListEmpty();
-50
View File
@@ -4739,53 +4739,3 @@ bool Client::IsAugmentRestricted(uint8 item_type, uint32 augment_restriction)
return false; 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
);
}
+214 -233
View File
@@ -27,37 +27,24 @@
#include "zonedb.h" #include "zonedb.h"
#include "global_loot_manager.h" #include "global_loot_manager.h"
#include "../common/repositories/criteria/content_filter_criteria.h" #include "../common/repositories/criteria/content_filter_criteria.h"
#include "quest_parser_collection.h"
#ifdef _WINDOWS #ifdef _WINDOWS
#define snprintf _snprintf #define snprintf _snprintf
#endif #endif
// Queries the loottable: adds item & coin to the npc // Queries the loottable: adds item & coin to the npc
void ZoneDatabase::AddLootTableToNPC( void ZoneDatabase::AddLootTableToNPC(NPC* npc, uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat) {
NPC *npc, const LootTable_Struct* lts = nullptr;
uint32 loottable_id, // global loot passes nullptr for these
ItemList *itemlist, bool bGlobal = copper == nullptr && silver == nullptr && gold == nullptr && plat == nullptr;
uint32 *copper, if (!bGlobal) {
uint32 *silver,
uint32 *gold,
uint32 *plat
)
{
const bool is_global = (
copper == nullptr &&
silver == nullptr &&
gold == nullptr &&
plat == nullptr
);
if (!is_global) {
*copper = 0; *copper = 0;
*silver = 0; *silver = 0;
*gold = 0; *gold = 0;
*plat = 0; *plat = 0;
} }
const auto *lts = database.GetLootTable(loottable_id); lts = database.GetLootTable(loottable_id);
if (!lts) { if (!lts) {
return; return;
} }
@@ -68,23 +55,19 @@ void ZoneDatabase::AddLootTableToNPC(
uint32 min_cash = lts->mincash; uint32 min_cash = lts->mincash;
uint32 max_cash = lts->maxcash; uint32 max_cash = lts->maxcash;
if (min_cash > max_cash) { if(min_cash > max_cash) {
const uint32 t = min_cash; uint32 t = min_cash;
min_cash = max_cash; min_cash = max_cash;
max_cash = t; max_cash = t;
} }
uint32 cash = 0; uint32 cash = 0;
if (!is_global) { if (!bGlobal) {
if ( if(max_cash > 0 && lts->avgcoin > 0 && EQ::ValueWithin(lts->avgcoin, min_cash, max_cash)) {
max_cash > 0 && float upper_chance = (float)(lts->avgcoin - min_cash) / (float)(max_cash - min_cash);
lts->avgcoin > 0 && float avg_cash_roll = (float)zone->random.Real(0.0, 1.0);
EQ::ValueWithin(lts->avgcoin, min_cash, max_cash)
) {
const float upper_chance = static_cast<float>(lts->avgcoin - min_cash) / static_cast<float>(max_cash - min_cash);
const float avg_cash_roll = static_cast<float>(zone->random.Real(0.0, 1.0));
if (avg_cash_roll < upper_chance) { if(avg_cash_roll < upper_chance) {
cash = zone->random.Int(lts->avgcoin, max_cash); cash = zone->random.Int(lts->avgcoin, max_cash);
} else { } else {
cash = zone->random.Int(min_cash, lts->avgcoin); cash = zone->random.Int(min_cash, lts->avgcoin);
@@ -94,7 +77,7 @@ void ZoneDatabase::AddLootTableToNPC(
} }
} }
if (cash != 0) { if(cash != 0) {
*plat = cash / 1000; *plat = cash / 1000;
cash -= *plat * 1000; cash -= *plat * 1000;
@@ -107,23 +90,25 @@ void ZoneDatabase::AddLootTableToNPC(
*copper = cash; *copper = cash;
} }
const uint32 global_loot_multiplier = RuleI(Zone, GlobalLootMultiplier); uint32 global_loot_multiplier = RuleI(Zone, GlobalLootMultiplier);
for (uint32 i = 0; i < lts->NumEntries; i++) { // Do items
for (uint32 i=0; i<lts->NumEntries; i++) {
for (uint32 k = 1; k <= (lts->Entries[i].multiplier * global_loot_multiplier); k++) { for (uint32 k = 1; k <= (lts->Entries[i].multiplier * global_loot_multiplier); k++) {
const uint8 drop_limit = lts->Entries[i].droplimit; uint8 droplimit = lts->Entries[i].droplimit;
const uint8 minimum_drop = lts->Entries[i].mindrop; uint8 mindrop = lts->Entries[i].mindrop;
//LootTable Entry probability //LootTable Entry probability
const float probability = lts->Entries[i].probability; float ltchance = 0.0f;
ltchance = lts->Entries[i].probability;
float drop_chance = 0.0f; float drop_chance = 0.0f;
if (EQ::ValueWithin(probability, 0.0f, 100.0f)) { if(ltchance > 0.0 && ltchance < 100.0) {
drop_chance = static_cast<float>(zone->random.Real(0.0, 100.0)); drop_chance = (float)zone->random.Real(0.0, 100.0);
} }
if (probability != 0.0 && (probability == 100.0 || drop_chance <= probability)) { if (ltchance != 0.0 && (ltchance == 100.0 || drop_chance <= ltchance)) {
AddLootDropToNPC(npc, lts->Entries[i].lootdrop_id, itemlist, drop_limit, minimum_drop); AddLootDropToNPC(npc, lts->Entries[i].lootdrop_id, itemlist, droplimit, mindrop);
} }
} }
} }
@@ -133,29 +118,31 @@ void ZoneDatabase::AddLootTableToNPC(
// maxdrops = size of the array npcd // maxdrops = size of the array npcd
void ZoneDatabase::AddLootDropToNPC(NPC *npc, uint32 lootdrop_id, ItemList *item_list, uint8 droplimit, uint8 mindrop) void ZoneDatabase::AddLootDropToNPC(NPC *npc, uint32 lootdrop_id, ItemList *item_list, uint8 droplimit, uint8 mindrop)
{ {
const auto *lds = GetLootDrop(lootdrop_id); const LootDrop_Struct *loot_drop = GetLootDrop(lootdrop_id);
if ( if (!loot_drop) {
!lds || return;
lds->NumEntries == 0 || }
!content_service.DoesPassContentFiltering(lds->content_flags)
) { if (loot_drop->NumEntries == 0) {
return;
}
if (!content_service.DoesPassContentFiltering(loot_drop->content_flags)) {
return; return;
} }
// if this lootdrop is droplimit=0 and mindrop 0, scan list once and return // if this lootdrop is droplimit=0 and mindrop 0, scan list once and return
if (droplimit == 0 && mindrop == 0) { if (droplimit == 0 && mindrop == 0) {
for (uint32 i = 0; i < lds->NumEntries; ++i) { for (uint32 i = 0; i < loot_drop->NumEntries; ++i) {
const uint8 charges = lds->Entries[i].multiplier; int charges = loot_drop->Entries[i].multiplier;
for (int j = 0; j < charges; ++j) { for (int j = 0; j < charges; ++j) {
if ( if (zone->random.Real(0.0, 100.0) <= loot_drop->Entries[i].chance &&
zone->random.Real(0.0, 100.0) <= lds->Entries[i].chance && npc->MeetsLootDropLevelRequirements(loot_drop->Entries[i], true)) {
npc->MeetsLootDropLevelRequirements(lds->Entries[i], true) const EQ::ItemData *database_item = GetItem(loot_drop->Entries[i].item_id);
) {
const EQ::ItemData *database_item = GetItem(lds->Entries[i].item_id);
npc->AddLootDrop( npc->AddLootDrop(
database_item, database_item,
item_list, item_list,
lds->Entries[i] loot_drop->Entries[i]
); );
} }
} }
@@ -163,7 +150,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC *npc, uint32 lootdrop_id, ItemList *item
return; return;
} }
if (lds->NumEntries > 100 && droplimit == 0) { if (loot_drop->NumEntries > 100 && droplimit == 0) {
droplimit = 10; droplimit = 10;
} }
@@ -176,17 +163,16 @@ void ZoneDatabase::AddLootDropToNPC(NPC *npc, uint32 lootdrop_id, ItemList *item
bool roll_table_chance_bypass = false; bool roll_table_chance_bypass = false;
bool active_item_list = false; bool active_item_list = false;
for (uint32 i = 0; i < lds->NumEntries; ++i) { for (uint32 i = 0; i < loot_drop->NumEntries; ++i) {
const EQ::ItemData *db_item = GetItem(lds->Entries[i].item_id); const EQ::ItemData *db_item = GetItem(loot_drop->Entries[i].item_id);
if (db_item && npc->MeetsLootDropLevelRequirements(lds->Entries[i])) { if (db_item && npc->MeetsLootDropLevelRequirements(loot_drop->Entries[i])) {
roll_t += lds->Entries[i].chance; roll_t += loot_drop->Entries[i].chance;
if (loot_drop->Entries[i].chance >= 100) {
if (lds->Entries[i].chance >= 100) {
roll_table_chance_bypass = true; roll_table_chance_bypass = true;
} else {
no_loot_prob *= (100 - lds->Entries[i].chance) / 100.0f;
} }
else {
no_loot_prob *= (100 - loot_drop->Entries[i].chance) / 100.0f;
}
active_item_list = true; active_item_list = true;
} }
} }
@@ -205,40 +191,41 @@ void ZoneDatabase::AddLootDropToNPC(NPC *npc, uint32 lootdrop_id, ItemList *item
for (int i = 0; i < droplimit; ++i) { for (int i = 0; i < droplimit; ++i) {
if (drops < mindrop || roll_table_chance_bypass || (float) zone->random.Real(0.0, 1.0) >= no_loot_prob) { if (drops < mindrop || roll_table_chance_bypass || (float) zone->random.Real(0.0, 1.0) >= no_loot_prob) {
float roll = (float) zone->random.Real(0.0, roll_t); float roll = (float) zone->random.Real(0.0, roll_t);
for (uint32 j = 0; j < lds->NumEntries; ++j) { for (uint32 j = 0; j < loot_drop->NumEntries; ++j) {
const auto *db_item = GetItem(lds->Entries[j].item_id); const EQ::ItemData *db_item = GetItem(loot_drop->Entries[j].item_id);
if (db_item) { if (db_item) {
// if it doesn't meet the requirements do nothing // if it doesn't meet the requirements do nothing
if (!npc->MeetsLootDropLevelRequirements(lds->Entries[j])) { if (!npc->MeetsLootDropLevelRequirements(loot_drop->Entries[j])) {
continue; continue;
} }
if (roll < lds->Entries[j].chance) { if (roll < loot_drop->Entries[j].chance) {
npc->AddLootDrop( npc->AddLootDrop(
db_item, db_item,
item_list, item_list,
lds->Entries[j] loot_drop->Entries[j]
); );
drops++; drops++;
uint8 charges = lds->Entries[i].multiplier; int charges = (int) loot_drop->Entries[i].multiplier;
charges = EQ::ClampLower(charges, static_cast<uint8>(1)); charges = EQ::ClampLower(charges, 1);
for (int k = 1; k < charges; ++k) { for (int k = 1; k < charges; ++k) {
float c_roll = static_cast<float>(zone->random.Real(0.0, 100.0)); float c_roll = (float) zone->random.Real(0.0, 100.0);
if (c_roll <= lds->Entries[i].chance) { if (c_roll <= loot_drop->Entries[i].chance) {
npc->AddLootDrop( npc->AddLootDrop(
db_item, db_item,
item_list, item_list,
lds->Entries[i] loot_drop->Entries[i]
); );
} }
} }
j = lds->NumEntries; j = loot_drop->NumEntries;
break; break;
} else { }
roll -= lds->Entries[j].chance; else {
roll -= loot_drop->Entries[j].chance;
} }
} }
} }
@@ -304,18 +291,19 @@ void NPC::AddLootDrop(
ItemList *itemlist, ItemList *itemlist,
LootDropEntries_Struct loot_drop, LootDropEntries_Struct loot_drop,
bool wear_change, bool wear_change,
uint32 augment_one, uint32 aug1,
uint32 augment_two, uint32 aug2,
uint32 augment_three, uint32 aug3,
uint32 augment_four, uint32 aug4,
uint32 augment_five, uint32 aug5,
uint32 augment_six uint32 aug6
) )
{ {
if (!item2) { if (!item2) {
return; return;
} }
//make sure we are doing something...
if (!itemlist && !wear_change) { if (!itemlist && !wear_change) {
return; return;
} }
@@ -352,17 +340,18 @@ void NPC::AddLootDrop(
item->item_id = item2->ID; item->item_id = item2->ID;
item->charges = loot_drop.item_charges; item->charges = loot_drop.item_charges;
item->aug_1 = augment_one; item->aug_1 = aug1;
item->aug_2 = augment_two; item->aug_2 = aug2;
item->aug_3 = augment_three; item->aug_3 = aug3;
item->aug_4 = augment_four; item->aug_4 = aug4;
item->aug_5 = augment_five; item->aug_5 = aug5;
item->aug_6 = augment_six; item->aug_6 = aug6;
item->attuned = false; item->attuned = 0;
item->trivial_min_level = loot_drop.trivial_min_level; item->trivial_min_level = loot_drop.trivial_min_level;
item->trivial_max_level = loot_drop.trivial_max_level; item->trivial_max_level = loot_drop.trivial_max_level;
item->equip_slot = EQ::invslot::SLOT_INVALID; item->equip_slot = EQ::invslot::SLOT_INVALID;
// unsure if required to equip, YOLO for now // unsure if required to equip, YOLO for now
if (item2->ItemType == EQ::item::ItemTypeBow) { if (item2->ItemType == EQ::item::ItemTypeBow) {
SetBowEquipped(true); SetBowEquipped(true);
@@ -374,17 +363,17 @@ void NPC::AddLootDrop(
bool found = false; // track if we found an empty slot we fit into bool found = false; // track if we found an empty slot we fit into
int found_slot = INVALID_INDEX; // for multi-slot items int foundslot = INVALID_INDEX; // for multi-slot items
auto *inst = database.CreateItem( const auto* inst = database.CreateItem(
item2->ID, item2->ID,
loot_drop.item_charges, loot_drop.item_charges,
augment_one, aug1,
augment_two, aug2,
augment_three, aug3,
augment_four, aug4,
augment_five, aug5,
augment_six aug6
); );
if (!inst) { if (!inst) {
@@ -392,8 +381,9 @@ void NPC::AddLootDrop(
} }
if (loot_drop.equip_item > 0) { if (loot_drop.equip_item > 0) {
uint8 equipment_slot = UINT8_MAX; uint8 eslot = 0xFF;
const EQ::ItemData *compitem = nullptr; char newid[20];
const EQ::ItemData* compitem = nullptr;
// Equip rules are as follows: // Equip rules are as follows:
// If the item has the NoPet flag set it will not be equipped. // If the item has the NoPet flag set it will not be equipped.
@@ -405,136 +395,141 @@ void NPC::AddLootDrop(
// it is an improvement. // it is an improvement.
if (!item2->NoPet) { if (!item2->NoPet) {
for ( for (int i = EQ::invslot::EQUIPMENT_BEGIN; !found && i <= EQ::invslot::EQUIPMENT_END; i++) {
int i = EQ::invslot::EQUIPMENT_BEGIN; uint32 slots = (1 << i);
!found && i <= EQ::invslot::EQUIPMENT_END;
i++
) {
const uint32 slots = (1 << i);
if (item2->Slots & slots) { if (item2->Slots & slots) {
if (equipment[i]) { if(equipment[i])
{
compitem = database.GetItem(equipment[i]); compitem = database.GetItem(equipment[i]);
if ( if (item2->AC > compitem->AC ||
item2->AC > compitem->AC || (item2->AC == compitem->AC && item2->HP > compitem->HP))
(item2->AC == compitem->AC && item2->HP > compitem->HP) {
) {
// item would be an upgrade // item would be an upgrade
// check if we're multi-slot, if yes then we have to keep // check if we're multi-slot, if yes then we have to keep
// looking in case any of the other slots we can fit into are empty. // looking in case any of the other slots we can fit into are empty.
if (item2->Slots != slots) { if (item2->Slots != slots) {
found_slot = i; foundslot = i;
} else { }
else {
// Unequip old item // Unequip old item
auto *old_item = GetItem(i); auto* olditem = GetItem(i);
old_item->equip_slot = EQ::invslot::SLOT_INVALID; olditem->equip_slot = EQ::invslot::SLOT_INVALID;
equipment[i] = item2->ID; equipment[i] = item2->ID;
found_slot = i; foundslot = i;
found = true; found = true;
} }
} } // end if ac
} else {
equipment[i] = item2->ID;
found_slot = i;
found = true;
} }
} else
} {
} equipment[i] = item2->ID;
foundslot = i;
found = true;
}
} // end if (slots)
} // end for
} // end if NoPet
// Possible slot was found but not selected. Pick it now. // Possible slot was found but not selected. Pick it now.
if (!found && found_slot >= 0) { if (!found && foundslot >= 0) {
equipment[found_slot] = item2->ID; equipment[foundslot] = item2->ID;
found = true; found = true;
} }
uint32 equipment_material; // @merth: IDFile size has been increased, this needs to change
if ( uint16 emat;
item2->Material <= 0 || if(item2->Material <= 0
( || (item2->Slots & ((1 << EQ::invslot::slotPrimary) | (1 << EQ::invslot::slotSecondary)))) {
item2->Slots & ( memset(newid, 0, sizeof(newid));
(1 << EQ::invslot::slotPrimary) | for(int i=0;i<7;i++){
(1 << EQ::invslot::slotSecondary) if (!isalpha(item2->IDFile[i])){
) strn0cpy(newid, &item2->IDFile[i],6);
) i=8;
) {
equipment_material = Strings::ToUnsignedInt(&item2->IDFile[2]);
} else {
equipment_material = item2->Material;
}
if (found_slot == EQ::invslot::slotPrimary) {
equipment_slot = EQ::textures::weaponPrimary;
if (item2->Damage > 0) {
SendAddPlayerState(PlayerState::PrimaryWeaponEquipped);
if (!RuleB(Combat, ClassicNPCBackstab)) {
SetFacestab(true);
} }
} }
if (item2->IsType2HWeapon()) { emat = Strings::ToInt(newid);
SetTwoHanderEquipped(true); } else {
} emat = item2->Material;
} else if ( }
found_slot == EQ::invslot::slotSecondary &&
(
GetOwner() ||
(CanThisClassDualWield() && zone->random.Roll(NPC_DW_CHANCE)) ||
item2->Damage == 0
) &&
(
item2->IsType1HWeapon() ||
item2->ItemType == EQ::item::ItemTypeShield ||
item2->ItemType == EQ::item::ItemTypeLight
)
) {
equipment_slot = EQ::textures::weaponSecondary;
if (foundslot == EQ::invslot::slotPrimary) {
eslot = EQ::textures::weaponPrimary;
if (item2->Damage > 0) { if (item2->Damage > 0) {
SendAddPlayerState(PlayerState::PrimaryWeaponEquipped);
if (!RuleB(Combat, ClassicNPCBackstab))
SetFacestab(true);
}
if (item2->IsType2HWeapon())
SetTwoHanderEquipped(true);
}
else if (foundslot == EQ::invslot::slotSecondary
&& (GetOwner() != nullptr || (CanThisClassDualWield() && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) &&
(item2->IsType1HWeapon() || item2->ItemType == EQ::item::ItemTypeShield || item2->ItemType == EQ::item::ItemTypeLight))
{
eslot = EQ::textures::weaponSecondary;
if (item2->Damage > 0)
SendAddPlayerState(PlayerState::SecondaryWeaponEquipped); SendAddPlayerState(PlayerState::SecondaryWeaponEquipped);
} }
} else if (found_slot == EQ::invslot::slotHead) { else if (foundslot == EQ::invslot::slotHead) {
equipment_slot = EQ::textures::armorHead; eslot = EQ::textures::armorHead;
} else if (found_slot == EQ::invslot::slotChest) { }
equipment_slot = EQ::textures::armorChest; else if (foundslot == EQ::invslot::slotChest) {
} else if (found_slot == EQ::invslot::slotArms) { eslot = EQ::textures::armorChest;
equipment_slot = EQ::textures::armorArms; }
} else if (EQ::ValueWithin(found_slot, EQ::invslot::slotWrist1, EQ::invslot::slotWrist2)) { else if (foundslot == EQ::invslot::slotArms) {
equipment_slot = EQ::textures::armorWrist; eslot = EQ::textures::armorArms;
} else if (found_slot == EQ::invslot::slotHands) { }
equipment_slot = EQ::textures::armorHands; else if (foundslot == EQ::invslot::slotWrist1 || foundslot == EQ::invslot::slotWrist2) {
} else if (found_slot == EQ::invslot::slotLegs) { eslot = EQ::textures::armorWrist;
equipment_slot = EQ::textures::armorLegs; }
} else if (found_slot == EQ::invslot::slotFeet) { else if (foundslot == EQ::invslot::slotHands) {
equipment_slot = EQ::textures::armorFeet; eslot = EQ::textures::armorHands;
}
else if (foundslot == EQ::invslot::slotLegs) {
eslot = EQ::textures::armorLegs;
}
else if (foundslot == EQ::invslot::slotFeet) {
eslot = EQ::textures::armorFeet;
} }
if (equipment_slot != UINT8_MAX) { /*
if (wear_change) { what was this about???
p_wear_change_struct->wear_slot_id = equipment_slot;
p_wear_change_struct->material = equipment_material;
}
}
if (((npc->GetRace()==127) && (npc->CastToMob()->GetOwnerID()!=0)) && (item2->Slots==24576) || (item2->Slots==8192) || (item2->Slots==16384)){
npc->d_melee_texture2=Strings::ToInt(newid);
wc->wear_slot_id=8;
if (item2->Material >0)
wc->material=item2->Material;
else
wc->material=Strings::ToInt(newid);
npc->AC+=item2->AC;
npc->STR+=item2->STR;
npc->INT+=item2->INT;
}
*/
//if we found an open slot it goes in...
if(eslot != 0xFF) {
if(wear_change) {
p_wear_change_struct->wear_slot_id = eslot;
p_wear_change_struct->material = emat;
}
}
if (found) { if (found) {
item->equip_slot = found_slot; item->equip_slot = foundslot;
} }
} }
if (itemlist) { if (itemlist) {
if (found_slot != INVALID_INDEX) { if (foundslot != INVALID_INDEX) {
GetInv().PutItem(found_slot, *inst); GetInv().PutItem(foundslot, *inst);
}
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_LOOT_ADDED)) {
std::vector<std::any> args = { inst };
parse->EventNPC(EVENT_LOOT_ADDED, this, nullptr, "", 0, &args);
} }
itemlist->push_back(item); itemlist->push_back(item);
@@ -556,69 +551,55 @@ void NPC::AddLootDrop(
} }
UpdateEquipmentLight(); UpdateEquipmentLight();
if (UpdateActiveLight()) { if (UpdateActiveLight()) {
SendAppearancePacket(AT_Light, GetActiveLightType()); SendAppearancePacket(AT_Light, GetActiveLightType());
} }
} }
void NPC::AddItem(const EQ::ItemData *item, uint16 charges, bool equip_item) void NPC::AddItem(const EQ::ItemData *item, uint16 charges, bool equipitem)
{ {
//slot isnt needed, its determined from the item.
auto loot_drop_entry = NPC::NewLootDropEntry(); auto loot_drop_entry = NPC::NewLootDropEntry();
loot_drop_entry.equip_item = static_cast<uint8>(equipitem ? 1 : 0);
loot_drop_entry.equip_item = static_cast<uint8>(equip_item ? 1 : 0);
loot_drop_entry.item_charges = charges; loot_drop_entry.item_charges = charges;
AddLootDrop(item, &itemlist, loot_drop_entry, true); AddLootDrop(item, &itemlist, loot_drop_entry, true);
} }
void NPC::AddItem( void NPC::AddItem(
uint32 item_id, uint32 itemid,
uint16 charges, uint16 charges,
bool equip_item, bool equipitem,
uint32 augment_one, uint32 aug1,
uint32 augment_two, uint32 aug2,
uint32 augment_three, uint32 aug3,
uint32 augment_four, uint32 aug4,
uint32 augment_five, uint32 aug5,
uint32 augment_six uint32 aug6
) )
{ {
const auto *item = database.GetItem(item_id); //slot isnt needed, its determined from the item.
if (!item) { const EQ::ItemData *i = database.GetItem(itemid);
if (i == nullptr) {
return; return;
} }
auto loot_drop_entry = NPC::NewLootDropEntry(); auto loot_drop_entry = NPC::NewLootDropEntry();
loot_drop_entry.equip_item = static_cast<uint8>(equipitem ? 1 : 0);
loot_drop_entry.equip_item = static_cast<uint8>(equip_item ? 1 : 0);
loot_drop_entry.item_charges = charges; loot_drop_entry.item_charges = charges;
AddLootDrop( AddLootDrop(i, &itemlist, loot_drop_entry, true, aug1, aug2, aug3, aug4, aug5, aug6);
item,
&itemlist,
loot_drop_entry,
true,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six
);
} }
void NPC::AddLootTable() void NPC::AddLootTable() {
{
if (npctype_id != 0) { // check if it's a GM spawn if (npctype_id != 0) { // check if it's a GM spawn
database.AddLootTableToNPC(this, loottable_id, &itemlist, &copper, &silver, &gold, &platinum); database.AddLootTableToNPC(this,loottable_id, &itemlist, &copper, &silver, &gold, &platinum);
} }
} }
void NPC::AddLootTable(uint32 loottable_id) void NPC::AddLootTable(uint32 ldid) {
{
if (npctype_id != 0) { // check if it's a GM spawn if (npctype_id != 0) { // check if it's a GM spawn
database.AddLootTableToNPC(this, loottable_id, &itemlist, &copper, &silver, &gold, &platinum); database.AddLootTableToNPC(this,ldid, &itemlist, &copper, &silver, &gold, &platinum);
} }
} }
+1 -109
View File
@@ -389,96 +389,6 @@ int Lua_Bot::GetRawItemAC() {
return self->GetRawItemAC(); return self->GetRawItemAC();
} }
void Lua_Bot::ClearDisciplineReuseTimer() {
Lua_Safe_Call_Void();
return self->ClearDisciplineReuseTimer();
}
void Lua_Bot::ClearDisciplineReuseTimer(uint16 spell_id) {
Lua_Safe_Call_Void();
return self->ClearDisciplineReuseTimer(spell_id);
}
void Lua_Bot::ClearItemReuseTimer() {
Lua_Safe_Call_Void();
return self->ClearItemReuseTimer();
}
void Lua_Bot::ClearItemReuseTimer(uint32 item_id) {
Lua_Safe_Call_Void();
return self->ClearItemReuseTimer(item_id);
}
void Lua_Bot::ClearSpellRecastTimer() {
Lua_Safe_Call_Void();
return self->ClearSpellRecastTimer();
}
void Lua_Bot::ClearSpellRecastTimer(uint16 spell_id) {
Lua_Safe_Call_Void();
return self->ClearSpellRecastTimer(spell_id);
}
uint32 Lua_Bot::GetDisciplineReuseTimer() {
Lua_Safe_Call_Int();
return self->GetDisciplineReuseRemainingTime();
}
uint32 Lua_Bot::GetDisciplineReuseTimer(uint16 spell_id) {
Lua_Safe_Call_Int();
return self->GetDisciplineReuseRemainingTime(spell_id);
}
uint32 Lua_Bot::GetItemReuseTimer() {
Lua_Safe_Call_Int();
return self->GetItemReuseRemainingTime();
}
uint32 Lua_Bot::GetItemReuseTimer(uint32 item_id) {
Lua_Safe_Call_Int();
return self->GetItemReuseRemainingTime(item_id);
}
uint32 Lua_Bot::GetSpellRecastTimer() {
Lua_Safe_Call_Int();
return self->GetSpellRecastRemainingTime();
}
uint32 Lua_Bot::GetSpellRecastTimer(uint16 spell_id) {
Lua_Safe_Call_Int();
return self->GetSpellRecastRemainingTime(spell_id);
}
void Lua_Bot::SetDisciplineReuseTimer(uint16 spell_id) {
Lua_Safe_Call_Void();
return self->SetDisciplineReuseTimer(spell_id);
}
void Lua_Bot::SetDisciplineReuseTimer(uint16 spell_id, uint32 reuse_timer) {
Lua_Safe_Call_Void();
return self->SetDisciplineReuseTimer(spell_id, reuse_timer);
}
void Lua_Bot::SetItemReuseTimer(uint32 item_id) {
Lua_Safe_Call_Void();
return self->SetItemReuseTimer(item_id);
}
void Lua_Bot::SetItemReuseTimer(uint32 item_id, uint32 reuse_timer) {
Lua_Safe_Call_Void();
return self->SetItemReuseTimer(item_id, reuse_timer);
}
void Lua_Bot::SetSpellRecastTimer(uint16 spell_id) {
Lua_Safe_Call_Void();
return self->SetSpellRecastTimer(spell_id);
}
void Lua_Bot::SetSpellRecastTimer(uint16 spell_id, uint32 recast_delay) {
Lua_Safe_Call_Void();
return self->SetSpellRecastTimer(spell_id, recast_delay);
}
bool Lua_Bot::IsGrouped() { bool Lua_Bot::IsGrouped() {
Lua_Safe_Call_Bool(); Lua_Safe_Call_Bool();
return self->IsGrouped(); return self->IsGrouped();
@@ -690,12 +600,6 @@ luabind::scope lua_register_bot() {
.def("ApplySpellRaid", (void(Lua_Bot::*)(int,int,int,bool,bool))&Lua_Bot::ApplySpellRaid) .def("ApplySpellRaid", (void(Lua_Bot::*)(int,int,int,bool,bool))&Lua_Bot::ApplySpellRaid)
.def("Camp", (void(Lua_Bot::*)(void))&Lua_Bot::Camp) .def("Camp", (void(Lua_Bot::*)(void))&Lua_Bot::Camp)
.def("Camp", (void(Lua_Bot::*)(bool))&Lua_Bot::Camp) .def("Camp", (void(Lua_Bot::*)(bool))&Lua_Bot::Camp)
.def("ClearDisciplineReuseTimer", (void(Lua_Bot::*)())&Lua_Bot::ClearDisciplineReuseTimer)
.def("ClearDisciplineReuseTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::ClearDisciplineReuseTimer)
.def("ClearItemReuseTimer", (void(Lua_Bot::*)())&Lua_Bot::ClearItemReuseTimer)
.def("ClearItemReuseTimer", (void(Lua_Bot::*)(uint32))&Lua_Bot::ClearItemReuseTimer)
.def("ClearSpellRecastTimer", (void(Lua_Bot::*)())&Lua_Bot::ClearSpellRecastTimer)
.def("ClearSpellRecastTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::ClearSpellRecastTimer)
.def("CountBotItem", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountBotItem) .def("CountBotItem", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountBotItem)
.def("CountItemEquippedByID", (int(Lua_Bot::*)(uint32))&Lua_Bot::CountItemEquippedByID) .def("CountItemEquippedByID", (int(Lua_Bot::*)(uint32))&Lua_Bot::CountItemEquippedByID)
.def("DeleteBucket", (void(Lua_Bot::*)(std::string))&Lua_Bot::DeleteBucket) .def("DeleteBucket", (void(Lua_Bot::*)(std::string))&Lua_Bot::DeleteBucket)
@@ -719,8 +623,6 @@ luabind::scope lua_register_bot() {
.def("GetBotID", (uint32(Lua_Bot::*)(void))&Lua_Bot::GetBotID) .def("GetBotID", (uint32(Lua_Bot::*)(void))&Lua_Bot::GetBotID)
.def("GetBotItem", (Lua_ItemInst(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItem) .def("GetBotItem", (Lua_ItemInst(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItem)
.def("GetBotItemIDBySlot", (uint32(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItemIDBySlot) .def("GetBotItemIDBySlot", (uint32(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItemIDBySlot)
.def("GetDisciplineReuseTimer", (uint32(Lua_Bot::*)())&Lua_Bot::GetDisciplineReuseTimer)
.def("GetDisciplineReuseTimer", (uint32(Lua_Bot::*)(uint16))&Lua_Bot::GetDisciplineReuseTimer)
.def("GetBucket", (std::string(Lua_Bot::*)(std::string))&Lua_Bot::GetBucket) .def("GetBucket", (std::string(Lua_Bot::*)(std::string))&Lua_Bot::GetBucket)
.def("GetBucketExpires", (std::string(Lua_Bot::*)(std::string))&Lua_Bot::GetBucketExpires) .def("GetBucketExpires", (std::string(Lua_Bot::*)(std::string))&Lua_Bot::GetBucketExpires)
.def("GetBucketRemaining", (std::string(Lua_Bot::*)(std::string))&Lua_Bot::GetBucketRemaining) .def("GetBucketRemaining", (std::string(Lua_Bot::*)(std::string))&Lua_Bot::GetBucketRemaining)
@@ -731,17 +633,13 @@ luabind::scope lua_register_bot() {
.def("GetInstrumentMod", (int(Lua_Bot::*)(int))&Lua_Bot::GetInstrumentMod) .def("GetInstrumentMod", (int(Lua_Bot::*)(int))&Lua_Bot::GetInstrumentMod)
.def("GetItemAt", (Lua_ItemInst(Lua_Bot::*)(int16))&Lua_Bot::GetItemAt) .def("GetItemAt", (Lua_ItemInst(Lua_Bot::*)(int16))&Lua_Bot::GetItemAt)
.def("GetItemIDAt", (int(Lua_Bot::*)(int16))&Lua_Bot::GetItemIDAt) .def("GetItemIDAt", (int(Lua_Bot::*)(int16))&Lua_Bot::GetItemIDAt)
.def("GetItemReuseTimer", (uint32(Lua_Bot::*)())&Lua_Bot::GetItemReuseTimer)
.def("GetItemReuseTimer", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::GetItemReuseTimer)
.def("GetOwner", (Lua_Mob(Lua_Bot::*)(void))&Lua_Bot::GetOwner) .def("GetOwner", (Lua_Mob(Lua_Bot::*)(void))&Lua_Bot::GetOwner)
.def("GetRaceAbbreviation", (std::string(Lua_Bot::*)(void))&Lua_Bot::GetRaceAbbreviation) .def("GetRaceAbbreviation", (std::string(Lua_Bot::*)(void))&Lua_Bot::GetRaceAbbreviation)
.def("GetRawItemAC", (int(Lua_Bot::*)(void))&Lua_Bot::GetRawItemAC) .def("GetRawItemAC", (int(Lua_Bot::*)(void))&Lua_Bot::GetRawItemAC)
.def("GetSpellDamage", (int(Lua_Bot::*)(void))&Lua_Bot::GetSpellDamage) .def("GetSpellDamage", (int(Lua_Bot::*)(void))&Lua_Bot::GetSpellDamage)
.def("GetSpellRecastTimer", (uint32(Lua_Bot::*)())&Lua_Bot::GetSpellRecastTimer)
.def("GetSpellRecastTimer", (uint32(Lua_Bot::*)(uint16))&Lua_Bot::GetSpellRecastTimer)
.def("HasAugmentEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasAugmentEquippedByID) .def("HasAugmentEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasAugmentEquippedByID)
.def("HasBotItem", (int16(Lua_Bot::*)(uint32))&Lua_Bot::HasBotItem) .def("HasBotItem", (int16(Lua_Bot::*)(uint32))&Lua_Bot::HasBotItem)
.def("HasBotSpellEntry", (bool(Lua_Bot::*)(uint16))&Lua_Bot::HasBotSpellEntry) .def("HasBotSpellEntry", (bool(Lua_Bot::*)(uint16)) & Lua_Bot::HasBotSpellEntry)
.def("HasItemEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasItemEquippedByID) .def("HasItemEquippedByID", (bool(Lua_Bot::*)(uint32))&Lua_Bot::HasItemEquippedByID)
.def("IsGrouped", (bool(Lua_Bot::*)(void))&Lua_Bot::IsGrouped) .def("IsGrouped", (bool(Lua_Bot::*)(void))&Lua_Bot::IsGrouped)
.def("IsSitting", (bool(Lua_Bot::*)(void))&Lua_Bot::IsSitting) .def("IsSitting", (bool(Lua_Bot::*)(void))&Lua_Bot::IsSitting)
@@ -757,10 +655,6 @@ luabind::scope lua_register_bot() {
.def("SetBucket", (void(Lua_Bot::*)(std::string,std::string,std::string))&Lua_Bot::SetBucket) .def("SetBucket", (void(Lua_Bot::*)(std::string,std::string,std::string))&Lua_Bot::SetBucket)
.def("SetExpansionBitmask", (void(Lua_Bot::*)(int))&Lua_Bot::SetExpansionBitmask) .def("SetExpansionBitmask", (void(Lua_Bot::*)(int))&Lua_Bot::SetExpansionBitmask)
.def("SetExpansionBitmask", (void(Lua_Bot::*)(int,bool))&Lua_Bot::SetExpansionBitmask) .def("SetExpansionBitmask", (void(Lua_Bot::*)(int,bool))&Lua_Bot::SetExpansionBitmask)
.def("SetDisciplineReuseTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::SetDisciplineReuseTimer)
.def("SetDisciplineReuseTimer", (void(Lua_Bot::*)(uint16, uint32))&Lua_Bot::SetDisciplineReuseTimer)
.def("SetItemReuseTimer", (void(Lua_Bot::*)(uint32))&Lua_Bot::SetItemReuseTimer)
.def("SetItemReuseTimer", (void(Lua_Bot::*)(uint32, uint32))&Lua_Bot::SetItemReuseTimer)
.def("SetSpellDuration", (void(Lua_Bot::*)(int))&Lua_Bot::SetSpellDuration) .def("SetSpellDuration", (void(Lua_Bot::*)(int))&Lua_Bot::SetSpellDuration)
.def("SetSpellDuration", (void(Lua_Bot::*)(int,int))&Lua_Bot::SetSpellDuration) .def("SetSpellDuration", (void(Lua_Bot::*)(int,int))&Lua_Bot::SetSpellDuration)
.def("SetSpellDuration", (void(Lua_Bot::*)(int,int,int))&Lua_Bot::SetSpellDuration) .def("SetSpellDuration", (void(Lua_Bot::*)(int,int,int))&Lua_Bot::SetSpellDuration)
@@ -774,8 +668,6 @@ luabind::scope lua_register_bot() {
.def("SetSpellDurationRaid", (void(Lua_Bot::*)(int,int,int))&Lua_Bot::SetSpellDurationRaid) .def("SetSpellDurationRaid", (void(Lua_Bot::*)(int,int,int))&Lua_Bot::SetSpellDurationRaid)
.def("SetSpellDurationRaid", (void(Lua_Bot::*)(int,int,int,bool))&Lua_Bot::SetSpellDurationRaid) .def("SetSpellDurationRaid", (void(Lua_Bot::*)(int,int,int,bool))&Lua_Bot::SetSpellDurationRaid)
.def("SetSpellDurationRaid", (void(Lua_Bot::*)(int,int,int,bool,bool))&Lua_Bot::SetSpellDurationRaid) .def("SetSpellDurationRaid", (void(Lua_Bot::*)(int,int,int,bool,bool))&Lua_Bot::SetSpellDurationRaid)
.def("SetSpellRecastTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::SetSpellRecastTimer)
.def("SetSpellRecastTimer", (void(Lua_Bot::*)(uint16, uint32))&Lua_Bot::SetSpellRecastTimer)
.def("SendPayload", (void(Lua_Bot::*)(int))&Lua_Bot::SendPayload) .def("SendPayload", (void(Lua_Bot::*)(int))&Lua_Bot::SendPayload)
.def("SendPayload", (void(Lua_Bot::*)(int,std::string))&Lua_Bot::SendPayload) .def("SendPayload", (void(Lua_Bot::*)(int,std::string))&Lua_Bot::SendPayload)
.def("Signal", (void(Lua_Bot::*)(int))&Lua_Bot::Signal) .def("Signal", (void(Lua_Bot::*)(int))&Lua_Bot::Signal)

Some files were not shown because too many files have changed in this diff Show More