Compare commits

..

27 Commits

Author SHA1 Message Date
KimLS b894d7ee3a update base character data repo 2024-10-12 12:52:07 -07:00
KimLS eecfce6514 update allocations table base repo 2024-10-12 12:41:38 -07:00
KimLS 2d6950149a Fix for server side everything showing as MR 2024-10-12 12:12:57 -07:00
KimLS 3945a8c0c0 Add titanium support 2024-10-12 12:02:40 -07:00
KimLS f27209a812 Add sof support 2024-10-12 11:27:37 -07:00
KimLS d4982743bf Add sod support 2024-10-12 11:23:59 -07:00
KimLS e2dd8f5f60 Add support to rof 2024-10-12 11:13:24 -07:00
KimLS bfc0cceecc Basics work for rof2 2024-10-12 11:06:36 -07:00
KimLS c9902881b7 Generate repo; create will save resists to db 2024-10-12 10:47:03 -07:00
KimLS 62bb426847 working on loading resists from character create. 2024-10-11 23:33:23 -07:00
Alex King c873fe5a22 [Bug Fix] Fix Mercenary Encounter Crash (#4509) 2024-10-11 23:00:09 -04:00
Fryguy e06b0c4b0c [Bug Fix] Master of Disguise should apply to illusions casted by others. (#4506)
Many era comments outline how Master of Disguise would apply to Project Illusion spells on you:

https://thesafehouse.org/forums/forum/everquest-wing/main-lounge/14249-new-aa-master-of-disguise/page4

https://thesafehouse.org/forums/forum/everquest-wing/training-studios/18143-master-of-disguise-broken

```
Im not a big fan of wolf form, but having a 1200 min NDT is pretty nice  I also agree its great to shrink on a raid once and not have to worry about it. 7 aa is a little steep imho, but with a name change and some frog potions, I may reapply to my guild as the servers only froggy rogue /cackle.
```

```
share form of the great wolf gave a 1500min timer.
```
2024-10-11 13:39:36 -04:00
catapultam-habeo ed2130f649 [Bug Fix] Correctly limit max targets of PBAOE (#4507)
* fix pbaoe max targets incorrectly set

* fix scratch copy
2024-10-11 13:15:19 -04:00
Alex King 448a33a60c [Quest API] Add Scripting Support to Mercenaries (#4500)
* [Quest API] Add Scripting Support to Mercenaries

* Cleanup

* Cleanup

* Update lua_merc.h

* Update mob.cpp

* XYZH

* Final

* Update attack.cpp

* Update attack.cpp

* Simplify event invocation

* Inline example

* Nullptr init example

* EVENT_TIMER simplify add EventPlayerNpcBotMerc

* EVENT_TIMER_START

* Remove has_start_event

* EVENT_TIMER_START with settimerMS

* EVENT_POPUP_RESPONSE

* Consolidation

* Update attack.cpp

* Push

* Update quest_parser_collection.h

* Comments

* Cleanup per comments

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2024-10-10 21:29:29 -04:00
Fryguy 8f86cb353e [Bug Fix] Spells - Self Only (Yellow) cast when non group member is targeted (#4503)
* [Bug Fix] Spells - Self Only (Yellow) cast when non group member is targeted

When using a Yellow gem invis spell, it should cast on yourself regardless of the targetted entity.

* Update spells.cpp

---------

Co-authored-by: Alex King <89047260+Kinglykrab@users.noreply.github.com>
2024-10-10 21:27:49 -04:00
Alex 178129443f [Loginserver] Login Fatal Error Spamming (#4476)
Co-authored-by: KimLS <KimLS@peqtgc.com>
2024-10-09 02:15:49 -05:00
Alex King a7c3b41afc [Quest API] Add Buff Fade Methods to Perl/Lua (#4501)
* [Quest API] Add Buff Fade Methods to Perl/Lua

* BuffFadeSongs()
2024-10-09 02:12:33 -05:00
Alex King a5a568d548 [Bug Fix] Fix character_exp_modifiers Default Values (#4502) 2024-10-09 02:11:57 -05:00
Alex King e3198edb86 [Quest API] Add EVENT_READ_ITEM to Perl/Lua (#4497)
* [Quest API] Add EVENT_READ_ITEM to Perl/Lua

* Add item_id export

* Add item export.

* Update client.cpp
2024-10-08 18:25:14 -04:00
Alex King 8568cf7d49 [Bug Fix] Fix NPC::CanTalk() Crash (#4499)
* [Bug FIx] Fix NPC::CanTalk() Crash

* Update npc.cpp

* Update mob.cpp

* Update npc.cpp
2024-10-07 00:17:49 -05:00
Alex King 1fb7a860a1 [Bug Fix] Fix #set motd Crash (#4495) 2024-10-05 07:58:22 -05:00
nytmyr 7eaee2649e [Bots] Add "silent" option to ^spawn and mute raid spawn (#4494)
When zoning or forming a raid, bots would spam their spawn message. They will now be muted.

Adds an optional argument "silent" to the ^spawn command. This will bypass ^oo spawnmessage settings and not send a spawn message. Example: ^spawn Warbot silent
2024-10-04 20:20:52 -04:00
Alex King a17f467b98 [Quest API] Add NPC List Filter Methods to Perl/Lua (#4493)
* [Quest API] Add GetNPCsByNPCIDs to Perl/Lua

* Push

* Update entity.cpp

* Separate methods.
2024-10-03 20:28:57 -04:00
Alex King 3359839a9b [Bug Fix] Fix Targeted AOE Max Targets Rule (#4488) 2024-10-02 20:25:35 -05:00
Alex 7e51e629f9 [Loginserver] Larion loginserver support (#4492)
* Add larion version and opcode path

* WIP: getting server to work

* Identify server_id

* Add missing opcode, add opcodes file

---------

Co-authored-by: KimLS <KimLS@peqtgc.com>
2024-10-02 20:20:13 -05:00
Alex King dc6c28a52d [Cleanup] Remove Extra Skill in EQ::skills::GetExtraDamageSkills() (#4486) 2024-10-02 20:07:19 -05:00
Alex King 78aee0780a [Bug Fix] Fix Group ID 0 in Group::SaveGroupLeaderAA() (#4487) 2024-10-02 20:06:56 -05:00
95 changed files with 3317 additions and 1959 deletions
-1
View File
@@ -482,4 +482,3 @@ ENDIF(EQEMU_BUILD_TESTS)
IF(EQEMU_BUILD_CLIENT_FILES) IF(EQEMU_BUILD_CLIENT_FILES)
ADD_SUBDIRECTORY(client_files) ADD_SUBDIRECTORY(client_files)
ENDIF(EQEMU_BUILD_CLIENT_FILES) ENDIF(EQEMU_BUILD_CLIENT_FILES)
+3 -7
View File
@@ -542,6 +542,7 @@ SET(common_headers
eqemu_config.h eqemu_config.h
eqemu_config_elements.h eqemu_config_elements.h
eqemu_logsys.h eqemu_logsys.h
eqemu_logsys_log_aliases.h
eq_limits.h eq_limits.h
eq_packet.h eq_packet.h
eq_stream_ident.h eq_stream_ident.h
@@ -802,13 +803,8 @@ IF (UNIX)
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 (EQEMU_BUILD_PCH) IF (WIN32 AND EQEMU_BUILD_PCH)
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch-emu-common.h) TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch.h)
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch-containers.h)
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch-utilities.h)
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch-types.h)
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch-fmt.h)
# TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/pch-repositories.h)
ENDIF () ENDIF ()
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
+6
View File
@@ -514,6 +514,12 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
c.raid_auto_consent = pp->raidAutoconsent; c.raid_auto_consent = pp->raidAutoconsent;
c.guild_auto_consent = pp->guildAutoconsent; c.guild_auto_consent = pp->guildAutoconsent;
c.RestTimer = pp->RestTimer; c.RestTimer = pp->RestTimer;
c.cold_resist = pp->cold_resist;
c.fire_resist = pp->fire_resist;
c.magic_resist = pp->magic_resist;
c.disease_resist = pp->disease_resist;
c.poison_resist = pp->poison_resist;
c.corruption_resist = pp->corruption_resist;
CharacterDataRepository::ReplaceOne(*this, c); CharacterDataRepository::ReplaceOne(*this, c);
@@ -5746,6 +5746,18 @@ ALTER TABLE `inventory`
ADD COLUMN `guid` BIGINT UNSIGNED NULL DEFAULT '0' AFTER `ornament_hero_model`; ADD COLUMN `guid` BIGINT UNSIGNED NULL DEFAULT '0' AFTER `ornament_hero_model`;
ALTER TABLE `inventory_snapshots` ALTER TABLE `inventory_snapshots`
ADD COLUMN `guid` BIGINT UNSIGNED NULL DEFAULT '0' AFTER `ornament_hero_model`; ADD COLUMN `guid` BIGINT UNSIGNED NULL DEFAULT '0' AFTER `ornament_hero_model`;
)"
},
ManifestEntry{
.version = 9284,
.description = "2024_10_08_character_exp_modifiers_default.sql",
.check = "SHOW CREATE TABLE `character_exp_modifiers`",
.condition = "contains",
.match = "`exp_modifier` float NOT NULL,",
.sql = R"(
ALTER TABLE `character_exp_modifiers`
MODIFY COLUMN `aa_modifier` float NOT NULL DEFAULT 1.0 AFTER `instance_version`,
MODIFY COLUMN `exp_modifier` float NOT NULL DEFAULT 1.0 AFTER `aa_modifier`;
)" )"
} }
// -- template; copy/paste this when you need to create a new entry // -- template; copy/paste this when you need to create a new entry
+1
View File
@@ -21,6 +21,7 @@
#include "bodytypes.h" #include "bodytypes.h"
#include "data_verification.h" #include "data_verification.h"
#include "eqemu_logsys.h" #include "eqemu_logsys.h"
#include "eqemu_logsys_log_aliases.h"
#include "rulesys.h" #include "rulesys.h"
int16 EQ::invtype::GetInvTypeSize(int16 inv_type) { int16 EQ::invtype::GetInvTypeSize(int16 inv_type) {
+6
View File
@@ -756,4 +756,10 @@ namespace PCNPCOnlyFlagType {
constexpr int NPC = 2; constexpr int NPC = 2;
} }
namespace BookType {
constexpr uint8 Scroll = 0;
constexpr uint8 Book = 1;
constexpr uint8 ItemInfo = 2;
}
#endif /*COMMON_EMU_CONSTANTS_H*/ #endif /*COMMON_EMU_CONSTANTS_H*/
+1
View File
@@ -534,6 +534,7 @@ N(OP_Stamina),
N(OP_Stun), N(OP_Stun),
N(OP_Surname), N(OP_Surname),
N(OP_SwapSpell), N(OP_SwapSpell),
N(OP_SystemFingerprint),
N(OP_TargetBuffs), N(OP_TargetBuffs),
N(OP_TargetCommand), N(OP_TargetCommand),
N(OP_TargetHoTT), N(OP_TargetHoTT),
+6
View File
@@ -1121,6 +1121,12 @@ struct PlayerProfile_Struct
/*19559*/ uint8 unknown19595[5]; // ***Placeholder (6/29/2005) /*19559*/ uint8 unknown19595[5]; // ***Placeholder (6/29/2005)
/*19564*/ uint32 RestTimer; /*19564*/ uint32 RestTimer;
/*19568*/ uint32 char_id; // Found as part of bazaar revamp (5/15/2024) /*19568*/ uint32 char_id; // Found as part of bazaar revamp (5/15/2024)
/*19572*/ uint32 cold_resist;
/*19576*/ uint32 fire_resist;
/*19580*/ uint32 magic_resist;
/*19584*/ uint32 disease_resist;
/*19588*/ uint32 poison_resist;
/*19592*/ uint32 corruption_resist;
// All player profile packets are translated and this overhead is ignored in out-bound packets // All player profile packets are translated and this overhead is ignored in out-bound packets
PlayerProfile_Struct() : m_player_profile_version(EQ::versions::MobVersion::Unknown) { } PlayerProfile_Struct() : m_player_profile_version(EQ::versions::MobVersion::Unknown) { }
+1 -1
View File
@@ -246,7 +246,7 @@ namespace Logs {
}; };
} }
#include "eqemu_logsys_log_aliases.cpp" #include "eqemu_logsys_log_aliases.h"
class Database; class Database;
@@ -18,8 +18,8 @@
* *
*/ */
#ifndef EQEMU_EQEMU_LOGSYS_LOG_ALIASES_CPP #ifndef EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H
#define EQEMU_EQEMU_LOGSYS_LOG_ALIASES_CPP #define EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H
#define LogAA(message, ...) do {\ #define LogAA(message, ...) do {\
if (LogSys.IsLogEnabled(Logs::General, Logs::AA))\ if (LogSys.IsLogEnabled(Logs::General, Logs::AA))\
@@ -855,4 +855,4 @@
} while (0) } while (0)
#endif //EQEMU_EQEMU_LOGSYS_LOG_ALIASES_CPP #endif //EQEMU_EQEMU_LOGSYS_LOG_ALIASES_H
+6 -6
View File
@@ -2288,13 +2288,13 @@ namespace RoF
outapp->WriteSInt32(345); // Mana Total ? outapp->WriteSInt32(345); // Mana Total ?
// these are needed to fix display bugs // these are needed to fix display bugs
outapp->WriteUInt32(0x19); // base CR outapp->WriteUInt32(emu->cold_resist); // base CR
outapp->WriteUInt32(0x19); // base FR outapp->WriteUInt32(emu->fire_resist); // base FR
outapp->WriteUInt32(0x19); // base MR outapp->WriteUInt32(emu->magic_resist); // base MR
outapp->WriteUInt32(0xf); // base DR outapp->WriteUInt32(emu->disease_resist); // base DR
outapp->WriteUInt32(0xf); // base PR outapp->WriteUInt32(emu->poison_resist); // base PR
outapp->WriteUInt32(0xf); // base PhR? outapp->WriteUInt32(0xf); // base PhR?
outapp->WriteUInt32(0xf); // base Corrup outapp->WriteUInt32(emu->corruption_resist); // base Corrup
outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown
+6 -6
View File
@@ -2806,13 +2806,13 @@ namespace RoF2
outapp->WriteSInt32(345); // Mana Total ? outapp->WriteSInt32(345); // Mana Total ?
// these are needed to fix display bugs // these are needed to fix display bugs
outapp->WriteUInt32(0x19); // base CR outapp->WriteUInt32(emu->cold_resist); // base CR
outapp->WriteUInt32(0x19); // base FR outapp->WriteUInt32(emu->fire_resist); // base FR
outapp->WriteUInt32(0x19); // base MR outapp->WriteUInt32(emu->magic_resist); // base MR
outapp->WriteUInt32(0xf); // base DR outapp->WriteUInt32(emu->disease_resist); // base DR
outapp->WriteUInt32(0xf); // base PR outapp->WriteUInt32(emu->poison_resist); // base PR
outapp->WriteUInt32(0xf); // base PhR? outapp->WriteUInt32(0xf); // base PhR?
outapp->WriteUInt32(0xf); // base Corrup outapp->WriteUInt32(emu->corruption_resist); // base Corrup
outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown
+19 -7
View File
@@ -1669,15 +1669,27 @@ namespace SoD
// OUT(unknown19584[4]); // OUT(unknown19584[4]);
// OUT(unknown19588); // OUT(unknown19588);
const uint8 bytes[] = { const uint8 unknown12864_bytes[] = {
0xa3, 0x02, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0xa3, 0x02, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0x19, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F,
0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; };
memcpy(eq->unknown12864, bytes, sizeof(bytes)); memcpy(eq->unknown12864, unknown12864_bytes, sizeof(unknown12864_bytes));
eq->cold_resist = emu->cold_resist;
eq->fire_resist = emu->fire_resist;
eq->magic_resist = emu->magic_resist;
eq->disease_resist = emu->disease_resist;
eq->poison_resist = emu->poison_resist;
eq->physical_resist = 15;
eq->corruption_resist = emu->corruption_resist;
const uint8 unknown15112_bytes[] = {
0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
memcpy(eq->unknown15112, unknown15112_bytes, sizeof(unknown15112_bytes));
//set the checksum... //set the checksum...
CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4); CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4);
+9 -1
View File
@@ -944,7 +944,15 @@ struct PlayerProfile_Struct
/*14700*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot /*14700*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot
/*15060*/ uint8 unknown12852[8]; /*15060*/ uint8 unknown12852[8];
/*15068*/ uint32 available_slots; /*15068*/ uint32 available_slots;
/*15072*/ uint8 unknown12864[80]; //#### uint8 uint8 unknown12864[76]; in Titanium ####[80] /*15072*/ uint8 unknown12864[12]; //#### uint8 uint8 unknown12864[76]; in Titanium ####[80]
/*15084*/ uint32 cold_resist;
/*15088*/ uint32 fire_resist;
/*15092*/ uint32 magic_resist;
/*15096*/ uint32 disease_resist;
/*15100*/ uint32 poison_resist;
/*15104*/ uint32 physical_resist;
/*15108*/ uint32 corruption_resist;
/*15112*/ uint8 unknown15112[40];
//END SUB-STRUCT used for shrouding. //END SUB-STRUCT used for shrouding.
/*15152*/ char name[64]; // Name of player /*15152*/ char name[64]; // Name of player
/*15216*/ char last_name[32]; // Last name of player /*15216*/ char last_name[32]; // Last name of player
+19 -7
View File
@@ -1339,15 +1339,27 @@ namespace SoF
// OUT(unknown19584[4]); // OUT(unknown19584[4]);
// OUT(unknown19588); // OUT(unknown19588);
const uint8 bytes[] = { const uint8 unknown12864_bytes[] = {
0xa3, 0x02, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0xa3, 0x02, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0x19, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F,
0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; };
memcpy(eq->unknown12864, bytes, sizeof(bytes)); memcpy(eq->unknown12864, unknown12864_bytes, sizeof(unknown12864_bytes));
eq->cold_resist = emu->cold_resist;
eq->fire_resist = emu->fire_resist;
eq->magic_resist = emu->magic_resist;
eq->disease_resist = emu->disease_resist;
eq->poison_resist = emu->poison_resist;
eq->physical_resist = 15;
eq->corruption_resist = emu->corruption_resist;
const uint8 unknown15112_bytes[] = {
0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
memcpy(eq->unknown15112, unknown15112_bytes, sizeof(unknown15112_bytes));
//set the checksum... //set the checksum...
CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4); CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4);
+10 -1
View File
@@ -944,7 +944,16 @@ struct PlayerProfile_Struct //23576 Octets
/*14700*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot /*14700*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot
/*15060*/ uint8 unknown12852[8]; /*15060*/ uint8 unknown12852[8];
/*15068*/ uint32 available_slots; /*15068*/ uint32 available_slots;
/*15072*/ uint8 unknown12864[80]; //#### uint8 uint8 unknown12864[76]; in Titanium ####[80] /*15072*/ uint8 unknown12864[12]; //#### uint8 uint8 unknown12864[76]; in Titanium ####[80]
/*15084*/ uint32 cold_resist;
/*15088*/ uint32 fire_resist;
/*15092*/ uint32 magic_resist;
/*15096*/ uint32 disease_resist;
/*15100*/ uint32 poison_resist;
/*15104*/ uint32 physical_resist;
/*15108*/ uint32 corruption_resist;
/*15112*/ uint8 unknown15112[40];
//END SUB-STRUCT used for shrouding. //END SUB-STRUCT used for shrouding.
/*15120*/ char name[64]; // Name of player /*15120*/ char name[64]; // Name of player
/*15184*/ char last_name[32]; // Last name of player /*15184*/ char last_name[32]; // Last name of player
+16 -5
View File
@@ -1600,14 +1600,25 @@ namespace Titanium
// OUT(unknown19584[4]); // OUT(unknown19584[4]);
// OUT(unknown19588); // OUT(unknown19588);
const uint8 unknown12864_bytes[] = {
0x78, 0x03, 0x00, 0x00, 0x1A, 0x04, 0x00, 0x00, 0x1A, 0x04, 0x00, 0x00
};
const uint8 bytes[] = { memcpy(eq->unknown12864, unknown12864_bytes, sizeof(unknown12864_bytes));
0x78, 0x03, 0x00, 0x00, 0x1A, 0x04, 0x00, 0x00, 0x1A, 0x04, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
0x19, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, eq->cold_resist = emu->cold_resist;
0x0F, 0x00, 0x00, 0x00, 0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F, 0x09, 0x00, 0x00, 0x00, eq->fire_resist = emu->fire_resist;
eq->magic_resist = emu->magic_resist;
eq->disease_resist = emu->disease_resist;
eq->poison_resist = emu->poison_resist;
eq->physical_resist = 15;
const uint8 unknown12900_bytes[] = {
0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F, 0x09, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14
}; };
memcpy(eq->unknown12864, bytes, sizeof(bytes));
memcpy(eq->unknown12900, unknown12900_bytes, sizeof(unknown12900_bytes));
//set the checksum... //set the checksum...
CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4); CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4);
+8 -1
View File
@@ -879,7 +879,14 @@ struct PlayerProfile_Struct
/*12564*/ PotionBelt_Struct potionbelt; // potion belt /*12564*/ PotionBelt_Struct potionbelt; // potion belt
/*12852*/ uint8 unknown12852[8]; /*12852*/ uint8 unknown12852[8];
/*12860*/ uint32 available_slots; /*12860*/ uint32 available_slots;
/*12864*/ uint8 unknown12864[76]; /*12864*/ uint8 unknown12864[12];
/*12876*/ uint32 cold_resist;
/*12880*/ uint32 fire_resist;
/*12884*/ uint32 magic_resist;
/*12888*/ uint32 disease_resist;
/*12892*/ uint32 poison_resist;
/*12896*/ uint32 physical_resist;
/*12900*/ uint8 unknown12900[40];
/*12940*/ char name[64]; // Name of player /*12940*/ char name[64]; // Name of player
/*13004*/ char last_name[32]; // Last name of player /*13004*/ char last_name[32]; // Last name of player
/*13036*/ uint32 guild_id; // guildid /*13036*/ uint32 guild_id; // guildid
-13
View File
@@ -1,13 +0,0 @@
#ifndef EQEMU_CONTAINERS_PCH_H
#define EQEMU_CONTAINERS_PCH_H
// containers
#include <iterator>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <list>
#include <vector>
#endif
-20
View File
@@ -1,20 +0,0 @@
#ifndef EQEMU_EMU_COMMON_PCH_H
#define EQEMU_EMU_COMMON_PCH_H
#include "mysql.h"
// emu
#include "../../common/types.h"
#include "../../common/database.h"
#include "../../common/timer.h"
#include "../../common/strings.h"
#include "../../common/http/httplib.h"
#include "../../common/base_packet.h"
#include "../../common/database.h"
#include "../../common/emu_constants.h"
#include "../../common/servertalk.h"
#include "../../common/global_define.h"
#include "../../common/eqemu_logsys.h"
#include "../../common/linked_list.h"
#endif
-9
View File
@@ -1,9 +0,0 @@
#ifndef EQEMU_FMT_PCH_H
#define EQEMU_FMT_PCH_H
// fmt
#include <fmt/format.h>
#include <fmt/core.h>
#include <cereal/archives/json.hpp>
#endif
-229
View File
@@ -1,229 +0,0 @@
#ifndef EQEMU_REPOSITORIES_PCH_H
#define EQEMU_REPOSITORIES_PCH_H
#include "../../common/repositories/discovered_items_repository.h"
#include "../../common/repositories/lootdrop_repository.h"
#include "../../common/repositories/spells_new_repository.h"
#include "../../common/repositories/aa_rank_effects_repository.h"
#include "../../common/repositories/titles_repository.h"
#include "../../common/repositories/character_bandolier_repository.h"
#include "../../common/repositories/completed_shared_tasks_repository.h"
#include "../../common/repositories/faction_list_mod_repository.h"
#include "../../common/repositories/merc_templates_repository.h"
#include "../../common/repositories/spawngroup_repository.h"
#include "../../common/repositories/character_bind_repository.h"
#include "../../common/repositories/npc_types_tint_repository.h"
#include "../../common/repositories/merc_armorinfo_repository.h"
#include "../../common/repositories/adventure_template_entry_flavor_repository.h"
#include "../../common/repositories/character_pet_info_repository.h"
#include "../../common/repositories/raid_details_repository.h"
#include "../../common/repositories/guild_tributes_repository.h"
#include "../../common/repositories/tasksets_repository.h"
#include "../../common/repositories/character_inspect_messages_repository.h"
#include "../../common/repositories/merc_spell_list_entries_repository.h"
#include "../../common/repositories/npc_types_repository.h"
#include "../../common/repositories/bot_buffs_repository.h"
#include "../../common/repositories/shared_task_activity_state_repository.h"
#include "../../common/repositories/forage_repository.h"
#include "../../common/repositories/global_loot_repository.h"
#include "../../common/repositories/adventure_members_repository.h"
#include "../../common/repositories/merc_subtypes_repository.h"
#include "../../common/repositories/aa_ranks_repository.h"
#include "../../common/repositories/character_auras_repository.h"
#include "../../common/repositories/loottable_repository.h"
#include "../../common/repositories/bot_timers_repository.h"
#include "../../common/repositories/graveyard_repository.h"
#include "../../common/repositories/expedition_lockouts_repository.h"
#include "../../common/repositories/bot_group_members_repository.h"
#include "../../common/repositories/spawn_conditions_repository.h"
#include "../../common/repositories/character_disciplines_repository.h"
#include "../../common/repositories/npc_faction_entries_repository.h"
#include "../../common/repositories/pets_equipmentset_entries_repository.h"
#include "../../common/repositories/bot_inspect_messages_repository.h"
#include "../../common/repositories/char_create_combinations_repository.h"
#include "../../common/repositories/guild_ranks_repository.h"
#include "../../common/repositories/character_stats_record_repository.h"
#include "../../common/repositories/adventure_stats_repository.h"
#include "../../common/repositories/buyer_trade_items_repository.h"
#include "../../common/repositories/buyer_buy_lines_repository.h"
#include "../../common/repositories/timers_repository.h"
#include "../../common/repositories/lfguild_repository.h"
#include "../../common/repositories/character_potionbelt_repository.h"
#include "../../common/repositories/ground_spawns_repository.h"
#include "../../common/repositories/npc_spells_effects_repository.h"
#include "../../common/repositories/guild_relations_repository.h"
#include "../../common/repositories/merc_stats_repository.h"
#include "../../common/repositories/petitions_repository.h"
#include "../../common/repositories/chatchannels_repository.h"
#include "../../common/repositories/character_parcels_repository.h"
#include "../../common/repositories/zone_flags_repository.h"
#include "../../common/repositories/merc_merchant_templates_repository.h"
#include "../../common/repositories/criteria/content_filter_criteria.h"
#include "../../common/repositories/login_server_admins_repository.h"
#include "../../common/repositories/character_pet_inventory_repository.h"
#include "../../common/repositories/merc_name_types_repository.h"
#include "../../common/repositories/character_peqzone_flags_repository.h"
#include "../../common/repositories/spawnentry_repository.h"
#include "../../common/repositories/player_titlesets_repository.h"
#include "../../common/repositories/gm_ips_repository.h"
#include "../../common/repositories/character_spells_repository.h"
#include "../../common/repositories/rule_sets_repository.h"
#include "../../common/repositories/character_alt_currency_repository.h"
#include "../../common/repositories/aa_ability_repository.h"
#include "../../common/repositories/command_subsettings_repository.h"
#include "../../common/repositories/items_repository.h"
#include "../../common/repositories/login_api_tokens_repository.h"
#include "../../common/repositories/bot_stances_repository.h"
#include "../../common/repositories/spell_globals_repository.h"
#include "../../common/repositories/pets_equipmentset_repository.h"
#include "../../common/repositories/starting_items_repository.h"
#include "../../common/repositories/bot_create_combinations_repository.h"
#include "../../common/repositories/inventory_snapshots_repository.h"
#include "../../common/repositories/ldon_trap_templates_repository.h"
#include "../../common/repositories/guild_members_repository.h"
#include "../../common/repositories/expeditions_repository.h"
#include "../../common/repositories/level_exp_mods_repository.h"
#include "../../common/repositories/pets_beastlord_data_repository.h"
#include "../../common/repositories/merc_stance_entries_repository.h"
#include "../../common/repositories/doors_repository.h"
#include "../../common/repositories/tool_game_objects_repository.h"
#include "../../common/repositories/npc_spells_entries_repository.h"
#include "../../common/repositories/bot_heal_rotation_targets_repository.h"
#include "../../common/repositories/shared_tasks_repository.h"
#include "../../common/repositories/tradeskill_recipe_repository.h"
#include "../../common/repositories/char_create_point_allocations_repository.h"
#include "../../common/repositories/bot_spells_entries_repository.h"
#include "../../common/repositories/raid_members_repository.h"
#include "../../common/repositories/character_languages_repository.h"
#include "../../common/repositories/merchantlist_repository.h"
#include "../../common/repositories/object_repository.h"
#include "../../common/repositories/login_world_servers_repository.h"
#include "../../common/repositories/character_parcels_containers_repository.h"
#include "../../common/repositories/bot_starting_items_repository.h"
#include "../../common/repositories/adventure_template_entry_repository.h"
#include "../../common/repositories/alternate_currency_repository.h"
#include "../../common/repositories/tributes_repository.h"
#include "../../common/repositories/bug_reports_repository.h"
#include "../../common/repositories/account_repository.h"
#include "../../common/repositories/quest_globals_repository.h"
#include "../../common/repositories/merc_types_repository.h"
#include "../../common/repositories/completed_tasks_repository.h"
#include "../../common/repositories/object_contents_repository.h"
#include "../../common/repositories/dynamic_zone_members_repository.h"
#include "../../common/repositories/aa_rank_prereqs_repository.h"
#include "../../common/repositories/bot_pet_buffs_repository.h"
#include "../../common/repositories/character_activities_repository.h"
#include "../../common/repositories/character_corpse_items_repository.h"
#include "../../common/repositories/spawn2_repository.h"
#include "../../common/repositories/bot_owner_options_repository.h"
#include "../../common/repositories/bot_heal_rotations_repository.h"
#include "../../common/repositories/content_flags_repository.h"
#include "../../common/repositories/ip_exemptions_repository.h"
#include "../../common/repositories/completed_shared_task_members_repository.h"
#include "../../common/repositories/character_material_repository.h"
#include "../../common/repositories/grid_repository.h"
#include "../../common/repositories/db_str_repository.h"
#include "../../common/repositories/character_skills_repository.h"
#include "../../common/repositories/guild_bank_repository.h"
#include "../../common/repositories/reports_repository.h"
#include "../../common/repositories/instance_list_player_repository.h"
#include "../../common/repositories/character_tribute_repository.h"
#include "../../common/repositories/ldon_trap_entries_repository.h"
#include "../../common/repositories/bot_pets_repository.h"
#include "../../common/repositories/merc_buffs_repository.h"
#include "../../common/repositories/skill_caps_repository.h"
#include "../../common/repositories/character_data_repository.h"
#include "../../common/repositories/account_ip_repository.h"
#include "../../common/repositories/traps_repository.h"
#include "../../common/repositories/dynamic_zone_templates_repository.h"
#include "../../common/repositories/mail_repository.h"
#include "../../common/repositories/group_leaders_repository.h"
#include "../../common/repositories/respawn_times_repository.h"
#include "../../common/repositories/task_activities_repository.h"
#include "../../common/repositories/blocked_spells_repository.h"
#include "../../common/repositories/rule_values_repository.h"
#include "../../common/repositories/tradeskill_recipe_entries_repository.h"
#include "../../common/repositories/spawn_events_repository.h"
#include "../../common/repositories/player_event_log_settings_repository.h"
#include "../../common/repositories/completed_shared_task_activity_state_repository.h"
#include "../../common/repositories/inventory_repository.h"
#include "../../common/repositories/perl_event_export_settings_repository.h"
#include "../../common/repositories/zone_points_repository.h"
#include "../../common/repositories/character_memmed_spells_repository.h"
#include "../../common/repositories/spawn_condition_values_repository.h"
#include "../../common/repositories/login_server_list_types_repository.h"
#include "../../common/repositories/npc_emotes_repository.h"
#include "../../common/repositories/veteran_reward_templates_repository.h"
#include "../../common/repositories/merc_weaponinfo_repository.h"
#include "../../common/repositories/data_buckets_repository.h"
#include "../../common/repositories/fishing_repository.h"
#include "../../common/repositories/books_repository.h"
#include "../../common/repositories/character_alternate_abilities_repository.h"
#include "../../common/repositories/bot_spell_casting_chances_repository.h"
#include "../../common/repositories/login_accounts_repository.h"
#include "../../common/repositories/tribute_levels_repository.h"
#include "../../common/repositories/merchantlist_temp_repository.h"
#include "../../common/repositories/account_rewards_repository.h"
#include "../../common/repositories/lootdrop_entries_repository.h"
#include "../../common/repositories/server_scheduled_events_repository.h"
#include "../../common/repositories/bot_groups_repository.h"
#include "../../common/repositories/shared_task_dynamic_zones_repository.h"
#include "../../common/repositories/zone_repository.h"
#include "../../common/repositories/horses_repository.h"
#include "../../common/repositories/character_pet_buffs_repository.h"
#include "../../common/repositories/dynamic_zones_repository.h"
#include "../../common/repositories/start_zones_repository.h"
#include "../../common/repositories/keyring_repository.h"
#include "../../common/repositories/merc_merchant_template_entries_repository.h"
#include "../../common/repositories/character_item_recast_repository.h"
#include "../../common/repositories/merc_inventory_repository.h"
#include "../../common/repositories/merc_npc_types_repository.h"
#include "../../common/repositories/pets_repository.h"
#include "../../common/repositories/damageshieldtypes_repository.h"
#include "../../common/repositories/char_recipe_list_repository.h"
#include "../../common/repositories/instance_list_repository.h"
#include "../../common/repositories/bot_guild_members_repository.h"
#include "../../common/repositories/character_tasks_repository.h"
#include "../../common/repositories/npc_spells_effects_entries_repository.h"
#include "../../common/repositories/auras_repository.h"
#include "../../common/repositories/character_task_timers_repository.h"
#include "../../common/repositories/merc_spell_lists_repository.h"
#include "../../common/repositories/npc_faction_repository.h"
#include "../../common/repositories/friends_repository.h"
#include "../../common/repositories/bot_spell_settings_repository.h"
#include "../../common/repositories/player_event_logs_repository.h"
#include "../../common/repositories/bot_data_repository.h"
#include "../../common/repositories/character_leadership_abilities_repository.h"
#include "../../common/repositories/grid_entries_repository.h"
#include "../../common/repositories/bot_inventories_repository.h"
#include "../../common/repositories/tasks_repository.h"
#include "../../common/repositories/name_filter_repository.h"
#include "../../common/repositories/character_instance_safereturns_repository.h"
#include "../../common/repositories/faction_association_repository.h"
#include "../../common/repositories/logsys_categories_repository.h"
#include "../../common/repositories/buyer_repository.h"
#include "../../common/repositories/character_currency_repository.h"
#include "../../common/repositories/discord_webhooks_repository.h"
#include "../../common/repositories/guild_permissions_repository.h"
#include "../../common/repositories/chatchannel_reserved_names_repository.h"
#include "../../common/repositories/character_expedition_lockouts_repository.h"
#include "../../common/repositories/loottable_entries_repository.h"
#include "../../common/repositories/bot_pet_inventories_repository.h"
#include "../../common/repositories/npc_spells_repository.h"
#include "../../common/repositories/faction_list_repository.h"
#include "../../common/repositories/group_id_repository.h"
#include "../../common/repositories/character_buffs_repository.h"
#include "../../common/repositories/faction_values_repository.h"
#include "../../common/repositories/variables_repository.h"
#include "../../common/repositories/guilds_repository.h"
#include "../../common/repositories/bot_heal_rotation_members_repository.h"
#include "../../common/repositories/spell_buckets_repository.h"
#include "../../common/repositories/spawn2_disabled_repository.h"
#include "../../common/repositories/saylink_repository.h"
#include "../../common/repositories/trader_repository.h"
#include "../../common/repositories/shared_task_members_repository.h"
#include "../../common/repositories/merc_merchant_entries_repository.h"
#include "../../common/repositories/character_corpses_repository.h"
#include "../../common/repositories/adventure_details_repository.h"
#endif
-11
View File
@@ -1,11 +0,0 @@
#ifndef EQEMU_TYPES_PCH_H
#define EQEMU_TYPES_PCH_H
// types
#include <limits>
#include <string>
#include <cctype>
#include <sstream>
#include <type_traits>
#endif
-20
View File
@@ -1,20 +0,0 @@
#ifndef EQEMU_UTILITIES_PCH_H
#define EQEMU_UTILITIES_PCH_H
// utilities
#include <iostream>
#include <cassert>
#include <cmath>
#include <memory>
#include <functional>
#include <algorithm>
#include <utility>
#include <tuple>
#include <fstream>
#include <chrono>
#include <cstdio>
#include <stdio.h>
#include <mutex>
#include <filesystem>
#endif
+34
View File
@@ -0,0 +1,34 @@
// types
#include <limits>
#include <string>
#include <cctype>
#include <sstream>
// containers
#include <iterator>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <list>
#include <vector>
// utilities
#include <iostream>
#include <cassert>
#include <cmath>
#include <memory>
#include <functional>
#include <algorithm>
#include <utility>
#include <tuple>
#include <fstream>
#include <cstdio>
// fmt
#include <fmt/format.h>
// lua
#include "lua.hpp"
#include <luabind/luabind.hpp>
#include <luabind/object.hpp>
@@ -34,6 +34,12 @@ public:
uint32_t alloc_int; uint32_t alloc_int;
uint32_t alloc_wis; uint32_t alloc_wis;
uint32_t alloc_cha; uint32_t alloc_cha;
uint32_t base_cr;
uint32_t base_fr;
uint32_t base_mr;
uint32_t base_dr;
uint32_t base_pr;
uint32_t base_corrup;
}; };
static std::string PrimaryKey() static std::string PrimaryKey()
@@ -59,6 +65,12 @@ public:
"alloc_int", "alloc_int",
"alloc_wis", "alloc_wis",
"alloc_cha", "alloc_cha",
"base_cr",
"base_fr",
"base_mr",
"base_dr",
"base_pr",
"base_corrup",
}; };
} }
@@ -80,6 +92,12 @@ public:
"alloc_int", "alloc_int",
"alloc_wis", "alloc_wis",
"alloc_cha", "alloc_cha",
"base_cr",
"base_fr",
"base_mr",
"base_dr",
"base_pr",
"base_corrup",
}; };
} }
@@ -135,6 +153,12 @@ public:
e.alloc_int = 0; e.alloc_int = 0;
e.alloc_wis = 0; e.alloc_wis = 0;
e.alloc_cha = 0; e.alloc_cha = 0;
e.base_cr = 0;
e.base_fr = 0;
e.base_mr = 0;
e.base_dr = 0;
e.base_pr = 0;
e.base_corrup = 0;
return e; return e;
} }
@@ -186,6 +210,12 @@ public:
e.alloc_int = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0; e.alloc_int = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
e.alloc_wis = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0; e.alloc_wis = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.alloc_cha = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0; e.alloc_cha = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.base_cr = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
e.base_fr = row[16] ? static_cast<uint32_t>(strtoul(row[16], nullptr, 10)) : 0;
e.base_mr = row[17] ? static_cast<uint32_t>(strtoul(row[17], nullptr, 10)) : 0;
e.base_dr = row[18] ? static_cast<uint32_t>(strtoul(row[18], nullptr, 10)) : 0;
e.base_pr = row[19] ? static_cast<uint32_t>(strtoul(row[19], nullptr, 10)) : 0;
e.base_corrup = row[20] ? static_cast<uint32_t>(strtoul(row[20], nullptr, 10)) : 0;
return e; return e;
} }
@@ -234,6 +264,12 @@ public:
v.push_back(columns[12] + " = " + std::to_string(e.alloc_int)); v.push_back(columns[12] + " = " + std::to_string(e.alloc_int));
v.push_back(columns[13] + " = " + std::to_string(e.alloc_wis)); v.push_back(columns[13] + " = " + std::to_string(e.alloc_wis));
v.push_back(columns[14] + " = " + std::to_string(e.alloc_cha)); v.push_back(columns[14] + " = " + std::to_string(e.alloc_cha));
v.push_back(columns[15] + " = " + std::to_string(e.base_cr));
v.push_back(columns[16] + " = " + std::to_string(e.base_fr));
v.push_back(columns[17] + " = " + std::to_string(e.base_mr));
v.push_back(columns[18] + " = " + std::to_string(e.base_dr));
v.push_back(columns[19] + " = " + std::to_string(e.base_pr));
v.push_back(columns[20] + " = " + std::to_string(e.base_corrup));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -270,6 +306,12 @@ public:
v.push_back(std::to_string(e.alloc_int)); v.push_back(std::to_string(e.alloc_int));
v.push_back(std::to_string(e.alloc_wis)); v.push_back(std::to_string(e.alloc_wis));
v.push_back(std::to_string(e.alloc_cha)); v.push_back(std::to_string(e.alloc_cha));
v.push_back(std::to_string(e.base_cr));
v.push_back(std::to_string(e.base_fr));
v.push_back(std::to_string(e.base_mr));
v.push_back(std::to_string(e.base_dr));
v.push_back(std::to_string(e.base_pr));
v.push_back(std::to_string(e.base_corrup));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -314,6 +356,12 @@ public:
v.push_back(std::to_string(e.alloc_int)); v.push_back(std::to_string(e.alloc_int));
v.push_back(std::to_string(e.alloc_wis)); v.push_back(std::to_string(e.alloc_wis));
v.push_back(std::to_string(e.alloc_cha)); v.push_back(std::to_string(e.alloc_cha));
v.push_back(std::to_string(e.base_cr));
v.push_back(std::to_string(e.base_fr));
v.push_back(std::to_string(e.base_mr));
v.push_back(std::to_string(e.base_dr));
v.push_back(std::to_string(e.base_pr));
v.push_back(std::to_string(e.base_corrup));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
} }
@@ -362,6 +410,12 @@ public:
e.alloc_int = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0; e.alloc_int = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
e.alloc_wis = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0; e.alloc_wis = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.alloc_cha = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0; e.alloc_cha = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.base_cr = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
e.base_fr = row[16] ? static_cast<uint32_t>(strtoul(row[16], nullptr, 10)) : 0;
e.base_mr = row[17] ? static_cast<uint32_t>(strtoul(row[17], nullptr, 10)) : 0;
e.base_dr = row[18] ? static_cast<uint32_t>(strtoul(row[18], nullptr, 10)) : 0;
e.base_pr = row[19] ? static_cast<uint32_t>(strtoul(row[19], nullptr, 10)) : 0;
e.base_corrup = row[20] ? static_cast<uint32_t>(strtoul(row[20], nullptr, 10)) : 0;
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -401,6 +455,12 @@ public:
e.alloc_int = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0; e.alloc_int = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
e.alloc_wis = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0; e.alloc_wis = row[13] ? static_cast<uint32_t>(strtoul(row[13], nullptr, 10)) : 0;
e.alloc_cha = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0; e.alloc_cha = row[14] ? static_cast<uint32_t>(strtoul(row[14], nullptr, 10)) : 0;
e.base_cr = row[15] ? static_cast<uint32_t>(strtoul(row[15], nullptr, 10)) : 0;
e.base_fr = row[16] ? static_cast<uint32_t>(strtoul(row[16], nullptr, 10)) : 0;
e.base_mr = row[17] ? static_cast<uint32_t>(strtoul(row[17], nullptr, 10)) : 0;
e.base_dr = row[18] ? static_cast<uint32_t>(strtoul(row[18], nullptr, 10)) : 0;
e.base_pr = row[19] ? static_cast<uint32_t>(strtoul(row[19], nullptr, 10)) : 0;
e.base_corrup = row[20] ? static_cast<uint32_t>(strtoul(row[20], nullptr, 10)) : 0;
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -490,6 +550,12 @@ public:
v.push_back(std::to_string(e.alloc_int)); v.push_back(std::to_string(e.alloc_int));
v.push_back(std::to_string(e.alloc_wis)); v.push_back(std::to_string(e.alloc_wis));
v.push_back(std::to_string(e.alloc_cha)); v.push_back(std::to_string(e.alloc_cha));
v.push_back(std::to_string(e.base_cr));
v.push_back(std::to_string(e.base_fr));
v.push_back(std::to_string(e.base_mr));
v.push_back(std::to_string(e.base_dr));
v.push_back(std::to_string(e.base_pr));
v.push_back(std::to_string(e.base_corrup));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -527,6 +593,12 @@ public:
v.push_back(std::to_string(e.alloc_int)); v.push_back(std::to_string(e.alloc_int));
v.push_back(std::to_string(e.alloc_wis)); v.push_back(std::to_string(e.alloc_wis));
v.push_back(std::to_string(e.alloc_cha)); v.push_back(std::to_string(e.alloc_cha));
v.push_back(std::to_string(e.base_cr));
v.push_back(std::to_string(e.base_fr));
v.push_back(std::to_string(e.base_mr));
v.push_back(std::to_string(e.base_dr));
v.push_back(std::to_string(e.base_pr));
v.push_back(std::to_string(e.base_corrup));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
} }
@@ -123,6 +123,12 @@ public:
uint32_t aa_points_old; uint32_t aa_points_old;
uint32_t e_last_invsnapshot; uint32_t e_last_invsnapshot;
time_t deleted_at; time_t deleted_at;
uint32_t cold_resist;
uint32_t fire_resist;
uint32_t magic_resist;
uint32_t disease_resist;
uint32_t poison_resist;
uint32_t corruption_resist;
}; };
static std::string PrimaryKey() static std::string PrimaryKey()
@@ -237,6 +243,12 @@ public:
"aa_points_old", "aa_points_old",
"e_last_invsnapshot", "e_last_invsnapshot",
"deleted_at", "deleted_at",
"cold_resist",
"fire_resist",
"magic_resist",
"disease_resist",
"poison_resist",
"corruption_resist",
}; };
} }
@@ -347,6 +359,12 @@ public:
"aa_points_old", "aa_points_old",
"e_last_invsnapshot", "e_last_invsnapshot",
"UNIX_TIMESTAMP(deleted_at)", "UNIX_TIMESTAMP(deleted_at)",
"cold_resist",
"fire_resist",
"magic_resist",
"disease_resist",
"poison_resist",
"corruption_resist",
}; };
} }
@@ -491,6 +509,12 @@ public:
e.aa_points_old = 0; e.aa_points_old = 0;
e.e_last_invsnapshot = 0; e.e_last_invsnapshot = 0;
e.deleted_at = 0; e.deleted_at = 0;
e.cold_resist = 0;
e.fire_resist = 0;
e.magic_resist = 0;
e.disease_resist = 0;
e.poison_resist = 0;
e.corruption_resist = 0;
return e; return e;
} }
@@ -631,6 +655,12 @@ public:
e.aa_points_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0; e.aa_points_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
e.e_last_invsnapshot = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0; e.e_last_invsnapshot = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0;
e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10); e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10);
e.cold_resist = row[104] ? static_cast<uint32_t>(strtoul(row[104], nullptr, 10)) : 0;
e.fire_resist = row[105] ? static_cast<uint32_t>(strtoul(row[105], nullptr, 10)) : 0;
e.magic_resist = row[106] ? static_cast<uint32_t>(strtoul(row[106], nullptr, 10)) : 0;
e.disease_resist = row[107] ? static_cast<uint32_t>(strtoul(row[107], nullptr, 10)) : 0;
e.poison_resist = row[108] ? static_cast<uint32_t>(strtoul(row[108], nullptr, 10)) : 0;
e.corruption_resist = row[109] ? static_cast<uint32_t>(strtoul(row[109], nullptr, 10)) : 0;
return e; return e;
} }
@@ -767,6 +797,12 @@ public:
v.push_back(columns[101] + " = " + std::to_string(e.aa_points_old)); v.push_back(columns[101] + " = " + std::to_string(e.aa_points_old));
v.push_back(columns[102] + " = " + std::to_string(e.e_last_invsnapshot)); v.push_back(columns[102] + " = " + std::to_string(e.e_last_invsnapshot));
v.push_back(columns[103] + " = FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); v.push_back(columns[103] + " = FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")");
v.push_back(columns[104] + " = " + std::to_string(e.cold_resist));
v.push_back(columns[105] + " = " + std::to_string(e.fire_resist));
v.push_back(columns[106] + " = " + std::to_string(e.magic_resist));
v.push_back(columns[107] + " = " + std::to_string(e.disease_resist));
v.push_back(columns[108] + " = " + std::to_string(e.poison_resist));
v.push_back(columns[109] + " = " + std::to_string(e.corruption_resist));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -892,6 +928,12 @@ public:
v.push_back(std::to_string(e.aa_points_old)); v.push_back(std::to_string(e.aa_points_old));
v.push_back(std::to_string(e.e_last_invsnapshot)); v.push_back(std::to_string(e.e_last_invsnapshot));
v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")");
v.push_back(std::to_string(e.cold_resist));
v.push_back(std::to_string(e.fire_resist));
v.push_back(std::to_string(e.magic_resist));
v.push_back(std::to_string(e.disease_resist));
v.push_back(std::to_string(e.poison_resist));
v.push_back(std::to_string(e.corruption_resist));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -1025,6 +1067,12 @@ public:
v.push_back(std::to_string(e.aa_points_old)); v.push_back(std::to_string(e.aa_points_old));
v.push_back(std::to_string(e.e_last_invsnapshot)); v.push_back(std::to_string(e.e_last_invsnapshot));
v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")");
v.push_back(std::to_string(e.cold_resist));
v.push_back(std::to_string(e.fire_resist));
v.push_back(std::to_string(e.magic_resist));
v.push_back(std::to_string(e.disease_resist));
v.push_back(std::to_string(e.poison_resist));
v.push_back(std::to_string(e.corruption_resist));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
} }
@@ -1162,6 +1210,12 @@ public:
e.aa_points_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0; e.aa_points_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
e.e_last_invsnapshot = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0; e.e_last_invsnapshot = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0;
e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10); e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10);
e.cold_resist = row[104] ? static_cast<uint32_t>(strtoul(row[104], nullptr, 10)) : 0;
e.fire_resist = row[105] ? static_cast<uint32_t>(strtoul(row[105], nullptr, 10)) : 0;
e.magic_resist = row[106] ? static_cast<uint32_t>(strtoul(row[106], nullptr, 10)) : 0;
e.disease_resist = row[107] ? static_cast<uint32_t>(strtoul(row[107], nullptr, 10)) : 0;
e.poison_resist = row[108] ? static_cast<uint32_t>(strtoul(row[108], nullptr, 10)) : 0;
e.corruption_resist = row[109] ? static_cast<uint32_t>(strtoul(row[109], nullptr, 10)) : 0;
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -1290,6 +1344,12 @@ public:
e.aa_points_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0; e.aa_points_old = row[101] ? static_cast<uint32_t>(strtoul(row[101], nullptr, 10)) : 0;
e.e_last_invsnapshot = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0; e.e_last_invsnapshot = row[102] ? static_cast<uint32_t>(strtoul(row[102], nullptr, 10)) : 0;
e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10); e.deleted_at = strtoll(row[103] ? row[103] : "-1", nullptr, 10);
e.cold_resist = row[104] ? static_cast<uint32_t>(strtoul(row[104], nullptr, 10)) : 0;
e.fire_resist = row[105] ? static_cast<uint32_t>(strtoul(row[105], nullptr, 10)) : 0;
e.magic_resist = row[106] ? static_cast<uint32_t>(strtoul(row[106], nullptr, 10)) : 0;
e.disease_resist = row[107] ? static_cast<uint32_t>(strtoul(row[107], nullptr, 10)) : 0;
e.poison_resist = row[108] ? static_cast<uint32_t>(strtoul(row[108], nullptr, 10)) : 0;
e.corruption_resist = row[109] ? static_cast<uint32_t>(strtoul(row[109], nullptr, 10)) : 0;
all_entries.push_back(e); all_entries.push_back(e);
} }
@@ -1468,6 +1528,12 @@ public:
v.push_back(std::to_string(e.aa_points_old)); v.push_back(std::to_string(e.aa_points_old));
v.push_back(std::to_string(e.e_last_invsnapshot)); v.push_back(std::to_string(e.e_last_invsnapshot));
v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")");
v.push_back(std::to_string(e.cold_resist));
v.push_back(std::to_string(e.fire_resist));
v.push_back(std::to_string(e.magic_resist));
v.push_back(std::to_string(e.disease_resist));
v.push_back(std::to_string(e.poison_resist));
v.push_back(std::to_string(e.corruption_resist));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@@ -1594,6 +1660,12 @@ public:
v.push_back(std::to_string(e.aa_points_old)); v.push_back(std::to_string(e.aa_points_old));
v.push_back(std::to_string(e.e_last_invsnapshot)); v.push_back(std::to_string(e.e_last_invsnapshot));
v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")"); v.push_back("FROM_UNIXTIME(" + (e.deleted_at > 0 ? std::to_string(e.deleted_at) : "null") + ")");
v.push_back(std::to_string(e.cold_resist));
v.push_back(std::to_string(e.fire_resist));
v.push_back(std::to_string(e.magic_resist));
v.push_back(std::to_string(e.disease_resist));
v.push_back(std::to_string(e.poison_resist));
v.push_back(std::to_string(e.corruption_resist));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
} }
+3 -1
View File
@@ -475,7 +475,6 @@ RULE_BOOL(Spells, OldRainTargets, false, "Use old incorrectly implemented maximu
RULE_REAL(Spells, CallOfTheHeroAggroClearDist, 250.0, "Distance at which CoTH will wipe aggro. To disable and always enable aggro wipe on any distance of CoTH, set to 0.") RULE_REAL(Spells, CallOfTheHeroAggroClearDist, 250.0, "Distance at which CoTH will wipe aggro. To disable and always enable aggro wipe on any distance of CoTH, set to 0.")
RULE_BOOL(Spells, NPCSpellPush, false, "Enable spell push on NPCs") RULE_BOOL(Spells, NPCSpellPush, false, "Enable spell push on NPCs")
RULE_BOOL(Spells, July242002PetResists, true, "Enable Pets using PCs resist change from July 24 2002") RULE_BOOL(Spells, July242002PetResists, true, "Enable Pets using PCs resist change from July 24 2002")
RULE_INT(Spells, AOEMaxTargets, 0, "Max number of targets a Targeted AOE spell can cast on. Set to 0 for no limit.")
RULE_BOOL(Spells, CazicTouchTargetsPetOwner, true, "If True, causes Cazic Touch to swap targets from pet to pet owner if a pet is tanking.") RULE_BOOL(Spells, CazicTouchTargetsPetOwner, true, "If True, causes Cazic Touch to swap targets from pet to pet owner if a pet is tanking.")
RULE_BOOL(Spells, PreventFactionWarOnCharmBreak, false, "Enable spell interupts and dot removal on charm break to prevent faction wars.") RULE_BOOL(Spells, PreventFactionWarOnCharmBreak, false, "Enable spell interupts and dot removal on charm break to prevent faction wars.")
RULE_BOOL(Spells, AllowDoubleInvis, true, "Allows you to cast invisibility spells on a player that is already invisible, live like behavior.") RULE_BOOL(Spells, AllowDoubleInvis, true, "Allows you to cast invisibility spells on a player that is already invisible, live like behavior.")
@@ -515,6 +514,9 @@ RULE_BOOL(Spells, UseClassicSpellFocus, false, "Enabling will tell the server to
RULE_BOOL(Spells, ManaTapsOnAnyClass, false, "Enabling this will allow you to cast mana taps on any class, this will bypass ManaTapsRequireNPCMana rule.") RULE_BOOL(Spells, ManaTapsOnAnyClass, false, "Enabling this will allow you to cast mana taps on any class, this will bypass ManaTapsRequireNPCMana rule.")
RULE_INT(Spells, HealAmountMessageFilterThreshold, 100, "Lifetaps below this threshold will not have a message sent to the client (Heal will still process) 0 to Disable.") RULE_INT(Spells, HealAmountMessageFilterThreshold, 100, "Lifetaps below this threshold will not have a message sent to the client (Heal will still process) 0 to Disable.")
RULE_BOOL(Spells, SnareOverridesSpeedBonuses, false, "Enabling will allow snares to override any speed bonuses the entity may have. Default: False") RULE_BOOL(Spells, SnareOverridesSpeedBonuses, false, "Enabling will allow snares to override any speed bonuses the entity may have. Default: False")
RULE_INT(Spells, TargetedAOEMaxTargets, 4, "Max number of targets a Targeted AOE spell can cast on. Set to 0 for no limit.")
RULE_INT(Spells, PointBlankAOEMaxTargets, 0, "Max number of targets a Point-Blank AOE spell can cast on. Set to 0 for no limit.")
RULE_INT(Spells, DefaultAOEMaxTargets, 4, "Max number of targets that an AOE spell which does not meet other descriptions can cast on. Set to 0 for no limit.")
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Combat) RULE_CATEGORY(Combat)
+17 -18
View File
@@ -47,6 +47,7 @@
#include "repositories/character_corpses_repository.h" #include "repositories/character_corpses_repository.h"
#include "repositories/skill_caps_repository.h" #include "repositories/skill_caps_repository.h"
#include "repositories/inventory_repository.h" #include "repositories/inventory_repository.h"
#include "repositories/books_repository.h"
namespace ItemField namespace ItemField
{ {
@@ -1391,30 +1392,28 @@ const EQ::ItemData* SharedDatabase::IterateItems(uint32* id) const
return nullptr; return nullptr;
} }
std::string SharedDatabase::GetBook(const char *txtfile, int16 *language) Book_Struct SharedDatabase::GetBook(const std::string& text_file)
{ {
char txtfile2[20]; const auto& l = BooksRepository::GetWhere(
std::string txtout; *this,
strcpy(txtfile2, txtfile); fmt::format(
"`name` = '{}'",
Strings::Escape(text_file)
)
);
const std::string query = StringFormat("SELECT txtfile, language FROM books WHERE name = '%s'", txtfile2); Book_Struct b;
auto results = QueryDatabase(query);
if (!results.Success()) { if (l.empty()) {
txtout.assign(" ",1); return b;
return txtout;
} }
if (results.RowCount() == 0) { const auto& e = l.front();
LogError("No book to send, ({})", txtfile);
txtout.assign(" ",1);
return txtout;
}
auto& row = results.begin(); b.language = e.language;
txtout.assign(row[0],strlen(row[0])); b.text = e.txtfile;
*language = static_cast<int16>(Strings::ToInt(row[1]));
return txtout; return b;
} }
// Create appropriate EQ::ItemInstance class // Create appropriate EQ::ItemInstance class
+8 -3
View File
@@ -41,8 +41,7 @@ struct NPCFactionList;
struct FactionAssociations; struct FactionAssociations;
namespace EQ namespace EQ {
{
struct ItemData; struct ItemData;
class ItemInstance; class ItemInstance;
@@ -50,6 +49,12 @@ namespace EQ
class MemoryMappedFile; class MemoryMappedFile;
} }
struct Book_Struct
{
uint8 language;
std::string text;
};
/* /*
This object is inherited by world and zone's DB object, This object is inherited by world and zone's DB object,
and is mainly here to facilitate shared memory, and other and is mainly here to facilitate shared memory, and other
@@ -114,7 +119,7 @@ public:
int admin int admin
); );
std::string GetBook(const char *txtfile, int16 *language); Book_Struct GetBook(const std::string& text_file);
/** /**
* items * items
-1
View File
@@ -249,7 +249,6 @@ const std::vector<EQ::skills::SkillType>& EQ::skills::GetExtraDamageSkills()
EQ::skills::SkillFlyingKick, EQ::skills::SkillFlyingKick,
EQ::skills::SkillKick, EQ::skills::SkillKick,
EQ::skills::SkillRoundKick, EQ::skills::SkillRoundKick,
EQ::skills::SkillRoundKick,
EQ::skills::SkillTigerClaw, EQ::skills::SkillTigerClaw,
EQ::skills::SkillFrenzy EQ::skills::SkillFrenzy
}; };
+1 -1
View File
@@ -42,7 +42,7 @@
* 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 9283 #define CURRENT_BINARY_DATABASE_VERSION 9284
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9045
#endif #endif
+7
View File
@@ -138,6 +138,13 @@ public:
*/ */
unsigned int GetPlaySequence() const { return m_play_sequence_id; } unsigned int GetPlaySequence() const { return m_play_sequence_id; }
/**
* Gets the client version
*
* @return
*/
LSClientVersion GetClientVersion() const { return m_client_version; }
/** /**
* Gets the connection for this client * Gets the connection for this client
* *
+40
View File
@@ -88,6 +88,46 @@ ClientManager::ClientManager()
clients.push_back(c); clients.push_back(c);
} }
); );
int larion_port = server.config.GetVariableInt("client_configuration", "larion_port", 15900);
EQStreamManagerInterfaceOptions larion_opts(larion_port, false, false);
larion_stream = new EQ::Net::EQStreamManager(larion_opts);
larion_ops = new RegularOpcodeManager;
opcodes_path = fmt::format(
"{}/{}",
path.GetServerPath(),
server.config.GetVariableString(
"client_configuration",
"larion_opcodes",
"login_opcodes.conf"
)
);
if (!larion_ops->LoadOpcodes(opcodes_path.c_str())) {
LogError(
"ClientManager fatal error: couldn't load opcodes for Larion file [{0}]",
server.config.GetVariableString("client_configuration", "larion_opcodes", "login_opcodes.conf")
);
run_server = false;
}
larion_stream->OnNewConnection(
[this](std::shared_ptr<EQ::Net::EQStream> stream) {
LogInfo(
"New Larion client connection from [{0}:{1}]",
long2ip(stream->GetRemoteIP()),
stream->GetRemotePort()
);
stream->SetOpcodeManager(&larion_ops);
Client* c = new Client(stream, cv_larion);
clients.push_back(c);
}
);
} }
ClientManager::~ClientManager() ClientManager::~ClientManager()
+2
View File
@@ -55,6 +55,8 @@ private:
EQ::Net::EQStreamManager *titanium_stream; EQ::Net::EQStreamManager *titanium_stream;
OpcodeManager *sod_ops; OpcodeManager *sod_ops;
EQ::Net::EQStreamManager *sod_stream; EQ::Net::EQStreamManager *sod_stream;
OpcodeManager *larion_ops;
EQ::Net::EQStreamManager* larion_stream;
}; };
#endif #endif
+2 -1
View File
@@ -83,7 +83,8 @@ struct PlayEverquestResponse_Struct {
enum LSClientVersion { enum LSClientVersion {
cv_titanium, cv_titanium,
cv_sod cv_sod,
cv_larion
}; };
enum LSClientStatus { enum LSClientStatus {
@@ -0,0 +1,14 @@
#EQEmu Public Login Server OPCodes
OP_SessionReady=0x0001
OP_Login=0x0002
OP_ServerListRequest=0x0004
OP_PlayEverquestRequest=0x000d
OP_PlayEverquestResponse=0x0022
OP_ChatMessage=0x0017
OP_LoginAccepted=0x0018
OP_ServerListResponse=0x0019
OP_Poll=0x0029
OP_EnterChat=0x000f
OP_PollResponse=0x0011
OP_SystemFingerprint=0x0016
OP_ExpansionList=0x0030
+1 -1
View File
@@ -137,7 +137,7 @@ std::unique_ptr<EQApplicationPacket> ServerManager::CreateServerListPacket(Clien
use_local_ip ? "Local" : "Remote" use_local_ip ? "Local" : "Remote"
); );
world_server->SerializeForClientServerList(buf, use_local_ip); world_server->SerializeForClientServerList(buf, use_local_ip, client->GetClientVersion());
} }
return std::make_unique<EQApplicationPacket>(OP_ServerListResponse, buf); return std::make_unique<EQApplicationPacket>(OP_ServerListResponse, buf);
+14 -2
View File
@@ -977,7 +977,7 @@ bool WorldServer::ValidateWorldServerAdminLogin(
return false; return false;
} }
void WorldServer::SerializeForClientServerList(SerializeBuffer &out, bool use_local_ip) const void WorldServer::SerializeForClientServerList(SerializeBuffer& out, bool use_local_ip, LSClientVersion version) const
{ {
// see LoginClientServerData_Struct // see LoginClientServerData_Struct
if (use_local_ip) { if (use_local_ip) {
@@ -987,6 +987,10 @@ void WorldServer::SerializeForClientServerList(SerializeBuffer &out, bool use_lo
out.WriteString(GetRemoteIP()); out.WriteString(GetRemoteIP());
} }
if (version == cv_larion) {
out.WriteUInt32(9000);
}
switch (GetServerListID()) { switch (GetServerListID()) {
case LS::ServerType::Legends: case LS::ServerType::Legends:
out.WriteInt32(LS::ServerTypeFlags::Legends); out.WriteInt32(LS::ServerTypeFlags::Legends);
@@ -998,8 +1002,16 @@ void WorldServer::SerializeForClientServerList(SerializeBuffer &out, bool use_lo
out.WriteInt32(LS::ServerTypeFlags::Standard); out.WriteInt32(LS::ServerTypeFlags::Standard);
break; break;
} }
if (version == cv_larion) {
auto server_id = GetServerId();
//if this is 0, the client will not show the server in the list
out.WriteUInt32(1);
out.WriteUInt32(server_id);
}
else {
out.WriteUInt32(GetServerId()); out.WriteUInt32(GetServerId());
}
out.WriteString(GetServerLongName()); out.WriteString(GetServerLongName());
out.WriteString("us"); // country code out.WriteString("us"); // country code
out.WriteString("en"); // language code out.WriteString("en"); // language code
+2 -1
View File
@@ -7,6 +7,7 @@
#include "../common/packet_dump.h" #include "../common/packet_dump.h"
#include "database.h" #include "database.h"
#include "../common/event/timer.h" #include "../common/event/timer.h"
#include "login_types.h"
#include <string> #include <string>
#include <memory> #include <memory>
@@ -149,7 +150,7 @@ public:
bool HandleNewLoginserverRegisteredOnly(Database::DbWorldRegistration &world_registration); bool HandleNewLoginserverRegisteredOnly(Database::DbWorldRegistration &world_registration);
bool HandleNewLoginserverInfoUnregisteredAllowed(Database::DbWorldRegistration &world_registration); bool HandleNewLoginserverInfoUnregisteredAllowed(Database::DbWorldRegistration &world_registration);
void SerializeForClientServerList(class SerializeBuffer& out, bool use_local_ip) const; void SerializeForClientServerList(class SerializeBuffer& out, bool use_local_ip, LSClientVersion version) const;
private: private:
-1
View File
@@ -12,7 +12,6 @@ perl utils/scripts/build/tag-version.pl
mkdir -p build && cd build && \ mkdir -p build && cd build && \
cmake -DEQEMU_BUILD_TESTS=ON \ cmake -DEQEMU_BUILD_TESTS=ON \
-DEQEMU_BUILD_STATIC=ON \ -DEQEMU_BUILD_STATIC=ON \
-DEQEMU_BUILD_PCH=ON \
-DEQEMU_BUILD_LOGIN=ON \ -DEQEMU_BUILD_LOGIN=ON \
-DEQEMU_BUILD_LUA=ON \ -DEQEMU_BUILD_LUA=ON \
-DEQEMU_BUILD_PERL=ON \ -DEQEMU_BUILD_PERL=ON \
+3 -6
View File
@@ -56,6 +56,7 @@ SET(world_headers
login_server.h login_server.h
login_server_list.h login_server_list.h
queryserv.h queryserv.h
race_combos.h
shared_task_manager.h shared_task_manager.h
shared_task_world_messaging.h shared_task_world_messaging.h
sof_char_create_data.h sof_char_create_data.h
@@ -78,12 +79,8 @@ 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 (EQEMU_BUILD_PCH) IF (WIN32 AND EQEMU_BUILD_PCH)
TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/pch-emu-common.h) TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/pch.h)
TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/pch-containers.h)
TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/pch-utilities.h)
TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/pch-types.h)
TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/pch-fmt.h)
ENDIF () ENDIF ()
ADD_DEFINITIONS(-DWORLD) ADD_DEFINITIONS(-DWORLD)
+1 -1
View File
@@ -1,4 +1,4 @@
#include "../../common/eqemu_logsys.h" #include "../../common/eqemu_logsys_log_aliases.h"
#include "../worlddb.h" #include "../worlddb.h"
void WorldserverCLI::CopyCharacter(int argc, char **argv, argh::parser &cmd, std::string &description) void WorldserverCLI::CopyCharacter(int argc, char **argv, argh::parser &cmd, std::string &description)
+312 -227
View File
@@ -47,6 +47,7 @@
#include "clientlist.h" #include "clientlist.h"
#include "wguild_mgr.h" #include "wguild_mgr.h"
#include "sof_char_create_data.h" #include "sof_char_create_data.h"
#include "race_combos.h"
#include "../common/zone_store.h" #include "../common/zone_store.h"
#include "../common/repositories/account_repository.h" #include "../common/repositories/account_repository.h"
#include "../common/repositories/player_event_logs_repository.h" #include "../common/repositories/player_event_logs_repository.h"
@@ -85,8 +86,8 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
std::vector<RaceClassAllocation> character_create_allocations; std::vector<CharCreatePointAllocation> character_create_allocations;
std::vector<RaceClassCombos> character_create_race_class_combos; std::vector<CharCreateCombination> character_create_race_class_combos;
extern ZSList zoneserver_list; extern ZSList zoneserver_list;
extern LoginServerList loginserverlist; extern LoginServerList loginserverlist;
@@ -1642,229 +1643,6 @@ void Client::SendApproveWorld()
safe_delete(outapp); safe_delete(outapp);
} }
bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
{
PlayerProfile_Struct pp;
EQ::InventoryProfile inv;
pp.SetPlayerProfileVersion(EQ::versions::ConvertClientVersionToMobVersion(EQ::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit)));
inv.SetInventoryVersion(EQ::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit));
inv.SetGMInventory(false); // character cannot have gm flag at this point
time_t bday = time(nullptr);
in_addr in;
const uint32 stats_sum = (
cc->AGI +
cc->CHA +
cc->DEX +
cc->INT +
cc->STA +
cc->STR +
cc->WIS
);
in.s_addr = GetIP();
LogInfo(
"Character creation request from [{}] LS [{}] [{}] [{}]",
GetCLE()->LSName(),
GetCLE()->LSID(),
inet_ntoa(in),
GetPort()
);
LogInfo("Name [{}]", name);
LogInfo(
"race [{}] class [{}] gender [{}] deity [{}] start_zone [{}] tutorial [{}]",
cc->race,
cc->class_,
cc->gender,
cc->deity,
cc->start_zone,
cc->tutorial ? "true" : "false"
);
LogInfo(
"AGI [{}] CHA [{}] DEX [{}] INT [{}] STA [{}] STR [{}] WIS [{}] Total [{}]",
cc->AGI,
cc->CHA,
cc->DEX,
cc->INT,
cc->STA,
cc->STR,
cc->WIS,
stats_sum
);
LogInfo("Face [{}] Eye Colors [{}] [{}]", cc->face, cc->eyecolor1, cc->eyecolor2);
LogInfo("Hair [{}] Hair Color [{}]", cc->hairstyle, cc->haircolor);
LogInfo("Beard [{}] Beard Color [{}]", cc->beard, cc->beardcolor);
/* Validate the char creation struct */
if (m_ClientVersionBit & EQ::versions::maskSoFAndLater) {
if (!CheckCharCreateInfoSoF(cc)) {
LogInfo("CheckCharCreateInfo did not validate the request (bad race/class/stats)");
return false;
}
} else {
if (!CheckCharCreateInfoTitanium(cc)) {
LogInfo("CheckCharCreateInfo did not validate the request (bad race/class/stats)");
return false;
}
}
/* Convert incoming cc_s to the new PlayerProfile_Struct */
memset(&pp, 0, sizeof(PlayerProfile_Struct)); // start building the profile
strn0cpy(pp.name, name, sizeof(pp.name));
pp.race = cc->race;
pp.class_ = cc->class_;
pp.gender = cc->gender;
pp.deity = cc->deity;
pp.STR = cc->STR;
pp.STA = cc->STA;
pp.AGI = cc->AGI;
pp.DEX = cc->DEX;
pp.WIS = cc->WIS;
pp.INT = cc->INT;
pp.CHA = cc->CHA;
pp.face = cc->face;
pp.eyecolor1 = cc->eyecolor1;
pp.eyecolor2 = cc->eyecolor2;
pp.hairstyle = cc->hairstyle;
pp.haircolor = cc->haircolor;
pp.beard = cc->beard;
pp.beardcolor = cc->beardcolor;
pp.drakkin_heritage = cc->drakkin_heritage;
pp.drakkin_tattoo = cc->drakkin_tattoo;
pp.drakkin_details = cc->drakkin_details;
pp.birthday = bday;
pp.lastlogin = bday;
pp.level = 1;
pp.points = 5;
pp.cur_hp = 1000;
pp.hunger_level = 6000;
pp.thirst_level = 6000;
/* Set default skills for everybody */
pp.skills[EQ::skills::SkillSwimming] = RuleI(Skills, SwimmingStartValue);
pp.skills[EQ::skills::SkillSenseHeading] = RuleI(Skills, SenseHeadingStartValue);
/* Set Racial and Class specific language and skills */
SetRacialLanguages(&pp);
SetRaceStartingSkills(&pp);
SetClassStartingSkills(&pp);
SetClassLanguages(&pp);
memset(pp.spell_book, std::numeric_limits<uint8>::max(), (sizeof(uint32) * EQ::spells::SPELLBOOK_SIZE));
memset(pp.mem_spells, std::numeric_limits<uint8>::max(), (sizeof(uint32) * EQ::spells::SPELL_GEM_COUNT));
for (auto& b : pp.buffs) {
b.spellid = std::numeric_limits<uint16>::max();
}
/* If server is PVP by default, make all character set to it. */
pp.pvp = database.GetServerType() == 1 ? 1 : 0;
/* If it is an SoF Client and the SoF Start Zone rule is set, send new chars there */
if (m_ClientVersionBit & EQ::versions::maskSoFAndLater) {
LogInfo("Found [SoFStartZoneID] rule setting [{}]", RuleI(World, SoFStartZoneID));
if (RuleI(World, SoFStartZoneID) > 0) {
pp.zone_id = RuleI(World, SoFStartZoneID);
cc->start_zone = pp.zone_id;
}
} else {
LogInfo("Found [TitaniumStartZoneID] rule setting [{}]", RuleI(World, TitaniumStartZoneID));
if (RuleI(World, TitaniumStartZoneID) > 0) { /* if there's a startzone variable put them in there */
pp.zone_id = RuleI(World, TitaniumStartZoneID);
cc->start_zone = pp.zone_id;
}
}
/* use normal starting zone logic to either get defaults, or if startzone was set, load that from the db table.*/
const bool is_valid_start_zone = content_db.GetStartZone(&pp, cc, m_ClientVersionBit & EQ::versions::maskTitaniumAndEarlier);
if (!is_valid_start_zone){
return false;
}
if (!pp.zone_id) {
pp.zone_id = Zones::QEYNOS;
pp.x = pp.y = pp.z = -1;
}
for (uint8 slot_id = 1; slot_id < 5; slot_id++) {
pp.binds[slot_id].zone_id = pp.zone_id;
pp.binds[slot_id].x = pp.x;
pp.binds[slot_id].y = pp.y;
pp.binds[slot_id].z = pp.z;
pp.binds[slot_id].heading = pp.heading;
}
/* Overrides if we have the tutorial flag set! */
if (cc->tutorial && RuleB(World, EnableTutorialButton)) {
pp.zone_id = RuleI(World, TutorialZoneID);
auto z = GetZone(pp.zone_id);
if (z) {
pp.x = z->safe_x;
pp.y = z->safe_y;
pp.z = z->safe_z;
}
}
/* Will either be the same as home or tutorial if enabled. */
if (RuleB(World, StartZoneSameAsBindOnCreation)) {
pp.binds[0].zone_id = pp.zone_id;
pp.binds[0].x = pp.x;
pp.binds[0].y = pp.y;
pp.binds[0].z = pp.z;
pp.binds[0].heading = pp.heading;
}
if (GetZone(pp.zone_id)) {
LogInfo(
"Current location zone_short_name [{}] zone_id [{}] x [{:.2f}] y [{:.2f}] z [{:.2f}] heading [{:.2f}]",
ZoneName(pp.zone_id),
pp.zone_id,
pp.x,
pp.y,
pp.z,
pp.heading
);
}
if (GetZone(pp.binds[0].zone_id)) {
LogInfo(
"Bind location zone_short_name [{}] zone_id [{}] x [{:.2f}] y [{:.2f}] z [{:.2f}] heading [{:.2f}]",
ZoneName(pp.binds[0].zone_id),
pp.binds[0].zone_id,
pp.binds[0].x,
pp.binds[0].y,
pp.binds[0].z,
pp.binds[4].heading
);
}
if (GetZone(pp.binds[4].zone_id)) {
LogInfo(
"Home location zone_short_name [{}] zone_id [{}] x [{:.2f}] y [{:.2f}] z [{:.2f}] heading [{:.2f}]",
ZoneName(pp.binds[4].zone_id),
pp.binds[4].zone_id,
pp.binds[4].x,
pp.binds[4].y,
pp.binds[4].z,
pp.binds[4].heading
);
}
content_db.SetStartingItems(&pp, &inv, pp.race, pp.class_, pp.deity, pp.zone_id, pp.name, GetAdmin());
const bool success = StoreCharacter(GetAccountID(), &pp, &inv);
LogInfo("Character creation {} for [{}]", success ? "succeeded" : "failed", pp.name);
return success;
}
// returns true if the request is ok, false if there's an error // returns true if the request is ok, false if there's an error
bool CheckCharCreateInfoSoF(CharCreate_Struct* cc) bool CheckCharCreateInfoSoF(CharCreate_Struct* cc)
{ {
@@ -1873,7 +1651,7 @@ bool CheckCharCreateInfoSoF(CharCreate_Struct *cc)
LogInfo("Validating char creation info"); LogInfo("Validating char creation info");
RaceClassCombos class_combo; CharCreateCombination class_combo;
bool found = false; bool found = false;
int combos = character_create_race_class_combos.size(); int combos = character_create_race_class_combos.size();
for (int i = 0; i < combos; ++i) { for (int i = 0; i < combos; ++i) {
@@ -1893,7 +1671,7 @@ bool CheckCharCreateInfoSoF(CharCreate_Struct *cc)
} }
uint32 allocs = character_create_allocations.size(); uint32 allocs = character_create_allocations.size();
RaceClassAllocation allocation = {0}; CharCreatePointAllocation allocation = { 0 };
found = false; found = false;
for (int i = 0; i < allocs; ++i) { for (int i = 0; i < allocs; ++i) {
if (character_create_allocations[i].Index == class_combo.AllocationIndex) { if (character_create_allocations[i].Index == class_combo.AllocationIndex) {
@@ -2132,6 +1910,313 @@ bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc)
return Charerrors == 0; return Charerrors == 0;
} }
//TODO: these hard coded values should be settable somewhere somehow.
//Also they're not 100% accurate so if I don't make them settable somehow
//we need to go back and match them to the logic that was ripped out of zone
void GetResistsForCharacterCreate(CharCreate_Struct* cc,
bool sofAndLater,
uint32 &cold_resist,
uint32& fire_resist,
uint32& magic_resist,
uint32& disease_resist,
uint32& poison_resist,
uint32& corruption_resist)
{
if (!sofAndLater) {
cold_resist = 25;
fire_resist = 25;
magic_resist = 25;
disease_resist = 15;
poison_resist = 15;
corruption_resist = 15;
return;
}
CharCreateCombination class_combo;
bool found = false;
int combos = character_create_race_class_combos.size();
for (int i = 0; i < combos; ++i) {
if (character_create_race_class_combos[i].Class == cc->class_ &&
character_create_race_class_combos[i].Race == cc->race &&
character_create_race_class_combos[i].Deity == cc->deity &&
character_create_race_class_combos[i].Zone == cc->start_zone) {
class_combo = character_create_race_class_combos[i];
found = true;
break;
}
}
if (!found) {
cold_resist = 25;
fire_resist = 25;
magic_resist = 25;
disease_resist = 15;
poison_resist = 15;
corruption_resist = 15;
return;
}
CharCreatePointAllocation allocation;
found = false;
combos = character_create_allocations.size();
for (int i = 0; i < combos; ++i) {
if (character_create_allocations[i].Index == class_combo.AllocationIndex) {
allocation = character_create_allocations[i];
found = true;
break;
}
}
if (!found) {
cold_resist = 25;
fire_resist = 25;
magic_resist = 25;
disease_resist = 15;
poison_resist = 15;
corruption_resist = 15;
return;
}
cold_resist = allocation.BaseResists[0];
fire_resist = allocation.BaseResists[1];
magic_resist = allocation.BaseResists[2];
disease_resist = allocation.BaseResists[3];
poison_resist = allocation.BaseResists[4];
corruption_resist = allocation.BaseResists[5];
}
bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
{
PlayerProfile_Struct pp;
EQ::InventoryProfile inv;
pp.SetPlayerProfileVersion(EQ::versions::ConvertClientVersionToMobVersion(EQ::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit)));
inv.SetInventoryVersion(EQ::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit));
inv.SetGMInventory(false); // character cannot have gm flag at this point
time_t bday = time(nullptr);
in_addr in;
const uint32 stats_sum = (
cc->AGI +
cc->CHA +
cc->DEX +
cc->INT +
cc->STA +
cc->STR +
cc->WIS
);
in.s_addr = GetIP();
LogInfo(
"Character creation request from [{}] LS [{}] [{}] [{}]",
GetCLE()->LSName(),
GetCLE()->LSID(),
inet_ntoa(in),
GetPort()
);
LogInfo("Name [{}]", name);
LogInfo(
"race [{}] class [{}] gender [{}] deity [{}] start_zone [{}] tutorial [{}]",
cc->race,
cc->class_,
cc->gender,
cc->deity,
cc->start_zone,
cc->tutorial ? "true" : "false"
);
LogInfo(
"AGI [{}] CHA [{}] DEX [{}] INT [{}] STA [{}] STR [{}] WIS [{}] Total [{}]",
cc->AGI,
cc->CHA,
cc->DEX,
cc->INT,
cc->STA,
cc->STR,
cc->WIS,
stats_sum
);
LogInfo("Face [{}] Eye Colors [{}] [{}]", cc->face, cc->eyecolor1, cc->eyecolor2);
LogInfo("Hair [{}] Hair Color [{}]", cc->hairstyle, cc->haircolor);
LogInfo("Beard [{}] Beard Color [{}]", cc->beard, cc->beardcolor);
/* Validate the char creation struct */
if (m_ClientVersionBit & EQ::versions::maskSoFAndLater) {
if (!CheckCharCreateInfoSoF(cc)) {
LogInfo("CheckCharCreateInfo did not validate the request (bad race/class/stats)");
return false;
}
} else {
if (!CheckCharCreateInfoTitanium(cc)) {
LogInfo("CheckCharCreateInfo did not validate the request (bad race/class/stats)");
return false;
}
}
/* Convert incoming cc_s to the new PlayerProfile_Struct */
memset(&pp, 0, sizeof(PlayerProfile_Struct)); // start building the profile
strn0cpy(pp.name, name, sizeof(pp.name));
pp.race = cc->race;
pp.class_ = cc->class_;
pp.gender = cc->gender;
pp.deity = cc->deity;
pp.STR = cc->STR;
pp.STA = cc->STA;
pp.AGI = cc->AGI;
pp.DEX = cc->DEX;
pp.WIS = cc->WIS;
pp.INT = cc->INT;
pp.CHA = cc->CHA;
pp.face = cc->face;
pp.eyecolor1 = cc->eyecolor1;
pp.eyecolor2 = cc->eyecolor2;
pp.hairstyle = cc->hairstyle;
pp.haircolor = cc->haircolor;
pp.beard = cc->beard;
pp.beardcolor = cc->beardcolor;
pp.drakkin_heritage = cc->drakkin_heritage;
pp.drakkin_tattoo = cc->drakkin_tattoo;
pp.drakkin_details = cc->drakkin_details;
pp.birthday = bday;
pp.lastlogin = bday;
pp.level = 1;
pp.points = 5;
pp.cur_hp = 1000;
pp.hunger_level = 6000;
pp.thirst_level = 6000;
GetResistsForCharacterCreate(cc,
m_ClientVersionBit & EQ::versions::maskSoFAndLater,
pp.cold_resist,
pp.fire_resist,
pp.magic_resist,
pp.disease_resist,
pp.poison_resist,
pp.corruption_resist);
/* Set default skills for everybody */
pp.skills[EQ::skills::SkillSwimming] = RuleI(Skills, SwimmingStartValue);
pp.skills[EQ::skills::SkillSenseHeading] = RuleI(Skills, SenseHeadingStartValue);
/* Set Racial and Class specific language and skills */
SetRacialLanguages(&pp);
SetRaceStartingSkills(&pp);
SetClassStartingSkills(&pp);
SetClassLanguages(&pp);
memset(pp.spell_book, std::numeric_limits<uint8>::max(), (sizeof(uint32) * EQ::spells::SPELLBOOK_SIZE));
memset(pp.mem_spells, std::numeric_limits<uint8>::max(), (sizeof(uint32) * EQ::spells::SPELL_GEM_COUNT));
for (auto& b : pp.buffs) {
b.spellid = std::numeric_limits<uint16>::max();
}
/* If server is PVP by default, make all character set to it. */
pp.pvp = database.GetServerType() == 1 ? 1 : 0;
/* If it is an SoF Client and the SoF Start Zone rule is set, send new chars there */
if (m_ClientVersionBit & EQ::versions::maskSoFAndLater) {
LogInfo("Found [SoFStartZoneID] rule setting [{}]", RuleI(World, SoFStartZoneID));
if (RuleI(World, SoFStartZoneID) > 0) {
pp.zone_id = RuleI(World, SoFStartZoneID);
cc->start_zone = pp.zone_id;
}
} else {
LogInfo("Found [TitaniumStartZoneID] rule setting [{}]", RuleI(World, TitaniumStartZoneID));
if (RuleI(World, TitaniumStartZoneID) > 0) { /* if there's a startzone variable put them in there */
pp.zone_id = RuleI(World, TitaniumStartZoneID);
cc->start_zone = pp.zone_id;
}
}
/* use normal starting zone logic to either get defaults, or if startzone was set, load that from the db table.*/
const bool is_valid_start_zone = content_db.GetStartZone(&pp, cc, m_ClientVersionBit & EQ::versions::maskTitaniumAndEarlier);
if (!is_valid_start_zone){
return false;
}
if (!pp.zone_id) {
pp.zone_id = Zones::QEYNOS;
pp.x = pp.y = pp.z = -1;
}
for (uint8 slot_id = 1; slot_id < 5; slot_id++) {
pp.binds[slot_id].zone_id = pp.zone_id;
pp.binds[slot_id].x = pp.x;
pp.binds[slot_id].y = pp.y;
pp.binds[slot_id].z = pp.z;
pp.binds[slot_id].heading = pp.heading;
}
/* Overrides if we have the tutorial flag set! */
if (cc->tutorial && RuleB(World, EnableTutorialButton)) {
pp.zone_id = RuleI(World, TutorialZoneID);
auto z = GetZone(pp.zone_id);
if (z) {
pp.x = z->safe_x;
pp.y = z->safe_y;
pp.z = z->safe_z;
}
}
/* Will either be the same as home or tutorial if enabled. */
if (RuleB(World, StartZoneSameAsBindOnCreation)) {
pp.binds[0].zone_id = pp.zone_id;
pp.binds[0].x = pp.x;
pp.binds[0].y = pp.y;
pp.binds[0].z = pp.z;
pp.binds[0].heading = pp.heading;
}
if (GetZone(pp.zone_id)) {
LogInfo(
"Current location zone_short_name [{}] zone_id [{}] x [{:.2f}] y [{:.2f}] z [{:.2f}] heading [{:.2f}]",
ZoneName(pp.zone_id),
pp.zone_id,
pp.x,
pp.y,
pp.z,
pp.heading
);
}
if (GetZone(pp.binds[0].zone_id)) {
LogInfo(
"Bind location zone_short_name [{}] zone_id [{}] x [{:.2f}] y [{:.2f}] z [{:.2f}] heading [{:.2f}]",
ZoneName(pp.binds[0].zone_id),
pp.binds[0].zone_id,
pp.binds[0].x,
pp.binds[0].y,
pp.binds[0].z,
pp.binds[4].heading
);
}
if (GetZone(pp.binds[4].zone_id)) {
LogInfo(
"Home location zone_short_name [{}] zone_id [{}] x [{:.2f}] y [{:.2f}] z [{:.2f}] heading [{:.2f}]",
ZoneName(pp.binds[4].zone_id),
pp.binds[4].zone_id,
pp.binds[4].x,
pp.binds[4].y,
pp.binds[4].z,
pp.binds[4].heading
);
}
content_db.SetStartingItems(&pp, &inv, pp.race, pp.class_, pp.deity, pp.zone_id, pp.name, GetAdmin());
const bool success = StoreCharacter(GetAccountID(), &pp, &inv);
LogInfo("Character creation {} for [{}]", success ? "succeeded" : "failed", pp.name);
return success;
}
void Client::SetClassStartingSkills(PlayerProfile_Struct *pp) void Client::SetClassStartingSkills(PlayerProfile_Struct *pp)
{ {
for (uint32 i = 0; i <= EQ::skills::HIGHEST_SKILL; ++i) { for (uint32 i = 0; i <= EQ::skills::HIGHEST_SKILL; ++i) {
-3
View File
@@ -122,7 +122,4 @@ private:
void RecordPossibleHack(const std::string& message); void RecordPossibleHack(const std::string& message);
}; };
bool CheckCharCreateInfoSoF(CharCreate_Struct *cc);
bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc);
#endif #endif
+23 -5
View File
@@ -315,6 +315,13 @@ void LoginServer::ProcessLSFatalError(uint16_t opcode, EQ::Net::Packet &p)
error, error,
reason reason
); );
if (m_legacy_client) {
m_legacy_client.release();
}
else if (m_client) {
m_client.release();
}
} }
void LoginServer::ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p) void LoginServer::ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p)
@@ -598,6 +605,11 @@ bool LoginServer::Connect()
void LoginServer::SendInfo() void LoginServer::SendInfo()
{ {
if (m_client == nullptr && m_legacy_client == nullptr) {
LogDebug("No client to send info to loginserver");
return;
}
const WorldConfig *Config = WorldConfig::get(); const WorldConfig *Config = WorldConfig::get();
auto pack = new ServerPacket; auto pack = new ServerPacket;
@@ -643,6 +655,11 @@ void LoginServer::SendInfo()
void LoginServer::SendStatus() void LoginServer::SendStatus()
{ {
if (m_client == nullptr && m_legacy_client == nullptr) {
LogDebug("No client to send status to loginserver");
return;
}
auto pack = new ServerPacket; auto pack = new ServerPacket;
pack->opcode = ServerOP_LSStatus; pack->opcode = ServerOP_LSStatus;
pack->size = sizeof(ServerLSStatus_Struct); pack->size = sizeof(ServerLSStatus_Struct);
@@ -671,20 +688,21 @@ void LoginServer::SendStatus()
*/ */
void LoginServer::SendPacket(ServerPacket *pack) void LoginServer::SendPacket(ServerPacket *pack)
{ {
if (m_is_legacy) {
if (m_legacy_client) { if (m_legacy_client) {
m_legacy_client->SendPacket(pack); m_legacy_client->SendPacket(pack);
} }
} else if (m_client) {
else {
if (m_client) {
m_client->SendPacket(pack); m_client->SendPacket(pack);
} }
} }
}
void LoginServer::SendAccountUpdate(ServerPacket *pack) void LoginServer::SendAccountUpdate(ServerPacket *pack)
{ {
if (m_client == nullptr && m_legacy_client == nullptr) {
LogDebug("No client to send account update to loginserver");
return;
}
auto *ls_account_update = (ServerLSAccountUpdate_Struct *) pack->pBuffer; auto *ls_account_update = (ServerLSAccountUpdate_Struct *) pack->pBuffer;
if (CanUpdate()) { if (CanUpdate()) {
LogInfo( LogInfo(
+18
View File
@@ -0,0 +1,18 @@
#pragma once
struct CharCreatePointAllocation
{
unsigned int Index;
unsigned int BaseStats[7];
unsigned int DefaultPointAllocation[7];
unsigned int BaseResists[7];
};
struct CharCreateCombination {
unsigned int ExpansionRequired;
unsigned int Race;
unsigned int Class;
unsigned int Deity;
unsigned int AllocationIndex;
unsigned int Zone;
};
+11 -4
View File
@@ -25,14 +25,15 @@
#include <cstdlib> #include <cstdlib>
#include <vector> #include <vector>
#include "sof_char_create_data.h" #include "sof_char_create_data.h"
#include "race_combos.h"
#include "../common/repositories/character_instance_safereturns_repository.h" #include "../common/repositories/character_instance_safereturns_repository.h"
#include "../common/repositories/criteria/content_filter_criteria.h" #include "../common/repositories/criteria/content_filter_criteria.h"
#include "../common/zone_store.h" #include "../common/zone_store.h"
WorldDatabase database; WorldDatabase database;
WorldDatabase content_db; WorldDatabase content_db;
extern std::vector<RaceClassAllocation> character_create_allocations; extern std::vector<CharCreatePointAllocation> character_create_allocations;
extern std::vector<RaceClassCombos> character_create_race_class_combos; extern std::vector<CharCreateCombination> character_create_race_class_combos;
/** /**
@@ -807,7 +808,7 @@ bool WorldDatabase::LoadCharacterCreateAllocations()
return false; return false;
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
RaceClassAllocation allocate; CharCreatePointAllocation allocate;
allocate.Index = Strings::ToInt(row[0]); allocate.Index = Strings::ToInt(row[0]);
allocate.BaseStats[0] = Strings::ToInt(row[1]); allocate.BaseStats[0] = Strings::ToInt(row[1]);
allocate.BaseStats[3] = Strings::ToInt(row[2]); allocate.BaseStats[3] = Strings::ToInt(row[2]);
@@ -823,6 +824,12 @@ bool WorldDatabase::LoadCharacterCreateAllocations()
allocate.DefaultPointAllocation[4] = Strings::ToInt(row[12]); allocate.DefaultPointAllocation[4] = Strings::ToInt(row[12]);
allocate.DefaultPointAllocation[5] = Strings::ToInt(row[13]); allocate.DefaultPointAllocation[5] = Strings::ToInt(row[13]);
allocate.DefaultPointAllocation[6] = Strings::ToInt(row[14]); allocate.DefaultPointAllocation[6] = Strings::ToInt(row[14]);
allocate.BaseResists[0] = Strings::ToInt(row[15]);
allocate.BaseResists[1] = Strings::ToInt(row[16]);
allocate.BaseResists[2] = Strings::ToInt(row[17]);
allocate.BaseResists[3] = Strings::ToInt(row[18]);
allocate.BaseResists[4] = Strings::ToInt(row[19]);
allocate.BaseResists[5] = Strings::ToInt(row[20]);
character_create_allocations.push_back(allocate); character_create_allocations.push_back(allocate);
} }
@@ -840,7 +847,7 @@ bool WorldDatabase::LoadCharacterCreateCombos()
return false; return false;
for (auto row = results.begin(); row != results.end(); ++row) { for (auto row = results.begin(); row != results.end(); ++row) {
RaceClassCombos combo; CharCreateCombination combo;
combo.AllocationIndex = Strings::ToInt(row[0]); combo.AllocationIndex = Strings::ToInt(row[0]);
combo.Race = Strings::ToInt(row[1]); combo.Race = Strings::ToInt(row[1]);
combo.Class = Strings::ToInt(row[2]); combo.Class = Strings::ToInt(row[2]);
+7 -8
View File
@@ -65,6 +65,7 @@ SET(zone_sources
lua_inventory.cpp lua_inventory.cpp
lua_item.cpp lua_item.cpp
lua_iteminst.cpp lua_iteminst.cpp
lua_merc.cpp
lua_mob.cpp lua_mob.cpp
lua_mod.cpp lua_mod.cpp
lua_npc.cpp lua_npc.cpp
@@ -115,6 +116,7 @@ SET(zone_sources
perl_groups.cpp perl_groups.cpp
perl_hateentry.cpp perl_hateentry.cpp
perl_inventory.cpp perl_inventory.cpp
perl_merc.cpp
perl_mob.cpp perl_mob.cpp
perl_npc.cpp perl_npc.cpp
perl_object.cpp perl_object.cpp
@@ -224,6 +226,7 @@ SET(zone_headers
lua_inventory.h lua_inventory.h
lua_item.h lua_item.h
lua_iteminst.h lua_iteminst.h
lua_merc.h
lua_mob.h lua_mob.h
lua_mod.h lua_mod.h
lua_npc.h lua_npc.h
@@ -289,14 +292,10 @@ ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers})
INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
IF (EQEMU_BUILD_PCH) IF (WIN32 AND EQEMU_BUILD_PCH)
TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/pch/pch-emu-common.h) TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/pch/pch.h)
TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/pch/pch-containers.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)
TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/pch/pch-utilities.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 ../common/pch/pch-types.h)
TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/pch/pch-fmt.h)
# TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/pch/pch-repositories.h)
TARGET_PRECOMPILE_HEADERS(zone PRIVATE pch/pch.h)
ENDIF() ENDIF()
ADD_DEFINITIONS(-DZONE) ADD_DEFINITIONS(-DZONE)
+56 -123
View File
@@ -1550,17 +1550,18 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, boo
hit.damage_done = 0; hit.damage_done = 0;
} }
if (IsBot()) { parse->EventBotMerc(
if (parse->BotHasQuestSub(EVENT_USE_SKILL)) { EVENT_USE_SKILL,
const auto& export_string = fmt::format( this,
nullptr,
[&]() {
return fmt::format(
"{} {}", "{} {}",
hit.skill, hit.skill,
GetSkill(hit.skill) GetSkill(hit.skill)
); );
parse->EventBot(EVENT_USE_SKILL, CastToBot(), nullptr, export_string, 0);
}
} }
);
} }
} }
@@ -1922,11 +1923,9 @@ bool Client::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::Skil
} }
if (killer_mob) { if (killer_mob) {
if (killer_mob->IsNPC()) { parse->EventBotMercNPC(EVENT_SLAY, killer_mob, this);
if (parse->HasQuestSub(killer_mob->GetNPCTypeID(), EVENT_SLAY)) {
parse->EventNPC(EVENT_SLAY, killer_mob->CastToNPC(), this, "", 0);
}
if (killer_mob->IsNPC()) {
killed_by = KilledByTypes::Killed_NPC; killed_by = KilledByTypes::Killed_NPC;
auto emote_id = killer_mob->GetEmoteID(); auto emote_id = killer_mob->GetEmoteID();
@@ -1934,12 +1933,6 @@ bool Client::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::Skil
killer_mob->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledPC, emoteid, this); killer_mob->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledPC, emoteid, this);
} }
killer_mob->TrySpellOnKill(killed_level, spell);
} else if (killer_mob->IsBot()) {
if (parse->BotHasQuestSub(EVENT_SLAY)) {
parse->EventBot(EVENT_SLAY, killer_mob->CastToBot(), this, "", 0);
}
killer_mob->TrySpellOnKill(killed_level, spell); killer_mob->TrySpellOnKill(killed_level, spell);
} }
@@ -2458,14 +2451,10 @@ void NPC::Damage(Mob* other, int64 damage, uint16 spell_id, EQ::skills::SkillTyp
spell_id = SPELL_UNKNOWN; spell_id = SPELL_UNKNOWN;
//handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds //handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds
if (attacked_timer.Check()) if (attacked_timer.Check()) {
{ parse->EventMercNPC(EVENT_ATTACK, this, other);
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_ATTACK)) { }
LogCombat("Triggering EVENT_ATTACK due to attack by [{}]", other ? other->GetName() : "nullptr");
parse->EventNPC(EVENT_ATTACK, this, other, "", 0);
}
}
attacked_timer.Start(CombatEventTimer_expire); attacked_timer.Start(CombatEventTimer_expire);
if (!IsEngaged()) if (!IsEngaged())
@@ -2506,42 +2495,23 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
Mob* owner_or_self = killer_mob ? killer_mob->GetOwnerOrSelf() : nullptr; Mob* owner_or_self = killer_mob ? killer_mob->GetOwnerOrSelf() : nullptr;
if (IsNPC()) { auto exports = [&]() {
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH)) { return fmt::format(
const auto& export_string = fmt::format(
"{} {} {} {}", "{} {} {} {}",
killer_mob ? killer_mob->GetID() : 0, killer_mob ? killer_mob->GetID() : 0,
damage, damage,
spell, spell,
static_cast<int>(attack_skill) static_cast<int>(attack_skill)
); );
};
if (parse->EventNPC(EVENT_DEATH, this, owner_or_self, export_string, 0) != 0) { if (parse->EventBotMercNPC(EVENT_DEATH, this, owner_or_self, exports) != 0) {
if (GetHP() < 0) { if (GetHP() < 0) {
SetHP(0); SetHP(0);
} }
return false; return false;
} }
}
} else if (IsBot()) {
if (parse->BotHasQuestSub(EVENT_DEATH)) {
const auto& export_string = fmt::format(
"{} {} {} {}",
killer_mob ? killer_mob->GetID() : 0,
damage,
spell,
static_cast<int>(attack_skill)
);
if (parse->EventBot(EVENT_DEATH, CastToBot(), owner_or_self, export_string, 0) != 0) {
if (GetHP() < 0) {
SetHP(0);
}
return false;
}
}
}
if (killer_mob && killer_mob->IsOfClientBot() && IsValidSpell(spell) && damage > 0) { if (killer_mob && killer_mob->IsOfClientBot() && IsValidSpell(spell) && damage > 0) {
char val1[20] = { 0 }; char val1[20] = { 0 };
@@ -3077,10 +3047,8 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
} }
} }
if (killer_mob && killer_mob->IsBot()) { if (killer_mob) {
if (parse->BotHasQuestSub(EVENT_NPC_SLAY)) { parse->EventBotMerc(EVENT_NPC_SLAY, killer_mob, this);
parse->EventBot(EVENT_NPC_SLAY, killer_mob->CastToBot(), this, "", 0);
}
killer_mob->TrySpellOnKill(killed_level, spell); killer_mob->TrySpellOnKill(killed_level, spell);
} }
@@ -3108,8 +3076,14 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
} }
} }
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) { std::vector<std::any> args = { corpse };
const auto& export_string = fmt::format(
parse->EventMercNPC(
EVENT_DEATH_COMPLETE,
this,
owner_or_self,
[&]() {
return fmt::format(
"{} {} {} {} {} {} {} {} {}", "{} {} {} {} {} {} {} {} {}",
killer_mob ? killer_mob->GetID() : 0, killer_mob ? killer_mob->GetID() : 0,
damage, damage,
@@ -3121,11 +3095,10 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
m_combat_record.GetDamageReceived(), m_combat_record.GetDamageReceived(),
m_combat_record.GetHealingReceived() m_combat_record.GetHealingReceived()
); );
},
std::vector<std::any> args = { corpse }; 0,
&args
parse->EventNPC(EVENT_DEATH_COMPLETE, this, owner_or_self, export_string, 0, &args); );
}
// Zone controller process EVENT_DEATH_ZONE (Death events) // Zone controller process EVENT_DEATH_ZONE (Death events)
if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DEATH_ZONE)) { if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DEATH_ZONE)) {
@@ -4285,55 +4258,20 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
//final damage has been determined. //final damage has been determined.
int old_hp_ratio = (int)GetHPRatio(); int old_hp_ratio = (int)GetHPRatio();
const auto has_bot_given_event = parse->BotHasQuestSub(EVENT_DAMAGE_GIVEN);
const auto has_bot_taken_event = parse->BotHasQuestSub(EVENT_DAMAGE_TAKEN);
const auto has_npc_given_event = (
(
IsNPC() &&
parse->HasQuestSub(CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_GIVEN)
) ||
(
attacker &&
attacker->IsNPC() &&
parse->HasQuestSub(attacker->CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_GIVEN)
)
);
const auto has_npc_taken_event = (
(
IsNPC() &&
parse->HasQuestSub(CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_TAKEN)
) ||
(
attacker &&
attacker->IsNPC() &&
parse->HasQuestSub(attacker->CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_TAKEN)
)
);
const auto has_player_given_event = parse->PlayerHasQuestSub(EVENT_DAMAGE_GIVEN);
const auto has_player_taken_event = parse->PlayerHasQuestSub(EVENT_DAMAGE_TAKEN);
const auto has_given_event = (
has_bot_given_event ||
has_npc_given_event ||
has_player_given_event
);
const auto has_taken_event = (
has_bot_taken_event ||
has_npc_taken_event ||
has_player_taken_event
);
std::vector<std::any> args; std::vector<std::any> args;
int64 damage_override = 0; int64 damage_override = 0;
if (has_given_event && attacker) { if (attacker) {
const auto export_string = fmt::format( args = { this };
parse->EventMob(
EVENT_DAMAGE_GIVEN,
attacker,
this,
[&]() {
return fmt::format(
"{} {} {} {} {} {} {} {} {}", "{} {} {} {} {} {} {} {} {}",
GetID(), GetID(),
damage, damage,
@@ -4345,19 +4283,20 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
iBuffTic ? 1 : 0, iBuffTic ? 1 : 0,
static_cast<int>(special) static_cast<int>(special)
); );
},
if (attacker->IsBot() && has_bot_given_event) { 0,
parse->EventBot(EVENT_DAMAGE_GIVEN, attacker->CastToBot(), this, export_string, 0); &args
} else if (attacker->IsClient() && has_player_given_event) { );
args.push_back(this);
parse->EventPlayer(EVENT_DAMAGE_GIVEN, attacker->CastToClient(), export_string, 0, &args);
} else if (attacker->IsNPC() && has_npc_given_event) {
parse->EventNPC(EVENT_DAMAGE_GIVEN, attacker->CastToNPC(), this, export_string, 0);
}
} }
if (has_taken_event) { args = { attacker };
const auto export_string = fmt::format(
damage_override = parse->EventMob(
EVENT_DAMAGE_TAKEN,
this,
attacker,
[&]() {
return fmt::format(
"{} {} {} {} {} {} {} {} {}", "{} {} {} {} {} {} {} {} {}",
attacker ? attacker->GetID() : 0, attacker ? attacker->GetID() : 0,
damage, damage,
@@ -4369,16 +4308,10 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
iBuffTic ? 1 : 0, iBuffTic ? 1 : 0,
static_cast<int>(special) static_cast<int>(special)
); );
},
if (IsBot() && has_bot_taken_event) { 0,
damage_override = parse->EventBot(EVENT_DAMAGE_TAKEN, CastToBot(), attacker ? attacker : nullptr, export_string, 0); &args
} else if (IsClient() && has_player_taken_event) { );
args.push_back(attacker ? attacker : nullptr);
damage_override = parse->EventPlayer(EVENT_DAMAGE_TAKEN, CastToClient(), export_string, 0, &args);
} else if (IsNPC() && has_npc_taken_event) {
damage_override = parse->EventNPC(EVENT_DAMAGE_TAKEN, CastToNPC(), attacker ? attacker : nullptr, export_string, 0);
}
}
if (damage_override > 0) { if (damage_override > 0) {
damage = damage_override; damage = damage_override;
+11 -3
View File
@@ -857,7 +857,7 @@ void bot_command_spawn(Client *c, const Seperator *sep)
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(
"Usage: {} [bot_name]", "Usage: {} [bot_name] [optional: silent]",
sep->arg[0] sep->arg[0]
).c_str() ).c_str()
); );
@@ -1045,9 +1045,17 @@ void bot_command_spawn(Client *c, const Seperator *sep)
message_index = VALIDATECLASSID(my_bot->GetClass()); message_index = VALIDATECLASSID(my_bot->GetClass());
} }
if (c->GetBotOption(Client::booSpawnMessageSay)) { std::string silent_confirm = sep->arg[2];
bool silentTell = false;
if (!silent_confirm.compare("silent")) {
silentTell = true;
}
if (!silentTell && c->GetBotOption(Client::booSpawnMessageSay)) {
Bot::BotGroupSay(my_bot, bot_spawn_message[message_index].c_str()); Bot::BotGroupSay(my_bot, bot_spawn_message[message_index].c_str());
} else if (c->GetBotOption(Client::booSpawnMessageTell)) { }
else if (!silentTell && c->GetBotOption(Client::booSpawnMessageTell)) {
my_bot->OwnerMessage(bot_spawn_message[message_index]); my_bot->OwnerMessage(bot_spawn_message[message_index]);
} }
} }
+2
View File
@@ -316,6 +316,8 @@ void Client::SpawnRaidBotsOnConnect(Raid* raid) {
if (strcmp(m.member_name, b.bot_name) == 0) { if (strcmp(m.member_name, b.bot_name) == 0) {
std::string buffer = "^spawn "; std::string buffer = "^spawn ";
buffer.append(m.member_name); buffer.append(m.member_name);
std::string silent = " silent";
buffer.append(silent);
bot_command_real_dispatch(this, buffer.c_str()); bot_command_real_dispatch(this, buffer.c_str());
auto bot = entity_list.GetBotByBotName(m.member_name); auto bot = entity_list.GetBotByBotName(m.member_name);
+80 -81
View File
@@ -1243,45 +1243,28 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
entity_list.ProcessProximitySay(message, this, language); entity_list.ProcessProximitySay(message, this, language);
} }
if ( Mob* t = GetTarget();
GetTarget() &&
GetTarget()->IsNPC() &&
!IsInvisible(GetTarget())
) {
auto* t = GetTarget()->CastToNPC();
if (!t->IsEngaged()) {
CheckLDoNHail(t);
CheckEmoteHail(t, message);
if (DistanceNoZ(m_Position, t->GetPosition()) <= RuleI(Range, Say)) { if (
if (parse->HasQuestSub(t->GetNPCTypeID(), EVENT_SAY)) { t &&
parse->EventNPC(EVENT_SAY, t, this, message, language); !IsInvisible(t) &&
DistanceNoZ(m_Position, t->GetPosition()) <= RuleI(Range, Say)
) {
const bool is_engaged = t->IsEngaged();
if (is_engaged) {
parse->EventBotMercNPC(EVENT_AGGRO_SAY, t, this, [&]() { return message; }, language);
} else {
parse->EventBotMercNPC(EVENT_SAY, t, this, [&]() { return message; }, language);
} }
if (t->IsNPC() && !is_engaged) {
CheckLDoNHail(t->CastToNPC());
CheckEmoteHail(t->CastToNPC(), message);
if (RuleB(TaskSystem, EnableTaskSystem)) { if (RuleB(TaskSystem, EnableTaskSystem)) {
if (UpdateTasksOnSpeakWith(t)) { if (UpdateTasksOnSpeakWith(t->CastToNPC())) {
t->DoQuestPause(this); t->CastToNPC()->DoQuestPause(this);
}
}
}
} else {
if (parse->HasQuestSub(t->GetNPCTypeID(), EVENT_AGGRO_SAY)) {
if (DistanceSquaredNoZ(m_Position, t->GetPosition()) <= RuleI(Range, Say)) {
parse->EventNPC(EVENT_AGGRO_SAY, t, this, message, language);
}
}
}
}
else if (GetTarget() && GetTarget()->IsBot() && !IsInvisible(GetTarget())) {
if (DistanceNoZ(m_Position, GetTarget()->GetPosition()) <= RuleI(Range, Say)) {
if (GetTarget()->IsEngaged()) {
if (parse->BotHasQuestSub(EVENT_AGGRO_SAY)) {
parse->EventBot(EVENT_AGGRO_SAY, GetTarget()->CastToBot(), this, message, language);
}
} else {
if (parse->BotHasQuestSub(EVENT_SAY)) {
parse->EventBot(EVENT_SAY, GetTarget()->CastToBot(), this, message, language);
} }
} }
} }
@@ -2299,52 +2282,67 @@ void Client::SetGM(bool toggle) {
UpdateWho(); UpdateWho();
} }
void Client::ReadBook(BookRequest_Struct *book) { void Client::ReadBook(BookRequest_Struct* book)
int16 book_language=0; {
char *txtfile = book->txtfile; const std::string& text_file = book->txtfile;
if(txtfile[0] == '0' && txtfile[1] == '\0') { if (text_file.empty()) {
//invalid book... coming up on non-book items.
return; return;
} }
std::string booktxt2 = content_db.GetBook(txtfile, &book_language); auto b = content_db.GetBook(text_file);
int length = booktxt2.length();
if (booktxt2[0] != '\0') { if (!b.text.empty()) {
#if EQDEBUG >= 6 auto outapp = new EQApplicationPacket(OP_ReadBook, b.text.size() + sizeof(BookText_Struct));
LogInfo("Client::ReadBook() textfile:[{}] Text:[{}]", txtfile, booktxt2.c_str()); auto inst = const_cast<EQ::ItemInstance*>(m_inv[book->invslot]);
#endif
auto outapp = new EQApplicationPacket(OP_ReadBook, length + sizeof(BookText_Struct));
BookText_Struct *out = (BookText_Struct *) outapp->pBuffer; auto t = (BookText_Struct*) outapp->pBuffer;
out->window = book->window;
out->type = book->type;
out->invslot = book->invslot;
out->target_id = book->target_id;
out->can_cast = 0; // todo: implement
out->can_scribe = false;
if (ClientVersion() >= EQ::versions::ClientVersion::SoF && book->invslot <= EQ::invbag::GENERAL_BAGS_END) t->window = book->window;
{ t->type = book->type;
const EQ::ItemInstance* inst = m_inv[book->invslot]; t->invslot = book->invslot;
if (inst && inst->GetItem()) t->target_id = book->target_id;
{ t->can_cast = 0; // todo: implement
auto recipe = TradeskillRecipeRepository::GetWhere(content_db, t->can_scribe = false;
fmt::format("learned_by_item_id = {} LIMIT 1", inst->GetItem()->ID));
out->type = inst->GetItem()->Book; if (ClientVersion() >= EQ::versions::ClientVersion::SoF && book->invslot <= EQ::invbag::GENERAL_BAGS_END) {
out->can_scribe = !recipe.empty(); if (inst && inst->GetItem()) {
auto recipe = TradeskillRecipeRepository::GetWhere(
content_db,
fmt::format(
"learned_by_item_id = {} LIMIT 1",
inst->GetItem()->ID
)
);
t->type = inst->GetItem()->Book;
t->can_scribe = !recipe.empty();
} }
} }
memcpy(out->booktext, booktxt2.c_str(), length); memcpy(t->booktext, b.text.c_str(), b.text.size());
if (EQ::ValueWithin(book_language, Language::CommonTongue, Language::Unknown27)) { if (EQ::ValueWithin(b.language, Language::CommonTongue, Language::Unknown27)) {
if (m_pp.languages[book_language] < Language::MaxValue) { if (m_pp.languages[b.language] < Language::MaxValue) {
GarbleMessage(out->booktext, (Language::MaxValue - m_pp.languages[book_language])); GarbleMessage(t->booktext, (Language::MaxValue - m_pp.languages[b.language]));
} }
} }
// Send only books and scrolls to this event
if (parse->PlayerHasQuestSub(EVENT_READ_ITEM) && t->type != BookType::ItemInfo) {
std::vector<std::any> args = {
b.text,
t->can_cast,
t->can_scribe,
t->invslot,
t->target_id,
t->type,
inst
};
parse->EventPlayer(EVENT_READ_ITEM, this, book->txtfile, inst ? inst->GetID() : 0, &args);
}
QueuePacket(outapp); QueuePacket(outapp);
safe_delete(outapp); safe_delete(outapp);
} }
@@ -10916,23 +10914,24 @@ void Client::SetIPExemption(int exemption_amount)
void Client::ReadBookByName(std::string book_name, uint8 book_type) void Client::ReadBookByName(std::string book_name, uint8 book_type)
{ {
int16 book_language = 0; auto b = content_db.GetBook(book_name);
std::string book_text = content_db.GetBook(book_name.c_str(), &book_language);
int length = book_text.length();
if (book_text[0] != '\0') { if (!b.text.empty()) {
LogDebug("Client::ReadBookByName() Book Name: [{}] Text: [{}]", book_name, book_text.c_str()); LogDebug("Book Name: [{}] Text: [{}]", book_name, b.text);
auto outapp = new EQApplicationPacket(OP_ReadBook, length + sizeof(BookText_Struct));
BookText_Struct *out = (BookText_Struct *) outapp->pBuffer;
out->window = 0xFF;
out->type = book_type;
out->invslot = 0;
memcpy(out->booktext, book_text.c_str(), length); auto outapp = new EQApplicationPacket(OP_ReadBook, b.text.size() + sizeof(BookText_Struct));
if (EQ::ValueWithin(book_language, Language::CommonTongue, Language::Unknown27)) { auto o = (BookText_Struct *) outapp->pBuffer;
if (m_pp.languages[book_language] < Language::MaxValue) {
GarbleMessage(out->booktext, (Language::MaxValue - m_pp.languages[book_language])); o->window = std::numeric_limits<uint8>::max();
o->type = book_type;
o->invslot = 0;
memcpy(o->booktext, b.text.c_str(), b.text.size());
if (EQ::ValueWithin(b.language, Language::CommonTongue, Language::Unknown27)) {
if (m_pp.languages[b.language] < Language::MaxValue) {
GarbleMessage(o->booktext, (Language::MaxValue - m_pp.languages[b.language]));
} }
} }
+2 -1
View File
@@ -196,6 +196,7 @@ struct RespawnOption
float heading; float heading;
}; };
// do not ask what all these mean because I have no idea! // do not ask what all these mean because I have no idea!
// named from the client's CEverQuest::GetInnateDesc, they're missing some // named from the client's CEverQuest::GetInnateDesc, they're missing some
enum eInnateSkill { enum eInnateSkill {
@@ -596,7 +597,7 @@ public:
inline uint8 GetBaseINT() const { return m_pp.INT; } inline uint8 GetBaseINT() const { return m_pp.INT; }
inline uint8 GetBaseAGI() const { return m_pp.AGI; } inline uint8 GetBaseAGI() const { return m_pp.AGI; }
inline uint8 GetBaseWIS() const { return m_pp.WIS; } inline uint8 GetBaseWIS() const { return m_pp.WIS; }
inline uint8 GetBaseCorrup() const { return 15; } // Same for all inline uint8 GetBaseCorrup() const { return m_pp.corruption_resist; }
inline uint8 GetBasePhR() const { return 0; } // Guessing at 0 as base inline uint8 GetBasePhR() const { return 0; } // Guessing at 0 as base
inline virtual int32 GetHeroicSTR() const { return itembonuses.HeroicSTR; } inline virtual int32 GetHeroicSTR() const { return itembonuses.HeroicSTR; }
+5 -295
View File
@@ -1009,65 +1009,7 @@ int Client::CalcHaste()
//in Mob::ResistSpell //in Mob::ResistSpell
int32 Client::CalcMR() int32 Client::CalcMR()
{ {
//racial bases MR = m_pp.magic_resist;
switch (GetBaseRace()) {
case HUMAN:
MR = 25;
break;
case BARBARIAN:
MR = 25;
break;
case ERUDITE:
MR = 30;
break;
case WOOD_ELF:
MR = 25;
break;
case HIGH_ELF:
MR = 25;
break;
case DARK_ELF:
MR = 25;
break;
case HALF_ELF:
MR = 25;
break;
case DWARF:
MR = 30;
break;
case TROLL:
MR = 25;
break;
case OGRE:
MR = 25;
break;
case HALFLING:
MR = 25;
break;
case GNOME:
MR = 25;
break;
case IKSAR:
MR = 25;
break;
case VAHSHIR:
MR = 25;
break;
case FROGLOK:
MR = 30;
break;
case DRAKKIN:
{
MR = 25;
if (GetDrakkinHeritage() == 2)
MR += 10;
else if (GetDrakkinHeritage() == 5)
MR += 2;
break;
}
default:
MR = 20;
}
MR += itembonuses.MR + spellbonuses.MR + aabonuses.MR; MR += itembonuses.MR + spellbonuses.MR + aabonuses.MR;
if (GetClass() == Class::Warrior || GetClass() == Class::Berserker) { if (GetClass() == Class::Warrior || GetClass() == Class::Berserker) {
MR += GetLevel() / 2; MR += GetLevel() / 2;
@@ -1083,65 +1025,7 @@ int32 Client::CalcMR()
int32 Client::CalcFR() int32 Client::CalcFR()
{ {
//racial bases FR = m_pp.fire_resist;
switch (GetBaseRace()) {
case HUMAN:
FR = 25;
break;
case BARBARIAN:
FR = 25;
break;
case ERUDITE:
FR = 25;
break;
case WOOD_ELF:
FR = 25;
break;
case HIGH_ELF:
FR = 25;
break;
case DARK_ELF:
FR = 25;
break;
case HALF_ELF:
FR = 25;
break;
case DWARF:
FR = 25;
break;
case TROLL:
FR = 5;
break;
case OGRE:
FR = 25;
break;
case HALFLING:
FR = 25;
break;
case GNOME:
FR = 25;
break;
case IKSAR:
FR = 30;
break;
case VAHSHIR:
FR = 25;
break;
case FROGLOK:
FR = 25;
break;
case DRAKKIN:
{
FR = 25;
if (GetDrakkinHeritage() == 0)
FR += 10;
else if (GetDrakkinHeritage() == 5)
FR += 2;
break;
}
default:
FR = 20;
}
int c = GetClass(); int c = GetClass();
if (c == Class::Ranger) { if (c == Class::Ranger) {
FR += 4; FR += 4;
@@ -1169,65 +1053,7 @@ int32 Client::CalcFR()
int32 Client::CalcDR() int32 Client::CalcDR()
{ {
//racial bases DR = m_pp.disease_resist;
switch (GetBaseRace()) {
case HUMAN:
DR = 15;
break;
case BARBARIAN:
DR = 15;
break;
case ERUDITE:
DR = 10;
break;
case WOOD_ELF:
DR = 15;
break;
case HIGH_ELF:
DR = 15;
break;
case DARK_ELF:
DR = 15;
break;
case HALF_ELF:
DR = 15;
break;
case DWARF:
DR = 15;
break;
case TROLL:
DR = 15;
break;
case OGRE:
DR = 15;
break;
case HALFLING:
DR = 20;
break;
case GNOME:
DR = 15;
break;
case IKSAR:
DR = 15;
break;
case VAHSHIR:
DR = 15;
break;
case FROGLOK:
DR = 15;
break;
case DRAKKIN:
{
DR = 15;
if (GetDrakkinHeritage() == 1)
DR += 10;
else if (GetDrakkinHeritage() == 5)
DR += 2;
break;
}
default:
DR = 15;
}
int c = GetClass(); int c = GetClass();
// the monk one is part of base resist // the monk one is part of base resist
if (c == Class::Monk) { if (c == Class::Monk) {
@@ -1261,65 +1087,7 @@ int32 Client::CalcDR()
int32 Client::CalcPR() int32 Client::CalcPR()
{ {
//racial bases PR = m_pp.poison_resist;
switch (GetBaseRace()) {
case HUMAN:
PR = 15;
break;
case BARBARIAN:
PR = 15;
break;
case ERUDITE:
PR = 15;
break;
case WOOD_ELF:
PR = 15;
break;
case HIGH_ELF:
PR = 15;
break;
case DARK_ELF:
PR = 15;
break;
case HALF_ELF:
PR = 15;
break;
case DWARF:
PR = 20;
break;
case TROLL:
PR = 15;
break;
case OGRE:
PR = 15;
break;
case HALFLING:
PR = 20;
break;
case GNOME:
PR = 15;
break;
case IKSAR:
PR = 15;
break;
case VAHSHIR:
PR = 15;
break;
case FROGLOK:
PR = 30;
break;
case DRAKKIN:
{
PR = 15;
if (GetDrakkinHeritage() == 3)
PR += 10;
else if (GetDrakkinHeritage() == 5)
PR += 2;
break;
}
default:
PR = 15;
}
int c = GetClass(); int c = GetClass();
// this monk bonus is part of the base // this monk bonus is part of the base
if (c == Class::Monk) { if (c == Class::Monk) {
@@ -1353,65 +1121,7 @@ int32 Client::CalcPR()
int32 Client::CalcCR() int32 Client::CalcCR()
{ {
//racial bases CR = m_pp.cold_resist;
switch (GetBaseRace()) {
case HUMAN:
CR = 25;
break;
case BARBARIAN:
CR = 35;
break;
case ERUDITE:
CR = 25;
break;
case WOOD_ELF:
CR = 25;
break;
case HIGH_ELF:
CR = 25;
break;
case DARK_ELF:
CR = 25;
break;
case HALF_ELF:
CR = 25;
break;
case DWARF:
CR = 25;
break;
case TROLL:
CR = 25;
break;
case OGRE:
CR = 25;
break;
case HALFLING:
CR = 25;
break;
case GNOME:
CR = 25;
break;
case IKSAR:
CR = 15;
break;
case VAHSHIR:
CR = 25;
break;
case FROGLOK:
CR = 25;
break;
case DRAKKIN:
{
CR = 25;
if (GetDrakkinHeritage() == 4)
CR += 10;
else if (GetDrakkinHeritage() == 5)
CR += 2;
break;
}
default:
CR = 25;
}
int c = GetClass(); int c = GetClass();
if (c == Class::Ranger || c == Class::Beastlord) { if (c == Class::Ranger || c == Class::Beastlord) {
CR += 4; CR += 4;
+8 -16
View File
@@ -11984,15 +11984,7 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app)
auto t = GetTarget(); auto t = GetTarget();
if (t) { if (t) {
if (t->IsNPC()) { parse->EventBotMercNPC(EVENT_POPUP_RESPONSE, t, this, [&]() { return std::to_string(popup_response->popupid); });
if (parse->HasQuestSub(t->GetNPCTypeID(), EVENT_POPUP_RESPONSE)) {
parse->EventNPC(EVENT_POPUP_RESPONSE, t->CastToNPC(), this, std::to_string(popup_response->popupid), 0);
}
} else if (t->IsBot()) {
if (parse->BotHasQuestSub(EVENT_POPUP_RESPONSE)) {
parse->EventBot(EVENT_POPUP_RESPONSE, t->CastToBot(), this, std::to_string(popup_response->popupid), 0);
}
}
} }
} }
@@ -13046,14 +13038,14 @@ void Client::Handle_OP_ReadBook(const EQApplicationPacket *app)
LogError("Wrong size: OP_ReadBook, size=[{}], expected [{}]", app->size, sizeof(BookRequest_Struct)); LogError("Wrong size: OP_ReadBook, size=[{}], expected [{}]", app->size, sizeof(BookRequest_Struct));
return; return;
} }
BookRequest_Struct* book = (BookRequest_Struct*)app->pBuffer;
ReadBook(book); auto b = (BookRequest_Struct*) app->pBuffer;
if (ClientVersion() >= EQ::versions::ClientVersion::SoF) ReadBook(b);
{
EQApplicationPacket EndOfBook(OP_FinishWindow, 0); if (ClientVersion() >= EQ::versions::ClientVersion::SoF) {
QueuePacket(&EndOfBook); EQApplicationPacket end_of_book(OP_FinishWindow, 0);
QueuePacket(&end_of_book);
} }
return;
} }
void Client::Handle_OP_RecipeAutoCombine(const EQApplicationPacket *app) void Client::Handle_OP_RecipeAutoCombine(const EQApplicationPacket *app)
+8 -2
View File
@@ -1096,7 +1096,7 @@ void EntityList::AESpell(
max_targets = nullptr; max_targets = nullptr;
} }
int max_targets_allowed = RuleI(Range, AOEMaxTargets); // unlimited int max_targets_allowed = RuleI(Spells, DefaultAOEMaxTargets);;
if (max_targets) { // rains pass this in since they need to preserve the count through waves if (max_targets) { // rains pass this in since they need to preserve the count through waves
max_targets_allowed = *max_targets; max_targets_allowed = *max_targets;
} else if (spells[spell_id].aoe_max_targets) { } else if (spells[spell_id].aoe_max_targets) {
@@ -1108,7 +1108,13 @@ void EntityList::AESpell(
!IsEffectInSpell(spell_id, SE_Lull) && !IsEffectInSpell(spell_id, SE_Lull) &&
!IsEffectInSpell(spell_id, SE_Mez) !IsEffectInSpell(spell_id, SE_Mez)
) { ) {
max_targets_allowed = 4; max_targets_allowed = RuleI(Spells, TargetedAOEMaxTargets);
} else if (
IsPBAENukeSpell(spell_id) &&
IsDetrimentalSpell &&
!is_npc
) {
max_targets_allowed = RuleI(Spells, PointBlankAOEMaxTargets);
} }
int target_hit_counter = 0; int target_hit_counter = 0;
+226 -56
View File
@@ -57,6 +57,7 @@ void perl_register_expedition();
void perl_register_expedition_lock_messages(); void perl_register_expedition_lock_messages();
void perl_register_bot(); void perl_register_bot();
void perl_register_buff(); void perl_register_buff();
void perl_register_merc();
#endif // EMBPERL_XS_CLASSES #endif // EMBPERL_XS_CLASSES
#endif // EMBPERL_XS #endif // EMBPERL_XS
@@ -203,6 +204,7 @@ const char* QuestEventSubroutines[_LargestEventID] = {
"EVENT_ENTITY_VARIABLE_UPDATE", "EVENT_ENTITY_VARIABLE_UPDATE",
"EVENT_AA_LOSS", "EVENT_AA_LOSS",
"EVENT_SPELL_BLOCKED", "EVENT_SPELL_BLOCKED",
"EVENT_READ_ITEM",
// Add new events before these or Lua crashes // Add new events before these or Lua crashes
"EVENT_SPELL_EFFECT_BOT", "EVENT_SPELL_EFFECT_BOT",
@@ -216,6 +218,8 @@ PerlembParser::PerlembParser() : perl(nullptr)
global_player_quest_status_ = questUnloaded; global_player_quest_status_ = questUnloaded;
bot_quest_status_ = questUnloaded; bot_quest_status_ = questUnloaded;
global_bot_quest_status_ = questUnloaded; global_bot_quest_status_ = questUnloaded;
merc_quest_status_ = questUnloaded;
global_merc_quest_status_ = questUnloaded;
} }
PerlembParser::~PerlembParser() PerlembParser::~PerlembParser()
@@ -257,6 +261,8 @@ void PerlembParser::ReloadQuests()
global_player_quest_status_ = questUnloaded; global_player_quest_status_ = questUnloaded;
bot_quest_status_ = questUnloaded; bot_quest_status_ = questUnloaded;
global_bot_quest_status_ = questUnloaded; global_bot_quest_status_ = questUnloaded;
merc_quest_status_ = questUnloaded;
global_merc_quest_status_ = questUnloaded;
item_quest_status_.clear(); item_quest_status_.clear();
spell_quest_status_.clear(); spell_quest_status_.clear();
@@ -284,6 +290,8 @@ int PerlembParser::EventCommon(
bool is_global_npc_quest = false; bool is_global_npc_quest = false;
bool is_bot_quest = false; bool is_bot_quest = false;
bool is_global_bot_quest = false; bool is_global_bot_quest = false;
bool is_merc_quest = false;
bool is_global_merc_quest = false;
bool is_item_quest = false; bool is_item_quest = false;
bool is_spell_quest = false; bool is_spell_quest = false;
@@ -294,6 +302,8 @@ int PerlembParser::EventCommon(
is_global_player_quest, is_global_player_quest,
is_bot_quest, is_bot_quest,
is_global_bot_quest, is_global_bot_quest,
is_merc_quest,
is_global_merc_quest,
is_global_npc_quest, is_global_npc_quest,
is_item_quest, is_item_quest,
is_spell_quest, is_spell_quest,
@@ -309,6 +319,8 @@ int PerlembParser::EventCommon(
is_global_player_quest, is_global_player_quest,
is_bot_quest, is_bot_quest,
is_global_bot_quest, is_global_bot_quest,
is_merc_quest,
is_global_merc_quest,
is_global_npc_quest, is_global_npc_quest,
is_item_quest, is_item_quest,
is_spell_quest, is_spell_quest,
@@ -338,6 +350,8 @@ int PerlembParser::EventCommon(
is_global_player_quest, is_global_player_quest,
is_bot_quest, is_bot_quest,
is_global_bot_quest, is_global_bot_quest,
is_merc_quest,
is_global_merc_quest,
is_global_npc_quest, is_global_npc_quest,
is_item_quest, is_item_quest,
is_spell_quest, is_spell_quest,
@@ -355,6 +369,8 @@ int PerlembParser::EventCommon(
is_global_player_quest, is_global_player_quest,
is_bot_quest, is_bot_quest,
is_global_bot_quest, is_global_bot_quest,
is_merc_quest,
is_global_merc_quest,
is_global_npc_quest, is_global_npc_quest,
is_item_quest, is_item_quest,
is_spell_quest, is_spell_quest,
@@ -381,7 +397,7 @@ int PerlembParser::EventCommon(
if (is_player_quest || is_global_player_quest) { if (is_player_quest || is_global_player_quest) {
return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, mob, mob, nullptr, nullptr); return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, mob, mob, nullptr, nullptr);
} else if (is_bot_quest || is_global_bot_quest) { } else if (is_bot_quest || is_global_bot_quest || is_merc_quest || is_global_merc_quest) {
return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, npc_mob, mob, nullptr, nullptr); return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, npc_mob, mob, nullptr, nullptr);
} else if (is_item_quest) { } else if (is_item_quest) {
return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, mob, mob, inst, nullptr); return SendCommands(package_name.c_str(), QuestEventSubroutines[event_id], 0, mob, mob, inst, nullptr);
@@ -1008,41 +1024,22 @@ int PerlembParser::SendCommands(
#ifdef EMBPERL_XS_CLASSES #ifdef EMBPERL_XS_CLASSES
dTHX; dTHX;
{ {
std::string cl = fmt::format("${}::client", prefix); const std::vector<std::string>& suffixes = {
std::string np = fmt::format("${}::npc", prefix); "bot",
std::string qi = fmt::format("${}::questitem", prefix); "client",
std::string sp = fmt::format("${}::spell", prefix); "entity_list",
std::string enl = fmt::format("${}::entity_list", prefix); "merc",
std::string bot = fmt::format("${}::bot", prefix); "npc",
"questitem",
"spell"
};
if (clear_vars_.find(cl) != clear_vars_.end()) { for (const auto& suffix : suffixes) {
auto e = fmt::format("{} = undef;", cl); const std::string& key = fmt::format("${}::{}", prefix, suffix);
if (clear_vars_.find(suffix) != clear_vars_.end()) {
auto e = fmt::format("{} = undef;", key);
perl->eval(e.c_str()); perl->eval(e.c_str());
} }
if (clear_vars_.find(np) != clear_vars_.end()) {
auto e = fmt::format("{} = undef;", np);
perl->eval(e.c_str());
}
if (clear_vars_.find(qi) != clear_vars_.end()) {
auto e = fmt::format("{} = undef;", qi);
perl->eval(e.c_str());
}
if (clear_vars_.find(sp) != clear_vars_.end()) {
auto e = fmt::format("{} = undef;", sp);
perl->eval(e.c_str());
}
if (clear_vars_.find(enl) != clear_vars_.end()) {
auto e = fmt::format("{} = undef;", enl);
perl->eval(e.c_str());
}
if (clear_vars_.find(bot) != clear_vars_.end()) {
auto e = fmt::format("{} = undef;", bot);
perl->eval(e.c_str());
} }
} }
@@ -1059,19 +1056,21 @@ int PerlembParser::SendCommands(
sv_setsv(client, _empty_sv); sv_setsv(client, _empty_sv);
} }
//only export NPC if it's a npc quest if (other->IsBot()) {
if (!other->IsClient() && other->IsNPC()) {
NPC* n = quest_manager.GetNPC();
buf = fmt::format("{}::npc", prefix);
SV* npc = get_sv(buf.c_str(), true);
sv_setref_pv(npc, "NPC", n);
}
if (!other->IsClient() && other->IsBot()) {
Bot* b = quest_manager.GetBot(); Bot* b = quest_manager.GetBot();
buf = fmt::format("{}::bot", prefix); buf = fmt::format("{}::bot", prefix);
SV* bot = get_sv(buf.c_str(), true); SV* bot = get_sv(buf.c_str(), true);
sv_setref_pv(bot, "Bot", b); sv_setref_pv(bot, "Bot", b);
} else if (other->IsMerc()) {
Merc* m = quest_manager.GetMerc();
buf = fmt::format("{}::merc", prefix);
SV* merc = get_sv(buf.c_str(), true);
sv_setref_pv(merc, "Merc", m);
} else if (other->IsNPC()) {
NPC* n = quest_manager.GetNPC();
buf = fmt::format("{}::npc", prefix);
SV* npc = get_sv(buf.c_str(), true);
sv_setref_pv(npc, "NPC", n);
} }
//only export QuestItem if it's an inst quest //only export QuestItem if it's an inst quest
@@ -1097,23 +1096,25 @@ int PerlembParser::SendCommands(
#endif #endif
//now call the requested sub //now call the requested sub
ret_value = perl->dosub(std::string(prefix).append("::").append(event_id).c_str()); const std::string& sub_key = fmt::format("{}::{}", prefix, event_id);
ret_value = perl->dosub(sub_key.c_str());
#ifdef EMBPERL_XS_CLASSES #ifdef EMBPERL_XS_CLASSES
{ {
std::string cl = fmt::format("${}::client", prefix); const std::vector<std::string>& suffixes = {
std::string np = fmt::format("${}::npc", prefix); "bot",
std::string qi = fmt::format("${}::questitem", prefix); "client",
std::string sp = fmt::format("${}::spell", prefix); "entity_list",
std::string enl = fmt::format("${}::entity_list", prefix); "merc",
std::string bot = fmt::format("${}::bot", prefix); "npc",
"questitem",
"spell"
};
clear_vars_[cl] = 1; for (const auto& suffix : suffixes) {
clear_vars_[np] = 1; const std::string& key = fmt::format("${}::{}", prefix, suffix);
clear_vars_[qi] = 1; clear_vars_[key] = 1;
clear_vars_[sp] = 1; }
clear_vars_[enl] = 1;
clear_vars_[bot] = 1;
} }
#endif #endif
@@ -1183,6 +1184,7 @@ void PerlembParser::MapFunctions()
perl_register_expedition_lock_messages(); perl_register_expedition_lock_messages();
perl_register_bot(); perl_register_bot();
perl_register_buff(); perl_register_buff();
perl_register_merc();
#endif // EMBPERL_XS_CLASSES #endif // EMBPERL_XS_CLASSES
} }
@@ -1191,6 +1193,8 @@ void PerlembParser::GetQuestTypes(
bool& is_global_player_quest, bool& is_global_player_quest,
bool& is_bot_quest, bool& is_bot_quest,
bool& is_global_bot_quest, bool& is_global_bot_quest,
bool& is_merc_quest,
bool& is_global_merc_quest,
bool& is_global_npc_quest, bool& is_global_npc_quest,
bool& is_item_quest, bool& is_item_quest,
bool& is_spell_quest, bool& is_spell_quest,
@@ -1218,10 +1222,14 @@ void PerlembParser::GetQuestTypes(
if (is_global) { if (is_global) {
if (npc_mob->IsBot()) { if (npc_mob->IsBot()) {
is_global_bot_quest = true; is_global_bot_quest = true;
} else if (npc_mob->IsMerc()) {
is_global_merc_quest = true;
} }
} else { } else {
if (npc_mob->IsBot()) { if (npc_mob->IsBot()) {
is_bot_quest = true; is_bot_quest = true;
} else if (npc_mob->IsMerc()) {
is_merc_quest = true;
} }
} }
} else { } else {
@@ -1250,6 +1258,8 @@ void PerlembParser::GetQuestPackageName(
bool& is_global_player_quest, bool& is_global_player_quest,
bool& is_bot_quest, bool& is_bot_quest,
bool& is_global_bot_quest, bool& is_global_bot_quest,
bool& is_merc_quest,
bool& is_global_merc_quest,
bool& is_global_npc_quest, bool& is_global_npc_quest,
bool& is_item_quest, bool& is_item_quest,
bool& is_spell_quest, bool& is_spell_quest,
@@ -1267,6 +1277,8 @@ void PerlembParser::GetQuestPackageName(
!is_global_player_quest && !is_global_player_quest &&
!is_bot_quest && !is_bot_quest &&
!is_global_bot_quest && !is_global_bot_quest &&
!is_merc_quest &&
!is_global_merc_quest &&
!is_item_quest && !is_item_quest &&
!is_spell_quest !is_spell_quest
) { ) {
@@ -1290,6 +1302,10 @@ void PerlembParser::GetQuestPackageName(
package_name = "qst_bot"; package_name = "qst_bot";
} else if (is_global_bot_quest) { } else if (is_global_bot_quest) {
package_name = "qst_global_bot"; package_name = "qst_global_bot";
} else if (is_merc_quest) {
package_name = "qst_merc";
} else if (is_global_merc_quest) {
package_name = "qst_global_merc";
} else { } else {
package_name = fmt::format("qst_spell_{}", object_id); package_name = fmt::format("qst_spell_{}", object_id);
} }
@@ -1315,6 +1331,8 @@ void PerlembParser::ExportQGlobals(
bool is_global_player_quest, bool is_global_player_quest,
bool is_bot_quest, bool is_bot_quest,
bool is_global_bot_quest, bool is_global_bot_quest,
bool is_merc_quest,
bool is_global_merc_quest,
bool is_global_npc_quest, bool is_global_npc_quest,
bool is_item_quest, bool is_item_quest,
bool is_spell_quest, bool is_spell_quest,
@@ -1330,6 +1348,8 @@ void PerlembParser::ExportQGlobals(
!is_global_player_quest && !is_global_player_quest &&
!is_bot_quest && !is_bot_quest &&
!is_global_bot_quest && !is_global_bot_quest &&
!is_merc_quest &&
!is_global_merc_quest &&
!is_item_quest && !is_item_quest &&
!is_spell_quest !is_spell_quest
) { ) {
@@ -1465,6 +1485,8 @@ void PerlembParser::ExportMobVariables(
bool is_global_player_quest, bool is_global_player_quest,
bool is_bot_quest, bool is_bot_quest,
bool is_global_bot_quest, bool is_global_bot_quest,
bool is_merc_quest,
bool is_global_merc_quest,
bool is_global_npc_quest, bool is_global_npc_quest,
bool is_item_quest, bool is_item_quest,
bool is_spell_quest, bool is_spell_quest,
@@ -1490,6 +1512,8 @@ void PerlembParser::ExportMobVariables(
!is_global_player_quest && !is_global_player_quest &&
!is_bot_quest && !is_bot_quest &&
!is_global_bot_quest && !is_global_bot_quest &&
!is_merc_quest &&
!is_global_merc_quest &&
!is_item_quest !is_item_quest
) { ) {
if (mob && mob->IsClient() && npc_mob && npc_mob->IsNPC()) { if (mob && mob->IsClient() && npc_mob && npc_mob->IsNPC()) {
@@ -1520,6 +1544,8 @@ void PerlembParser::ExportMobVariables(
!is_global_player_quest && !is_global_player_quest &&
!is_bot_quest && !is_bot_quest &&
!is_global_bot_quest && !is_global_bot_quest &&
!is_merc_quest &&
!is_global_merc_quest &&
!is_item_quest && !is_item_quest &&
!is_spell_quest !is_spell_quest
) { ) {
@@ -2080,7 +2106,8 @@ void PerlembParser::ExportEventVariables(
"killed_bot_id", "killed_bot_id",
killed->IsBot() ? killed->CastToBot()->GetBotID() : 0 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_merc_id", killed->IsMerc() ? killed->CastToMerc()->GetMercenaryID() : 0);
ExportVar(package_name.c_str(), "killed_npc_id", !killed->IsMerc() && killed->IsNPC() ? killed->GetNPCTypeID() : 0);
} }
} }
break; break;
@@ -2356,6 +2383,7 @@ void PerlembParser::ExportEventVariables(
case EVENT_DESPAWN: { case EVENT_DESPAWN: {
ExportVar(package_name.c_str(), "despawned_entity_id", npc_mob->GetID()); ExportVar(package_name.c_str(), "despawned_entity_id", npc_mob->GetID());
ExportVar(package_name.c_str(), "despawned_bot_id", npc_mob->IsBot() ? npc_mob->CastToBot()->GetBotID() : 0); ExportVar(package_name.c_str(), "despawned_bot_id", npc_mob->IsBot() ? npc_mob->CastToBot()->GetBotID() : 0);
ExportVar(package_name.c_str(), "despawned_merc_id", npc_mob->IsMerc() ? npc_mob->CastToMerc()->GetMercenaryID() : 0);
ExportVar(package_name.c_str(), "despawned_npc_id", npc_mob->IsNPC() ? npc_mob->GetNPCTypeID() : 0); ExportVar(package_name.c_str(), "despawned_npc_id", npc_mob->IsNPC() ? npc_mob->GetNPCTypeID() : 0);
break; break;
} }
@@ -2488,6 +2516,28 @@ void PerlembParser::ExportEventVariables(
break; break;
} }
case EVENT_READ_ITEM: {;
ExportVar(package_name.c_str(), "item_id", extra_data);
ExportVar(package_name.c_str(), "text_file", data);
if (extra_pointers && extra_pointers->size() == 7) {
ExportVar(package_name.c_str(), "book_text", std::any_cast<std::string>(extra_pointers->at(0)).c_str());
ExportVar(package_name.c_str(), "can_cast", std::any_cast<int8>(extra_pointers->at(1)));
ExportVar(package_name.c_str(), "can_scribe", std::any_cast<int8>(extra_pointers->at(2)));
ExportVar(package_name.c_str(), "slot_id", std::any_cast<int16>(extra_pointers->at(3)));
ExportVar(package_name.c_str(), "target_id", std::any_cast<int>(extra_pointers->at(4)));
ExportVar(package_name.c_str(), "type", std::any_cast<uint8>(extra_pointers->at(5)));
ExportVar(
package_name.c_str(),
"item",
"QuestItem",
std::any_cast<EQ::ItemInstance*>(extra_pointers->at(6))
);
}
break;
}
default: { default: {
break; break;
} }
@@ -2614,4 +2664,124 @@ int PerlembParser::EventGlobalBot(
); );
} }
void PerlembParser::LoadMercScript(std::string filename)
{
if (!perl || merc_quest_status_ != questUnloaded) {
return;
}
try {
perl->eval_file("qst_merc", filename.c_str());
} catch (std::string e) {
AddError(
fmt::format(
"Error Compiling Merc Quest File [{}] Error [{}]",
filename,
e
)
);
merc_quest_status_ = questFailedToLoad;
return;
}
merc_quest_status_ = questLoaded;
}
void PerlembParser::LoadGlobalMercScript(std::string filename)
{
if (!perl || global_merc_quest_status_ != questUnloaded) {
return;
}
try {
perl->eval_file("qst_global_merc", filename.c_str());
} catch (std::string e) {
AddError(
fmt::format(
"Error Compiling Global Merc Quest File [{}] Error [{}]",
filename,
e
)
);
global_merc_quest_status_ = questFailedToLoad;
return;
}
global_merc_quest_status_ = questLoaded;
}
bool PerlembParser::MercHasQuestSub(QuestEventID event_id)
{
if (
!perl ||
merc_quest_status_ != questLoaded ||
event_id >= _LargestEventID
) {
return false;
}
return perl->SubExists("qst_merc", QuestEventSubroutines[event_id]);
}
bool PerlembParser::GlobalMercHasQuestSub(QuestEventID event_id)
{
if (
!perl ||
global_merc_quest_status_ != questLoaded ||
event_id >= _LargestEventID
) {
return false;
}
return (perl->SubExists("qst_global_merc", QuestEventSubroutines[event_id]));
}
int PerlembParser::EventMerc(
QuestEventID event_id,
Merc* merc,
Mob* mob,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
)
{
return EventCommon(
event_id,
0,
data.c_str(),
merc,
nullptr,
nullptr,
mob,
extra_data,
false,
extra_pointers
);
}
int PerlembParser::EventGlobalMerc(
QuestEventID event_id,
Merc* merc,
Mob* mob,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
)
{
return EventCommon(
event_id,
0,
data.c_str(),
merc,
nullptr,
nullptr,
mob,
extra_data,
true,
extra_pointers
);
}
#endif #endif
+32
View File
@@ -118,6 +118,24 @@ public:
std::vector<std::any>* extra_pointers std::vector<std::any>* extra_pointers
); );
virtual int EventMerc(
QuestEventID event_id,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
);
virtual int EventGlobalMerc(
QuestEventID event_id,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
);
virtual bool HasQuestSub(uint32 npc_id, QuestEventID event_id); virtual bool HasQuestSub(uint32 npc_id, QuestEventID event_id);
virtual bool HasGlobalQuestSub(QuestEventID event_id); virtual bool HasGlobalQuestSub(QuestEventID event_id);
virtual bool PlayerHasQuestSub(QuestEventID event_id); virtual bool PlayerHasQuestSub(QuestEventID event_id);
@@ -126,6 +144,8 @@ public:
virtual bool ItemHasQuestSub(EQ::ItemInstance* inst, QuestEventID event_id); virtual bool ItemHasQuestSub(EQ::ItemInstance* inst, QuestEventID event_id);
virtual bool BotHasQuestSub(QuestEventID event_id); virtual bool BotHasQuestSub(QuestEventID event_id);
virtual bool GlobalBotHasQuestSub(QuestEventID event_id); virtual bool GlobalBotHasQuestSub(QuestEventID event_id);
virtual bool MercHasQuestSub(QuestEventID event_id);
virtual bool GlobalMercHasQuestSub(QuestEventID event_id);
virtual void LoadNPCScript(std::string filename, int npc_id); virtual void LoadNPCScript(std::string filename, int npc_id);
virtual void LoadGlobalNPCScript(std::string filename); virtual void LoadGlobalNPCScript(std::string filename);
@@ -135,6 +155,8 @@ public:
virtual void LoadSpellScript(std::string filename, uint32 spell_id); virtual void LoadSpellScript(std::string filename, uint32 spell_id);
virtual void LoadBotScript(std::string filename); virtual void LoadBotScript(std::string filename);
virtual void LoadGlobalBotScript(std::string filename); virtual void LoadGlobalBotScript(std::string filename);
virtual void LoadMercScript(std::string filename);
virtual void LoadGlobalMercScript(std::string filename);
virtual void AddVar(std::string name, std::string val); virtual void AddVar(std::string name, std::string val);
virtual std::string GetVar(std::string name); virtual std::string GetVar(std::string name);
@@ -182,6 +204,8 @@ private:
bool& is_global_player_quest, bool& is_global_player_quest,
bool& is_bot_quest, bool& is_bot_quest,
bool& is_global_bot_quest, bool& is_global_bot_quest,
bool& is_merc_quest,
bool& is_global_merc_quest,
bool& is_global_npc_quest, bool& is_global_npc_quest,
bool& is_item_quest, bool& is_item_quest,
bool& is_spell_quest, bool& is_spell_quest,
@@ -197,6 +221,8 @@ private:
bool& is_global_player_quest, bool& is_global_player_quest,
bool& is_bot_quest, bool& is_bot_quest,
bool& is_global_bot_quest, bool& is_global_bot_quest,
bool& is_merc_quest,
bool& is_global_merc_quest,
bool& is_global_npc_quest, bool& is_global_npc_quest,
bool& is_item_quest, bool& is_item_quest,
bool& is_spell_quest, bool& is_spell_quest,
@@ -216,6 +242,8 @@ private:
bool is_global_player_quest, bool is_global_player_quest,
bool is_bot_quest, bool is_bot_quest,
bool is_global_bot_quest, bool is_global_bot_quest,
bool is_merc_quest,
bool is_global_merc_quest,
bool is_global_npc_quest, bool is_global_npc_quest,
bool is_item_quest, bool is_item_quest,
bool is_spell_quest, bool is_spell_quest,
@@ -230,6 +258,8 @@ private:
bool is_global_player_quest, bool is_global_player_quest,
bool is_bot_quest, bool is_bot_quest,
bool is_global_bot_quest, bool is_global_bot_quest,
bool is_merc_quest,
bool is_global_merc_quest,
bool is_global_npc_quest, bool is_global_npc_quest,
bool is_item_quest, bool is_item_quest,
bool is_spell_quest, bool is_spell_quest,
@@ -263,6 +293,8 @@ private:
PerlQuestStatus global_player_quest_status_; PerlQuestStatus global_player_quest_status_;
PerlQuestStatus bot_quest_status_; PerlQuestStatus bot_quest_status_;
PerlQuestStatus global_bot_quest_status_; PerlQuestStatus global_bot_quest_status_;
PerlQuestStatus merc_quest_status_;
PerlQuestStatus global_merc_quest_status_;
SV* _empty_sv; SV* _empty_sv;
+40
View File
@@ -776,6 +776,10 @@ void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue)
merc_list.emplace(std::pair<uint16, Merc *>(merc->GetID(), merc)); merc_list.emplace(std::pair<uint16, Merc *>(merc->GetID(), merc));
mob_list.emplace(std::pair<uint16, Mob *>(merc->GetID(), merc)); mob_list.emplace(std::pair<uint16, Mob *>(merc->GetID(), merc));
if (parse->MercHasQuestSub(EVENT_SPAWN)) {
parse->EventMerc(EVENT_SPAWN, merc, nullptr, "", 0);
}
} }
} }
@@ -5937,3 +5941,39 @@ void EntityList::DamageArea(
} }
} }
} }
std::vector<NPC*> EntityList::GetNPCsByIDs(std::vector<uint32> npc_ids)
{
std::vector<NPC*> v;
for (const auto& e : GetNPCList()) {
const auto& n = std::find(npc_ids.begin(), npc_ids.end(), e.second->GetNPCTypeID());
if (e.second) {
if (n != npc_ids.end()) {
continue;
}
v.emplace_back(e.second);
}
}
return v;
}
std::vector<NPC*> EntityList::GetExcludedNPCsByIDs(std::vector<uint32> npc_ids)
{
std::vector<NPC*> v;
for (const auto& e : GetNPCList()) {
const auto& n = std::find(npc_ids.begin(), npc_ids.end(), e.second->GetNPCTypeID());
if (e.second) {
if (n == npc_ids.end()) {
continue;
}
v.emplace_back(e.second);
}
}
return v;
}
+3
View File
@@ -560,6 +560,9 @@ public:
std::unordered_map<uint16, Mob *> &GetCloseMobList(Mob *mob, float distance = 0.0f); std::unordered_map<uint16, Mob *> &GetCloseMobList(Mob *mob, float distance = 0.0f);
std::vector<NPC*> GetNPCsByIDs(std::vector<uint32> npc_ids);
std::vector<NPC*> GetExcludedNPCsByIDs(std::vector<uint32> npc_ids);
void DepopAll(int NPCTypeID, bool StartSpawnTimer = true); void DepopAll(int NPCTypeID, bool StartSpawnTimer = true);
uint16 GetFreeID(); uint16 GetFreeID();
+1
View File
@@ -144,6 +144,7 @@ typedef enum {
EVENT_ENTITY_VARIABLE_UPDATE, EVENT_ENTITY_VARIABLE_UPDATE,
EVENT_AA_LOSS, EVENT_AA_LOSS,
EVENT_SPELL_BLOCKED, EVENT_SPELL_BLOCKED,
EVENT_READ_ITEM,
// Add new events before these or Lua crashes // Add new events before these or Lua crashes
EVENT_SPELL_EFFECT_BOT, EVENT_SPELL_EFFECT_BOT,
+1 -1
View File
@@ -17,7 +17,7 @@ void SetMOTD(Client *c, const Seperator *sep)
auto m = (ServerMotd_Struct *) pack->pBuffer; auto m = (ServerMotd_Struct *) pack->pBuffer;
strn0cpy(m->myname, c->GetName(), sizeof(m->myname)); strn0cpy(m->myname, c->GetName(), sizeof(m->myname));
strn0cpy(m->motd, message.c_str(), sizeof(m->motd)); strn0cpy(m->motd, !message.empty() ? message.c_str() : "", sizeof(m->motd));
worldserver.SendPacket(pack); worldserver.SendPacket(pack);
safe_delete(pack); safe_delete(pack);
+8 -3
View File
@@ -2117,14 +2117,19 @@ void Group::UnDelegateMarkNPC(const char *OldNPCMarkerName)
void Group::SaveGroupLeaderAA() void Group::SaveGroupLeaderAA()
{ {
const uint32 group_id = GetID();
if (!group_id) {
return;
}
// Stores the Group Leaders Leadership AA data from the Player Profile as a blob in the group_leaders table. // Stores the Group Leaders Leadership AA data from the Player Profile as a blob in the group_leaders table.
// This is done so that group members not in the same zone as the Leader still have access to this information. // This is done so that group members not in the same zone as the Leader still have access to this information.
std::string aa((char*) &LeaderAbilities, sizeof(GroupLeadershipAA_Struct)); std::string aa((char*) &LeaderAbilities, sizeof(GroupLeadershipAA_Struct));
auto results = GroupLeadersRepository::UpdateLeadershipAA(database, aa, GetID());
if (!results) { if (!GroupLeadersRepository::UpdateLeadershipAA(database, aa, group_id)) {
LogError("Unable to store GroupLeadershipAA for group_id: [{}]", GetID()); LogError("Unable to store GroupLeadershipAA for group_id: [{}]", group_id);
} }
} }
+8
View File
@@ -12,6 +12,7 @@
#include "lua_door.h" #include "lua_door.h"
#include "lua_bot.h" #include "lua_bot.h"
#include "lua_merc.h"
bool Lua_Entity::IsClient() { bool Lua_Entity::IsClient() {
Lua_Safe_Call_Bool(); Lua_Safe_Call_Bool();
@@ -140,6 +141,12 @@ Lua_Bot Lua_Entity::CastToBot() {
return Lua_Bot(b); return Lua_Bot(b);
} }
Lua_Merc Lua_Entity::CastToMerc() {
void *d = GetLuaPtrData();
Merc *m = reinterpret_cast<Merc*>(d);
return Lua_Merc(m);
}
luabind::scope lua_register_entity() { luabind::scope lua_register_entity() {
return luabind::class_<Lua_Entity>("Entity") return luabind::class_<Lua_Entity>("Entity")
.def(luabind::constructor<>()) .def(luabind::constructor<>())
@@ -149,6 +156,7 @@ luabind::scope lua_register_entity() {
.def("CastToClient", &Lua_Entity::CastToClient) .def("CastToClient", &Lua_Entity::CastToClient)
.def("CastToCorpse", &Lua_Entity::CastToCorpse) .def("CastToCorpse", &Lua_Entity::CastToCorpse)
.def("CastToDoor", &Lua_Entity::CastToDoor) .def("CastToDoor", &Lua_Entity::CastToDoor)
.def("CastToMerc", &Lua_Entity::CastToMerc)
.def("CastToMob", &Lua_Entity::CastToMob) .def("CastToMob", &Lua_Entity::CastToMob)
.def("CastToNPC", &Lua_Entity::CastToNPC) .def("CastToNPC", &Lua_Entity::CastToNPC)
.def("CastToObject", &Lua_Entity::CastToObject) .def("CastToObject", &Lua_Entity::CastToObject)
+2
View File
@@ -7,6 +7,7 @@
class Entity; class Entity;
class Lua_Client; class Lua_Client;
class Lua_Bot; class Lua_Bot;
class Lua_Merc;
class Lua_NPC; class Lua_NPC;
class Lua_Mob; class Lua_Mob;
struct Lua_HateList; struct Lua_HateList;
@@ -59,6 +60,7 @@ public:
Lua_Object CastToObject(); Lua_Object CastToObject();
Lua_Door CastToDoor(); Lua_Door CastToDoor();
Lua_Bot CastToBot(); Lua_Bot CastToBot();
Lua_Merc CastToMerc();
}; };
#endif #endif
+63
View File
@@ -16,6 +16,7 @@
#include "lua_spawn.h" #include "lua_spawn.h"
#include "lua_bot.h" #include "lua_bot.h"
#include "lua_merc.h"
struct Lua_Mob_List { struct Lua_Mob_List {
std::vector<Lua_Mob> entries; std::vector<Lua_Mob> entries;
@@ -764,6 +765,66 @@ void Lua_EntityList::MassGroupBuff(Lua_Mob caster, Lua_Mob center, uint16 spell_
self->MassGroupBuff(caster, center, spell_id, affect_caster); self->MassGroupBuff(caster, center, spell_id, affect_caster);
} }
Lua_NPC_List Lua_EntityList::GetNPCsByExcludedIDs(luabind::adl::object table)
{
Lua_Safe_Call_Class(Lua_NPC_List);
Lua_NPC_List ret;
if (luabind::type(table) != LUA_TTABLE) {
return ret;
}
if (d_) {
auto self = reinterpret_cast<NativeType*>(d_);
std::vector<uint32> ids;
int index = 1;
while (luabind::type(table[index]) != LUA_TNIL) {
ids.emplace_back(luabind::object_cast<uint32>(table[index]));
index++;
}
const auto& l = self->GetExcludedNPCsByIDs(ids);
for (const auto& e : l) {
ret.entries.emplace_back(Lua_NPC(e));
}
}
return ret;
}
Lua_NPC_List Lua_EntityList::GetNPCsByIDs(luabind::adl::object table)
{
Lua_Safe_Call_Class(Lua_NPC_List);
Lua_NPC_List ret;
if (luabind::type(table) != LUA_TTABLE) {
return ret;
}
if (d_) {
auto self = reinterpret_cast<NativeType*>(d_);
std::vector<uint32> ids;
int index = 1;
while (luabind::type(table[index]) != LUA_TNIL) {
ids.emplace_back(luabind::object_cast<uint32>(table[index]));
index++;
}
const auto& l = self->GetNPCsByIDs(ids);
for (const auto& e : l) {
ret.entries.emplace_back(Lua_NPC(e));
}
}
return ret;
}
luabind::scope lua_register_entity_list() { luabind::scope lua_register_entity_list() {
return luabind::class_<Lua_EntityList>("EntityList") return luabind::class_<Lua_EntityList>("EntityList")
.def(luabind::constructor<>()) .def(luabind::constructor<>())
@@ -829,6 +890,8 @@ luabind::scope lua_register_entity_list() {
.def("GetNPCByNPCTypeID", (Lua_NPC(Lua_EntityList::*)(int))&Lua_EntityList::GetNPCByNPCTypeID) .def("GetNPCByNPCTypeID", (Lua_NPC(Lua_EntityList::*)(int))&Lua_EntityList::GetNPCByNPCTypeID)
.def("GetNPCBySpawnID", (Lua_NPC(Lua_EntityList::*)(int))&Lua_EntityList::GetNPCBySpawnID) .def("GetNPCBySpawnID", (Lua_NPC(Lua_EntityList::*)(int))&Lua_EntityList::GetNPCBySpawnID)
.def("GetNPCList", (Lua_NPC_List(Lua_EntityList::*)(void))&Lua_EntityList::GetNPCList) .def("GetNPCList", (Lua_NPC_List(Lua_EntityList::*)(void))&Lua_EntityList::GetNPCList)
.def("GetNPCsByExcludedIDs", (Lua_NPC_List(Lua_EntityList::*)(luabind::adl::object))&Lua_EntityList::GetNPCsByExcludedIDs)
.def("GetNPCsByIDs", (Lua_NPC_List(Lua_EntityList::*)(luabind::adl::object))&Lua_EntityList::GetNPCsByIDs)
.def("GetObjectByDBID", (Lua_Object(Lua_EntityList::*)(uint32))&Lua_EntityList::GetObjectByDBID) .def("GetObjectByDBID", (Lua_Object(Lua_EntityList::*)(uint32))&Lua_EntityList::GetObjectByDBID)
.def("GetObjectByID", (Lua_Object(Lua_EntityList::*)(int))&Lua_EntityList::GetObjectByID) .def("GetObjectByID", (Lua_Object(Lua_EntityList::*)(int))&Lua_EntityList::GetObjectByID)
.def("GetObjectList", (Lua_Object_List(Lua_EntityList::*)(void))&Lua_EntityList::GetObjectList) .def("GetObjectList", (Lua_Object_List(Lua_EntityList::*)(void))&Lua_EntityList::GetObjectList)
+3 -1
View File
@@ -8,6 +8,7 @@ class EntityList;
class Lua_Mob; class Lua_Mob;
class Lua_Client; class Lua_Client;
class Lua_Bot; class Lua_Bot;
class Lua_Merc;
class Lua_NPC; class Lua_NPC;
class Lua_Door; class Lua_Door;
class Lua_Corpse; class Lua_Corpse;
@@ -156,7 +157,8 @@ public:
void AreaTaunt(Lua_Client caster, float range, int bonus_hate); void AreaTaunt(Lua_Client caster, float range, int bonus_hate);
void MassGroupBuff(Lua_Mob caster, Lua_Mob center, uint16 spell_id); void MassGroupBuff(Lua_Mob caster, Lua_Mob center, uint16 spell_id);
void MassGroupBuff(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster); void MassGroupBuff(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster);
Lua_NPC_List GetNPCsByIDs(luabind::adl::object npc_ids);
Lua_NPC_List GetNPCsByExcludedIDs(luabind::adl::object npc_ids);
}; };
#endif #endif
+2 -1
View File
@@ -6907,7 +6907,8 @@ luabind::scope lua_register_events() {
luabind::value("entity_variable_delete", static_cast<int>(EVENT_ENTITY_VARIABLE_DELETE)), luabind::value("entity_variable_delete", static_cast<int>(EVENT_ENTITY_VARIABLE_DELETE)),
luabind::value("entity_variable_set", static_cast<int>(EVENT_ENTITY_VARIABLE_SET)), luabind::value("entity_variable_set", static_cast<int>(EVENT_ENTITY_VARIABLE_SET)),
luabind::value("entity_variable_update", static_cast<int>(EVENT_ENTITY_VARIABLE_UPDATE)), luabind::value("entity_variable_update", static_cast<int>(EVENT_ENTITY_VARIABLE_UPDATE)),
luabind::value("aa_loss", static_cast<int>(EVENT_AA_LOSS)) luabind::value("aa_loss", static_cast<int>(EVENT_AA_LOSS)),
luabind::value("read", static_cast<int>(EVENT_READ_ITEM))
)]; )];
} }
+229
View File
@@ -0,0 +1,229 @@
#ifdef LUA_EQEMU
#include "lua.hpp"
#include <luabind/luabind.hpp>
#include "merc.h"
#include "lua_client.h"
#include "lua_merc.h"
#include "lua_group.h"
#include "lua_item.h"
#include "lua_iteminst.h"
#include "lua_mob.h"
uint32 Lua_Merc::GetCostFormula()
{
Lua_Safe_Call_Int();
return self->GetCostFormula();
}
Lua_Group Lua_Merc::GetGroup()
{
Lua_Safe_Call_Class(Lua_Group);
return self->GetGroup();
}
int Lua_Merc::GetHatedCount()
{
Lua_Safe_Call_Int();
return self->GetHatedCount();
}
float Lua_Merc::GetMaxMeleeRangeToTarget(Lua_Mob target)
{
Lua_Safe_Call_Real();
return self->GetMaxMeleeRangeToTarget(target);
}
uint32 Lua_Merc::GetMercenaryCharacterID()
{
Lua_Safe_Call_Int();
return self->GetMercenaryCharacterID();
}
uint32 Lua_Merc::GetMercenaryID()
{
Lua_Safe_Call_Int();
return self->GetMercenaryID();
}
uint32 Lua_Merc::GetMercenaryNameType()
{
Lua_Safe_Call_Int();
return self->GetMercNameType();
}
Lua_Client Lua_Merc::GetMercenaryOwner()
{
Lua_Safe_Call_Class(Lua_Client);
return Lua_Client(self->GetMercenaryOwner());
}
uint32 Lua_Merc::GetMercenarySubtype()
{
Lua_Safe_Call_Int();
return self->GetMercenarySubType();
}
uint32 Lua_Merc::GetMercenaryTemplateID()
{
Lua_Safe_Call_Int();
return self->GetMercenaryTemplateID();
}
uint32 Lua_Merc::GetMercenaryType()
{
Lua_Safe_Call_Int();
return self->GetMercenaryType();
}
Lua_Mob Lua_Merc::GetOwner()
{
Lua_Safe_Call_Class(Lua_Mob);
return Lua_Mob(self->GetOwner());
}
Lua_Mob Lua_Merc::GetOwnerOrSelf()
{
Lua_Safe_Call_Class(Lua_Mob);
return Lua_Mob(self->GetOwnerOrSelf());
}
uint8 Lua_Merc::GetProficiencyID()
{
Lua_Safe_Call_Int();
return self->GetProficiencyID();
}
uint8 Lua_Merc::GetStance()
{
Lua_Safe_Call_Int();
return self->GetStance();
}
uint8 Lua_Merc::GetTierID()
{
Lua_Safe_Call_Int();
return self->GetTierID();
}
bool Lua_Merc::HasOrMayGetAggro()
{
Lua_Safe_Call_Bool();
return self->HasOrMayGetAggro();
}
bool Lua_Merc::IsMercenaryCaster()
{
Lua_Safe_Call_Bool();
return self->IsMercCaster();
}
bool Lua_Merc::IsMercenaryCasterCombatRange(Lua_Mob target)
{
Lua_Safe_Call_Bool();
return self->IsMercCasterCombatRange(target);
}
bool Lua_Merc::IsSitting()
{
Lua_Safe_Call_Bool();
return self->IsSitting();
}
bool Lua_Merc::IsStanding()
{
Lua_Safe_Call_Bool();
return self->IsStanding();
}
void Lua_Merc::ScaleStats(int scale_percentage)
{
Lua_Safe_Call_Void();
self->ScaleStats(scale_percentage);
}
void Lua_Merc::ScaleStats(int scale_percentage, bool set_to_max)
{
Lua_Safe_Call_Void();
self->ScaleStats(scale_percentage, set_to_max);
}
void Lua_Merc::SendPayload(int payload_id, std::string payload_value)
{
Lua_Safe_Call_Void();
self->SendPayload(payload_id, payload_value);
}
void Lua_Merc::SetTarget(Lua_Mob target)
{
Lua_Safe_Call_Void();
self->SetTarget(target);
}
void Lua_Merc::Signal(int signal_id)
{
Lua_Safe_Call_Void();
self->Signal(signal_id);
}
void Lua_Merc::Sit()
{
Lua_Safe_Call_Void();
self->Sit();
}
void Lua_Merc::Stand()
{
Lua_Safe_Call_Void();
self->Stand();
}
bool Lua_Merc::Suspend()
{
Lua_Safe_Call_Bool();
return self->Suspend();
}
bool Lua_Merc::UseDiscipline(uint16 spell_id, uint16 target_id)
{
Lua_Safe_Call_Bool();
return self->UseDiscipline(spell_id, target_id);
}
luabind::scope lua_register_merc() {
return luabind::class_<Lua_Merc, Lua_Mob>("Merc")
.def(luabind::constructor<>())
.def("GetCostFormula", &Lua_Merc::GetCostFormula)
.def("GetGroup", &Lua_Merc::GetGroup)
.def("GetHatedCount", &Lua_Merc::GetHatedCount)
.def("GetMaxMeleeRangeToTarget", &Lua_Merc::GetMaxMeleeRangeToTarget)
.def("GetMercenaryCharacterID", &Lua_Merc::GetMercenaryCharacterID)
.def("GetMercenaryID", &Lua_Merc::GetMercenaryID)
.def("GetMercenaryNameType", &Lua_Merc::GetMercenaryNameType)
.def("GetMercenaryOwner", &Lua_Merc::GetMercenaryOwner)
.def("GetMercenarySubtype", &Lua_Merc::GetMercenarySubtype)
.def("GetMercenaryTemplateID", &Lua_Merc::GetMercenaryTemplateID)
.def("GetMercenaryType", &Lua_Merc::GetMercenaryType)
.def("GetOwner", &Lua_Merc::GetOwner)
.def("GetOwnerOrSelf", &Lua_Merc::GetOwnerOrSelf)
.def("GetProficiencyID", &Lua_Merc::GetProficiencyID)
.def("GetStance", &Lua_Merc::GetStance)
.def("GetTierID", &Lua_Merc::GetTierID)
.def("HasOrMayGetAggro", &Lua_Merc::HasOrMayGetAggro)
.def("IsMercenaryCaster", &Lua_Merc::IsMercenaryCaster)
.def("IsMercenaryCasterCombatRange", &Lua_Merc::IsMercenaryCasterCombatRange)
.def("IsSitting", &Lua_Merc::IsSitting)
.def("IsStanding", &Lua_Merc::IsStanding)
.def("ScaleStats", (void(Lua_Merc::*)(int))&Lua_Merc::ScaleStats)
.def("ScaleStats", (void(Lua_Merc::*)(int,bool))&Lua_Merc::ScaleStats)
.def("SendPayload", &Lua_Merc::SendPayload)
.def("SetTarget", &Lua_Merc::SetTarget)
.def("Signal", &Lua_Merc::Signal)
.def("Sit", &Lua_Merc::Sit)
.def("Stand", &Lua_Merc::Stand)
.def("Suspend", &Lua_Merc::Suspend)
.def("UseDiscipline", &Lua_Merc::UseDiscipline);
}
#endif
+63
View File
@@ -0,0 +1,63 @@
#ifndef EQEMU_LUA_MERC_H
#define EQEMU_LUA_MERC_H
#ifdef LUA_EQEMU
#include "lua_mob.h"
class Merc;
class Lua_Group;
class Lua_Merc;
class Lua_Mob;
namespace luabind {
struct scope;
}
luabind::scope lua_register_merc();
class Lua_Merc : public Lua_Mob
{
typedef Merc NativeType;
public:
Lua_Merc() { SetLuaPtrData(nullptr); }
Lua_Merc(Merc *d) { SetLuaPtrData(reinterpret_cast<Entity*>(d)); }
virtual ~Lua_Merc() { }
operator Merc*() {
return reinterpret_cast<Merc*>(GetLuaPtrData());
}
uint32 GetCostFormula();
Lua_Group GetGroup();
int GetHatedCount();
float GetMaxMeleeRangeToTarget(Lua_Mob target);
uint32 GetMercenaryCharacterID();
uint32 GetMercenaryID();
uint32 GetMercenaryNameType();
Lua_Client GetMercenaryOwner();
uint32 GetMercenarySubtype();
uint32 GetMercenaryTemplateID();
uint32 GetMercenaryType();
Lua_Mob GetOwner();
Lua_Mob GetOwnerOrSelf();
uint8 GetProficiencyID();
uint8 GetStance();
uint8 GetTierID();
bool HasOrMayGetAggro();
bool IsMercenaryCaster();
bool IsMercenaryCasterCombatRange(Lua_Mob target);
bool IsSitting();
bool IsStanding();
void ScaleStats(int scale_percentage);
void ScaleStats(int scale_percentage, bool set_to_max);
void SendPayload(int payload_id, std::string payload_value);
void SetTarget(Lua_Mob target);
void Signal(int signal_id);
void Sit();
void Stand();
bool Suspend();
bool UseDiscipline(uint16 spell_id, uint16 target_id);
};
#endif // LUA_EQEMU
#endif // EQEMU_LUA_MERC_H
+35
View File
@@ -3446,6 +3446,36 @@ void Lua_Mob::MassGroupBuff(Lua_Mob center, uint16 spell_id, bool affect_caster)
entity_list.MassGroupBuff(self, center, spell_id, affect_caster); entity_list.MassGroupBuff(self, center, spell_id, affect_caster);
} }
void Lua_Mob::BuffFadeBeneficial()
{
Lua_Safe_Call_Void();
self->BuffFadeBeneficial();
}
void Lua_Mob::BuffFadeDetrimental()
{
Lua_Safe_Call_Void();
self->BuffFadeDetrimental();
}
void Lua_Mob::BuffFadeDetrimentalByCaster(Lua_Mob caster)
{
Lua_Safe_Call_Void();
self->BuffFadeDetrimentalByCaster(caster);
}
void Lua_Mob::BuffFadeNonPersistDeath()
{
Lua_Safe_Call_Void();
self->BuffFadeNonPersistDeath();
}
void Lua_Mob::BuffFadeSongs()
{
Lua_Safe_Call_Void();
self->BuffFadeSongs();
}
luabind::scope lua_register_mob() { luabind::scope lua_register_mob() {
return luabind::class_<Lua_Mob, Lua_Entity>("Mob") return luabind::class_<Lua_Mob, Lua_Entity>("Mob")
.def(luabind::constructor<>()) .def(luabind::constructor<>())
@@ -3483,11 +3513,16 @@ luabind::scope lua_register_mob() {
.def("BuffCount", (uint32(Lua_Mob::*)(bool))&Lua_Mob::BuffCount) .def("BuffCount", (uint32(Lua_Mob::*)(bool))&Lua_Mob::BuffCount)
.def("BuffCount", (uint32(Lua_Mob::*)(bool,bool))&Lua_Mob::BuffCount) .def("BuffCount", (uint32(Lua_Mob::*)(bool,bool))&Lua_Mob::BuffCount)
.def("BuffFadeAll", (void(Lua_Mob::*)(void))&Lua_Mob::BuffFadeAll) .def("BuffFadeAll", (void(Lua_Mob::*)(void))&Lua_Mob::BuffFadeAll)
.def("BuffFadeBeneficial", (void(Lua_Mob::*)(void))&Lua_Mob::BuffFadeBeneficial)
.def("BuffFadeByEffect", (void(Lua_Mob::*)(int))&Lua_Mob::BuffFadeByEffect) .def("BuffFadeByEffect", (void(Lua_Mob::*)(int))&Lua_Mob::BuffFadeByEffect)
.def("BuffFadeByEffect", (void(Lua_Mob::*)(int,int))&Lua_Mob::BuffFadeByEffect) .def("BuffFadeByEffect", (void(Lua_Mob::*)(int,int))&Lua_Mob::BuffFadeByEffect)
.def("BuffFadeBySlot", (void(Lua_Mob::*)(int))&Lua_Mob::BuffFadeBySlot) .def("BuffFadeBySlot", (void(Lua_Mob::*)(int))&Lua_Mob::BuffFadeBySlot)
.def("BuffFadeBySlot", (void(Lua_Mob::*)(int,bool))&Lua_Mob::BuffFadeBySlot) .def("BuffFadeBySlot", (void(Lua_Mob::*)(int,bool))&Lua_Mob::BuffFadeBySlot)
.def("BuffFadeBySpellID", (void(Lua_Mob::*)(int))&Lua_Mob::BuffFadeBySpellID) .def("BuffFadeBySpellID", (void(Lua_Mob::*)(int))&Lua_Mob::BuffFadeBySpellID)
.def("BuffFadeDetrimental", (void(Lua_Mob::*)(void))&Lua_Mob::BuffFadeDetrimental)
.def("BuffFadeDetrimentalByCaster", (void(Lua_Mob::*)(Lua_Mob))&Lua_Mob::BuffFadeDetrimentalByCaster)
.def("BuffFadeNonPersistDeath", (void(Lua_Mob::*)(void))&Lua_Mob::BuffFadeNonPersistDeath)
.def("BuffFadeSongs", (void(Lua_Mob::*)(void))&Lua_Mob::BuffFadeSongs)
.def("CalculateDistance", (float(Lua_Mob::*)(double,double,double))&Lua_Mob::CalculateDistance) .def("CalculateDistance", (float(Lua_Mob::*)(double,double,double))&Lua_Mob::CalculateDistance)
.def("CalculateDistance", (float(Lua_Mob::*)(Lua_Mob))&Lua_Mob::CalculateDistance) .def("CalculateDistance", (float(Lua_Mob::*)(Lua_Mob))&Lua_Mob::CalculateDistance)
.def("CalculateHeadingToTarget", (double(Lua_Mob::*)(double,double))&Lua_Mob::CalculateHeadingToTarget) .def("CalculateHeadingToTarget", (double(Lua_Mob::*)(double,double))&Lua_Mob::CalculateHeadingToTarget)
+6
View File
@@ -10,6 +10,7 @@ class Lua_Item;
class Lua_ItemInst; class Lua_ItemInst;
class Lua_StatBonuses; class Lua_StatBonuses;
class Lua_Bot; class Lua_Bot;
class Lua_Merc;
class Lua_NPC; class Lua_NPC;
class Lua_Client; class Lua_Client;
struct Lua_Mob_List; struct Lua_Mob_List;
@@ -605,6 +606,11 @@ public:
void AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets); void AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets);
void MassGroupBuff(Lua_Mob center, uint16 spell_id); void MassGroupBuff(Lua_Mob center, uint16 spell_id);
void MassGroupBuff(Lua_Mob center, uint16 spell_id, bool affect_caster); void MassGroupBuff(Lua_Mob center, uint16 spell_id, bool affect_caster);
void BuffFadeBeneficial();
void BuffFadeDetrimental();
void BuffFadeDetrimentalByCaster(Lua_Mob caster);
void BuffFadeNonPersistDeath();
void BuffFadeSongs();
}; };
#endif #endif
+192 -1
View File
@@ -32,6 +32,7 @@
#include "lua_inventory.h" #include "lua_inventory.h"
#include "lua_item.h" #include "lua_item.h"
#include "lua_iteminst.h" #include "lua_iteminst.h"
#include "lua_merc.h"
#include "lua_mob.h" #include "lua_mob.h"
#include "lua_npc.h" #include "lua_npc.h"
#include "lua_object.h" #include "lua_object.h"
@@ -184,7 +185,8 @@ const char *LuaEvents[_LargestEventID] = {
"event_entity_variable_set", "event_entity_variable_set",
"event_entity_variable_update", "event_entity_variable_update",
"event_aa_loss", "event_aa_loss",
"event_spell_blocked" "event_spell_blocked",
"event_read_item"
}; };
extern Zone *zone; extern Zone *zone;
@@ -348,6 +350,7 @@ LuaParser::LuaParser() {
PlayerArgumentDispatch[EVENT_ENTITY_VARIABLE_UPDATE] = handle_player_entity_variable; PlayerArgumentDispatch[EVENT_ENTITY_VARIABLE_UPDATE] = handle_player_entity_variable;
PlayerArgumentDispatch[EVENT_AA_LOSS] = handle_player_aa_loss; PlayerArgumentDispatch[EVENT_AA_LOSS] = handle_player_aa_loss;
PlayerArgumentDispatch[EVENT_SPELL_BLOCKED] = handle_player_spell_blocked; PlayerArgumentDispatch[EVENT_SPELL_BLOCKED] = handle_player_spell_blocked;
PlayerArgumentDispatch[EVENT_READ_ITEM] = handle_player_read_item;
ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click; ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click;
ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click; ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click;
@@ -1277,6 +1280,7 @@ void LuaParser::MapFunctions(lua_State *L) {
lua_register_npc(), lua_register_npc(),
lua_register_client(), lua_register_client(),
lua_register_bot(), lua_register_bot(),
lua_register_merc(),
lua_register_inventory(), lua_register_inventory(),
lua_register_inventory_where(), lua_register_inventory_where(),
lua_register_iteminst(), lua_register_iteminst(),
@@ -1833,3 +1837,190 @@ void LuaParser::LoadBotScript(std::string filename) {
void LuaParser::LoadGlobalBotScript(std::string filename) { void LuaParser::LoadGlobalBotScript(std::string filename) {
LoadScript(filename, "global_bot"); LoadScript(filename, "global_bot");
} }
int LuaParser::EventMerc(
QuestEventID evt,
Merc *merc,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
evt = ConvertLuaEvent(evt);
if (evt >= _LargestEventID) {
return 0;
}
if (!merc) {
return 0;
}
if (!MercHasQuestSub(evt)) {
return 0;
}
return _EventMerc("merc", evt, merc, init, data, extra_data, extra_pointers);
}
int LuaParser::EventGlobalMerc(
QuestEventID evt,
Merc *merc,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
evt = ConvertLuaEvent(evt);
if (evt >= _LargestEventID) {
return 0;
}
if (!merc) {
return 0;
}
if (!GlobalMercHasQuestSub(evt)) {
return 0;
}
return _EventMerc("global_merc", evt, merc, init, data, extra_data, extra_pointers);
}
int LuaParser::_EventMerc(
std::string package_name,
QuestEventID evt,
Merc *merc,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers,
luabind::adl::object *l_func
) {
const char *sub_name = LuaEvents[evt];
int start = lua_gettop(L);
try {
int npop = 2;
PushErrorHandler(L);
if(l_func != nullptr) {
l_func->push(L);
} else {
lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str());
lua_getfield(L, -1, sub_name);
npop = 3;
}
lua_createtable(L, 0, 0);
//push self
Lua_Merc l_merc(merc);
luabind::adl::object l_merc_o = luabind::adl::object(L, l_merc);
l_merc_o.push(L);
lua_setfield(L, -2, "self");
auto arg_function = NPCArgumentDispatch[evt];
arg_function(this, L, merc, init, data, extra_data, extra_pointers);
auto* c = (init && init->IsClient()) ? init->CastToClient() : nullptr;
quest_manager.StartQuest(merc, c);
if(lua_pcall(L, 1, 1, start + 1)) {
std::string error = lua_tostring(L, -1);
AddError(error);
quest_manager.EndQuest();
lua_pop(L, npop);
return 0;
}
quest_manager.EndQuest();
if(lua_isnumber(L, -1)) {
int ret = static_cast<int>(lua_tointeger(L, -1));
lua_pop(L, npop);
return ret;
}
lua_pop(L, npop);
} catch(std::exception &ex) {
AddError(
fmt::format(
"Lua Exception | [{}] for Merc [{}] in [{}]: {}",
sub_name,
merc->GetID(),
package_name,
ex.what()
)
);
//Restore our stack to the best of our ability
int end = lua_gettop(L);
int n = end - start;
if(n > 0) {
lua_pop(L, n);
}
}
return 0;
}
int LuaParser::DispatchEventMerc(
QuestEventID evt,
Merc *merc,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
evt = ConvertLuaEvent(evt);
if (evt >= _LargestEventID) {
return 0;
}
std::string package_name = "merc";
auto iter = lua_encounter_events_registered.find(package_name);
if (iter == lua_encounter_events_registered.end()) {
return 0;
}
int ret = 0;
auto riter = iter->second.begin();
while (riter != iter->second.end()) {
if (riter->event_id == evt) {
package_name = fmt::format("encounter_{}", riter->encounter_name);
int i = _EventMerc(package_name, evt, merc, init, data, extra_data, extra_pointers, &riter->lua_reference);
if (i != 0) {
ret = i;
}
}
++riter;
}
return ret;
}
bool LuaParser::MercHasQuestSub(QuestEventID evt) {
evt = ConvertLuaEvent(evt);
if (evt >= _LargestEventID) {
return false;
}
const char *subname = LuaEvents[evt];
return HasFunction(subname, "merc");
}
bool LuaParser::GlobalMercHasQuestSub(QuestEventID evt) {
evt = ConvertLuaEvent(evt);
if (evt >= _LargestEventID) {
return false;
}
const char *subname = LuaEvents[evt];
return HasFunction(subname, "global_merc");
}
void LuaParser::LoadMercScript(std::string filename) {
LoadScript(filename, "merc");
}
void LuaParser::LoadGlobalMercScript(std::string filename) {
LoadScript(filename, "global_merc");
}
+38
View File
@@ -109,6 +109,22 @@ public:
uint32 extra_data, uint32 extra_data,
std::vector<std::any> *extra_pointers std::vector<std::any> *extra_pointers
); );
virtual int EventMerc(
QuestEventID evt,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
);
virtual int EventGlobalMerc(
QuestEventID evt,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
);
virtual bool HasQuestSub(uint32 npc_id, QuestEventID evt); virtual bool HasQuestSub(uint32 npc_id, QuestEventID evt);
virtual bool HasGlobalQuestSub(QuestEventID evt); virtual bool HasGlobalQuestSub(QuestEventID evt);
@@ -120,6 +136,8 @@ public:
virtual bool HasEncounterSub(const std::string& package_name, QuestEventID evt); virtual bool HasEncounterSub(const std::string& package_name, QuestEventID evt);
virtual bool BotHasQuestSub(QuestEventID evt); virtual bool BotHasQuestSub(QuestEventID evt);
virtual bool GlobalBotHasQuestSub(QuestEventID evt); virtual bool GlobalBotHasQuestSub(QuestEventID evt);
virtual bool MercHasQuestSub(QuestEventID evt);
virtual bool GlobalMercHasQuestSub(QuestEventID evt);
virtual void LoadNPCScript(std::string filename, int npc_id); virtual void LoadNPCScript(std::string filename, int npc_id);
virtual void LoadGlobalNPCScript(std::string filename); virtual void LoadGlobalNPCScript(std::string filename);
@@ -130,6 +148,8 @@ public:
virtual void LoadEncounterScript(std::string filename, std::string encounter_name); virtual void LoadEncounterScript(std::string filename, std::string encounter_name);
virtual void LoadBotScript(std::string filename); virtual void LoadBotScript(std::string filename);
virtual void LoadGlobalBotScript(std::string filename); virtual void LoadGlobalBotScript(std::string filename);
virtual void LoadMercScript(std::string filename);
virtual void LoadGlobalMercScript(std::string filename);
virtual void AddVar(std::string name, std::string val); virtual void AddVar(std::string name, std::string val);
virtual std::string GetVar(std::string name); virtual std::string GetVar(std::string name);
@@ -179,6 +199,14 @@ public:
uint32 extra_data, uint32 extra_data,
std::vector<std::any> *extra_pointers std::vector<std::any> *extra_pointers
); );
virtual int DispatchEventMerc(
QuestEventID evt,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
);
static LuaParser* Instance() { static LuaParser* Instance() {
static LuaParser inst; static LuaParser inst;
@@ -269,6 +297,16 @@ private:
std::vector<std::any> *extra_pointers, std::vector<std::any> *extra_pointers,
luabind::adl::object *l_func = nullptr luabind::adl::object *l_func = nullptr
); );
int _EventMerc(
std::string package_name,
QuestEventID evt,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers,
luabind::adl::object* l_func = nullptr
);
void LoadScript(std::string filename, std::string package_name); void LoadScript(std::string filename, std::string package_name);
void MapFunctions(lua_State *L); void MapFunctions(lua_State *L);
+55
View File
@@ -734,6 +734,18 @@ void handle_player_death(
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[4])); lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[4]));
lua_setfield(L, -2, "killed_entity_id"); lua_setfield(L, -2, "killed_entity_id");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[5]));
lua_setfield(L, -2, "combat_start_time");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[6]));
lua_setfield(L, -2, "combat_end_time");
lua_pushinteger(L, Strings::ToBigInt(sep.arg[7]));
lua_setfield(L, -2, "damage_received");
lua_pushinteger(L, Strings::ToBigInt(sep.arg[8]));
lua_setfield(L, -2, "healing_received");
} }
void handle_player_timer( void handle_player_timer(
@@ -1745,6 +1757,49 @@ void handle_player_spell_blocked(
lua_setfield(L, -2, "cast_spell"); lua_setfield(L, -2, "cast_spell");
} }
void handle_player_read_item(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
)
{
lua_pushstring(L, data.c_str());
lua_setfield(L, -2, "text_file");
lua_pushinteger(L, extra_data);
lua_setfield(L, -2, "item_id");
if (extra_pointers) {
if (extra_pointers->size() == 7) {
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(0)).c_str());
lua_setfield(L, -2, "book_text");
lua_pushboolean(L, std::any_cast<int8>(extra_pointers->at(1)));
lua_setfield(L, -2, "can_cast");
lua_pushboolean(L, std::any_cast<int8>(extra_pointers->at(2)));
lua_setfield(L, -2, "can_scribe");
lua_pushinteger(L, std::any_cast<int16>(extra_pointers->at(3)));
lua_setfield(L, -2, "slot_id");
lua_pushinteger(L, std::any_cast<int>(extra_pointers->at(4)));
lua_setfield(L, -2, "target_id");
lua_pushinteger(L, std::any_cast<uint8>(extra_pointers->at(5)));
lua_setfield(L, -2, "type");
Lua_ItemInst l_item(std::any_cast<EQ::ItemInstance*>(extra_pointers->at(6)));
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
l_item_o.push(L);
lua_setfield(L, -2, "item");
}
}
}
// Item // Item
void handle_item_click( void handle_item_click(
QuestInterface *parse, QuestInterface *parse,
+10
View File
@@ -8,6 +8,7 @@ typedef void(*ItemArgumentHandler)(QuestInterface*, lua_State*, Client*, EQ::Ite
typedef void(*SpellArgumentHandler)(QuestInterface*, lua_State*, Mob*, Client*, uint32, std::string, uint32, std::vector<std::any>*); typedef void(*SpellArgumentHandler)(QuestInterface*, lua_State*, Mob*, Client*, uint32, std::string, uint32, std::vector<std::any>*);
typedef void(*EncounterArgumentHandler)(QuestInterface*, lua_State*, Encounter* encounter, std::string, uint32, std::vector<std::any>*); typedef void(*EncounterArgumentHandler)(QuestInterface*, lua_State*, Encounter* encounter, std::string, uint32, std::vector<std::any>*);
typedef void(*BotArgumentHandler)(QuestInterface*, lua_State*, Bot*, Mob*, std::string, uint32, std::vector<std::any>*); typedef void(*BotArgumentHandler)(QuestInterface*, lua_State*, Bot*, Mob*, std::string, uint32, std::vector<std::any>*);
typedef void(*MercArgumentHandler)(QuestInterface*, lua_State*, Merc*, Mob*, std::string, uint32, std::vector<std::any>*);
// NPC // NPC
void handle_npc_event_say( void handle_npc_event_say(
@@ -855,6 +856,15 @@ void handle_player_spell_blocked(
std::vector<std::any> *extra_pointers std::vector<std::any> *extra_pointers
); );
void handle_player_read_item(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
// Item // Item
void handle_item_click( void handle_item_click(
QuestInterface *parse, QuestInterface *parse,
+17 -10
View File
@@ -5,6 +5,7 @@
#include "entity.h" #include "entity.h"
#include "groups.h" #include "groups.h"
#include "mob.h" #include "mob.h"
#include "quest_parser_collection.h"
#include "zone.h" #include "zone.h"
#include "string_ids.h" #include "string_ids.h"
@@ -4078,12 +4079,6 @@ bool Merc::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillT
Save(); Save();
//no corpse, no exp if we're a merc.
//We'll suspend instead, since that's what live does.
//Not actually sure live supports 'depopping' merc corpses.
//if(entity_list.GetCorpseByID(GetID()))
// entity_list.GetCorpseByID(GetID())->Depop();
// If client is in zone, suspend merc, else depop it. // If client is in zone, suspend merc, else depop it.
if (!Suspend()) { if (!Suspend()) {
Depop(); Depop();
@@ -4671,7 +4666,6 @@ bool Merc::Spawn(Client *owner) {
//UpdateMercAppearance(); //UpdateMercAppearance();
return true; return true;
} }
@@ -5189,9 +5183,6 @@ void Client::SpawnMerc(Merc* merc, bool setMaxStats) {
merc->SetStance(GetMercInfo().Stance); merc->SetStance(GetMercInfo().Stance);
Log(Logs::General, Logs::Mercenaries, "SpawnMerc Success for %s.", GetName()); Log(Logs::General, Logs::Mercenaries, "SpawnMerc Success for %s.", GetName());
return;
} }
bool Merc::Suspend() { bool Merc::Suspend() {
@@ -5914,3 +5905,19 @@ uint32 Merc::CalcUpkeepCost(uint32 templateID , uint8 level, uint8 currency_type
return cost; return cost;
} }
void Merc::Signal(int signal_id)
{
if (parse->MercHasQuestSub(EVENT_SIGNAL)) {
parse->EventMerc(EVENT_SIGNAL, this, nullptr, std::to_string(signal_id), 0);
}
}
void Merc::SendPayload(int payload_id, std::string payload_value)
{
if (parse->MercHasQuestSub(EVENT_PAYLOAD)) {
const auto& export_string = fmt::format("{} {}", payload_id, payload_value);
parse->EventMerc(EVENT_PAYLOAD, this, nullptr, export_string, 0);
}
}
+3
View File
@@ -146,6 +146,9 @@ public:
bool IsMedding() { return _medding; }; bool IsMedding() { return _medding; };
bool IsSuspended() { return _suspended; }; bool IsSuspended() { return _suspended; };
void Signal(int signal_id);
void SendPayload(int payload_id, std::string payload_value);
static uint32 CalcPurchaseCost( uint32 templateID , uint8 level, uint8 currency_type = 0); static uint32 CalcPurchaseCost( uint32 templateID , uint8 level, uint8 currency_type = 0);
static uint32 CalcUpkeepCost( uint32 templateID , uint8 level, uint8 currency_type = 0); static uint32 CalcUpkeepCost( uint32 templateID , uint8 level, uint8 currency_type = 0);
+11 -75
View File
@@ -4068,7 +4068,8 @@ uint8 Mob::GetDefaultGender(uint16 in_race, uint8 in_gender) {
in_race == Race::Human2 || in_race == Race::Human2 ||
in_race == Race::ElvenGhost || in_race == Race::ElvenGhost ||
in_race == Race::HumanGhost || in_race == Race::HumanGhost ||
in_race == Race::Coldain2 in_race == Race::Coldain2 ||
in_race == Race::Akheva
) { ) {
if (in_gender >= Gender::Neuter) { // Male default for PC Races if (in_gender >= Gender::Neuter) { // Male default for PC Races
return Gender::Male; return Gender::Male;
@@ -5513,37 +5514,13 @@ void Mob::SetTarget(Mob *mob)
target = mob; target = mob;
entity_list.UpdateHoTT(this); entity_list.UpdateHoTT(this);
const auto has_target_change_event = (
parse->HasQuestSub(GetNPCTypeID(), EVENT_TARGET_CHANGE) ||
parse->PlayerHasQuestSub(EVENT_TARGET_CHANGE) ||
parse->BotHasQuestSub(EVENT_TARGET_CHANGE)
);
if (IsClient() && CastToClient()->admin > AccountStatus::GMMgmt) { if (IsClient() && CastToClient()->admin > AccountStatus::GMMgmt) {
DisplayInfo(mob); DisplayInfo(mob);
} }
if (has_target_change_event) { std::vector<std::any> args = { mob };
std::vector<std::any> args;
args.emplace_back(mob); parse->EventMob(EVENT_TARGET_CHANGE, this, mob, [&]() { return ""; }, 0, &args);
if (IsNPC()) {
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_TARGET_CHANGE)) {
parse->EventNPC(EVENT_TARGET_CHANGE, CastToNPC(), mob, "", 0, &args);
}
} else if (IsClient()) {
if (parse->PlayerHasQuestSub(EVENT_TARGET_CHANGE)) {
parse->EventPlayer(EVENT_TARGET_CHANGE, CastToClient(), "", 0, &args);
}
CastToClient()->SetBotPrecombat(false); // Any change in target will nullify this flag (target == mob checked above)
} else if (IsBot()) {
if (parse->BotHasQuestSub(EVENT_TARGET_CHANGE)) {
parse->EventBot(EVENT_TARGET_CHANGE, CastToBot(), mob, "", 0, &args);
}
}
}
if (IsPet() && GetOwner() && GetOwner()->IsClient()) { if (IsPet() && GetOwner() && GetOwner()->IsClient()) {
GetOwner()->CastToClient()->UpdateXTargetType(MyPetTarget, mob); GetOwner()->CastToClient()->UpdateXTargetType(MyPetTarget, mob);
@@ -5716,22 +5693,10 @@ bool Mob::ClearEntityVariables()
return false; return false;
} }
if (
(IsBot() && parse->BotHasQuestSub(EVENT_ENTITY_VARIABLE_DELETE)) ||
(IsClient() && parse->PlayerHasQuestSub(EVENT_ENTITY_VARIABLE_DELETE)) ||
(IsNPC() && parse->HasQuestSub(GetNPCTypeID(), EVENT_ENTITY_VARIABLE_DELETE))
) {
for (const auto& e : m_EntityVariables) { for (const auto& e : m_EntityVariables) {
std::vector<std::any> args = { e.first, e.second }; std::vector<std::any> args = { e.first, e.second };
if (IsBot()) { parse->EventMob(EVENT_ENTITY_VARIABLE_DELETE, this, nullptr, [&]() { return ""; }, 0, &args);
parse->EventBot(EVENT_ENTITY_VARIABLE_DELETE, CastToBot(), nullptr, "", 0, &args);
} else if (IsClient()) {
parse->EventPlayer(EVENT_ENTITY_VARIABLE_DELETE, CastToClient(), "", 0, &args);
} else if (IsNPC()) {
parse->EventNPC(EVENT_ENTITY_VARIABLE_DELETE, CastToNPC(), nullptr, "", 0, &args);
}
}
} }
m_EntityVariables.clear(); m_EntityVariables.clear();
@@ -5749,23 +5714,10 @@ bool Mob::DeleteEntityVariable(std::string variable_name)
return false; return false;
} }
m_EntityVariables.erase(v);
if (
(IsBot() && parse->BotHasQuestSub(EVENT_ENTITY_VARIABLE_DELETE)) ||
(IsClient() && parse->PlayerHasQuestSub(EVENT_ENTITY_VARIABLE_DELETE)) ||
(IsNPC() && parse->HasQuestSub(GetNPCTypeID(), EVENT_ENTITY_VARIABLE_DELETE))
) {
std::vector<std::any> args = { v->first, v->second }; std::vector<std::any> args = { v->first, v->second };
parse->EventMob(EVENT_ENTITY_VARIABLE_DELETE, this, nullptr, [&]() { return ""; }, 0, &args);
if (IsBot()) { m_EntityVariables.erase(v);
parse->EventBot(EVENT_ENTITY_VARIABLE_DELETE, CastToBot(), nullptr, "", 0, &args);
} else if (IsClient()) {
parse->EventPlayer(EVENT_ENTITY_VARIABLE_DELETE, CastToClient(), "", 0, &args);
} else if (IsNPC()) {
parse->EventNPC(EVENT_ENTITY_VARIABLE_DELETE, CastToNPC(), nullptr, "", 0, &args);
}
}
return true; return true;
} }
@@ -5813,32 +5765,16 @@ void Mob::SetEntityVariable(std::string variable_name, std::string variable_valu
return; return;
} }
const QuestEventID event_id = (
!EntityVariableExists(variable_name) ?
EVENT_ENTITY_VARIABLE_SET :
EVENT_ENTITY_VARIABLE_UPDATE
);
if (
(IsBot() && parse->BotHasQuestSub(event_id)) ||
(IsClient() && parse->PlayerHasQuestSub(event_id)) ||
(IsNPC() && parse->HasQuestSub(GetNPCTypeID(), event_id))
) {
std::vector<std::any> args; std::vector<std::any> args;
if (event_id != EVENT_ENTITY_VARIABLE_UPDATE) { if (!EntityVariableExists(variable_name)) {
args = { variable_name, variable_value }; args = { variable_name, variable_value };
parse->EventMob(EVENT_ENTITY_VARIABLE_SET, this, nullptr, [&]() { return ""; }, 0, &args);
} else { } else {
args = { variable_name, GetEntityVariable(variable_name), variable_value }; args = { variable_name, GetEntityVariable(variable_name), variable_value };
}
if (IsBot()) { parse->EventMob(EVENT_ENTITY_VARIABLE_UPDATE, this, nullptr, [&]() { return ""; }, 0, &args);
parse->EventBot(event_id, CastToBot(), nullptr, "", 0, &args);
} else if (IsClient()) {
parse->EventPlayer(event_id, CastToClient(), "", 0, &args);
} else if (IsNPC()) {
parse->EventNPC(event_id, CastToNPC(), nullptr, "", 0, &args);
}
} }
m_EntityVariables[variable_name] = variable_value; m_EntityVariables[variable_name] = variable_value;
+1
View File
@@ -447,6 +447,7 @@ public:
void BuffFadeBySlot(int slot, bool iRecalcBonuses = true); void BuffFadeBySlot(int slot, bool iRecalcBonuses = true);
void BuffFadeDetrimentalByCaster(Mob *caster); void BuffFadeDetrimentalByCaster(Mob *caster);
void BuffFadeBySitModifier(); void BuffFadeBySitModifier();
void BuffFadeSongs();
void BuffDetachCaster(Mob *caster); void BuffDetachCaster(Mob *caster);
bool IsAffectedByBuffByGlobalGroup(GlobalGroup group); bool IsAffectedByBuffByGlobalGroup(GlobalGroup group);
void BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration); void BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration);
+4 -16
View File
@@ -1755,6 +1755,8 @@ void Mob::AI_Event_Engaged(Mob *attacker, bool yell_for_help)
SetAppearance(eaStanding); SetAppearance(eaStanding);
parse->EventBotMerc(EVENT_COMBAT, this, attacker, [&] { return "1"; });
if (IsNPC()) { if (IsNPC()) {
CastToNPC()->AIautocastspell_timer->Start(300, false); CastToNPC()->AIautocastspell_timer->Start(300, false);
@@ -1793,12 +1795,6 @@ void Mob::AI_Event_Engaged(Mob *attacker, bool yell_for_help)
} }
} }
} }
if (IsBot()) {
if (parse->BotHasQuestSub(EVENT_COMBAT)) {
parse->EventBot(EVENT_COMBAT, CastToBot(), attacker, "1", 0);
}
}
} }
// Note: Hate list may not be actually clear until after this function call completes // Note: Hate list may not be actually clear until after this function call completes
@@ -1819,15 +1815,12 @@ void Mob::AI_Event_NoLongerEngaged() {
StopNavigation(); StopNavigation();
ClearRampage(); ClearRampage();
parse->EventBotMercNPC(EVENT_COMBAT, this, nullptr, [&]() { return "0"; });
if (IsNPC()) { if (IsNPC()) {
SetPrimaryAggro(false); SetPrimaryAggro(false);
SetAssistAggro(false); SetAssistAggro(false);
if (CastToNPC()->GetCombatEvent() && GetHP() > 0) { if (CastToNPC()->GetCombatEvent() && GetHP() > 0) {
if (entity_list.GetNPCByID(GetID())) {
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_COMBAT)) {
parse->EventNPC(EVENT_COMBAT, CastToNPC(), nullptr, "0", 0);
}
const uint32 emote_id = CastToNPC()->GetEmoteID(); const uint32 emote_id = CastToNPC()->GetEmoteID();
if (emote_id) { if (emote_id) {
CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::LeaveCombat, emote_id); CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::LeaveCombat, emote_id);
@@ -1837,11 +1830,6 @@ void Mob::AI_Event_NoLongerEngaged() {
CastToNPC()->SetCombatEvent(false); CastToNPC()->SetCombatEvent(false);
} }
} }
} else if (IsBot()) {
if (parse->BotHasQuestSub(EVENT_COMBAT)) {
parse->EventBot(EVENT_COMBAT, CastToBot(), nullptr, "0", 0);
}
}
} }
//this gets called from InterruptSpell() for failure or SpellFinished() for success //this gets called from InterruptSpell() for failure or SpellFinished() for success
+245 -36
View File
@@ -833,23 +833,11 @@ void NPC::Depop(bool start_spawn_timer) {
DoNPCEmote(EQ::constants::EmoteEventTypes::OnDespawn, emoteid); DoNPCEmote(EQ::constants::EmoteEventTypes::OnDespawn, emoteid);
} }
if (IsNPC()) { parse->EventBotMercNPC(EVENT_DESPAWN, this, nullptr);
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DESPAWN)) {
parse->EventNPC(EVENT_DESPAWN, this, nullptr, "", 0);
}
if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DESPAWN_ZONE)) { if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DESPAWN_ZONE)) {
DispatchZoneControllerEvent(EVENT_DESPAWN_ZONE, this, "", 0, nullptr); DispatchZoneControllerEvent(EVENT_DESPAWN_ZONE, this, "", 0, nullptr);
} }
} else if (IsBot()) {
if (parse->BotHasQuestSub(EVENT_DESPAWN)) {
parse->EventBot(EVENT_DESPAWN, CastToBot(), nullptr, "", 0);
}
if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DESPAWN_ZONE)) {
DispatchZoneControllerEvent(EVENT_DESPAWN_ZONE, this, "", 0, nullptr);
}
}
p_depop = true; p_depop = true;
if (respawn2) { if (respawn2) {
@@ -2917,32 +2905,253 @@ void NPC::DoNPCEmote(uint8 event_, uint32 emote_id, Mob* t)
bool NPC::CanTalk() bool NPC::CanTalk()
{ {
//Races that should be able to talk. (Races up to Titanium) switch (GetRace()) {
case Race::Human:
uint16 TalkRace[473] = case Race::Barbarian:
{1,2,3,4,5,6,7,8,9,10,11,12,0,0,15,16,0,18,19,20,0,0,23,0,25,0,0,0,0,0,0, case Race::Erudite:
32,0,0,0,0,0,0,39,40,0,0,0,44,0,0,0,0,49,0,51,0,53,54,55,56,57,58,0,0,0, case Race::WoodElf:
62,0,64,65,66,67,0,0,70,71,0,0,0,0,0,77,78,79,0,81,82,0,0,0,86,0,0,0,90, case Race::HighElf:
0,92,93,94,95,0,0,98,99,0,101,0,103,0,0,0,0,0,0,110,111,112,0,0,0,0,0,0, case Race::DarkElf:
0,0,0,0,123,0,0,126,0,128,0,130,131,0,0,0,0,136,137,0,139,140,0,0,0,144, case Race::HalfElf:
0,0,0,0,0,150,151,152,153,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, case Race::Dwarf:
0,0,0,0,0,0,183,184,0,0,187,188,189,0,0,0,0,0,195,196,0,198,0,0,0,202,0, case Race::Troll:
0,205,0,0,208,0,0,0,0,0,0,0,0,217,0,219,0,0,0,0,0,0,226,0,0,229,230,0,0, case Race::Ogre:
0,0,235,236,0,238,239,240,241,242,243,244,0,246,247,0,0,0,251,0,0,254,255, case Race::Halfling:
256,257,0,0,0,0,0,0,0,0,266,267,0,0,270,271,0,0,0,0,0,277,278,0,0,0,0,283, case Race::Gnome:
284,0,286,0,288,289,290,0,0,0,0,295,296,297,298,299,300,0,0,0,304,0,0,0,0, case Race::Werewolf:
0,0,0,0,0,0,0,0,0,0,0,320,0,322,323,324,325,0,0,0,0,330,331,332,333,334,335, case Race::Brownie:
336,337,338,339,340,341,342,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,359,360,361,362, case Race::Centaur:
0,364,365,366,0,368,369,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,385,386,0,0,0,0,0,392, case Race::Giant:
393,394,395,396,397,398,0,400,402,0,0,0,0,406,0,408,0,0,411,0,413,0,0,0,417, case Race::Trakanon:
0,0,420,0,0,0,0,425,0,0,0,0,0,0,0,433,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, case Race::VenrilSathir:
0,0,0,0,0,458,0,0,0,0,0,0,0,0,467,0,0,470,0,0,473}; case Race::Kerran:
case Race::Fairy:
if (TalkRace[GetRace() - 1] > 0) case Race::Ghost:
case Race::Gnoll:
case Race::Goblin:
case Race::FreeportGuard:
case Race::LavaDragon:
case Race::LizardMan:
case Race::Minotaur:
case Race::Orc:
case Race::HumanBeggar:
case Race::Pixie:
case Race::Drachnid:
case Race::SolusekRo:
case Race::Tunare:
case Race::Treant:
case Race::Vampire:
case Race::StatueOfRallosZek:
case Race::HighpassCitizen:
case Race::Zombie:
case Race::QeynosCitizen:
case Race::NeriakCitizen:
case Race::EruditeCitizen:
case Race::Bixie:
case Race::RivervaleCitizen:
case Race::Scarecrow:
case Race::Sphinx:
case Race::HalasCitizen:
case Race::GrobbCitizen:
case Race::OggokCitizen:
case Race::KaladimCitizen:
case Race::CazicThule:
case Race::ElfVampire:
case Race::Denizen:
case Race::Efreeti:
case Race::PhinigelAutropos:
case Race::Mermaid:
case Race::Harpy:
case Race::Fayguard:
case Race::Innoruuk:
case Race::Djinn:
case Race::InvisibleMan:
case Race::Iksar:
case Race::VahShir:
case Race::Sarnak:
case Race::Xalgoz:
case Race::Yeti:
case Race::IksarCitizen:
case Race::ForestGiant:
case Race::Burynai:
case Race::Erollisi:
case Race::Tribunal:
case Race::Bertoxxulous:
case Race::Bristlebane:
case Race::Ratman:
case Race::Coldain:
case Race::VeliousDragon:
case Race::Siren:
case Race::FrostGiant:
case Race::StormGiant:
case Race::BlackAndWhiteDragon:
case Race::GhostDragon:
case Race::PrismaticDragon:
case Race::Grimling:
case Race::KhatiSha:
case Race::Vampire2:
case Race::Shissar:
case Race::VampireVolatalis:
case Race::Shadel:
case Race::Netherbian:
case Race::Akhevan:
case Race::Wretch:
case Race::LordInquisitorSeru:
case Race::VahShirKing:
case Race::VahShirGuard:
case Race::TeleportMan:
case Race::Werewolf2:
case Race::Nymph:
case Race::Dryad:
case Race::Treant2:
case Race::TarewMarr:
case Race::SolusekRo2:
case Race::GuardOfJustice:
case Race::SolusekRoGuard:
case Race::BertoxxulousNew:
case Race::TribunalNew:
case Race::TerrisThule:
case Race::KnightOfPestilence:
case Race::Lepertoloth:
case Race::Pusling:
case Race::WaterMephit:
case Race::NightmareGoblin:
case Race::Karana:
case Race::Saryrn:
case Race::FenninRo:
case Race::SoulDevourer:
case Race::NewRallosZek:
case Race::VallonZek:
case Race::TallonZek:
case Race::AirMephit:
case Race::EarthMephit:
case Race::FireMephit:
case Race::NightmareMephit:
case Race::Zebuxoruk:
case Race::MithanielMarr:
case Race::UndeadKnight:
case Race::Rathe:
case Race::Xegony:
case Race::Fiend:
case Race::Quarm:
case Race::Efreeti2:
case Race::Valorian2:
case Race::AnimatedArmor:
case Race::UndeadFootman:
case Race::RallosOgre:
case Race::Froglok2:
case Race::TrollCrewMember:
case Race::PirateDeckhand:
case Race::BrokenSkullPirate:
case Race::PirateGhost:
case Race::OneArmedPirate:
case Race::SpiritmasterNadox:
case Race::BrokenSkullTaskmaster:
case Race::GnomePirate:
case Race::DarkElfPirate:
case Race::OgrePirate:
case Race::HumanPirate:
case Race::EruditePirate:
case Race::UndeadVampire:
case Race::Vampire3:
case Race::RujarkianOrc:
case Race::BoneGolem:
case Race::SandElf:
case Race::MasterVampire:
case Race::MasterOrc:
case Race::Mummy:
case Race::NewGoblin:
case Race::Nihil:
case Race::Trusik:
case Race::Ukun:
case Race::Ixt:
case Race::Ikaav:
case Race::Aneuk:
case Race::Kyv:
case Race::Noc:
case Race::Ratuk:
case Race::Huvul:
case Race::Mastruq:
case Race::MataMuram:
case Race::Succubus:
case Race::Pyrilen:
case Race::Dragorn:
case Race::Gelidran:
case Race::Minotaur2:
case Race::CrystalShard:
case Race::Goblin2:
case Race::Giant2:
case Race::Orc2:
case Race::Werewolf3:
case Race::Shiliskin:
case Race::Minotaur3:
case Race::Fairy2:
case Race::Bolvirk:
case Race::Elddar:
case Race::ForestGiant2:
case Race::BoneGolem2:
case Race::Scrykin:
case Race::Treant3:
case Race::Vampire4:
case Race::AyonaeRo:
case Race::SullonZek:
case Race::Bixie2:
case Race::Centaur2:
case Race::Drakkin:
case Race::Giant3:
case Race::Gnoll2:
case Race::GiantShade:
case Race::Harpy2:
case Race::Satyr:
case Race::Dynleth:
case Race::Kedge:
case Race::Kerran2:
case Race::Shissar2:
case Race::Siren2:
case Race::Sphinx2:
case Race::Human2:
case Race::Brownie2:
case Race::Exoskeleton:
case Race::Minotaur4:
case Race::Scarecrow2:
case Race::Wereorc:
case Race::ElvenGhost:
case Race::HumanGhost:
case Race::Burynai2:
case Race::Dracolich:
case Race::IksarGhost:
case Race::Mephit:
case Race::Sarnak2:
case Race::Gnoll3:
case Race::GodOfDiscord:
case Race::Ogre2:
case Race::Giant4:
case Race::Apexus:
case Race::Bellikos:
case Race::BrellsFirstCreation:
case Race::Brell:
case Race::Coldain2:
case Race::Coldain3:
case Race::Telmira:
case Race::MorellThule:
case Race::Amygdalan:
case Race::Sandman:
case Race::RoyalGuard:
case Race::CazicThule2:
case Race::Erudite2:
case Race::Alaran:
case Race::AlaranGhost:
case Race::Ratman2:
case Race::Akheva:
case Race::Luclin:
case Race::Luclin2:
case Race::Luclin3:
case Race::Luclin4:
return true; return true;
default:
return false; return false;
} }
}
//this is called with 'this' as the mob being looked at, and //this is called with 'this' as the mob being looked at, and
//iOther the mob who is doing the looking. It should figure out //iOther the mob who is doing the looking. It should figure out
-53
View File
@@ -1,53 +0,0 @@
#ifndef EQEMU_ZONE_PCH_H
#define EQEMU_ZONE_PCH_H
#include "../quest_parser_collection.h"
#include "../mob.h"
#include "../npc.h"
#include "../corpse.h"
#include "../doors.h"
#include "../bot.h"
#include "../entity.h"
#include "../client.h"
#include "../zone.h"
// perl
#include "../embperl.h"
// lua
#include "lua.hpp"
#include <luabind/luabind.hpp>
#include <luabind/object.hpp>
#include <luabind/class.hpp>
#include "../lua_object.h"
#include "../lua_spell.h"
#include "../lua_item.h"
#include "../lua_bit.h"
#include "../lua_mob.h"
#include "../lua_packet.h"
#include "../lua_npc.h"
#include "../lua_expedition.h"
#include "../lua_mod.h"
#include "../lua_inventory.h"
#include "../lua_encounter.h"
#include "../lua_raid.h"
#include "../lua_client.h"
#include "../lua_bot.h"
#include "../lua_general.h"
#include "../lua_entity.h"
#include "../lua_ptr.h"
#include "../lua_spawn.h"
#include "../lua_iteminst.h"
#include "../lua_group.h"
#include "../lua_hate_list.h"
#include "../lua_corpse.h"
#include "../lua_buff.h"
#include "../lua_entity_list.h"
#include "../lua_parser.h"
#include "../lua_door.h"
#include "../lua_parser_events.h"
#include "../lua_stat_bonuses.h"
#endif //EQEMU_ZONE_PCH_H
+6
View File
@@ -3207,6 +3207,11 @@ void Perl_Client_AreaTaunt(Client* self, float range, int bonus_hate)
entity_list.AETaunt(self, range, bonus_hate); entity_list.AETaunt(self, range, bonus_hate);
} }
Merc* Perl_Client_GetMerc(Client* self)
{
return self->GetMerc();
}
void perl_register_client() void perl_register_client()
{ {
perl::interpreter perl(PERL_GET_THX); perl::interpreter perl(PERL_GET_THX);
@@ -3438,6 +3443,7 @@ void perl_register_client()
package.add("GetLearnedDisciplines", &Perl_Client_GetLearnedDisciplines); package.add("GetLearnedDisciplines", &Perl_Client_GetLearnedDisciplines);
package.add("GetLockoutExpeditionUUID", &Perl_Client_GetLockoutExpeditionUUID); package.add("GetLockoutExpeditionUUID", &Perl_Client_GetLockoutExpeditionUUID);
package.add("GetMaxEndurance", &Perl_Client_GetMaxEndurance); package.add("GetMaxEndurance", &Perl_Client_GetMaxEndurance);
package.add("GetMerc", &Perl_Client_GetMerc);
package.add("GetMemmedSpells", &Perl_Client_GetMemmedSpells); package.add("GetMemmedSpells", &Perl_Client_GetMemmedSpells);
package.add("GetModCharacterFactionLevel", &Perl_Client_GetModCharacterFactionLevel); package.add("GetModCharacterFactionLevel", &Perl_Client_GetModCharacterFactionLevel);
package.add("GetMoney", &Perl_Client_GetMoney); package.add("GetMoney", &Perl_Client_GetMoney);
+40
View File
@@ -739,6 +739,44 @@ void Perl_EntityList_MassGroupBuff(EntityList* self, Mob* caster, Mob* center, u
self->MassGroupBuff(caster, center, spell_id, affect_caster); self->MassGroupBuff(caster, center, spell_id, affect_caster);
} }
perl::array Perl_EntityList_GetNPCsByExcludedIDs(EntityList* self, perl::array npc_ids)
{
std::vector<uint32> ids;
for (int i = 0; i < npc_ids.size(); i++) {
ids.emplace_back(npc_ids[i]);
}
const auto& l = self->GetExcludedNPCsByIDs(ids);
perl::array npcs;
for (const auto& e : l) {
npcs.push_back(e);
}
return npcs;
}
perl::array Perl_EntityList_GetNPCsByIDs(EntityList* self, perl::array npc_ids)
{
std::vector<uint32> ids;
for (int i = 0; i < npc_ids.size(); i++) {
ids.emplace_back(npc_ids[i]);
}
const auto& l = self->GetNPCsByIDs(ids);
perl::array npcs;
for (const auto& e : l) {
npcs.push_back(e);
}
return npcs;
}
void perl_register_entitylist() void perl_register_entitylist()
{ {
perl::interpreter perl(PERL_GET_THX); perl::interpreter perl(PERL_GET_THX);
@@ -804,6 +842,8 @@ void perl_register_entitylist()
package.add("GetNPCByNPCTypeID", &Perl_EntityList_GetNPCByNPCTypeID); package.add("GetNPCByNPCTypeID", &Perl_EntityList_GetNPCByNPCTypeID);
package.add("GetNPCBySpawnID", &Perl_EntityList_GetNPCBySpawnID); package.add("GetNPCBySpawnID", &Perl_EntityList_GetNPCBySpawnID);
package.add("GetNPCList", &Perl_EntityList_GetNPCList); package.add("GetNPCList", &Perl_EntityList_GetNPCList);
package.add("GetNPCsByExcludedIDs", &Perl_EntityList_GetNPCsByExcludedIDs);
package.add("GetNPCsByIDs", &Perl_EntityList_GetNPCsByIDs);
package.add("GetObjectByDBID", &Perl_EntityList_GetObjectByDBID); package.add("GetObjectByDBID", &Perl_EntityList_GetObjectByDBID);
package.add("GetObjectByID", &Perl_EntityList_GetObjectByID); package.add("GetObjectByID", &Perl_EntityList_GetObjectByID);
package.add("GetObjectList", &Perl_EntityList_GetObjectList); package.add("GetObjectList", &Perl_EntityList_GetObjectList);
+195
View File
@@ -0,0 +1,195 @@
#include "../common/features.h"
#ifdef EMBPERL_XS_CLASSES
#include "../common/global_define.h"
#include "embperl.h"
#include "merc.h"
uint32 Perl_Merc_GetCostFormula(Merc* self)
{
return self->GetCostFormula();
}
Group* Perl_Merc_GetGroup(Merc* self)
{
return self->GetGroup();
}
int Perl_Merc_GetHatedCount(Merc* self)
{
return self->GetHatedCount();
}
float Perl_Merc_GetMaxMeleeRangeToTarget(Merc* self, Mob* target)
{
return self->GetMaxMeleeRangeToTarget(target);
}
uint32 Perl_Merc_GetMercenaryCharacterID(Merc* self)
{
return self->GetMercenaryCharacterID();
}
uint32 Perl_Merc_GetMercenaryID(Merc* self)
{
return self->GetMercenaryID();
}
uint32 Perl_Merc_GetMercenaryNameType(Merc* self)
{
return self->GetMercNameType();
}
Client* Perl_Merc_GetMercenaryOwner(Merc* self)
{
return self->GetMercenaryOwner();
}
uint32 Perl_Merc_GetMercenarySubtype(Merc* self)
{
return self->GetMercenarySubType();
}
uint32 Perl_Merc_GetMercenaryTemplateID(Merc* self)
{
return self->GetMercenaryTemplateID();
}
uint32 Perl_Merc_GetMercenaryType(Merc* self)
{
return self->GetMercenaryType();
}
Mob* Perl_Merc_GetOwner(Merc* self)
{
return self->GetOwner();
}
Mob* Perl_Merc_GetOwnerOrSelf(Merc* self)
{
return self->GetOwnerOrSelf();
}
uint8 Perl_Merc_GetProficiencyID(Merc* self)
{
return self->GetProficiencyID();
}
uint8 Perl_Merc_GetStance(Merc* self)
{
return self->GetStance();
}
uint8 Perl_Merc_GetTierID(Merc* self)
{
return self->GetTierID();
}
bool Perl_Merc_HasOrMayGetAggro(Merc* self)
{
return self->HasOrMayGetAggro();
}
bool Perl_Merc_IsMercenaryCaster(Merc* self)
{
return self->IsMercCaster();
}
bool Perl_Merc_IsMercenaryCasterCombatRange(Merc* self, Mob* target)
{
return self->IsMercCasterCombatRange(target);
}
bool Perl_Merc_IsSitting(Merc* self)
{
return self->IsSitting();
}
bool Perl_Merc_IsStanding(Merc* self)
{
return self->IsStanding();
}
void Perl_Merc_ScaleStats(Merc* self, int scale_percentage)
{
self->ScaleStats(scale_percentage);
}
void Perl_Merc_ScaleStats(Merc* self, int scale_percentage, bool set_to_max)
{
self->ScaleStats(scale_percentage, set_to_max);
}
void Perl_Merc_SendPayload(Merc* self, int payload_id, std::string payload_value)
{
self->SendPayload(payload_id, payload_value);
}
void Perl_Merc_SetTarget(Merc* self, Mob* target)
{
self->SetTarget(target);
}
void Perl_Merc_Signal(Merc* self, int signal_id)
{
self->Signal(signal_id);
}
void Perl_Merc_Sit(Merc* self)
{
self->Sit();
}
void Perl_Merc_Stand(Merc* self)
{
self->Stand();
}
bool Perl_Merc_Suspend(Merc* self)
{
return self->Suspend();
}
bool Perl_Merc_UseDiscipline(Merc* self, uint16 spell_id, uint16 target_id)
{
return self->UseDiscipline(spell_id, target_id);
}
void perl_register_merc()
{
perl::interpreter state(PERL_GET_THX);
auto package = state.new_class<Merc>("Merc");
package.add_base_class("NPC");
package.add("GetCostFormula", &Perl_Merc_GetCostFormula);
package.add("GetGroup", &Perl_Merc_GetGroup);
package.add("GetHatedCount", &Perl_Merc_GetHatedCount);
package.add("GetMaxMeleeRangeToTarget", &Perl_Merc_GetMaxMeleeRangeToTarget);
package.add("GetMercenaryCharacterID", &Perl_Merc_GetMercenaryCharacterID);
package.add("GetMercenaryID", &Perl_Merc_GetMercenaryID);
package.add("GetMercenaryNameType", &Perl_Merc_GetMercenaryNameType);
package.add("GetMercenaryOwner", &Perl_Merc_GetMercenaryOwner);
package.add("GetMercenarySubtype", &Perl_Merc_GetMercenarySubtype);
package.add("GetMercenaryTemplateID", &Perl_Merc_GetMercenaryTemplateID);
package.add("GetMercenaryType", &Perl_Merc_GetMercenaryType);
package.add("GetOwner", &Perl_Merc_GetOwner);
package.add("GetOwnerOrSelf", &Perl_Merc_GetOwnerOrSelf);
package.add("GetProficiencyID", &Perl_Merc_GetProficiencyID);
package.add("GetStance", &Perl_Merc_GetStance);
package.add("GetTierID", &Perl_Merc_GetTierID);
package.add("HasOrMayGetAggro", &Perl_Merc_HasOrMayGetAggro);
package.add("IsMercenaryCaster", &Perl_Merc_IsMercenaryCaster);
package.add("IsMercenaryCasterCombatRange", &Perl_Merc_IsMercenaryCasterCombatRange);
package.add("IsSitting", &Perl_Merc_IsSitting);
package.add("IsStanding", &Perl_Merc_IsStanding);
package.add("ScaleStats", (void(*)(Merc*, int))&Perl_Merc_ScaleStats);
package.add("ScaleStats", (void(*)(Merc*, int, bool))&Perl_Merc_ScaleStats);
package.add("SendPayload", &Perl_Merc_SendPayload);
package.add("SetTarget", &Perl_Merc_SetTarget);
package.add("Signal", &Perl_Merc_Signal);
package.add("Sit", &Perl_Merc_Sit);
package.add("Stand", &Perl_Merc_Stand);
package.add("Suspend", &Perl_Merc_Suspend);
package.add("UseDiscipline", &Perl_Merc_UseDiscipline);
}
#endif //EMBPERL_XS_CLASSES
+30
View File
@@ -3543,6 +3543,31 @@ void Perl_Mob_MassGroupBuff(Mob* self, Mob* center, uint16 spell_id, bool affect
entity_list.MassGroupBuff(self, center, spell_id, affect_caster); entity_list.MassGroupBuff(self, center, spell_id, affect_caster);
} }
void Perl_Mob_BuffFadeBeneficial(Mob* self)
{
self->BuffFadeBeneficial();
}
void Perl_Mob_BuffFadeDetrimental(Mob* self)
{
self->BuffFadeDetrimental();
}
void Perl_Mob_BuffFadeDetrimentalByCaster(Mob* self, Mob* caster)
{
self->BuffFadeDetrimentalByCaster(caster);
}
void Perl_Mob_BuffFadeNonPersistDeath(Mob* self)
{
self->BuffFadeNonPersistDeath();
}
void Perl_Mob_BuffFadeSongs(Mob* self)
{
self->BuffFadeSongs();
}
void perl_register_mob() void perl_register_mob()
{ {
perl::interpreter perl(PERL_GET_THX); perl::interpreter perl(PERL_GET_THX);
@@ -3578,11 +3603,16 @@ void perl_register_mob()
package.add("BuffCount", (uint32(*)(Mob*, bool))&Perl_Mob_BuffCount); package.add("BuffCount", (uint32(*)(Mob*, bool))&Perl_Mob_BuffCount);
package.add("BuffCount", (uint32(*)(Mob*, bool, bool))&Perl_Mob_BuffCount); package.add("BuffCount", (uint32(*)(Mob*, bool, bool))&Perl_Mob_BuffCount);
package.add("BuffFadeAll", &Perl_Mob_BuffFadeAll); package.add("BuffFadeAll", &Perl_Mob_BuffFadeAll);
package.add("BuffFadeBeneficial", &Perl_Mob_BuffFadeBeneficial);
package.add("BuffFadeByEffect", (void(*)(Mob*, int))&Perl_Mob_BuffFadeByEffect); package.add("BuffFadeByEffect", (void(*)(Mob*, int))&Perl_Mob_BuffFadeByEffect);
package.add("BuffFadeByEffect", (void(*)(Mob*, int, int))&Perl_Mob_BuffFadeByEffect); package.add("BuffFadeByEffect", (void(*)(Mob*, int, int))&Perl_Mob_BuffFadeByEffect);
package.add("BuffFadeBySlot", (void(*)(Mob*, int))&Perl_Mob_BuffFadeBySlot); package.add("BuffFadeBySlot", (void(*)(Mob*, int))&Perl_Mob_BuffFadeBySlot);
package.add("BuffFadeBySlot", (void(*)(Mob*, int, bool))&Perl_Mob_BuffFadeBySlot); package.add("BuffFadeBySlot", (void(*)(Mob*, int, bool))&Perl_Mob_BuffFadeBySlot);
package.add("BuffFadeBySpellID", &Perl_Mob_BuffFadeBySpellID); package.add("BuffFadeBySpellID", &Perl_Mob_BuffFadeBySpellID);
package.add("BuffFadeDetrimental", &Perl_Mob_BuffFadeDetrimental);
package.add("BuffFadeDetrimentalByCaster", &Perl_Mob_BuffFadeDetrimentalByCaster);
package.add("BuffFadeNonPersistDeath", &Perl_Mob_BuffFadeNonPersistDeath);
package.add("BuffFadeSongs", &Perl_Mob_BuffFadeSongs);
package.add("CalculateDistance", (float(*)(Mob*, float, float, float))&Perl_Mob_CalculateDistance); package.add("CalculateDistance", (float(*)(Mob*, float, float, float))&Perl_Mob_CalculateDistance);
package.add("CalculateDistance", (float(*)(Mob*, Mob*))&Perl_Mob_CalculateDistance); package.add("CalculateDistance", (float(*)(Mob*, Mob*))&Perl_Mob_CalculateDistance);
package.add("CalculateHeadingToTarget", &Perl_Mob_CalculateHeadingToTarget); package.add("CalculateHeadingToTarget", &Perl_Mob_CalculateHeadingToTarget);
+48
View File
@@ -139,6 +139,30 @@ public:
return 0; return 0;
} }
virtual int EventMerc(
QuestEventID event_id,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
)
{
return 0;
}
virtual int EventGlobalMerc(
QuestEventID event_id,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
)
{
return 0;
}
virtual bool HasQuestSub(uint32 npc_id, QuestEventID event_id) virtual bool HasQuestSub(uint32 npc_id, QuestEventID event_id)
{ {
return false; return false;
@@ -189,6 +213,16 @@ public:
return false; return false;
} }
virtual bool MercHasQuestSub(QuestEventID event_id)
{
return false;
}
virtual bool GlobalMercHasQuestSub(QuestEventID event_id)
{
return false;
}
virtual void LoadNPCScript(std::string filename, int npc_id) { } virtual void LoadNPCScript(std::string filename, int npc_id) { }
virtual void LoadGlobalNPCScript(std::string filename) { } virtual void LoadGlobalNPCScript(std::string filename) { }
virtual void LoadPlayerScript(std::string filename) { } virtual void LoadPlayerScript(std::string filename) { }
@@ -198,6 +232,8 @@ public:
virtual void LoadEncounterScript(std::string filename, std::string encounter_name) { } virtual void LoadEncounterScript(std::string filename, std::string encounter_name) { }
virtual void LoadBotScript(std::string filename) { } virtual void LoadBotScript(std::string filename) { }
virtual void LoadGlobalBotScript(std::string filename) { } virtual void LoadGlobalBotScript(std::string filename) { }
virtual void LoadMercScript(std::string filename) { }
virtual void LoadGlobalMercScript(std::string filename) { }
virtual int DispatchEventNPC( virtual int DispatchEventNPC(
QuestEventID event_id, QuestEventID event_id,
@@ -260,6 +296,18 @@ public:
return 0; return 0;
} }
virtual int DispatchEventMerc(
QuestEventID event_id,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
)
{
return 0;
}
virtual void AddVar(std::string name, std::string val) { } virtual void AddVar(std::string name, std::string val) { }
virtual std::string GetVar(std::string name) virtual std::string GetVar(std::string name)
{ {
+301
View File
@@ -47,6 +47,8 @@ QuestParserCollection::QuestParserCollection()
_global_npc_quest_status = QuestUnloaded; _global_npc_quest_status = QuestUnloaded;
_bot_quest_status = QuestUnloaded; _bot_quest_status = QuestUnloaded;
_global_bot_quest_status = QuestUnloaded; _global_bot_quest_status = QuestUnloaded;
_merc_quest_status = QuestUnloaded;
_global_merc_quest_status = QuestUnloaded;
} }
QuestParserCollection::~QuestParserCollection() { } QuestParserCollection::~QuestParserCollection() { }
@@ -94,6 +96,8 @@ void QuestParserCollection::ReloadQuests(bool reset_timers)
_global_npc_quest_status = QuestUnloaded; _global_npc_quest_status = QuestUnloaded;
_bot_quest_status = QuestUnloaded; _bot_quest_status = QuestUnloaded;
_global_bot_quest_status = QuestUnloaded; _global_bot_quest_status = QuestUnloaded;
_merc_quest_status = QuestUnloaded;
_global_merc_quest_status = QuestUnloaded;
_spell_quest_status.clear(); _spell_quest_status.clear();
_item_quest_status.clear(); _item_quest_status.clear();
@@ -379,6 +383,49 @@ bool QuestParserCollection::BotHasQuestSub(QuestEventID event_id)
return BotHasQuestSubLocal(event_id) || BotHasQuestSubGlobal(event_id); return BotHasQuestSubLocal(event_id) || BotHasQuestSubGlobal(event_id);
} }
bool QuestParserCollection::MercHasQuestSubLocal(QuestEventID event_id)
{
if (_merc_quest_status == QuestUnloaded) {
std::string filename;
auto qi = GetQIByMercQuest(filename);
if (qi) {
_merc_quest_status = qi->GetIdentifier();
qi->LoadMercScript(filename);
return qi->MercHasQuestSub(event_id);
}
} else if (_merc_quest_status != QuestFailedToLoad) {
auto iter = _interfaces.find(_merc_quest_status);
return iter->second->MercHasQuestSub(event_id);
}
return false;
}
bool QuestParserCollection::MercHasQuestSubGlobal(QuestEventID event_id)
{
if (_global_merc_quest_status == QuestUnloaded) {
std::string filename;
auto qi = GetQIByGlobalMercQuest(filename);
if (qi) {
_global_merc_quest_status = qi->GetIdentifier();
qi->LoadGlobalMercScript(filename);
return qi->GlobalMercHasQuestSub(event_id);
}
} else if (_global_merc_quest_status != QuestFailedToLoad) {
auto iter = _interfaces.find(_global_merc_quest_status);
return iter->second->GlobalMercHasQuestSub(event_id);
}
return false;
}
bool QuestParserCollection::MercHasQuestSub(QuestEventID event_id)
{
return MercHasQuestSubLocal(event_id) || MercHasQuestSubGlobal(event_id);
}
int QuestParserCollection::EventNPC( int QuestParserCollection::EventNPC(
QuestEventID event_id, QuestEventID event_id,
NPC* npc, NPC* npc,
@@ -793,6 +840,86 @@ int QuestParserCollection::EventBotGlobal(
return 0; return 0;
} }
int QuestParserCollection::EventMerc(
QuestEventID event_id,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
)
{
const int local_return = EventMercLocal(event_id, merc, init, data, extra_data, extra_pointers);
const int global_return = EventMercGlobal(event_id, merc, init, data, extra_data, extra_pointers);
const int default_return = DispatchEventMerc(event_id, merc, init, data, extra_data, extra_pointers);
if (local_return != 0) {
return local_return;
} else if (global_return != 0) {
return global_return;
} else if (default_return != 0) {
return default_return;
}
return 0;
}
int QuestParserCollection::EventMercLocal(
QuestEventID event_id,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
)
{
if (_merc_quest_status == QuestUnloaded) {
std::string filename;
auto qi = GetQIByMercQuest(filename);
if (qi) {
_merc_quest_status = qi->GetIdentifier();
qi->LoadMercScript(filename);
return qi->EventMerc(event_id, merc, init, data, extra_data, extra_pointers);
}
} else {
if (_merc_quest_status != QuestFailedToLoad) {
auto iter = _interfaces.find(_merc_quest_status);
return iter->second->EventMerc(event_id, merc, init, data, extra_data, extra_pointers);
}
}
return 0;
}
int QuestParserCollection::EventMercGlobal(
QuestEventID event_id,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
)
{
if (_global_merc_quest_status == QuestUnloaded) {
std::string filename;
auto qi = GetQIByGlobalMercQuest(filename);
if (qi) {
_global_merc_quest_status = qi->GetIdentifier();
qi->LoadGlobalMercScript(filename);
return qi->EventGlobalMerc(event_id, merc, init, data, extra_data, extra_pointers);
}
} else {
if (_global_merc_quest_status != QuestFailedToLoad) {
auto iter = _interfaces.find(_global_merc_quest_status);
return iter->second->EventGlobalMerc(event_id, merc, init, data, extra_data, extra_pointers);
}
}
return 0;
}
QuestInterface* QuestParserCollection::GetQIByNPCQuest(uint32 npc_id, std::string& filename) QuestInterface* QuestParserCollection::GetQIByNPCQuest(uint32 npc_id, std::string& filename)
{ {
if (!zone) { if (!zone) {
@@ -1188,6 +1315,81 @@ QuestInterface* QuestParserCollection::GetQIByGlobalBotQuest(std::string& filena
return nullptr; return nullptr;
} }
QuestInterface* QuestParserCollection::GetQIByMercQuest(std::string& filename)
{
if (!zone || !zone->IsLoaded()) {
return nullptr;
}
const std::string& global_path = fmt::format(
"{}/{}",
path.GetQuestsPath(),
QUEST_GLOBAL_DIRECTORY
);
const std::string& zone_path = fmt::format(
"{}/{}",
path.GetQuestsPath(),
zone->GetShortName()
);
const std::string& zone_versioned_path = fmt::format(
"{}/{}/v{}",
path.GetQuestsPath(),
zone->GetShortName(),
zone->GetInstanceVersion()
);
std::vector<std::string> file_names = {
fmt::format("{}/merc", zone_versioned_path), // Local versioned by Instance Version ./quests/zone/v0/merc.ext
fmt::format("{}/merc_v{}", zone_path, zone->GetInstanceVersion()), // Local by Instance Version
fmt::format("{}/merc", zone_path), // Local
fmt::format("{}/merc", global_path) // Global
};
std::string file_name;
for (auto & file : file_names) {
for (auto* e: _load_precedence) {
file_name = fmt::format(
"{}.{}",
file,
_extensions.find(e->GetIdentifier())->second
);
if (File::Exists(file_name)) {
filename = file_name;
return e;
}
}
}
return nullptr;
}
QuestInterface* QuestParserCollection::GetQIByGlobalMercQuest(std::string& filename)
{
if (!zone) {
return nullptr;
}
std::string file_name;
for (auto* e: _load_precedence) {
file_name = fmt::format(
"{}/{}/global_merc.{}",
path.GetQuestsPath(),
QUEST_GLOBAL_DIRECTORY,
_extensions.find(e->GetIdentifier())->second
);
if (File::Exists(file_name)) {
filename = file_name;
return e;
}
}
return nullptr;
}
void QuestParserCollection::GetErrors(std::list<std::string>& quest_errors) void QuestParserCollection::GetErrors(std::list<std::string>& quest_errors)
{ {
quest_errors.clear(); quest_errors.clear();
@@ -1303,6 +1505,27 @@ int QuestParserCollection::DispatchEventBot(
return ret; return ret;
} }
int QuestParserCollection::DispatchEventMerc(
QuestEventID event_id,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
)
{
int ret = 0;
for (const auto& e: _load_precedence) {
int i = e->DispatchEventMerc(event_id, merc, init, data, extra_data, extra_pointers);
if (i != 0) {
ret = i;
}
}
return ret;
}
void QuestParserCollection::LoadPerlEventExportSettings(PerlEventExportSettings* s) void QuestParserCollection::LoadPerlEventExportSettings(PerlEventExportSettings* s)
{ {
for (int i = 0; i < _LargestEventID; i++) { for (int i = 0; i < _LargestEventID; i++) {
@@ -1325,3 +1548,81 @@ void QuestParserCollection::LoadPerlEventExportSettings(PerlEventExportSettings*
LogInfo("Loaded [{}] Perl Event Export Settings", l.size()); LogInfo("Loaded [{}] Perl Event Export Settings", l.size());
} }
int QuestParserCollection::EventBotMerc(
QuestEventID event_id,
Mob* e,
Mob* init,
std::function<std::string()> lazy_data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
)
{
if (e->IsBot() && BotHasQuestSub(event_id)) {
return EventBot(event_id, e->CastToBot(), init, lazy_data(), extra_data, extra_pointers);
} else if (e->IsMerc() && MercHasQuestSub(event_id)) {
return EventMerc(event_id, e->CastToMerc(), init, lazy_data(), extra_data, extra_pointers);
}
return false; // No quest subscription found
}
int QuestParserCollection::EventMercNPC(
QuestEventID event_id,
Mob* e,
Mob* init,
std::function<std::string()> lazy_data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
)
{
if (e->IsMerc() && MercHasQuestSub(event_id)) {
return EventMerc(event_id, e->CastToMerc(), init, lazy_data(), extra_data, extra_pointers);
} else if (e->IsNPC() && HasQuestSub(e->GetNPCTypeID(), event_id)) {
return EventNPC(event_id, e->CastToNPC(), init, lazy_data(), extra_data, extra_pointers);
}
return false; // No quest subscription found
}
int QuestParserCollection::EventBotMercNPC(
QuestEventID event_id,
Mob* e,
Mob* init,
std::function<std::string()> lazy_data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
)
{
if (e->IsBot() && BotHasQuestSub(event_id)) {
return EventBot(event_id, e->CastToBot(), init, lazy_data(), extra_data, extra_pointers);
} else if (e->IsMerc() && MercHasQuestSub(event_id)) {
return EventMerc(event_id, e->CastToMerc(), init, lazy_data(), extra_data, extra_pointers);
} else if (e->IsNPC() && HasQuestSub(e->GetNPCTypeID(), event_id)) {
return EventNPC(event_id, e->CastToNPC(), init, lazy_data(), extra_data, extra_pointers);
}
return false; // No quest subscription found
}
int QuestParserCollection::EventMob(
QuestEventID event_id,
Mob* e,
Mob* init,
std::function<std::string()> lazy_data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
)
{
if (e->IsClient() && PlayerHasQuestSub(event_id)) {
return EventPlayer(event_id, e->CastToClient(), lazy_data(), extra_data, extra_pointers);
} else if (e->IsBot() && BotHasQuestSub(event_id)) {
return EventBot(event_id, e->CastToBot(), init, lazy_data(), extra_data, extra_pointers);
} else if (e->IsMerc() && MercHasQuestSub(event_id)) {
return EventMerc(event_id, e->CastToMerc(), init, lazy_data(), extra_data, extra_pointers);
} else if (e->IsNPC() && HasQuestSub(e->GetNPCTypeID(), event_id)) {
return EventNPC(event_id, e->CastToNPC(), init, lazy_data(), extra_data, extra_pointers);
}
return false; // No quest subscription found
}
+79
View File
@@ -71,6 +71,7 @@ public:
bool SpellHasQuestSub(uint32 spell_id, QuestEventID event_id); bool SpellHasQuestSub(uint32 spell_id, QuestEventID event_id);
bool ItemHasQuestSub(EQ::ItemInstance* inst, QuestEventID event_id); bool ItemHasQuestSub(EQ::ItemInstance* inst, QuestEventID event_id);
bool BotHasQuestSub(QuestEventID event_id); bool BotHasQuestSub(QuestEventID event_id);
bool MercHasQuestSub(QuestEventID event_id);
int EventNPC( int EventNPC(
QuestEventID event_id, QuestEventID event_id,
@@ -126,6 +127,51 @@ public:
std::vector<std::any> *extra_pointers = nullptr std::vector<std::any> *extra_pointers = nullptr
); );
int EventMerc(
QuestEventID event_id,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers = nullptr
);
int EventBotMerc(
QuestEventID event_id,
Mob* e,
Mob* init,
std::function<std::string()> lazy_data = []() { return ""; },
uint32 extra_data = 0,
std::vector<std::any>* extra_pointers = nullptr
);
int EventMercNPC(
QuestEventID event_id,
Mob* e,
Mob* init,
std::function<std::string()> lazy_data = []() { return ""; },
uint32 extra_data = 0,
std::vector<std::any>* extra_pointers = nullptr
);
int EventBotMercNPC(
QuestEventID event_id,
Mob* e,
Mob* init,
std::function<std::string()> lazy_data = []() { return ""; },
uint32 extra_data = 0,
std::vector<std::any>* extra_pointers = nullptr
);
int EventMob(
QuestEventID event_id,
Mob* e,
Mob* init,
std::function<std::string()> lazy_data = []() { return ""; },
uint32 extra_data = 0,
std::vector<std::any>* extra_pointers = nullptr
);
void GetErrors(std::list<std::string> &quest_errors); void GetErrors(std::list<std::string> &quest_errors);
/* /*
@@ -161,6 +207,8 @@ private:
bool HasEncounterSub(QuestEventID event_id, const std::string& package_name); bool HasEncounterSub(QuestEventID event_id, const std::string& package_name);
bool BotHasQuestSubLocal(QuestEventID event_id); bool BotHasQuestSubLocal(QuestEventID event_id);
bool BotHasQuestSubGlobal(QuestEventID event_id); bool BotHasQuestSubGlobal(QuestEventID event_id);
bool MercHasQuestSubLocal(QuestEventID event_id);
bool MercHasQuestSubGlobal(QuestEventID event_id);
int EventNPCLocal( int EventNPCLocal(
QuestEventID event_id, QuestEventID event_id,
@@ -214,6 +262,24 @@ private:
std::vector<std::any> *extra_pointers std::vector<std::any> *extra_pointers
); );
int EventMercLocal(
QuestEventID event_id,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
);
int EventMercGlobal(
QuestEventID event_id,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
);
QuestInterface* GetQIByNPCQuest(uint32 npc_id, std::string& filename); QuestInterface* GetQIByNPCQuest(uint32 npc_id, std::string& filename);
QuestInterface* GetQIByGlobalNPCQuest(std::string& filename); QuestInterface* GetQIByGlobalNPCQuest(std::string& filename);
QuestInterface* GetQIByPlayerQuest(std::string& filename); QuestInterface* GetQIByPlayerQuest(std::string& filename);
@@ -223,6 +289,8 @@ private:
QuestInterface* GetQIByEncounterQuest(std::string encounter_name, std::string& filename); QuestInterface* GetQIByEncounterQuest(std::string encounter_name, std::string& filename);
QuestInterface* GetQIByBotQuest(std::string& filename); QuestInterface* GetQIByBotQuest(std::string& filename);
QuestInterface* GetQIByGlobalBotQuest(std::string& filename); QuestInterface* GetQIByGlobalBotQuest(std::string& filename);
QuestInterface* GetQIByMercQuest(std::string& filename);
QuestInterface* GetQIByGlobalMercQuest(std::string& filename);
int DispatchEventNPC( int DispatchEventNPC(
QuestEventID event_id, QuestEventID event_id,
@@ -270,6 +338,15 @@ private:
std::vector<std::any>* extra_pointers std::vector<std::any>* extra_pointers
); );
int DispatchEventMerc(
QuestEventID event_id,
Merc* merc,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
);
std::map<uint32, QuestInterface*> _interfaces; std::map<uint32, QuestInterface*> _interfaces;
std::map<uint32, std::string> _extensions; std::map<uint32, std::string> _extensions;
std::list<QuestInterface*> _load_precedence; std::list<QuestInterface*> _load_precedence;
@@ -280,6 +357,8 @@ private:
uint32 _global_player_quest_status; uint32 _global_player_quest_status;
uint32 _bot_quest_status; uint32 _bot_quest_status;
uint32 _global_bot_quest_status; uint32 _global_bot_quest_status;
uint32 _merc_quest_status;
uint32 _global_merc_quest_status;
std::map<uint32, uint32> _spell_quest_status; std::map<uint32, uint32> _spell_quest_status;
std::map<uint32, uint32> _item_quest_status; std::map<uint32, uint32> _item_quest_status;
std::map<std::string, uint32> _encounter_quest_status; std::map<std::string, uint32> _encounter_quest_status;
+79 -224
View File
@@ -90,12 +90,7 @@ void QuestManager::Process() {
while (cur != end) { while (cur != end) {
if (cur->Timer_.Enabled() && cur->Timer_.Check()) { if (cur->Timer_.Enabled() && cur->Timer_.Check()) {
if (cur->mob) { if (cur->mob) {
if (cur->mob->IsNPC()) { if (cur->mob->IsEncounter()) {
if (parse->HasQuestSub(cur->mob->GetNPCTypeID(), EVENT_TIMER)) {
parse->EventNPC(EVENT_TIMER, cur->mob->CastToNPC(), nullptr, cur->name, 0);
}
}
else if (cur->mob->IsEncounter()) {
parse->EventEncounter( parse->EventEncounter(
EVENT_TIMER, EVENT_TIMER,
cur->mob->CastToEncounter()->GetEncounterName(), cur->mob->CastToEncounter()->GetEncounterName(),
@@ -103,17 +98,8 @@ void QuestManager::Process() {
0, 0,
nullptr nullptr
); );
} } else {
else if (cur->mob->IsClient()) { parse->EventMob(EVENT_TIMER, cur->mob, nullptr, [&]() { return cur->name; }, 0);
if (parse->PlayerHasQuestSub(EVENT_TIMER)) {
//this is inheriently unsafe if we ever make it so more than npc/client start timers
parse->EventPlayer(EVENT_TIMER, cur->mob->CastToClient(), cur->name, 0);
}
}
else if (cur->mob->IsBot()) {
if (parse->BotHasQuestSub(EVENT_TIMER)) {
parse->EventBot(EVENT_TIMER, cur->mob->CastToBot(), nullptr, cur->name, 0);
}
} }
//we MUST reset our iterator since the quest could have removed/added any //we MUST reset our iterator since the quest could have removed/added any
@@ -539,32 +525,20 @@ void QuestManager::settimer(const std::string& timer_name, uint32 seconds, Mob*
return; return;
} }
const bool has_start_event = ( std::function<std::string()> f = [&]() {
(mob->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_START)) || return fmt::format(
(mob->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_START)) || "{} {}",
(mob->IsNPC() && parse->HasQuestSub(mob->GetNPCTypeID(), EVENT_TIMER_START)) timer_name,
seconds * 1000
); );
};
if (!QTimerList.empty()) { if (!QTimerList.empty()) {
for (auto& e : QTimerList) { for (auto& e : QTimerList) {
if (e.mob && e.mob == mob && e.name == timer_name) { if (e.mob && e.mob == mob && e.name == timer_name) {
e.Timer_.Start(seconds * 1000, false); e.Timer_.Start(seconds * 1000, false);
if (has_start_event) { parse->EventMob(EVENT_TIMER_START, mob, nullptr, f);
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
seconds * 1000
);
if (mob->IsClient()) {
parse->EventPlayer(EVENT_TIMER_START, mob->CastToClient(), export_string, 0);
} else if (mob->IsBot()) {
parse->EventBot(EVENT_TIMER_START, mob->CastToBot(), nullptr, export_string, 0);
} else if (mob->IsNPC()) {
parse->EventNPC(EVENT_TIMER_START, mob->CastToNPC(), nullptr, export_string, 0);
}
}
return; return;
} }
@@ -573,21 +547,7 @@ void QuestManager::settimer(const std::string& timer_name, uint32 seconds, Mob*
QTimerList.emplace_back(QuestTimer(seconds * 1000, mob, timer_name)); QTimerList.emplace_back(QuestTimer(seconds * 1000, mob, timer_name));
if (has_start_event) { parse->EventMob(EVENT_TIMER_START, mob, nullptr, f);
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
seconds * 1000
);
if (mob->IsClient()) {
parse->EventPlayer(EVENT_TIMER_START, mob->CastToClient(), export_string, 0);
} else if (mob->IsBot()) {
parse->EventBot(EVENT_TIMER_START, mob->CastToBot(), nullptr, export_string, 0);
} else if (mob->IsNPC()) {
parse->EventNPC(EVENT_TIMER_START, mob->CastToNPC(), nullptr, export_string, 0);
}
}
} }
void QuestManager::settimerMS(const std::string& timer_name, uint32 milliseconds) void QuestManager::settimerMS(const std::string& timer_name, uint32 milliseconds)
@@ -598,11 +558,13 @@ void QuestManager::settimerMS(const std::string& timer_name, uint32 milliseconds
return; return;
} }
const bool has_start_event = ( std::function<std::string()> f = [&]() {
(owner->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_START)) || return fmt::format(
(owner->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_START)) || "{} {}",
(owner->IsNPC() && parse->HasQuestSub(owner->GetNPCTypeID(), EVENT_TIMER_START)) timer_name,
milliseconds
); );
};
if (questitem) { if (questitem) {
questitem->SetTimer(timer_name, milliseconds); questitem->SetTimer(timer_name, milliseconds);
@@ -625,21 +587,7 @@ void QuestManager::settimerMS(const std::string& timer_name, uint32 milliseconds
if (e.mob && e.mob == owner && e.name == timer_name) { if (e.mob && e.mob == owner && e.name == timer_name) {
e.Timer_.Start(milliseconds, false); e.Timer_.Start(milliseconds, false);
if (has_start_event) { parse->EventMob(EVENT_TIMER_START, owner, nullptr, f);
const std::string& export_string = fmt::format(
"{} {}",
e.name,
milliseconds
);
if (owner->IsClient()) {
parse->EventPlayer(EVENT_TIMER_START, owner->CastToClient(), export_string, 0);
} else if (owner->IsBot()) {
parse->EventBot(EVENT_TIMER_START, owner->CastToBot(), nullptr, export_string, 0);
} else if (owner->IsNPC()) {
parse->EventNPC(EVENT_TIMER_START, owner->CastToNPC(), nullptr, export_string, 0);
}
}
return; return;
} }
@@ -648,21 +596,7 @@ void QuestManager::settimerMS(const std::string& timer_name, uint32 milliseconds
QTimerList.emplace_back(QuestTimer(milliseconds, owner, timer_name)); QTimerList.emplace_back(QuestTimer(milliseconds, owner, timer_name));
if (has_start_event) { parse->EventMob(EVENT_TIMER_START, owner, nullptr, f);
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
milliseconds
);
if (owner->IsClient()) {
parse->EventPlayer(EVENT_TIMER_START, owner->CastToClient(), export_string, 0);
} else if (owner->IsBot()) {
parse->EventBot(EVENT_TIMER_START, owner->CastToBot(), nullptr, export_string, 0);
} else if (owner->IsNPC()) {
parse->EventNPC(EVENT_TIMER_START, owner->CastToNPC(), nullptr, export_string, 0);
}
}
} }
void QuestManager::settimerMS(const std::string& timer_name, uint32 milliseconds, EQ::ItemInstance* inst) void QuestManager::settimerMS(const std::string& timer_name, uint32 milliseconds, EQ::ItemInstance* inst)
@@ -678,32 +612,20 @@ void QuestManager::settimerMS(const std::string& timer_name, uint32 milliseconds
return; return;
} }
const bool has_start_event = ( std::function<std::string()> f = [&]() {
(m->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_START)) || return fmt::format(
(m->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_START)) || "{} {}",
(m->IsNPC() && parse->HasQuestSub(m->GetNPCTypeID(), EVENT_TIMER_START)) timer_name,
milliseconds
); );
};
if (!QTimerList.empty()) { if (!QTimerList.empty()) {
for (auto& e : QTimerList) { for (auto& e : QTimerList) {
if (e.mob && e.mob == m && e.name == timer_name) { if (e.mob && e.mob == m && e.name == timer_name) {
e.Timer_.Start(milliseconds, false); e.Timer_.Start(milliseconds, false);
if (has_start_event) { parse->EventMob(EVENT_TIMER_START, m, nullptr, f);
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
milliseconds
);
if (m->IsClient()) {
parse->EventPlayer(EVENT_TIMER_START, m->CastToClient(), export_string, 0);
} else if (m->IsBot()) {
parse->EventBot(EVENT_TIMER_START, m->CastToBot(), nullptr, export_string, 0);
} else if (m->IsNPC()) {
parse->EventNPC(EVENT_TIMER_START, m->CastToNPC(), nullptr, export_string, 0);
}
}
return; return;
} }
@@ -712,21 +634,7 @@ void QuestManager::settimerMS(const std::string& timer_name, uint32 milliseconds
QTimerList.emplace_back(QuestTimer(milliseconds, m, timer_name)); QTimerList.emplace_back(QuestTimer(milliseconds, m, timer_name));
if (has_start_event) { parse->EventMob(EVENT_TIMER_START, m, nullptr, f);
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
milliseconds
);
if (m->IsClient()) {
parse->EventPlayer(EVENT_TIMER_START, m->CastToClient(), export_string, 0);
} else if (m->IsBot()) {
parse->EventBot(EVENT_TIMER_START, m->CastToBot(), nullptr, export_string, 0);
} else if (m->IsNPC()) {
parse->EventNPC(EVENT_TIMER_START, m->CastToNPC(), nullptr, export_string, 0);
}
}
} }
void QuestManager::stoptimer(const std::string& timer_name) void QuestManager::stoptimer(const std::string& timer_name)
@@ -751,23 +659,16 @@ void QuestManager::stoptimer(const std::string& timer_name)
return; return;
} }
const bool has_stop_event = (
(owner->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_STOP)) ||
(owner->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_STOP)) ||
(owner->IsNPC() && parse->HasQuestSub(owner->GetNPCTypeID(), EVENT_TIMER_STOP))
);
for (auto e = QTimerList.begin(); e != QTimerList.end(); ++e) { for (auto e = QTimerList.begin(); e != QTimerList.end(); ++e) {
if (e->mob && e->mob == owner && e->name == timer_name) { if (e->mob && e->mob == owner && e->name == timer_name) {
if (has_stop_event) { parse->EventMob(
if (owner->IsClient()) { EVENT_TIMER_STOP,
parse->EventPlayer(EVENT_TIMER_STOP, owner->CastToClient(), timer_name, 0); owner,
} else if (owner->IsBot()) { nullptr,
parse->EventBot(EVENT_TIMER_STOP, owner->CastToBot(), nullptr, timer_name, 0); [&]() {
} else if (owner->IsNPC()) { return timer_name;
parse->EventNPC(EVENT_TIMER_STOP, owner->CastToNPC(), nullptr, timer_name, 0);
}
} }
);
QTimerList.erase(e); QTimerList.erase(e);
break; break;
@@ -792,23 +693,16 @@ void QuestManager::stoptimer(const std::string& timer_name, Mob* m)
return; return;
} }
const bool has_stop_event = (
(m->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_STOP)) ||
(m->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_STOP)) ||
(m->IsNPC() && parse->HasQuestSub(m->GetNPCTypeID(), EVENT_TIMER_STOP))
);
for (auto e = QTimerList.begin(); e != QTimerList.end();) { for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == m) { if (e->mob && e->mob == m) {
if (has_stop_event) { parse->EventMob(
if (m->IsClient()) { EVENT_TIMER_STOP,
parse->EventPlayer(EVENT_TIMER_STOP, m->CastToClient(), e->name, 0); m,
} else if (m->IsBot()) { nullptr,
parse->EventBot(EVENT_TIMER_STOP, m->CastToBot(), nullptr, e->name, 0); [&]() {
} else if (m->IsNPC()) { return timer_name;
parse->EventNPC(EVENT_TIMER_STOP, m->CastToNPC(), nullptr, e->name, 0);
}
} }
);
QTimerList.erase(e); QTimerList.erase(e);
break; break;
@@ -847,23 +741,16 @@ void QuestManager::stopalltimers()
return; return;
} }
const bool has_stop_event = (
(owner->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_STOP)) ||
(owner->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_STOP)) ||
(owner->IsNPC() && parse->HasQuestSub(owner->GetNPCTypeID(), EVENT_TIMER_STOP))
);
for (auto e = QTimerList.begin(); e != QTimerList.end();) { for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == owner) { if (e->mob && e->mob == owner) {
if (has_stop_event) { parse->EventMob(
if (owner->IsClient()) { EVENT_TIMER_STOP,
parse->EventPlayer(EVENT_TIMER_STOP, owner->CastToClient(), e->name, 0); owner,
} else if (owner->IsBot()) { nullptr,
parse->EventBot(EVENT_TIMER_STOP, owner->CastToBot(), nullptr, e->name, 0); [&]() {
} else if (owner->IsNPC()) { return e->name;
parse->EventNPC(EVENT_TIMER_STOP, owner->CastToNPC(), nullptr, e->name, 0);
}
} }
);
e = QTimerList.erase(e); e = QTimerList.erase(e);
} else { } else {
@@ -903,23 +790,16 @@ void QuestManager::stopalltimers(Mob* m)
return; return;
} }
const bool has_stop_event = (
(m->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_STOP)) ||
(m->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_STOP)) ||
(m->IsNPC() && parse->HasQuestSub(m->GetNPCTypeID(), EVENT_TIMER_STOP))
);
for (auto e = QTimerList.begin(); e != QTimerList.end();) { for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == m) { if (e->mob && e->mob == m) {
if (has_stop_event) { parse->EventMob(
if (m->IsClient()) { EVENT_TIMER_STOP,
parse->EventPlayer(EVENT_TIMER_STOP, m->CastToClient(), e->name, 0); m,
} else if (m->IsBot()) { nullptr,
parse->EventBot(EVENT_TIMER_STOP, m->CastToBot(), nullptr, e->name, 0); [&]() {
} else if (m->IsNPC()) { return e->name;
parse->EventNPC(EVENT_TIMER_STOP, m->CastToNPC(), nullptr, e->name, 0);
}
} }
);
e = QTimerList.erase(e); e = QTimerList.erase(e);
} else { } else {
@@ -955,12 +835,6 @@ void QuestManager::pausetimer(const std::string& timer_name, Mob* m)
uint32 milliseconds = 0; uint32 milliseconds = 0;
const bool has_pause_event = (
(mob->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_PAUSE)) ||
(mob->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_PAUSE)) ||
(mob->IsNPC() && parse->HasQuestSub(mob->GetNPCTypeID(), EVENT_TIMER_PAUSE))
);
if (!QTimerList.empty()) { if (!QTimerList.empty()) {
for (auto e = QTimerList.begin(); e != QTimerList.end(); ++e) { for (auto e = QTimerList.begin(); e != QTimerList.end(); ++e) {
if (e->mob && e->mob == mob && e->name == timer_name) { if (e->mob && e->mob == mob && e->name == timer_name) {
@@ -979,21 +853,18 @@ void QuestManager::pausetimer(const std::string& timer_name, Mob* m)
} }
); );
if (has_pause_event) { parse->EventMob(
const std::string& export_string = fmt::format( EVENT_TIMER_PAUSE,
mob,
nullptr,
[&]() {
return fmt::format(
"{} {}", "{} {}",
timer_name, timer_name,
milliseconds milliseconds
); );
if (mob->IsClient()) {
parse->EventPlayer(EVENT_TIMER_PAUSE, mob->CastToClient(), export_string, 0);
} else if (mob->IsBot()) {
parse->EventBot(EVENT_TIMER_PAUSE, mob->CastToBot(), nullptr, export_string, 0);
} else if (mob->IsNPC()) {
parse->EventNPC(EVENT_TIMER_PAUSE, mob->CastToNPC(), nullptr, export_string, 0);
}
} }
);
LogQuests("Pausing timer [{}] for [{}] with [{}] ms remaining", timer_name, owner->GetName(), milliseconds); LogQuests("Pausing timer [{}] for [{}] with [{}] ms remaining", timer_name, owner->GetName(), milliseconds);
} }
@@ -1031,11 +902,13 @@ void QuestManager::resumetimer(const std::string& timer_name, Mob* m)
return; return;
} }
const bool has_resume_event = ( std::function<std::string()> f = [&]() {
(mob->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_RESUME)) || return fmt::format(
(mob->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_RESUME)) || "{} {}",
(mob->IsNPC() && parse->HasQuestSub(mob->GetNPCTypeID(), EVENT_TIMER_RESUME)) timer_name,
milliseconds
); );
};
if (!QTimerList.empty()) { if (!QTimerList.empty()) {
for (auto e : QTimerList) { for (auto e : QTimerList) {
@@ -1049,21 +922,8 @@ void QuestManager::resumetimer(const std::string& timer_name, Mob* m)
milliseconds milliseconds
); );
if (has_resume_event) { parse->EventMob(EVENT_TIMER_RESUME, mob, nullptr, f);
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
milliseconds
);
if (mob->IsClient()) {
parse->EventPlayer(EVENT_TIMER_RESUME, mob->CastToClient(), export_string, 0);
} else if (mob->IsBot()) {
parse->EventBot(EVENT_TIMER_RESUME, mob->CastToBot(), nullptr, export_string, 0);
} else if (mob->IsNPC()) {
parse->EventNPC(EVENT_TIMER_RESUME, mob->CastToNPC(), nullptr, export_string, 0);
}
}
return; return;
} }
} }
@@ -1071,21 +931,7 @@ void QuestManager::resumetimer(const std::string& timer_name, Mob* m)
QTimerList.emplace_back(QuestTimer(milliseconds, m, timer_name)); QTimerList.emplace_back(QuestTimer(milliseconds, m, timer_name));
if (has_resume_event) { parse->EventMob(EVENT_TIMER_RESUME, mob, nullptr, f);
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
milliseconds
);
if (mob->IsClient()) {
parse->EventPlayer(EVENT_TIMER_RESUME, mob->CastToClient(), export_string, 0);
} else if (mob->IsBot()) {
parse->EventBot(EVENT_TIMER_RESUME, mob->CastToBot(), nullptr, export_string, 0);
} else if (mob->IsNPC()) {
parse->EventNPC(EVENT_TIMER_RESUME, mob->CastToNPC(), nullptr, export_string, 0);
}
}
LogQuests( LogQuests(
"Creating a new timer and resuming [{}] for [{}] with [{}] ms remaining", "Creating a new timer and resuming [{}] for [{}] with [{}] ms remaining",
@@ -4213,6 +4059,15 @@ Bot *QuestManager::GetBot() const {
return nullptr; return nullptr;
} }
Merc *QuestManager::GetMerc() const {
if (!quests_running_.empty()) {
running_quest e = quests_running_.top();
return (e.owner && e.owner->IsMerc()) ? e.owner->CastToMerc() : nullptr;
}
return nullptr;
}
Mob *QuestManager::GetOwner() const { Mob *QuestManager::GetOwner() const {
if(!quests_running_.empty()) { if(!quests_running_.empty()) {
running_quest e = quests_running_.top(); running_quest e = quests_running_.top();
+1
View File
@@ -360,6 +360,7 @@ public:
Bot *GetBot() const; Bot *GetBot() const;
Client *GetInitiator() const; Client *GetInitiator() const;
Merc* GetMerc() const;
NPC *GetNPC() const; NPC *GetNPC() const;
Mob *GetOwner() const; Mob *GetOwner() const;
EQ::InventoryProfile* GetInventory() const; EQ::InventoryProfile* GetInventory() const;
+67 -136
View File
@@ -254,54 +254,34 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
} }
} }
if (IsClient()) {
if (parse->PlayerHasQuestSub(EVENT_CAST_BEGIN)) {
Mob* spell_target = entity_list.GetMobID(target_id); Mob* spell_target = entity_list.GetMobID(target_id);
std::vector<std::any> args = { spell_target }; std::vector<std::any> args = { spell_target };
const auto& export_string = fmt::format( int return_value = parse->EventMob(
EVENT_CAST_BEGIN,
this,
nullptr,
[&]() {
return fmt::format(
"{} {} {} {}", "{} {} {} {}",
spell_id, spell_id,
GetID(), GetID(),
GetCasterLevel(spell_id), GetCasterLevel(spell_id),
target_id target_id
); );
if (parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), export_string, 0, &args) != 0) { },
0,
&args
);
if (IsClient() && return_value != 0) {
if (IsDiscipline(spell_id)) { if (IsDiscipline(spell_id)) {
CastToClient()->SendDisciplineTimer(spells[spell_id].timer_id, 0); CastToClient()->SendDisciplineTimer(spells[spell_id].timer_id, 0);
} } else {
else {
CastToClient()->SendSpellBarEnable(spell_id); CastToClient()->SendSpellBarEnable(spell_id);
} }
return false; return false;
} }
}
} else if (IsNPC()) {
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_CAST_BEGIN)) {
Mob* spell_target = entity_list.GetMobID(target_id);
std::vector<std::any> args = { spell_target };
const auto& export_string = fmt::format(
"{} {} {} {}",
spell_id,
GetID(),
GetCasterLevel(spell_id),
target_id
);
parse->EventNPC(EVENT_CAST_BEGIN, CastToNPC(), nullptr, export_string, 0, &args);
}
} else if (IsBot()) {
if (parse->BotHasQuestSub(EVENT_CAST_BEGIN)) {
Mob* spell_target = entity_list.GetMobID(target_id);
std::vector<std::any> args = { spell_target };
const auto& export_string = fmt::format(
"{} {} {} {}",
spell_id,
GetID(),
GetCasterLevel(spell_id),
target_id
);
parse->EventBot(EVENT_CAST_BEGIN, CastToBot(), nullptr, export_string, 0, &args);
}
}
//To prevent NPC ghosting when spells are cast from scripts //To prevent NPC ghosting when spells are cast from scripts
if (IsNPC() && IsMoving() && cast_time > 0) { if (IsNPC() && IsMoving() && cast_time > 0) {
@@ -823,12 +803,10 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp
if (!spell_target) { if (!spell_target) {
if (IsGroupSpell(spell_id)) { if (IsGroupSpell(spell_id)) {
return true; return true;
} } else if (spells[spell_id].target_type == ST_Self) {
else if (spells[spell_id].target_type == ST_Self) {
spell_target = this; spell_target = this;
} }
} } else {
else {
if (IsGroupSpell(spell_id) && spell_target != this) { if (IsGroupSpell(spell_id) && spell_target != this) {
ignore_on_casting = true; ignore_on_casting = true;
} }
@@ -942,7 +920,13 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp
/* /*
Requires target to be in same group or same raid in order to apply invisible. Requires target to be in same group or same raid in order to apply invisible.
*/ */
if (check_on_casting && RuleB(Spells, InvisRequiresGroup) && IsInvisibleSpell(spell_id)) { if (
check_on_casting &&
spells[spell_id].target_type != ST_Self &&
GetTarget() != this &&
RuleB(Spells, InvisRequiresGroup) &&
IsInvisibleSpell(spell_id)
) {
if (IsClient() && spell_target && spell_target->IsClient()) { if (IsClient() && spell_target && spell_target->IsClient()) {
if (spell_target && spell_target->GetID() != GetID()) { if (spell_target && spell_target->GetID() != GetID()) {
bool cast_failed = true; bool cast_failed = true;
@@ -954,8 +938,7 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp
(target_group->GetID() == my_group->GetID())) { (target_group->GetID() == my_group->GetID())) {
cast_failed = false; cast_failed = false;
} }
} } else if (spell_target->IsRaidGrouped()) {
else if (spell_target->IsRaidGrouped()) {
Raid *target_raid = spell_target->GetRaid(); Raid *target_raid = spell_target->GetRaid();
Raid *my_raid = GetRaid(); Raid *my_raid = GetRaid();
if (target_raid && if (target_raid &&
@@ -1819,47 +1802,24 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo
} }
} }
// std::vector<std::any> args = { spell_target };
// at this point the spell has successfully been cast
//
if (IsClient()) { parse->EventMob(
if (parse->PlayerHasQuestSub(EVENT_CAST)) { EVENT_CAST,
std::vector<std::any> args = { spell_target }; this,
const auto& export_string = fmt::format( nullptr,
[&]() {
return fmt::format(
"{} {} {} {}", "{} {} {} {}",
spell_id, spell_id,
GetID(), GetID(),
GetCasterLevel(spell_id), GetCasterLevel(spell_id),
target_id target_id
); );
parse->EventPlayer(EVENT_CAST, CastToClient(), export_string, 0, &args); },
} 0,
} else if (IsNPC()) { &args
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_CAST)) {
std::vector<std::any> args = { spell_target };
const auto& export_string = fmt::format(
"{} {} {} {}",
spell_id,
GetID(),
GetCasterLevel(spell_id),
target_id
); );
parse->EventNPC(EVENT_CAST, CastToNPC(), nullptr, export_string, 0, &args);
}
} else if (IsBot()) {
if (parse->BotHasQuestSub(EVENT_CAST)) {
std::vector<std::any> args = { spell_target };
const auto& export_string = fmt::format(
"{} {} {} {}",
spell_id,
GetID(),
GetCasterLevel(spell_id),
target_id
);
parse->EventBot(EVENT_CAST, CastToBot(), nullptr, export_string, 0, &args);
}
}
if(bard_song_mode) if(bard_song_mode)
{ {
@@ -3004,7 +2964,6 @@ int Mob::CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caste
int res = CalcBuffDuration_formula(castlevel, formula, duration); int res = CalcBuffDuration_formula(castlevel, formula, duration);
if ( if (
caster == target &&
( (
target->aabonuses.IllusionPersistence || target->aabonuses.IllusionPersistence ||
target->spellbonuses.IllusionPersistence || target->spellbonuses.IllusionPersistence ||
@@ -3619,44 +3578,18 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid
); );
} }
const bool caster_has_block_event = ( std::function<std::string()> f = [&]() {
(caster->IsBot() && parse->BotHasQuestSub(EVENT_SPELL_BLOCKED)) || return fmt::format(
(caster->IsClient() && parse->PlayerHasQuestSub(EVENT_SPELL_BLOCKED)) ||
(caster->IsNPC() && parse->HasQuestSub(caster->GetNPCTypeID(), EVENT_SPELL_BLOCKED))
);
const bool cast_on_has_block_event = (
(IsBot() && parse->BotHasQuestSub(EVENT_SPELL_BLOCKED)) ||
(IsClient() && parse->PlayerHasQuestSub(EVENT_SPELL_BLOCKED)) ||
(IsNPC() && parse->HasQuestSub(GetNPCTypeID(), EVENT_SPELL_BLOCKED))
);
if (caster_has_block_event || cast_on_has_block_event) {
const std::string& export_string = fmt::format(
"{} {}", "{} {}",
curbuf.spellid, curbuf.spellid,
spell_id spell_id
); );
};
if (caster_has_block_event) { parse->EventMob(EVENT_SPELL_BLOCKED, caster, this, f);
if (caster->IsBot()) {
parse->EventBot(EVENT_SPELL_BLOCKED, caster->CastToBot(), this, export_string, 0);
} else if (caster->IsClient()) {
parse->EventPlayer(EVENT_SPELL_BLOCKED, caster->CastToClient(), export_string, 0);
} else if (caster->IsNPC()) {
parse->EventNPC(EVENT_SPELL_BLOCKED, caster->CastToNPC(), this, export_string, 0);
}
}
if (cast_on_has_block_event && caster != this) { if (caster != this) {
if (IsBot()) { parse->EventMob(EVENT_SPELL_BLOCKED, this, caster, f);
parse->EventBot(EVENT_SPELL_BLOCKED, CastToBot(), caster, export_string, 0);
} else if (IsClient()) {
parse->EventPlayer(EVENT_SPELL_BLOCKED, CastToClient(), export_string, 0);
} else if (IsNPC()) {
parse->EventNPC(EVENT_SPELL_BLOCKED, CastToNPC(), caster, export_string, 0);
}
}
} }
} }
@@ -4030,43 +3963,24 @@ bool Mob::SpellOnTarget(
(spellOwner->IsClient() ? FilterPCSpells : FilterNPCSpells) /* EQ Filter Type: (8 or 9) */ (spellOwner->IsClient() ? FilterPCSpells : FilterNPCSpells) /* EQ Filter Type: (8 or 9) */
); );
if (spelltar->IsNPC()) {
if (parse->HasQuestSub(spelltar->GetNPCTypeID(), EVENT_CAST_ON)) {
std::vector<std::any> args = { spelltar }; std::vector<std::any> args = { spelltar };
const auto& export_string = fmt::format(
parse->EventMob(
EVENT_CAST_ON,
spelltar,
this,
[&]() {
return fmt::format(
"{} {} {} {}", "{} {} {} {}",
spell_id, spell_id,
GetID(), GetID(),
caster_level, caster_level,
target_id target_id
); );
parse->EventNPC(EVENT_CAST_ON, spelltar->CastToNPC(), this, export_string, 0, &args); },
} 0,
} else if (spelltar->IsClient()) { &args
if (parse->PlayerHasQuestSub(EVENT_CAST_ON)) {
std::vector<std::any> args = { spelltar };
const auto& export_string = fmt::format(
"{} {} {} {}",
spell_id,
GetID(),
caster_level,
target_id
); );
parse->EventPlayer(EVENT_CAST_ON, spelltar->CastToClient(), export_string, 0, &args);
}
} else if (spelltar->IsBot()) {
if (parse->BotHasQuestSub(EVENT_CAST_ON)) {
std::vector<std::any> args = { spelltar };
const auto& export_string = fmt::format(
"{} {} {} {}",
spell_id,
GetID(),
caster_level,
target_id
);
parse->EventBot(EVENT_CAST_ON, spelltar->CastToBot(), this, export_string, 0, &args);
}
}
if (!DoCastingChecksOnTarget(false, spell_id, spelltar)) { if (!DoCastingChecksOnTarget(false, spell_id, spelltar)) {
safe_delete(action_packet); safe_delete(action_packet);
@@ -4984,6 +4898,23 @@ void Mob::BuffFadeByEffect(int effect_id, int slot_to_skip)
} }
} }
void Mob::BuffFadeSongs() {
bool recalc_bonus = false;
int buff_count = GetMaxTotalSlots();
for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) {
const uint16 current_spell_id = buffs[buff_slot].spellid;
if (IsBardSong(current_spell_id)) {
BuffFadeBySlot(buff_slot, false);
recalc_bonus = true;
}
}
if (recalc_bonus) {
CalcBonuses();
}
}
bool Mob::IsAffectedByBuffByGlobalGroup(GlobalGroup group) bool Mob::IsAffectedByBuffByGlobalGroup(GlobalGroup group)
{ {
int buff_count = GetMaxTotalSlots(); int buff_count = GetMaxTotalSlots();
+12
View File
@@ -561,6 +561,12 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct*
m_epp->expended_aa = e.e_expended_aa_spent; m_epp->expended_aa = e.e_expended_aa_spent;
m_epp->last_invsnapshot_time = e.e_last_invsnapshot; m_epp->last_invsnapshot_time = e.e_last_invsnapshot;
m_epp->next_invsnapshot_time = m_epp->last_invsnapshot_time + (RuleI(Character, InvSnapshotMinIntervalM) * 60); m_epp->next_invsnapshot_time = m_epp->last_invsnapshot_time + (RuleI(Character, InvSnapshotMinIntervalM) * 60);
pp->cold_resist = e.cold_resist;
pp->fire_resist = e.fire_resist;
pp->magic_resist = e.magic_resist;
pp->disease_resist = e.disease_resist;
pp->poison_resist = e.poison_resist;
pp->corruption_resist = e.corruption_resist;
return true; return true;
} }
@@ -1158,6 +1164,12 @@ bool ZoneDatabase::SaveCharacterData(
e.e_expended_aa_spent = m_epp->expended_aa; e.e_expended_aa_spent = m_epp->expended_aa;
e.e_last_invsnapshot = m_epp->last_invsnapshot_time; e.e_last_invsnapshot = m_epp->last_invsnapshot_time;
e.mailkey = c->GetMailKeyFull(); e.mailkey = c->GetMailKeyFull();
e.cold_resist = pp->cold_resist;
e.fire_resist = pp->fire_resist;
e.magic_resist = pp->magic_resist;
e.disease_resist = pp->disease_resist;
e.poison_resist = pp->poison_resist;
e.corruption_resist = pp->corruption_resist;
const int replaced = CharacterDataRepository::ReplaceOne(database, e); const int replaced = CharacterDataRepository::ReplaceOne(database, e);