mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-16 21:51:29 +00:00
commit
5a94e82db8
16
.drone.yml
Normal file
16
.drone.yml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: EQEmulator Server Linux CI
|
||||||
|
|
||||||
|
# Limits how many of these builds can run on the drone runner at a time, this isn't about cores
|
||||||
|
concurrency:
|
||||||
|
limit: 1
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: server-build
|
||||||
|
# Source build script https://github.com/Akkadius/akk-stack/blob/master/containers/eqemu-server/Dockerfile#L20
|
||||||
|
image: akkadius/eqemu-server:latest
|
||||||
|
commands:
|
||||||
|
- sudo chown eqemu:eqemu /drone/src/ * -R
|
||||||
|
- git submodule init && git submodule update && mkdir -p build && cd build && cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_BOTS=ON -DEQEMU_BUILD_LUA=ON -G 'Unix Makefiles' .. && make -j$((`nproc`-4))
|
||||||
@ -12,7 +12,7 @@ IF(NOT CMAKE_BUILD_TYPE)
|
|||||||
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
|
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
|
||||||
ENDIF(NOT CMAKE_BUILD_TYPE)
|
ENDIF(NOT CMAKE_BUILD_TYPE)
|
||||||
|
|
||||||
SET(CMAKE_CXX_STANDARD 11)
|
SET(CMAKE_CXX_STANDARD 14)
|
||||||
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
SET(CMAKE_CXX_EXTENSIONS OFF)
|
SET(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
|||||||
@ -80,3 +80,4 @@ forum, although pull requests will be much quicker and easier on all parties.
|
|||||||
<a href="https://github.com/EQEmu/server/graphs/contributors">
|
<a href="https://github.com/EQEmu/server/graphs/contributors">
|
||||||
<img src="https://contributors-img.firebaseapp.com/image?repo=EQEmu/server" />
|
<img src="https://contributors-img.firebaseapp.com/image?repo=EQEmu/server" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|||||||
@ -378,6 +378,8 @@ const char *GetClassIDName(uint8 class_id, uint8 level)
|
|||||||
return "Berserker Guildmaster";
|
return "Berserker Guildmaster";
|
||||||
case MERCHANT:
|
case MERCHANT:
|
||||||
return "Merchant";
|
return "Merchant";
|
||||||
|
case DISCORD_MERCHANT:
|
||||||
|
return "Discord Merchant";
|
||||||
case ADVENTURERECRUITER:
|
case ADVENTURERECRUITER:
|
||||||
return "Adventure Recruiter";
|
return "Adventure Recruiter";
|
||||||
case ADVENTUREMERCHANT:
|
case ADVENTUREMERCHANT:
|
||||||
@ -388,6 +390,18 @@ const char *GetClassIDName(uint8 class_id, uint8 level)
|
|||||||
return "Tribute Master";
|
return "Tribute Master";
|
||||||
case GUILD_TRIBUTE_MASTER:
|
case GUILD_TRIBUTE_MASTER:
|
||||||
return "Guild Tribute Master";
|
return "Guild Tribute Master";
|
||||||
|
case GUILD_BANKER:
|
||||||
|
return "Guild Banker";
|
||||||
|
case NORRATHS_KEEPERS_MERCHANT:
|
||||||
|
return "Radiant Crystal Merchant";
|
||||||
|
case DARK_REIGN_MERCHANT:
|
||||||
|
return "Ebon Crystal Merchant";
|
||||||
|
case FELLOWSHIP_MASTER:
|
||||||
|
return "Fellowship Master";
|
||||||
|
case ALT_CURRENCY_MERCHANT:
|
||||||
|
return "Alternate Currency Merchant";
|
||||||
|
case MERCERNARY_MASTER:
|
||||||
|
return "Mercenary Liaison";
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,6 +61,7 @@
|
|||||||
#define CORPSE_CLASS 62 // only seen on Danvi's Corpse in Akheva so far..
|
#define CORPSE_CLASS 62 // only seen on Danvi's Corpse in Akheva so far..
|
||||||
#define TRIBUTE_MASTER 63
|
#define TRIBUTE_MASTER 63
|
||||||
#define GUILD_TRIBUTE_MASTER 64 // not sure
|
#define GUILD_TRIBUTE_MASTER 64 // not sure
|
||||||
|
#define GUILD_BANKER 66
|
||||||
#define NORRATHS_KEEPERS_MERCHANT 67
|
#define NORRATHS_KEEPERS_MERCHANT 67
|
||||||
#define DARK_REIGN_MERCHANT 68
|
#define DARK_REIGN_MERCHANT 68
|
||||||
#define FELLOWSHIP_MASTER 69
|
#define FELLOWSHIP_MASTER 69
|
||||||
|
|||||||
@ -300,8 +300,7 @@ void DatabaseDumpService::Dump()
|
|||||||
config->DatabaseUsername
|
config->DatabaseUsername
|
||||||
);
|
);
|
||||||
|
|
||||||
std::string options = "--allow-keywords --extended-insert";
|
std::string options = "--allow-keywords --extended-insert --max-allowed-packet=1G --net-buffer-length=32704";
|
||||||
|
|
||||||
if (IsDumpWithNoData()) {
|
if (IsDumpWithNoData()) {
|
||||||
options += " --no-data";
|
options += " --no-data";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -493,6 +493,9 @@ void Database::DeleteInstance(uint16 instance_id)
|
|||||||
query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id);
|
query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id);
|
||||||
QueryDatabase(query);
|
QueryDatabase(query);
|
||||||
|
|
||||||
|
query = fmt::format("DELETE FROM dynamic_zones WHERE instance_id={}", instance_id);
|
||||||
|
QueryDatabase(query);
|
||||||
|
|
||||||
BuryCorpsesInInstance(instance_id);
|
BuryCorpsesInInstance(instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,8 +585,7 @@ void Database::PurgeExpiredInstances()
|
|||||||
QueryDatabase(fmt::format("DELETE FROM respawn_times WHERE instance_id IN ({})", imploded_instance_ids));
|
QueryDatabase(fmt::format("DELETE FROM respawn_times WHERE instance_id IN ({})", imploded_instance_ids));
|
||||||
QueryDatabase(fmt::format("DELETE FROM spawn_condition_values WHERE instance_id IN ({})", imploded_instance_ids));
|
QueryDatabase(fmt::format("DELETE FROM spawn_condition_values WHERE instance_id IN ({})", imploded_instance_ids));
|
||||||
QueryDatabase(fmt::format("UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id IN ({})", imploded_instance_ids));
|
QueryDatabase(fmt::format("UPDATE character_corpses SET is_buried = 1, instance_id = 0 WHERE instance_id IN ({})", imploded_instance_ids));
|
||||||
|
QueryDatabase(fmt::format("DELETE FROM dynamic_zones WHERE instance_id IN ({})", imploded_instance_ids));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
|
void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration)
|
||||||
|
|||||||
@ -50,6 +50,7 @@ namespace DatabaseSchema {
|
|||||||
{"character_data", "id"},
|
{"character_data", "id"},
|
||||||
{"character_disciplines", "id"},
|
{"character_disciplines", "id"},
|
||||||
{"character_enabledtasks", "charid"},
|
{"character_enabledtasks", "charid"},
|
||||||
|
{"character_expedition_lockouts", "character_id"},
|
||||||
{"character_inspect_messages", "id"},
|
{"character_inspect_messages", "id"},
|
||||||
{"character_item_recast", "id"},
|
{"character_item_recast", "id"},
|
||||||
{"character_languages", "id"},
|
{"character_languages", "id"},
|
||||||
@ -114,6 +115,7 @@ namespace DatabaseSchema {
|
|||||||
"character_data",
|
"character_data",
|
||||||
"character_disciplines",
|
"character_disciplines",
|
||||||
"character_enabledtasks",
|
"character_enabledtasks",
|
||||||
|
"character_expedition_lockouts",
|
||||||
"character_inspect_messages",
|
"character_inspect_messages",
|
||||||
"character_item_recast",
|
"character_item_recast",
|
||||||
"character_languages",
|
"character_languages",
|
||||||
@ -305,7 +307,11 @@ namespace DatabaseSchema {
|
|||||||
"banned_ips",
|
"banned_ips",
|
||||||
"bug_reports",
|
"bug_reports",
|
||||||
"bugs",
|
"bugs",
|
||||||
|
"dynamic_zones",
|
||||||
"eventlog",
|
"eventlog",
|
||||||
|
"expedition_lockouts",
|
||||||
|
"expedition_members",
|
||||||
|
"expeditions",
|
||||||
"gm_ips",
|
"gm_ips",
|
||||||
"group_id",
|
"group_id",
|
||||||
"group_leaders",
|
"group_leaders",
|
||||||
|
|||||||
@ -136,20 +136,22 @@ N(OP_Dye),
|
|||||||
N(OP_DynamicWall),
|
N(OP_DynamicWall),
|
||||||
N(OP_DzAddPlayer),
|
N(OP_DzAddPlayer),
|
||||||
N(OP_DzChooseZone),
|
N(OP_DzChooseZone),
|
||||||
|
N(OP_DzChooseZoneReply),
|
||||||
N(OP_DzCompass),
|
N(OP_DzCompass),
|
||||||
N(OP_DzExpeditionEndsWarning),
|
N(OP_DzExpeditionEndsWarning),
|
||||||
N(OP_DzExpeditionInfo),
|
N(OP_DzExpeditionInfo),
|
||||||
N(OP_DzExpeditionList),
|
N(OP_DzExpeditionInvite),
|
||||||
N(OP_DzJoinExpeditionConfirm),
|
N(OP_DzExpeditionInviteResponse),
|
||||||
N(OP_DzJoinExpeditionReply),
|
N(OP_DzExpeditionLockoutTimers),
|
||||||
N(OP_DzLeaderStatus),
|
|
||||||
N(OP_DzListTimers),
|
N(OP_DzListTimers),
|
||||||
N(OP_DzMakeLeader),
|
N(OP_DzMakeLeader),
|
||||||
N(OP_DzMemberList),
|
N(OP_DzMemberList),
|
||||||
N(OP_DzMemberStatus),
|
N(OP_DzMemberListName),
|
||||||
|
N(OP_DzMemberListStatus),
|
||||||
N(OP_DzPlayerList),
|
N(OP_DzPlayerList),
|
||||||
N(OP_DzQuit),
|
N(OP_DzQuit),
|
||||||
N(OP_DzRemovePlayer),
|
N(OP_DzRemovePlayer),
|
||||||
|
N(OP_DzSetLeaderName),
|
||||||
N(OP_DzSwapPlayer),
|
N(OP_DzSwapPlayer),
|
||||||
N(OP_Emote),
|
N(OP_Emote),
|
||||||
N(OP_EndLootRequest),
|
N(OP_EndLootRequest),
|
||||||
@ -271,6 +273,7 @@ N(OP_ItemVerifyRequest),
|
|||||||
N(OP_ItemViewUnknown),
|
N(OP_ItemViewUnknown),
|
||||||
N(OP_Jump),
|
N(OP_Jump),
|
||||||
N(OP_KeyRing),
|
N(OP_KeyRing),
|
||||||
|
N(OP_KickPlayers),
|
||||||
N(OP_KnowledgeBase),
|
N(OP_KnowledgeBase),
|
||||||
N(OP_LDoNButton),
|
N(OP_LDoNButton),
|
||||||
N(OP_LDoNDisarmTraps),
|
N(OP_LDoNDisarmTraps),
|
||||||
|
|||||||
@ -375,13 +375,16 @@ struct NewZone_Struct {
|
|||||||
/*0686*/ uint16 zone_instance;
|
/*0686*/ uint16 zone_instance;
|
||||||
/*0688*/ uint32 unknown688;
|
/*0688*/ uint32 unknown688;
|
||||||
/*0692*/ uint8 unknown692[8];
|
/*0692*/ uint8 unknown692[8];
|
||||||
|
// Titanium doesn't have a translator, but we can still safely add stuff under here without issues since client memcpy's only what it knows
|
||||||
|
// Just wastes some bandwidth sending to tit clients /shrug
|
||||||
/*0700*/ float fog_density;
|
/*0700*/ float fog_density;
|
||||||
/*0704*/ uint32 SuspendBuffs;
|
/*0704*/ uint32 SuspendBuffs;
|
||||||
/*0708*/ uint32 FastRegenHP;
|
/*0708*/ uint32 FastRegenHP;
|
||||||
/*0712*/ uint32 FastRegenMana;
|
/*0712*/ uint32 FastRegenMana;
|
||||||
/*0716*/ uint32 FastRegenEndurance;
|
/*0716*/ uint32 FastRegenEndurance;
|
||||||
/*0720*/ uint32 NPCAggroMaxDist;
|
/*0720*/ uint32 NPCAggroMaxDist;
|
||||||
/*0724*/
|
/*0724*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, if this value is 0, it prevents you from running off edges that would end up underworld
|
||||||
|
/*0728*/
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4832,17 +4835,98 @@ struct BuffIcon_Struct
|
|||||||
BuffIconEntry_Struct entries[0];
|
BuffIconEntry_Struct entries[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionInfo_Struct
|
struct ExpeditionInvite_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 max_players;
|
/*000*/ uint32 client_id; // unique character id
|
||||||
/*004*/ char expedition_name[128];
|
/*004*/ uint32 unknown004; // added after titanium
|
||||||
/*132*/ char leader_name[64];
|
/*008*/ char inviter_name[64];
|
||||||
|
/*072*/ char expedition_name[128];
|
||||||
|
/*200*/ uint8 swapping; // 0: adding 1: swapping
|
||||||
|
/*201*/ char swap_name[64]; // if swapping, swap name being removed
|
||||||
|
/*265*/ uint8 padding[3];
|
||||||
|
/*268*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply
|
||||||
|
/*270*/ uint16 dz_instance_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionJoinPrompt_Struct
|
struct ExpeditionInviteResponse_Struct
|
||||||
{
|
{
|
||||||
/*000*/ char player_name[64];
|
/*000*/ uint32 unknown000;
|
||||||
/*064*/ char expedition_name[64];
|
/*004*/ uint32 unknown004; // added after titanium
|
||||||
|
/*008*/ uint16 dz_zone_id; // dz_id pair sent in invite
|
||||||
|
/*010*/ uint16 dz_instance_id;
|
||||||
|
/*012*/ uint8 accepted; // 0: declined 1: accepted
|
||||||
|
/*013*/ uint8 swapping; // 0: adding 1: swapping (sent in invite)
|
||||||
|
/*014*/ char swap_name[64]; // swap name sent in invite
|
||||||
|
/*078*/ uint8 unknown078; // padding garbage?
|
||||||
|
/*079*/ uint8 unknown079; // padding garbage?
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionInfo_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004; // added after titanium
|
||||||
|
/*008*/ uint32 assigned; // padded bool, 0: not in expedition (clear data), 1: in expedition
|
||||||
|
/*012*/ uint32 max_players;
|
||||||
|
/*016*/ char expedition_name[128];
|
||||||
|
/*144*/ char leader_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ char name[64]; // variable length, null terminated, max 0x40 (64)
|
||||||
|
/*064*/ uint8 expedition_status; // 0: unknown, 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberList_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 member_count;
|
||||||
|
/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberListName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status
|
||||||
|
/*012*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimerEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ char expedition_name[128]; // variable length, null terminated, max 0x80 (128)
|
||||||
|
/*000*/ uint32 seconds_remaining;
|
||||||
|
/*000*/ int32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers
|
||||||
|
/*000*/ char event_name[256]; // variable length, null terminated, max 0x100 (256)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimers_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionSetLeaderName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char leader_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommand_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommandSwap_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char add_player_name[64]; // swap to (player must confirm)
|
||||||
|
/*072*/ char rem_player_name[64]; // swap from
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionExpireWarning
|
struct ExpeditionExpireWarning
|
||||||
@ -4850,48 +4934,67 @@ struct ExpeditionExpireWarning
|
|||||||
/*008*/ uint32 minutes_remaining;
|
/*008*/ uint32 minutes_remaining;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompassEntry_Struct
|
struct DynamicZoneCompassEntry_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 enabled; //guess
|
/*000*/ uint16 dz_zone_id; // target dz id pair
|
||||||
/*004*/ float y;
|
/*002*/ uint16 dz_instance_id;
|
||||||
/*008*/ float x;
|
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
|
||||||
/*012*/ float z;
|
/*008*/ uint32 unknown008;
|
||||||
|
/*012*/ float y;
|
||||||
|
/*016*/ float x;
|
||||||
|
/*020*/ float z;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompass_Struct
|
struct DynamicZoneCompass_Struct
|
||||||
{
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
/*000*/ uint32 count;
|
/*000*/ uint32 count;
|
||||||
/*004*/ ExpeditionCompassEntry_Struct entries[0];
|
/*004*/ DynamicZoneCompassEntry_Struct entries[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionMemberEntry_Struct
|
struct DynamicZoneChooseZoneEntry_Struct
|
||||||
{
|
{
|
||||||
char name[64];
|
/*000*/ uint16 dz_zone_id; // dz_id pair
|
||||||
char status;
|
/*002*/ uint16 dz_instance_id;
|
||||||
|
/*004*/ uint32 unknown_id1; // seen 28 00 00 00 (40), sent back in reply
|
||||||
|
/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply
|
||||||
|
/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different
|
||||||
|
/*016*/ char description[128]; // variable length, null terminated
|
||||||
|
/*144*/ char leader_name[64]; // variable length, null terminated
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionMemberList_Struct
|
struct DynamicZoneChooseZone_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 count;
|
/*000*/ uint32 client_id;
|
||||||
/*004*/ ExpeditionMemberEntry_Struct entries[0];
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionLockoutEntry_Struct
|
struct DynamicZoneChooseZoneReply_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 time_left;
|
/*000*/ uint32 unknown000; // ff ff ff ff
|
||||||
/*004*/ char expedition[128];
|
/*004*/ uint32 unknown004; // seen 69 00 00 00
|
||||||
/*132*/ char expedition_event[128];
|
/*008*/ uint32 unknown008; // ff ff ff ff
|
||||||
|
/*012*/ uint32 unknown_id1; // from choose zone entry message
|
||||||
|
/*016*/ uint16 dz_zone_id; // dz_id pair
|
||||||
|
/*018*/ uint16 dz_instance_id;
|
||||||
|
/*020*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest
|
||||||
|
/*024*/ uint32 unknown_id2; // from choose zone entry message
|
||||||
|
/*028*/ uint32 unknown028; // 00 00 00 00
|
||||||
|
/*032*/ uint32 unknown032; // always same as unknown044
|
||||||
|
/*036*/ uint32 unknown036;
|
||||||
|
/*040*/ uint32 unknown040;
|
||||||
|
/*044*/ uint32 unknown044; // always same as unknown032
|
||||||
|
/*048*/ uint32 unknown048; // seen 01 00 00 00 and 02 00 00 00
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionLockoutList_Struct
|
struct KickPlayers_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 count;
|
/*000*/ char char_name[64];
|
||||||
/*004*/ ExpeditionLockoutEntry_Struct entries[0];
|
/*064*/ uint32 unknown064; // always 0
|
||||||
};
|
/*068*/ uint8 kick_expedition; // true if /kickplayers exp
|
||||||
|
/*069*/ uint8 kick_task; // true if /kickplayers task
|
||||||
struct ExpeditionLeaderSet_Struct
|
/*070*/ uint8 padding[2];
|
||||||
{
|
|
||||||
/*000*/ char leader_name[64];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CorpseDrag_Struct
|
struct CorpseDrag_Struct
|
||||||
|
|||||||
@ -118,6 +118,9 @@ namespace Logs {
|
|||||||
Merchants,
|
Merchants,
|
||||||
ZonePoints,
|
ZonePoints,
|
||||||
Loot,
|
Loot,
|
||||||
|
Expeditions,
|
||||||
|
DynamicZones,
|
||||||
|
Group,
|
||||||
MaxCategoryID /* Don't Remove this */
|
MaxCategoryID /* Don't Remove this */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -194,7 +197,10 @@ namespace Logs {
|
|||||||
"HotReload",
|
"HotReload",
|
||||||
"Merchants",
|
"Merchants",
|
||||||
"ZonePoints",
|
"ZonePoints",
|
||||||
"Loot"
|
"Loot",
|
||||||
|
"Expeditions",
|
||||||
|
"DynamicZones",
|
||||||
|
"Group",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -161,6 +161,16 @@
|
|||||||
OutF(LogSys, Logs::Detail, Logs::Doors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
OutF(LogSys, Logs::Detail, Logs::Doors, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define LogGroup(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Group].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Group, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogGroupDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Group].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Group, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define LogGuilds(message, ...) do {\
|
#define LogGuilds(message, ...) do {\
|
||||||
if (LogSys.log_settings[Logs::Guilds].is_category_enabled == 1)\
|
if (LogSys.log_settings[Logs::Guilds].is_category_enabled == 1)\
|
||||||
OutF(LogSys, Logs::General, Logs::Guilds, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
OutF(LogSys, Logs::General, Logs::Guilds, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
@ -601,6 +611,31 @@
|
|||||||
OutF(LogSys, Logs::Detail, Logs::Loot, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
OutF(LogSys, Logs::Detail, Logs::Loot, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define LogExpeditions(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Expeditions].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::Expeditions, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogExpeditionsModerate(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Expeditions].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Moderate, Logs::Expeditions, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogExpeditionsDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::Expeditions].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::Expeditions, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogDynamicZones(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::DynamicZones].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::General, Logs::DynamicZones, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogDynamicZonesDetail(message, ...) do {\
|
||||||
|
if (LogSys.log_settings[Logs::DynamicZones].is_category_enabled == 1)\
|
||||||
|
OutF(LogSys, Logs::Detail, Logs::DynamicZones, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define Log(debug_level, log_category, message, ...) do {\
|
#define Log(debug_level, log_category, message, ...) do {\
|
||||||
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
|
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
|
||||||
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
|
||||||
@ -694,6 +729,12 @@
|
|||||||
#define LogDoorsDetail(message, ...) do {\
|
#define LogDoorsDetail(message, ...) do {\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define LogGroup(message, ...) do {\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogGroupDetail(message, ...) do {\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define LogGuilds(message, ...) do {\
|
#define LogGuilds(message, ...) do {\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@ -952,6 +993,21 @@
|
|||||||
#define LogZonePointsDetail(message, ...) do {\
|
#define LogZonePointsDetail(message, ...) do {\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define LogExpeditions(message, ...) do {\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogExpeditionsModerate(message, ...) do {\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogExpeditionsDetail(message, ...) do {\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogDynamicZones(message, ...) do {\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LogDynamicZonesDetail(message, ...) do {\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define Log(debug_level, log_category, message, ...) do {\
|
#define Log(debug_level, log_category, message, ...) do {\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|||||||
@ -710,15 +710,48 @@ namespace RoF
|
|||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzChooseZone)
|
||||||
|
{
|
||||||
|
SETUP_VAR_ENCODE(DynamicZoneChooseZone_Struct);
|
||||||
|
|
||||||
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
|
buf.WriteUInt32(emu->count);
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
|
{
|
||||||
|
buf.WriteUInt16(emu->choices[i].dz_zone_id);
|
||||||
|
buf.WriteUInt16(emu->choices[i].dz_instance_id);
|
||||||
|
buf.WriteUInt32(emu->choices[i].unknown_id1);
|
||||||
|
buf.WriteUInt32(emu->choices[i].dz_type);
|
||||||
|
buf.WriteUInt32(emu->choices[i].unknown_id2);
|
||||||
|
buf.WriteString(emu->choices[i].description);
|
||||||
|
buf.WriteString(emu->choices[i].leader_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
__packet->size = buf.size();
|
||||||
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzCompass)
|
ENCODE(OP_DzCompass)
|
||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionCompass_Struct);
|
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
|
||||||
ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count);
|
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
|
||||||
|
sizeof(structs::DynamicZoneCompass_Struct) +
|
||||||
|
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
|
||||||
|
);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
OUT(count);
|
OUT(count);
|
||||||
|
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
{
|
{
|
||||||
|
OUT(entries[i].dz_zone_id);
|
||||||
|
OUT(entries[i].dz_instance_id);
|
||||||
|
OUT(entries[i].dz_type);
|
||||||
OUT(entries[i].x);
|
OUT(entries[i].x);
|
||||||
OUT(entries[i].y);
|
OUT(entries[i].y);
|
||||||
OUT(entries[i].z);
|
OUT(entries[i].z);
|
||||||
@ -742,81 +775,60 @@ namespace RoF
|
|||||||
ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct);
|
||||||
SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct);
|
SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
|
OUT(assigned);
|
||||||
OUT(max_players);
|
OUT(max_players);
|
||||||
eq->unknown004 = 785316192;
|
strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
||||||
eq->unknown008 = 435601;
|
strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
||||||
strncpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
|
||||||
strncpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzExpeditionList)
|
ENCODE(OP_DzExpeditionInvite)
|
||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionInvite_Struct);
|
||||||
|
SETUP_DIRECT_ENCODE(ExpeditionInvite_Struct, structs::ExpeditionInvite_Struct);
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
OUT(client_id);
|
||||||
uint32 client_id = 0;
|
strn0cpy(eq->inviter_name, emu->inviter_name, sizeof(eq->inviter_name));
|
||||||
uint8 null_term = 0;
|
strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
OUT(swapping);
|
||||||
ss.write((const char*)&emu->count, sizeof(uint32));
|
strn0cpy(eq->swap_name, emu->swap_name, sizeof(eq->swap_name));
|
||||||
|
OUT(dz_zone_id);
|
||||||
|
OUT(dz_instance_id);
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzExpeditionLockoutTimers)
|
||||||
|
{
|
||||||
|
SETUP_VAR_ENCODE(ExpeditionLockoutTimers_Struct);
|
||||||
|
|
||||||
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
|
buf.WriteUInt32(emu->count);
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
{
|
{
|
||||||
ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition));
|
buf.WriteString(emu->timers[i].expedition_name);
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
buf.WriteUInt32(emu->timers[i].seconds_remaining);
|
||||||
ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32));
|
buf.WriteInt32(emu->timers[i].event_type);
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
buf.WriteString(emu->timers[i].event_name);
|
||||||
ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event));
|
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
__packet->size = buf.size();
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzJoinExpeditionConfirm)
|
ENCODE(OP_DzSetLeaderName)
|
||||||
{
|
{
|
||||||
ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionSetLeaderName_Struct);
|
||||||
SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct);
|
SETUP_DIRECT_ENCODE(ExpeditionSetLeaderName_Struct, structs::ExpeditionSetLeaderName_Struct);
|
||||||
|
|
||||||
strncpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
OUT(client_id);
|
||||||
strncpy(eq->player_name, emu->player_name, sizeof(eq->player_name));
|
strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
||||||
|
|
||||||
FINISH_ENCODE();
|
|
||||||
}
|
|
||||||
|
|
||||||
ENCODE(OP_DzLeaderStatus)
|
|
||||||
{
|
|
||||||
SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct);
|
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
|
||||||
uint32 client_id = 0;
|
|
||||||
uint8 null_term = 0;
|
|
||||||
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write(emu->leader_name, strlen(emu->leader_name));
|
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));//1
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
@ -825,26 +837,43 @@ namespace RoF
|
|||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionMemberList_Struct);
|
SETUP_VAR_ENCODE(ExpeditionMemberList_Struct);
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
uint32 client_id = 0;
|
buf.WriteUInt32(emu->member_count);
|
||||||
uint8 null_term = 0;
|
for (uint32 i = 0; i < emu->member_count; ++i)
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&emu->count, sizeof(uint32));
|
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
|
||||||
{
|
{
|
||||||
ss.write(emu->entries[i].name, strlen(emu->entries[i].name));
|
buf.WriteString(emu->members[i].name);
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
buf.WriteUInt8(emu->members[i].expedition_status);
|
||||||
ss.write((const char*)&emu->entries[i].status, sizeof(char));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
__packet->size = buf.size();
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzMemberListName)
|
||||||
|
{
|
||||||
|
ENCODE_LENGTH_EXACT(ExpeditionMemberListName_Struct);
|
||||||
|
SETUP_DIRECT_ENCODE(ExpeditionMemberListName_Struct, structs::ExpeditionMemberListName_Struct);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
|
OUT(add_name);
|
||||||
|
strn0cpy(eq->name, emu->name, sizeof(eq->name));
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzMemberListStatus)
|
||||||
|
{
|
||||||
|
auto emu = reinterpret_cast<ExpeditionMemberList_Struct*>((*p)->pBuffer);
|
||||||
|
if (emu->member_count == 1)
|
||||||
|
{
|
||||||
|
ENCODE_FORWARD(OP_DzMemberList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ENCODE(OP_Emote)
|
ENCODE(OP_Emote)
|
||||||
{
|
{
|
||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
@ -1827,6 +1856,7 @@ namespace RoF
|
|||||||
OUT(FastRegenHP);
|
OUT(FastRegenHP);
|
||||||
OUT(FastRegenMana);
|
OUT(FastRegenMana);
|
||||||
OUT(FastRegenEndurance);
|
OUT(FastRegenEndurance);
|
||||||
|
OUT(underworld_teleport_index);
|
||||||
|
|
||||||
eq->FogDensity = emu->fog_density;
|
eq->FogDensity = emu->fog_density;
|
||||||
|
|
||||||
@ -4387,6 +4417,84 @@ namespace RoF
|
|||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzAddPlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzChooseZoneReply)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::DynamicZoneChooseZoneReply_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(DynamicZoneChooseZoneReply_Struct, structs::DynamicZoneChooseZoneReply_Struct);
|
||||||
|
|
||||||
|
IN(unknown000);
|
||||||
|
IN(unknown004);
|
||||||
|
IN(unknown008);
|
||||||
|
IN(unknown_id1);
|
||||||
|
IN(dz_zone_id);
|
||||||
|
IN(dz_instance_id);
|
||||||
|
IN(dz_type);
|
||||||
|
IN(unknown_id2);
|
||||||
|
IN(unknown028);
|
||||||
|
IN(unknown032);
|
||||||
|
IN(unknown036);
|
||||||
|
IN(unknown040);
|
||||||
|
IN(unknown044);
|
||||||
|
IN(unknown048);
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzExpeditionInviteResponse)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionInviteResponse_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionInviteResponse_Struct, structs::ExpeditionInviteResponse_Struct);
|
||||||
|
|
||||||
|
IN(dz_zone_id);
|
||||||
|
IN(dz_instance_id);
|
||||||
|
IN(accepted);
|
||||||
|
IN(swapping);
|
||||||
|
strn0cpy(emu->swap_name, eq->swap_name, sizeof(emu->swap_name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzMakeLeader)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzRemovePlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzSwapPlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommandSwap_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommandSwap_Struct, structs::ExpeditionCommandSwap_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->add_player_name, eq->add_player_name, sizeof(emu->add_player_name));
|
||||||
|
strn0cpy(emu->rem_player_name, eq->rem_player_name, sizeof(emu->rem_player_name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
DECODE(OP_Emote)
|
DECODE(OP_Emote)
|
||||||
{
|
{
|
||||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||||
|
|||||||
@ -759,15 +759,48 @@ namespace RoF2
|
|||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzChooseZone)
|
||||||
|
{
|
||||||
|
SETUP_VAR_ENCODE(DynamicZoneChooseZone_Struct);
|
||||||
|
|
||||||
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
|
buf.WriteUInt32(emu->count);
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
|
{
|
||||||
|
buf.WriteUInt16(emu->choices[i].dz_zone_id);
|
||||||
|
buf.WriteUInt16(emu->choices[i].dz_instance_id);
|
||||||
|
buf.WriteUInt32(emu->choices[i].unknown_id1);
|
||||||
|
buf.WriteUInt32(emu->choices[i].dz_type);
|
||||||
|
buf.WriteUInt32(emu->choices[i].unknown_id2);
|
||||||
|
buf.WriteString(emu->choices[i].description);
|
||||||
|
buf.WriteString(emu->choices[i].leader_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
__packet->size = buf.size();
|
||||||
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzCompass)
|
ENCODE(OP_DzCompass)
|
||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionCompass_Struct);
|
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
|
||||||
ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count);
|
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
|
||||||
|
sizeof(structs::DynamicZoneCompass_Struct) +
|
||||||
|
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
|
||||||
|
);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
OUT(count);
|
OUT(count);
|
||||||
|
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
{
|
{
|
||||||
|
OUT(entries[i].dz_zone_id);
|
||||||
|
OUT(entries[i].dz_instance_id);
|
||||||
|
OUT(entries[i].dz_type);
|
||||||
OUT(entries[i].x);
|
OUT(entries[i].x);
|
||||||
OUT(entries[i].y);
|
OUT(entries[i].y);
|
||||||
OUT(entries[i].z);
|
OUT(entries[i].z);
|
||||||
@ -791,81 +824,60 @@ namespace RoF2
|
|||||||
ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct);
|
||||||
SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct);
|
SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
|
OUT(assigned);
|
||||||
OUT(max_players);
|
OUT(max_players);
|
||||||
eq->unknown004 = 785316192;
|
strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
||||||
eq->unknown008 = 435601;
|
strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
||||||
strncpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
|
||||||
strncpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzExpeditionList)
|
ENCODE(OP_DzExpeditionInvite)
|
||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionInvite_Struct);
|
||||||
|
SETUP_DIRECT_ENCODE(ExpeditionInvite_Struct, structs::ExpeditionInvite_Struct);
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
OUT(client_id);
|
||||||
uint32 client_id = 0;
|
strn0cpy(eq->inviter_name, emu->inviter_name, sizeof(eq->inviter_name));
|
||||||
uint8 null_term = 0;
|
strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
OUT(swapping);
|
||||||
ss.write((const char*)&emu->count, sizeof(uint32));
|
strn0cpy(eq->swap_name, emu->swap_name, sizeof(eq->swap_name));
|
||||||
|
OUT(dz_zone_id);
|
||||||
|
OUT(dz_instance_id);
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzExpeditionLockoutTimers)
|
||||||
|
{
|
||||||
|
SETUP_VAR_ENCODE(ExpeditionLockoutTimers_Struct);
|
||||||
|
|
||||||
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
|
buf.WriteUInt32(emu->count);
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
{
|
{
|
||||||
ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition));
|
buf.WriteString(emu->timers[i].expedition_name);
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
buf.WriteUInt32(emu->timers[i].seconds_remaining);
|
||||||
ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32));
|
buf.WriteInt32(emu->timers[i].event_type);
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
buf.WriteString(emu->timers[i].event_name);
|
||||||
ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event));
|
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
__packet->size = buf.size();
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzJoinExpeditionConfirm)
|
ENCODE(OP_DzSetLeaderName)
|
||||||
{
|
{
|
||||||
ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionSetLeaderName_Struct);
|
||||||
SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct);
|
SETUP_DIRECT_ENCODE(ExpeditionSetLeaderName_Struct, structs::ExpeditionSetLeaderName_Struct);
|
||||||
|
|
||||||
strncpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
OUT(client_id);
|
||||||
strncpy(eq->player_name, emu->player_name, sizeof(eq->player_name));
|
strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
||||||
|
|
||||||
FINISH_ENCODE();
|
|
||||||
}
|
|
||||||
|
|
||||||
ENCODE(OP_DzLeaderStatus)
|
|
||||||
{
|
|
||||||
SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct);
|
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
|
||||||
uint32 client_id = 0;
|
|
||||||
uint8 null_term = 0;
|
|
||||||
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write(emu->leader_name, strlen(emu->leader_name));
|
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));//1
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
@ -874,26 +886,43 @@ namespace RoF2
|
|||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionMemberList_Struct);
|
SETUP_VAR_ENCODE(ExpeditionMemberList_Struct);
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
uint32 client_id = 0;
|
buf.WriteUInt32(emu->member_count);
|
||||||
uint8 null_term = 0;
|
for (uint32 i = 0; i < emu->member_count; ++i)
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&emu->count, sizeof(uint32));
|
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
|
||||||
{
|
{
|
||||||
ss.write(emu->entries[i].name, strlen(emu->entries[i].name));
|
buf.WriteString(emu->members[i].name);
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
buf.WriteUInt8(emu->members[i].expedition_status);
|
||||||
ss.write((const char*)&emu->entries[i].status, sizeof(char));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
__packet->size = buf.size();
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzMemberListName)
|
||||||
|
{
|
||||||
|
ENCODE_LENGTH_EXACT(ExpeditionMemberListName_Struct);
|
||||||
|
SETUP_DIRECT_ENCODE(ExpeditionMemberListName_Struct, structs::ExpeditionMemberListName_Struct);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
|
OUT(add_name);
|
||||||
|
strn0cpy(eq->name, emu->name, sizeof(eq->name));
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzMemberListStatus)
|
||||||
|
{
|
||||||
|
auto emu = reinterpret_cast<ExpeditionMemberList_Struct*>((*p)->pBuffer);
|
||||||
|
if (emu->member_count == 1)
|
||||||
|
{
|
||||||
|
ENCODE_FORWARD(OP_DzMemberList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ENCODE(OP_Emote)
|
ENCODE(OP_Emote)
|
||||||
{
|
{
|
||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
@ -1876,6 +1905,7 @@ namespace RoF2
|
|||||||
OUT(FastRegenHP);
|
OUT(FastRegenHP);
|
||||||
OUT(FastRegenMana);
|
OUT(FastRegenMana);
|
||||||
OUT(FastRegenEndurance);
|
OUT(FastRegenEndurance);
|
||||||
|
OUT(underworld_teleport_index);
|
||||||
|
|
||||||
eq->FogDensity = emu->fog_density;
|
eq->FogDensity = emu->fog_density;
|
||||||
|
|
||||||
@ -4584,6 +4614,84 @@ namespace RoF2
|
|||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzAddPlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzChooseZoneReply)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::DynamicZoneChooseZoneReply_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(DynamicZoneChooseZoneReply_Struct, structs::DynamicZoneChooseZoneReply_Struct);
|
||||||
|
|
||||||
|
IN(unknown000);
|
||||||
|
IN(unknown004);
|
||||||
|
IN(unknown008);
|
||||||
|
IN(unknown_id1);
|
||||||
|
IN(dz_zone_id);
|
||||||
|
IN(dz_instance_id);
|
||||||
|
IN(dz_type);
|
||||||
|
IN(unknown_id2);
|
||||||
|
IN(unknown028);
|
||||||
|
IN(unknown032);
|
||||||
|
IN(unknown036);
|
||||||
|
IN(unknown040);
|
||||||
|
IN(unknown044);
|
||||||
|
IN(unknown048);
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzExpeditionInviteResponse)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionInviteResponse_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionInviteResponse_Struct, structs::ExpeditionInviteResponse_Struct);
|
||||||
|
|
||||||
|
IN(dz_zone_id);
|
||||||
|
IN(dz_instance_id);
|
||||||
|
IN(accepted);
|
||||||
|
IN(swapping);
|
||||||
|
strn0cpy(emu->swap_name, eq->swap_name, sizeof(emu->swap_name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzMakeLeader)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzRemovePlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzSwapPlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommandSwap_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommandSwap_Struct, structs::ExpeditionCommandSwap_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->add_player_name, eq->add_player_name, sizeof(emu->add_player_name));
|
||||||
|
strn0cpy(emu->rem_player_name, eq->rem_player_name, sizeof(emu->rem_player_name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
DECODE(OP_Emote)
|
DECODE(OP_Emote)
|
||||||
{
|
{
|
||||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||||
|
|||||||
@ -58,13 +58,16 @@ E(OP_DeleteCharge)
|
|||||||
E(OP_DeleteItem)
|
E(OP_DeleteItem)
|
||||||
E(OP_DeleteSpawn)
|
E(OP_DeleteSpawn)
|
||||||
E(OP_DisciplineUpdate)
|
E(OP_DisciplineUpdate)
|
||||||
|
E(OP_DzChooseZone)
|
||||||
E(OP_DzCompass)
|
E(OP_DzCompass)
|
||||||
E(OP_DzExpeditionEndsWarning)
|
E(OP_DzExpeditionEndsWarning)
|
||||||
E(OP_DzExpeditionInfo)
|
E(OP_DzExpeditionInfo)
|
||||||
E(OP_DzExpeditionList)
|
E(OP_DzExpeditionInvite)
|
||||||
E(OP_DzJoinExpeditionConfirm)
|
E(OP_DzExpeditionLockoutTimers)
|
||||||
E(OP_DzLeaderStatus)
|
|
||||||
E(OP_DzMemberList)
|
E(OP_DzMemberList)
|
||||||
|
E(OP_DzMemberListName)
|
||||||
|
E(OP_DzMemberListStatus)
|
||||||
|
E(OP_DzSetLeaderName)
|
||||||
E(OP_Emote)
|
E(OP_Emote)
|
||||||
E(OP_ExpansionInfo)
|
E(OP_ExpansionInfo)
|
||||||
E(OP_FormattedMessage)
|
E(OP_FormattedMessage)
|
||||||
@ -159,6 +162,12 @@ D(OP_ConsiderCorpse)
|
|||||||
D(OP_Consume)
|
D(OP_Consume)
|
||||||
D(OP_Damage)
|
D(OP_Damage)
|
||||||
D(OP_DeleteItem)
|
D(OP_DeleteItem)
|
||||||
|
D(OP_DzAddPlayer)
|
||||||
|
D(OP_DzChooseZoneReply)
|
||||||
|
D(OP_DzExpeditionInviteResponse)
|
||||||
|
D(OP_DzMakeLeader)
|
||||||
|
D(OP_DzRemovePlayer)
|
||||||
|
D(OP_DzSwapPlayer)
|
||||||
D(OP_Emote)
|
D(OP_Emote)
|
||||||
D(OP_EnvDamage)
|
D(OP_EnvDamage)
|
||||||
D(OP_FaceChange)
|
D(OP_FaceChange)
|
||||||
|
|||||||
@ -628,7 +628,7 @@ struct NewZone_Struct {
|
|||||||
/*0856*/ uint32 scriptNPCReceivedanItem;
|
/*0856*/ uint32 scriptNPCReceivedanItem;
|
||||||
/*0860*/ uint32 bCheck; // padded bool
|
/*0860*/ uint32 bCheck; // padded bool
|
||||||
/*0864*/ uint32 scriptIDSomething;
|
/*0864*/ uint32 scriptIDSomething;
|
||||||
/*0868*/ uint32 scriptIDSomething2;
|
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
|
||||||
/*0872*/ uint32 scriptIDSomething3;
|
/*0872*/ uint32 scriptIDSomething3;
|
||||||
/*0876*/ uint32 SuspendBuffs; // padded bool
|
/*0876*/ uint32 SuspendBuffs; // padded bool
|
||||||
/*0880*/ uint32 LavaDamage; // LavaDamage value
|
/*0880*/ uint32 LavaDamage; // LavaDamage value
|
||||||
@ -4882,52 +4882,169 @@ struct VeteranClaim
|
|||||||
/*076*/ uint32 action;
|
/*076*/ uint32 action;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionEntryHeader_Struct
|
struct ExpeditionInvite_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id; // unique character id
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char inviter_name[64];
|
||||||
|
/*072*/ char expedition_name[128];
|
||||||
|
/*200*/ uint8 swapping; // 0: adding 1: swapping
|
||||||
|
/*201*/ char swap_name[64]; // if swapping, swap name being removed
|
||||||
|
/*265*/ uint8 padding[3];
|
||||||
|
/*268*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply
|
||||||
|
/*270*/ uint16 dz_instance_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionInviteResponse_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 unknown000;
|
/*000*/ uint32 unknown000;
|
||||||
/*000*/ uint32 number_of_entries;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ExpeditionJoinPrompt_Struct
|
|
||||||
{
|
|
||||||
/*000*/ uint32 clientid;
|
|
||||||
/*004*/ uint32 unknown004;
|
/*004*/ uint32 unknown004;
|
||||||
/*008*/ char player_name[64];
|
/*008*/ uint16 dz_zone_id; // dz_id pair sent in invite
|
||||||
/*072*/ char expedition_name[64];
|
/*010*/ uint16 dz_instance_id;
|
||||||
};
|
/*012*/ uint8 accepted; // 0: declined 1: accepted
|
||||||
|
/*013*/ uint8 swapping; // 0: adding 1: swapping (sent in invite)
|
||||||
struct ExpeditionExpireWarning
|
/*014*/ char swap_name[64]; // swap name sent in invite
|
||||||
{
|
/*078*/ uint8 unknown078; // padding garbage?
|
||||||
/*000*/ uint32 clientid;
|
/*079*/ uint8 unknown079; // padding garbage?
|
||||||
/*004*/ uint32 unknown004;
|
|
||||||
/*008*/ uint32 minutes_remaining;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionInfo_Struct
|
struct ExpeditionInfo_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint32 client_id;
|
||||||
/*004*/ uint32 unknown004;
|
/*004*/ uint32 unknown004;
|
||||||
/*008*/ uint32 unknown008;
|
/*008*/ uint32 assigned; // padded bool, 0: not in expedition (clear data), 1: in expedition
|
||||||
/*012*/ uint32 max_players;
|
/*012*/ uint32 max_players;
|
||||||
/*016*/ char expedition_name[128];
|
/*016*/ char expedition_name[128];
|
||||||
/*142*/ char leader_name[64];
|
/*144*/ char leader_name[64];
|
||||||
|
//*208*/ uint32 unknown208; // live sends 01 00 00 00 here but client doesn't read it
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompassEntry_Struct
|
struct ExpeditionMemberEntry_Struct
|
||||||
{
|
{
|
||||||
/*000*/ float unknown000; //seen *((uint32*)) = 1584791871
|
/*000*/ char name[1]; // variable length, null terminated, max 0x40 (64)
|
||||||
/*004*/ uint32 enabled; //guess
|
/*000*/ uint8 expedition_status; // 0: unknown 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead
|
||||||
/*008*/ uint32 unknown008; //seen 1019
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberList_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 member_count; // number of players in window
|
||||||
|
/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberListName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status
|
||||||
|
/*012*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimerEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ char expedition_name[1]; // variable length, null terminated, max 0x80 (128)
|
||||||
|
/*000*/ uint32 seconds_remaining;
|
||||||
|
/*000*/ int32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers
|
||||||
|
/*000*/ char event_name[1]; // variable length, null terminated, max 0x100 (256)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimers_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionSetLeaderName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char leader_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommand_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommandSwap_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char add_player_name[64]; // swap to (player must confirm)
|
||||||
|
/*072*/ char rem_player_name[64]; // swap from
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionExpireWarning
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ uint32 minutes_remaining;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneCompassEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint16 dz_zone_id; // target dz id pair
|
||||||
|
/*002*/ uint16 dz_instance_id;
|
||||||
|
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
|
||||||
|
/*008*/ uint32 unknown008;
|
||||||
/*012*/ float y;
|
/*012*/ float y;
|
||||||
/*016*/ float x;
|
/*016*/ float x;
|
||||||
/*020*/ float z;
|
/*020*/ float z;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompass_Struct
|
struct DynamicZoneCompass_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint32 client_id;
|
||||||
/*004*/ uint32 count;
|
/*004*/ uint32 count;
|
||||||
/*008*/ ExpeditionCompassEntry_Struct entries[0];
|
/*008*/ DynamicZoneCompassEntry_Struct entries[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZoneEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint16 dz_zone_id; // dz_id pair
|
||||||
|
/*002*/ uint16 dz_instance_id;
|
||||||
|
/*004*/ uint32 unknown_id1; // seen 28 00 00 00 (40), sent back in reply
|
||||||
|
/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply
|
||||||
|
/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different
|
||||||
|
/*016*/ char description[1]; // variable length, null terminated, max 0x80 (128)
|
||||||
|
/*000*/ char leader_name[1]; // variable length, null terminated, max 0x40 (64)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZone_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZoneReply_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000; // ff ff ff ff
|
||||||
|
/*004*/ uint32 unknown004; // seen 69 00 00 00
|
||||||
|
/*008*/ uint32 unknown008; // ff ff ff ff
|
||||||
|
/*012*/ uint32 unknown_id1; // from choose zone entry message
|
||||||
|
/*016*/ uint16 dz_zone_id; // dz_id pair
|
||||||
|
/*018*/ uint16 dz_instance_id;
|
||||||
|
/*020*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest
|
||||||
|
/*024*/ uint32 unknown_id2; // from choose zone entry message
|
||||||
|
/*028*/ uint32 unknown028; // 00 00 00 00
|
||||||
|
/*032*/ uint32 unknown032; // always same as unknown044
|
||||||
|
/*036*/ uint32 unknown036;
|
||||||
|
/*040*/ uint32 unknown040;
|
||||||
|
/*044*/ uint32 unknown044; // always same as unknown032
|
||||||
|
/*048*/ uint32 unknown048; // seen 01 00 00 00 and 02 00 00 00
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KickPlayers_Struct
|
||||||
|
{
|
||||||
|
/*000*/ char char_name[64];
|
||||||
|
/*064*/ uint32 unknown064; // always 0
|
||||||
|
/*068*/ uint8 kick_expedition; // true if /kickplayers exp
|
||||||
|
/*069*/ uint8 kick_task; // true if /kickplayers task
|
||||||
|
/*070*/ uint8 padding[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MaxCharacters_Struct
|
struct MaxCharacters_Struct
|
||||||
|
|||||||
@ -44,13 +44,16 @@ E(OP_DeleteCharge)
|
|||||||
E(OP_DeleteItem)
|
E(OP_DeleteItem)
|
||||||
E(OP_DeleteSpawn)
|
E(OP_DeleteSpawn)
|
||||||
E(OP_DisciplineUpdate)
|
E(OP_DisciplineUpdate)
|
||||||
|
E(OP_DzChooseZone)
|
||||||
E(OP_DzCompass)
|
E(OP_DzCompass)
|
||||||
E(OP_DzExpeditionEndsWarning)
|
E(OP_DzExpeditionEndsWarning)
|
||||||
E(OP_DzExpeditionInfo)
|
E(OP_DzExpeditionInfo)
|
||||||
E(OP_DzExpeditionList)
|
E(OP_DzExpeditionInvite)
|
||||||
E(OP_DzJoinExpeditionConfirm)
|
E(OP_DzExpeditionLockoutTimers)
|
||||||
E(OP_DzLeaderStatus)
|
|
||||||
E(OP_DzMemberList)
|
E(OP_DzMemberList)
|
||||||
|
E(OP_DzMemberListName)
|
||||||
|
E(OP_DzMemberListStatus)
|
||||||
|
E(OP_DzSetLeaderName)
|
||||||
E(OP_Emote)
|
E(OP_Emote)
|
||||||
E(OP_ExpansionInfo)
|
E(OP_ExpansionInfo)
|
||||||
E(OP_FormattedMessage)
|
E(OP_FormattedMessage)
|
||||||
@ -145,6 +148,12 @@ D(OP_ConsiderCorpse)
|
|||||||
D(OP_Consume)
|
D(OP_Consume)
|
||||||
D(OP_Damage)
|
D(OP_Damage)
|
||||||
D(OP_DeleteItem)
|
D(OP_DeleteItem)
|
||||||
|
D(OP_DzAddPlayer)
|
||||||
|
D(OP_DzChooseZoneReply)
|
||||||
|
D(OP_DzExpeditionInviteResponse)
|
||||||
|
D(OP_DzMakeLeader)
|
||||||
|
D(OP_DzRemovePlayer)
|
||||||
|
D(OP_DzSwapPlayer)
|
||||||
D(OP_Emote)
|
D(OP_Emote)
|
||||||
D(OP_EnvDamage)
|
D(OP_EnvDamage)
|
||||||
D(OP_FaceChange)
|
D(OP_FaceChange)
|
||||||
|
|||||||
@ -575,7 +575,11 @@ struct NewZone_Struct {
|
|||||||
/*0848*/ int32 unknown848;
|
/*0848*/ int32 unknown848;
|
||||||
/*0852*/ uint16 zone_id;
|
/*0852*/ uint16 zone_id;
|
||||||
/*0854*/ uint16 zone_instance;
|
/*0854*/ uint16 zone_instance;
|
||||||
/*0856*/ char unknown856[20];
|
/*0856*/ uint32 scriptNPCReceivedanItem;
|
||||||
|
/*0860*/ uint32 bCheck; // padded bool
|
||||||
|
/*0864*/ uint32 scriptIDSomething;
|
||||||
|
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
|
||||||
|
/*0872*/ uint32 scriptIDSomething3;
|
||||||
/*0876*/ uint32 SuspendBuffs;
|
/*0876*/ uint32 SuspendBuffs;
|
||||||
/*0880*/ uint32 unknown880; // Seen 50
|
/*0880*/ uint32 unknown880; // Seen 50
|
||||||
/*0884*/ uint32 unknown884; // Seen 10
|
/*0884*/ uint32 unknown884; // Seen 10
|
||||||
@ -4811,52 +4815,159 @@ struct VeteranClaim
|
|||||||
/*076*/ uint32 action;
|
/*076*/ uint32 action;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionEntryHeader_Struct
|
struct ExpeditionInvite_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id; // unique character id
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char inviter_name[64];
|
||||||
|
/*072*/ char expedition_name[128];
|
||||||
|
/*200*/ uint8 swapping; // 0: adding 1: swapping
|
||||||
|
/*201*/ char swap_name[64]; // if swapping, swap name being removed
|
||||||
|
/*265*/ uint8 padding[3];
|
||||||
|
/*268*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply
|
||||||
|
/*270*/ uint16 dz_instance_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionInviteResponse_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 unknown000;
|
/*000*/ uint32 unknown000;
|
||||||
/*000*/ uint32 number_of_entries;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ExpeditionJoinPrompt_Struct
|
|
||||||
{
|
|
||||||
/*000*/ uint32 clientid;
|
|
||||||
/*004*/ uint32 unknown004;
|
/*004*/ uint32 unknown004;
|
||||||
/*008*/ char player_name[64];
|
/*008*/ uint16 dz_zone_id; // dz_id pair sent in invite
|
||||||
/*072*/ char expedition_name[64];
|
/*010*/ uint16 dz_instance_id;
|
||||||
};
|
/*012*/ uint8 accepted; // 0: declined 1: accepted
|
||||||
|
/*013*/ uint8 swapping; // 0: adding 1: swapping (sent in invite)
|
||||||
struct ExpeditionExpireWarning
|
/*014*/ char swap_name[64]; // swap name sent in invite
|
||||||
{
|
/*078*/ uint8 unknown078; // padding garbage?
|
||||||
/*000*/ uint32 clientid;
|
/*079*/ uint8 unknown079; // padding garbage?
|
||||||
/*004*/ uint32 unknown004;
|
|
||||||
/*008*/ uint32 minutes_remaining;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionInfo_Struct
|
struct ExpeditionInfo_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint32 client_id;
|
||||||
/*004*/ uint32 unknown004;
|
/*004*/ uint32 unknown004;
|
||||||
/*008*/ uint32 unknown008;
|
/*008*/ uint32 assigned; // padded bool
|
||||||
/*012*/ uint32 max_players;
|
/*012*/ uint32 max_players;
|
||||||
/*016*/ char expedition_name[128];
|
/*016*/ char expedition_name[128];
|
||||||
/*142*/ char leader_name[64];
|
/*144*/ char leader_name[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompassEntry_Struct
|
struct ExpeditionMemberEntry_Struct
|
||||||
{
|
{
|
||||||
/*000*/ float unknown000; //seen *((uint32*)) = 1584791871
|
/*000*/ char name[1]; // variable length, null terminated, max 0x40 (64)
|
||||||
/*004*/ uint32 enabled; //guess
|
/*000*/ uint8 expedition_status; // 0: unknown 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead
|
||||||
/*008*/ uint32 unknown008; //seen 1019
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberList_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 member_count; // number of players in window
|
||||||
|
/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberListName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status
|
||||||
|
/*012*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimerEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ char expedition_name[1]; // variable length, null terminated, max 0x80 (128)
|
||||||
|
/*000*/ uint32 seconds_remaining;
|
||||||
|
/*000*/ int32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers
|
||||||
|
/*000*/ char event_name[1]; // variable length, null terminated, max 0x100 (256)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimers_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionSetLeaderName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char leader_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommand_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommandSwap_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char add_player_name[64]; // swap to (player must confirm)
|
||||||
|
/*072*/ char rem_player_name[64]; // swap from
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionExpireWarning
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ uint32 minutes_remaining;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneCompassEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint16 dz_zone_id; // target dz id pair
|
||||||
|
/*002*/ uint16 dz_instance_id;
|
||||||
|
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
|
||||||
|
/*008*/ uint32 unknown008;
|
||||||
/*012*/ float y;
|
/*012*/ float y;
|
||||||
/*016*/ float x;
|
/*016*/ float x;
|
||||||
/*020*/ float z;
|
/*020*/ float z;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompass_Struct
|
struct DynamicZoneCompass_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint32 client_id;
|
||||||
/*004*/ uint32 count;
|
/*004*/ uint32 count;
|
||||||
/*008*/ ExpeditionCompassEntry_Struct entries[0];
|
/*008*/ DynamicZoneCompassEntry_Struct entries[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZoneEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint16 dz_zone_id; // dz_id pair
|
||||||
|
/*002*/ uint16 dz_instance_id;
|
||||||
|
/*004*/ uint32 unknown_id1; // sent back in reply
|
||||||
|
/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply
|
||||||
|
/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different
|
||||||
|
/*016*/ char description[1]; // variable length, null terminated, max 0x80 (128)
|
||||||
|
/*000*/ char leader_name[1]; // variable length, null terminated, max 0x40 (64)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZone_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZoneReply_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000; // ff ff ff ff
|
||||||
|
/*004*/ uint32 unknown004; // seen 69 00 00 00
|
||||||
|
/*008*/ uint32 unknown008; // ff ff ff ff
|
||||||
|
/*012*/ uint32 unknown_id1; // from choose zone entry message
|
||||||
|
/*016*/ uint16 dz_zone_id; // dz_id pair
|
||||||
|
/*018*/ uint16 dz_instance_id;
|
||||||
|
/*020*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest
|
||||||
|
/*024*/ uint32 unknown_id2; // from choose zone entry message
|
||||||
|
/*028*/ uint32 unknown028; // 00 00 00 00
|
||||||
|
/*032*/ uint32 unknown032; // always same as unknown044
|
||||||
|
/*036*/ uint32 unknown036;
|
||||||
|
/*040*/ uint32 unknown040;
|
||||||
|
/*044*/ uint32 unknown044; // always same as unknown032
|
||||||
|
/*048*/ uint32 unknown048; // seen 01 00 00 00 and 02 00 00 00
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MaxCharacters_Struct
|
struct MaxCharacters_Struct
|
||||||
|
|||||||
@ -483,15 +483,48 @@ namespace SoD
|
|||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzChooseZone)
|
||||||
|
{
|
||||||
|
SETUP_VAR_ENCODE(DynamicZoneChooseZone_Struct);
|
||||||
|
|
||||||
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
|
buf.WriteUInt32(emu->count);
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
|
{
|
||||||
|
buf.WriteUInt16(emu->choices[i].dz_zone_id);
|
||||||
|
buf.WriteUInt16(emu->choices[i].dz_instance_id);
|
||||||
|
buf.WriteUInt32(emu->choices[i].unknown_id1);
|
||||||
|
buf.WriteUInt32(emu->choices[i].dz_type);
|
||||||
|
buf.WriteUInt32(emu->choices[i].unknown_id2);
|
||||||
|
buf.WriteString(emu->choices[i].description);
|
||||||
|
buf.WriteString(emu->choices[i].leader_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
__packet->size = buf.size();
|
||||||
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzCompass)
|
ENCODE(OP_DzCompass)
|
||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionCompass_Struct);
|
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
|
||||||
ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count);
|
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
|
||||||
|
sizeof(structs::DynamicZoneCompass_Struct) +
|
||||||
|
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
|
||||||
|
);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
OUT(count);
|
OUT(count);
|
||||||
|
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
{
|
{
|
||||||
|
OUT(entries[i].dz_zone_id);
|
||||||
|
OUT(entries[i].dz_instance_id);
|
||||||
|
OUT(entries[i].dz_type);
|
||||||
OUT(entries[i].x);
|
OUT(entries[i].x);
|
||||||
OUT(entries[i].y);
|
OUT(entries[i].y);
|
||||||
OUT(entries[i].z);
|
OUT(entries[i].z);
|
||||||
@ -515,81 +548,60 @@ namespace SoD
|
|||||||
ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct);
|
||||||
SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct);
|
SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
|
OUT(assigned);
|
||||||
OUT(max_players);
|
OUT(max_players);
|
||||||
eq->unknown004 = 785316192;
|
strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
||||||
eq->unknown008 = 435601;
|
strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
||||||
strcpy(eq->expedition_name, emu->expedition_name);
|
|
||||||
strcpy(eq->leader_name, emu->leader_name);
|
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzExpeditionList)
|
ENCODE(OP_DzExpeditionInvite)
|
||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionInvite_Struct);
|
||||||
|
SETUP_DIRECT_ENCODE(ExpeditionInvite_Struct, structs::ExpeditionInvite_Struct);
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
OUT(client_id);
|
||||||
uint32 client_id = 0;
|
strn0cpy(eq->inviter_name, emu->inviter_name, sizeof(eq->inviter_name));
|
||||||
uint8 null_term = 0;
|
strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
OUT(swapping);
|
||||||
ss.write((const char*)&emu->count, sizeof(uint32));
|
strn0cpy(eq->swap_name, emu->swap_name, sizeof(eq->swap_name));
|
||||||
|
OUT(dz_zone_id);
|
||||||
|
OUT(dz_instance_id);
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzExpeditionLockoutTimers)
|
||||||
|
{
|
||||||
|
SETUP_VAR_ENCODE(ExpeditionLockoutTimers_Struct);
|
||||||
|
|
||||||
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
|
buf.WriteUInt32(emu->count);
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
{
|
{
|
||||||
ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition));
|
buf.WriteString(emu->timers[i].expedition_name);
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
buf.WriteUInt32(emu->timers[i].seconds_remaining);
|
||||||
ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32));
|
buf.WriteInt32(emu->timers[i].event_type);
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
buf.WriteString(emu->timers[i].event_name);
|
||||||
ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event));
|
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
__packet->size = buf.size();
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzJoinExpeditionConfirm)
|
ENCODE(OP_DzSetLeaderName)
|
||||||
{
|
{
|
||||||
ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionSetLeaderName_Struct);
|
||||||
SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct);
|
SETUP_DIRECT_ENCODE(ExpeditionSetLeaderName_Struct, structs::ExpeditionSetLeaderName_Struct);
|
||||||
|
|
||||||
strcpy(eq->expedition_name, emu->expedition_name);
|
OUT(client_id);
|
||||||
strcpy(eq->player_name, emu->player_name);
|
strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
||||||
|
|
||||||
FINISH_ENCODE();
|
|
||||||
}
|
|
||||||
|
|
||||||
ENCODE(OP_DzLeaderStatus)
|
|
||||||
{
|
|
||||||
SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct);
|
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
|
||||||
uint32 client_id = 0;
|
|
||||||
uint8 null_term = 0;
|
|
||||||
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write(emu->leader_name, strlen(emu->leader_name));
|
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));//1
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
@ -598,26 +610,44 @@ namespace SoD
|
|||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionMemberList_Struct);
|
SETUP_VAR_ENCODE(ExpeditionMemberList_Struct);
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
uint32 client_id = 0;
|
buf.WriteUInt32(emu->member_count);
|
||||||
uint8 null_term = 0;
|
for (uint32 i = 0; i < emu->member_count; ++i)
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&emu->count, sizeof(uint32));
|
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
|
||||||
{
|
{
|
||||||
ss.write(emu->entries[i].name, strlen(emu->entries[i].name));
|
buf.WriteString(emu->members[i].name);
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
buf.WriteUInt8(emu->members[i].expedition_status);
|
||||||
ss.write((const char*)&emu->entries[i].status, sizeof(char));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
__packet->size = buf.size();
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzMemberListName)
|
||||||
|
{
|
||||||
|
ENCODE_LENGTH_EXACT(ExpeditionMemberListName_Struct);
|
||||||
|
SETUP_DIRECT_ENCODE(ExpeditionMemberListName_Struct, structs::ExpeditionMemberListName_Struct);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
|
OUT(add_name);
|
||||||
|
strn0cpy(eq->name, emu->name, sizeof(eq->name));
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzMemberListStatus)
|
||||||
|
{
|
||||||
|
auto emu = reinterpret_cast<ExpeditionMemberList_Struct*>((*p)->pBuffer);
|
||||||
|
if (emu->member_count == 1)
|
||||||
|
{
|
||||||
|
ENCODE_FORWARD(OP_DzMemberList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ENCODE(OP_Emote)
|
ENCODE(OP_Emote)
|
||||||
{
|
{
|
||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
@ -1353,6 +1383,7 @@ namespace SoD
|
|||||||
OUT(FastRegenHP);
|
OUT(FastRegenHP);
|
||||||
OUT(FastRegenMana);
|
OUT(FastRegenMana);
|
||||||
OUT(FastRegenEndurance);
|
OUT(FastRegenEndurance);
|
||||||
|
OUT(underworld_teleport_index);
|
||||||
|
|
||||||
/*fill in some unknowns with observed values, hopefully it will help */
|
/*fill in some unknowns with observed values, hopefully it will help */
|
||||||
eq->unknown800 = -1;
|
eq->unknown800 = -1;
|
||||||
@ -2973,6 +3004,84 @@ namespace SoD
|
|||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzAddPlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzChooseZoneReply)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::DynamicZoneChooseZoneReply_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(DynamicZoneChooseZoneReply_Struct, structs::DynamicZoneChooseZoneReply_Struct);
|
||||||
|
|
||||||
|
IN(unknown000);
|
||||||
|
IN(unknown004);
|
||||||
|
IN(unknown008);
|
||||||
|
IN(unknown_id1);
|
||||||
|
IN(dz_zone_id);
|
||||||
|
IN(dz_instance_id);
|
||||||
|
IN(dz_type);
|
||||||
|
IN(unknown_id2);
|
||||||
|
IN(unknown028);
|
||||||
|
IN(unknown032);
|
||||||
|
IN(unknown036);
|
||||||
|
IN(unknown040);
|
||||||
|
IN(unknown044);
|
||||||
|
IN(unknown048);
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzExpeditionInviteResponse)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionInviteResponse_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionInviteResponse_Struct, structs::ExpeditionInviteResponse_Struct);
|
||||||
|
|
||||||
|
IN(dz_zone_id);
|
||||||
|
IN(dz_instance_id);
|
||||||
|
IN(accepted);
|
||||||
|
IN(swapping);
|
||||||
|
strn0cpy(emu->swap_name, eq->swap_name, sizeof(emu->swap_name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzMakeLeader)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzRemovePlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzSwapPlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommandSwap_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommandSwap_Struct, structs::ExpeditionCommandSwap_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->add_player_name, eq->add_player_name, sizeof(emu->add_player_name));
|
||||||
|
strn0cpy(emu->rem_player_name, eq->rem_player_name, sizeof(emu->rem_player_name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
DECODE(OP_Emote)
|
DECODE(OP_Emote)
|
||||||
{
|
{
|
||||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||||
|
|||||||
@ -35,13 +35,16 @@ E(OP_Consider)
|
|||||||
E(OP_Damage)
|
E(OP_Damage)
|
||||||
E(OP_DeleteCharge)
|
E(OP_DeleteCharge)
|
||||||
E(OP_DeleteItem)
|
E(OP_DeleteItem)
|
||||||
|
E(OP_DzChooseZone)
|
||||||
E(OP_DzCompass)
|
E(OP_DzCompass)
|
||||||
E(OP_DzExpeditionEndsWarning)
|
E(OP_DzExpeditionEndsWarning)
|
||||||
E(OP_DzExpeditionInfo)
|
E(OP_DzExpeditionInfo)
|
||||||
E(OP_DzExpeditionList)
|
E(OP_DzExpeditionInvite)
|
||||||
E(OP_DzJoinExpeditionConfirm)
|
E(OP_DzExpeditionLockoutTimers)
|
||||||
E(OP_DzLeaderStatus)
|
|
||||||
E(OP_DzMemberList)
|
E(OP_DzMemberList)
|
||||||
|
E(OP_DzMemberListName)
|
||||||
|
E(OP_DzMemberListStatus)
|
||||||
|
E(OP_DzSetLeaderName)
|
||||||
E(OP_Emote)
|
E(OP_Emote)
|
||||||
E(OP_ExpansionInfo)
|
E(OP_ExpansionInfo)
|
||||||
E(OP_FormattedMessage)
|
E(OP_FormattedMessage)
|
||||||
@ -111,6 +114,12 @@ D(OP_Consider)
|
|||||||
D(OP_ConsiderCorpse)
|
D(OP_ConsiderCorpse)
|
||||||
D(OP_Consume)
|
D(OP_Consume)
|
||||||
D(OP_DeleteItem)
|
D(OP_DeleteItem)
|
||||||
|
D(OP_DzAddPlayer)
|
||||||
|
D(OP_DzChooseZoneReply)
|
||||||
|
D(OP_DzExpeditionInviteResponse)
|
||||||
|
D(OP_DzMakeLeader)
|
||||||
|
D(OP_DzRemovePlayer)
|
||||||
|
D(OP_DzSwapPlayer)
|
||||||
D(OP_Emote)
|
D(OP_Emote)
|
||||||
D(OP_FaceChange)
|
D(OP_FaceChange)
|
||||||
D(OP_FindPersonRequest)
|
D(OP_FindPersonRequest)
|
||||||
|
|||||||
@ -444,7 +444,11 @@ struct NewZone_Struct {
|
|||||||
/*0848*/ int32 unknown848;
|
/*0848*/ int32 unknown848;
|
||||||
/*0852*/ uint16 zone_id;
|
/*0852*/ uint16 zone_id;
|
||||||
/*0854*/ uint16 zone_instance;
|
/*0854*/ uint16 zone_instance;
|
||||||
/*0856*/ char unknown856[20];
|
/*0856*/ uint32 scriptNPCReceivedanItem;
|
||||||
|
/*0860*/ uint32 bCheck; // padded bool
|
||||||
|
/*0864*/ uint32 scriptIDSomething;
|
||||||
|
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
|
||||||
|
/*0872*/ uint32 scriptIDSomething3;
|
||||||
/*0876*/ uint32 SuspendBuffs;
|
/*0876*/ uint32 SuspendBuffs;
|
||||||
/*0880*/ uint32 unknown880; //seen 50
|
/*0880*/ uint32 unknown880; //seen 50
|
||||||
/*0884*/ uint32 unknown884; //seen 10
|
/*0884*/ uint32 unknown884; //seen 10
|
||||||
@ -4165,52 +4169,160 @@ struct VeteranReward
|
|||||||
/*012*/ VeteranRewardItem items[8];
|
/*012*/ VeteranRewardItem items[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionEntryHeader_Struct
|
|
||||||
|
struct ExpeditionInvite_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id; // unique character id
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char inviter_name[64];
|
||||||
|
/*072*/ char expedition_name[128];
|
||||||
|
/*200*/ uint8 swapping; // 0: adding 1: swapping
|
||||||
|
/*201*/ char swap_name[64]; // if swapping, swap name being removed
|
||||||
|
/*265*/ uint8 padding[3];
|
||||||
|
/*268*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply
|
||||||
|
/*270*/ uint16 dz_instance_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionInviteResponse_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 unknown000;
|
/*000*/ uint32 unknown000;
|
||||||
/*000*/ uint32 number_of_entries;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ExpeditionJoinPrompt_Struct
|
|
||||||
{
|
|
||||||
/*000*/ uint32 clientid;
|
|
||||||
/*004*/ uint32 unknown004;
|
/*004*/ uint32 unknown004;
|
||||||
/*008*/ char player_name[64];
|
/*008*/ uint16 dz_zone_id; // dz_id pair sent in invite
|
||||||
/*072*/ char expedition_name[64];
|
/*010*/ uint16 dz_instance_id;
|
||||||
};
|
/*012*/ uint8 accepted; // 0: declined 1: accepted
|
||||||
|
/*013*/ uint8 swapping; // 0: adding 1: swapping (sent in invite)
|
||||||
struct ExpeditionExpireWarning
|
/*014*/ char swap_name[64]; // swap name sent in invite
|
||||||
{
|
/*078*/ uint8 unknown078; // padding garbage?
|
||||||
/*000*/ uint32 clientid;
|
/*079*/ uint8 unknown079; // padding garbage?
|
||||||
/*004*/ uint32 unknown004;
|
|
||||||
/*008*/ uint32 minutes_remaining;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionInfo_Struct
|
struct ExpeditionInfo_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint32 client_id;
|
||||||
/*004*/ uint32 unknown004;
|
/*004*/ uint32 unknown004;
|
||||||
/*008*/ uint32 unknown008;
|
/*008*/ uint32 assigned; // padded bool
|
||||||
/*012*/ uint32 max_players;
|
/*012*/ uint32 max_players;
|
||||||
/*016*/ char expedition_name[128];
|
/*016*/ char expedition_name[128];
|
||||||
/*142*/ char leader_name[64];
|
/*144*/ char leader_name[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompassEntry_Struct
|
struct ExpeditionMemberEntry_Struct
|
||||||
{
|
{
|
||||||
/*000*/ float unknown000; //seen *((uint32*)) = 1584791871
|
/*000*/ char name[1]; // variable length, null terminated, max 0x40 (64)
|
||||||
/*004*/ uint32 enabled; //guess
|
/*000*/ uint8 expedition_status; // 0: unknown 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead
|
||||||
/*008*/ uint32 unknown008; //seen 1019
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberList_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 member_count; // number of players in window
|
||||||
|
/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberListName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status
|
||||||
|
/*012*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimerEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ char expedition_name[1]; // variable length, null terminated, max 0x80 (128)
|
||||||
|
/*000*/ uint32 seconds_remaining;
|
||||||
|
/*000*/ int32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers
|
||||||
|
/*000*/ char event_name[1]; // variable length, null terminated, max 0x100 (256)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimers_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionSetLeaderName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char leader_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommand_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommandSwap_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char add_player_name[64]; // swap to (player must confirm)
|
||||||
|
/*072*/ char rem_player_name[64]; // swap from
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionExpireWarning
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ uint32 minutes_remaining;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneCompassEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint16 dz_zone_id; // target dz id pair
|
||||||
|
/*002*/ uint16 dz_instance_id;
|
||||||
|
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
|
||||||
|
/*008*/ uint32 unknown008;
|
||||||
/*012*/ float y;
|
/*012*/ float y;
|
||||||
/*016*/ float x;
|
/*016*/ float x;
|
||||||
/*020*/ float z;
|
/*020*/ float z;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompass_Struct
|
struct DynamicZoneCompass_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint32 client_id;
|
||||||
/*004*/ uint32 count;
|
/*004*/ uint32 count;
|
||||||
/*008*/ ExpeditionCompassEntry_Struct entries[0];
|
/*008*/ DynamicZoneCompassEntry_Struct entries[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZoneEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint16 dz_zone_id; // dz_id pair
|
||||||
|
/*002*/ uint16 dz_instance_id;
|
||||||
|
/*004*/ uint32 unknown_id1; // sent back in reply
|
||||||
|
/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply
|
||||||
|
/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different
|
||||||
|
/*016*/ char description[1]; // variable length, null terminated, max 0x80 (128)
|
||||||
|
/*000*/ char leader_name[1]; // variable length, null terminated, max 0x40 (64)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZone_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZoneReply_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000; // ff ff ff ff
|
||||||
|
/*004*/ uint32 unknown004; // seen 69 00 00 00
|
||||||
|
/*008*/ uint32 unknown008; // ff ff ff ff
|
||||||
|
/*012*/ uint32 unknown_id1; // from choose zone entry message
|
||||||
|
/*016*/ uint16 dz_zone_id; // dz_id pair
|
||||||
|
/*018*/ uint16 dz_instance_id;
|
||||||
|
/*020*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest
|
||||||
|
/*024*/ uint32 unknown_id2; // from choose zone entry message
|
||||||
|
/*028*/ uint32 unknown028; // 00 00 00 00
|
||||||
|
/*032*/ uint32 unknown032; // always same as unknown044
|
||||||
|
/*036*/ uint32 unknown036;
|
||||||
|
/*040*/ uint32 unknown040;
|
||||||
|
/*044*/ uint32 unknown044; // always same as unknown032
|
||||||
|
/*048*/ uint32 unknown048; // seen 01 00 00 00 and 02 00 00 00
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AltCurrencySelectItem_Struct {
|
struct AltCurrencySelectItem_Struct {
|
||||||
|
|||||||
@ -471,14 +471,48 @@ namespace SoF
|
|||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzChooseZone)
|
||||||
|
{
|
||||||
|
SETUP_VAR_ENCODE(DynamicZoneChooseZone_Struct);
|
||||||
|
|
||||||
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
|
buf.WriteUInt32(emu->count);
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
|
{
|
||||||
|
buf.WriteUInt16(emu->choices[i].dz_zone_id);
|
||||||
|
buf.WriteUInt16(emu->choices[i].dz_instance_id);
|
||||||
|
buf.WriteUInt32(emu->choices[i].unknown_id1);
|
||||||
|
buf.WriteUInt32(emu->choices[i].dz_type);
|
||||||
|
buf.WriteUInt32(emu->choices[i].unknown_id2);
|
||||||
|
buf.WriteString(emu->choices[i].description);
|
||||||
|
buf.WriteString(emu->choices[i].leader_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
__packet->size = buf.size();
|
||||||
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzCompass)
|
ENCODE(OP_DzCompass)
|
||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionCompass_Struct);
|
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
|
||||||
ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count);
|
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
|
||||||
|
sizeof(structs::DynamicZoneCompass_Struct) +
|
||||||
|
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
|
||||||
|
);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
OUT(count);
|
OUT(count);
|
||||||
|
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
{
|
{
|
||||||
|
OUT(entries[i].dz_zone_id);
|
||||||
|
OUT(entries[i].dz_instance_id);
|
||||||
|
OUT(entries[i].dz_type);
|
||||||
OUT(entries[i].x);
|
OUT(entries[i].x);
|
||||||
OUT(entries[i].y);
|
OUT(entries[i].y);
|
||||||
OUT(entries[i].z);
|
OUT(entries[i].z);
|
||||||
@ -502,80 +536,60 @@ namespace SoF
|
|||||||
ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct);
|
||||||
SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct);
|
SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
|
OUT(assigned);
|
||||||
OUT(max_players);
|
OUT(max_players);
|
||||||
eq->enabled_max = 1;
|
strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
||||||
strcpy(eq->expedition_name, emu->expedition_name);
|
strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
||||||
strcpy(eq->leader_name, emu->leader_name);
|
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzExpeditionList)
|
ENCODE(OP_DzExpeditionInvite)
|
||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionInvite_Struct);
|
||||||
|
SETUP_DIRECT_ENCODE(ExpeditionInvite_Struct, structs::ExpeditionInvite_Struct);
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
OUT(client_id);
|
||||||
uint32 client_id = 0;
|
strn0cpy(eq->inviter_name, emu->inviter_name, sizeof(eq->inviter_name));
|
||||||
uint8 null_term = 0;
|
strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
OUT(swapping);
|
||||||
ss.write((const char*)&emu->count, sizeof(uint32));
|
strn0cpy(eq->swap_name, emu->swap_name, sizeof(eq->swap_name));
|
||||||
for (int i = 0; i < emu->count; ++i)
|
OUT(dz_zone_id);
|
||||||
{
|
OUT(dz_instance_id);
|
||||||
ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition));
|
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
FINISH_ENCODE();
|
||||||
ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event));
|
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
ENCODE(OP_DzExpeditionLockoutTimers)
|
||||||
|
{
|
||||||
|
SETUP_VAR_ENCODE(ExpeditionLockoutTimers_Struct);
|
||||||
|
|
||||||
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
|
buf.WriteUInt32(emu->count);
|
||||||
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
|
{
|
||||||
|
buf.WriteString(emu->timers[i].expedition_name);
|
||||||
|
buf.WriteUInt32(emu->timers[i].seconds_remaining);
|
||||||
|
buf.WriteInt32(emu->timers[i].event_type);
|
||||||
|
buf.WriteString(emu->timers[i].event_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
__packet->size = buf.size();
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzJoinExpeditionConfirm)
|
ENCODE(OP_DzSetLeaderName)
|
||||||
{
|
{
|
||||||
ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionSetLeaderName_Struct);
|
||||||
SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct);
|
SETUP_DIRECT_ENCODE(ExpeditionSetLeaderName_Struct, structs::ExpeditionSetLeaderName_Struct);
|
||||||
|
|
||||||
strcpy(eq->expedition_name, emu->expedition_name);
|
OUT(client_id);
|
||||||
strcpy(eq->player_name, emu->player_name);
|
strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
||||||
|
|
||||||
FINISH_ENCODE();
|
|
||||||
}
|
|
||||||
|
|
||||||
ENCODE(OP_DzLeaderStatus)
|
|
||||||
{
|
|
||||||
SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct);
|
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
|
||||||
uint32 client_id = 0;
|
|
||||||
uint8 null_term = 0;
|
|
||||||
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
//ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write(emu->leader_name, strlen(emu->leader_name));
|
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));//1
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
@ -584,26 +598,43 @@ namespace SoF
|
|||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionMemberList_Struct);
|
SETUP_VAR_ENCODE(ExpeditionMemberList_Struct);
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
uint32 client_id = 0;
|
buf.WriteUInt32(emu->member_count);
|
||||||
uint8 null_term = 0;
|
for (uint32 i = 0; i < emu->member_count; ++i)
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&emu->count, sizeof(uint32));
|
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
|
||||||
{
|
{
|
||||||
ss.write(emu->entries[i].name, strlen(emu->entries[i].name));
|
buf.WriteString(emu->members[i].name);
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
buf.WriteUInt8(emu->members[i].expedition_status);
|
||||||
ss.write((const char*)&emu->entries[i].status, sizeof(char));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
__packet->size = buf.size();
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzMemberListName)
|
||||||
|
{
|
||||||
|
ENCODE_LENGTH_EXACT(ExpeditionMemberListName_Struct);
|
||||||
|
SETUP_DIRECT_ENCODE(ExpeditionMemberListName_Struct, structs::ExpeditionMemberListName_Struct);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
|
OUT(add_name);
|
||||||
|
strn0cpy(eq->name, emu->name, sizeof(eq->name));
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzMemberListStatus)
|
||||||
|
{
|
||||||
|
auto emu = reinterpret_cast<ExpeditionMemberList_Struct*>((*p)->pBuffer);
|
||||||
|
if (emu->member_count == 1)
|
||||||
|
{
|
||||||
|
ENCODE_FORWARD(OP_DzMemberList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ENCODE(OP_Emote)
|
ENCODE(OP_Emote)
|
||||||
{
|
{
|
||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
@ -1030,6 +1061,7 @@ namespace SoF
|
|||||||
OUT(FastRegenHP);
|
OUT(FastRegenHP);
|
||||||
OUT(FastRegenMana);
|
OUT(FastRegenMana);
|
||||||
OUT(FastRegenEndurance);
|
OUT(FastRegenEndurance);
|
||||||
|
OUT(underworld_teleport_index);
|
||||||
|
|
||||||
/*fill in some unknowns with observed values, hopefully it will help */
|
/*fill in some unknowns with observed values, hopefully it will help */
|
||||||
eq->unknown796 = -1;
|
eq->unknown796 = -1;
|
||||||
@ -2434,6 +2466,83 @@ namespace SoF
|
|||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzAddPlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzChooseZoneReply)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::DynamicZoneChooseZoneReply_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(DynamicZoneChooseZoneReply_Struct, structs::DynamicZoneChooseZoneReply_Struct);
|
||||||
|
|
||||||
|
emu->unknown000 = eq->unknown000;
|
||||||
|
emu->unknown008 = eq->unknown004;
|
||||||
|
IN(unknown_id1);
|
||||||
|
IN(dz_zone_id);
|
||||||
|
IN(dz_instance_id);
|
||||||
|
IN(dz_type);
|
||||||
|
IN(unknown_id2);
|
||||||
|
emu->unknown028 = eq->unknown024;
|
||||||
|
emu->unknown032 = eq->unknown028;
|
||||||
|
emu->unknown036 = eq->unknown032;
|
||||||
|
emu->unknown040 = eq->unknown036;
|
||||||
|
emu->unknown044 = eq->unknown040;
|
||||||
|
emu->unknown048 = eq->unknown044;
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzExpeditionInviteResponse)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionInviteResponse_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionInviteResponse_Struct, structs::ExpeditionInviteResponse_Struct);
|
||||||
|
|
||||||
|
IN(dz_zone_id);
|
||||||
|
IN(dz_instance_id);
|
||||||
|
IN(accepted);
|
||||||
|
IN(swapping);
|
||||||
|
strn0cpy(emu->swap_name, eq->swap_name, sizeof(emu->swap_name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzMakeLeader)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzRemovePlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzSwapPlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommandSwap_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommandSwap_Struct, structs::ExpeditionCommandSwap_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->add_player_name, eq->add_player_name, sizeof(emu->add_player_name));
|
||||||
|
strn0cpy(emu->rem_player_name, eq->rem_player_name, sizeof(emu->rem_player_name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
DECODE(OP_Emote)
|
DECODE(OP_Emote)
|
||||||
{
|
{
|
||||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||||
|
|||||||
@ -36,13 +36,16 @@ E(OP_Damage)
|
|||||||
E(OP_DeleteCharge)
|
E(OP_DeleteCharge)
|
||||||
E(OP_DeleteItem)
|
E(OP_DeleteItem)
|
||||||
E(OP_DeleteSpawn)
|
E(OP_DeleteSpawn)
|
||||||
|
E(OP_DzChooseZone)
|
||||||
E(OP_DzCompass)
|
E(OP_DzCompass)
|
||||||
E(OP_DzExpeditionEndsWarning)
|
E(OP_DzExpeditionEndsWarning)
|
||||||
E(OP_DzExpeditionInfo)
|
E(OP_DzExpeditionInfo)
|
||||||
E(OP_DzExpeditionList)
|
E(OP_DzExpeditionInvite)
|
||||||
E(OP_DzJoinExpeditionConfirm)
|
E(OP_DzExpeditionLockoutTimers)
|
||||||
E(OP_DzLeaderStatus)
|
|
||||||
E(OP_DzMemberList)
|
E(OP_DzMemberList)
|
||||||
|
E(OP_DzMemberListName)
|
||||||
|
E(OP_DzMemberListStatus)
|
||||||
|
E(OP_DzSetLeaderName)
|
||||||
E(OP_Emote)
|
E(OP_Emote)
|
||||||
E(OP_ExpansionInfo)
|
E(OP_ExpansionInfo)
|
||||||
E(OP_FormattedMessage)
|
E(OP_FormattedMessage)
|
||||||
@ -103,6 +106,12 @@ D(OP_Consider)
|
|||||||
D(OP_ConsiderCorpse)
|
D(OP_ConsiderCorpse)
|
||||||
D(OP_Consume)
|
D(OP_Consume)
|
||||||
D(OP_DeleteItem)
|
D(OP_DeleteItem)
|
||||||
|
D(OP_DzAddPlayer)
|
||||||
|
D(OP_DzChooseZoneReply)
|
||||||
|
D(OP_DzExpeditionInviteResponse)
|
||||||
|
D(OP_DzMakeLeader)
|
||||||
|
D(OP_DzRemovePlayer)
|
||||||
|
D(OP_DzSwapPlayer)
|
||||||
D(OP_Emote)
|
D(OP_Emote)
|
||||||
D(OP_FaceChange)
|
D(OP_FaceChange)
|
||||||
D(OP_FindPersonRequest)
|
D(OP_FindPersonRequest)
|
||||||
|
|||||||
@ -448,7 +448,11 @@ struct NewZone_Struct {
|
|||||||
/*0844*/ int32 unknown844;
|
/*0844*/ int32 unknown844;
|
||||||
/*0848*/ uint16 zone_id;
|
/*0848*/ uint16 zone_id;
|
||||||
/*0850*/ uint16 zone_instance;
|
/*0850*/ uint16 zone_instance;
|
||||||
/*0852*/ char unknown852[20];
|
/*0852*/ uint32 scriptNPCReceivedanItem;
|
||||||
|
/*0856*/ uint32 bCheck; // padded bool
|
||||||
|
/*0860*/ uint32 scriptIDSomething;
|
||||||
|
/*0864*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
|
||||||
|
/*0868*/ uint32 scriptIDSomething3;
|
||||||
/*0872*/ uint32 SuspendBuffs;
|
/*0872*/ uint32 SuspendBuffs;
|
||||||
/*0876*/ uint32 unknown876; //seen 50
|
/*0876*/ uint32 unknown876; //seen 50
|
||||||
/*0880*/ uint32 unknown880; //seen 10
|
/*0880*/ uint32 unknown880; //seen 10
|
||||||
@ -4084,43 +4088,150 @@ struct VeteranReward
|
|||||||
/*012*/ VeteranRewardItem items[8];
|
/*012*/ VeteranRewardItem items[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionExpireWarning
|
struct ExpeditionInvite_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ char inviter_name[64];
|
||||||
|
/*068*/ char expedition_name[128];
|
||||||
|
/*196*/ uint8 swapping; // 0: adding 1: swapping
|
||||||
|
/*197*/ char swap_name[64]; // if swapping, swap name being removed
|
||||||
|
/*261*/ uint8 padding[3];
|
||||||
|
/*264*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply
|
||||||
|
/*268*/ uint16 dz_instance_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionInviteResponse_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 unknown000;
|
/*000*/ uint32 unknown000;
|
||||||
/*004*/ uint32 minutes_remaining;
|
/*004*/ uint16 dz_zone_id; // dz_id pair sent in invite
|
||||||
|
/*006*/ uint16 dz_instance_id;
|
||||||
|
/*008*/ uint8 accepted; // 0: declined 1: accepted
|
||||||
|
/*009*/ uint8 swapping; // 0: adding 1: swapping (sent in invite)
|
||||||
|
/*010*/ char swap_name[64]; // swap name sent in invite
|
||||||
|
/*074*/ uint8 unknown078; // padding/garbage?
|
||||||
|
/*075*/ uint8 unknown079; // padding/garbage?
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionInfo_Struct
|
struct ExpeditionInfo_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint32 client_id;
|
||||||
/*004*/ uint32 enabled_max;
|
/*004*/ uint32 assigned; // padded bool
|
||||||
/*008*/ uint32 max_players;
|
/*008*/ uint32 max_players;
|
||||||
/*012*/ char expedition_name[128];
|
/*012*/ char expedition_name[128];
|
||||||
/*142*/ char leader_name[64];
|
/*140*/ char leader_name[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompassEntry_Struct
|
struct ExpeditionMemberEntry_Struct
|
||||||
{
|
{
|
||||||
/*000*/ float unknown000; //seen *((uint32*)) = 1584791871
|
/*000*/ char name[1]; // variable length, null terminated, max 0x40 (64)
|
||||||
/*004*/ uint32 enabled; //guess
|
/*000*/ uint8 expedition_status; // 0: unknown 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead
|
||||||
/*008*/ uint32 unknown008; //seen 1019
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberList_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 member_count;
|
||||||
|
/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberListName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status
|
||||||
|
/*008*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimerEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ char expedition_name[1]; // variable length, null terminated, max 0x80 (128)
|
||||||
|
/*000*/ uint32 seconds_remaining;
|
||||||
|
/*000*/ int32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers
|
||||||
|
/*000*/ char event_name[1]; // variable length, null terminated, max 0x100 (256)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimers_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionSetLeaderName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ char leader_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommand_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommandSwap_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ char add_player_name[64]; // swap to (player must confirm)
|
||||||
|
/*068*/ char rem_player_name[64]; // swap from
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionExpireWarning
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 minutes_remaining;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneCompassEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint16 dz_zone_id; // target dz id pair
|
||||||
|
/*002*/ uint16 dz_instance_id;
|
||||||
|
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
|
||||||
|
/*008*/ uint32 unknown008;
|
||||||
/*012*/ float y;
|
/*012*/ float y;
|
||||||
/*016*/ float x;
|
/*016*/ float x;
|
||||||
/*020*/ float z;
|
/*020*/ float z;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompass_Struct
|
struct DynamicZoneCompass_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint32 client_id;
|
||||||
/*004*/ uint32 count;
|
/*004*/ uint32 count;
|
||||||
/*008*/ ExpeditionCompassEntry_Struct entries[0];
|
/*008*/ DynamicZoneCompassEntry_Struct entries[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionJoinPrompt_Struct
|
struct DynamicZoneChooseZoneEntry_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint16 dz_zone_id; // dz_id pair
|
||||||
/*004*/ char player_name[64];
|
/*002*/ uint16 dz_instance_id;
|
||||||
/*068*/ char expedition_name[64];
|
/*004*/ uint32 unknown_id1; // sent back in reply
|
||||||
|
/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply
|
||||||
|
/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different
|
||||||
|
/*016*/ char description[1]; // variable length, null terminated, max 0x80 (128)
|
||||||
|
/*000*/ char leader_name[1]; // variable length, null terminated, max 0x40 (64)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZone_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZoneReply_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ uint32 unknown_id1;
|
||||||
|
/*012*/ uint16 dz_zone_id;
|
||||||
|
/*014*/ uint16 dz_instance_id;
|
||||||
|
/*016*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest
|
||||||
|
/*020*/ uint32 unknown_id2;
|
||||||
|
/*024*/ uint32 unknown024;
|
||||||
|
/*028*/ uint32 unknown028; // always same as unknown040
|
||||||
|
/*032*/ uint32 unknown032;
|
||||||
|
/*036*/ uint32 unknown036;
|
||||||
|
/*040*/ uint32 unknown040; // always same as unknown028
|
||||||
|
/*044*/ uint32 unknown044;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AltCurrencySelectItem_Struct {
|
struct AltCurrencySelectItem_Struct {
|
||||||
|
|||||||
@ -414,15 +414,48 @@ namespace Titanium
|
|||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzChooseZone)
|
||||||
|
{
|
||||||
|
SETUP_VAR_ENCODE(DynamicZoneChooseZone_Struct);
|
||||||
|
|
||||||
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
|
buf.WriteUInt32(emu->count);
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
|
{
|
||||||
|
buf.WriteUInt16(emu->choices[i].dz_zone_id);
|
||||||
|
buf.WriteUInt16(emu->choices[i].dz_instance_id);
|
||||||
|
buf.WriteUInt32(emu->choices[i].unknown_id1);
|
||||||
|
buf.WriteUInt32(emu->choices[i].dz_type);
|
||||||
|
buf.WriteUInt32(emu->choices[i].unknown_id2);
|
||||||
|
buf.WriteString(emu->choices[i].description);
|
||||||
|
buf.WriteString(emu->choices[i].leader_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
__packet->size = buf.size();
|
||||||
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzCompass)
|
ENCODE(OP_DzCompass)
|
||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionCompass_Struct);
|
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
|
||||||
ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count);
|
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
|
||||||
|
sizeof(structs::DynamicZoneCompass_Struct) +
|
||||||
|
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
|
||||||
|
);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
OUT(count);
|
OUT(count);
|
||||||
|
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
{
|
{
|
||||||
|
OUT(entries[i].dz_zone_id);
|
||||||
|
OUT(entries[i].dz_instance_id);
|
||||||
|
OUT(entries[i].dz_type);
|
||||||
OUT(entries[i].x);
|
OUT(entries[i].x);
|
||||||
OUT(entries[i].y);
|
OUT(entries[i].y);
|
||||||
OUT(entries[i].z);
|
OUT(entries[i].z);
|
||||||
@ -446,80 +479,60 @@ namespace Titanium
|
|||||||
ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct);
|
||||||
SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct);
|
SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
|
OUT(assigned);
|
||||||
OUT(max_players);
|
OUT(max_players);
|
||||||
eq->enabled_max = 1;
|
strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
||||||
strcpy(eq->expedition_name, emu->expedition_name);
|
strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
||||||
strcpy(eq->leader_name, emu->leader_name);
|
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzExpeditionList)
|
ENCODE(OP_DzExpeditionInvite)
|
||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionInvite_Struct);
|
||||||
|
SETUP_DIRECT_ENCODE(ExpeditionInvite_Struct, structs::ExpeditionInvite_Struct);
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
OUT(client_id);
|
||||||
uint32 client_id = 0;
|
strn0cpy(eq->inviter_name, emu->inviter_name, sizeof(eq->inviter_name));
|
||||||
uint8 null_term = 0;
|
strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
OUT(swapping);
|
||||||
ss.write((const char*)&emu->count, sizeof(uint32));
|
strn0cpy(eq->swap_name, emu->swap_name, sizeof(eq->swap_name));
|
||||||
|
OUT(dz_zone_id);
|
||||||
|
OUT(dz_instance_id);
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzExpeditionLockoutTimers)
|
||||||
|
{
|
||||||
|
SETUP_VAR_ENCODE(ExpeditionLockoutTimers_Struct);
|
||||||
|
|
||||||
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
|
buf.WriteUInt32(emu->count);
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
{
|
{
|
||||||
ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition));
|
buf.WriteString(emu->timers[i].expedition_name);
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
buf.WriteUInt32(emu->timers[i].seconds_remaining);
|
||||||
ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32));
|
buf.WriteInt32(emu->timers[i].event_type);
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
buf.WriteString(emu->timers[i].event_name);
|
||||||
ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event));
|
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
__packet->size = buf.size();
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzJoinExpeditionConfirm)
|
ENCODE(OP_DzSetLeaderName)
|
||||||
{
|
{
|
||||||
ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionSetLeaderName_Struct);
|
||||||
SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct);
|
SETUP_DIRECT_ENCODE(ExpeditionSetLeaderName_Struct, structs::ExpeditionSetLeaderName_Struct);
|
||||||
|
|
||||||
strcpy(eq->expedition_name, emu->expedition_name);
|
OUT(client_id);
|
||||||
strcpy(eq->player_name, emu->player_name);
|
strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
||||||
|
|
||||||
FINISH_ENCODE();
|
|
||||||
}
|
|
||||||
|
|
||||||
ENCODE(OP_DzLeaderStatus)
|
|
||||||
{
|
|
||||||
SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct);
|
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
|
||||||
uint32 client_id = 0;
|
|
||||||
uint8 null_term = 0;
|
|
||||||
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
//ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write(emu->leader_name, strlen(emu->leader_name));
|
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));//1
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
@ -528,26 +541,43 @@ namespace Titanium
|
|||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionMemberList_Struct);
|
SETUP_VAR_ENCODE(ExpeditionMemberList_Struct);
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
uint32 client_id = 0;
|
buf.WriteUInt32(emu->member_count);
|
||||||
uint8 null_term = 0;
|
for (uint32 i = 0; i < emu->member_count; ++i)
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&emu->count, sizeof(uint32));
|
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
|
||||||
{
|
{
|
||||||
ss.write(emu->entries[i].name, strlen(emu->entries[i].name));
|
buf.WriteString(emu->members[i].name);
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
buf.WriteUInt8(emu->members[i].expedition_status);
|
||||||
ss.write((const char*)&emu->entries[i].status, sizeof(char));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
__packet->size = buf.size();
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzMemberListName)
|
||||||
|
{
|
||||||
|
ENCODE_LENGTH_EXACT(ExpeditionMemberListName_Struct);
|
||||||
|
SETUP_DIRECT_ENCODE(ExpeditionMemberListName_Struct, structs::ExpeditionMemberListName_Struct);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
|
OUT(add_name);
|
||||||
|
strn0cpy(eq->name, emu->name, sizeof(eq->name));
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzMemberListStatus)
|
||||||
|
{
|
||||||
|
auto emu = reinterpret_cast<ExpeditionMemberList_Struct*>((*p)->pBuffer);
|
||||||
|
if (emu->member_count == 1)
|
||||||
|
{
|
||||||
|
ENCODE_FORWARD(OP_DzMemberList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ENCODE(OP_Emote)
|
ENCODE(OP_Emote)
|
||||||
{
|
{
|
||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
@ -1943,6 +1973,83 @@ namespace Titanium
|
|||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzAddPlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzChooseZoneReply)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::DynamicZoneChooseZoneReply_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(DynamicZoneChooseZoneReply_Struct, structs::DynamicZoneChooseZoneReply_Struct);
|
||||||
|
|
||||||
|
emu->unknown000 = eq->unknown000;
|
||||||
|
emu->unknown008 = eq->unknown004;
|
||||||
|
IN(unknown_id1);
|
||||||
|
IN(dz_zone_id);
|
||||||
|
IN(dz_instance_id);
|
||||||
|
IN(dz_type);
|
||||||
|
IN(unknown_id2);
|
||||||
|
emu->unknown028 = eq->unknown024;
|
||||||
|
emu->unknown032 = eq->unknown028;
|
||||||
|
emu->unknown036 = eq->unknown032;
|
||||||
|
emu->unknown040 = eq->unknown036;
|
||||||
|
emu->unknown044 = eq->unknown040;
|
||||||
|
emu->unknown048 = eq->unknown044;
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzExpeditionInviteResponse)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionInviteResponse_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionInviteResponse_Struct, structs::ExpeditionInviteResponse_Struct);
|
||||||
|
|
||||||
|
IN(dz_zone_id);
|
||||||
|
IN(dz_instance_id);
|
||||||
|
IN(accepted);
|
||||||
|
IN(swapping);
|
||||||
|
strn0cpy(emu->swap_name, eq->swap_name, sizeof(emu->swap_name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzMakeLeader)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzRemovePlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzSwapPlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommandSwap_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommandSwap_Struct, structs::ExpeditionCommandSwap_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->add_player_name, eq->add_player_name, sizeof(emu->add_player_name));
|
||||||
|
strn0cpy(emu->rem_player_name, eq->rem_player_name, sizeof(emu->rem_player_name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
DECODE(OP_Emote)
|
DECODE(OP_Emote)
|
||||||
{
|
{
|
||||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||||
|
|||||||
@ -32,13 +32,16 @@ E(OP_Damage)
|
|||||||
E(OP_DeleteCharge)
|
E(OP_DeleteCharge)
|
||||||
E(OP_DeleteItem)
|
E(OP_DeleteItem)
|
||||||
E(OP_DeleteSpawn)
|
E(OP_DeleteSpawn)
|
||||||
|
E(OP_DzChooseZone)
|
||||||
E(OP_DzCompass)
|
E(OP_DzCompass)
|
||||||
E(OP_DzExpeditionEndsWarning)
|
E(OP_DzExpeditionEndsWarning)
|
||||||
E(OP_DzExpeditionInfo)
|
E(OP_DzExpeditionInfo)
|
||||||
E(OP_DzExpeditionList)
|
E(OP_DzExpeditionInvite)
|
||||||
E(OP_DzJoinExpeditionConfirm)
|
E(OP_DzExpeditionLockoutTimers)
|
||||||
E(OP_DzLeaderStatus)
|
|
||||||
E(OP_DzMemberList)
|
E(OP_DzMemberList)
|
||||||
|
E(OP_DzMemberListName)
|
||||||
|
E(OP_DzMemberListStatus)
|
||||||
|
E(OP_DzSetLeaderName)
|
||||||
E(OP_Emote)
|
E(OP_Emote)
|
||||||
E(OP_FormattedMessage)
|
E(OP_FormattedMessage)
|
||||||
E(OP_GroundSpawn)
|
E(OP_GroundSpawn)
|
||||||
@ -86,6 +89,12 @@ D(OP_CharacterCreate)
|
|||||||
D(OP_ClientUpdate)
|
D(OP_ClientUpdate)
|
||||||
D(OP_Consume)
|
D(OP_Consume)
|
||||||
D(OP_DeleteItem)
|
D(OP_DeleteItem)
|
||||||
|
D(OP_DzAddPlayer)
|
||||||
|
D(OP_DzChooseZoneReply)
|
||||||
|
D(OP_DzExpeditionInviteResponse)
|
||||||
|
D(OP_DzMakeLeader)
|
||||||
|
D(OP_DzRemovePlayer)
|
||||||
|
D(OP_DzSwapPlayer)
|
||||||
D(OP_Emote)
|
D(OP_Emote)
|
||||||
D(OP_FaceChange)
|
D(OP_FaceChange)
|
||||||
D(OP_InspectAnswer)
|
D(OP_InspectAnswer)
|
||||||
|
|||||||
@ -3299,43 +3299,150 @@ struct VeteranReward
|
|||||||
/*004*/ VeteranRewardItem item;
|
/*004*/ VeteranRewardItem item;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionExpireWarning
|
struct ExpeditionInvite_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ char inviter_name[64];
|
||||||
|
/*068*/ char expedition_name[128];
|
||||||
|
/*196*/ uint8 swapping; // 0: adding 1: swapping
|
||||||
|
/*197*/ char swap_name[64]; // if swapping, swap name being removed
|
||||||
|
/*261*/ uint8 padding[3];
|
||||||
|
/*264*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply
|
||||||
|
/*268*/ uint16 dz_instance_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionInviteResponse_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 unknown000;
|
/*000*/ uint32 unknown000;
|
||||||
/*004*/ uint32 minutes_remaining;
|
/*004*/ uint16 dz_zone_id; // dz_id pair sent in invite
|
||||||
|
/*006*/ uint16 dz_instance_id;
|
||||||
|
/*008*/ uint8 accepted; // 0: declined 1: accepted
|
||||||
|
/*009*/ uint8 swapping; // 0: adding 1: swapping (sent in invite)
|
||||||
|
/*010*/ char swap_name[64]; // swap name sent in invite
|
||||||
|
/*074*/ uint8 unknown078; // padding/garbage?
|
||||||
|
/*075*/ uint8 unknown079; // padding/garbage?
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionInfo_Struct
|
struct ExpeditionInfo_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint32 client_id;
|
||||||
/*004*/ uint32 enabled_max;
|
/*004*/ uint32 assigned; // padded bool
|
||||||
/*008*/ uint32 max_players;
|
/*008*/ uint32 max_players;
|
||||||
/*012*/ char expedition_name[128];
|
/*012*/ char expedition_name[128];
|
||||||
/*142*/ char leader_name[64];
|
/*140*/ char leader_name[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompassEntry_Struct
|
struct ExpeditionMemberEntry_Struct
|
||||||
{
|
{
|
||||||
/*000*/ float unknown000; //seen *((uint32*)) = 1584791871
|
/*000*/ char name[1]; // variable length, null terminated, max 0x40 (64)
|
||||||
/*004*/ uint32 enabled; //guess
|
/*000*/ uint8 expedition_status; // 0: unknown 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead
|
||||||
/*008*/ uint32 unknown008; //seen 1019
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberList_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 member_count;
|
||||||
|
/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberListName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status
|
||||||
|
/*008*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimerEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ char expedition_name[1]; // variable length, null terminated, max 0x80 (128)
|
||||||
|
/*000*/ uint32 seconds_remaining;
|
||||||
|
/*000*/ int32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers
|
||||||
|
/*000*/ char event_name[1]; // variable length, null terminated, max 0x100 (256)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimers_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionSetLeaderName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ char leader_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommand_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommandSwap_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ char add_player_name[64]; // swap to (player must confirm)
|
||||||
|
/*068*/ char rem_player_name[64]; // swap from
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionExpireWarning
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 minutes_remaining;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneCompassEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint16 dz_zone_id; // target dz id pair
|
||||||
|
/*002*/ uint16 dz_instance_id;
|
||||||
|
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
|
||||||
|
/*008*/ uint32 unknown008;
|
||||||
/*012*/ float y;
|
/*012*/ float y;
|
||||||
/*016*/ float x;
|
/*016*/ float x;
|
||||||
/*020*/ float z;
|
/*020*/ float z;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompass_Struct
|
struct DynamicZoneCompass_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint32 client_id;
|
||||||
/*004*/ uint32 count;
|
/*004*/ uint32 count;
|
||||||
/*008*/ ExpeditionCompassEntry_Struct entries[0];
|
/*008*/ DynamicZoneCompassEntry_Struct entries[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionJoinPrompt_Struct
|
struct DynamicZoneChooseZoneEntry_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint16 dz_zone_id; // dz_id pair
|
||||||
/*004*/ char player_name[64];
|
/*002*/ uint16 dz_instance_id;
|
||||||
/*068*/ char expedition_name[64];
|
/*004*/ uint32 unknown_id1; // sent back in reply
|
||||||
|
/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply
|
||||||
|
/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different
|
||||||
|
/*016*/ char description[1]; // variable length, null terminated, max 0x80 (128)
|
||||||
|
/*000*/ char leader_name[1]; // variable length, null terminated, max 0x40 (64)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZone_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZoneReply_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ uint32 unknown_id1;
|
||||||
|
/*012*/ uint16 dz_zone_id;
|
||||||
|
/*014*/ uint16 dz_instance_id;
|
||||||
|
/*016*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest
|
||||||
|
/*020*/ uint32 unknown_id2;
|
||||||
|
/*024*/ uint32 unknown024;
|
||||||
|
/*028*/ uint32 unknown028; // always same as unknown040
|
||||||
|
/*032*/ uint32 unknown032;
|
||||||
|
/*036*/ uint32 unknown036;
|
||||||
|
/*040*/ uint32 unknown040; // always same as unknown028
|
||||||
|
/*044*/ uint32 unknown044;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LFGuild_SearchPlayer_Struct
|
struct LFGuild_SearchPlayer_Struct
|
||||||
|
|||||||
@ -613,14 +613,48 @@ namespace UF
|
|||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzChooseZone)
|
||||||
|
{
|
||||||
|
SETUP_VAR_ENCODE(DynamicZoneChooseZone_Struct);
|
||||||
|
|
||||||
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
|
buf.WriteUInt32(emu->count);
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
|
{
|
||||||
|
buf.WriteUInt16(emu->choices[i].dz_zone_id);
|
||||||
|
buf.WriteUInt16(emu->choices[i].dz_instance_id);
|
||||||
|
buf.WriteUInt32(emu->choices[i].unknown_id1);
|
||||||
|
buf.WriteUInt32(emu->choices[i].dz_type);
|
||||||
|
buf.WriteUInt32(emu->choices[i].unknown_id2);
|
||||||
|
buf.WriteString(emu->choices[i].description);
|
||||||
|
buf.WriteString(emu->choices[i].leader_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
__packet->size = buf.size();
|
||||||
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzCompass)
|
ENCODE(OP_DzCompass)
|
||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionCompass_Struct);
|
SETUP_VAR_ENCODE(DynamicZoneCompass_Struct);
|
||||||
ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count);
|
ALLOC_VAR_ENCODE(structs::DynamicZoneCompass_Struct,
|
||||||
|
sizeof(structs::DynamicZoneCompass_Struct) +
|
||||||
|
sizeof(structs::DynamicZoneCompassEntry_Struct) * emu->count
|
||||||
|
);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
OUT(count);
|
OUT(count);
|
||||||
|
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
{
|
{
|
||||||
|
OUT(entries[i].dz_zone_id);
|
||||||
|
OUT(entries[i].dz_instance_id);
|
||||||
|
OUT(entries[i].dz_type);
|
||||||
OUT(entries[i].x);
|
OUT(entries[i].x);
|
||||||
OUT(entries[i].y);
|
OUT(entries[i].y);
|
||||||
OUT(entries[i].z);
|
OUT(entries[i].z);
|
||||||
@ -644,81 +678,60 @@ namespace UF
|
|||||||
ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct);
|
||||||
SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct);
|
SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
|
OUT(assigned);
|
||||||
OUT(max_players);
|
OUT(max_players);
|
||||||
eq->unknown004 = 785316192;
|
strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
||||||
eq->unknown008 = 435601;
|
strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
||||||
strcpy(eq->expedition_name, emu->expedition_name);
|
|
||||||
strcpy(eq->leader_name, emu->leader_name);
|
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzExpeditionList)
|
ENCODE(OP_DzExpeditionInvite)
|
||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionInvite_Struct);
|
||||||
|
SETUP_DIRECT_ENCODE(ExpeditionInvite_Struct, structs::ExpeditionInvite_Struct);
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
OUT(client_id);
|
||||||
uint32 client_id = 0;
|
strn0cpy(eq->inviter_name, emu->inviter_name, sizeof(eq->inviter_name));
|
||||||
uint8 null_term = 0;
|
strn0cpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name));
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
OUT(swapping);
|
||||||
ss.write((const char*)&emu->count, sizeof(uint32));
|
strn0cpy(eq->swap_name, emu->swap_name, sizeof(eq->swap_name));
|
||||||
|
OUT(dz_zone_id);
|
||||||
|
OUT(dz_instance_id);
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzExpeditionLockoutTimers)
|
||||||
|
{
|
||||||
|
SETUP_VAR_ENCODE(ExpeditionLockoutTimers_Struct);
|
||||||
|
|
||||||
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
|
buf.WriteUInt32(emu->count);
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
for (uint32 i = 0; i < emu->count; ++i)
|
||||||
{
|
{
|
||||||
ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition));
|
buf.WriteString(emu->timers[i].expedition_name);
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
buf.WriteUInt32(emu->timers[i].seconds_remaining);
|
||||||
ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32));
|
buf.WriteInt32(emu->timers[i].event_type);
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
buf.WriteString(emu->timers[i].event_name);
|
||||||
ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event));
|
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
__packet->size = buf.size();
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODE(OP_DzJoinExpeditionConfirm)
|
ENCODE(OP_DzSetLeaderName)
|
||||||
{
|
{
|
||||||
ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct);
|
ENCODE_LENGTH_EXACT(ExpeditionSetLeaderName_Struct);
|
||||||
SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct);
|
SETUP_DIRECT_ENCODE(ExpeditionSetLeaderName_Struct, structs::ExpeditionSetLeaderName_Struct);
|
||||||
|
|
||||||
strcpy(eq->expedition_name, emu->expedition_name);
|
OUT(client_id);
|
||||||
strcpy(eq->player_name, emu->player_name);
|
strn0cpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name));
|
||||||
|
|
||||||
FINISH_ENCODE();
|
|
||||||
}
|
|
||||||
|
|
||||||
ENCODE(OP_DzLeaderStatus)
|
|
||||||
{
|
|
||||||
SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct);
|
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
|
||||||
uint32 client_id = 0;
|
|
||||||
uint8 null_term = 0;
|
|
||||||
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write(emu->leader_name, strlen(emu->leader_name));
|
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));//1
|
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
@ -727,26 +740,43 @@ namespace UF
|
|||||||
{
|
{
|
||||||
SETUP_VAR_ENCODE(ExpeditionMemberList_Struct);
|
SETUP_VAR_ENCODE(ExpeditionMemberList_Struct);
|
||||||
|
|
||||||
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
|
SerializeBuffer buf;
|
||||||
|
buf.WriteUInt32(emu->client_id);
|
||||||
uint32 client_id = 0;
|
buf.WriteUInt32(emu->member_count);
|
||||||
uint8 null_term = 0;
|
for (uint32 i = 0; i < emu->member_count; ++i)
|
||||||
ss.write((const char*)&client_id, sizeof(uint32));
|
|
||||||
ss.write((const char*)&emu->count, sizeof(uint32));
|
|
||||||
for (uint32 i = 0; i < emu->count; ++i)
|
|
||||||
{
|
{
|
||||||
ss.write(emu->entries[i].name, strlen(emu->entries[i].name));
|
buf.WriteString(emu->members[i].name);
|
||||||
ss.write((const char*)&null_term, sizeof(char));
|
buf.WriteUInt8(emu->members[i].expedition_status);
|
||||||
ss.write((const char*)&emu->entries[i].status, sizeof(char));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__packet->size = ss.str().length();
|
__packet->size = buf.size();
|
||||||
__packet->pBuffer = new unsigned char[__packet->size];
|
__packet->pBuffer = new unsigned char[__packet->size];
|
||||||
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
|
memcpy(__packet->pBuffer, buf.buffer(), __packet->size);
|
||||||
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzMemberListName)
|
||||||
|
{
|
||||||
|
ENCODE_LENGTH_EXACT(ExpeditionMemberListName_Struct);
|
||||||
|
SETUP_DIRECT_ENCODE(ExpeditionMemberListName_Struct, structs::ExpeditionMemberListName_Struct);
|
||||||
|
|
||||||
|
OUT(client_id);
|
||||||
|
OUT(add_name);
|
||||||
|
strn0cpy(eq->name, emu->name, sizeof(eq->name));
|
||||||
|
|
||||||
|
FINISH_ENCODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
ENCODE(OP_DzMemberListStatus)
|
||||||
|
{
|
||||||
|
auto emu = reinterpret_cast<ExpeditionMemberList_Struct*>((*p)->pBuffer);
|
||||||
|
if (emu->member_count == 1)
|
||||||
|
{
|
||||||
|
ENCODE_FORWARD(OP_DzMemberList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ENCODE(OP_Emote)
|
ENCODE(OP_Emote)
|
||||||
{
|
{
|
||||||
EQApplicationPacket *in = *p;
|
EQApplicationPacket *in = *p;
|
||||||
@ -1577,6 +1607,7 @@ namespace UF
|
|||||||
OUT(FastRegenHP);
|
OUT(FastRegenHP);
|
||||||
OUT(FastRegenMana);
|
OUT(FastRegenMana);
|
||||||
OUT(FastRegenEndurance);
|
OUT(FastRegenEndurance);
|
||||||
|
OUT(underworld_teleport_index);
|
||||||
|
|
||||||
eq->FogDensity = emu->fog_density;
|
eq->FogDensity = emu->fog_density;
|
||||||
|
|
||||||
@ -3314,6 +3345,84 @@ namespace UF
|
|||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzAddPlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzChooseZoneReply)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::DynamicZoneChooseZoneReply_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(DynamicZoneChooseZoneReply_Struct, structs::DynamicZoneChooseZoneReply_Struct);
|
||||||
|
|
||||||
|
IN(unknown000);
|
||||||
|
IN(unknown004);
|
||||||
|
IN(unknown008);
|
||||||
|
IN(unknown_id1);
|
||||||
|
IN(dz_zone_id);
|
||||||
|
IN(dz_instance_id);
|
||||||
|
IN(dz_type);
|
||||||
|
IN(unknown_id2);
|
||||||
|
IN(unknown028);
|
||||||
|
IN(unknown032);
|
||||||
|
IN(unknown036);
|
||||||
|
IN(unknown040);
|
||||||
|
IN(unknown044);
|
||||||
|
IN(unknown048);
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzExpeditionInviteResponse)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionInviteResponse_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionInviteResponse_Struct, structs::ExpeditionInviteResponse_Struct);
|
||||||
|
|
||||||
|
IN(dz_zone_id);
|
||||||
|
IN(dz_instance_id);
|
||||||
|
IN(accepted);
|
||||||
|
IN(swapping);
|
||||||
|
strn0cpy(emu->swap_name, eq->swap_name, sizeof(emu->swap_name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzMakeLeader)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzRemovePlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommand_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommand_Struct, structs::ExpeditionCommand_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->name, eq->name, sizeof(emu->name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECODE(OP_DzSwapPlayer)
|
||||||
|
{
|
||||||
|
DECODE_LENGTH_EXACT(structs::ExpeditionCommandSwap_Struct);
|
||||||
|
SETUP_DIRECT_DECODE(ExpeditionCommandSwap_Struct, structs::ExpeditionCommandSwap_Struct);
|
||||||
|
|
||||||
|
strn0cpy(emu->add_player_name, eq->add_player_name, sizeof(emu->add_player_name));
|
||||||
|
strn0cpy(emu->rem_player_name, eq->rem_player_name, sizeof(emu->rem_player_name));
|
||||||
|
|
||||||
|
FINISH_DIRECT_DECODE();
|
||||||
|
}
|
||||||
|
|
||||||
DECODE(OP_Emote)
|
DECODE(OP_Emote)
|
||||||
{
|
{
|
||||||
unsigned char *__eq_buffer = __packet->pBuffer;
|
unsigned char *__eq_buffer = __packet->pBuffer;
|
||||||
|
|||||||
@ -38,13 +38,16 @@ E(OP_Damage)
|
|||||||
E(OP_DeleteCharge)
|
E(OP_DeleteCharge)
|
||||||
E(OP_DeleteItem)
|
E(OP_DeleteItem)
|
||||||
E(OP_DisciplineUpdate)
|
E(OP_DisciplineUpdate)
|
||||||
|
E(OP_DzChooseZone)
|
||||||
E(OP_DzCompass)
|
E(OP_DzCompass)
|
||||||
E(OP_DzExpeditionEndsWarning)
|
E(OP_DzExpeditionEndsWarning)
|
||||||
E(OP_DzExpeditionInfo)
|
E(OP_DzExpeditionInfo)
|
||||||
E(OP_DzExpeditionList)
|
E(OP_DzExpeditionInvite)
|
||||||
E(OP_DzJoinExpeditionConfirm)
|
E(OP_DzExpeditionLockoutTimers)
|
||||||
E(OP_DzLeaderStatus)
|
|
||||||
E(OP_DzMemberList)
|
E(OP_DzMemberList)
|
||||||
|
E(OP_DzMemberListName)
|
||||||
|
E(OP_DzMemberListStatus)
|
||||||
|
E(OP_DzSetLeaderName)
|
||||||
E(OP_Emote)
|
E(OP_Emote)
|
||||||
E(OP_ExpansionInfo)
|
E(OP_ExpansionInfo)
|
||||||
E(OP_FormattedMessage)
|
E(OP_FormattedMessage)
|
||||||
@ -120,6 +123,12 @@ D(OP_ConsiderCorpse)
|
|||||||
D(OP_Consume)
|
D(OP_Consume)
|
||||||
D(OP_Damage)
|
D(OP_Damage)
|
||||||
D(OP_DeleteItem)
|
D(OP_DeleteItem)
|
||||||
|
D(OP_DzAddPlayer)
|
||||||
|
D(OP_DzChooseZoneReply)
|
||||||
|
D(OP_DzExpeditionInviteResponse)
|
||||||
|
D(OP_DzMakeLeader)
|
||||||
|
D(OP_DzRemovePlayer)
|
||||||
|
D(OP_DzSwapPlayer)
|
||||||
D(OP_Emote)
|
D(OP_Emote)
|
||||||
D(OP_EnvDamage)
|
D(OP_EnvDamage)
|
||||||
D(OP_FaceChange)
|
D(OP_FaceChange)
|
||||||
|
|||||||
@ -444,7 +444,11 @@ struct NewZone_Struct {
|
|||||||
/*0848*/ int32 unknown848;
|
/*0848*/ int32 unknown848;
|
||||||
/*0852*/ uint16 zone_id;
|
/*0852*/ uint16 zone_id;
|
||||||
/*0854*/ uint16 zone_instance;
|
/*0854*/ uint16 zone_instance;
|
||||||
/*0856*/ char unknown856[20];
|
/*0856*/ uint32 scriptNPCReceivedanItem;
|
||||||
|
/*0860*/ uint32 bCheck; // padded bool
|
||||||
|
/*0864*/ uint32 scriptIDSomething;
|
||||||
|
/*0868*/ uint32 underworld_teleport_index; // > 0 teleports w/ zone point index, invalid succors, -1 affects some collisions
|
||||||
|
/*0872*/ uint32 scriptIDSomething3;
|
||||||
/*0876*/ uint32 SuspendBuffs;
|
/*0876*/ uint32 SuspendBuffs;
|
||||||
/*0880*/ uint32 unknown880; //seen 50
|
/*0880*/ uint32 unknown880; //seen 50
|
||||||
/*0884*/ uint32 unknown884; //seen 10
|
/*0884*/ uint32 unknown884; //seen 10
|
||||||
@ -4246,52 +4250,160 @@ struct VeteranReward
|
|||||||
/*012*/ VeteranRewardItem items[8];
|
/*012*/ VeteranRewardItem items[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionEntryHeader_Struct
|
|
||||||
|
struct ExpeditionInvite_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id; // unique character id
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char inviter_name[64];
|
||||||
|
/*072*/ char expedition_name[128];
|
||||||
|
/*200*/ uint8 swapping; // 0: adding 1: swapping
|
||||||
|
/*201*/ char swap_name[64]; // if swapping, swap name being removed
|
||||||
|
/*265*/ uint8 padding[3];
|
||||||
|
/*268*/ uint16 dz_zone_id; // dz_id zone/instance pair, sent back in reply
|
||||||
|
/*270*/ uint16 dz_instance_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionInviteResponse_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 unknown000;
|
/*000*/ uint32 unknown000;
|
||||||
/*000*/ uint32 number_of_entries;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ExpeditionJoinPrompt_Struct
|
|
||||||
{
|
|
||||||
/*000*/ uint32 clientid;
|
|
||||||
/*004*/ uint32 unknown004;
|
/*004*/ uint32 unknown004;
|
||||||
/*008*/ char player_name[64];
|
/*008*/ uint16 dz_zone_id; // dz_id pair sent in invite
|
||||||
/*072*/ char expedition_name[64];
|
/*010*/ uint16 dz_instance_id;
|
||||||
};
|
/*012*/ uint8 accepted; // 0: declined 1: accepted
|
||||||
|
/*013*/ uint8 swapping; // 0: adding 1: swapping (sent in invite)
|
||||||
struct ExpeditionExpireWarning
|
/*014*/ char swap_name[64]; // swap name sent in invite
|
||||||
{
|
/*078*/ uint8 unknown078; // padding garbage?
|
||||||
/*000*/ uint32 clientid;
|
/*079*/ uint8 unknown079; // padding garbage?
|
||||||
/*004*/ uint32 unknown004;
|
|
||||||
/*008*/ uint32 minutes_remaining;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionInfo_Struct
|
struct ExpeditionInfo_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint32 client_id;
|
||||||
/*004*/ uint32 unknown004;
|
/*004*/ uint32 unknown004;
|
||||||
/*008*/ uint32 unknown008;
|
/*008*/ uint32 assigned; // padded bool
|
||||||
/*012*/ uint32 max_players;
|
/*012*/ uint32 max_players;
|
||||||
/*016*/ char expedition_name[128];
|
/*016*/ char expedition_name[128];
|
||||||
/*142*/ char leader_name[64];
|
/*144*/ char leader_name[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompassEntry_Struct
|
struct ExpeditionMemberEntry_Struct
|
||||||
{
|
{
|
||||||
/*000*/ float unknown000; //seen *((uint32*)) = 1584791871
|
/*000*/ char name[1]; // variable length, null terminated, max 0x40 (64)
|
||||||
/*004*/ uint32 enabled; //guess
|
/*000*/ uint8 expedition_status; // 0: unknown 1: Online, 2: Offline, 3: In Dynamic Zone, 4: Link Dead
|
||||||
/*008*/ uint32 unknown008; //seen 1019
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberList_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 member_count; // number of players in window
|
||||||
|
/*008*/ ExpeditionMemberEntry_Struct members[0]; // variable length
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMemberListName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ uint32 add_name; // padded bool, 0: remove name, 1: add name with unknown status
|
||||||
|
/*012*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimerEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ char expedition_name[1]; // variable length, null terminated, max 0x80 (128)
|
||||||
|
/*000*/ uint32 seconds_remaining;
|
||||||
|
/*000*/ int32 event_type; // seen -1 (0xffffffff) for replay timers and 1 for event timers
|
||||||
|
/*000*/ char event_name[1]; // variable length, null terminated, max 0x100 (256)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionLockoutTimers_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ ExpeditionLockoutTimerEntry_Struct timers[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionSetLeaderName_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char leader_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommand_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionCommandSwap_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ char add_player_name[64]; // swap to (player must confirm)
|
||||||
|
/*072*/ char rem_player_name[64]; // swap from
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionExpireWarning
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 unknown004;
|
||||||
|
/*008*/ uint32 minutes_remaining;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneCompassEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint16 dz_zone_id; // target dz id pair
|
||||||
|
/*002*/ uint16 dz_instance_id;
|
||||||
|
/*004*/ uint32 dz_type; // 1: Expedition, 2: Tutorial (purple), 3: Task, 4: Mission, 5: Quest (green)
|
||||||
|
/*008*/ uint32 unknown008;
|
||||||
/*012*/ float y;
|
/*012*/ float y;
|
||||||
/*016*/ float x;
|
/*016*/ float x;
|
||||||
/*020*/ float z;
|
/*020*/ float z;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpeditionCompass_Struct
|
struct DynamicZoneCompass_Struct
|
||||||
{
|
{
|
||||||
/*000*/ uint32 clientid;
|
/*000*/ uint32 client_id;
|
||||||
/*004*/ uint32 count;
|
/*004*/ uint32 count;
|
||||||
/*008*/ ExpeditionCompassEntry_Struct entries[0];
|
/*008*/ DynamicZoneCompassEntry_Struct entries[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZoneEntry_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint16 dz_zone_id; // dz_id pair
|
||||||
|
/*002*/ uint16 dz_instance_id;
|
||||||
|
/*004*/ uint32 unknown_id1; // sent back in reply
|
||||||
|
/*008*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest -- sent back in reply
|
||||||
|
/*012*/ uint32 unknown_id2; // possibly an id based on dz type, for expeditions this was same as dz_id (zone|instance) but task dz was different
|
||||||
|
/*016*/ char description[1]; // variable length, null terminated, max 0x80 (128)
|
||||||
|
/*000*/ char leader_name[1]; // variable length, null terminated, max 0x40 (64)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZone_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 client_id;
|
||||||
|
/*004*/ uint32 count;
|
||||||
|
/*008*/ DynamicZoneChooseZoneEntry_Struct choices[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneChooseZoneReply_Struct
|
||||||
|
{
|
||||||
|
/*000*/ uint32 unknown000; // ff ff ff ff
|
||||||
|
/*004*/ uint32 unknown004; // seen 69 00 00 00
|
||||||
|
/*008*/ uint32 unknown008; // ff ff ff ff
|
||||||
|
/*012*/ uint32 unknown_id1; // from choose zone entry message
|
||||||
|
/*016*/ uint16 dz_zone_id; // dz_id pair
|
||||||
|
/*018*/ uint16 dz_instance_id;
|
||||||
|
/*020*/ uint32 dz_type; // 1: Expedition, 2: Tutorial, 3: Task, 4: Mission, 5: Quest
|
||||||
|
/*024*/ uint32 unknown_id2; // from choose zone entry message
|
||||||
|
/*028*/ uint32 unknown028; // 00 00 00 00
|
||||||
|
/*032*/ uint32 unknown032; // always same as unknown044
|
||||||
|
/*036*/ uint32 unknown036;
|
||||||
|
/*040*/ uint32 unknown040;
|
||||||
|
/*044*/ uint32 unknown044; // always same as unknown032
|
||||||
|
/*048*/ uint32 unknown048; // seen 01 00 00 00 and 02 00 00 00
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AltCurrencySelectItem_Struct {
|
struct AltCurrencySelectItem_Struct {
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
|
|
||||||
RULE_CATEGORY(Character)
|
RULE_CATEGORY(Character)
|
||||||
RULE_INT(Character, MaxLevel, 65, "Sets the highest level attainable by experience for players")
|
RULE_INT(Character, MaxLevel, 65, "Sets the highest level for players that can be reached through experience")
|
||||||
RULE_BOOL(Character, PerCharacterQglobalMaxLevel, false, "Check for qglobal 'CharMaxLevel' character qglobal (Type 5, \"\"), if player tries to level beyond that point, it will not go beyond that level")
|
RULE_BOOL(Character, PerCharacterQglobalMaxLevel, false, "Check for qglobal 'CharMaxLevel' character qglobal (Type 5, \"\"), if player tries to level beyond that point, it will not go beyond that level")
|
||||||
RULE_BOOL(Character, PerCharacterBucketMaxLevel, false, "Check for data bucket 'CharMaxLevel', if player tries to level beyond that point, it will not go beyond that level")
|
RULE_BOOL(Character, PerCharacterBucketMaxLevel, false, "Check for data bucket 'CharMaxLevel', if player tries to level beyond that point, it will not go beyond that level")
|
||||||
RULE_INT(Character, MaxExpLevel, 0, "Defines the maximum level that can be reached through experience")
|
RULE_INT(Character, MaxExpLevel, 0, "Defines the maximum level that can be reached through experience")
|
||||||
@ -57,8 +57,8 @@ RULE_REAL(Character, ExpMultiplier, 0.5, "If greater than 0, the experience gain
|
|||||||
RULE_REAL(Character, AAExpMultiplier, 0.5, "If greater than 0, the AA experience gained is multiplied by this value. ")
|
RULE_REAL(Character, AAExpMultiplier, 0.5, "If greater than 0, the AA experience gained is multiplied by this value. ")
|
||||||
RULE_REAL(Character, GroupExpMultiplier, 0.5, "The experience in a group is multiplied by this value in addition to the group multiplier. The group multiplier is: 2 members=x 1.2, 3=x1.4, 4=x1.6, 5=x1.8, 6=x2.16")
|
RULE_REAL(Character, GroupExpMultiplier, 0.5, "The experience in a group is multiplied by this value in addition to the group multiplier. The group multiplier is: 2 members=x 1.2, 3=x1.4, 4=x1.6, 5=x1.8, 6=x2.16")
|
||||||
RULE_REAL(Character, RaidExpMultiplier, 0.2, "The experience gained in raids is multiplied by (1-RaidExpMultiplier) ")
|
RULE_REAL(Character, RaidExpMultiplier, 0.2, "The experience gained in raids is multiplied by (1-RaidExpMultiplier) ")
|
||||||
RULE_BOOL(Character, UseXPConScaling, true, "When activated, the experience is modified depending on the difference between player level and NPC level. The settings Green/LightBlue/Blue//White/Yellow and RedModifier are used")
|
RULE_BOOL(Character, UseXPConScaling, true, "When activated, the experience is modified depending on the difference between player level and NPC level. The values from the rules GreenModifier to RedModifier are used")
|
||||||
RULE_INT(Character, ShowExpValues, 0, "Show expirience values. 0=normal, 1=show raw experience values, 2=show raw experience values and percent")
|
RULE_INT(Character, ShowExpValues, 0, "Show experience values. 0=normal, 1=show raw experience values, 2=show raw experience values and percent")
|
||||||
RULE_INT(Character, GreenModifier, 20, "The experience obtained for green con mobs is multiplied by value/100")
|
RULE_INT(Character, GreenModifier, 20, "The experience obtained for green con mobs is multiplied by value/100")
|
||||||
RULE_INT(Character, LightBlueModifier, 40, "The experience obtained for light-blue con mobs is multiplied by value/100")
|
RULE_INT(Character, LightBlueModifier, 40, "The experience obtained for light-blue con mobs is multiplied by value/100")
|
||||||
RULE_INT(Character, BlueModifier, 90, "The experience obtained for blue con mobs is multiplied by value/100")
|
RULE_INT(Character, BlueModifier, 90, "The experience obtained for blue con mobs is multiplied by value/100")
|
||||||
@ -80,7 +80,7 @@ RULE_INT(Character, ItemAccuracyCap, 150, "Limit on accuracy granted by items")
|
|||||||
RULE_INT(Character, ItemAvoidanceCap, 100, "Limit on avoidance granted by items")
|
RULE_INT(Character, ItemAvoidanceCap, 100, "Limit on avoidance granted by items")
|
||||||
RULE_INT(Character, ItemCombatEffectsCap, 100, "Limit on combat effects granted by items")
|
RULE_INT(Character, ItemCombatEffectsCap, 100, "Limit on combat effects granted by items")
|
||||||
RULE_INT(Character, ItemShieldingCap, 35, "Limit on shielding granted by items")
|
RULE_INT(Character, ItemShieldingCap, 35, "Limit on shielding granted by items")
|
||||||
RULE_INT(Character, ItemSpellShieldingCap, 35, "Limit on spell shieldung granted by items")
|
RULE_INT(Character, ItemSpellShieldingCap, 35, "Limit on spell shielding granted by items")
|
||||||
RULE_INT(Character, ItemDoTShieldingCap, 35, "Limit on DoT shielding granted by items")
|
RULE_INT(Character, ItemDoTShieldingCap, 35, "Limit on DoT shielding granted by items")
|
||||||
RULE_INT(Character, ItemStunResistCap, 35, "Limit on resistance granted by items")
|
RULE_INT(Character, ItemStunResistCap, 35, "Limit on resistance granted by items")
|
||||||
RULE_INT(Character, ItemStrikethroughCap, 35, "Limit on strikethrough granted by items")
|
RULE_INT(Character, ItemStrikethroughCap, 35, "Limit on strikethrough granted by items")
|
||||||
@ -119,7 +119,7 @@ RULE_BOOL(Character, MaintainIntoxicationAcrossZones, true, "If true, alcohol ef
|
|||||||
RULE_BOOL(Character, EnableDiscoveredItems, true, "If enabled, it enables EVENT_DISCOVER_ITEM and also saves character names and timestamps for the first time an item is discovered")
|
RULE_BOOL(Character, EnableDiscoveredItems, true, "If enabled, it enables EVENT_DISCOVER_ITEM and also saves character names and timestamps for the first time an item is discovered")
|
||||||
RULE_BOOL(Character, EnableXTargetting, true, "Enable Extended Targeting Window, for users with UF and later clients")
|
RULE_BOOL(Character, EnableXTargetting, true, "Enable Extended Targeting Window, for users with UF and later clients")
|
||||||
RULE_BOOL(Character, EnableAggroMeter, true, "Enable Aggro Meter, for users with RoF and later clients")
|
RULE_BOOL(Character, EnableAggroMeter, true, "Enable Aggro Meter, for users with RoF and later clients")
|
||||||
RULE_BOOL(Character, KeepLevelOverMax, false, "Don't delevel a character that has somehow gone over the level cap")
|
RULE_BOOL(Character, KeepLevelOverMax, false, "Don't de-level a character that has somehow gone over the level cap")
|
||||||
RULE_INT(Character, FoodLossPerUpdate, 32, "How much food/water you lose per stamina update")
|
RULE_INT(Character, FoodLossPerUpdate, 32, "How much food/water you lose per stamina update")
|
||||||
RULE_BOOL(Character, EnableHungerPenalties, false, "Being hungry/thirsty has negative effects -- it does appear normal live servers do not have penalties")
|
RULE_BOOL(Character, EnableHungerPenalties, false, "Being hungry/thirsty has negative effects -- it does appear normal live servers do not have penalties")
|
||||||
RULE_BOOL(Character, EnableFoodRequirement, true, "If disabled, food is no longer required")
|
RULE_BOOL(Character, EnableFoodRequirement, true, "If disabled, food is no longer required")
|
||||||
@ -129,16 +129,16 @@ RULE_INT(Character, BaseRunSpeedCap, 158, "Base Run Speed Cap, on live it's 158%
|
|||||||
RULE_INT(Character, OrnamentationAugmentType, 20, "Ornamentation Augment Type")
|
RULE_INT(Character, OrnamentationAugmentType, 20, "Ornamentation Augment Type")
|
||||||
RULE_REAL(Character, EnvironmentDamageMulipliter, 1, "Multiplier for environmental damage like fall damage.")
|
RULE_REAL(Character, EnvironmentDamageMulipliter, 1, "Multiplier for environmental damage like fall damage.")
|
||||||
RULE_BOOL(Character, UnmemSpellsOnDeath, true, "Setting whether at death all memorized Spells are forgotten")
|
RULE_BOOL(Character, UnmemSpellsOnDeath, true, "Setting whether at death all memorized Spells are forgotten")
|
||||||
RULE_INT(Character, TradeskillUpAlchemy, 2, "Alchemy skillup rate adjust. Lower is faster")
|
RULE_INT(Character, TradeskillUpAlchemy, 2, "Alchemy skillup rate adjustment. Lower is faster")
|
||||||
RULE_INT(Character, TradeskillUpBaking, 2, "Baking skillup rate adjust. Lower is faster")
|
RULE_INT(Character, TradeskillUpBaking, 2, "Baking skillup rate adjustment. Lower is faster")
|
||||||
RULE_INT(Character, TradeskillUpBlacksmithing, 2, "Blacksmithing skillup rate adjust. Lower is faster")
|
RULE_INT(Character, TradeskillUpBlacksmithing, 2, "Blacksmithing skillup rate adjustment. Lower is faster")
|
||||||
RULE_INT(Character, TradeskillUpBrewing, 3, "Brewing skillup rate adjust. Lower is faster")
|
RULE_INT(Character, TradeskillUpBrewing, 3, "Brewing skillup rate adjustment. Lower is faster")
|
||||||
RULE_INT(Character, TradeskillUpFletching, 2, "Fletching skillup rate adjust. Lower is faster")
|
RULE_INT(Character, TradeskillUpFletching, 2, "Fletching skillup rate adjustment. Lower is faster")
|
||||||
RULE_INT(Character, TradeskillUpJewelcrafting, 2, "Jewelcrafting skillup rate adjust. Lower is faster")
|
RULE_INT(Character, TradeskillUpJewelcrafting, 2, "Jewelcrafting skillup rate adjustment. Lower is faster")
|
||||||
RULE_INT(Character, TradeskillUpMakePoison, 2, "Make Poison skillup rate adjust. Lower is faster")
|
RULE_INT(Character, TradeskillUpMakePoison, 2, "Make Poison skillup rate adjustment. Lower is faster")
|
||||||
RULE_INT(Character, TradeskillUpPottery, 4, "Pottery skillup rate adjust. Lower is faster")
|
RULE_INT(Character, TradeskillUpPottery, 4, "Pottery skillup rate adjustment. Lower is faster")
|
||||||
RULE_INT(Character, TradeskillUpResearch, 1, "Research skillup rate adjust. Lower is faster")
|
RULE_INT(Character, TradeskillUpResearch, 1, "Research skillup rate adjustment. Lower is faster")
|
||||||
RULE_INT(Character, TradeskillUpTinkering, 2, "Tinkering skillup rate adjust. Lower is faster")
|
RULE_INT(Character, TradeskillUpTinkering, 2, "Tinkering skillup rate adjustment. Lower is faster")
|
||||||
RULE_BOOL(Character, MarqueeHPUpdates, false, "Will show health percentage in center of screen if health lesser than 100%")
|
RULE_BOOL(Character, MarqueeHPUpdates, false, "Will show health percentage in center of screen if health lesser than 100%")
|
||||||
RULE_INT(Character, IksarCommonTongue, 95, "Starting value for Common Tongue for Iksars")
|
RULE_INT(Character, IksarCommonTongue, 95, "Starting value for Common Tongue for Iksars")
|
||||||
RULE_INT(Character, OgreCommonTongue, 95, "Starting value for Common Tongue for Ogres")
|
RULE_INT(Character, OgreCommonTongue, 95, "Starting value for Common Tongue for Ogres")
|
||||||
@ -147,7 +147,7 @@ RULE_BOOL(Character, ActiveInvSnapshots, false, "Takes a periodic snapshot of in
|
|||||||
RULE_INT(Character, InvSnapshotMinIntervalM, 180, "Minimum time between inventory snapshots (minutes)")
|
RULE_INT(Character, InvSnapshotMinIntervalM, 180, "Minimum time between inventory snapshots (minutes)")
|
||||||
RULE_INT(Character, InvSnapshotMinRetryM, 30, "Time to re-attempt an inventory snapshot after a failure (minutes)")
|
RULE_INT(Character, InvSnapshotMinRetryM, 30, "Time to re-attempt an inventory snapshot after a failure (minutes)")
|
||||||
RULE_INT(Character, InvSnapshotHistoryD, 30, "Time to keep snapshot entries (days)")
|
RULE_INT(Character, InvSnapshotHistoryD, 30, "Time to keep snapshot entries (days)")
|
||||||
RULE_BOOL(Character, RestrictSpellScribing, false, "Setting whether to testricts spell scribing to allowable races/classes of spell scroll")
|
RULE_BOOL(Character, RestrictSpellScribing, false, "Setting whether to restrict spell scribing to allowable races/classes of spell scroll")
|
||||||
RULE_BOOL(Character, UseStackablePickPocketing, true, "Allows stackable pickpocketed items to stack instead of only being allowed in empty inventory slots")
|
RULE_BOOL(Character, UseStackablePickPocketing, true, "Allows stackable pickpocketed items to stack instead of only being allowed in empty inventory slots")
|
||||||
RULE_BOOL(Character, EnableAvoidanceCap, false, "Setting whether the avoidance cap should be activated")
|
RULE_BOOL(Character, EnableAvoidanceCap, false, "Setting whether the avoidance cap should be activated")
|
||||||
RULE_INT(Character, AvoidanceCap, 750, "750 Is a pretty good value, seen people dodge all attacks beyond 1,000 Avoidance")
|
RULE_INT(Character, AvoidanceCap, 750, "750 Is a pretty good value, seen people dodge all attacks beyond 1,000 Avoidance")
|
||||||
@ -197,7 +197,7 @@ RULE_INT(Skills, MaxTrainSpecializations, 50, "Maximum level a GM trainer will t
|
|||||||
RULE_INT(Skills, SwimmingStartValue, 100, "Start value of swimming skill")
|
RULE_INT(Skills, SwimmingStartValue, 100, "Start value of swimming skill")
|
||||||
RULE_BOOL(Skills, TrainSenseHeading, false, "Switch whether SenseHeading is trained by use")
|
RULE_BOOL(Skills, TrainSenseHeading, false, "Switch whether SenseHeading is trained by use")
|
||||||
RULE_INT(Skills, SenseHeadingStartValue, 200, "Start value of sense heading skill")
|
RULE_INT(Skills, SenseHeadingStartValue, 200, "Start value of sense heading skill")
|
||||||
RULE_BOOL(Skills, SelfLanguageLearning, true, "Enabling self learning of languages")
|
RULE_BOOL(Skills, SelfLanguageLearning, true, "Enabling self-learning of languages")
|
||||||
RULE_BOOL(Skills, RequireTomeHandin, false, "Disable click-to-learn and force hand in to Guild Master")
|
RULE_BOOL(Skills, RequireTomeHandin, false, "Disable click-to-learn and force hand in to Guild Master")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
@ -246,6 +246,7 @@ RULE_BOOL(World, MaxClientsSimplifiedLogic, false, "New logic that only uses Exe
|
|||||||
RULE_INT (World, TellQueueSize, 20, "Maximum tell queue size")
|
RULE_INT (World, TellQueueSize, 20, "Maximum tell queue size")
|
||||||
RULE_BOOL(World, StartZoneSameAsBindOnCreation, true, "Should the start zone always be the same location as your bind?")
|
RULE_BOOL(World, StartZoneSameAsBindOnCreation, true, "Should the start zone always be the same location as your bind?")
|
||||||
RULE_BOOL(World, EnforceCharacterLimitAtLogin, false, "Enforce the limit for characters that are online at login")
|
RULE_BOOL(World, EnforceCharacterLimitAtLogin, false, "Enforce the limit for characters that are online at login")
|
||||||
|
RULE_BOOL(World, EnableDevTools, true, "Enable or Disable the Developer Tools globally (Most of the time you want this enabled)")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Zone)
|
RULE_CATEGORY(Zone)
|
||||||
@ -397,7 +398,7 @@ RULE_INT(Combat, PetBaseCritChance, 0, "Pet base crit chance")
|
|||||||
RULE_INT(Combat, NPCBashKickLevel, 6, "The level that NPCcan KICK/BASH")
|
RULE_INT(Combat, NPCBashKickLevel, 6, "The level that NPCcan KICK/BASH")
|
||||||
RULE_INT(Combat, NPCBashKickStunChance, 15, "Percent chance that a bash/kick will stun")
|
RULE_INT(Combat, NPCBashKickStunChance, 15, "Percent chance that a bash/kick will stun")
|
||||||
RULE_INT(Combat, MeleeCritDifficulty, 8900, "Value against which is rolled to check if a melee crit is triggered. Lower is easier")
|
RULE_INT(Combat, MeleeCritDifficulty, 8900, "Value against which is rolled to check if a melee crit is triggered. Lower is easier")
|
||||||
RULE_INT(Combat, ArcheryCritDifficulty, 3400, "Value against which is rolled to check if a archery crit is triggered. Lower is easier")
|
RULE_INT(Combat, ArcheryCritDifficulty, 3400, "Value against which is rolled to check if an archery crit is triggered. Lower is easier")
|
||||||
RULE_INT(Combat, ThrowingCritDifficulty, 1100, "Value against which is rolled to check if a throwing crit is triggered. Lower is easier")
|
RULE_INT(Combat, ThrowingCritDifficulty, 1100, "Value against which is rolled to check if a throwing crit is triggered. Lower is easier")
|
||||||
RULE_BOOL(Combat, NPCCanCrit, false, "Setting whether an NPC can land critical hits")
|
RULE_BOOL(Combat, NPCCanCrit, false, "Setting whether an NPC can land critical hits")
|
||||||
RULE_BOOL(Combat, UseIntervalAC, true, "Switch whether bonuses, armour class, multipliers, classes and caps should be considered in the calculation of damage values")
|
RULE_BOOL(Combat, UseIntervalAC, true, "Switch whether bonuses, armour class, multipliers, classes and caps should be considered in the calculation of damage values")
|
||||||
@ -416,7 +417,7 @@ RULE_REAL(Combat, BaseProcChance, 0.035, "Base chance for procs")
|
|||||||
RULE_REAL(Combat, ProcDexDivideBy, 11000, "Divisor for the probability of a proc increased by dexterity")
|
RULE_REAL(Combat, ProcDexDivideBy, 11000, "Divisor for the probability of a proc increased by dexterity")
|
||||||
RULE_BOOL(Combat, AdjustSpecialProcPerMinute, true, "Set PPM for special abilities like HeadShot (Live does this as of 4-14)")
|
RULE_BOOL(Combat, AdjustSpecialProcPerMinute, true, "Set PPM for special abilities like HeadShot (Live does this as of 4-14)")
|
||||||
RULE_REAL(Combat, AvgSpecialProcsPerMinute, 2.0, "Unclear what best value is atm")
|
RULE_REAL(Combat, AvgSpecialProcsPerMinute, 2.0, "Unclear what best value is atm")
|
||||||
RULE_REAL(Combat, BaseHitChance, 69.0, "Base chance to hiz")
|
RULE_REAL(Combat, BaseHitChance, 69.0, "Base chance to hit")
|
||||||
RULE_REAL(Combat, NPCBonusHitChance, 26.0, "Bonus chance to hit for NPC")
|
RULE_REAL(Combat, NPCBonusHitChance, 26.0, "Bonus chance to hit for NPC")
|
||||||
RULE_REAL(Combat, HitFalloffMinor, 5.0, "Hit will fall off up to value over the initial level range (percent)")
|
RULE_REAL(Combat, HitFalloffMinor, 5.0, "Hit will fall off up to value over the initial level range (percent)")
|
||||||
RULE_REAL(Combat, HitFalloffModerate, 7.0, "Hit will fall off up to value over the three levels after the initial level range (percent)")
|
RULE_REAL(Combat, HitFalloffModerate, 7.0, "Hit will fall off up to value over the three levels after the initial level range (percent)")
|
||||||
@ -493,11 +494,11 @@ RULE_BOOL(Combat, UseLiveCombatRounds, true, "Turn this false if you don't want
|
|||||||
RULE_INT(Combat, NPCAssistCap, 5, "Maxiumium number of NPC that will assist another NPC at once")
|
RULE_INT(Combat, NPCAssistCap, 5, "Maxiumium number of NPC that will assist another NPC at once")
|
||||||
RULE_INT(Combat, NPCAssistCapTimer, 6000, "Time a NPC will take to clear assist aggro cap space (milliseconds)")
|
RULE_INT(Combat, NPCAssistCapTimer, 6000, "Time a NPC will take to clear assist aggro cap space (milliseconds)")
|
||||||
RULE_BOOL(Combat, UseRevampHandToHand, false, "Use h2h revamped dmg/delays I believe this was implemented during SoF")
|
RULE_BOOL(Combat, UseRevampHandToHand, false, "Use h2h revamped dmg/delays I believe this was implemented during SoF")
|
||||||
RULE_BOOL(Combat, ClassicMasterWu, false, "Classic master wu uses a random special, modern doesn't")
|
RULE_BOOL(Combat, ClassicMasterWu, false, "Classic Master Wu uses a random special, modern doesn't")
|
||||||
RULE_REAL(Combat, HitBoxMod, 1.00, "Added to test hit boxes.")
|
RULE_REAL(Combat, HitBoxMod, 1.00, "Added to test hit boxes.")
|
||||||
RULE_INT(Combat, LevelToStopDamageCaps, 0, "Level to stop damage caps. 1 will effectively disable them, 20 should give basically same results as old incorrect system")
|
RULE_INT(Combat, LevelToStopDamageCaps, 0, "Level to stop damage caps. 1 will effectively disable them, 20 should give basically same results as old incorrect system")
|
||||||
RULE_INT(Combat, LevelToStopACTwinkControl, 50, "Level to stop armorclass twink control. 1 will effectively disable it, 50 should give basically same results as current system")
|
RULE_INT(Combat, LevelToStopACTwinkControl, 50, "Level to stop armorclass twink control. 1 will effectively disable it, 50 should give basically same results as current system")
|
||||||
RULE_BOOL(Combat, ClassicNPCBackstab, false, "True disables npc facestab - NPCget normal attack if not behind")
|
RULE_BOOL(Combat, ClassicNPCBackstab, false, "True disables NPC facestab - NPC get normal attack if not behind")
|
||||||
RULE_BOOL(Combat, UseNPCDamageClassLevelMods, true, "Uses GetClassLevelDamageMod calc in npc_scale_manager")
|
RULE_BOOL(Combat, UseNPCDamageClassLevelMods, true, "Uses GetClassLevelDamageMod calc in npc_scale_manager")
|
||||||
RULE_BOOL(Combat, UseExtendedPoisonProcs, false, "Allow old school poisons to last until characrer zones, at a lower proc rate")
|
RULE_BOOL(Combat, UseExtendedPoisonProcs, false, "Allow old school poisons to last until characrer zones, at a lower proc rate")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
@ -508,7 +509,7 @@ RULE_INT(NPC, MajorNPCCorpseDecayTimeMS, 1500000, "NPC corpse decay time, if NPC
|
|||||||
RULE_INT(NPC, CorpseUnlockTimer, 150000, "Time after which corpses are unlocked for everyone to loot (milliseconds)")
|
RULE_INT(NPC, CorpseUnlockTimer, 150000, "Time after which corpses are unlocked for everyone to loot (milliseconds)")
|
||||||
RULE_INT(NPC, EmptyNPCCorpseDecayTimeMS, 0, "NPC corpse decay time, if no items are left on the corpse (milliseconds)")
|
RULE_INT(NPC, EmptyNPCCorpseDecayTimeMS, 0, "NPC corpse decay time, if no items are left on the corpse (milliseconds)")
|
||||||
RULE_BOOL(NPC, UseItemBonusesForNonPets, true, "Switch whether item bonuses should be used for NPCs who are not pets")
|
RULE_BOOL(NPC, UseItemBonusesForNonPets, true, "Switch whether item bonuses should be used for NPCs who are not pets")
|
||||||
RULE_BOOL(NPC, UseBaneDamage, false, "If NPCs can't inheriently hit the target we don't add bane/magic dmg which isn't exactly the same as PCs")
|
RULE_BOOL(NPC, UseBaneDamage, false, "If NPCs can't inherently hit the target we don't add bane/magic dmg which isn't exactly the same as PCs")
|
||||||
RULE_INT(NPC, SayPauseTimeInSec, 5, "Time span in which an NPC pauses his movement after a Say event without aggro (seconds)")
|
RULE_INT(NPC, SayPauseTimeInSec, 5, "Time span in which an NPC pauses his movement after a Say event without aggro (seconds)")
|
||||||
RULE_INT(NPC, OOCRegen, 0, "Enable out-of-combat regeneration for NPC")
|
RULE_INT(NPC, OOCRegen, 0, "Enable out-of-combat regeneration for NPC")
|
||||||
RULE_BOOL(NPC, BuffFriends, false, "Setting whether NPC should buff other NPC")
|
RULE_BOOL(NPC, BuffFriends, false, "Setting whether NPC should buff other NPC")
|
||||||
@ -529,7 +530,7 @@ RULE_BOOL(NPC, NPCGateNearBind, false, "Will NPC attempt to gate when near bind
|
|||||||
RULE_INT(NPC, NPCGateDistanceBind, 75, "Distance from bind before NPC will attempt to gate")
|
RULE_INT(NPC, NPCGateDistanceBind, 75, "Distance from bind before NPC will attempt to gate")
|
||||||
RULE_BOOL(NPC, NPCHealOnGate, true, "Will the NPC Heal on Gate")
|
RULE_BOOL(NPC, NPCHealOnGate, true, "Will the NPC Heal on Gate")
|
||||||
RULE_BOOL(NPC, UseMeditateBasedManaRegen, false, "Based NPC ooc regen on Meditate skill")
|
RULE_BOOL(NPC, UseMeditateBasedManaRegen, false, "Based NPC ooc regen on Meditate skill")
|
||||||
RULE_REAL(NPC, NPCHealOnGateAmount, 25, "How much the npc will heal on gate if enabled")
|
RULE_REAL(NPC, NPCHealOnGateAmount, 25, "How much the NPC will heal on gate if enabled")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Aggro)
|
RULE_CATEGORY(Aggro)
|
||||||
@ -547,7 +548,8 @@ RULE_INT(Aggro, IntAggroThreshold, 75, "Int lesser or equal the value will aggro
|
|||||||
RULE_BOOL(Aggro, AllowTickPulling, false, "tick pulling is an exploit in an NPC's call for help fixed sometime in 2006 on live")
|
RULE_BOOL(Aggro, AllowTickPulling, false, "tick pulling is an exploit in an NPC's call for help fixed sometime in 2006 on live")
|
||||||
RULE_INT(Aggro, MinAggroLevel, 18, "Minimum level for use with UseLevelAggro")
|
RULE_INT(Aggro, MinAggroLevel, 18, "Minimum level for use with UseLevelAggro")
|
||||||
RULE_BOOL(Aggro, UseLevelAggro, true, "MinAggroLevel rule value+ and Undead will aggro regardless of level difference. This will disabled Rule:IntAggroThreshold if set to true")
|
RULE_BOOL(Aggro, UseLevelAggro, true, "MinAggroLevel rule value+ and Undead will aggro regardless of level difference. This will disabled Rule:IntAggroThreshold if set to true")
|
||||||
RULE_INT(Aggro, ClientAggroCheckInterval, 6, "Interval in which clients actually check for aggro - in seconds")
|
RULE_INT(Aggro, ClientAggroCheckMovingInterval, 1000, "Interval in which clients actually check for aggro while moving - in milliseconds - this should be lower than ClientAggroCheckIdleInterval")
|
||||||
|
RULE_INT(Aggro, ClientAggroCheckIdleInterval, 6000, "Interval in which clients actually check for aggro while idle - in milliseconds - this should be higher than ClientAggroCheckMovingInterval")
|
||||||
RULE_REAL(Aggro, PetAttackRange, 40000.0, "Maximum squared range /pet attack works at default is 200")
|
RULE_REAL(Aggro, PetAttackRange, 40000.0, "Maximum squared range /pet attack works at default is 200")
|
||||||
RULE_BOOL(Aggro, NPCAggroMaxDistanceEnabled, true, "If enabled, NPC's will drop aggro beyond 600 units or what is defined at the zone level")
|
RULE_BOOL(Aggro, NPCAggroMaxDistanceEnabled, true, "If enabled, NPC's will drop aggro beyond 600 units or what is defined at the zone level")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
@ -619,7 +621,7 @@ RULE_BOOL(Chat, EnableVoiceMacros, true, "Enable voice macros")
|
|||||||
RULE_BOOL(Chat, EnableMailKeyIPVerification, true, "Setting whether the authenticity of the client should be verified via its IP address when accessing the InGame mailbox")
|
RULE_BOOL(Chat, EnableMailKeyIPVerification, true, "Setting whether the authenticity of the client should be verified via its IP address when accessing the InGame mailbox")
|
||||||
RULE_BOOL(Chat, EnableAntiSpam, true, "Enable anti-spam system for chat")
|
RULE_BOOL(Chat, EnableAntiSpam, true, "Enable anti-spam system for chat")
|
||||||
RULE_BOOL(Chat, SuppressCommandErrors, false, "Do not suppress command errors by default")
|
RULE_BOOL(Chat, SuppressCommandErrors, false, "Do not suppress command errors by default")
|
||||||
RULE_INT(Chat, MinStatusToBypassAntiSpam, 100, "Minimum status to bypass the anti spam system")
|
RULE_INT(Chat, MinStatusToBypassAntiSpam, 100, "Minimum status to bypass the anti-spam system")
|
||||||
RULE_INT(Chat, MinimumMessagesPerInterval, 4, "Minimum number of chat messages allowed per interval. The karma value is added to this value")
|
RULE_INT(Chat, MinimumMessagesPerInterval, 4, "Minimum number of chat messages allowed per interval. The karma value is added to this value")
|
||||||
RULE_INT(Chat, MaximumMessagesPerInterval, 12, "Maximum value of chat messages allowed per interval")
|
RULE_INT(Chat, MaximumMessagesPerInterval, 12, "Maximum value of chat messages allowed per interval")
|
||||||
RULE_INT(Chat, MaxMessagesBeforeKick, 20, "If an attempt is made to send more than the maximum allowed number of chat messages per interval, the client will be disconnected after this absolute number of messages")
|
RULE_INT(Chat, MaxMessagesBeforeKick, 20, "If an attempt is made to send more than the maximum allowed number of chat messages per interval, the client will be disconnected after this absolute number of messages")
|
||||||
@ -783,6 +785,20 @@ RULE_BOOL(Instances, RecycleInstanceIds, true, "Setting whether free instance ID
|
|||||||
RULE_INT(Instances, GuildHallExpirationDays, 90, "Amount of days before a Guild Hall instance expires")
|
RULE_INT(Instances, GuildHallExpirationDays, 90, "Amount of days before a Guild Hall instance expires")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
|
RULE_CATEGORY(Expedition)
|
||||||
|
RULE_INT(Expedition, MinStatusToBypassPlayerCountRequirements, 80, "Minimum GM status to bypass minimum player requirements for Expedition creation")
|
||||||
|
RULE_BOOL(Expedition, EmptyDzShutdownEnabled, true, "Enable early instance shutdown after last member of expedition removed")
|
||||||
|
RULE_INT(Expedition, EmptyDzShutdownDelaySeconds, 1500, "Seconds to set dynamic zone instance expiration if early shutdown enabled")
|
||||||
|
RULE_INT(Expedition, WorldExpeditionProcessRateMS, 6000, "Timer interval (ms) that world checks expedition states")
|
||||||
|
RULE_BOOL(Expedition, AlwaysNotifyNewLeaderOnChange, false, "Always notify clients when made expedition leader. If false (live-like) new leaders are only notified when made leader via /dzmakeleader")
|
||||||
|
RULE_REAL(Expedition, LockoutDurationMultiplier, 1.0, "Multiplies lockout duration by this value when new lockouts are added")
|
||||||
|
RULE_BOOL(Expedition, EnableInDynamicZoneStatus, false, "Enables the 'In Dynamic Zone' member status in expedition window. If false (live-like) players inside the dz will show as 'Online'")
|
||||||
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
|
RULE_CATEGORY(DynamicZone)
|
||||||
|
RULE_INT(DynamicZone, ClientRemovalDelayMS, 60000, "Delay (ms) until a client is teleported out of dynamic zone after being removed as member")
|
||||||
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
#undef RULE_CATEGORY
|
#undef RULE_CATEGORY
|
||||||
#undef RULE_INT
|
#undef RULE_INT
|
||||||
#undef RULE_REAL
|
#undef RULE_REAL
|
||||||
|
|||||||
@ -101,7 +101,7 @@ const std::string &EQ::SayLinkEngine::GenerateLink()
|
|||||||
m_Error = true;
|
m_Error = true;
|
||||||
m_Link = "<LINKER ERROR>";
|
m_Link = "<LINKER ERROR>";
|
||||||
LogError("SayLinkEngine::GenerateLink() failed to generate a useable say link");
|
LogError("SayLinkEngine::GenerateLink() failed to generate a useable say link");
|
||||||
LogError(">> LinkType: {}, Lengths: {link: {}({}), body: {}({}), text: {}({})}",
|
LogError(">> LinkType: {}, Lengths: [link: {}({}), body: {}({}), text: {}({})]",
|
||||||
m_LinkType,
|
m_LinkType,
|
||||||
m_Link.length(),
|
m_Link.length(),
|
||||||
EQ::constants::SAY_LINK_MAXIMUM_SIZE,
|
EQ::constants::SAY_LINK_MAXIMUM_SIZE,
|
||||||
|
|||||||
@ -80,6 +80,7 @@
|
|||||||
#define ServerOP_UpdateSpawn 0x003f
|
#define ServerOP_UpdateSpawn 0x003f
|
||||||
#define ServerOP_SpawnStatusChange 0x0040
|
#define ServerOP_SpawnStatusChange 0x0040
|
||||||
#define ServerOP_DropClient 0x0041 // DropClient
|
#define ServerOP_DropClient 0x0041 // DropClient
|
||||||
|
#define ServerOP_ChangeGroupLeader 0x0042
|
||||||
#define ServerOP_ReloadTasks 0x0060
|
#define ServerOP_ReloadTasks 0x0060
|
||||||
#define ServerOP_DepopAllPlayersCorpses 0x0061
|
#define ServerOP_DepopAllPlayersCorpses 0x0061
|
||||||
#define ServerOP_ReloadTitles 0x0062
|
#define ServerOP_ReloadTitles 0x0062
|
||||||
@ -140,6 +141,35 @@
|
|||||||
#define ServerOP_LFPUpdate 0x0213
|
#define ServerOP_LFPUpdate 0x0213
|
||||||
#define ServerOP_LFPMatches 0x0214
|
#define ServerOP_LFPMatches 0x0214
|
||||||
#define ServerOP_ClientVersionSummary 0x0215
|
#define ServerOP_ClientVersionSummary 0x0215
|
||||||
|
|
||||||
|
#define ServerOP_ExpeditionCreate 0x0400
|
||||||
|
#define ServerOP_ExpeditionDeleted 0x0401
|
||||||
|
#define ServerOP_ExpeditionLeaderChanged 0x0402
|
||||||
|
#define ServerOP_ExpeditionLockout 0x0403
|
||||||
|
#define ServerOP_ExpeditionMemberChange 0x0404
|
||||||
|
#define ServerOP_ExpeditionMemberSwap 0x0405
|
||||||
|
#define ServerOP_ExpeditionMemberStatus 0x0406
|
||||||
|
#define ServerOP_ExpeditionGetOnlineMembers 0x0407
|
||||||
|
#define ServerOP_ExpeditionDzAddPlayer 0x0408
|
||||||
|
#define ServerOP_ExpeditionDzMakeLeader 0x0409
|
||||||
|
#define ServerOP_ExpeditionDzCompass 0x040a
|
||||||
|
#define ServerOP_ExpeditionDzSafeReturn 0x040b
|
||||||
|
#define ServerOP_ExpeditionDzZoneIn 0x040c
|
||||||
|
#define ServerOP_ExpeditionCharacterLockout 0x040d
|
||||||
|
#define ServerOP_ExpeditionSaveInvite 0x040e
|
||||||
|
#define ServerOP_ExpeditionRequestInvite 0x040f
|
||||||
|
#define ServerOP_ExpeditionReplayOnJoin 0x0410
|
||||||
|
#define ServerOP_ExpeditionLockState 0x0411
|
||||||
|
#define ServerOP_ExpeditionMembersRemoved 0x0412
|
||||||
|
#define ServerOP_ExpeditionDzDuration 0x0413
|
||||||
|
#define ServerOP_ExpeditionLockoutDuration 0x0414
|
||||||
|
#define ServerOP_ExpeditionSecondsRemaining 0x0415
|
||||||
|
#define ServerOP_ExpeditionExpireWarning 0x0416
|
||||||
|
#define ServerOP_ExpeditionChooseNewLeader 0x0417
|
||||||
|
|
||||||
|
#define ServerOP_DzCharacterChange 0x0450
|
||||||
|
#define ServerOP_DzRemoveAllCharacters 0x0451
|
||||||
|
|
||||||
#define ServerOP_LSInfo 0x1000
|
#define ServerOP_LSInfo 0x1000
|
||||||
#define ServerOP_LSStatus 0x1001
|
#define ServerOP_LSStatus 0x1001
|
||||||
#define ServerOP_LSClientAuthLeg 0x1002
|
#define ServerOP_LSClientAuthLeg 0x1002
|
||||||
@ -257,6 +287,7 @@
|
|||||||
#define ServerOP_CZTaskRemoveGroup 0x4560
|
#define ServerOP_CZTaskRemoveGroup 0x4560
|
||||||
#define ServerOP_CZTaskRemoveRaid 0x4561
|
#define ServerOP_CZTaskRemoveRaid 0x4561
|
||||||
#define ServerOP_CZTaskRemoveGuild 0x4562
|
#define ServerOP_CZTaskRemoveGuild 0x4562
|
||||||
|
#define ServerOP_CZClientMessageString 0x4563
|
||||||
|
|
||||||
#define ServerOP_WWAssignTask 0x4750
|
#define ServerOP_WWAssignTask 0x4750
|
||||||
#define ServerOP_WWCastSpell 0x4751
|
#define ServerOP_WWCastSpell 0x4751
|
||||||
@ -831,6 +862,7 @@ struct ServerGroupLeave_Struct {
|
|||||||
uint16 instance_id;
|
uint16 instance_id;
|
||||||
uint32 gid;
|
uint32 gid;
|
||||||
char member_name[64]; //kick this member from the group
|
char member_name[64]; //kick this member from the group
|
||||||
|
bool checkleader;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerGroupJoin_Struct {
|
struct ServerGroupJoin_Struct {
|
||||||
@ -840,10 +872,20 @@ struct ServerGroupJoin_Struct {
|
|||||||
char member_name[64]; //this person is joining the group
|
char member_name[64]; //this person is joining the group
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ServerGroupLeader_Struct {
|
||||||
|
uint32 zoneid;
|
||||||
|
uint16 instance_id;
|
||||||
|
uint32 gid;
|
||||||
|
char leader_name[64];
|
||||||
|
char oldleader_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
struct ServerForceGroupUpdate_Struct {
|
struct ServerForceGroupUpdate_Struct {
|
||||||
uint32 origZoneID;
|
uint32 origZoneID;
|
||||||
uint16 instance_id;
|
uint16 instance_id;
|
||||||
uint32 gid;
|
uint32 gid;
|
||||||
|
char leader_name[64];
|
||||||
|
char oldleader_name[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerGroupChannelMessage_Struct {
|
struct ServerGroupChannelMessage_Struct {
|
||||||
@ -1433,6 +1475,14 @@ struct CZNPCSignal_Struct {
|
|||||||
uint32 signal;
|
uint32 signal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CZClientMessageString_Struct {
|
||||||
|
uint32 string_id;
|
||||||
|
uint16 chat_type;
|
||||||
|
char character_name[64];
|
||||||
|
uint32 args_size;
|
||||||
|
char args[1]; // null delimited
|
||||||
|
};
|
||||||
|
|
||||||
struct CZClientSignalByName_Struct {
|
struct CZClientSignalByName_Struct {
|
||||||
char character_name[64];
|
char character_name[64];
|
||||||
uint32 signal;
|
uint32 signal;
|
||||||
@ -1958,6 +2008,146 @@ struct UCSServerStatus_Struct {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionID_Struct {
|
||||||
|
uint32 expedition_id;
|
||||||
|
uint32 sender_zone_id;
|
||||||
|
uint32 sender_instance_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionLeaderID_Struct {
|
||||||
|
uint32 expedition_id;
|
||||||
|
uint32 leader_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionMemberChange_Struct {
|
||||||
|
uint32 expedition_id;
|
||||||
|
uint32 sender_zone_id;
|
||||||
|
uint16 sender_instance_id;
|
||||||
|
uint8 removed; // 0: added, 1: removed
|
||||||
|
uint32 char_id;
|
||||||
|
char char_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionMemberSwap_Struct {
|
||||||
|
uint32 expedition_id;
|
||||||
|
uint32 sender_zone_id;
|
||||||
|
uint16 sender_instance_id;
|
||||||
|
uint32 add_char_id;
|
||||||
|
uint32 remove_char_id;
|
||||||
|
char add_char_name[64];
|
||||||
|
char remove_char_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionMemberStatus_Struct {
|
||||||
|
uint32 expedition_id;
|
||||||
|
uint32 sender_zone_id;
|
||||||
|
uint16 sender_instance_id;
|
||||||
|
uint8 status; // 0: unknown 1: Online 2: Offline 3: In Dynamic Zone 4: Link Dead
|
||||||
|
uint32 character_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionCharacterEntry_Struct {
|
||||||
|
uint32 expedition_id;
|
||||||
|
uint32 character_id;
|
||||||
|
uint32 character_zone_id;
|
||||||
|
uint16 character_instance_id;
|
||||||
|
uint8 character_online; // 0: offline 1: online
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionCharacters_Struct {
|
||||||
|
uint32 sender_zone_id;
|
||||||
|
uint16 sender_instance_id;
|
||||||
|
uint32 count;
|
||||||
|
ServerExpeditionCharacterEntry_Struct entries[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionLockout_Struct {
|
||||||
|
uint32 expedition_id;
|
||||||
|
uint64 expire_time;
|
||||||
|
uint32 duration;
|
||||||
|
uint32 sender_zone_id;
|
||||||
|
uint16 sender_instance_id;
|
||||||
|
uint8 remove;
|
||||||
|
uint8 members_only;
|
||||||
|
int seconds_adjust;
|
||||||
|
char event_name[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionLockState_Struct {
|
||||||
|
uint32 expedition_id;
|
||||||
|
uint32 sender_zone_id;
|
||||||
|
uint16 sender_instance_id;
|
||||||
|
uint8 enabled;
|
||||||
|
uint8 lock_msg; // 0: none, 1: closing 2: trial begin
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionSetting_Struct {
|
||||||
|
uint32 expedition_id;
|
||||||
|
uint32 sender_zone_id;
|
||||||
|
uint16 sender_instance_id;
|
||||||
|
uint8 enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionCharacterLockout_Struct {
|
||||||
|
uint8 remove;
|
||||||
|
uint32 character_id;
|
||||||
|
uint64 expire_time;
|
||||||
|
uint32 duration;
|
||||||
|
char uuid[37];
|
||||||
|
char expedition_name[128];
|
||||||
|
char event_name[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionCharacterID_Struct {
|
||||||
|
uint32_t character_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionUpdateDuration_Struct {
|
||||||
|
uint32_t expedition_id;
|
||||||
|
uint32_t new_duration_seconds;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerExpeditionExpireWarning_Struct {
|
||||||
|
uint32_t expedition_id;
|
||||||
|
uint32_t minutes_remaining;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerDzCommand_Struct {
|
||||||
|
uint32 expedition_id;
|
||||||
|
uint8 is_char_online; // 0: target name is offline, 1: online
|
||||||
|
char requester_name[64];
|
||||||
|
char target_name[64];
|
||||||
|
char remove_name[64]; // used for swap command
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerDzCommandMakeLeader_Struct {
|
||||||
|
uint32 expedition_id;
|
||||||
|
uint32 requester_id;
|
||||||
|
uint8 is_online; // set by world, 0: new leader name offline, 1: online
|
||||||
|
uint8 is_success; // set by world, 0: makeleader failed, 1: success (is online member)
|
||||||
|
char new_leader_name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerDzLocation_Struct {
|
||||||
|
uint32 owner_id; // system associated with the dz (expedition, shared task, etc)
|
||||||
|
uint16 dz_zone_id;
|
||||||
|
uint16 dz_instance_id;
|
||||||
|
uint32 sender_zone_id;
|
||||||
|
uint16 sender_instance_id;
|
||||||
|
uint32 zone_id; // compass or safereturn zone id
|
||||||
|
float y;
|
||||||
|
float x;
|
||||||
|
float z;
|
||||||
|
float heading;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServerDzCharacter_Struct {
|
||||||
|
uint16 zone_id;
|
||||||
|
uint16 instance_id;
|
||||||
|
uint8 remove; // 0: added 1: removed
|
||||||
|
uint32 character_id;
|
||||||
|
};
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1271,7 +1271,7 @@ bool IsSpellUsableThisZoneType(uint16 spell_id, uint8 zone_type)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetSpellName(int16 spell_id)
|
const char* GetSpellName(uint16 spell_id)
|
||||||
{
|
{
|
||||||
return spells[spell_id].name;
|
return spells[spell_id].name;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -981,6 +981,6 @@ uint32 GetNimbusEffect(uint16 spell_id);
|
|||||||
int32 GetFuriousBash(uint16 spell_id);
|
int32 GetFuriousBash(uint16 spell_id);
|
||||||
bool IsShortDurationBuff(uint16 spell_id);
|
bool IsShortDurationBuff(uint16 spell_id);
|
||||||
bool IsSpellUsableThisZoneType(uint16 spell_id, uint8 zone_type);
|
bool IsSpellUsableThisZoneType(uint16 spell_id, uint8 zone_type);
|
||||||
const char *GetSpellName(int16 spell_id);
|
const char *GetSpellName(uint16 spell_id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -592,3 +592,15 @@ std::string numberToWords(unsigned long long int n)
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// first letter capitalized and rest made lower case
|
||||||
|
std::string FormatName(const std::string& char_name)
|
||||||
|
{
|
||||||
|
std::string formatted(char_name);
|
||||||
|
if (!formatted.empty())
|
||||||
|
{
|
||||||
|
std::transform(formatted.begin(), formatted.end(), formatted.begin(), ::tolower);
|
||||||
|
formatted[0] = ::toupper(formatted[0]);
|
||||||
|
}
|
||||||
|
return formatted;
|
||||||
|
}
|
||||||
|
|||||||
@ -206,6 +206,6 @@ void MakeLowerString(const char *source, char *target);
|
|||||||
void RemoveApostrophes(std::string &s);
|
void RemoveApostrophes(std::string &s);
|
||||||
std::string convert2digit(int n, std::string suffix);
|
std::string convert2digit(int n, std::string suffix);
|
||||||
std::string numberToWords(unsigned long long int n);
|
std::string numberToWords(unsigned long long int n);
|
||||||
|
std::string FormatName(const std::string& char_name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -34,7 +34,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 9157
|
#define CURRENT_BINARY_DATABASE_VERSION 9159
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9027
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9027
|
||||||
|
|||||||
@ -366,6 +366,7 @@ OP_CancelSneakHide=0x265f
|
|||||||
OP_AggroMeterLockTarget=0x70b7
|
OP_AggroMeterLockTarget=0x70b7
|
||||||
OP_AggroMeterTargetInfo=0x18fe
|
OP_AggroMeterTargetInfo=0x18fe
|
||||||
OP_AggroMeterUpdate=0x75aa
|
OP_AggroMeterUpdate=0x75aa
|
||||||
|
OP_UnderWorld=0x44f9 # clients sends up when they detect an underworld issue, might be useful for cheat detection
|
||||||
|
|
||||||
OP_DzQuit=0x5fc8
|
OP_DzQuit=0x5fc8
|
||||||
OP_DzListTimers=0x67b9
|
OP_DzListTimers=0x67b9
|
||||||
@ -374,16 +375,18 @@ OP_DzRemovePlayer=0x0dc1
|
|||||||
OP_DzSwapPlayer=0x4995
|
OP_DzSwapPlayer=0x4995
|
||||||
OP_DzMakeLeader=0x17b2
|
OP_DzMakeLeader=0x17b2
|
||||||
OP_DzPlayerList=0x1aff
|
OP_DzPlayerList=0x1aff
|
||||||
OP_DzJoinExpeditionConfirm=0x30df
|
OP_DzExpeditionInvite=0x30df
|
||||||
OP_DzJoinExpeditionReply=0x15d4
|
OP_DzExpeditionInviteResponse=0x15d4
|
||||||
OP_DzExpeditionInfo=0x3861
|
OP_DzExpeditionInfo=0x3861
|
||||||
OP_DzExpeditionList=0x0b3b
|
OP_DzExpeditionLockoutTimers=0x0b3b
|
||||||
OP_DzMemberStatus=0x26c2
|
|
||||||
OP_DzLeaderStatus=0x4021
|
|
||||||
OP_DzExpeditionEndsWarning=0x32eb
|
|
||||||
OP_DzMemberList=0x348f
|
OP_DzMemberList=0x348f
|
||||||
|
OP_DzMemberListName=0x26c2
|
||||||
|
OP_DzMemberListStatus=0x0000
|
||||||
|
OP_DzSetLeaderName=0x4021
|
||||||
|
OP_DzExpeditionEndsWarning=0x32eb
|
||||||
OP_DzCompass=0x0e01 # Was 0x4f09
|
OP_DzCompass=0x0e01 # Was 0x4f09
|
||||||
OP_DzChooseZone=0x6e5e # Maybe 0x29d6
|
OP_DzChooseZone=0x6e5e # Maybe 0x29d6
|
||||||
|
OP_DzChooseZoneReply=0x0000
|
||||||
|
|
||||||
# New Opcodes
|
# New Opcodes
|
||||||
OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ?
|
OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ?
|
||||||
|
|||||||
@ -367,25 +367,29 @@ OP_CancelSneakHide=0x0927
|
|||||||
OP_AggroMeterLockTarget=0x1643
|
OP_AggroMeterLockTarget=0x1643
|
||||||
OP_AggroMeterTargetInfo=0x16bc
|
OP_AggroMeterTargetInfo=0x16bc
|
||||||
OP_AggroMeterUpdate=0x1781
|
OP_AggroMeterUpdate=0x1781
|
||||||
|
OP_UnderWorld=0x2eb3 # clients sends up when they detect an underworld issue, might be useful for cheat detection
|
||||||
|
OP_KickPlayers=0x6770
|
||||||
|
|
||||||
# Expeditions
|
# Expeditions
|
||||||
|
OP_DzQuit=0xb2e3
|
||||||
|
OP_DzListTimers=0x7b68
|
||||||
OP_DzAddPlayer=0x4701
|
OP_DzAddPlayer=0x4701
|
||||||
OP_DzRemovePlayer=0x1abc
|
OP_DzRemovePlayer=0x1abc
|
||||||
OP_DzSwapPlayer=0x405b
|
OP_DzSwapPlayer=0x405b
|
||||||
OP_DzMakeLeader=0x543d
|
OP_DzMakeLeader=0x543d
|
||||||
OP_DzPlayerList=0x14c6
|
OP_DzPlayerList=0x14c6
|
||||||
OP_DzJoinExpeditionConfirm=0x7f4b
|
OP_DzExpeditionInvite=0x7f4b
|
||||||
OP_DzJoinExpeditionReply=0x1950
|
OP_DzExpeditionInviteResponse=0x1950
|
||||||
OP_DzListTimers=0x7b68
|
|
||||||
OP_DzExpeditionInfo=0x9119
|
OP_DzExpeditionInfo=0x9119
|
||||||
OP_DzExpeditionList=0x205f
|
OP_DzExpeditionLockoutTimers=0x205f
|
||||||
OP_DzQuit=0xb2e3
|
|
||||||
OP_DzMemberStatus=0x32f0
|
|
||||||
OP_DzLeaderStatus=0x3de9
|
|
||||||
OP_DzMemberList=0x5ae4
|
OP_DzMemberList=0x5ae4
|
||||||
OP_DzExpeditionEndsWarning=0x383c
|
OP_DzMemberListName=0x32f0
|
||||||
|
OP_DzMemberListStatus=0x12F5
|
||||||
|
OP_DzSetLeaderName=0x3de9
|
||||||
|
OP_DzExpeditionEndsWarning=0x5189
|
||||||
OP_DzCompass=0x3e0e
|
OP_DzCompass=0x3e0e
|
||||||
OP_DzChooseZone=0x0b7d
|
OP_DzChooseZone=0x0b7d
|
||||||
|
OP_DzChooseZoneReply=0x4de1
|
||||||
|
|
||||||
# New Opcodes
|
# New Opcodes
|
||||||
OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ?
|
OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ?
|
||||||
|
|||||||
@ -357,6 +357,7 @@ OP_OpenContainer=0x3278
|
|||||||
OP_Marquee=0x7dc9
|
OP_Marquee=0x7dc9
|
||||||
OP_Fling=0x2b88
|
OP_Fling=0x2b88
|
||||||
OP_CancelSneakHide=0x7705
|
OP_CancelSneakHide=0x7705
|
||||||
|
OP_UnderWorld=0x51ae # clients sends up when they detect an underworld issue, might be useful for cheat detection
|
||||||
|
|
||||||
# Expedition
|
# Expedition
|
||||||
OP_DzQuit=0x054e
|
OP_DzQuit=0x054e
|
||||||
@ -366,17 +367,18 @@ OP_DzRemovePlayer=0xa682
|
|||||||
OP_DzSwapPlayer=0x0d8d
|
OP_DzSwapPlayer=0x0d8d
|
||||||
OP_DzMakeLeader=0x1caa
|
OP_DzMakeLeader=0x1caa
|
||||||
OP_DzPlayerList=0x74ca
|
OP_DzPlayerList=0x74ca
|
||||||
OP_DzJoinExpeditionConfirm=0x1772
|
OP_DzExpeditionInvite=0x1772
|
||||||
OP_DzJoinExpeditionReply=0x3c13
|
OP_DzExpeditionInviteResponse=0x3c13
|
||||||
OP_DzExpeditionInfo=0x128e
|
OP_DzExpeditionInfo=0x128e
|
||||||
OP_DzMemberStatus=0x4661
|
OP_DzExpeditionLockoutTimers=0x3657
|
||||||
OP_DzLeaderStatus=0x226f
|
|
||||||
OP_DzExpeditionEndsWarning=0x1879
|
|
||||||
OP_DzExpeditionList=0x3657
|
|
||||||
OP_DzMemberList=0x74e4
|
OP_DzMemberList=0x74e4
|
||||||
|
OP_DzMemberListName=0x4661
|
||||||
|
OP_DzMemberListStatus=0x1d99
|
||||||
|
OP_DzSetLeaderName=0x226f
|
||||||
|
OP_DzExpeditionEndsWarning=0x1879
|
||||||
OP_DzCompass=0x35d3
|
OP_DzCompass=0x35d3
|
||||||
OP_DzChooseZone=0x0d8a
|
OP_DzChooseZone=0x0d8a
|
||||||
#0x1d99 was grouped with these too but I don't really know it's purpose.
|
OP_DzChooseZoneReply=0x5a67
|
||||||
|
|
||||||
# New Opcodes
|
# New Opcodes
|
||||||
OP_SpawnPositionUpdate=0x4656 #
|
OP_SpawnPositionUpdate=0x4656 #
|
||||||
|
|||||||
@ -338,6 +338,7 @@ OP_OpenContainer=0x10e3
|
|||||||
OP_Marquee=0x2f75
|
OP_Marquee=0x2f75
|
||||||
OP_Untargetable=0x3e36
|
OP_Untargetable=0x3e36
|
||||||
OP_CancelSneakHide=0x5335
|
OP_CancelSneakHide=0x5335
|
||||||
|
OP_UnderWorld=0x7580 # clients sends up when they detect an underworld issue, might be useful for cheat detection
|
||||||
|
|
||||||
#expedition
|
#expedition
|
||||||
OP_DzQuit=0x20d6
|
OP_DzQuit=0x20d6
|
||||||
@ -347,16 +348,18 @@ OP_DzRemovePlayer=0x2ce8
|
|||||||
OP_DzSwapPlayer=0x2c3e
|
OP_DzSwapPlayer=0x2c3e
|
||||||
OP_DzMakeLeader=0x1a75
|
OP_DzMakeLeader=0x1a75
|
||||||
OP_DzPlayerList=0x5116
|
OP_DzPlayerList=0x5116
|
||||||
OP_DzJoinExpeditionConfirm=0x1793
|
OP_DzExpeditionInvite=0x1793
|
||||||
OP_DzJoinExpeditionReply=0x7a6f
|
OP_DzExpeditionInviteResponse=0x7a6f
|
||||||
OP_DzExpeditionInfo=0x60a6
|
OP_DzExpeditionInfo=0x60a6
|
||||||
OP_DzMemberStatus=0x0516
|
OP_DzExpeditionLockoutTimers=0x02ac
|
||||||
OP_DzLeaderStatus=0x79d3
|
|
||||||
OP_DzExpeditionEndsWarning=0x5153
|
|
||||||
OP_DzExpeditionList=0x02ac
|
|
||||||
OP_DzMemberList=0x5e14
|
OP_DzMemberList=0x5e14
|
||||||
|
OP_DzMemberListName=0x0516
|
||||||
|
OP_DzMemberListStatus=0x0000
|
||||||
|
OP_DzSetLeaderName=0x79d3
|
||||||
|
OP_DzExpeditionEndsWarning=0x5153
|
||||||
OP_DzCompass=0x531d
|
OP_DzCompass=0x531d
|
||||||
OP_DzChooseZone=0x3c5b
|
OP_DzChooseZone=0x3c5b
|
||||||
|
OP_DzChooseZoneReply=0x0000
|
||||||
|
|
||||||
#Looting
|
#Looting
|
||||||
OP_LootRequest=0x36E3 #Trevius 02/16/09
|
OP_LootRequest=0x36E3 #Trevius 02/16/09
|
||||||
|
|||||||
@ -297,17 +297,18 @@ OP_DzRemovePlayer=0x540b
|
|||||||
OP_DzSwapPlayer=0x794a
|
OP_DzSwapPlayer=0x794a
|
||||||
OP_DzMakeLeader=0x0ce9
|
OP_DzMakeLeader=0x0ce9
|
||||||
OP_DzPlayerList=0xada0
|
OP_DzPlayerList=0xada0
|
||||||
OP_DzJoinExpeditionConfirm=0x3817
|
OP_DzExpeditionInvite=0x3817
|
||||||
OP_DzJoinExpeditionReply=0x5da9
|
OP_DzExpeditionInviteResponse=0x5da9
|
||||||
OP_DzExpeditionInfo=0x98e
|
OP_DzExpeditionInfo=0x98e
|
||||||
OP_DzMemberStatus=0x1826
|
OP_DzExpeditionLockoutTimers=0x7c12
|
||||||
OP_DzLeaderStatus=0x7abc
|
|
||||||
OP_DzExpeditionEndsWarning=0x1c3f
|
|
||||||
OP_DzExpeditionList=0x7c12
|
|
||||||
OP_DzMemberList=0x9b6
|
OP_DzMemberList=0x9b6
|
||||||
|
OP_DzMemberListName=0x1826
|
||||||
|
OP_DzMemberListStatus=0x330d
|
||||||
|
OP_DzSetLeaderName=0x7abc
|
||||||
|
OP_DzExpeditionEndsWarning=0x1c3f
|
||||||
OP_DzCompass=0x28aa
|
OP_DzCompass=0x28aa
|
||||||
OP_DzChooseZone=0x1022
|
OP_DzChooseZone=0x1022
|
||||||
#0x330d is something but I'm not sure what yet.
|
OP_DzChooseZoneReply=0x20e7
|
||||||
|
|
||||||
#bazaar trader stuff stuff:
|
#bazaar trader stuff stuff:
|
||||||
#become and buy from
|
#become and buy from
|
||||||
@ -543,6 +544,7 @@ OP_PlayerStateRemove=0x381d
|
|||||||
OP_VoiceMacroIn=0x2866 # Client to Server
|
OP_VoiceMacroIn=0x2866 # Client to Server
|
||||||
OP_VoiceMacroOut=0x2ec6 # Server to Client
|
OP_VoiceMacroOut=0x2ec6 # Server to Client
|
||||||
OP_CameraEffect=0x0937 # Correct
|
OP_CameraEffect=0x0937 # Correct
|
||||||
|
OP_UnderWorld=0x7186 # clients sends up when they detect an underworld issue, might be useful for cheat detection
|
||||||
|
|
||||||
#named unknowns, to make looking for real unknown easier
|
#named unknowns, to make looking for real unknown easier
|
||||||
OP_AnnoyingZoneUnknown=0x729c
|
OP_AnnoyingZoneUnknown=0x729c
|
||||||
|
|||||||
@ -368,6 +368,7 @@ OP_OpenContainer=0x041a
|
|||||||
OP_Marquee=0x3675
|
OP_Marquee=0x3675
|
||||||
OP_Fling=0x51b1
|
OP_Fling=0x51b1
|
||||||
OP_CancelSneakHide=0x7686
|
OP_CancelSneakHide=0x7686
|
||||||
|
OP_UnderWorld=0x2d9d # clients sends up when they detect an underworld issue, might be useful for cheat detection
|
||||||
|
|
||||||
OP_DzQuit=0x1539
|
OP_DzQuit=0x1539
|
||||||
OP_DzListTimers=0x21e9
|
OP_DzListTimers=0x21e9
|
||||||
@ -376,16 +377,18 @@ OP_DzRemovePlayer=0x054e
|
|||||||
OP_DzSwapPlayer=0x4661
|
OP_DzSwapPlayer=0x4661
|
||||||
OP_DzMakeLeader=0x226f
|
OP_DzMakeLeader=0x226f
|
||||||
OP_DzPlayerList=0x74e4
|
OP_DzPlayerList=0x74e4
|
||||||
OP_DzJoinExpeditionConfirm=0x3c5e
|
OP_DzExpeditionInvite=0x3c5e
|
||||||
OP_DzJoinExpeditionReply=0x1154
|
OP_DzExpeditionInviteResponse=0x1154
|
||||||
OP_DzExpeditionInfo=0x1150
|
OP_DzExpeditionInfo=0x1150
|
||||||
OP_DzMemberStatus=0x2d17
|
OP_DzExpeditionLockoutTimers=0x70d8
|
||||||
OP_DzLeaderStatus=0x2caf
|
|
||||||
OP_DzExpeditionEndsWarning=0x6ac2
|
|
||||||
OP_DzExpeditionList=0x70d8
|
|
||||||
OP_DzMemberList=0x15c4
|
OP_DzMemberList=0x15c4
|
||||||
|
OP_DzMemberListName=0x2d17
|
||||||
|
OP_DzMemberListStatus=0x0d98
|
||||||
|
OP_DzSetLeaderName=0x2caf
|
||||||
|
OP_DzExpeditionEndsWarning=0x6ac2
|
||||||
OP_DzCompass=0x01cb
|
OP_DzCompass=0x01cb
|
||||||
OP_DzChooseZone=0x65e1
|
OP_DzChooseZone=0x65e1
|
||||||
|
OP_DzChooseZoneReply=0xa682
|
||||||
|
|
||||||
#shroud
|
#shroud
|
||||||
OP_ShroudSelectionWindow=0x72ad
|
OP_ShroudSelectionWindow=0x72ad
|
||||||
|
|||||||
@ -411,6 +411,8 @@
|
|||||||
9155|2020_08_15_lootdrop_level_filtering.sql|SHOW COLUMNS from `lootdrop_entries` LIKE 'trivial_min_level'|empty|
|
9155|2020_08_15_lootdrop_level_filtering.sql|SHOW COLUMNS from `lootdrop_entries` LIKE 'trivial_min_level'|empty|
|
||||||
9156|2020_08_16_virtual_zonepoints.sql|SHOW COLUMNS from `zone_points` LIKE 'is_virtual'|empty|
|
9156|2020_08_16_virtual_zonepoints.sql|SHOW COLUMNS from `zone_points` LIKE 'is_virtual'|empty|
|
||||||
9157|2020_09_02_pet_taunting.sql|SHOW COLUMNS from `character_pet_info` LIKE 'taunting'|empty|
|
9157|2020_09_02_pet_taunting.sql|SHOW COLUMNS from `character_pet_info` LIKE 'taunting'|empty|
|
||||||
|
9158|2020_12_09_underworld.sql|SHOW COLUMNS from `zone` LIKE 'underworld_teleport_index'|empty|
|
||||||
|
9159|2020_12_22_expedition_system.sql|SELECT * FROM db_version WHERE version >= 9159|empty|
|
||||||
|
|
||||||
# Upgrade conditions:
|
# Upgrade conditions:
|
||||||
# This won't be needed after this system is implemented, but it is used database that are not
|
# This won't be needed after this system is implemented, but it is used database that are not
|
||||||
|
|||||||
6
utils/sql/git/required/2020_12_09_underworld.sql
Normal file
6
utils/sql/git/required/2020_12_09_underworld.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
ALTER TABLE `zone` ADD COLUMN `underworld_teleport_index` INT(4) NOT NULL DEFAULT '0';
|
||||||
|
UPDATE `zone` SET `underworld` = '-2030' WHERE `zoneidnumber` = '71';
|
||||||
|
UPDATE `zone` SET `underworld_teleport_index` = '11' WHERE `zoneidnumber` = '71';
|
||||||
|
UPDATE `zone` SET `underworld_teleport_index` = '-1' WHERE `zoneidnumber` = '75';
|
||||||
|
UPDATE `zone` SET `underworld_teleport_index` = '-1' WHERE `zoneidnumber` = '150';
|
||||||
|
|
||||||
82
utils/sql/git/required/2020_12_22_expedition_system.sql
Normal file
82
utils/sql/git/required/2020_12_22_expedition_system.sql
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
CREATE TABLE `expeditions` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`uuid` VARCHAR(36) NOT NULL,
|
||||||
|
`dynamic_zone_id` INT(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
`expedition_name` VARCHAR(128) NOT NULL,
|
||||||
|
`leader_id` INT(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
`min_players` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
`max_players` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
`add_replay_on_join` TINYINT(3) UNSIGNED NOT NULL DEFAULT 1,
|
||||||
|
`is_locked` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE INDEX `dynamic_zone_id` (`dynamic_zone_id`)
|
||||||
|
)
|
||||||
|
COLLATE='latin1_swedish_ci'
|
||||||
|
ENGINE=InnoDB
|
||||||
|
;
|
||||||
|
|
||||||
|
CREATE TABLE `expedition_lockouts` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`expedition_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`event_name` VARCHAR(256) NOT NULL,
|
||||||
|
`expire_time` DATETIME NOT NULL DEFAULT current_timestamp(),
|
||||||
|
`duration` INT(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
`from_expedition_uuid` VARCHAR(36) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE INDEX `expedition_id_event_name` (`expedition_id`, `event_name`)
|
||||||
|
)
|
||||||
|
COLLATE='latin1_swedish_ci'
|
||||||
|
ENGINE=InnoDB
|
||||||
|
;
|
||||||
|
|
||||||
|
CREATE TABLE `expedition_members` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`expedition_id` INT(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
`character_id` INT(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
`is_current_member` TINYINT(3) UNSIGNED NOT NULL DEFAULT 1,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE INDEX `expedition_id_character_id` (`expedition_id`, `character_id`)
|
||||||
|
)
|
||||||
|
COLLATE='latin1_swedish_ci'
|
||||||
|
ENGINE=InnoDB
|
||||||
|
;
|
||||||
|
|
||||||
|
CREATE TABLE `character_expedition_lockouts` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`character_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`expedition_name` VARCHAR(128) NOT NULL,
|
||||||
|
`event_name` VARCHAR(256) NOT NULL,
|
||||||
|
`expire_time` DATETIME NOT NULL DEFAULT current_timestamp(),
|
||||||
|
`duration` INT(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
`from_expedition_uuid` VARCHAR(36) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE INDEX `character_id_expedition_name_event_name` (`character_id`, `expedition_name`, `event_name`)
|
||||||
|
)
|
||||||
|
COLLATE='latin1_swedish_ci'
|
||||||
|
ENGINE=InnoDB
|
||||||
|
;
|
||||||
|
|
||||||
|
CREATE TABLE `dynamic_zones` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`instance_id` INT(10) NOT NULL DEFAULT 0,
|
||||||
|
`type` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
`compass_zone_id` INT(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
`compass_x` FLOAT NOT NULL DEFAULT 0,
|
||||||
|
`compass_y` FLOAT NOT NULL DEFAULT 0,
|
||||||
|
`compass_z` FLOAT NOT NULL DEFAULT 0,
|
||||||
|
`safe_return_zone_id` INT(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
`safe_return_x` FLOAT NOT NULL DEFAULT 0,
|
||||||
|
`safe_return_y` FLOAT NOT NULL DEFAULT 0,
|
||||||
|
`safe_return_z` FLOAT NOT NULL DEFAULT 0,
|
||||||
|
`safe_return_heading` FLOAT NOT NULL DEFAULT 0,
|
||||||
|
`zone_in_x` FLOAT NOT NULL DEFAULT 0,
|
||||||
|
`zone_in_y` FLOAT NOT NULL DEFAULT 0,
|
||||||
|
`zone_in_z` FLOAT NOT NULL DEFAULT 0,
|
||||||
|
`zone_in_heading` FLOAT NOT NULL DEFAULT 0,
|
||||||
|
`has_zone_in` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE INDEX `instance_id` (`instance_id`)
|
||||||
|
)
|
||||||
|
COLLATE='utf8mb4_general_ci'
|
||||||
|
ENGINE=InnoDB
|
||||||
|
;
|
||||||
@ -9,6 +9,10 @@ SET(world_sources
|
|||||||
console.cpp
|
console.cpp
|
||||||
eql_config.cpp
|
eql_config.cpp
|
||||||
eqemu_api_world_data_service.cpp
|
eqemu_api_world_data_service.cpp
|
||||||
|
expedition.cpp
|
||||||
|
expedition_database.cpp
|
||||||
|
expedition_message.cpp
|
||||||
|
expedition_state.cpp
|
||||||
launcher_link.cpp
|
launcher_link.cpp
|
||||||
launcher_list.cpp
|
launcher_list.cpp
|
||||||
lfplist.cpp
|
lfplist.cpp
|
||||||
@ -39,6 +43,10 @@ SET(world_headers
|
|||||||
console.h
|
console.h
|
||||||
eql_config.h
|
eql_config.h
|
||||||
eqemu_api_world_data_service.h
|
eqemu_api_world_data_service.h
|
||||||
|
expedition.h
|
||||||
|
expedition_database.h
|
||||||
|
expedition_message.h
|
||||||
|
expedition_state.h
|
||||||
launcher_link.h
|
launcher_link.h
|
||||||
launcher_list.h
|
launcher_list.h
|
||||||
lfplist.h
|
lfplist.h
|
||||||
|
|||||||
@ -127,6 +127,9 @@ public:
|
|||||||
inline void PushToTellQueue(ServerChannelMessage_Struct *scm) { tell_queue.push_back(scm); }
|
inline void PushToTellQueue(ServerChannelMessage_Struct *scm) { tell_queue.push_back(scm); }
|
||||||
void ProcessTellQueue();
|
void ProcessTellQueue();
|
||||||
|
|
||||||
|
void SetPendingExpeditionInvite(ServerPacket* pack) { p_pending_expedition_invite.reset(pack->Copy()); };
|
||||||
|
std::unique_ptr<ServerPacket> GetPendingExpeditionInvite() { return std::move(p_pending_expedition_invite); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ClearVars(bool iAll = false);
|
void ClearVars(bool iAll = false);
|
||||||
|
|
||||||
@ -171,6 +174,8 @@ private:
|
|||||||
|
|
||||||
// Tell Queue -- really a vector :D
|
// Tell Queue -- really a vector :D
|
||||||
std::vector<ServerChannelMessage_Struct *> tell_queue;
|
std::vector<ServerChannelMessage_Struct *> tell_queue;
|
||||||
|
|
||||||
|
std::unique_ptr<ServerPacket> p_pending_expedition_invite = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*CLIENTENTRY_H_*/
|
#endif /*CLIENTENTRY_H_*/
|
||||||
|
|||||||
195
world/expedition.cpp
Normal file
195
world/expedition.cpp
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "expedition.h"
|
||||||
|
#include "expedition_database.h"
|
||||||
|
#include "cliententry.h"
|
||||||
|
#include "clientlist.h"
|
||||||
|
#include "zonelist.h"
|
||||||
|
#include "zoneserver.h"
|
||||||
|
#include "../common/eqemu_logsys.h"
|
||||||
|
|
||||||
|
extern ClientList client_list;
|
||||||
|
extern ZSList zoneserver_list;
|
||||||
|
|
||||||
|
Expedition::Expedition(uint32_t expedition_id, uint32_t dz_id, uint32_t dz_instance_id,
|
||||||
|
uint32_t dz_zone_id, uint32_t start_time, uint32_t duration, uint32_t leader_id
|
||||||
|
) :
|
||||||
|
m_expedition_id(expedition_id),
|
||||||
|
m_dz_id(dz_id),
|
||||||
|
m_dz_instance_id(dz_instance_id),
|
||||||
|
m_dz_zone_id(dz_zone_id),
|
||||||
|
m_start_time(std::chrono::system_clock::from_time_t(start_time)),
|
||||||
|
m_duration(duration),
|
||||||
|
m_leader_id(leader_id)
|
||||||
|
{
|
||||||
|
m_expire_time = m_start_time + m_duration;
|
||||||
|
m_warning_cooldown_timer.Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expedition::AddMember(uint32_t character_id)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(m_member_ids.begin(), m_member_ids.end(),
|
||||||
|
[&](uint32_t member_id) { return member_id == character_id; });
|
||||||
|
|
||||||
|
if (it == m_member_ids.end())
|
||||||
|
{
|
||||||
|
m_member_ids.emplace_back(character_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Expedition::HasMember(uint32_t character_id)
|
||||||
|
{
|
||||||
|
return std::any_of(m_member_ids.begin(), m_member_ids.end(),
|
||||||
|
[&](uint32_t member_id) { return member_id == character_id; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expedition::RemoveMember(uint32_t character_id)
|
||||||
|
{
|
||||||
|
m_member_ids.erase(std::remove_if(m_member_ids.begin(), m_member_ids.end(),
|
||||||
|
[&](uint32_t member_id) { return member_id == character_id; }
|
||||||
|
), m_member_ids.end());
|
||||||
|
|
||||||
|
if (!m_member_ids.empty() && character_id == m_leader_id)
|
||||||
|
{
|
||||||
|
ChooseNewLeader();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expedition::ChooseNewLeader()
|
||||||
|
{
|
||||||
|
// we don't track expedition member status in world so may choose a linkdead member
|
||||||
|
// this is fine since it will trigger another change when that member goes offline
|
||||||
|
auto it = std::find_if(m_member_ids.begin(), m_member_ids.end(), [&](uint32_t member_id) {
|
||||||
|
auto member_cle = (member_id != m_leader_id) ? client_list.FindCLEByCharacterID(member_id) : nullptr;
|
||||||
|
return (member_id != m_leader_id && member_cle && member_cle->GetOnline() == CLE_Status::InZone);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it == m_member_ids.end())
|
||||||
|
{
|
||||||
|
// no online members found, fallback to choosing any member
|
||||||
|
it = std::find_if(m_member_ids.begin(), m_member_ids.end(),
|
||||||
|
[&](uint32_t member_id) { return (member_id != m_leader_id); });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it != m_member_ids.end())
|
||||||
|
{
|
||||||
|
SetNewLeader(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Expedition::SetNewLeader(uint32_t character_id)
|
||||||
|
{
|
||||||
|
if (!HasMember(character_id))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogExpeditionsModerate("Replacing [{}] leader [{}] with [{}]", m_expedition_id, m_leader_id, character_id);
|
||||||
|
ExpeditionDatabase::UpdateLeaderID(m_expedition_id, character_id);
|
||||||
|
m_leader_id = character_id;
|
||||||
|
SendZonesLeaderChanged();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expedition::SendZonesExpeditionDeleted()
|
||||||
|
{
|
||||||
|
uint32_t pack_size = sizeof(ServerExpeditionID_Struct);
|
||||||
|
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(ServerOP_ExpeditionDeleted, pack_size));
|
||||||
|
auto buf = reinterpret_cast<ServerExpeditionID_Struct*>(pack->pBuffer);
|
||||||
|
buf->expedition_id = GetID();
|
||||||
|
zoneserver_list.SendPacket(pack.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expedition::SendZonesDurationUpdate()
|
||||||
|
{
|
||||||
|
uint32_t packsize = sizeof(ServerExpeditionUpdateDuration_Struct);
|
||||||
|
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(ServerOP_ExpeditionDzDuration, packsize));
|
||||||
|
auto packbuf = reinterpret_cast<ServerExpeditionUpdateDuration_Struct*>(pack->pBuffer);
|
||||||
|
packbuf->expedition_id = GetID();
|
||||||
|
packbuf->new_duration_seconds = static_cast<uint32_t>(m_duration.count());
|
||||||
|
zoneserver_list.SendPacket(pack.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expedition::SendZonesExpireWarning(uint32_t minutes_remaining)
|
||||||
|
{
|
||||||
|
uint32_t pack_size = sizeof(ServerExpeditionExpireWarning_Struct);
|
||||||
|
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(ServerOP_ExpeditionExpireWarning, pack_size));
|
||||||
|
auto buf = reinterpret_cast<ServerExpeditionExpireWarning_Struct*>(pack->pBuffer);
|
||||||
|
buf->expedition_id = GetID();
|
||||||
|
buf->minutes_remaining = minutes_remaining;
|
||||||
|
zoneserver_list.SendPacket(pack.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expedition::SendZonesLeaderChanged()
|
||||||
|
{
|
||||||
|
uint32_t pack_size = sizeof(ServerExpeditionLeaderID_Struct);
|
||||||
|
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(ServerOP_ExpeditionLeaderChanged, pack_size));
|
||||||
|
auto buf = reinterpret_cast<ServerExpeditionLeaderID_Struct*>(pack->pBuffer);
|
||||||
|
buf->expedition_id = GetID();
|
||||||
|
buf->leader_id = m_leader_id;
|
||||||
|
zoneserver_list.SendPacket(pack.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expedition::UpdateDzSecondsRemaining(uint32_t seconds_remaining)
|
||||||
|
{
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
auto update_time = std::chrono::seconds(seconds_remaining);
|
||||||
|
|
||||||
|
auto current_remaining = m_expire_time - now;
|
||||||
|
if (current_remaining > update_time) // reduce only
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail(
|
||||||
|
"Updating expedition [{}] dz instance [{}] seconds remaining to [{}]s",
|
||||||
|
GetID(), GetInstanceID(), seconds_remaining
|
||||||
|
);
|
||||||
|
|
||||||
|
// preserve original start time and adjust duration instead
|
||||||
|
m_expire_time = now + update_time;
|
||||||
|
m_duration = std::chrono::duration_cast<std::chrono::seconds>(m_expire_time - m_start_time);
|
||||||
|
|
||||||
|
ExpeditionDatabase::UpdateDzDuration(GetInstanceID(), static_cast<uint32_t>(m_duration.count()));
|
||||||
|
|
||||||
|
// update zone level caches and update the actual dz instance's timer
|
||||||
|
SendZonesDurationUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::chrono::system_clock::duration Expedition::GetRemainingDuration() const
|
||||||
|
{
|
||||||
|
return m_expire_time - std::chrono::system_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expedition::CheckExpireWarning()
|
||||||
|
{
|
||||||
|
if (m_warning_cooldown_timer.Check(false))
|
||||||
|
{
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
auto remaining = GetRemainingDuration();
|
||||||
|
if ((remaining > 14min && remaining < 15min) ||
|
||||||
|
(remaining > 4min && remaining < 5min) ||
|
||||||
|
(remaining > 0min && remaining < 1min))
|
||||||
|
{
|
||||||
|
int minutes = std::chrono::duration_cast<std::chrono::minutes>(remaining).count() + 1;
|
||||||
|
SendZonesExpireWarning(minutes);
|
||||||
|
m_warning_cooldown_timer.Start(70000); // 1 minute 10 seconds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
world/expedition.h
Normal file
73
world/expedition.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WORLD_EXPEDITION_H
|
||||||
|
#define WORLD_EXPEDITION_H
|
||||||
|
|
||||||
|
#include "../common/timer.h"
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Expedition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Expedition() = default;
|
||||||
|
Expedition(uint32_t expedition_id, uint32_t dz_id, uint32_t dz_instance_id,
|
||||||
|
uint32_t dz_zone_id, uint32_t expire_time, uint32_t duration, uint32_t leader_id);
|
||||||
|
|
||||||
|
void AddMember(uint32_t character_id);
|
||||||
|
void RemoveMember(uint32_t character_id);
|
||||||
|
void RemoveAllMembers() { m_member_ids.clear(); }
|
||||||
|
void CheckExpireWarning();
|
||||||
|
void ChooseNewLeader();
|
||||||
|
uint32_t GetID() const { return m_expedition_id; }
|
||||||
|
uint16_t GetInstanceID() const { return static_cast<uint16_t>(m_dz_instance_id); }
|
||||||
|
uint16_t GetZoneID() const { return static_cast<uint16_t>(m_dz_zone_id); }
|
||||||
|
bool HasMember(uint32_t character_id);
|
||||||
|
bool IsEmpty() const { return m_member_ids.empty(); }
|
||||||
|
bool IsExpired() const { return m_expire_time < std::chrono::system_clock::now(); }
|
||||||
|
bool IsPendingDelete() const { return m_pending_delete; }
|
||||||
|
bool IsValid() const { return m_expedition_id != 0; }
|
||||||
|
void SendZonesDurationUpdate();
|
||||||
|
void SendZonesExpeditionDeleted();
|
||||||
|
void SendZonesExpireWarning(uint32_t minutes_remaining);
|
||||||
|
bool SetNewLeader(uint32_t new_leader_id);
|
||||||
|
void SetPendingDelete(bool pending) { m_pending_delete = pending; }
|
||||||
|
void UpdateDzSecondsRemaining(uint32_t seconds_remaining);
|
||||||
|
std::chrono::system_clock::duration GetRemainingDuration() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SendZonesLeaderChanged();
|
||||||
|
|
||||||
|
uint32_t m_expedition_id = 0;
|
||||||
|
uint32_t m_dz_id = 0;
|
||||||
|
uint32_t m_dz_instance_id = 0;
|
||||||
|
uint32_t m_dz_zone_id = 0;
|
||||||
|
uint32_t m_leader_id = 0;
|
||||||
|
bool m_pending_delete = false;
|
||||||
|
Timer m_warning_cooldown_timer;
|
||||||
|
std::vector<uint32_t> m_member_ids;
|
||||||
|
std::chrono::seconds m_duration;
|
||||||
|
std::chrono::time_point<std::chrono::system_clock> m_start_time;
|
||||||
|
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
215
world/expedition_database.cpp
Normal file
215
world/expedition_database.cpp
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "expedition_database.h"
|
||||||
|
#include "expedition.h"
|
||||||
|
#include "worlddb.h"
|
||||||
|
|
||||||
|
void ExpeditionDatabase::PurgeExpiredExpeditions()
|
||||||
|
{
|
||||||
|
std::string query = SQL(
|
||||||
|
SELECT
|
||||||
|
expeditions.id
|
||||||
|
FROM expeditions
|
||||||
|
LEFT JOIN dynamic_zones ON expeditions.dynamic_zone_id = dynamic_zones.id
|
||||||
|
LEFT JOIN instance_list ON dynamic_zones.instance_id = instance_list.id
|
||||||
|
LEFT JOIN
|
||||||
|
(
|
||||||
|
SELECT expedition_id, COUNT(IF(is_current_member = TRUE, 1, NULL)) member_count
|
||||||
|
FROM expedition_members
|
||||||
|
GROUP BY expedition_id
|
||||||
|
) expedition_members
|
||||||
|
ON expedition_members.expedition_id = expeditions.id
|
||||||
|
WHERE
|
||||||
|
instance_list.id IS NULL
|
||||||
|
OR expedition_members.member_count IS NULL
|
||||||
|
OR expedition_members.member_count = 0
|
||||||
|
OR (instance_list.start_time + instance_list.duration) <= UNIX_TIMESTAMP();
|
||||||
|
);
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (results.Success())
|
||||||
|
{
|
||||||
|
std::vector<uint32_t> expedition_ids;
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row)
|
||||||
|
{
|
||||||
|
expedition_ids.emplace_back(static_cast<uint32_t>(strtoul(row[0], nullptr, 10)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!expedition_ids.empty())
|
||||||
|
{
|
||||||
|
ExpeditionDatabase::MoveMembersToSafeReturn(expedition_ids);
|
||||||
|
ExpeditionDatabase::DeleteExpeditions(expedition_ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::PurgeExpiredCharacterLockouts()
|
||||||
|
{
|
||||||
|
std::string query = SQL(
|
||||||
|
DELETE FROM character_expedition_lockouts
|
||||||
|
WHERE expire_time <= NOW();
|
||||||
|
);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Expedition> ExpeditionDatabase::LoadExpeditions(uint32_t select_expedition_id)
|
||||||
|
{
|
||||||
|
std::vector<Expedition> expeditions;
|
||||||
|
|
||||||
|
std::string query = SQL(
|
||||||
|
SELECT
|
||||||
|
expeditions.id,
|
||||||
|
expeditions.dynamic_zone_id,
|
||||||
|
instance_list.id,
|
||||||
|
instance_list.zone,
|
||||||
|
instance_list.start_time,
|
||||||
|
instance_list.duration,
|
||||||
|
expeditions.leader_id,
|
||||||
|
expedition_members.character_id
|
||||||
|
FROM expeditions
|
||||||
|
INNER JOIN dynamic_zones ON expeditions.dynamic_zone_id = dynamic_zones.id
|
||||||
|
INNER JOIN instance_list ON dynamic_zones.instance_id = instance_list.id
|
||||||
|
INNER JOIN expedition_members ON expedition_members.expedition_id = expeditions.id
|
||||||
|
AND expedition_members.is_current_member = TRUE
|
||||||
|
);
|
||||||
|
|
||||||
|
if (select_expedition_id != 0)
|
||||||
|
{
|
||||||
|
query.append(fmt::format(" WHERE expeditions.id = {};", select_expedition_id));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
query.append(" ORDER BY expeditions.id;");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (results.Success())
|
||||||
|
{
|
||||||
|
uint32_t last_expedition_id = 0;
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row)
|
||||||
|
{
|
||||||
|
uint32_t expedition_id = strtoul(row[0], nullptr, 10);
|
||||||
|
|
||||||
|
if (last_expedition_id != expedition_id)
|
||||||
|
{
|
||||||
|
expeditions.emplace_back(
|
||||||
|
static_cast<uint32_t>(strtoul(row[0], nullptr, 10)), // expedition_id
|
||||||
|
static_cast<uint32_t>(strtoul(row[1], nullptr, 10)), // dz_id
|
||||||
|
static_cast<uint32_t>(strtoul(row[2], nullptr, 10)), // dz_instance_id
|
||||||
|
static_cast<uint32_t>(strtoul(row[3], nullptr, 10)), // dz_zone_id
|
||||||
|
static_cast<uint32_t>(strtoul(row[4], nullptr, 10)), // start_time
|
||||||
|
static_cast<uint32_t>(strtoul(row[5], nullptr, 10)), // duration
|
||||||
|
static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) // leader_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
last_expedition_id = expedition_id;
|
||||||
|
|
||||||
|
uint32_t member_id = static_cast<uint32_t>(strtoul(row[7], nullptr, 10));
|
||||||
|
expeditions.back().AddMember(member_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return expeditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expedition ExpeditionDatabase::LoadExpedition(uint32_t expedition_id)
|
||||||
|
{
|
||||||
|
LogExpeditions("Loading expedition [{}] for world cache", expedition_id);
|
||||||
|
|
||||||
|
Expedition expedition;
|
||||||
|
|
||||||
|
auto expeditions = LoadExpeditions(expedition_id);
|
||||||
|
if (!expeditions.empty())
|
||||||
|
{
|
||||||
|
expedition = expeditions.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
return expedition;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::DeleteExpeditions(const std::vector<uint32_t>& expedition_ids)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Deleting [{}] expedition(s)", expedition_ids.size());
|
||||||
|
|
||||||
|
std::string expedition_ids_query = fmt::format("{}", fmt::join(expedition_ids, ","));
|
||||||
|
|
||||||
|
if (!expedition_ids_query.empty())
|
||||||
|
{
|
||||||
|
auto query = fmt::format("DELETE FROM expeditions WHERE id IN ({});", expedition_ids_query);
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
|
||||||
|
query = fmt::format("DELETE FROM expedition_members WHERE expedition_id IN ({});", expedition_ids_query);
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
|
||||||
|
query = fmt::format("DELETE FROM expedition_lockouts WHERE expedition_id IN ({});", expedition_ids_query);
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::UpdateDzDuration(uint16_t instance_id, uint32_t new_duration)
|
||||||
|
{
|
||||||
|
std::string query = fmt::format(
|
||||||
|
"UPDATE instance_list SET duration = {} WHERE id = {};",
|
||||||
|
new_duration, instance_id
|
||||||
|
);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::UpdateLeaderID(uint32_t expedition_id, uint32_t leader_id)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Updating leader [{}] for expedition [{}]", leader_id, expedition_id);
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
UPDATE expeditions SET leader_id = {} WHERE id = {};
|
||||||
|
), leader_id, expedition_id);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::MoveMembersToSafeReturn(const std::vector<uint32_t>& expedition_ids)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Moving members from [{}] expedition(s) to safereturn", expedition_ids.size());
|
||||||
|
|
||||||
|
// only offline members still in expired dz zones should be updated here
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
UPDATE character_data
|
||||||
|
INNER JOIN expedition_members ON character_data.id = expedition_members.character_id
|
||||||
|
INNER JOIN expeditions ON expedition_members.expedition_id = expeditions.id
|
||||||
|
INNER JOIN dynamic_zones ON expeditions.dynamic_zone_id = dynamic_zones.id
|
||||||
|
INNER JOIN instance_list ON dynamic_zones.instance_id = instance_list.id
|
||||||
|
AND character_data.zone_instance = instance_list.id
|
||||||
|
AND character_data.zone_id = instance_list.zone
|
||||||
|
SET
|
||||||
|
zone_id = IF(safe_return_zone_id > 0, safe_return_zone_id, zone_id),
|
||||||
|
zone_instance = IF(safe_return_zone_id > 0, 0, zone_instance),
|
||||||
|
x = IF(safe_return_zone_id > 0, safe_return_x, x),
|
||||||
|
y = IF(safe_return_zone_id > 0, safe_return_y, y),
|
||||||
|
z = IF(safe_return_zone_id > 0, safe_return_z, z),
|
||||||
|
heading = IF(safe_return_zone_id > 0, safe_return_heading, heading)
|
||||||
|
WHERE expeditions.id IN ({});
|
||||||
|
), fmt::join(expedition_ids, ","));
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
41
world/expedition_database.h
Normal file
41
world/expedition_database.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WORLD_EXPEDITION_DATABASE_H
|
||||||
|
#define WORLD_EXPEDITION_DATABASE_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Expedition;
|
||||||
|
|
||||||
|
namespace ExpeditionDatabase
|
||||||
|
{
|
||||||
|
void DeleteExpeditions(const std::vector<uint32_t>& expedition_ids);
|
||||||
|
std::vector<Expedition> LoadExpeditions(uint32_t select_expedition_id = 0);
|
||||||
|
Expedition LoadExpedition(uint32_t expedition_id);
|
||||||
|
void MoveMembersToSafeReturn(const std::vector<uint32_t>& expedition_ids);
|
||||||
|
void PurgeExpiredExpeditions();
|
||||||
|
void PurgeExpiredCharacterLockouts();
|
||||||
|
void UpdateDzDuration(uint16_t instance_id, uint32_t new_duration);
|
||||||
|
void UpdateLeaderID(uint32_t expedition_id, uint32_t leader_id);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
229
world/expedition_message.cpp
Normal file
229
world/expedition_message.cpp
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "expedition.h"
|
||||||
|
#include "expedition_message.h"
|
||||||
|
#include "expedition_state.h"
|
||||||
|
#include "cliententry.h"
|
||||||
|
#include "clientlist.h"
|
||||||
|
#include "zonelist.h"
|
||||||
|
#include "zoneserver.h"
|
||||||
|
#include "../common/servertalk.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
extern ClientList client_list;
|
||||||
|
extern ZSList zoneserver_list;
|
||||||
|
|
||||||
|
void ExpeditionMessage::HandleZoneMessage(ServerPacket* pack)
|
||||||
|
{
|
||||||
|
switch (pack->opcode)
|
||||||
|
{
|
||||||
|
case ServerOP_ExpeditionChooseNewLeader:
|
||||||
|
{
|
||||||
|
ExpeditionMessage::ChooseNewLeader(pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_ExpeditionCreate:
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerExpeditionID_Struct*>(pack->pBuffer);
|
||||||
|
expedition_state.AddExpedition(buf->expedition_id);
|
||||||
|
zoneserver_list.SendPacket(pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_ExpeditionMemberChange:
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerExpeditionMemberChange_Struct*>(pack->pBuffer);
|
||||||
|
expedition_state.MemberChange(buf->expedition_id, buf->char_id, buf->removed);
|
||||||
|
zoneserver_list.SendPacket(pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_ExpeditionMemberSwap:
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerExpeditionMemberSwap_Struct*>(pack->pBuffer);
|
||||||
|
expedition_state.MemberChange(buf->expedition_id, buf->add_char_id, false);
|
||||||
|
expedition_state.MemberChange(buf->expedition_id, buf->remove_char_id, true);
|
||||||
|
zoneserver_list.SendPacket(pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_ExpeditionMembersRemoved:
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerExpeditionID_Struct*>(pack->pBuffer);
|
||||||
|
expedition_state.RemoveAllMembers(buf->expedition_id);
|
||||||
|
zoneserver_list.SendPacket(pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_ExpeditionGetOnlineMembers:
|
||||||
|
{
|
||||||
|
ExpeditionMessage::GetOnlineMembers(pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_ExpeditionDzAddPlayer:
|
||||||
|
{
|
||||||
|
ExpeditionMessage::AddPlayer(pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_ExpeditionDzMakeLeader:
|
||||||
|
{
|
||||||
|
ExpeditionMessage::MakeLeader(pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_ExpeditionCharacterLockout:
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerExpeditionCharacterLockout_Struct*>(pack->pBuffer);
|
||||||
|
auto cle = client_list.FindCLEByCharacterID(buf->character_id);
|
||||||
|
if (cle && cle->Server())
|
||||||
|
{
|
||||||
|
cle->Server()->SendPacket(pack);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_ExpeditionSaveInvite:
|
||||||
|
{
|
||||||
|
ExpeditionMessage::SaveInvite(pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_ExpeditionRequestInvite:
|
||||||
|
{
|
||||||
|
ExpeditionMessage::RequestInvite(pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_ExpeditionSecondsRemaining:
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerExpeditionUpdateDuration_Struct*>(pack->pBuffer);
|
||||||
|
expedition_state.SetSecondsRemaining(buf->expedition_id, buf->new_duration_seconds);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionMessage::AddPlayer(ServerPacket* pack)
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerDzCommand_Struct*>(pack->pBuffer);
|
||||||
|
|
||||||
|
ClientListEntry* invited_cle = client_list.FindCharacter(buf->target_name);
|
||||||
|
if (invited_cle && invited_cle->Server())
|
||||||
|
{
|
||||||
|
// continue in the add target's zone
|
||||||
|
buf->is_char_online = true;
|
||||||
|
invited_cle->Server()->SendPacket(pack);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// add target not online, return to inviter
|
||||||
|
ClientListEntry* inviter_cle = client_list.FindCharacter(buf->requester_name);
|
||||||
|
if (inviter_cle && inviter_cle->Server())
|
||||||
|
{
|
||||||
|
inviter_cle->Server()->SendPacket(pack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionMessage::MakeLeader(ServerPacket* pack)
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerDzCommandMakeLeader_Struct*>(pack->pBuffer);
|
||||||
|
|
||||||
|
// notify requester (old leader) and new leader of the result
|
||||||
|
ZoneServer* new_leader_zs = nullptr;
|
||||||
|
ClientListEntry* new_leader_cle = client_list.FindCharacter(buf->new_leader_name);
|
||||||
|
if (new_leader_cle && new_leader_cle->Server())
|
||||||
|
{
|
||||||
|
auto expedition = expedition_state.GetExpedition(buf->expedition_id);
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
buf->is_success = expedition->SetNewLeader(new_leader_cle->CharID());
|
||||||
|
}
|
||||||
|
|
||||||
|
buf->is_online = true;
|
||||||
|
new_leader_zs = new_leader_cle->Server();
|
||||||
|
new_leader_zs->SendPacket(pack);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if old and new leader are in the same zone only send one message
|
||||||
|
ClientListEntry* requester_cle = client_list.FindCLEByCharacterID(buf->requester_id);
|
||||||
|
if (requester_cle && requester_cle->Server() && requester_cle->Server() != new_leader_zs)
|
||||||
|
{
|
||||||
|
requester_cle->Server()->SendPacket(pack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionMessage::GetOnlineMembers(ServerPacket* pack)
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerExpeditionCharacters_Struct*>(pack->pBuffer);
|
||||||
|
|
||||||
|
// not efficient but only requested during caching
|
||||||
|
char zone_name[64] = {0};
|
||||||
|
std::vector<ClientListEntry*> all_clients;
|
||||||
|
all_clients.reserve(client_list.GetClientCount());
|
||||||
|
client_list.GetClients(zone_name, all_clients);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < buf->count; ++i)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(all_clients.begin(), all_clients.end(), [&](const ClientListEntry* cle) {
|
||||||
|
return (cle && cle->CharID() == buf->entries[i].character_id);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != all_clients.end())
|
||||||
|
{
|
||||||
|
buf->entries[i].character_zone_id = (*it)->zone();
|
||||||
|
buf->entries[i].character_instance_id = (*it)->instance();
|
||||||
|
buf->entries[i].character_online = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zoneserver_list.SendPacket(buf->sender_zone_id, buf->sender_instance_id, pack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionMessage::SaveInvite(ServerPacket* pack)
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerDzCommand_Struct*>(pack->pBuffer);
|
||||||
|
|
||||||
|
ClientListEntry* invited_cle = client_list.FindCharacter(buf->target_name);
|
||||||
|
if (invited_cle)
|
||||||
|
{
|
||||||
|
// store packet on cle and re-send it when client requests it
|
||||||
|
buf->is_char_online = true;
|
||||||
|
pack->opcode = ServerOP_ExpeditionDzAddPlayer;
|
||||||
|
invited_cle->SetPendingExpeditionInvite(pack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionMessage::RequestInvite(ServerPacket* pack)
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerExpeditionCharacterID_Struct*>(pack->pBuffer);
|
||||||
|
ClientListEntry* cle = client_list.FindCLEByCharacterID(buf->character_id);
|
||||||
|
if (cle)
|
||||||
|
{
|
||||||
|
auto invite_pack = cle->GetPendingExpeditionInvite();
|
||||||
|
if (invite_pack && cle->Server())
|
||||||
|
{
|
||||||
|
cle->Server()->SendPacket(invite_pack.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionMessage::ChooseNewLeader(ServerPacket* pack)
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerExpeditionID_Struct*>(pack->pBuffer);
|
||||||
|
auto expedition = expedition_state.GetExpedition(buf->expedition_id);
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
expedition->ChooseNewLeader();
|
||||||
|
}
|
||||||
|
}
|
||||||
37
world/expedition_message.h
Normal file
37
world/expedition_message.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WORLD_EXPEDITION_MESSAGE_H
|
||||||
|
#define WORLD_EXPEDITION_MESSAGE_H
|
||||||
|
|
||||||
|
class ServerPacket;
|
||||||
|
|
||||||
|
namespace ExpeditionMessage
|
||||||
|
{
|
||||||
|
void AddPlayer(ServerPacket* pack);
|
||||||
|
void ChooseNewLeader(ServerPacket* pack);
|
||||||
|
void GetOnlineMembers(ServerPacket* pack);
|
||||||
|
void HandleZoneMessage(ServerPacket* pack);
|
||||||
|
void MakeLeader(ServerPacket* pack);
|
||||||
|
void RequestInvite(ServerPacket* pack);
|
||||||
|
void SaveInvite(ServerPacket* pack);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
158
world/expedition_state.cpp
Normal file
158
world/expedition_state.cpp
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "expedition_state.h"
|
||||||
|
#include "expedition.h"
|
||||||
|
#include "expedition_database.h"
|
||||||
|
#include "zonelist.h"
|
||||||
|
#include "zoneserver.h"
|
||||||
|
#include "../common/eqemu_logsys.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
extern ZSList zoneserver_list;
|
||||||
|
|
||||||
|
ExpeditionState expedition_state;
|
||||||
|
|
||||||
|
Expedition* ExpeditionState::GetExpedition(uint32_t expedition_id)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(m_expeditions.begin(), m_expeditions.end(),
|
||||||
|
[&](const Expedition& expedition) { return expedition.GetID() == expedition_id; });
|
||||||
|
|
||||||
|
return (it != m_expeditions.end()) ? &(*it) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionState::LoadActiveExpeditions()
|
||||||
|
{
|
||||||
|
BenchTimer benchmark;
|
||||||
|
|
||||||
|
m_expeditions = ExpeditionDatabase::LoadExpeditions();
|
||||||
|
|
||||||
|
auto elapsed = benchmark.elapsed();
|
||||||
|
LogExpeditions("World caching [{}] expeditions took [{}s]", m_expeditions.size(), elapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionState::AddExpedition(uint32_t expedition_id)
|
||||||
|
{
|
||||||
|
if (expedition_id == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto expedition = ExpeditionDatabase::LoadExpedition(expedition_id);
|
||||||
|
|
||||||
|
if (expedition.IsValid())
|
||||||
|
{
|
||||||
|
auto existing_expedition = GetExpedition(expedition_id);
|
||||||
|
if (!existing_expedition)
|
||||||
|
{
|
||||||
|
m_expeditions.emplace_back(expedition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionState::RemoveExpedition(uint32_t expedition_id)
|
||||||
|
{
|
||||||
|
m_expeditions.erase(std::remove_if(m_expeditions.begin(), m_expeditions.end(),
|
||||||
|
[&](const Expedition& expedition) {
|
||||||
|
return expedition.GetID() == expedition_id;
|
||||||
|
}
|
||||||
|
), m_expeditions.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionState::MemberChange(uint32_t expedition_id, uint32_t character_id, bool remove)
|
||||||
|
{
|
||||||
|
auto expedition = GetExpedition(expedition_id);
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
if (remove) {
|
||||||
|
expedition->RemoveMember(character_id);
|
||||||
|
} else {
|
||||||
|
expedition->AddMember(character_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionState::RemoveAllMembers(uint32_t expedition_id)
|
||||||
|
{
|
||||||
|
auto expedition = GetExpedition(expedition_id);
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
expedition->RemoveAllMembers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionState::SetSecondsRemaining(uint32_t expedition_id, uint32_t seconds_remaining)
|
||||||
|
{
|
||||||
|
auto expedition = GetExpedition(expedition_id);
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
expedition->UpdateDzSecondsRemaining(seconds_remaining);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionState::Process()
|
||||||
|
{
|
||||||
|
if (!m_process_throttle_timer.Check())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> expedition_ids;
|
||||||
|
|
||||||
|
for (auto it = m_expeditions.begin(); it != m_expeditions.end();)
|
||||||
|
{
|
||||||
|
bool is_deleted = false;
|
||||||
|
|
||||||
|
if (it->IsEmpty() || it->IsExpired())
|
||||||
|
{
|
||||||
|
// don't delete expedition until its dz instance is empty. this prevents
|
||||||
|
// an exploit where all members leave expedition and complete an event
|
||||||
|
// before being kicked from removal timer. the lockout could never be
|
||||||
|
// applied because the zone expedition cache was already invalidated.
|
||||||
|
auto dz_zoneserver = zoneserver_list.FindByInstanceID(it->GetInstanceID());
|
||||||
|
if (!dz_zoneserver || dz_zoneserver->NumPlayers() == 0)
|
||||||
|
{
|
||||||
|
LogExpeditions("Expedition [{}] expired or empty, notifying zones and deleting", it->GetID());
|
||||||
|
expedition_ids.emplace_back(it->GetID());
|
||||||
|
it->SendZonesExpeditionDeleted();
|
||||||
|
is_deleted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it->IsEmpty() && !it->IsPendingDelete() && RuleB(Expedition, EmptyDzShutdownEnabled))
|
||||||
|
{
|
||||||
|
it->UpdateDzSecondsRemaining(RuleI(Expedition, EmptyDzShutdownDelaySeconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
it->SetPendingDelete(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
it->CheckExpireWarning();
|
||||||
|
}
|
||||||
|
|
||||||
|
it = is_deleted ? m_expeditions.erase(it) : it + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!expedition_ids.empty())
|
||||||
|
{
|
||||||
|
ExpeditionDatabase::MoveMembersToSafeReturn(expedition_ids);
|
||||||
|
ExpeditionDatabase::DeleteExpeditions(expedition_ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
50
world/expedition_state.h
Normal file
50
world/expedition_state.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WORLD_EXPEDITION_STATE_H
|
||||||
|
#define WORLD_EXPEDITION_STATE_H
|
||||||
|
|
||||||
|
#include "../common/rulesys.h"
|
||||||
|
#include "../common/timer.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
extern class ExpeditionState expedition_state;
|
||||||
|
|
||||||
|
class Expedition;
|
||||||
|
|
||||||
|
class ExpeditionState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void AddExpedition(uint32_t expedition_id);
|
||||||
|
Expedition* GetExpedition(uint32_t expedition_id);
|
||||||
|
void LoadActiveExpeditions();
|
||||||
|
void MemberChange(uint32_t expedition_id, uint32_t character_id, bool remove);
|
||||||
|
void Process();
|
||||||
|
void RemoveAllMembers(uint32_t expedition_id);
|
||||||
|
void RemoveExpedition(uint32_t expedition_id);
|
||||||
|
void SetSecondsRemaining(uint32_t expedition_id, uint32_t seconds_remaining);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Expedition> m_expeditions;
|
||||||
|
Timer m_process_throttle_timer{static_cast<uint32_t>(RuleI(Expedition, WorldExpeditionProcessRateMS))};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -88,6 +88,8 @@ union semun {
|
|||||||
#include "queryserv.h"
|
#include "queryserv.h"
|
||||||
#include "web_interface.h"
|
#include "web_interface.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
#include "expedition_database.h"
|
||||||
|
#include "expedition_state.h"
|
||||||
|
|
||||||
#include "../common/net/servertalk_server.h"
|
#include "../common/net/servertalk_server.h"
|
||||||
#include "../zone/data_bucket.h"
|
#include "../zone/data_bucket.h"
|
||||||
@ -423,12 +425,19 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
adventure_manager.LoadLeaderboardInfo();
|
adventure_manager.LoadLeaderboardInfo();
|
||||||
|
|
||||||
|
LogInfo("Purging expired expeditions");
|
||||||
|
ExpeditionDatabase::PurgeExpiredExpeditions();
|
||||||
|
ExpeditionDatabase::PurgeExpiredCharacterLockouts();
|
||||||
|
|
||||||
LogInfo("Purging expired instances");
|
LogInfo("Purging expired instances");
|
||||||
database.PurgeExpiredInstances();
|
database.PurgeExpiredInstances();
|
||||||
|
|
||||||
Timer PurgeInstanceTimer(450000);
|
Timer PurgeInstanceTimer(450000);
|
||||||
PurgeInstanceTimer.Start(450000);
|
PurgeInstanceTimer.Start(450000);
|
||||||
|
|
||||||
|
LogInfo("Loading active expeditions");
|
||||||
|
expedition_state.LoadActiveExpeditions();
|
||||||
|
|
||||||
LogInfo("Loading char create info");
|
LogInfo("Loading char create info");
|
||||||
content_db.LoadCharacterCreateAllocations();
|
content_db.LoadCharacterCreateAllocations();
|
||||||
content_db.LoadCharacterCreateCombos();
|
content_db.LoadCharacterCreateCombos();
|
||||||
@ -599,6 +608,7 @@ int main(int argc, char** argv) {
|
|||||||
if (PurgeInstanceTimer.Check()) {
|
if (PurgeInstanceTimer.Check()) {
|
||||||
database.PurgeExpiredInstances();
|
database.PurgeExpiredInstances();
|
||||||
database.PurgeAllDeletedDataBuckets();
|
database.PurgeAllDeletedDataBuckets();
|
||||||
|
ExpeditionDatabase::PurgeExpiredCharacterLockouts();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EQTimeTimer.Check()) {
|
if (EQTimeTimer.Check()) {
|
||||||
@ -614,6 +624,7 @@ int main(int argc, char** argv) {
|
|||||||
launcher_list.Process();
|
launcher_list.Process();
|
||||||
LFPGroupList.Process();
|
LFPGroupList.Process();
|
||||||
adventure_manager.Process();
|
adventure_manager.Process();
|
||||||
|
expedition_state.Process();
|
||||||
|
|
||||||
if (InterserverTimer.Check()) {
|
if (InterserverTimer.Check()) {
|
||||||
InterserverTimer.Start();
|
InterserverTimer.Start();
|
||||||
|
|||||||
@ -36,6 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "ucs.h"
|
#include "ucs.h"
|
||||||
#include "queryserv.h"
|
#include "queryserv.h"
|
||||||
#include "world_store.h"
|
#include "world_store.h"
|
||||||
|
#include "expedition_message.h"
|
||||||
|
|
||||||
extern ClientList client_list;
|
extern ClientList client_list;
|
||||||
extern GroupLFPList LFPGroupList;
|
extern GroupLFPList LFPGroupList;
|
||||||
@ -276,6 +277,14 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ServerOP_ChangeGroupLeader: {
|
||||||
|
if (pack->size != sizeof(ServerGroupLeader_Struct)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
zoneserver_list.SendPacket(pack); //bounce it to all zones
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case ServerOP_RaidAdd: {
|
case ServerOP_RaidAdd: {
|
||||||
if (pack->size != sizeof(ServerRaidGeneralAction_Struct))
|
if (pack->size != sizeof(ServerRaidGeneralAction_Struct))
|
||||||
break;
|
break;
|
||||||
@ -1355,6 +1364,52 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
|||||||
cle->ProcessTellQueue();
|
cle->ProcessTellQueue();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ServerOP_CZClientMessageString:
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<CZClientMessageString_Struct*>(pack->pBuffer);
|
||||||
|
client_list.SendPacket(buf->character_name, pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_ExpeditionLockout:
|
||||||
|
case ServerOP_ExpeditionLockoutDuration:
|
||||||
|
case ServerOP_ExpeditionLockState:
|
||||||
|
case ServerOP_ExpeditionMemberStatus:
|
||||||
|
case ServerOP_ExpeditionReplayOnJoin:
|
||||||
|
case ServerOP_ExpeditionDzCompass:
|
||||||
|
case ServerOP_ExpeditionDzSafeReturn:
|
||||||
|
case ServerOP_ExpeditionDzZoneIn:
|
||||||
|
case ServerOP_ExpeditionExpireWarning:
|
||||||
|
{
|
||||||
|
zoneserver_list.SendPacket(pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_ExpeditionChooseNewLeader:
|
||||||
|
case ServerOP_ExpeditionCreate:
|
||||||
|
case ServerOP_ExpeditionGetOnlineMembers:
|
||||||
|
case ServerOP_ExpeditionMemberChange:
|
||||||
|
case ServerOP_ExpeditionMemberSwap:
|
||||||
|
case ServerOP_ExpeditionMembersRemoved:
|
||||||
|
case ServerOP_ExpeditionDzAddPlayer:
|
||||||
|
case ServerOP_ExpeditionDzMakeLeader:
|
||||||
|
case ServerOP_ExpeditionCharacterLockout:
|
||||||
|
case ServerOP_ExpeditionSaveInvite:
|
||||||
|
case ServerOP_ExpeditionRequestInvite:
|
||||||
|
case ServerOP_ExpeditionSecondsRemaining:
|
||||||
|
{
|
||||||
|
ExpeditionMessage::HandleZoneMessage(pack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_DzCharacterChange:
|
||||||
|
case ServerOP_DzRemoveAllCharacters:
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerDzCharacter_Struct*>(pack->pBuffer);
|
||||||
|
ZoneServer* instance_zs = zoneserver_list.FindByInstanceID(buf->instance_id);
|
||||||
|
if (instance_zs)
|
||||||
|
{
|
||||||
|
instance_zs->SendPacket(pack);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
LogInfo("Unknown ServerOPcode from zone {:#04x}, size [{}]", pack->opcode, pack->size);
|
LogInfo("Unknown ServerOPcode from zone {:#04x}, size [{}]", pack->opcode, pack->size);
|
||||||
|
|||||||
@ -22,6 +22,7 @@ SET(zone_sources
|
|||||||
corpse.cpp
|
corpse.cpp
|
||||||
data_bucket.cpp
|
data_bucket.cpp
|
||||||
doors.cpp
|
doors.cpp
|
||||||
|
dynamiczone.cpp
|
||||||
effects.cpp
|
effects.cpp
|
||||||
embparser.cpp
|
embparser.cpp
|
||||||
embparser_api.cpp
|
embparser_api.cpp
|
||||||
@ -30,6 +31,10 @@ SET(zone_sources
|
|||||||
encounter.cpp
|
encounter.cpp
|
||||||
entity.cpp
|
entity.cpp
|
||||||
exp.cpp
|
exp.cpp
|
||||||
|
expedition.cpp
|
||||||
|
expedition_database.cpp
|
||||||
|
expedition_lockout_timer.cpp
|
||||||
|
expedition_request.cpp
|
||||||
fastmath.cpp
|
fastmath.cpp
|
||||||
fearpath.cpp
|
fearpath.cpp
|
||||||
forage.cpp
|
forage.cpp
|
||||||
@ -48,6 +53,7 @@ SET(zone_sources
|
|||||||
lua_encounter.cpp
|
lua_encounter.cpp
|
||||||
lua_entity.cpp
|
lua_entity.cpp
|
||||||
lua_entity_list.cpp
|
lua_entity_list.cpp
|
||||||
|
lua_expedition.cpp
|
||||||
lua_general.cpp
|
lua_general.cpp
|
||||||
lua_group.cpp
|
lua_group.cpp
|
||||||
lua_hate_list.cpp
|
lua_hate_list.cpp
|
||||||
@ -100,6 +106,7 @@ SET(zone_sources
|
|||||||
perl_client.cpp
|
perl_client.cpp
|
||||||
perl_doors.cpp
|
perl_doors.cpp
|
||||||
perl_entity.cpp
|
perl_entity.cpp
|
||||||
|
perl_expedition.cpp
|
||||||
perl_groups.cpp
|
perl_groups.cpp
|
||||||
perl_hateentry.cpp
|
perl_hateentry.cpp
|
||||||
perl_mob.cpp
|
perl_mob.cpp
|
||||||
@ -165,6 +172,7 @@ SET(zone_headers
|
|||||||
corpse.h
|
corpse.h
|
||||||
data_bucket.h
|
data_bucket.h
|
||||||
doors.h
|
doors.h
|
||||||
|
dynamiczone.h
|
||||||
embparser.h
|
embparser.h
|
||||||
embperl.h
|
embperl.h
|
||||||
embxs.h
|
embxs.h
|
||||||
@ -172,6 +180,10 @@ SET(zone_headers
|
|||||||
entity.h
|
entity.h
|
||||||
errmsg.h
|
errmsg.h
|
||||||
event_codes.h
|
event_codes.h
|
||||||
|
expedition.h
|
||||||
|
expedition_database.h
|
||||||
|
expedition_lockout_timer.h
|
||||||
|
expedition_request.h
|
||||||
fastmath.h
|
fastmath.h
|
||||||
forage.h
|
forage.h
|
||||||
global_loot_manager.h
|
global_loot_manager.h
|
||||||
@ -187,6 +199,7 @@ SET(zone_headers
|
|||||||
lua_encounter.h
|
lua_encounter.h
|
||||||
lua_entity.h
|
lua_entity.h
|
||||||
lua_entity_list.h
|
lua_entity_list.h
|
||||||
|
lua_expedition.h
|
||||||
lua_general.h
|
lua_general.h
|
||||||
lua_group.h
|
lua_group.h
|
||||||
lua_hate_list.h
|
lua_hate_list.h
|
||||||
|
|||||||
@ -468,6 +468,12 @@ bool Mob::IsAttackAllowed(Mob *target, bool isSpellAttack)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target->GetSpecialAbility(IMMUNE_DAMAGE_CLIENT) && IsClient())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (target->GetSpecialAbility(IMMUNE_DAMAGE_NPC) && IsNPC())
|
||||||
|
return false;
|
||||||
|
|
||||||
// can't damage own pet (applies to everthing)
|
// can't damage own pet (applies to everthing)
|
||||||
Mob *target_owner = target->GetOwner();
|
Mob *target_owner = target->GetOwner();
|
||||||
Mob *our_owner = GetOwner();
|
Mob *our_owner = GetOwner();
|
||||||
|
|||||||
@ -2247,7 +2247,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQ::skills::SkillTy
|
|||||||
d->spawn_id = GetID();
|
d->spawn_id = GetID();
|
||||||
d->killer_id = killer_mob ? killer_mob->GetID() : 0;
|
d->killer_id = killer_mob ? killer_mob->GetID() : 0;
|
||||||
d->bindzoneid = 0;
|
d->bindzoneid = 0;
|
||||||
d->spell_id = spell == SPELL_UNKNOWN ? 0xffffffff : spell;
|
d->spell_id = 0xffffffff; // Sending spell was causing extra DoT land msg
|
||||||
d->attack_skill = SkillDamageTypes[attack_skill];
|
d->attack_skill = SkillDamageTypes[attack_skill];
|
||||||
d->damage = damage;
|
d->damage = damage;
|
||||||
app->priority = 6;
|
app->priority = 6;
|
||||||
@ -2667,6 +2667,12 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
|||||||
if (IsFamiliar() || GetSpecialAbility(IMMUNE_AGGRO))
|
if (IsFamiliar() || GetSpecialAbility(IMMUNE_AGGRO))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (GetSpecialAbility(IMMUNE_AGGRO_NPC) && other->IsNPC())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient())
|
||||||
|
return;
|
||||||
|
|
||||||
if (spell_id != SPELL_UNKNOWN && NoDetrimentalSpellAggro(spell_id))
|
if (spell_id != SPELL_UNKNOWN && NoDetrimentalSpellAggro(spell_id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2758,8 +2764,11 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
|||||||
else {
|
else {
|
||||||
// cb:2007-08-17
|
// cb:2007-08-17
|
||||||
// owner must get on list, but he's not actually gained any hate yet
|
// owner must get on list, but he's not actually gained any hate yet
|
||||||
if (!owner->GetSpecialAbility(IMMUNE_AGGRO))
|
if (
|
||||||
{
|
!owner->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||||
|
!(this->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && owner->IsClient()) &&
|
||||||
|
!(this->GetSpecialAbility(IMMUNE_AGGRO_NPC) && owner->IsNPC())
|
||||||
|
) {
|
||||||
if (owner->IsClient() && !CheckAggro(owner))
|
if (owner->IsClient() && !CheckAggro(owner))
|
||||||
owner->CastToClient()->AddAutoXTarget(this);
|
owner->CastToClient()->AddAutoXTarget(this);
|
||||||
hate_list.AddEntToHateList(owner, 0, 0, false, !iBuffTic);
|
hate_list.AddEntToHateList(owner, 0, 0, false, !iBuffTic);
|
||||||
@ -2768,13 +2777,25 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mypet && !mypet->IsHeld() && !mypet->IsPetStop()) { // I have a pet, add other to it
|
if (mypet && !mypet->IsHeld() && !mypet->IsPetStop()) { // I have a pet, add other to it
|
||||||
if (!mypet->IsFamiliar() && !mypet->GetSpecialAbility(IMMUNE_AGGRO))
|
if (
|
||||||
|
!mypet->IsFamiliar() &&
|
||||||
|
!mypet->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||||
|
!(mypet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && this->IsClient()) &&
|
||||||
|
!(mypet->GetSpecialAbility(IMMUNE_AGGRO_NPC) && this->IsNPC())
|
||||||
|
) {
|
||||||
mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (myowner) { // I am a pet, add other to owner if it's NPC/LD
|
else if (myowner) { // I am a pet, add other to owner if it's NPC/LD
|
||||||
if (myowner->IsAIControlled() && !myowner->GetSpecialAbility(IMMUNE_AGGRO))
|
if (
|
||||||
|
myowner->IsAIControlled() &&
|
||||||
|
!myowner->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||||
|
!(this->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && myowner->IsClient()) &&
|
||||||
|
!(this->GetSpecialAbility(IMMUNE_AGGRO_NPC) && myowner->IsNPC())
|
||||||
|
) {
|
||||||
myowner->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
myowner->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (other->GetTempPetCount())
|
if (other->GetTempPetCount())
|
||||||
entity_list.AddTempPetsToHateList(other, this, bFrenzy);
|
entity_list.AddTempPetsToHateList(other, this, bFrenzy);
|
||||||
@ -3467,8 +3488,19 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
|||||||
// pets that have GHold will never automatically add NPCs
|
// pets that have GHold will never automatically add NPCs
|
||||||
// pets that have Hold and no Focus will add NPCs if they're engaged
|
// pets that have Hold and no Focus will add NPCs if they're engaged
|
||||||
// pets that have Hold and Focus will not add NPCs
|
// pets that have Hold and Focus will not add NPCs
|
||||||
if (pet && !pet->IsFamiliar() && !pet->GetSpecialAbility(IMMUNE_AGGRO) && !pet->IsEngaged() && attacker && attacker != this && !attacker->IsCorpse() && !pet->IsGHeld() && !attacker->IsTrap())
|
if (
|
||||||
{
|
pet &&
|
||||||
|
!pet->IsFamiliar() &&
|
||||||
|
!pet->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||||
|
!pet->IsEngaged() &&
|
||||||
|
attacker &&
|
||||||
|
!(pet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && attacker->IsClient()) &&
|
||||||
|
!(pet->GetSpecialAbility(IMMUNE_AGGRO_NPC) && attacker->IsNPC()) &&
|
||||||
|
attacker != this &&
|
||||||
|
!attacker->IsCorpse() &&
|
||||||
|
!pet->IsGHeld() &&
|
||||||
|
!attacker->IsTrap()
|
||||||
|
) {
|
||||||
if (!pet->IsHeld()) {
|
if (!pet->IsHeld()) {
|
||||||
LogAggro("Sending pet [{}] into battle due to attack", pet->GetName());
|
LogAggro("Sending pet [{}] into battle due to attack", pet->GetName());
|
||||||
if (IsClient()) {
|
if (IsClient()) {
|
||||||
|
|||||||
@ -2211,12 +2211,12 @@ bool Bot::Process()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mob_scan_close.Check()) {
|
if (mob_close_scan_timer.Check()) {
|
||||||
LogAIScanClose(
|
LogAIScanClose(
|
||||||
"is_moving [{}] bot [{}] timer [{}]",
|
"is_moving [{}] bot [{}] timer [{}]",
|
||||||
moving ? "true" : "false",
|
moving ? "true" : "false",
|
||||||
GetCleanName(),
|
GetCleanName(),
|
||||||
mob_scan_close.GetDuration()
|
mob_close_scan_timer.GetDuration()
|
||||||
);
|
);
|
||||||
|
|
||||||
entity_list.ScanCloseClientMobs(close_mobs, this);
|
entity_list.ScanCloseClientMobs(close_mobs, this);
|
||||||
|
|||||||
766
zone/client.cpp
766
zone/client.cpp
@ -40,6 +40,10 @@ extern volatile bool RunLoops;
|
|||||||
#include "../common/data_verification.h"
|
#include "../common/data_verification.h"
|
||||||
#include "../common/profanity_manager.h"
|
#include "../common/profanity_manager.h"
|
||||||
#include "data_bucket.h"
|
#include "data_bucket.h"
|
||||||
|
#include "expedition.h"
|
||||||
|
#include "expedition_database.h"
|
||||||
|
#include "expedition_lockout_timer.h"
|
||||||
|
#include "expedition_request.h"
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
#include "worldserver.h"
|
#include "worldserver.h"
|
||||||
#include "zonedb.h"
|
#include "zonedb.h"
|
||||||
@ -139,7 +143,7 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
endupkeep_timer(1000),
|
endupkeep_timer(1000),
|
||||||
forget_timer(0),
|
forget_timer(0),
|
||||||
autosave_timer(RuleI(Character, AutosaveIntervalS) * 1000),
|
autosave_timer(RuleI(Character, AutosaveIntervalS) * 1000),
|
||||||
client_scan_npc_aggro_timer(RuleI(Aggro, ClientAggroCheckInterval) * 1000),
|
client_scan_npc_aggro_timer(RuleI(Aggro, ClientAggroCheckIdleInterval)),
|
||||||
client_zone_wide_full_position_update_timer(5 * 60 * 1000),
|
client_zone_wide_full_position_update_timer(5 * 60 * 1000),
|
||||||
tribute_timer(Tribute_duration),
|
tribute_timer(Tribute_duration),
|
||||||
proximity_timer(ClientProximity_interval),
|
proximity_timer(ClientProximity_interval),
|
||||||
@ -264,6 +268,7 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
InitializeMercInfo();
|
InitializeMercInfo();
|
||||||
SetMerc(0);
|
SetMerc(0);
|
||||||
if (RuleI(World, PVPMinLevel) > 0 && level >= RuleI(World, PVPMinLevel) && m_pp.pvp == 0) SetPVP(true, false);
|
if (RuleI(World, PVPMinLevel) > 0 && level >= RuleI(World, PVPMinLevel) && m_pp.pvp == 0) SetPVP(true, false);
|
||||||
|
dynamiczone_removal_timer.Disable();
|
||||||
|
|
||||||
//for good measure:
|
//for good measure:
|
||||||
memset(&m_pp, 0, sizeof(m_pp));
|
memset(&m_pp, 0, sizeof(m_pp));
|
||||||
@ -350,8 +355,8 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
/**
|
/**
|
||||||
* GM
|
* GM
|
||||||
*/
|
*/
|
||||||
display_mob_info_window = true;
|
SetDisplayMobInfoWindow(true);
|
||||||
dev_tools_window_enabled = true;
|
SetDevToolsEnabled(true);
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
bot_owner_options[booDeathMarquee] = false;
|
bot_owner_options[booDeathMarquee] = false;
|
||||||
@ -2428,13 +2433,17 @@ bool Client::CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who,
|
|||||||
char buffer[24] = { 0 };
|
char buffer[24] = { 0 };
|
||||||
snprintf(buffer, 23, "%d %d", skillid, skillval);
|
snprintf(buffer, 23, "%d %d", skillid, skillval);
|
||||||
parse->EventPlayer(EVENT_USE_SKILL, this, buffer, 0);
|
parse->EventPlayer(EVENT_USE_SKILL, this, buffer, 0);
|
||||||
if(against_who)
|
if (against_who) {
|
||||||
{
|
if (
|
||||||
if(against_who->GetSpecialAbility(IMMUNE_AGGRO) || against_who->IsClient() ||
|
against_who->GetSpecialAbility(IMMUNE_AGGRO) ||
|
||||||
GetLevelCon(against_who->GetLevel()) == CON_GRAY)
|
against_who->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) ||
|
||||||
{
|
against_who->IsClient() ||
|
||||||
|
GetLevelCon(against_who->GetLevel()) == CON_GRAY
|
||||||
|
) {
|
||||||
//false by default
|
//false by default
|
||||||
if( !mod_can_increase_skill(skillid, against_who) ) { return(false); }
|
if (!mod_can_increase_skill(skillid, against_who)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3201,6 +3210,27 @@ void Client::MessageString(uint32 type, uint32 string_id, const char* message1,
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::MessageString(const CZClientMessageString_Struct* msg)
|
||||||
|
{
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
if (msg->args_size == 0)
|
||||||
|
{
|
||||||
|
MessageString(msg->chat_type, msg->string_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t outsize = sizeof(FormattedMessage_Struct) + msg->args_size;
|
||||||
|
auto outapp = std::unique_ptr<EQApplicationPacket>(new EQApplicationPacket(OP_FormattedMessage, outsize));
|
||||||
|
auto outbuf = reinterpret_cast<FormattedMessage_Struct*>(outapp->pBuffer);
|
||||||
|
outbuf->string_id = msg->string_id;
|
||||||
|
outbuf->type = msg->chat_type;
|
||||||
|
memcpy(outbuf->message, msg->args, msg->args_size);
|
||||||
|
QueuePacket(outapp.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// helper function, returns true if we should see the message
|
// helper function, returns true if we should see the message
|
||||||
bool Client::FilteredMessageCheck(Mob *sender, eqFilterType filter)
|
bool Client::FilteredMessageCheck(Mob *sender, eqFilterType filter)
|
||||||
{
|
{
|
||||||
@ -3397,6 +3427,13 @@ void Client::LinkDead()
|
|||||||
if(raid){
|
if(raid){
|
||||||
raid->MemberZoned(this);
|
raid->MemberZoned(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expedition* expedition = GetExpedition();
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
expedition->SetMemberStatus(this, ExpeditionMemberStatus::LinkDead);
|
||||||
|
}
|
||||||
|
|
||||||
// save_timer.Start(2500);
|
// save_timer.Start(2500);
|
||||||
linkdead_timer.Start(RuleI(Zone,ClientLinkdeadMS));
|
linkdead_timer.Start(RuleI(Zone,ClientLinkdeadMS));
|
||||||
SendAppearancePacket(AT_Linkdead, 1);
|
SendAppearancePacket(AT_Linkdead, 1);
|
||||||
@ -4725,6 +4762,12 @@ void Client::IncrementAggroCount(bool raid_target)
|
|||||||
|
|
||||||
uint32 newtimer = raid_target ? RuleI(Character, RestRegenRaidTimeToActivate) : RuleI(Character, RestRegenTimeToActivate);
|
uint32 newtimer = raid_target ? RuleI(Character, RestRegenRaidTimeToActivate) : RuleI(Character, RestRegenTimeToActivate);
|
||||||
|
|
||||||
|
// When our aggro count is 1 here, we are exiting rest state. We need to pause our current timer, if we have time remaining
|
||||||
|
// We should not actually have to do anything to the Timer object since the AggroCount counter blocks it from being checked
|
||||||
|
// and will have it's timer changed when we exit combat so let's not do any extra work
|
||||||
|
if (AggroCount == 1 && rest_timer.GetRemainingTime()) // the Client::rest_timer is never disabled, so don't need to check
|
||||||
|
m_pp.RestTimer = std::max(1u, rest_timer.GetRemainingTime() / 1000); // I guess round up?
|
||||||
|
|
||||||
// save the new timer if it's higher
|
// save the new timer if it's higher
|
||||||
m_pp.RestTimer = std::max(m_pp.RestTimer, newtimer);
|
m_pp.RestTimer = std::max(m_pp.RestTimer, newtimer);
|
||||||
|
|
||||||
@ -4734,10 +4777,6 @@ void Client::IncrementAggroCount(bool raid_target)
|
|||||||
if(AggroCount > 1)
|
if(AggroCount > 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Pause the rest timer, it's possible the new timer is a non-raid timer we're currently ticking down on a raid timer
|
|
||||||
if (AggroCount == 1)
|
|
||||||
m_pp.RestTimer = std::max(m_pp.RestTimer, rest_timer.GetRemainingTime() / 1000);
|
|
||||||
|
|
||||||
if (ClientVersion() >= EQ::versions::ClientVersion::SoF) {
|
if (ClientVersion() >= EQ::versions::ClientVersion::SoF) {
|
||||||
auto outapp = new EQApplicationPacket(OP_RestState, 1);
|
auto outapp = new EQApplicationPacket(OP_RestState, 1);
|
||||||
char *Buffer = (char *)outapp->pBuffer;
|
char *Buffer = (char *)outapp->pBuffer;
|
||||||
@ -5743,6 +5782,18 @@ void Client::AddCrystals(uint32 Radiant, uint32 Ebon)
|
|||||||
SendCrystalCounts();
|
SendCrystalCounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::SetEbonCrystals(uint32 value) {
|
||||||
|
m_pp.currentEbonCrystals = value;
|
||||||
|
SaveCurrency();
|
||||||
|
SendCrystalCounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::SetRadiantCrystals(uint32 value) {
|
||||||
|
m_pp.currentRadCrystals = value;
|
||||||
|
SaveCurrency();
|
||||||
|
SendCrystalCounts();
|
||||||
|
}
|
||||||
|
|
||||||
// Processes a client request to inspect a SoF+ client's equipment.
|
// Processes a client request to inspect a SoF+ client's equipment.
|
||||||
void Client::ProcessInspectRequest(Client* requestee, Client* requester) {
|
void Client::ProcessInspectRequest(Client* requestee, Client* requester) {
|
||||||
if(requestee && requester) {
|
if(requestee && requester) {
|
||||||
@ -6110,21 +6161,19 @@ void Client::CheckEmoteHail(Mob *target, const char* message)
|
|||||||
|
|
||||||
void Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z, uint8 count)
|
void Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z, uint8 count)
|
||||||
{
|
{
|
||||||
|
if (count == 0)
|
||||||
auto outapp = new EQApplicationPacket(OP_DzCompass, sizeof(ExpeditionInfo_Struct) +
|
{
|
||||||
sizeof(ExpeditionCompassEntry_Struct) * count);
|
m_has_quest_compass = false;
|
||||||
ExpeditionCompass_Struct *ecs = (ExpeditionCompass_Struct*)outapp->pBuffer;
|
}
|
||||||
//ecs->clientid = GetID();
|
else
|
||||||
ecs->count = count;
|
{
|
||||||
|
m_has_quest_compass = true;
|
||||||
if (count) {
|
m_quest_compass.x = in_x;
|
||||||
ecs->entries[0].x = in_x;
|
m_quest_compass.y = in_y;
|
||||||
ecs->entries[0].y = in_y;
|
m_quest_compass.z = in_z;
|
||||||
ecs->entries[0].z = in_z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FastQueuePacket(&outapp);
|
SendDzCompassUpdate();
|
||||||
safe_delete(outapp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::SendZonePoints()
|
void Client::SendZonePoints()
|
||||||
@ -8617,7 +8666,7 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
|
|||||||
AddMoneyToPP(copper, silver, gold, platinum, false);
|
AddMoneyToPP(copper, silver, gold, platinum, false);
|
||||||
|
|
||||||
if (itemid > 0)
|
if (itemid > 0)
|
||||||
SummonItem(itemid, 0, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor);
|
SummonItem(itemid, -1, 0, 0, 0, 0, 0, false, EQ::invslot::slotCursor);
|
||||||
|
|
||||||
if (faction)
|
if (faction)
|
||||||
{
|
{
|
||||||
@ -9169,17 +9218,14 @@ void Client::SetDisplayMobInfoWindow(bool display_mob_info_window)
|
|||||||
Client::display_mob_info_window = display_mob_info_window;
|
Client::display_mob_info_window = display_mob_info_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::IsDevToolsWindowEnabled() const
|
bool Client::IsDevToolsEnabled() const
|
||||||
{
|
{
|
||||||
return dev_tools_window_enabled;
|
return dev_tools_enabled && RuleB(World, EnableDevTools);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void Client::SetDevToolsEnabled(bool in_dev_tools_enabled)
|
||||||
* @param in_dev_tools_window_enabled
|
|
||||||
*/
|
|
||||||
void Client::SetDevToolsWindowEnabled(bool in_dev_tools_window_enabled)
|
|
||||||
{
|
{
|
||||||
Client::dev_tools_window_enabled = in_dev_tools_window_enabled;
|
Client::dev_tools_enabled = in_dev_tools_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9388,7 +9434,7 @@ void Client::ShowDevToolsMenu()
|
|||||||
std::string menu_commands_search;
|
std::string menu_commands_search;
|
||||||
std::string menu_commands_show;
|
std::string menu_commands_show;
|
||||||
std::string reload_commands_show;
|
std::string reload_commands_show;
|
||||||
std::string window_toggle_command;
|
std::string devtools_toggle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search entity commands
|
* Search entity commands
|
||||||
@ -9423,9 +9469,9 @@ void Client::ShowDevToolsMenu()
|
|||||||
/**
|
/**
|
||||||
* Show window status
|
* Show window status
|
||||||
*/
|
*/
|
||||||
window_toggle_command = "Disabled [" + EQ::SayLinkEngine::GenerateQuestSaylink("#devtools enable_window", false, "Enable") + "] ";
|
devtools_toggle = "Disabled [" + EQ::SayLinkEngine::GenerateQuestSaylink("#devtools enable", false, "Enable") + "] ";
|
||||||
if (IsDevToolsWindowEnabled()) {
|
if (IsDevToolsEnabled()) {
|
||||||
window_toggle_command = "Enabled [" + EQ::SayLinkEngine::GenerateQuestSaylink("#devtools disable_window", false, "Disable") + "] ";
|
devtools_toggle = "Enabled [" + EQ::SayLinkEngine::GenerateQuestSaylink("#devtools disable", false, "Disable") + "] ";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9433,8 +9479,8 @@ void Client::ShowDevToolsMenu()
|
|||||||
*/
|
*/
|
||||||
SendChatLineBreak();
|
SendChatLineBreak();
|
||||||
Message(
|
Message(
|
||||||
Chat::White, "| [Devtools] Window %s Show this menu with %s | Current expansion [%s]",
|
Chat::White, "| [Devtools] %s Show this menu with %s | Current expansion [%s]",
|
||||||
window_toggle_command.c_str(),
|
devtools_toggle.c_str(),
|
||||||
EQ::SayLinkEngine::GenerateQuestSaylink("#dev", false, "#dev").c_str(),
|
EQ::SayLinkEngine::GenerateQuestSaylink("#dev", false, "#dev").c_str(),
|
||||||
content_service.GetCurrentExpansionName().c_str()
|
content_service.GetCurrentExpansionName().c_str()
|
||||||
);
|
);
|
||||||
@ -9448,3 +9494,643 @@ void Client::ShowDevToolsMenu()
|
|||||||
void Client::SendChatLineBreak(uint16 color) {
|
void Client::SendChatLineBreak(uint16 color) {
|
||||||
Message(color, "------------------------------------------------");
|
Message(color, "------------------------------------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::SendCrossZoneMessage(
|
||||||
|
Client* client, const std::string& character_name, uint16_t chat_type, const std::string& message)
|
||||||
|
{
|
||||||
|
// if client is null, falls back to sending a cross zone message by name
|
||||||
|
if (!client && !character_name.empty())
|
||||||
|
{
|
||||||
|
client = entity_list.GetClientByName(character_name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client)
|
||||||
|
{
|
||||||
|
client->Message(chat_type, message.c_str());
|
||||||
|
}
|
||||||
|
else if (!character_name.empty() && !message.empty())
|
||||||
|
{
|
||||||
|
uint32_t pack_size = sizeof(CZMessagePlayer_Struct);
|
||||||
|
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(ServerOP_CZMessagePlayer, pack_size));
|
||||||
|
auto buf = reinterpret_cast<CZMessagePlayer_Struct*>(pack->pBuffer);
|
||||||
|
buf->type = chat_type;
|
||||||
|
strn0cpy(buf->character_name, character_name.c_str(), sizeof(buf->character_name));
|
||||||
|
strn0cpy(buf->message, message.c_str(), sizeof(buf->message));
|
||||||
|
|
||||||
|
worldserver.SendPacket(pack.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::SendCrossZoneMessageString(
|
||||||
|
Client* client, const std::string& character_name, uint16_t chat_type,
|
||||||
|
uint32_t string_id, const std::initializer_list<std::string>& arguments)
|
||||||
|
{
|
||||||
|
// if client is null, falls back to sending a cross zone message by name
|
||||||
|
if (!client && !character_name.empty()) // double check client isn't in this zone
|
||||||
|
{
|
||||||
|
client = entity_list.GetClientByName(character_name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!client && character_name.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializeBuffer argument_buffer;
|
||||||
|
for (const auto& argument : arguments)
|
||||||
|
{
|
||||||
|
argument_buffer.WriteString(argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t args_size = static_cast<uint32_t>(argument_buffer.size());
|
||||||
|
uint32_t pack_size = sizeof(CZClientMessageString_Struct) + args_size;
|
||||||
|
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(ServerOP_CZClientMessageString, pack_size));
|
||||||
|
auto buf = reinterpret_cast<CZClientMessageString_Struct*>(pack->pBuffer);
|
||||||
|
buf->string_id = string_id;
|
||||||
|
buf->chat_type = chat_type;
|
||||||
|
strn0cpy(buf->character_name, character_name.c_str(), sizeof(buf->character_name));
|
||||||
|
buf->args_size = args_size;
|
||||||
|
memcpy(buf->args, argument_buffer.buffer(), argument_buffer.size());
|
||||||
|
|
||||||
|
if (client)
|
||||||
|
{
|
||||||
|
client->MessageString(buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
worldserver.SendPacket(pack.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::UpdateExpeditionInfoAndLockouts()
|
||||||
|
{
|
||||||
|
// this is processed by client after entering a zone
|
||||||
|
SendDzCompassUpdate();
|
||||||
|
|
||||||
|
m_expedition_lockouts = ExpeditionDatabase::LoadCharacterLockouts(CharacterID());
|
||||||
|
|
||||||
|
auto expedition = GetExpedition();
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
expedition->SendClientExpeditionInfo(this);
|
||||||
|
|
||||||
|
// live synchronizes lockouts obtained during the active expedition to
|
||||||
|
// members once they zone into the expedition's dynamic zone instance
|
||||||
|
if (expedition->GetDynamicZone().IsCurrentZoneDzInstance())
|
||||||
|
{
|
||||||
|
expedition->SyncCharacterLockouts(CharacterID(), m_expedition_lockouts);
|
||||||
|
expedition->SetMemberStatus(this, ExpeditionMemberStatus::InDynamicZone);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expedition->SetMemberStatus(this, ExpeditionMemberStatus::Online);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SendExpeditionLockoutTimers();
|
||||||
|
|
||||||
|
// ask world for any pending invite we saved from a previous zone
|
||||||
|
RequestPendingExpeditionInvite();
|
||||||
|
}
|
||||||
|
|
||||||
|
Expedition* Client::CreateExpedition(DynamicZone& dz_instance, ExpeditionRequest& request)
|
||||||
|
{
|
||||||
|
return Expedition::TryCreate(this, dz_instance, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
Expedition* Client::CreateExpedition(
|
||||||
|
const std::string& zone_name, uint32 version, uint32 duration, const std::string& expedition_name,
|
||||||
|
uint32 min_players, uint32 max_players, bool disable_messages)
|
||||||
|
{
|
||||||
|
DynamicZone dz_instance{ zone_name, version, duration, DynamicZoneType::Expedition };
|
||||||
|
ExpeditionRequest request{ expedition_name, min_players, max_players, disable_messages };
|
||||||
|
return Expedition::TryCreate(this, dz_instance, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
Expedition* Client::GetExpedition() const
|
||||||
|
{
|
||||||
|
if (zone && m_expedition_id)
|
||||||
|
{
|
||||||
|
auto expedition_cache_iter = zone->expedition_cache.find(m_expedition_id);
|
||||||
|
if (expedition_cache_iter != zone->expedition_cache.end())
|
||||||
|
{
|
||||||
|
return expedition_cache_iter->second.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::AddExpeditionLockout(const ExpeditionLockoutTimer& lockout, bool update_db)
|
||||||
|
{
|
||||||
|
// todo: support for account based lockouts like live AoC expeditions
|
||||||
|
|
||||||
|
// if client already has this lockout, we're replacing it with the new one
|
||||||
|
m_expedition_lockouts.erase(std::remove_if(m_expedition_lockouts.begin(), m_expedition_lockouts.end(),
|
||||||
|
[&](const ExpeditionLockoutTimer& existing_lockout) {
|
||||||
|
return existing_lockout.IsSameLockout(lockout);
|
||||||
|
}
|
||||||
|
), m_expedition_lockouts.end());
|
||||||
|
|
||||||
|
m_expedition_lockouts.emplace_back(lockout);
|
||||||
|
|
||||||
|
if (update_db) // for quest api
|
||||||
|
{
|
||||||
|
ExpeditionDatabase::InsertCharacterLockouts(CharacterID(), { lockout });
|
||||||
|
}
|
||||||
|
|
||||||
|
SendExpeditionLockoutTimers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::AddNewExpeditionLockout(
|
||||||
|
const std::string& expedition_name, const std::string& event_name, uint32_t seconds, std::string uuid)
|
||||||
|
{
|
||||||
|
auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds, uuid);
|
||||||
|
AddExpeditionLockout(lockout, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::AddExpeditionLockoutDuration(
|
||||||
|
const std::string& expedition_name, const std::string& event_name, int seconds,
|
||||||
|
const std::string& uuid, bool update_db)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(m_expedition_lockouts.begin(), m_expedition_lockouts.end(),
|
||||||
|
[&](const ExpeditionLockoutTimer& lockout) {
|
||||||
|
return lockout.IsSameLockout(expedition_name, event_name);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != m_expedition_lockouts.end())
|
||||||
|
{
|
||||||
|
it->AddLockoutTime(seconds);
|
||||||
|
|
||||||
|
if (!uuid.empty())
|
||||||
|
{
|
||||||
|
it->SetUUID(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (update_db)
|
||||||
|
{
|
||||||
|
ExpeditionDatabase::InsertCharacterLockouts(CharacterID(), { *it });
|
||||||
|
}
|
||||||
|
|
||||||
|
SendExpeditionLockoutTimers();
|
||||||
|
}
|
||||||
|
else if (seconds > 0) // missing lockouts inserted for reductions would be instantly expired
|
||||||
|
{
|
||||||
|
auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds, uuid);
|
||||||
|
AddExpeditionLockout(lockout, update_db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::RemoveExpeditionLockout(
|
||||||
|
const std::string& expedition_name, const std::string& event_name, bool update_db)
|
||||||
|
{
|
||||||
|
m_expedition_lockouts.erase(std::remove_if(m_expedition_lockouts.begin(), m_expedition_lockouts.end(),
|
||||||
|
[&](const ExpeditionLockoutTimer& lockout) {
|
||||||
|
return lockout.IsSameLockout(expedition_name, event_name);
|
||||||
|
}
|
||||||
|
), m_expedition_lockouts.end());
|
||||||
|
|
||||||
|
if (update_db) // for quest api
|
||||||
|
{
|
||||||
|
ExpeditionDatabase::DeleteCharacterLockout(CharacterID(), expedition_name, event_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
SendExpeditionLockoutTimers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::RemoveAllExpeditionLockouts(const std::string& expedition_name, bool update_db)
|
||||||
|
{
|
||||||
|
if (expedition_name.empty())
|
||||||
|
{
|
||||||
|
if (update_db)
|
||||||
|
{
|
||||||
|
ExpeditionDatabase::DeleteAllCharacterLockouts(CharacterID());
|
||||||
|
}
|
||||||
|
m_expedition_lockouts.clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (update_db)
|
||||||
|
{
|
||||||
|
ExpeditionDatabase::DeleteAllCharacterLockouts(CharacterID(), expedition_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_expedition_lockouts.erase(std::remove_if(m_expedition_lockouts.begin(), m_expedition_lockouts.end(),
|
||||||
|
[&](const ExpeditionLockoutTimer& lockout) {
|
||||||
|
return lockout.GetExpeditionName() == expedition_name;
|
||||||
|
}
|
||||||
|
), m_expedition_lockouts.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
SendExpeditionLockoutTimers();
|
||||||
|
}
|
||||||
|
|
||||||
|
const ExpeditionLockoutTimer* Client::GetExpeditionLockout(
|
||||||
|
const std::string& expedition_name, const std::string& event_name, bool include_expired) const
|
||||||
|
{
|
||||||
|
for (const auto& expedition_lockout : m_expedition_lockouts)
|
||||||
|
{
|
||||||
|
if ((include_expired || !expedition_lockout.IsExpired()) &&
|
||||||
|
expedition_lockout.IsSameLockout(expedition_name, event_name))
|
||||||
|
{
|
||||||
|
return &expedition_lockout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ExpeditionLockoutTimer> Client::GetExpeditionLockouts(
|
||||||
|
const std::string& expedition_name, bool include_expired)
|
||||||
|
{
|
||||||
|
std::vector<ExpeditionLockoutTimer> lockouts;
|
||||||
|
for (const auto& lockout : m_expedition_lockouts)
|
||||||
|
{
|
||||||
|
if ((include_expired || !lockout.IsExpired()) &&
|
||||||
|
lockout.GetExpeditionName() == expedition_name)
|
||||||
|
{
|
||||||
|
lockouts.emplace_back(lockout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lockouts;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Client::HasExpeditionLockout(
|
||||||
|
const std::string& expedition_name, const std::string& event_name, bool include_expired)
|
||||||
|
{
|
||||||
|
return (GetExpeditionLockout(expedition_name, event_name, include_expired) != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::SendExpeditionLockoutTimers()
|
||||||
|
{
|
||||||
|
std::vector<ExpeditionLockoutTimerEntry_Struct> lockout_entries;
|
||||||
|
|
||||||
|
// client displays lockouts rounded down to nearest minute, send lockouts
|
||||||
|
// with 60s offset added to compensate (live does this too)
|
||||||
|
constexpr uint32_t rounding_seconds = 60;
|
||||||
|
|
||||||
|
// erases expired lockouts while building lockout timer list
|
||||||
|
for (auto it = m_expedition_lockouts.begin(); it != m_expedition_lockouts.end();)
|
||||||
|
{
|
||||||
|
uint32_t seconds_remaining = it->GetSecondsRemaining();
|
||||||
|
if (seconds_remaining == 0)
|
||||||
|
{
|
||||||
|
it = m_expedition_lockouts.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ExpeditionLockoutTimerEntry_Struct lockout;
|
||||||
|
strn0cpy(lockout.expedition_name, it->GetExpeditionName().c_str(), sizeof(lockout.expedition_name));
|
||||||
|
lockout.seconds_remaining = seconds_remaining + rounding_seconds;
|
||||||
|
lockout.event_type = it->IsReplayTimer() ? Expedition::REPLAY_TIMER_ID : Expedition::EVENT_TIMER_ID;
|
||||||
|
strn0cpy(lockout.event_name, it->GetEventName().c_str(), sizeof(lockout.event_name));
|
||||||
|
|
||||||
|
lockout_entries.emplace_back(lockout);
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t lockout_count = static_cast<uint32_t>(lockout_entries.size());
|
||||||
|
uint32_t lockout_entries_size = sizeof(ExpeditionLockoutTimerEntry_Struct) * lockout_count;
|
||||||
|
uint32_t outsize = sizeof(ExpeditionLockoutTimers_Struct) + lockout_entries_size;
|
||||||
|
auto outapp = std::unique_ptr<EQApplicationPacket>(new EQApplicationPacket(OP_DzExpeditionLockoutTimers, outsize));
|
||||||
|
auto outbuf = reinterpret_cast<ExpeditionLockoutTimers_Struct*>(outapp->pBuffer);
|
||||||
|
outbuf->count = lockout_count;
|
||||||
|
if (!lockout_entries.empty())
|
||||||
|
{
|
||||||
|
memcpy(outbuf->timers, lockout_entries.data(), lockout_entries_size);
|
||||||
|
}
|
||||||
|
QueuePacket(outapp.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::RequestPendingExpeditionInvite()
|
||||||
|
{
|
||||||
|
uint32_t packsize = sizeof(ServerExpeditionCharacterID_Struct);
|
||||||
|
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(ServerOP_ExpeditionRequestInvite, packsize));
|
||||||
|
auto packbuf = reinterpret_cast<ServerExpeditionCharacterID_Struct*>(pack->pBuffer);
|
||||||
|
packbuf->character_id = CharacterID();
|
||||||
|
worldserver.SendPacket(pack.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::DzListTimers()
|
||||||
|
{
|
||||||
|
// only lists player's current replay timer lockouts, not all event lockouts
|
||||||
|
bool found = false;
|
||||||
|
for (const auto& lockout : m_expedition_lockouts)
|
||||||
|
{
|
||||||
|
if (lockout.IsReplayTimer())
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
auto time_remaining = lockout.GetDaysHoursMinutesRemaining();
|
||||||
|
MessageString(
|
||||||
|
Chat::Yellow, DZLIST_REPLAY_TIMER,
|
||||||
|
time_remaining.days.c_str(),
|
||||||
|
time_remaining.hours.c_str(),
|
||||||
|
time_remaining.mins.c_str(),
|
||||||
|
lockout.GetExpeditionName().c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
MessageString(Chat::Yellow, EXPEDITION_NO_TIMERS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::SetDzRemovalTimer(bool enable_timer)
|
||||||
|
{
|
||||||
|
uint32_t timer_ms = RuleI(DynamicZone, ClientRemovalDelayMS);
|
||||||
|
|
||||||
|
LogDynamicZones(
|
||||||
|
"Character [{}] instance [{}] removal timer enabled: [{}] delay (ms): [{}]",
|
||||||
|
CharacterID(), zone ? zone->GetInstanceID() : 0, enable_timer, timer_ms
|
||||||
|
);
|
||||||
|
|
||||||
|
if (enable_timer)
|
||||||
|
{
|
||||||
|
dynamiczone_removal_timer.Start(timer_ms);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dynamiczone_removal_timer.Disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::SendDzCompassUpdate()
|
||||||
|
{
|
||||||
|
// client may be associated with multiple dynamic zone compasses in this zone
|
||||||
|
std::vector<DynamicZoneCompassEntry_Struct> compass_entries;
|
||||||
|
|
||||||
|
for (const auto& client_dz : GetDynamicZones())
|
||||||
|
{
|
||||||
|
auto compass = client_dz.dynamic_zone.GetCompassLocation();
|
||||||
|
if (zone && zone->GetZoneID() == compass.zone_id && zone->GetInstanceID() == 0)
|
||||||
|
{
|
||||||
|
DynamicZoneCompassEntry_Struct entry;
|
||||||
|
entry.dz_zone_id = static_cast<uint16_t>(client_dz.dynamic_zone.GetZoneID());
|
||||||
|
entry.dz_instance_id = static_cast<uint16_t>(client_dz.dynamic_zone.GetInstanceID());
|
||||||
|
entry.dz_type = static_cast<uint32_t>(client_dz.dynamic_zone.GetType());
|
||||||
|
entry.x = compass.x;
|
||||||
|
entry.y = compass.y;
|
||||||
|
entry.z = compass.z;
|
||||||
|
|
||||||
|
compass_entries.emplace_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compass set via MarkSingleCompassLocation()
|
||||||
|
if (m_has_quest_compass)
|
||||||
|
{
|
||||||
|
DynamicZoneCompassEntry_Struct entry;
|
||||||
|
entry.dz_zone_id = 0;
|
||||||
|
entry.dz_instance_id = 0;
|
||||||
|
entry.dz_type = 0;
|
||||||
|
entry.x = m_quest_compass.x;
|
||||||
|
entry.y = m_quest_compass.y;
|
||||||
|
entry.z = m_quest_compass.z;
|
||||||
|
|
||||||
|
compass_entries.emplace_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 count = static_cast<uint32_t>(compass_entries.size());
|
||||||
|
uint32 entries_size = sizeof(DynamicZoneCompassEntry_Struct) * count;
|
||||||
|
uint32 outsize = sizeof(DynamicZoneCompass_Struct) + entries_size;
|
||||||
|
auto outapp = std::unique_ptr<EQApplicationPacket>(new EQApplicationPacket(OP_DzCompass, outsize));
|
||||||
|
auto outbuf = reinterpret_cast<DynamicZoneCompass_Struct*>(outapp->pBuffer);
|
||||||
|
outbuf->count = count;
|
||||||
|
memcpy(outbuf->entries, compass_entries.data(), entries_size);
|
||||||
|
|
||||||
|
QueuePacket(outapp.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::GoToDzSafeReturnOrBind(const DynamicZone& dynamic_zone)
|
||||||
|
{
|
||||||
|
auto safereturn = dynamic_zone.GetSafeReturnLocation();
|
||||||
|
LogDynamicZonesDetail(
|
||||||
|
"Sending character [{}] to safereturn zone [{}] or bind", CharacterID(), safereturn.zone_id
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!dynamic_zone.IsValid() || safereturn.zone_id == 0)
|
||||||
|
{
|
||||||
|
GoToBind();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MovePC(safereturn.zone_id, 0, safereturn.x, safereturn.y, safereturn.z, safereturn.heading);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<DynamicZoneInfo> Client::GetDynamicZones(uint32_t zone_id, int zone_version)
|
||||||
|
{
|
||||||
|
std::vector<DynamicZoneInfo> client_dzs;
|
||||||
|
|
||||||
|
// check client systems for any associated dynamic zones optionally filtered by zone
|
||||||
|
Expedition* expedition = GetExpedition();
|
||||||
|
if (expedition &&
|
||||||
|
(zone_id == 0 || expedition->GetDynamicZone().GetZoneID() == zone_id) &&
|
||||||
|
(zone_version < 0 || expedition->GetDynamicZone().GetZoneVersion() == zone_version))
|
||||||
|
{
|
||||||
|
client_dzs.emplace_back(expedition->GetName(), expedition->GetLeaderName(), expedition->GetDynamicZone());
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: tasks, missions (shared tasks), and quests with an associated dz to zone_id
|
||||||
|
|
||||||
|
return client_dzs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::MovePCDynamicZone(uint32 zone_id, int zone_version, bool msg_if_invalid)
|
||||||
|
{
|
||||||
|
if (zone_id == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto client_dzs = GetDynamicZones(zone_id, zone_version);
|
||||||
|
|
||||||
|
if (client_dzs.empty())
|
||||||
|
{
|
||||||
|
if (msg_if_invalid)
|
||||||
|
{
|
||||||
|
MessageString(Chat::Red, DYNAMICZONE_WAY_IS_BLOCKED); // unconfirmed message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (client_dzs.size() == 1)
|
||||||
|
{
|
||||||
|
const DynamicZone& dz = client_dzs[0].dynamic_zone;
|
||||||
|
DynamicZoneLocation zonein = dz.GetZoneInLocation();
|
||||||
|
ZoneMode zone_mode = dz.HasZoneInLocation() ? ZoneMode::ZoneSolicited : ZoneMode::ZoneToSafeCoords;
|
||||||
|
MovePC(zone_id, dz.GetInstanceID(), zonein.x, zonein.y, zonein.z, zonein.heading, 0, zone_mode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogDynamicZonesDetail(
|
||||||
|
"Sending DzSwitchListWnd to character [{}] associated with [{}] dynamic zone(s)",
|
||||||
|
CharacterID(), client_dzs.size());
|
||||||
|
|
||||||
|
// more than one dynamic zone to this zone, send out the switchlist window
|
||||||
|
// note that this will most likely crash clients if they've reloaded the ui
|
||||||
|
// this occurs on live as well so it may just be a long lasting client bug
|
||||||
|
uint32 count = static_cast<uint32_t>(client_dzs.size());
|
||||||
|
uint32 entries_size = sizeof(DynamicZoneChooseZoneEntry_Struct) * count;
|
||||||
|
uint32 outsize = sizeof(DynamicZoneChooseZone_Struct) + entries_size;
|
||||||
|
auto outapp = std::unique_ptr<EQApplicationPacket>(new EQApplicationPacket(OP_DzChooseZone, outsize));
|
||||||
|
auto outbuf = reinterpret_cast<DynamicZoneChooseZone_Struct*>(outapp->pBuffer);
|
||||||
|
outbuf->count = count;
|
||||||
|
for (int i = 0; i < client_dzs.size(); ++i)
|
||||||
|
{
|
||||||
|
outbuf->choices[i].dz_zone_id = client_dzs[i].dynamic_zone.GetZoneID();
|
||||||
|
outbuf->choices[i].dz_instance_id = client_dzs[i].dynamic_zone.GetInstanceID();
|
||||||
|
outbuf->choices[i].dz_type = static_cast<uint32_t>(client_dzs[i].dynamic_zone.GetType());
|
||||||
|
strn0cpy(outbuf->choices[i].description, client_dzs[i].description.c_str(), sizeof(outbuf->choices[i].description));
|
||||||
|
strn0cpy(outbuf->choices[i].leader_name, client_dzs[i].leader_name.c_str(), sizeof(outbuf->choices[i].leader_name));
|
||||||
|
}
|
||||||
|
QueuePacket(outapp.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::MovePCDynamicZone(const std::string& zone_name, int zone_version, bool msg_if_invalid)
|
||||||
|
{
|
||||||
|
auto zone_id = ZoneID(zone_name.c_str());
|
||||||
|
MovePCDynamicZone(zone_id, zone_version, msg_if_invalid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clipping) {
|
||||||
|
BuffFadeByEffect(SE_Levitate);
|
||||||
|
if (CheckLosFN(target_x, target_y, target_z, 6.0f) || ignore_los) {
|
||||||
|
auto outapp_fling = new EQApplicationPacket(OP_Fling, sizeof(fling_struct));
|
||||||
|
fling_struct* flingTo = (fling_struct*)outapp_fling->pBuffer;
|
||||||
|
if(clipping)
|
||||||
|
flingTo->collision = 0;
|
||||||
|
else
|
||||||
|
flingTo->collision = -1;
|
||||||
|
|
||||||
|
flingTo->travel_time = -1;
|
||||||
|
flingTo->unk3 = 1;
|
||||||
|
flingTo->disable_fall_damage = 1;
|
||||||
|
flingTo->speed_z = value;
|
||||||
|
flingTo->new_y = target_y;
|
||||||
|
flingTo->new_x = target_x;
|
||||||
|
flingTo->new_z = target_z;
|
||||||
|
outapp_fling->priority = 6;
|
||||||
|
FastQueuePacket(&outapp_fling);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> Client::GetLearnableDisciplines(uint8 min_level, uint8 max_level) {
|
||||||
|
bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals);
|
||||||
|
bool SpellBucketRule = RuleB(Spells, EnableSpellBuckets);
|
||||||
|
bool SpellGlobalCheckResult = false;
|
||||||
|
bool SpellBucketCheckResult = false;
|
||||||
|
std::vector<int> learnable_disciplines;
|
||||||
|
for (int spell_id = 0; spell_id < SPDAT_RECORDS; ++spell_id) {
|
||||||
|
bool learnable = false;
|
||||||
|
if (!IsValidSpell(spell_id))
|
||||||
|
continue;
|
||||||
|
if (!IsDiscipline(spell_id))
|
||||||
|
continue;
|
||||||
|
if (spells[spell_id].classes[WARRIOR] == 0)
|
||||||
|
continue;
|
||||||
|
if (max_level > 0 && spells[spell_id].classes[m_pp.class_ - 1] > max_level)
|
||||||
|
continue;
|
||||||
|
if (min_level > 1 && spells[spell_id].classes[m_pp.class_ - 1] < min_level)
|
||||||
|
continue;
|
||||||
|
if (spells[spell_id].skill == 52)
|
||||||
|
continue;
|
||||||
|
if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effectid[EFFECT_COUNT - 1] == 10)
|
||||||
|
continue;
|
||||||
|
if (HasDisciplineLearned(spell_id))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (SpellGlobalRule) {
|
||||||
|
SpellGlobalCheckResult = SpellGlobalCheck(spell_id, CharacterID());
|
||||||
|
if (SpellGlobalCheckResult) {
|
||||||
|
learnable = true;
|
||||||
|
}
|
||||||
|
} else if (SpellBucketRule) {
|
||||||
|
SpellBucketCheckResult = SpellBucketCheck(spell_id, CharacterID());
|
||||||
|
if (SpellBucketCheckResult) {
|
||||||
|
learnable = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
learnable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (learnable) {
|
||||||
|
learnable_disciplines.push_back(spell_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return learnable_disciplines;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> Client::GetLearnedDisciplines() {
|
||||||
|
std::vector<int> learned_disciplines;
|
||||||
|
for (int index = 0; index < MAX_PP_DISCIPLINES; index++) {
|
||||||
|
if (IsValidSpell(m_pp.disciplines.values[index])) {
|
||||||
|
learned_disciplines.push_back(m_pp.disciplines.values[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return learned_disciplines;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> Client::GetMemmedSpells() {
|
||||||
|
std::vector<int> memmed_spells;
|
||||||
|
for (int index = 0; index < EQ::spells::SPELL_GEM_COUNT; index++) {
|
||||||
|
if (IsValidSpell(m_pp.mem_spells[index])) {
|
||||||
|
memmed_spells.push_back(m_pp.mem_spells[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return memmed_spells;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> Client::GetScribeableSpells(uint8 min_level, uint8 max_level) {
|
||||||
|
bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals);
|
||||||
|
bool SpellBucketRule = RuleB(Spells, EnableSpellBuckets);
|
||||||
|
bool SpellGlobalCheckResult = false;
|
||||||
|
bool SpellBucketCheckResult = false;
|
||||||
|
std::vector<int> scribeable_spells;
|
||||||
|
for (int spell_id = 0; spell_id < SPDAT_RECORDS; ++spell_id) {
|
||||||
|
bool scribeable = false;
|
||||||
|
if (!IsValidSpell(spell_id))
|
||||||
|
continue;
|
||||||
|
if (spells[spell_id].classes[WARRIOR] == 0)
|
||||||
|
continue;
|
||||||
|
if (max_level > 0 && spells[spell_id].classes[m_pp.class_ - 1] > max_level)
|
||||||
|
continue;
|
||||||
|
if (min_level > 1 && spells[spell_id].classes[m_pp.class_ - 1] < min_level)
|
||||||
|
continue;
|
||||||
|
if (spells[spell_id].skill == 52)
|
||||||
|
continue;
|
||||||
|
if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effectid[EFFECT_COUNT - 1] == 10)
|
||||||
|
continue;
|
||||||
|
if (HasSpellScribed(spell_id))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (SpellGlobalRule) {
|
||||||
|
SpellGlobalCheckResult = SpellGlobalCheck(spell_id, CharacterID());
|
||||||
|
if (SpellGlobalCheckResult) {
|
||||||
|
scribeable = true;
|
||||||
|
}
|
||||||
|
} else if (SpellBucketRule) {
|
||||||
|
SpellBucketCheckResult = SpellBucketCheck(spell_id, CharacterID());
|
||||||
|
if (SpellBucketCheckResult) {
|
||||||
|
scribeable = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scribeable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scribeable) {
|
||||||
|
scribeable_spells.push_back(spell_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scribeable_spells;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> Client::GetScribedSpells() {
|
||||||
|
std::vector<int> scribed_spells;
|
||||||
|
for(int index = 0; index < EQ::spells::SPELLBOOK_SIZE; index++) {
|
||||||
|
if (IsValidSpell(m_pp.spell_book[index])) {
|
||||||
|
scribed_spells.push_back(m_pp.spell_book[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scribed_spells;
|
||||||
|
}
|
||||||
|
|||||||
@ -21,12 +21,18 @@
|
|||||||
class Client;
|
class Client;
|
||||||
class EQApplicationPacket;
|
class EQApplicationPacket;
|
||||||
class EQStream;
|
class EQStream;
|
||||||
|
class DynamicZone;
|
||||||
|
class Expedition;
|
||||||
|
class ExpeditionLockoutTimer;
|
||||||
|
class ExpeditionRequest;
|
||||||
class Group;
|
class Group;
|
||||||
class NPC;
|
class NPC;
|
||||||
class Object;
|
class Object;
|
||||||
class Raid;
|
class Raid;
|
||||||
class Seperator;
|
class Seperator;
|
||||||
class ServerPacket;
|
class ServerPacket;
|
||||||
|
struct DynamicZoneInfo;
|
||||||
|
struct DynamicZoneLocation;
|
||||||
enum WaterRegionType : int;
|
enum WaterRegionType : int;
|
||||||
|
|
||||||
namespace EQ
|
namespace EQ
|
||||||
@ -232,8 +238,8 @@ public:
|
|||||||
void SetDisplayMobInfoWindow(bool display_mob_info_window);
|
void SetDisplayMobInfoWindow(bool display_mob_info_window);
|
||||||
bool GetDisplayMobInfoWindow() const;
|
bool GetDisplayMobInfoWindow() const;
|
||||||
|
|
||||||
bool IsDevToolsWindowEnabled() const;
|
bool IsDevToolsEnabled() const;
|
||||||
void SetDevToolsWindowEnabled(bool dev_tools_window_enabled);
|
void SetDevToolsEnabled(bool in_dev_tools_enabled);
|
||||||
|
|
||||||
void SetPrimaryWeaponOrnamentation(uint32 model_id);
|
void SetPrimaryWeaponOrnamentation(uint32 model_id);
|
||||||
void SetSecondaryWeaponOrnamentation(uint32 model_id);
|
void SetSecondaryWeaponOrnamentation(uint32 model_id);
|
||||||
@ -283,6 +289,7 @@ public:
|
|||||||
uint8 SlotConvert(uint8 slot,bool bracer=false);
|
uint8 SlotConvert(uint8 slot,bool bracer=false);
|
||||||
void MessageString(uint32 type, uint32 string_id, uint32 distance = 0);
|
void MessageString(uint32 type, uint32 string_id, uint32 distance = 0);
|
||||||
void MessageString(uint32 type, uint32 string_id, const char* message,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0, uint32 distance = 0);
|
void MessageString(uint32 type, uint32 string_id, const char* message,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0, uint32 distance = 0);
|
||||||
|
void MessageString(const CZClientMessageString_Struct* msg);
|
||||||
bool FilteredMessageCheck(Mob *sender, eqFilterType filter);
|
bool FilteredMessageCheck(Mob *sender, eqFilterType filter);
|
||||||
void FilteredMessageString(Mob *sender, uint32 type, eqFilterType filter, uint32 string_id);
|
void FilteredMessageString(Mob *sender, uint32 type, eqFilterType filter, uint32 string_id);
|
||||||
void FilteredMessageString(Mob *sender, uint32 type, eqFilterType filter,
|
void FilteredMessageString(Mob *sender, uint32 type, eqFilterType filter,
|
||||||
@ -594,9 +601,9 @@ public:
|
|||||||
uint32 GetPVPPoints() { return m_pp.PVPCurrentPoints; }
|
uint32 GetPVPPoints() { return m_pp.PVPCurrentPoints; }
|
||||||
void AddPVPPoints(uint32 Points);
|
void AddPVPPoints(uint32 Points);
|
||||||
uint32 GetRadiantCrystals() { return m_pp.currentRadCrystals; }
|
uint32 GetRadiantCrystals() { return m_pp.currentRadCrystals; }
|
||||||
void SetRadiantCrystals(uint32 Crystals) { m_pp.currentRadCrystals = Crystals; }
|
void SetRadiantCrystals(uint32 value);
|
||||||
uint32 GetEbonCrystals() { return m_pp.currentEbonCrystals; }
|
uint32 GetEbonCrystals() { return m_pp.currentEbonCrystals; }
|
||||||
void SetEbonCrystals(uint32 Crystals) { m_pp.currentEbonCrystals = Crystals; }
|
void SetEbonCrystals(uint32 value);
|
||||||
void AddCrystals(uint32 Radiant, uint32 Ebon);
|
void AddCrystals(uint32 Radiant, uint32 Ebon);
|
||||||
void SendCrystalCounts();
|
void SendCrystalCounts();
|
||||||
|
|
||||||
@ -777,6 +784,11 @@ public:
|
|||||||
void UnmemSpellAll(bool update_client = true);
|
void UnmemSpellAll(bool update_client = true);
|
||||||
uint16 FindMemmedSpellBySlot(int slot);
|
uint16 FindMemmedSpellBySlot(int slot);
|
||||||
int MemmedCount();
|
int MemmedCount();
|
||||||
|
std::vector<int> GetLearnableDisciplines(uint8 min_level = 1, uint8 max_level = 0);
|
||||||
|
std::vector<int> GetLearnedDisciplines();
|
||||||
|
std::vector<int> GetMemmedSpells();
|
||||||
|
std::vector<int> GetScribeableSpells(uint8 min_level = 1, uint8 max_level = 0);
|
||||||
|
std::vector<int> GetScribedSpells();
|
||||||
void ScribeSpell(uint16 spell_id, int slot, bool update_client = true);
|
void ScribeSpell(uint16 spell_id, int slot, bool update_client = true);
|
||||||
void UnscribeSpell(int slot, bool update_client = true);
|
void UnscribeSpell(int slot, bool update_client = true);
|
||||||
void UnscribeSpellAll(bool update_client = true);
|
void UnscribeSpellAll(bool update_client = true);
|
||||||
@ -787,6 +799,8 @@ public:
|
|||||||
uint32 GetCharMaxLevelFromQGlobal();
|
uint32 GetCharMaxLevelFromQGlobal();
|
||||||
uint32 GetCharMaxLevelFromBucket();
|
uint32 GetCharMaxLevelFromBucket();
|
||||||
|
|
||||||
|
void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los = false, bool clipping = false);
|
||||||
|
|
||||||
inline bool IsStanding() const {return (playeraction == 0);}
|
inline bool IsStanding() const {return (playeraction == 0);}
|
||||||
inline bool IsSitting() const {return (playeraction == 1);}
|
inline bool IsSitting() const {return (playeraction == 1);}
|
||||||
inline bool IsCrouching() const {return (playeraction == 2);}
|
inline bool IsCrouching() const {return (playeraction == 2);}
|
||||||
@ -966,6 +980,7 @@ public:
|
|||||||
void SendDisciplineUpdate();
|
void SendDisciplineUpdate();
|
||||||
void SendDisciplineTimer(uint32 timer_id, uint32 duration);
|
void SendDisciplineTimer(uint32 timer_id, uint32 duration);
|
||||||
bool UseDiscipline(uint32 spell_id, uint32 target);
|
bool UseDiscipline(uint32 spell_id, uint32 target);
|
||||||
|
bool HasDisciplineLearned(uint16 spell_id);
|
||||||
|
|
||||||
void SetLinkedSpellReuseTimer(uint32 timer_id, uint32 duration);
|
void SetLinkedSpellReuseTimer(uint32 timer_id, uint32 duration);
|
||||||
bool IsLinkedSpellReuseTimerReady(uint32 timer_id);
|
bool IsLinkedSpellReuseTimerReady(uint32 timer_id);
|
||||||
@ -988,6 +1003,7 @@ public:
|
|||||||
void ProcessInspectRequest(Client* requestee, Client* requester);
|
void ProcessInspectRequest(Client* requestee, Client* requester);
|
||||||
bool ClientFinishedLoading() { return (conn_state == ClientConnectFinished); }
|
bool ClientFinishedLoading() { return (conn_state == ClientConnectFinished); }
|
||||||
int FindSpellBookSlotBySpellID(uint16 spellid);
|
int FindSpellBookSlotBySpellID(uint16 spellid);
|
||||||
|
uint32 GetSpellIDByBookSlot(int book_slot);
|
||||||
int GetNextAvailableSpellBookSlot(int starting_slot = 0);
|
int GetNextAvailableSpellBookSlot(int starting_slot = 0);
|
||||||
inline uint32 GetSpellByBookSlot(int book_slot) { return m_pp.spell_book[book_slot]; }
|
inline uint32 GetSpellByBookSlot(int book_slot) { return m_pp.spell_book[book_slot]; }
|
||||||
inline bool HasSpellScribed(int spellid) { return (FindSpellBookSlotBySpellID(spellid) != -1 ? true : false); }
|
inline bool HasSpellScribed(int spellid) { return (FindSpellBookSlotBySpellID(spellid) != -1 ? true : false); }
|
||||||
@ -1103,6 +1119,47 @@ public:
|
|||||||
|
|
||||||
void MarkSingleCompassLoc(float in_x, float in_y, float in_z, uint8 count=1);
|
void MarkSingleCompassLoc(float in_x, float in_y, float in_z, uint8 count=1);
|
||||||
|
|
||||||
|
// cross zone client messaging helpers (null client argument will fallback to messaging by name)
|
||||||
|
static void SendCrossZoneMessage(
|
||||||
|
Client* client, const std::string& client_name, uint16_t chat_type, const std::string& message);
|
||||||
|
static void SendCrossZoneMessageString(
|
||||||
|
Client* client, const std::string& client_name, uint16_t chat_type,
|
||||||
|
uint32_t string_id, const std::initializer_list<std::string>& arguments = {});
|
||||||
|
|
||||||
|
void AddExpeditionLockout(const ExpeditionLockoutTimer& lockout, bool update_db = false);
|
||||||
|
void AddExpeditionLockoutDuration(const std::string& expedition_name,
|
||||||
|
const std::string& event_Name, int seconds, const std::string& uuid = {}, bool update_db = false);
|
||||||
|
void AddNewExpeditionLockout(const std::string& expedition_name,
|
||||||
|
const std::string& event_name, uint32_t duration, std::string uuid = {});
|
||||||
|
Expedition* CreateExpedition(DynamicZone& dz_instance, ExpeditionRequest& request);
|
||||||
|
Expedition* CreateExpedition(
|
||||||
|
const std::string& zone_name, uint32 version, uint32 duration, const std::string& expedition_name,
|
||||||
|
uint32 min_players, uint32 max_players, bool disable_messages = false);
|
||||||
|
Expedition* GetExpedition() const;
|
||||||
|
uint32 GetExpeditionID() const { return m_expedition_id; }
|
||||||
|
const ExpeditionLockoutTimer* GetExpeditionLockout(
|
||||||
|
const std::string& expedition_name, const std::string& event_name, bool include_expired = false) const;
|
||||||
|
const std::vector<ExpeditionLockoutTimer>& GetExpeditionLockouts() const { return m_expedition_lockouts; };
|
||||||
|
std::vector<ExpeditionLockoutTimer> GetExpeditionLockouts(const std::string& expedition_name, bool include_expired = false);
|
||||||
|
uint32 GetPendingExpeditionInviteID() const { return m_pending_expedition_invite.expedition_id; }
|
||||||
|
bool HasExpeditionLockout(const std::string& expedition_name, const std::string& event_name, bool include_expired = false);
|
||||||
|
bool IsInExpedition() const { return m_expedition_id != 0; }
|
||||||
|
void RemoveAllExpeditionLockouts(const std::string& expedition_name, bool update_db = false);
|
||||||
|
void RemoveExpeditionLockout(const std::string& expedition_name,
|
||||||
|
const std::string& event_name, bool update_db = false);
|
||||||
|
void RequestPendingExpeditionInvite();
|
||||||
|
void SendExpeditionLockoutTimers();
|
||||||
|
void SetExpeditionID(uint32 expedition_id) { m_expedition_id = expedition_id; };
|
||||||
|
void SetPendingExpeditionInvite(ExpeditionInvite&& invite) { m_pending_expedition_invite = invite; }
|
||||||
|
void UpdateExpeditionInfoAndLockouts();
|
||||||
|
void DzListTimers();
|
||||||
|
void SetDzRemovalTimer(bool enable_timer);
|
||||||
|
void SendDzCompassUpdate();
|
||||||
|
void GoToDzSafeReturnOrBind(const DynamicZone& dynamic_zone);
|
||||||
|
void MovePCDynamicZone(uint32 zone_id, int zone_version = -1, bool msg_if_invalid = true);
|
||||||
|
void MovePCDynamicZone(const std::string& zone_name, int zone_version = -1, bool msg_if_invalid = true);
|
||||||
|
std::vector<DynamicZoneInfo> GetDynamicZones(uint32_t zone_id = 0, int zone_version = -1);
|
||||||
|
|
||||||
void CalcItemScale();
|
void CalcItemScale();
|
||||||
bool CalcItemScale(uint32 slot_x, uint32 slot_y); // behavior change: 'slot_y' is now [RANGE]_END and not [RANGE]_END + 1
|
bool CalcItemScale(uint32 slot_x, uint32 slot_y); // behavior change: 'slot_y' is now [RANGE]_END and not [RANGE]_END + 1
|
||||||
void DoItemEnterZone();
|
void DoItemEnterZone();
|
||||||
@ -1476,7 +1533,7 @@ private:
|
|||||||
uint32 tmSitting; // time stamp started sitting, used for HP regen bonus added on MAY 5, 2004
|
uint32 tmSitting; // time stamp started sitting, used for HP regen bonus added on MAY 5, 2004
|
||||||
|
|
||||||
bool display_mob_info_window;
|
bool display_mob_info_window;
|
||||||
bool dev_tools_window_enabled;
|
bool dev_tools_enabled;
|
||||||
|
|
||||||
int32 max_end;
|
int32 max_end;
|
||||||
int32 current_endurance;
|
int32 current_endurance;
|
||||||
@ -1556,6 +1613,7 @@ private:
|
|||||||
Timer hp_other_update_throttle_timer; /* This is to keep clients from DOSing the server with macros that change client targets constantly */
|
Timer hp_other_update_throttle_timer; /* This is to keep clients from DOSing the server with macros that change client targets constantly */
|
||||||
Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */
|
Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */
|
||||||
Timer consent_throttle_timer;
|
Timer consent_throttle_timer;
|
||||||
|
Timer dynamiczone_removal_timer;
|
||||||
|
|
||||||
glm::vec3 m_Proximity;
|
glm::vec3 m_Proximity;
|
||||||
glm::vec4 last_position_before_bulk_update;
|
glm::vec4 last_position_before_bulk_update;
|
||||||
@ -1657,6 +1715,12 @@ private:
|
|||||||
|
|
||||||
int client_max_level;
|
int client_max_level;
|
||||||
|
|
||||||
|
uint32 m_expedition_id = 0;
|
||||||
|
ExpeditionInvite m_pending_expedition_invite { 0 };
|
||||||
|
std::vector<ExpeditionLockoutTimer> m_expedition_lockouts;
|
||||||
|
glm::vec3 m_quest_compass;
|
||||||
|
bool m_has_quest_compass = false;
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -49,6 +49,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "../common/zone_numbers.h"
|
#include "../common/zone_numbers.h"
|
||||||
#include "data_bucket.h"
|
#include "data_bucket.h"
|
||||||
#include "event_codes.h"
|
#include "event_codes.h"
|
||||||
|
#include "expedition.h"
|
||||||
|
#include "expedition_database.h"
|
||||||
#include "guild_mgr.h"
|
#include "guild_mgr.h"
|
||||||
#include "merc.h"
|
#include "merc.h"
|
||||||
#include "petitions.h"
|
#include "petitions.h"
|
||||||
@ -191,6 +193,15 @@ void MapOpcodes()
|
|||||||
ConnectedOpcodes[OP_DuelResponse2] = &Client::Handle_OP_DuelResponse2;
|
ConnectedOpcodes[OP_DuelResponse2] = &Client::Handle_OP_DuelResponse2;
|
||||||
ConnectedOpcodes[OP_DumpName] = &Client::Handle_OP_DumpName;
|
ConnectedOpcodes[OP_DumpName] = &Client::Handle_OP_DumpName;
|
||||||
ConnectedOpcodes[OP_Dye] = &Client::Handle_OP_Dye;
|
ConnectedOpcodes[OP_Dye] = &Client::Handle_OP_Dye;
|
||||||
|
ConnectedOpcodes[OP_DzAddPlayer] = &Client::Handle_OP_DzAddPlayer;
|
||||||
|
ConnectedOpcodes[OP_DzChooseZoneReply] = &Client::Handle_OP_DzChooseZoneReply;
|
||||||
|
ConnectedOpcodes[OP_DzExpeditionInviteResponse] = &Client::Handle_OP_DzExpeditionInviteResponse;
|
||||||
|
ConnectedOpcodes[OP_DzListTimers] = &Client::Handle_OP_DzListTimers;
|
||||||
|
ConnectedOpcodes[OP_DzMakeLeader] = &Client::Handle_OP_DzMakeLeader;
|
||||||
|
ConnectedOpcodes[OP_DzPlayerList] = &Client::Handle_OP_DzPlayerList;
|
||||||
|
ConnectedOpcodes[OP_DzRemovePlayer] = &Client::Handle_OP_DzRemovePlayer;
|
||||||
|
ConnectedOpcodes[OP_DzSwapPlayer] = &Client::Handle_OP_DzSwapPlayer;
|
||||||
|
ConnectedOpcodes[OP_DzQuit] = &Client::Handle_OP_DzQuit;
|
||||||
ConnectedOpcodes[OP_Emote] = &Client::Handle_OP_Emote;
|
ConnectedOpcodes[OP_Emote] = &Client::Handle_OP_Emote;
|
||||||
ConnectedOpcodes[OP_EndLootRequest] = &Client::Handle_OP_EndLootRequest;
|
ConnectedOpcodes[OP_EndLootRequest] = &Client::Handle_OP_EndLootRequest;
|
||||||
ConnectedOpcodes[OP_EnvDamage] = &Client::Handle_OP_EnvDamage;
|
ConnectedOpcodes[OP_EnvDamage] = &Client::Handle_OP_EnvDamage;
|
||||||
@ -266,6 +277,7 @@ void MapOpcodes()
|
|||||||
ConnectedOpcodes[OP_ItemViewUnknown] = &Client::Handle_OP_Ignore;
|
ConnectedOpcodes[OP_ItemViewUnknown] = &Client::Handle_OP_Ignore;
|
||||||
ConnectedOpcodes[OP_Jump] = &Client::Handle_OP_Jump;
|
ConnectedOpcodes[OP_Jump] = &Client::Handle_OP_Jump;
|
||||||
ConnectedOpcodes[OP_KeyRing] = &Client::Handle_OP_KeyRing;
|
ConnectedOpcodes[OP_KeyRing] = &Client::Handle_OP_KeyRing;
|
||||||
|
ConnectedOpcodes[OP_KickPlayers] = &Client::Handle_OP_KickPlayers;
|
||||||
ConnectedOpcodes[OP_LDoNButton] = &Client::Handle_OP_LDoNButton;
|
ConnectedOpcodes[OP_LDoNButton] = &Client::Handle_OP_LDoNButton;
|
||||||
ConnectedOpcodes[OP_LDoNDisarmTraps] = &Client::Handle_OP_LDoNDisarmTraps;
|
ConnectedOpcodes[OP_LDoNDisarmTraps] = &Client::Handle_OP_LDoNDisarmTraps;
|
||||||
ConnectedOpcodes[OP_LDoNInspect] = &Client::Handle_OP_LDoNInspect;
|
ConnectedOpcodes[OP_LDoNInspect] = &Client::Handle_OP_LDoNInspect;
|
||||||
@ -885,6 +897,8 @@ void Client::CompleteConnect()
|
|||||||
guild_mgr.RequestOnlineGuildMembers(this->CharacterID(), this->GuildID());
|
guild_mgr.RequestOnlineGuildMembers(this->CharacterID(), this->GuildID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateExpeditionInfoAndLockouts();
|
||||||
|
|
||||||
/** Request adventure info **/
|
/** Request adventure info **/
|
||||||
auto pack = new ServerPacket(ServerOP_AdventureDataRequest, 64);
|
auto pack = new ServerPacket(ServerOP_AdventureDataRequest, 64);
|
||||||
strcpy((char*)pack->pBuffer, GetName());
|
strcpy((char*)pack->pBuffer, GetName());
|
||||||
@ -920,7 +934,7 @@ void Client::CompleteConnect()
|
|||||||
|
|
||||||
entity_list.ScanCloseMobs(close_mobs, this, true);
|
entity_list.ScanCloseMobs(close_mobs, this, true);
|
||||||
|
|
||||||
if (GetGM()) {
|
if (GetGM() && IsDevToolsEnabled()) {
|
||||||
ShowDevToolsMenu();
|
ShowDevToolsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1701,13 +1715,15 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
|||||||
/* Task Packets */
|
/* Task Packets */
|
||||||
LoadClientTaskState();
|
LoadClientTaskState();
|
||||||
|
|
||||||
|
m_expedition_id = ExpeditionDatabase::GetExpeditionIDFromCharacterID(CharacterID());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DevTools Load Settings
|
* DevTools Load Settings
|
||||||
*/
|
*/
|
||||||
if (Admin() >= EQ::DevTools::GM_ACCOUNT_STATUS_LEVEL) {
|
if (Admin() >= EQ::DevTools::GM_ACCOUNT_STATUS_LEVEL) {
|
||||||
std::string dev_tools_window_key = StringFormat("%i-dev-tools-window-disabled", AccountID());
|
std::string dev_tools_window_key = StringFormat("%i-dev-tools-disabled", AccountID());
|
||||||
if (DataBucket::GetData(dev_tools_window_key) == "true") {
|
if (DataBucket::GetData(dev_tools_window_key) == "true") {
|
||||||
dev_tools_window_enabled = false;
|
dev_tools_enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2025,12 +2041,10 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app)
|
|||||||
else if (aps->Type == NorrathsKeepersMerchant)
|
else if (aps->Type == NorrathsKeepersMerchant)
|
||||||
{
|
{
|
||||||
SetRadiantCrystals(GetRadiantCrystals() - (int32)item->LDoNPrice);
|
SetRadiantCrystals(GetRadiantCrystals() - (int32)item->LDoNPrice);
|
||||||
SendCrystalCounts();
|
|
||||||
}
|
}
|
||||||
else if (aps->Type == DarkReignMerchant)
|
else if (aps->Type == DarkReignMerchant)
|
||||||
{
|
{
|
||||||
SetEbonCrystals(GetEbonCrystals() - (int32)item->LDoNPrice);
|
SetEbonCrystals(GetEbonCrystals() - (int32)item->LDoNPrice);
|
||||||
SendCrystalCounts();
|
|
||||||
}
|
}
|
||||||
int16 charges = 1;
|
int16 charges = 1;
|
||||||
if (item->MaxCharges != 0)
|
if (item->MaxCharges != 0)
|
||||||
@ -4533,22 +4547,62 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
rewind_timer.Start(30000, true);
|
rewind_timer.Start(30000, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle client aggro scanning timers NPCs */
|
|
||||||
is_client_moving = (cy == m_Position.y && cx == m_Position.x) ? false : true;
|
is_client_moving = !(cy == m_Position.y && cx == m_Position.x);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client aggro scanning
|
||||||
|
*/
|
||||||
|
const uint16 client_scan_npc_aggro_timer_idle = RuleI(Aggro, ClientAggroCheckIdleInterval);
|
||||||
|
const uint16 client_scan_npc_aggro_timer_moving = RuleI(Aggro, ClientAggroCheckMovingInterval);
|
||||||
|
|
||||||
|
LogAggroDetail(
|
||||||
|
"ClientUpdate [{}] {}moving, scan timer [{}]",
|
||||||
|
GetCleanName(),
|
||||||
|
is_client_moving ? "" : "NOT ",
|
||||||
|
client_scan_npc_aggro_timer.GetRemainingTime()
|
||||||
|
);
|
||||||
|
|
||||||
if (is_client_moving) {
|
if (is_client_moving) {
|
||||||
LogDebug("ClientUpdate: Client is moving - scan timer is: [{}]", client_scan_npc_aggro_timer.GetDuration());
|
if (client_scan_npc_aggro_timer.GetRemainingTime() > client_scan_npc_aggro_timer_moving) {
|
||||||
if (client_scan_npc_aggro_timer.GetDuration() > 1000) {
|
LogAggroDetail("Client [{}] Restarting with moving timer", GetCleanName());
|
||||||
client_scan_npc_aggro_timer.Disable();
|
client_scan_npc_aggro_timer.Disable();
|
||||||
client_scan_npc_aggro_timer.Start(500);
|
client_scan_npc_aggro_timer.Start(client_scan_npc_aggro_timer_moving);
|
||||||
|
client_scan_npc_aggro_timer.Trigger();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else if (client_scan_npc_aggro_timer.GetDuration() == client_scan_npc_aggro_timer_moving) {
|
||||||
LogDebug("ClientUpdate: Client is NOT moving - scan timer is: [{}]", client_scan_npc_aggro_timer.GetDuration());
|
LogAggroDetail("Client [{}] Restarting with idle timer", GetCleanName());
|
||||||
if (client_scan_npc_aggro_timer.GetDuration() < 1000) {
|
|
||||||
client_scan_npc_aggro_timer.Disable();
|
client_scan_npc_aggro_timer.Disable();
|
||||||
client_scan_npc_aggro_timer.Start(3000);
|
client_scan_npc_aggro_timer.Start(client_scan_npc_aggro_timer_idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client mob close list cache scan timer
|
||||||
|
*/
|
||||||
|
const uint16 client_mob_close_scan_timer_moving = 6000;
|
||||||
|
const uint16 client_mob_close_scan_timer_idle = 60000;
|
||||||
|
|
||||||
|
LogAIScanCloseDetail(
|
||||||
|
"Client [{}] {}moving, scan timer [{}]",
|
||||||
|
GetCleanName(),
|
||||||
|
is_client_moving ? "" : "NOT ",
|
||||||
|
mob_close_scan_timer.GetRemainingTime()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (is_client_moving) {
|
||||||
|
if (mob_close_scan_timer.GetRemainingTime() > client_mob_close_scan_timer_moving) {
|
||||||
|
LogAIScanCloseDetail("Client [{}] Restarting with moving timer", GetCleanName());
|
||||||
|
mob_close_scan_timer.Disable();
|
||||||
|
mob_close_scan_timer.Start(client_mob_close_scan_timer_moving);
|
||||||
|
mob_close_scan_timer.Trigger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mob_close_scan_timer.GetDuration() == client_mob_close_scan_timer_moving) {
|
||||||
|
LogAIScanCloseDetail("Client [{}] Restarting with idle timer", GetCleanName());
|
||||||
|
mob_close_scan_timer.Disable();
|
||||||
|
mob_close_scan_timer.Start(client_mob_close_scan_timer_idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -5566,6 +5620,116 @@ void Client::Handle_OP_Dye(const EQApplicationPacket *app)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::Handle_OP_DzAddPlayer(const EQApplicationPacket *app)
|
||||||
|
{
|
||||||
|
auto expedition = GetExpedition();
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
auto dzcmd = reinterpret_cast<ExpeditionCommand_Struct*>(app->pBuffer);
|
||||||
|
expedition->DzAddPlayer(this, dzcmd->name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the only /dz command that sends an error message if no active expedition
|
||||||
|
Message(Chat::System, DZ_YOU_NOT_ASSIGNED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::Handle_OP_DzChooseZoneReply(const EQApplicationPacket *app)
|
||||||
|
{
|
||||||
|
auto dzmsg = reinterpret_cast<DynamicZoneChooseZoneReply_Struct*>(app->pBuffer);
|
||||||
|
LogDynamicZones(
|
||||||
|
"Character [{}] chose DynamicZone [{}]:[{}] type: [{}] with system id: [{}]",
|
||||||
|
CharacterID(), dzmsg->dz_zone_id, dzmsg->dz_instance_id, dzmsg->dz_type, dzmsg->unknown_id2
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!dzmsg->dz_instance_id || !database.VerifyInstanceAlive(dzmsg->dz_instance_id, CharacterID()))
|
||||||
|
{
|
||||||
|
// live just no-ops this without a message
|
||||||
|
LogDynamicZones(
|
||||||
|
"Character [{}] chose invalid DynamicZone [{}]:[{}] or is no longer a member",
|
||||||
|
CharacterID(), dzmsg->dz_zone_id, dzmsg->dz_instance_id
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto client_dzs = GetDynamicZones();
|
||||||
|
auto it = std::find_if(client_dzs.begin(), client_dzs.end(), [&](const DynamicZoneInfo dz_info) {
|
||||||
|
return dz_info.dynamic_zone.IsSameDz(dzmsg->dz_zone_id, dzmsg->dz_instance_id);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != client_dzs.end())
|
||||||
|
{
|
||||||
|
DynamicZoneLocation loc = it->dynamic_zone.GetZoneInLocation();
|
||||||
|
ZoneMode zone_mode = it->dynamic_zone.HasZoneInLocation() ? ZoneMode::ZoneSolicited : ZoneMode::ZoneToSafeCoords;
|
||||||
|
MovePC(dzmsg->dz_zone_id, dzmsg->dz_instance_id, loc.x, loc.y, loc.z, loc.heading, 0, zone_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::Handle_OP_DzExpeditionInviteResponse(const EQApplicationPacket *app)
|
||||||
|
{
|
||||||
|
auto expedition = Expedition::FindCachedExpeditionByID(m_pending_expedition_invite.expedition_id);
|
||||||
|
std::string swap_remove_name = m_pending_expedition_invite.swap_remove_name;
|
||||||
|
m_pending_expedition_invite = { 0 }; // clear before re-validating
|
||||||
|
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
auto dzmsg = reinterpret_cast<ExpeditionInviteResponse_Struct*>(app->pBuffer);
|
||||||
|
expedition->DzInviteResponse(this, dzmsg->accepted, swap_remove_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::Handle_OP_DzListTimers(const EQApplicationPacket *app)
|
||||||
|
{
|
||||||
|
DzListTimers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::Handle_OP_DzMakeLeader(const EQApplicationPacket *app)
|
||||||
|
{
|
||||||
|
auto expedition = GetExpedition();
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
auto dzcmd = reinterpret_cast<ExpeditionCommand_Struct*>(app->pBuffer);
|
||||||
|
expedition->DzMakeLeader(this, dzcmd->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::Handle_OP_DzPlayerList(const EQApplicationPacket *app)
|
||||||
|
{
|
||||||
|
auto expedition = GetExpedition();
|
||||||
|
if (expedition) {
|
||||||
|
expedition->DzPlayerList(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::Handle_OP_DzRemovePlayer(const EQApplicationPacket *app)
|
||||||
|
{
|
||||||
|
auto expedition = GetExpedition();
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
auto dzcmd = reinterpret_cast<ExpeditionCommand_Struct*>(app->pBuffer);
|
||||||
|
expedition->DzRemovePlayer(this, dzcmd->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::Handle_OP_DzSwapPlayer(const EQApplicationPacket *app)
|
||||||
|
{
|
||||||
|
auto expedition = GetExpedition();
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
auto dzcmd = reinterpret_cast<ExpeditionCommandSwap_Struct*>(app->pBuffer);
|
||||||
|
expedition->DzSwapPlayer(this, dzcmd->rem_player_name, dzcmd->add_player_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::Handle_OP_DzQuit(const EQApplicationPacket *app)
|
||||||
|
{
|
||||||
|
auto expedition = GetExpedition();
|
||||||
|
if (expedition) {
|
||||||
|
expedition->DzQuit(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Client::Handle_OP_Emote(const EQApplicationPacket *app)
|
void Client::Handle_OP_Emote(const EQApplicationPacket *app)
|
||||||
{
|
{
|
||||||
if (app->size != sizeof(Emote_Struct)) {
|
if (app->size != sizeof(Emote_Struct)) {
|
||||||
@ -8836,6 +9000,23 @@ void Client::Handle_OP_KeyRing(const EQApplicationPacket *app)
|
|||||||
KeyRingList();
|
KeyRingList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::Handle_OP_KickPlayers(const EQApplicationPacket *app)
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<KickPlayers_Struct*>(app->pBuffer);
|
||||||
|
if (buf->kick_expedition)
|
||||||
|
{
|
||||||
|
auto expedition = GetExpedition();
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
expedition->DzKickPlayers(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (buf->kick_task)
|
||||||
|
{
|
||||||
|
// todo: shared tasks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Client::Handle_OP_LDoNButton(const EQApplicationPacket *app)
|
void Client::Handle_OP_LDoNButton(const EQApplicationPacket *app)
|
||||||
{
|
{
|
||||||
if (app->size < sizeof(bool))
|
if (app->size < sizeof(bool))
|
||||||
@ -10872,8 +11053,8 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case EQ::popupresponse::MOB_INFO_DISMISS:
|
case EQ::popupresponse::MOB_INFO_DISMISS:
|
||||||
this->SetDisplayMobInfoWindow(false);
|
SetDisplayMobInfoWindow(false);
|
||||||
this->Message(Chat::Yellow, "[DevTools] Window snoozed in this zone...");
|
Message(Chat::Yellow, "[DevTools] Window snoozed in this zone...");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -101,6 +101,15 @@
|
|||||||
void Handle_OP_DuelResponse2(const EQApplicationPacket *app);
|
void Handle_OP_DuelResponse2(const EQApplicationPacket *app);
|
||||||
void Handle_OP_DumpName(const EQApplicationPacket *app);
|
void Handle_OP_DumpName(const EQApplicationPacket *app);
|
||||||
void Handle_OP_Dye(const EQApplicationPacket *app);
|
void Handle_OP_Dye(const EQApplicationPacket *app);
|
||||||
|
void Handle_OP_DzAddPlayer(const EQApplicationPacket *app);
|
||||||
|
void Handle_OP_DzChooseZoneReply(const EQApplicationPacket *app);
|
||||||
|
void Handle_OP_DzExpeditionInviteResponse(const EQApplicationPacket *app);
|
||||||
|
void Handle_OP_DzListTimers(const EQApplicationPacket *app);
|
||||||
|
void Handle_OP_DzMakeLeader(const EQApplicationPacket *app);
|
||||||
|
void Handle_OP_DzPlayerList(const EQApplicationPacket *app);
|
||||||
|
void Handle_OP_DzRemovePlayer(const EQApplicationPacket *app);
|
||||||
|
void Handle_OP_DzSwapPlayer(const EQApplicationPacket *app);
|
||||||
|
void Handle_OP_DzQuit(const EQApplicationPacket *app);
|
||||||
void Handle_OP_Emote(const EQApplicationPacket *app);
|
void Handle_OP_Emote(const EQApplicationPacket *app);
|
||||||
void Handle_OP_EndLootRequest(const EQApplicationPacket *app);
|
void Handle_OP_EndLootRequest(const EQApplicationPacket *app);
|
||||||
void Handle_OP_EnvDamage(const EQApplicationPacket *app);
|
void Handle_OP_EnvDamage(const EQApplicationPacket *app);
|
||||||
@ -174,6 +183,7 @@
|
|||||||
void Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app);
|
void Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app);
|
||||||
void Handle_OP_Jump(const EQApplicationPacket *app);
|
void Handle_OP_Jump(const EQApplicationPacket *app);
|
||||||
void Handle_OP_KeyRing(const EQApplicationPacket *app);
|
void Handle_OP_KeyRing(const EQApplicationPacket *app);
|
||||||
|
void Handle_OP_KickPlayers(const EQApplicationPacket *app);
|
||||||
void Handle_OP_LDoNButton(const EQApplicationPacket *app);
|
void Handle_OP_LDoNButton(const EQApplicationPacket *app);
|
||||||
void Handle_OP_LDoNDisarmTraps(const EQApplicationPacket *app);
|
void Handle_OP_LDoNDisarmTraps(const EQApplicationPacket *app);
|
||||||
void Handle_OP_LDoNInspect(const EQApplicationPacket *app);
|
void Handle_OP_LDoNInspect(const EQApplicationPacket *app);
|
||||||
|
|||||||
@ -44,6 +44,7 @@
|
|||||||
#include "../common/spdat.h"
|
#include "../common/spdat.h"
|
||||||
#include "../common/string_util.h"
|
#include "../common/string_util.h"
|
||||||
#include "event_codes.h"
|
#include "event_codes.h"
|
||||||
|
#include "expedition.h"
|
||||||
#include "guild_mgr.h"
|
#include "guild_mgr.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "petitions.h"
|
#include "petitions.h"
|
||||||
@ -160,6 +161,12 @@ bool Client::Process() {
|
|||||||
if (TaskPeriodic_Timer.Check() && taskstate)
|
if (TaskPeriodic_Timer.Check() && taskstate)
|
||||||
taskstate->TaskPeriodicChecks(this);
|
taskstate->TaskPeriodicChecks(this);
|
||||||
|
|
||||||
|
if (dynamiczone_removal_timer.Check() && zone && zone->GetInstanceID() != 0)
|
||||||
|
{
|
||||||
|
dynamiczone_removal_timer.Disable();
|
||||||
|
GoToDzSafeReturnOrBind(zone->GetDynamicZone());
|
||||||
|
}
|
||||||
|
|
||||||
if (linkdead_timer.Check()) {
|
if (linkdead_timer.Check()) {
|
||||||
LeaveGroup();
|
LeaveGroup();
|
||||||
Save();
|
Save();
|
||||||
@ -172,6 +179,13 @@ bool Client::Process() {
|
|||||||
if (myraid) {
|
if (myraid) {
|
||||||
myraid->MemberZoned(this);
|
myraid->MemberZoned(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expedition* expedition = GetExpedition();
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
expedition->SetMemberStatus(this, ExpeditionMemberStatus::Offline);
|
||||||
|
}
|
||||||
|
|
||||||
return false; //delete client
|
return false; //delete client
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,7 +271,7 @@ bool Client::Process() {
|
|||||||
* Used in aggro checks
|
* Used in aggro checks
|
||||||
*/
|
*/
|
||||||
if (mob_close_scan_timer.Check()) {
|
if (mob_close_scan_timer.Check()) {
|
||||||
entity_list.ScanCloseMobs(close_mobs, this, true);
|
entity_list.ScanCloseMobs(close_mobs, this, is_client_moving);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool may_use_attacks = false;
|
bool may_use_attacks = false;
|
||||||
@ -560,6 +574,12 @@ bool Client::Process() {
|
|||||||
client_state = CLIENT_LINKDEAD;
|
client_state = CLIENT_LINKDEAD;
|
||||||
AI_Start(CLIENT_LD_TIMEOUT);
|
AI_Start(CLIENT_LD_TIMEOUT);
|
||||||
SendAppearancePacket(AT_Linkdead, 1);
|
SendAppearancePacket(AT_Linkdead, 1);
|
||||||
|
|
||||||
|
Expedition* expedition = GetExpedition();
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
expedition->SetMemberStatus(this, ExpeditionMemberStatus::LinkDead);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,6 +711,12 @@ void Client::OnDisconnect(bool hard_disconnect) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expedition* expedition = GetExpedition();
|
||||||
|
if (expedition && !bZoning)
|
||||||
|
{
|
||||||
|
expedition->SetMemberStatus(this, ExpeditionMemberStatus::Offline);
|
||||||
|
}
|
||||||
|
|
||||||
RemoveAllAuras();
|
RemoveAllAuras();
|
||||||
|
|
||||||
Mob *Other = trade->With();
|
Mob *Other = trade->With();
|
||||||
|
|||||||
308
zone/command.cpp
308
zone/command.cpp
@ -60,6 +60,7 @@
|
|||||||
|
|
||||||
#include "data_bucket.h"
|
#include "data_bucket.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
#include "expedition.h"
|
||||||
#include "guild_mgr.h"
|
#include "guild_mgr.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "qglobals.h"
|
#include "qglobals.h"
|
||||||
@ -198,11 +199,14 @@ int command_init(void)
|
|||||||
command_add("disarmtrap", "Analog for ldon disarm trap for the newer clients since we still don't have it working.", 80, command_disarmtrap) ||
|
command_add("disarmtrap", "Analog for ldon disarm trap for the newer clients since we still don't have it working.", 80, command_disarmtrap) ||
|
||||||
command_add("distance", "- Reports the distance between you and your target.", 80, command_distance) ||
|
command_add("distance", "- Reports the distance between you and your target.", 80, command_distance) ||
|
||||||
command_add("doanim", "[animnum] [type] - Send an EmoteAnim for you or your target", 50, command_doanim) ||
|
command_add("doanim", "[animnum] [type] - Send an EmoteAnim for you or your target", 50, command_doanim) ||
|
||||||
|
command_add("dz", "Manage expeditions and dynamic zone instances", 80, command_dz) ||
|
||||||
|
command_add("dzkickplayers", "Removes all players from current expedition. (/kickplayers alternative for pre-RoF clients)", 0, command_dzkickplayers) ||
|
||||||
command_add("editmassrespawn", "[name-search] [second-value] - Mass (Zone wide) NPC respawn timer editing command", 100, command_editmassrespawn) ||
|
command_add("editmassrespawn", "[name-search] [second-value] - Mass (Zone wide) NPC respawn timer editing command", 100, command_editmassrespawn) ||
|
||||||
command_add("emote", "['name'/'world'/'zone'] [type] [message] - Send an emote message", 80, command_emote) ||
|
command_add("emote", "['name'/'world'/'zone'] [type] [message] - Send an emote message", 80, command_emote) ||
|
||||||
command_add("emotesearch", "Searches NPC Emotes", 80, command_emotesearch) ||
|
command_add("emotesearch", "Searches NPC Emotes", 80, command_emotesearch) ||
|
||||||
command_add("emoteview", "Lists all NPC Emotes", 80, command_emoteview) ||
|
command_add("emoteview", "Lists all NPC Emotes", 80, command_emoteview) ||
|
||||||
command_add("enablerecipe", "[recipe_id] - Enables a recipe using the recipe id.", 80, command_enablerecipe) ||
|
command_add("enablerecipe", "[recipe_id] - Enables a recipe using the recipe id.", 80, command_enablerecipe) ||
|
||||||
|
command_add("endurance", "Restores you or your target's endurance.", 50, command_endurance) ||
|
||||||
command_add("equipitem", "[slotid(0-21)] - Equip the item on your cursor into the specified slot", 50, command_equipitem) ||
|
command_add("equipitem", "[slotid(0-21)] - Equip the item on your cursor into the specified slot", 50, command_equipitem) ||
|
||||||
command_add("face", "- Change the face of your target", 80, command_face) ||
|
command_add("face", "- Change the face of your target", 80, command_face) ||
|
||||||
command_add("faction", "[Find (criteria | all ) | Review (criteria | all) | Reset (id)] - Resets Player's Faction", 80, command_faction) ||
|
command_add("faction", "[Find (criteria | all ) | Review (criteria | all) | Reset (id)] - Resets Player's Faction", 80, command_faction) ||
|
||||||
@ -435,6 +439,7 @@ int command_init(void)
|
|||||||
command_add("wp", "[add/delete] [grid_num] [pause] [wp_num] [-h] - Add/delete a waypoint to/from a wandering grid", 170, command_wp) ||
|
command_add("wp", "[add/delete] [grid_num] [pause] [wp_num] [-h] - Add/delete a waypoint to/from a wandering grid", 170, command_wp) ||
|
||||||
command_add("wpadd", "[pause] [-h] - Add your current location as a waypoint to your NPC target's AI path", 170, command_wpadd) ||
|
command_add("wpadd", "[pause] [-h] - Add your current location as a waypoint to your NPC target's AI path", 170, command_wpadd) ||
|
||||||
command_add("wpinfo", "- Show waypoint info about your NPC target", 170, command_wpinfo) ||
|
command_add("wpinfo", "- Show waypoint info about your NPC target", 170, command_wpinfo) ||
|
||||||
|
command_add("worldwide", "Performs world-wide GM functions such as cast (can be extended for other commands). Use caution", 250, command_worldwide) ||
|
||||||
command_add("xtargets", "Show your targets Extended Targets and optionally set how many xtargets they can have.", 250, command_xtargets) ||
|
command_add("xtargets", "Show your targets Extended Targets and optionally set how many xtargets they can have.", 250, command_xtargets) ||
|
||||||
command_add("zclip", "[min] [max] - modifies and resends zhdr packet", 80, command_zclip) ||
|
command_add("zclip", "[min] [max] - modifies and resends zhdr packet", 80, command_zclip) ||
|
||||||
command_add("zcolor", "[red] [green] [blue] - Change sky color", 80, command_zcolor) ||
|
command_add("zcolor", "[red] [green] [blue] - Change sky color", 80, command_zcolor) ||
|
||||||
@ -734,6 +739,42 @@ void command_logcommand(Client *c, const char *message)
|
|||||||
/*
|
/*
|
||||||
* commands go below here
|
* commands go below here
|
||||||
*/
|
*/
|
||||||
|
void command_worldwide(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
std::string sub_command;
|
||||||
|
if (sep->arg[1]) {
|
||||||
|
sub_command = sep->arg[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sub_command == "cast") {
|
||||||
|
if (sep->arg[2][0] && Seperator::IsNumber(sep->arg[2])) {
|
||||||
|
int spell_id = atoi(sep->arg[2]);
|
||||||
|
quest_manager.WorldWideCastSpell(spell_id, 0, 0);
|
||||||
|
worldserver.SendEmoteMessage(0, 0, 15, fmt::format("<SYSTEMWIDE MESSAGE> A GM has cast [{}] world-wide!", GetSpellName(spell_id)).c_str());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c->Message(Chat::Yellow, "Usage: #worldwide cast [spellid]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sep->arg[1]) {
|
||||||
|
c->Message(Chat::White, "This command is used to perform world-wide tasks");
|
||||||
|
c->Message(Chat::White, "Usage: #worldwide cast [spellid]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void command_endurance(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
Mob *t;
|
||||||
|
|
||||||
|
t = c->GetTarget() ? c->GetTarget() : c;
|
||||||
|
|
||||||
|
if (t->IsClient())
|
||||||
|
t->CastToClient()->SetEndurance(t->CastToClient()->GetMaxEndurance());
|
||||||
|
else
|
||||||
|
t->SetEndurance(t->GetMaxEndurance());
|
||||||
|
|
||||||
|
t->Message(Chat::White, "Your endurance has been refilled.");
|
||||||
|
}
|
||||||
void command_setstat(Client* c, const Seperator* sep){
|
void command_setstat(Client* c, const Seperator* sep){
|
||||||
if(sep->arg[1][0] && sep->arg[2][0] && c->GetTarget()!=0 && c->GetTarget()->IsClient()){
|
if(sep->arg[1][0] && sep->arg[2][0] && c->GetTarget()!=0 && c->GetTarget()->IsClient()){
|
||||||
c->GetTarget()->CastToClient()->SetStats(atoi(sep->arg[1]),atoi(sep->arg[2]));
|
c->GetTarget()->CastToClient()->SetStats(atoi(sep->arg[1]),atoi(sep->arg[2]));
|
||||||
@ -4837,6 +4878,10 @@ void command_corpse(Client *c, const Seperator *sep)
|
|||||||
c->Message(Chat::White, "Insufficient status to depop player corpse.");
|
c->Message(Chat::White, "Insufficient status to depop player corpse.");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else if (strcasecmp(sep->arg[1], "moveallgraveyard") == 0) {
|
||||||
|
int count = entity_list.MovePlayerCorpsesToGraveyard(true);
|
||||||
|
c->Message(Chat::White, "Moved [%d] player corpse(s) to zone graveyard", count);
|
||||||
|
}
|
||||||
else if (sep->arg[1][0] == 0 || strcasecmp(sep->arg[1], "help") == 0) {
|
else if (sep->arg[1][0] == 0 || strcasecmp(sep->arg[1], "help") == 0) {
|
||||||
c->Message(Chat::White, "#Corpse Sub-Commands:");
|
c->Message(Chat::White, "#Corpse Sub-Commands:");
|
||||||
c->Message(Chat::White, " DeleteNPCCorpses");
|
c->Message(Chat::White, " DeleteNPCCorpses");
|
||||||
@ -4844,6 +4889,7 @@ void command_corpse(Client *c, const Seperator *sep)
|
|||||||
c->Message(Chat::White, " ListNPC");
|
c->Message(Chat::White, " ListNPC");
|
||||||
c->Message(Chat::White, " ListPlayer");
|
c->Message(Chat::White, " ListPlayer");
|
||||||
c->Message(Chat::White, " Lock - GM locks the corpse - cannot be looted by non-GM");
|
c->Message(Chat::White, " Lock - GM locks the corpse - cannot be looted by non-GM");
|
||||||
|
c->Message(Chat::White, " MoveAllGraveyard - move all player corpses to zone's graveyard or non-instance");
|
||||||
c->Message(Chat::White, " UnLock");
|
c->Message(Chat::White, " UnLock");
|
||||||
c->Message(Chat::White, " RemoveCash");
|
c->Message(Chat::White, " RemoveCash");
|
||||||
c->Message(Chat::White, " InspectLoot");
|
c->Message(Chat::White, " InspectLoot");
|
||||||
@ -5592,18 +5638,18 @@ void command_depopzone(Client *c, const Seperator *sep)
|
|||||||
|
|
||||||
void command_devtools(Client *c, const Seperator *sep)
|
void command_devtools(Client *c, const Seperator *sep)
|
||||||
{
|
{
|
||||||
std::string dev_tools_window_key = StringFormat("%i-dev-tools-window-disabled", c->AccountID());
|
std::string dev_tools_key = StringFormat("%i-dev-tools-disabled", c->AccountID());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle window toggle
|
* Handle window toggle
|
||||||
*/
|
*/
|
||||||
if (strcasecmp(sep->arg[1], "disable_window") == 0) {
|
if (strcasecmp(sep->arg[1], "disable") == 0) {
|
||||||
DataBucket::SetData(dev_tools_window_key, "true");
|
DataBucket::SetData(dev_tools_key, "true");
|
||||||
c->SetDevToolsWindowEnabled(false);
|
c->SetDevToolsEnabled(false);
|
||||||
}
|
}
|
||||||
if (strcasecmp(sep->arg[1], "enable_window") == 0) {
|
if (strcasecmp(sep->arg[1], "enable") == 0) {
|
||||||
DataBucket::DeleteData(dev_tools_window_key);
|
DataBucket::DeleteData(dev_tools_key);
|
||||||
c->SetDevToolsWindowEnabled(true);
|
c->SetDevToolsEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
c->ShowDevToolsMenu();
|
c->ShowDevToolsMenu();
|
||||||
@ -6825,6 +6871,210 @@ void command_doanim(Client *c, const Seperator *sep)
|
|||||||
c->DoAnim(atoi(sep->arg[1]),atoi(sep->arg[2]));
|
c->DoAnim(atoi(sep->arg[1]),atoi(sep->arg[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void command_dz(Client* c, const Seperator* sep)
|
||||||
|
{
|
||||||
|
if (!c || !zone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(sep->arg[1], "expedition") == 0)
|
||||||
|
{
|
||||||
|
if (strcasecmp(sep->arg[2], "list") == 0)
|
||||||
|
{
|
||||||
|
std::vector<Expedition*> expeditions;
|
||||||
|
for (const auto& expedition : zone->expedition_cache)
|
||||||
|
{
|
||||||
|
expeditions.emplace_back(expedition.second.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(expeditions.begin(), expeditions.end(),
|
||||||
|
[](const Expedition* lhs, const Expedition* rhs) {
|
||||||
|
return lhs->GetID() < rhs->GetID();
|
||||||
|
});
|
||||||
|
|
||||||
|
c->Message(Chat::White, fmt::format("Total Active Expeditions: [{}]", expeditions.size()).c_str());
|
||||||
|
for (const auto& expedition : expeditions)
|
||||||
|
{
|
||||||
|
auto leader_saylink = EQ::SayLinkEngine::GenerateQuestSaylink(fmt::format(
|
||||||
|
"#goto {}", expedition->GetLeaderName()), false, expedition->GetLeaderName());
|
||||||
|
auto zone_saylink = EQ::SayLinkEngine::GenerateQuestSaylink(fmt::format(
|
||||||
|
"#zoneinstance {}", expedition->GetInstanceID()), false, "zone");
|
||||||
|
|
||||||
|
auto seconds = expedition->GetDynamicZone().GetSecondsRemaining();
|
||||||
|
|
||||||
|
c->Message(Chat::White, fmt::format(
|
||||||
|
"expedition id: [{}] dz id: [{}] name: [{}] leader: [{}] {}: [{}]:[{}]:[{}]:[{}] members: [{}] remaining: [{:02}:{:02}:{:02}]",
|
||||||
|
expedition->GetID(),
|
||||||
|
expedition->GetDynamicZoneID(),
|
||||||
|
expedition->GetName(),
|
||||||
|
leader_saylink,
|
||||||
|
zone_saylink,
|
||||||
|
ZoneName(expedition->GetDynamicZone().GetZoneID()),
|
||||||
|
expedition->GetDynamicZone().GetZoneID(),
|
||||||
|
expedition->GetInstanceID(),
|
||||||
|
expedition->GetDynamicZone().GetZoneVersion(),
|
||||||
|
expedition->GetMemberCount(),
|
||||||
|
seconds / 3600, // hours
|
||||||
|
(seconds / 60) % 60, // minutes
|
||||||
|
seconds % 60 // seconds
|
||||||
|
).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcasecmp(sep->arg[2], "reload") == 0)
|
||||||
|
{
|
||||||
|
Expedition::CacheAllFromDatabase();
|
||||||
|
c->Message(Chat::White, fmt::format(
|
||||||
|
"Reloaded [{}] expeditions to cache from database.", zone->expedition_cache.size()
|
||||||
|
).c_str());
|
||||||
|
}
|
||||||
|
else if (strcasecmp(sep->arg[2], "destroy") == 0 && sep->IsNumber(3))
|
||||||
|
{
|
||||||
|
auto expedition_id = std::strtoul(sep->arg[3], nullptr, 10);
|
||||||
|
auto expedition = Expedition::FindCachedExpeditionByID(expedition_id);
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
c->Message(Chat::White, fmt::format("Destroying expedition [{}] ({})",
|
||||||
|
expedition_id, expedition->GetName()).c_str());
|
||||||
|
expedition->RemoveAllMembers();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->Message(Chat::Red, fmt::format("Failed to destroy expedition [{}]", sep->arg[3]).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcasecmp(sep->arg[2], "unlock") == 0 && sep->IsNumber(3))
|
||||||
|
{
|
||||||
|
auto expedition_id = std::strtoul(sep->arg[3], nullptr, 10);
|
||||||
|
auto expedition = Expedition::FindCachedExpeditionByID(expedition_id);
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
c->Message(Chat::White, fmt::format("Unlocking expedition [{}]", expedition_id).c_str());
|
||||||
|
expedition->SetLocked(false, ExpeditionLockMessage::None, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->Message(Chat::Red, fmt::format("Failed to find expedition [{}]", sep->arg[3]).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcasecmp(sep->arg[1], "list") == 0)
|
||||||
|
{
|
||||||
|
std::string query = SQL(
|
||||||
|
SELECT
|
||||||
|
dynamic_zones.id,
|
||||||
|
dynamic_zones.type,
|
||||||
|
instance_list.id,
|
||||||
|
instance_list.zone,
|
||||||
|
instance_list.version,
|
||||||
|
instance_list.start_time,
|
||||||
|
instance_list.duration,
|
||||||
|
COUNT(instance_list_player.id) member_count
|
||||||
|
FROM dynamic_zones
|
||||||
|
INNER JOIN instance_list ON dynamic_zones.instance_id = instance_list.id
|
||||||
|
LEFT JOIN instance_list_player ON instance_list.id = instance_list_player.id
|
||||||
|
GROUP BY instance_list.id
|
||||||
|
ORDER BY dynamic_zones.id;
|
||||||
|
);
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (results.Success())
|
||||||
|
{
|
||||||
|
c->Message(Chat::White, fmt::format("Total Dynamic Zones: [{}]", results.RowCount()).c_str());
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row)
|
||||||
|
{
|
||||||
|
auto start_time = strtoul(row[5], nullptr, 10);
|
||||||
|
auto duration = strtoul(row[6], nullptr, 10);
|
||||||
|
auto expire_time = std::chrono::system_clock::from_time_t(start_time + duration);
|
||||||
|
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
auto remaining = std::chrono::duration_cast<std::chrono::seconds>(expire_time - now);
|
||||||
|
auto seconds = std::max(0, static_cast<int>(remaining.count()));
|
||||||
|
|
||||||
|
bool is_expired = now > expire_time;
|
||||||
|
if (!is_expired || strcasecmp(sep->arg[2], "all") == 0)
|
||||||
|
{
|
||||||
|
uint32_t instance_id = strtoul(row[2], nullptr, 10);
|
||||||
|
auto zone_saylink = is_expired ? "zone" : EQ::SayLinkEngine::GenerateQuestSaylink(
|
||||||
|
fmt::format("#zoneinstance {}", instance_id), false, "zone");
|
||||||
|
|
||||||
|
c->Message(Chat::White, fmt::format(
|
||||||
|
"dz id: [{}] type: [{}] {}: [{}]:[{}]:[{}] members: [{}] remaining: [{:02}:{:02}:{:02}]",
|
||||||
|
strtoul(row[0], nullptr, 10), // dynamic_zone_id
|
||||||
|
strtoul(row[1], nullptr, 10), // dynamic_zone_type
|
||||||
|
zone_saylink,
|
||||||
|
strtoul(row[3], nullptr, 10), // instance_zone_id
|
||||||
|
instance_id, // instance_id
|
||||||
|
strtoul(row[4], nullptr, 10), // instance_zone_version
|
||||||
|
strtoul(row[7], nullptr, 10), // instance member_count
|
||||||
|
seconds / 3600, // hours
|
||||||
|
(seconds / 60) % 60, // minutes
|
||||||
|
seconds % 60 // seconds
|
||||||
|
).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcasecmp(sep->arg[1], "lockouts") == 0)
|
||||||
|
{
|
||||||
|
if (strcasecmp(sep->arg[2], "remove") == 0 && sep->arg[3][0] != '\0')
|
||||||
|
{
|
||||||
|
if (sep->arg[5][0] == '\0')
|
||||||
|
{
|
||||||
|
c->Message(Chat::White, fmt::format(
|
||||||
|
"Removing [{}] lockouts on [{}].", sep->arg[4][0] ? sep->arg[4] : "all", sep->arg[3]
|
||||||
|
).c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->Message(Chat::White, fmt::format(
|
||||||
|
"Removing [{}]:[{}] lockout on [{}].", sep->arg[4], sep->arg[5], sep->arg[3]
|
||||||
|
).c_str());
|
||||||
|
}
|
||||||
|
Expedition::RemoveLockoutsByCharacterName(sep->arg[3], sep->arg[4], sep->arg[5]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcasecmp(sep->arg[1], "makeleader") == 0 && sep->IsNumber(2) && sep->arg[3][0] != '\0')
|
||||||
|
{
|
||||||
|
auto expedition_id = std::strtoul(sep->arg[2], nullptr, 10);
|
||||||
|
auto expedition = Expedition::FindCachedExpeditionByID(expedition_id);
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
auto char_name = FormatName(sep->arg[3]);
|
||||||
|
c->Message(Chat::White, fmt::format("Setting expedition [{}] leader to [{}]", expedition_id, char_name).c_str());
|
||||||
|
expedition->SendWorldMakeLeaderRequest(c->CharacterID(), char_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->Message(Chat::Red, fmt::format("Failed to find expedition [{}]", expedition_id).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->Message(Chat::White, "#dz usage:");
|
||||||
|
c->Message(Chat::White, "#dz expedition list - list expeditions in current zone cache");
|
||||||
|
c->Message(Chat::White, "#dz expedition reload - reload expedition zone cache from database");
|
||||||
|
c->Message(Chat::White, "#dz expedition destroy <expedition_id> - destroy expedition globally (must be in cache)");
|
||||||
|
c->Message(Chat::White, "#dz expedition unlock <expedition_id> - unlock expedition");
|
||||||
|
c->Message(Chat::White, "#dz list [all] - list dynamic zone instances from database -- 'all' includes expired");
|
||||||
|
c->Message(Chat::White, "#dz lockouts remove <char_name> - delete all of character's expedition lockouts");
|
||||||
|
c->Message(Chat::White, "#dz lockouts remove <char_name> \"<expedition_name>\" - delete lockouts by expedition");
|
||||||
|
c->Message(Chat::White, "#dz lockouts remove <char_name> \"<expedition_name>\" \"<event_name>\" - delete lockout by expedition event");
|
||||||
|
c->Message(Chat::White, "#dz makeleader <expedition_id> <character_name> - set new expedition leader");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void command_dzkickplayers(Client* c, const Seperator* sep)
|
||||||
|
{
|
||||||
|
if (c)
|
||||||
|
{
|
||||||
|
auto expedition = c->GetExpedition();
|
||||||
|
if (expedition)
|
||||||
|
{
|
||||||
|
expedition->DzKickPlayers(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void command_editmassrespawn(Client* c, const Seperator* sep)
|
void command_editmassrespawn(Client* c, const Seperator* sep)
|
||||||
{
|
{
|
||||||
if (strcasecmp(sep->arg[1], "usage") == 0) {
|
if (strcasecmp(sep->arg[1], "usage") == 0) {
|
||||||
@ -6879,7 +7129,7 @@ void command_editmassrespawn(Client* c, const Seperator* sep)
|
|||||||
|
|
||||||
int results_count = 0;
|
int results_count = 0;
|
||||||
|
|
||||||
auto results = database.QueryDatabase(query);
|
auto results = content_db.QueryDatabase(query);
|
||||||
if (results.Success() && results.RowCount()) {
|
if (results.Success() && results.RowCount()) {
|
||||||
|
|
||||||
results_count = results.RowCount();
|
results_count = results.RowCount();
|
||||||
@ -6906,7 +7156,7 @@ void command_editmassrespawn(Client* c, const Seperator* sep)
|
|||||||
|
|
||||||
if (change_apply) {
|
if (change_apply) {
|
||||||
|
|
||||||
results = database.QueryDatabase(
|
results = content_db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
SQL(
|
SQL(
|
||||||
UPDATE spawn2
|
UPDATE spawn2
|
||||||
@ -7741,13 +7991,6 @@ void command_itemsearch(Client *c, const Seperator *sep)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> amounts = {
|
|
||||||
"1",
|
|
||||||
"10",
|
|
||||||
"100",
|
|
||||||
"1000"
|
|
||||||
};
|
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
char sName[64];
|
char sName[64];
|
||||||
char sCriteria[255];
|
char sCriteria[255];
|
||||||
@ -7761,14 +8004,25 @@ void command_itemsearch(Client *c, const Seperator *sep)
|
|||||||
pdest = strstr(sName, sCriteria);
|
pdest = strstr(sName, sCriteria);
|
||||||
if (pdest != nullptr) {
|
if (pdest != nullptr) {
|
||||||
linker.SetItemData(item);
|
linker.SetItemData(item);
|
||||||
|
std::string item_id = std::to_string(item->ID);
|
||||||
std::string saylink_commands;
|
std::string saylink_commands =
|
||||||
for (auto &amount : amounts) {
|
"[" +
|
||||||
saylink_commands += EQ::SayLinkEngine::GenerateQuestSaylink(
|
EQ::SayLinkEngine::GenerateQuestSaylink(
|
||||||
"#si " + std::to_string(item->ID) + " " + amount,
|
"#si " + item_id,
|
||||||
false,
|
false,
|
||||||
"[" + amount + "] "
|
"X"
|
||||||
);
|
) +
|
||||||
|
"] ";
|
||||||
|
if (item->Stackable && item->StackSize > 1) {
|
||||||
|
std::string stack_size = std::to_string(item->StackSize);
|
||||||
|
saylink_commands +=
|
||||||
|
"[" +
|
||||||
|
EQ::SayLinkEngine::GenerateQuestSaylink(
|
||||||
|
"#si " + item_id + " " + stack_size,
|
||||||
|
false,
|
||||||
|
stack_size
|
||||||
|
) +
|
||||||
|
"]";
|
||||||
}
|
}
|
||||||
|
|
||||||
c->Message(
|
c->Message(
|
||||||
@ -7776,8 +8030,8 @@ void command_itemsearch(Client *c, const Seperator *sep)
|
|||||||
fmt::format(
|
fmt::format(
|
||||||
" Summon {} [{}] [{}]",
|
" Summon {} [{}] [{}]",
|
||||||
saylink_commands,
|
saylink_commands,
|
||||||
item->ID,
|
linker.GenerateLink(),
|
||||||
linker.GenerateLink()
|
item->ID
|
||||||
).c_str()
|
).c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -7855,14 +8109,10 @@ void command_setcrystals(Client *c, const Seperator *sep)
|
|||||||
else if(!strcasecmp(sep->arg[1], "radiant"))
|
else if(!strcasecmp(sep->arg[1], "radiant"))
|
||||||
{
|
{
|
||||||
t->SetRadiantCrystals(atoi(sep->arg[2]));
|
t->SetRadiantCrystals(atoi(sep->arg[2]));
|
||||||
t->SendCrystalCounts();
|
|
||||||
t->SaveCurrency();
|
|
||||||
}
|
}
|
||||||
else if(!strcasecmp(sep->arg[1], "ebon"))
|
else if(!strcasecmp(sep->arg[1], "ebon"))
|
||||||
{
|
{
|
||||||
t->SetEbonCrystals(atoi(sep->arg[2]));
|
t->SetEbonCrystals(atoi(sep->arg[2]));
|
||||||
t->SendCrystalCounts();
|
|
||||||
t->SaveCurrency();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -92,11 +92,14 @@ void command_disablerecipe(Client *c, const Seperator *sep);
|
|||||||
void command_disarmtrap(Client *c, const Seperator *sep);
|
void command_disarmtrap(Client *c, const Seperator *sep);
|
||||||
void command_distance(Client *c, const Seperator *sep);
|
void command_distance(Client *c, const Seperator *sep);
|
||||||
void command_doanim(Client *c, const Seperator *sep);
|
void command_doanim(Client *c, const Seperator *sep);
|
||||||
|
void command_dz(Client *c, const Seperator *sep);
|
||||||
|
void command_dzkickplayers(Client *c, const Seperator *sep);
|
||||||
void command_editmassrespawn(Client* c, const Seperator* sep);
|
void command_editmassrespawn(Client* c, const Seperator* sep);
|
||||||
void command_emote(Client *c, const Seperator *sep);
|
void command_emote(Client *c, const Seperator *sep);
|
||||||
void command_emotesearch(Client* c, const Seperator *sep);
|
void command_emotesearch(Client* c, const Seperator *sep);
|
||||||
void command_emoteview(Client* c, const Seperator *sep);
|
void command_emoteview(Client* c, const Seperator *sep);
|
||||||
void command_enablerecipe(Client *c, const Seperator *sep);
|
void command_enablerecipe(Client *c, const Seperator *sep);
|
||||||
|
void command_endurance(Client *c, const Seperator *sep);
|
||||||
void command_equipitem(Client *c, const Seperator *sep);
|
void command_equipitem(Client *c, const Seperator *sep);
|
||||||
void command_face(Client *c, const Seperator *sep);
|
void command_face(Client *c, const Seperator *sep);
|
||||||
void command_faction(Client *c, const Seperator *sep);
|
void command_faction(Client *c, const Seperator *sep);
|
||||||
@ -342,6 +345,7 @@ void command_worldshutdown(Client *c, const Seperator *sep);
|
|||||||
void command_wp(Client *c, const Seperator *sep);
|
void command_wp(Client *c, const Seperator *sep);
|
||||||
void command_wpadd(Client *c, const Seperator *sep);
|
void command_wpadd(Client *c, const Seperator *sep);
|
||||||
void command_wpinfo(Client *c, const Seperator *sep);
|
void command_wpinfo(Client *c, const Seperator *sep);
|
||||||
|
void command_worldwide(Client *c, const Seperator *sep);
|
||||||
void command_xtargets(Client *c, const Seperator *sep);
|
void command_xtargets(Client *c, const Seperator *sep);
|
||||||
void command_zclip(Client *c, const Seperator *sep);
|
void command_zclip(Client *c, const Seperator *sep);
|
||||||
void command_zcolor(Client *c, const Seperator *sep);
|
void command_zcolor(Client *c, const Seperator *sep);
|
||||||
|
|||||||
@ -195,7 +195,11 @@ enum {
|
|||||||
COUNTER_AVOID_DAMAGE = 44,
|
COUNTER_AVOID_DAMAGE = 44,
|
||||||
PROX_AGGRO = 45,
|
PROX_AGGRO = 45,
|
||||||
IMMUNE_RANGED_ATTACKS = 46,
|
IMMUNE_RANGED_ATTACKS = 46,
|
||||||
MAX_SPECIAL_ATTACK = 47
|
IMMUNE_DAMAGE_CLIENT = 47,
|
||||||
|
IMMUNE_DAMAGE_NPC = 48,
|
||||||
|
IMMUNE_AGGRO_CLIENT = 49,
|
||||||
|
IMMUNE_AGGRO_NPC = 50,
|
||||||
|
MAX_SPECIAL_ATTACK = 51
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum { //fear states
|
typedef enum { //fear states
|
||||||
@ -786,5 +790,12 @@ struct DamageHitInfo {
|
|||||||
EQ::skills::SkillType skill;
|
EQ::skills::SkillType skill;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ExpeditionInvite
|
||||||
|
{
|
||||||
|
uint32_t expedition_id;
|
||||||
|
std::string inviter_name;
|
||||||
|
std::string swap_remove_name;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,7 @@ Child of the Mob class.
|
|||||||
|
|
||||||
#include "corpse.h"
|
#include "corpse.h"
|
||||||
#include "entity.h"
|
#include "entity.h"
|
||||||
|
#include "expedition.h"
|
||||||
#include "groups.h"
|
#include "groups.h"
|
||||||
#include "mob.h"
|
#include "mob.h"
|
||||||
#include "raids.h"
|
#include "raids.h"
|
||||||
@ -825,22 +826,7 @@ bool Corpse::Process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (corpse_graveyard_timer.Check()) {
|
if (corpse_graveyard_timer.Check()) {
|
||||||
if (zone->HasGraveyard()) {
|
MovePlayerCorpseToGraveyard();
|
||||||
Save();
|
|
||||||
player_corpse_depop = true;
|
|
||||||
database.SendCharacterCorpseToGraveyard(corpse_db_id, zone->graveyard_zoneid(),
|
|
||||||
(zone->GetZoneID() == zone->graveyard_zoneid()) ? zone->GetInstanceID() : 0, zone->GetGraveyardPoint());
|
|
||||||
corpse_graveyard_timer.Disable();
|
|
||||||
auto pack = new ServerPacket(ServerOP_SpawnPlayerCorpse, sizeof(SpawnPlayerCorpse_Struct));
|
|
||||||
SpawnPlayerCorpse_Struct* spc = (SpawnPlayerCorpse_Struct*)pack->pBuffer;
|
|
||||||
spc->player_corpse_id = corpse_db_id;
|
|
||||||
spc->zone_id = zone->graveyard_zoneid();
|
|
||||||
worldserver.SendPacket(pack);
|
|
||||||
safe_delete(pack);
|
|
||||||
LogDebug("Moved [{}] player corpse to the designated graveyard in zone [{}]", this->GetName(), ZoneName(zone->graveyard_zoneid()));
|
|
||||||
corpse_db_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
corpse_graveyard_timer.Disable();
|
corpse_graveyard_timer.Disable();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1275,6 +1261,20 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (zone && zone->GetInstanceID() != 0)
|
||||||
|
{
|
||||||
|
// expeditions may prevent looting based on client's lockouts
|
||||||
|
auto expedition = Expedition::FindCachedExpeditionByZoneInstance(zone->GetZoneID(), zone->GetInstanceID());
|
||||||
|
if (expedition && !expedition->CanClientLootCorpse(client, GetNPCTypeID(), GetID()))
|
||||||
|
{
|
||||||
|
client->MessageString(Chat::Red, LOOT_NOT_ALLOWED, inst->GetItem()->Name);
|
||||||
|
client->QueuePacket(app);
|
||||||
|
SendEndLootErrorPacket(client);
|
||||||
|
ResetLooter();
|
||||||
|
delete inst;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// do we want this to have a fail option too?
|
// do we want this to have a fail option too?
|
||||||
parse->EventItem(EVENT_LOOT, client, inst, this, buf, 0);
|
parse->EventItem(EVENT_LOOT, client, inst, this, buf, 0);
|
||||||
@ -1628,3 +1628,53 @@ void Corpse::LoadPlayerCorpseDecayTime(uint32 corpse_db_id){
|
|||||||
corpse_graveyard_timer.SetTimer(3000);
|
corpse_graveyard_timer.SetTimer(3000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Corpse::SendWorldSpawnPlayerCorpseInZone(uint32_t zone_id)
|
||||||
|
{
|
||||||
|
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(ServerOP_SpawnPlayerCorpse, sizeof(SpawnPlayerCorpse_Struct)));
|
||||||
|
SpawnPlayerCorpse_Struct* spc = reinterpret_cast<SpawnPlayerCorpse_Struct*>(pack->pBuffer);
|
||||||
|
spc->player_corpse_id = corpse_db_id;
|
||||||
|
spc->zone_id = zone_id;
|
||||||
|
worldserver.SendPacket(pack.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Corpse::MovePlayerCorpseToGraveyard()
|
||||||
|
{
|
||||||
|
if (IsPlayerCorpse() && zone && zone->HasGraveyard())
|
||||||
|
{
|
||||||
|
Save();
|
||||||
|
|
||||||
|
uint16_t instance_id = (zone->GetZoneID() == zone->graveyard_zoneid()) ? zone->GetInstanceID() : 0;
|
||||||
|
database.SendCharacterCorpseToGraveyard(corpse_db_id, zone->graveyard_zoneid(), instance_id, zone->GetGraveyardPoint());
|
||||||
|
SendWorldSpawnPlayerCorpseInZone(zone->graveyard_zoneid());
|
||||||
|
|
||||||
|
corpse_db_id = 0;
|
||||||
|
player_corpse_depop = true;
|
||||||
|
corpse_graveyard_timer.Disable();
|
||||||
|
|
||||||
|
LogDebug("Moved [{}] player corpse to the designated graveyard in zone [{}]", GetName(), ZoneName(zone->graveyard_zoneid()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Corpse::MovePlayerCorpseToNonInstance()
|
||||||
|
{
|
||||||
|
if (IsPlayerCorpse() && zone && zone->GetInstanceID() != 0)
|
||||||
|
{
|
||||||
|
Save();
|
||||||
|
|
||||||
|
database.SendCharacterCorpseToNonInstance(corpse_db_id);
|
||||||
|
SendWorldSpawnPlayerCorpseInZone(zone->GetZoneID());
|
||||||
|
|
||||||
|
corpse_db_id = 0;
|
||||||
|
player_corpse_depop = true;
|
||||||
|
corpse_graveyard_timer.Disable();
|
||||||
|
|
||||||
|
LogDebug("Moved [{}] player corpse to non-instance version of zone [{}]", GetName(), ZoneName(zone->GetZoneID()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@ -79,6 +79,9 @@ class Corpse : public Mob {
|
|||||||
void SetConsentGuildID(uint32 guild_id) { if (IsPlayerCorpse()) { consented_guild_id = guild_id; } }
|
void SetConsentGuildID(uint32 guild_id) { if (IsPlayerCorpse()) { consented_guild_id = guild_id; } }
|
||||||
void AddConsentName(std::string consent_player_name);
|
void AddConsentName(std::string consent_player_name);
|
||||||
void RemoveConsentName(std::string consent_player_name);
|
void RemoveConsentName(std::string consent_player_name);
|
||||||
|
void SendWorldSpawnPlayerCorpseInZone(uint32_t zone_id);
|
||||||
|
bool MovePlayerCorpseToGraveyard();
|
||||||
|
bool MovePlayerCorpseToNonInstance();
|
||||||
|
|
||||||
void Delete();
|
void Delete();
|
||||||
void Bury();
|
void Bury();
|
||||||
|
|||||||
@ -207,6 +207,8 @@ void Doors::HandleClick(Client* sender, uint8 trigger) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: if IsDzDoor() call Client::MovePCDynamicZone(target_zone_id) (for systems that use dzs)
|
||||||
|
|
||||||
uint32 required_key_item = GetKeyItem();
|
uint32 required_key_item = GetKeyItem();
|
||||||
uint8 disable_add_to_key_ring = GetNoKeyring();
|
uint8 disable_add_to_key_ring = GetNoKeyring();
|
||||||
uint32 player_has_key = 0;
|
uint32 player_has_key = 0;
|
||||||
|
|||||||
544
zone/dynamiczone.cpp
Normal file
544
zone/dynamiczone.cpp
Normal file
@ -0,0 +1,544 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dynamiczone.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "worldserver.h"
|
||||||
|
#include "zonedb.h"
|
||||||
|
#include "../common/eqemu_logsys.h"
|
||||||
|
|
||||||
|
extern WorldServer worldserver;
|
||||||
|
|
||||||
|
DynamicZone::DynamicZone(
|
||||||
|
uint32_t zone_id, uint32_t version, uint32_t duration, DynamicZoneType type
|
||||||
|
) :
|
||||||
|
m_zone_id(zone_id),
|
||||||
|
m_version(version),
|
||||||
|
m_duration(duration),
|
||||||
|
m_type(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicZone::DynamicZone(
|
||||||
|
std::string zone_shortname, uint32_t version, uint32_t duration, DynamicZoneType type
|
||||||
|
) :
|
||||||
|
m_version(version),
|
||||||
|
m_duration(duration),
|
||||||
|
m_type(type)
|
||||||
|
{
|
||||||
|
m_zone_id = ZoneID(zone_shortname.c_str());
|
||||||
|
|
||||||
|
if (!m_zone_id)
|
||||||
|
{
|
||||||
|
LogDynamicZones("Failed to get zone id for zone [{}]", zone_shortname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<uint32_t, DynamicZone> DynamicZone::LoadMultipleDzFromDatabase(
|
||||||
|
const std::vector<uint32_t>& dynamic_zone_ids)
|
||||||
|
{
|
||||||
|
LogDynamicZonesDetail("Loading dynamic zone data for [{}] instances", dynamic_zone_ids.size());
|
||||||
|
|
||||||
|
std::string in_dynamic_zone_ids_query = fmt::format("{}", fmt::join(dynamic_zone_ids, ","));
|
||||||
|
|
||||||
|
std::unordered_map<uint32_t, DynamicZone> dynamic_zones;
|
||||||
|
|
||||||
|
if (!in_dynamic_zone_ids_query.empty())
|
||||||
|
{
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
{} WHERE dynamic_zones.id IN ({});
|
||||||
|
), DynamicZoneSelectQuery(), in_dynamic_zone_ids_query);
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (results.Success())
|
||||||
|
{
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row)
|
||||||
|
{
|
||||||
|
DynamicZone dz;
|
||||||
|
dz.LoadDatabaseResult(row);
|
||||||
|
dynamic_zones.emplace(dz.GetID(), dz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dynamic_zones;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DynamicZone::Create()
|
||||||
|
{
|
||||||
|
if (m_id != 0)
|
||||||
|
{
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetInstanceID() == 0)
|
||||||
|
{
|
||||||
|
CreateInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_id = SaveToDatabase();
|
||||||
|
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DynamicZone::CreateInstance()
|
||||||
|
{
|
||||||
|
if (m_instance_id)
|
||||||
|
{
|
||||||
|
LogDynamicZones("CreateInstance failed, instance id [{}] already created", m_instance_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_zone_id)
|
||||||
|
{
|
||||||
|
LogDynamicZones("CreateInstance failed, invalid zone id [{}]", m_zone_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t instance_id = 0;
|
||||||
|
if (!database.GetUnusedInstanceID(instance_id)) // todo: doesn't this race with insert?
|
||||||
|
{
|
||||||
|
LogDynamicZones("Failed to find unused instance id");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_start_time = std::chrono::system_clock::now();
|
||||||
|
auto start_time = std::chrono::system_clock::to_time_t(m_start_time);
|
||||||
|
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
INSERT INTO instance_list
|
||||||
|
(id, zone, version, start_time, duration)
|
||||||
|
VALUES
|
||||||
|
({}, {}, {}, {}, {})
|
||||||
|
), instance_id, m_zone_id, m_version, start_time, m_duration.count());
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (!results.Success())
|
||||||
|
{
|
||||||
|
LogDynamicZones("Failed to create instance [{}] for Dynamic Zone [{}]", instance_id, m_zone_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_instance_id = instance_id;
|
||||||
|
m_never_expires = false;
|
||||||
|
m_expire_time = m_start_time + m_duration;
|
||||||
|
|
||||||
|
return m_instance_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DynamicZone::DynamicZoneSelectQuery()
|
||||||
|
{
|
||||||
|
return std::string(SQL(
|
||||||
|
SELECT
|
||||||
|
instance_list.id,
|
||||||
|
instance_list.zone,
|
||||||
|
instance_list.version,
|
||||||
|
instance_list.start_time,
|
||||||
|
instance_list.duration,
|
||||||
|
instance_list.never_expires,
|
||||||
|
dynamic_zones.id,
|
||||||
|
dynamic_zones.type,
|
||||||
|
dynamic_zones.compass_zone_id,
|
||||||
|
dynamic_zones.compass_x,
|
||||||
|
dynamic_zones.compass_y,
|
||||||
|
dynamic_zones.compass_z,
|
||||||
|
dynamic_zones.safe_return_zone_id,
|
||||||
|
dynamic_zones.safe_return_x,
|
||||||
|
dynamic_zones.safe_return_y,
|
||||||
|
dynamic_zones.safe_return_z,
|
||||||
|
dynamic_zones.safe_return_heading,
|
||||||
|
dynamic_zones.zone_in_x,
|
||||||
|
dynamic_zones.zone_in_y,
|
||||||
|
dynamic_zones.zone_in_z,
|
||||||
|
dynamic_zones.zone_in_heading,
|
||||||
|
dynamic_zones.has_zone_in
|
||||||
|
FROM dynamic_zones
|
||||||
|
INNER JOIN instance_list ON dynamic_zones.instance_id = instance_list.id
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::LoadDatabaseResult(MySQLRequestRow& row)
|
||||||
|
{
|
||||||
|
m_instance_id = strtoul(row[0], nullptr, 10);
|
||||||
|
m_zone_id = strtoul(row[1], nullptr, 10);
|
||||||
|
m_version = strtoul(row[2], nullptr, 10);
|
||||||
|
m_start_time = std::chrono::system_clock::from_time_t(strtoul(row[3], nullptr, 10));
|
||||||
|
m_duration = std::chrono::seconds(strtoul(row[4], nullptr, 10));
|
||||||
|
m_expire_time = m_start_time + m_duration;
|
||||||
|
m_never_expires = (strtoul(row[5], nullptr, 10) != 0);
|
||||||
|
m_id = strtoul(row[6], nullptr, 10);
|
||||||
|
m_type = static_cast<DynamicZoneType>(strtoul(row[7], nullptr, 10));
|
||||||
|
m_compass.zone_id = strtoul(row[8], nullptr, 10);
|
||||||
|
m_compass.x = strtof(row[9], nullptr);
|
||||||
|
m_compass.y = strtof(row[10], nullptr);
|
||||||
|
m_compass.z = strtof(row[11], nullptr);
|
||||||
|
m_safereturn.zone_id = strtoul(row[12], nullptr, 10);
|
||||||
|
m_safereturn.x = strtof(row[13], nullptr);
|
||||||
|
m_safereturn.y = strtof(row[14], nullptr);
|
||||||
|
m_safereturn.z = strtof(row[15], nullptr);
|
||||||
|
m_safereturn.heading = strtof(row[16], nullptr);
|
||||||
|
m_zonein.x = strtof(row[17], nullptr);
|
||||||
|
m_zonein.y = strtof(row[18], nullptr);
|
||||||
|
m_zonein.z = strtof(row[19], nullptr);
|
||||||
|
m_zonein.heading = strtof(row[20], nullptr);
|
||||||
|
m_has_zonein = (strtoul(row[21], nullptr, 10) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DynamicZone::SaveToDatabase()
|
||||||
|
{
|
||||||
|
LogDynamicZonesDetail("Saving dz instance [{}] to database", m_instance_id);
|
||||||
|
|
||||||
|
if (m_instance_id != 0)
|
||||||
|
{
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
INSERT INTO dynamic_zones
|
||||||
|
(
|
||||||
|
instance_id,
|
||||||
|
type,
|
||||||
|
compass_zone_id,
|
||||||
|
compass_x,
|
||||||
|
compass_y,
|
||||||
|
compass_z,
|
||||||
|
safe_return_zone_id,
|
||||||
|
safe_return_x,
|
||||||
|
safe_return_y,
|
||||||
|
safe_return_z,
|
||||||
|
safe_return_heading,
|
||||||
|
zone_in_x,
|
||||||
|
zone_in_y,
|
||||||
|
zone_in_z,
|
||||||
|
zone_in_heading,
|
||||||
|
has_zone_in
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {});
|
||||||
|
),
|
||||||
|
m_instance_id,
|
||||||
|
static_cast<uint8_t>(m_type),
|
||||||
|
m_compass.zone_id,
|
||||||
|
m_compass.x,
|
||||||
|
m_compass.y,
|
||||||
|
m_compass.z,
|
||||||
|
m_safereturn.zone_id,
|
||||||
|
m_safereturn.x,
|
||||||
|
m_safereturn.y,
|
||||||
|
m_safereturn.z,
|
||||||
|
m_safereturn.heading,
|
||||||
|
m_zonein.x,
|
||||||
|
m_zonein.y,
|
||||||
|
m_zonein.z,
|
||||||
|
m_zonein.heading,
|
||||||
|
m_has_zonein
|
||||||
|
);
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (results.Success())
|
||||||
|
{
|
||||||
|
return results.LastInsertedID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::SaveCompassToDatabase()
|
||||||
|
{
|
||||||
|
LogDynamicZonesDetail(
|
||||||
|
"Instance [{}] saving compass zone: [{}] xyz: ([{}], [{}], [{}])",
|
||||||
|
m_instance_id, m_compass.zone_id, m_compass.x, m_compass.y, m_compass.z
|
||||||
|
);
|
||||||
|
|
||||||
|
if (m_instance_id != 0)
|
||||||
|
{
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
UPDATE dynamic_zones SET
|
||||||
|
compass_zone_id = {},
|
||||||
|
compass_x = {},
|
||||||
|
compass_y = {},
|
||||||
|
compass_z = {}
|
||||||
|
WHERE instance_id = {};
|
||||||
|
),
|
||||||
|
m_compass.zone_id,
|
||||||
|
m_compass.x,
|
||||||
|
m_compass.y,
|
||||||
|
m_compass.z,
|
||||||
|
m_instance_id
|
||||||
|
);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::SaveSafeReturnToDatabase()
|
||||||
|
{
|
||||||
|
LogDynamicZonesDetail(
|
||||||
|
"Instance [{}] saving safereturn zone: [{}] xyzh: ([{}], [{}], [{}], [{}])",
|
||||||
|
m_instance_id, m_safereturn.zone_id, m_safereturn.x, m_safereturn.y, m_safereturn.z, m_safereturn.heading
|
||||||
|
);
|
||||||
|
|
||||||
|
if (m_instance_id != 0)
|
||||||
|
{
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
UPDATE dynamic_zones SET
|
||||||
|
safe_return_zone_id = {},
|
||||||
|
safe_return_x = {},
|
||||||
|
safe_return_y = {},
|
||||||
|
safe_return_z = {},
|
||||||
|
safe_return_heading = {}
|
||||||
|
WHERE instance_id = {};
|
||||||
|
),
|
||||||
|
m_safereturn.zone_id,
|
||||||
|
m_safereturn.x,
|
||||||
|
m_safereturn.y,
|
||||||
|
m_safereturn.z,
|
||||||
|
m_safereturn.heading,
|
||||||
|
m_instance_id
|
||||||
|
);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::SaveZoneInLocationToDatabase()
|
||||||
|
{
|
||||||
|
LogDynamicZonesDetail(
|
||||||
|
"Instance [{}] saving zonein zone: [{}] xyzh: ([{}], [{}], [{}], [{}]) has: [{}]",
|
||||||
|
m_instance_id, m_zone_id, m_zonein.x, m_zonein.y, m_zonein.z, m_zonein.heading, m_has_zonein
|
||||||
|
);
|
||||||
|
|
||||||
|
if (m_instance_id != 0)
|
||||||
|
{
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
UPDATE dynamic_zones SET
|
||||||
|
zone_in_x = {},
|
||||||
|
zone_in_y = {},
|
||||||
|
zone_in_z = {},
|
||||||
|
zone_in_heading = {},
|
||||||
|
has_zone_in = {}
|
||||||
|
WHERE instance_id = {};
|
||||||
|
),
|
||||||
|
m_zonein.x,
|
||||||
|
m_zonein.y,
|
||||||
|
m_zonein.z,
|
||||||
|
m_zonein.heading,
|
||||||
|
m_has_zonein,
|
||||||
|
m_instance_id
|
||||||
|
);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::AddCharacter(uint32_t character_id)
|
||||||
|
{
|
||||||
|
database.AddClientToInstance(m_instance_id, character_id);
|
||||||
|
SendInstanceCharacterChange(character_id, false); // stops client kick timer
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::RemoveCharacter(uint32_t character_id)
|
||||||
|
{
|
||||||
|
database.RemoveClientFromInstance(m_instance_id, character_id);
|
||||||
|
SendInstanceCharacterChange(character_id, true); // start client kick timer
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::RemoveAllCharacters(bool enable_removal_timers)
|
||||||
|
{
|
||||||
|
if (GetInstanceID() == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enable_removal_timers)
|
||||||
|
{
|
||||||
|
// just remove all clients in bulk instead of only characters assigned to the instance
|
||||||
|
if (IsCurrentZoneDzInstance())
|
||||||
|
{
|
||||||
|
for (const auto& client_iter : entity_list.GetClientList())
|
||||||
|
{
|
||||||
|
if (client_iter.second)
|
||||||
|
{
|
||||||
|
client_iter.second->SetDzRemovalTimer(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (GetInstanceID() != 0)
|
||||||
|
{
|
||||||
|
uint32_t packsize = sizeof(ServerDzCharacter_Struct);
|
||||||
|
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(ServerOP_DzRemoveAllCharacters, packsize));
|
||||||
|
auto packbuf = reinterpret_cast<ServerDzCharacter_Struct*>(pack->pBuffer);
|
||||||
|
packbuf->zone_id = GetZoneID();
|
||||||
|
packbuf->instance_id = GetInstanceID();
|
||||||
|
packbuf->remove = true;
|
||||||
|
packbuf->character_id = 0;
|
||||||
|
worldserver.SendPacket(pack.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
database.RemoveClientsFromInstance(GetInstanceID());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::SaveInstanceMembersToDatabase(const std::vector<uint32_t>& character_ids)
|
||||||
|
{
|
||||||
|
LogDynamicZonesDetail("Saving [{}] instance members to database", character_ids.size());
|
||||||
|
|
||||||
|
std::string insert_values;
|
||||||
|
for (const auto& character_id : character_ids)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(insert_values), "({}, {}),", m_instance_id, character_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!insert_values.empty())
|
||||||
|
{
|
||||||
|
insert_values.pop_back(); // trailing comma
|
||||||
|
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
REPLACE INTO instance_list_player (id, charid) VALUES {};
|
||||||
|
), insert_values);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::SendInstanceCharacterChange(uint32_t character_id, bool removed)
|
||||||
|
{
|
||||||
|
// if removing, sets removal timer on client inside the instance
|
||||||
|
if (IsCurrentZoneDzInstance())
|
||||||
|
{
|
||||||
|
Client* client = entity_list.GetClientByCharID(character_id);
|
||||||
|
if (client)
|
||||||
|
{
|
||||||
|
client->SetDzRemovalTimer(removed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (GetInstanceID() != 0)
|
||||||
|
{
|
||||||
|
uint32_t packsize = sizeof(ServerDzCharacter_Struct);
|
||||||
|
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(ServerOP_DzCharacterChange, packsize));
|
||||||
|
auto packbuf = reinterpret_cast<ServerDzCharacter_Struct*>(pack->pBuffer);
|
||||||
|
packbuf->zone_id = GetZoneID();
|
||||||
|
packbuf->instance_id = GetInstanceID();
|
||||||
|
packbuf->remove = removed;
|
||||||
|
packbuf->character_id = character_id;
|
||||||
|
worldserver.SendPacket(pack.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::SetCompass(const DynamicZoneLocation& location, bool update_db)
|
||||||
|
{
|
||||||
|
m_compass = location;
|
||||||
|
|
||||||
|
if (update_db)
|
||||||
|
{
|
||||||
|
SaveCompassToDatabase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::SetSafeReturn(const DynamicZoneLocation& location, bool update_db)
|
||||||
|
{
|
||||||
|
m_safereturn = location;
|
||||||
|
|
||||||
|
if (update_db)
|
||||||
|
{
|
||||||
|
SaveSafeReturnToDatabase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::SetZoneInLocation(const DynamicZoneLocation& location, bool update_db)
|
||||||
|
{
|
||||||
|
m_zonein = location;
|
||||||
|
m_has_zonein = true;
|
||||||
|
|
||||||
|
if (update_db)
|
||||||
|
{
|
||||||
|
SaveZoneInLocationToDatabase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DynamicZone::IsCurrentZoneDzInstance() const
|
||||||
|
{
|
||||||
|
return (zone && zone->GetInstanceID() != 0 && zone->GetInstanceID() == GetInstanceID());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DynamicZone::IsInstanceID(uint32_t instance_id) const
|
||||||
|
{
|
||||||
|
return (GetInstanceID() != 0 && GetInstanceID() == instance_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DynamicZone::IsSameDz(uint32_t zone_id, uint32_t instance_id) const
|
||||||
|
{
|
||||||
|
return zone_id == m_zone_id && instance_id == m_instance_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DynamicZone::GetSecondsRemaining() const
|
||||||
|
{
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
if (m_expire_time > now)
|
||||||
|
{
|
||||||
|
auto remaining = m_expire_time - now;
|
||||||
|
return static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(remaining).count());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::SetUpdatedDuration(uint32_t new_duration)
|
||||||
|
{
|
||||||
|
// preserves original start time, just modifies duration and expire time
|
||||||
|
m_duration = std::chrono::seconds(new_duration);
|
||||||
|
m_expire_time = m_start_time + m_duration;
|
||||||
|
|
||||||
|
LogDynamicZones("Updated zone [{}]:[{}] seconds remaining: [{}]",
|
||||||
|
m_zone_id, m_instance_id, GetSecondsRemaining());
|
||||||
|
|
||||||
|
if (zone && IsCurrentZoneDzInstance())
|
||||||
|
{
|
||||||
|
zone->SetInstanceTimer(GetSecondsRemaining());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicZone::HandleWorldMessage(ServerPacket* pack)
|
||||||
|
{
|
||||||
|
switch (pack->opcode)
|
||||||
|
{
|
||||||
|
case ServerOP_DzCharacterChange:
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerDzCharacter_Struct*>(pack->pBuffer);
|
||||||
|
Client* client = entity_list.GetClientByCharID(buf->character_id);
|
||||||
|
if (client)
|
||||||
|
{
|
||||||
|
client->SetDzRemovalTimer(buf->remove); // instance kick timer
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ServerOP_DzRemoveAllCharacters:
|
||||||
|
{
|
||||||
|
auto buf = reinterpret_cast<ServerDzCharacter_Struct*>(pack->pBuffer);
|
||||||
|
if (buf->remove)
|
||||||
|
{
|
||||||
|
for (const auto& client_list_iter : entity_list.GetClientList())
|
||||||
|
{
|
||||||
|
if (client_list_iter.second)
|
||||||
|
{
|
||||||
|
client_list_iter.second->SetDzRemovalTimer(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
132
zone/dynamiczone.h
Normal file
132
zone/dynamiczone.h
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DYNAMICZONE_H
|
||||||
|
#define DYNAMICZONE_H
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class MySQLRequestRow;
|
||||||
|
class ServerPacket;
|
||||||
|
|
||||||
|
enum class DynamicZoneType : uint8_t
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Expedition,
|
||||||
|
Tutorial,
|
||||||
|
Task,
|
||||||
|
Mission, // Shared Task
|
||||||
|
Quest
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneLocation
|
||||||
|
{
|
||||||
|
uint32_t zone_id = 0;
|
||||||
|
float x = 0.0f;
|
||||||
|
float y = 0.0f;
|
||||||
|
float z = 0.0f;
|
||||||
|
float heading = 0.0f;
|
||||||
|
|
||||||
|
DynamicZoneLocation() = default;
|
||||||
|
DynamicZoneLocation(uint32_t zone_id_, float x_, float y_, float z_, float heading_)
|
||||||
|
: zone_id(zone_id_), x(x_), y(y_), z(z_), heading(heading_) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DynamicZone
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DynamicZone() = default;
|
||||||
|
DynamicZone(uint32_t zone_id, uint32_t version, uint32_t duration, DynamicZoneType type);
|
||||||
|
DynamicZone(std::string zone_shortname, uint32_t version, uint32_t duration, DynamicZoneType type);
|
||||||
|
DynamicZone(uint32_t dz_id) : m_id(dz_id) {}
|
||||||
|
DynamicZone(DynamicZoneType type) : m_type(type) {}
|
||||||
|
|
||||||
|
static std::unordered_map<uint32_t, DynamicZone> LoadMultipleDzFromDatabase(
|
||||||
|
const std::vector<uint32_t>& dynamic_zone_ids);
|
||||||
|
static void HandleWorldMessage(ServerPacket* pack);
|
||||||
|
|
||||||
|
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
|
||||||
|
uint32_t GetID() const { return m_id; }
|
||||||
|
uint16_t GetInstanceID() const { return static_cast<uint16_t>(m_instance_id); }
|
||||||
|
uint32_t GetSecondsRemaining() const;
|
||||||
|
uint16_t GetZoneID() const { return static_cast<uint16_t>(m_zone_id); }
|
||||||
|
uint32_t GetZoneIndex() const { return (m_instance_id << 16) | (m_zone_id & 0xffff); }
|
||||||
|
uint32_t GetZoneVersion() const { return m_version; }
|
||||||
|
DynamicZoneType GetType() const { return m_type; }
|
||||||
|
DynamicZoneLocation GetCompassLocation() const { return m_compass; }
|
||||||
|
DynamicZoneLocation GetSafeReturnLocation() const { return m_safereturn; }
|
||||||
|
DynamicZoneLocation GetZoneInLocation() const { return m_zonein; }
|
||||||
|
|
||||||
|
void AddCharacter(uint32_t character_id);
|
||||||
|
uint32_t Create();
|
||||||
|
uint32_t CreateInstance();
|
||||||
|
bool HasZoneInLocation() const { return m_has_zonein; }
|
||||||
|
bool IsCurrentZoneDzInstance() const;
|
||||||
|
bool IsInstanceID(uint32_t instance_id) const;
|
||||||
|
bool IsValid() const { return m_instance_id != 0; }
|
||||||
|
bool IsSameDz(uint32_t zone_id, uint32_t instance_id) const;
|
||||||
|
void RemoveAllCharacters(bool enable_removal_timers = true);
|
||||||
|
void RemoveCharacter(uint32_t character_id);
|
||||||
|
void SaveInstanceMembersToDatabase(const std::vector<uint32_t>& character_ids);
|
||||||
|
void SendInstanceCharacterChange(uint32_t character_id, bool removed);
|
||||||
|
void SetCompass(const DynamicZoneLocation& location, bool update_db = false);
|
||||||
|
void SetSafeReturn(const DynamicZoneLocation& location, bool update_db = false);
|
||||||
|
void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false);
|
||||||
|
void SetUpdatedDuration(uint32_t seconds);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::string DynamicZoneSelectQuery();
|
||||||
|
void LoadDatabaseResult(MySQLRequestRow& row);
|
||||||
|
void SaveCompassToDatabase();
|
||||||
|
void SaveSafeReturnToDatabase();
|
||||||
|
void SaveZoneInLocationToDatabase();
|
||||||
|
uint32_t SaveToDatabase();
|
||||||
|
|
||||||
|
uint32_t m_id = 0;
|
||||||
|
uint32_t m_zone_id = 0;
|
||||||
|
uint32_t m_instance_id = 0;
|
||||||
|
uint32_t m_version = 0;
|
||||||
|
bool m_never_expires = false;
|
||||||
|
bool m_has_zonein = false;
|
||||||
|
DynamicZoneType m_type = DynamicZoneType::None;
|
||||||
|
DynamicZoneLocation m_compass;
|
||||||
|
DynamicZoneLocation m_safereturn;
|
||||||
|
DynamicZoneLocation m_zonein;
|
||||||
|
std::chrono::seconds m_duration;
|
||||||
|
std::chrono::time_point<std::chrono::system_clock> m_start_time;
|
||||||
|
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DynamicZoneInfo
|
||||||
|
{
|
||||||
|
std::string description; // from owning system
|
||||||
|
std::string leader_name;
|
||||||
|
DynamicZone dynamic_zone;
|
||||||
|
|
||||||
|
DynamicZoneInfo() = default;
|
||||||
|
DynamicZoneInfo(std::string desc, std::string leader, const DynamicZone& dz)
|
||||||
|
: description(std::move(desc)), leader_name(std::move(leader)), dynamic_zone(dz) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -678,6 +678,17 @@ void Client::ResetDisciplineTimer(uint32 timer_id) {
|
|||||||
SendDisciplineTimer(timer_id, 0);
|
SendDisciplineTimer(timer_id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Client::HasDisciplineLearned(uint16 spell_id) {
|
||||||
|
bool has_learned = false;
|
||||||
|
for (auto index = 0; index < MAX_PP_DISCIPLINES; ++index) {
|
||||||
|
if (GetPP().disciplines.values[index] == spell_id) {
|
||||||
|
has_learned = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return has_learned;
|
||||||
|
}
|
||||||
|
|
||||||
void Client::SendDisciplineTimer(uint32 timer_id, uint32 duration)
|
void Client::SendDisciplineTimer(uint32 timer_id, uint32 duration)
|
||||||
{
|
{
|
||||||
if (timer_id < MAX_DISCIPLINE_TIMERS)
|
if (timer_id < MAX_DISCIPLINE_TIMERS)
|
||||||
|
|||||||
@ -971,6 +971,9 @@ void PerlembParser::MapFunctions()
|
|||||||
"package Doors;"
|
"package Doors;"
|
||||||
"&boot_Doors;" // load quest Doors XS
|
"&boot_Doors;" // load quest Doors XS
|
||||||
|
|
||||||
|
"package Expedition;"
|
||||||
|
"&boot_Expedition;"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
"package main;"
|
"package main;"
|
||||||
"}"
|
"}"
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
#include "embparser.h"
|
#include "embparser.h"
|
||||||
#include "embxs.h"
|
#include "embxs.h"
|
||||||
#include "entity.h"
|
#include "entity.h"
|
||||||
|
#include "expedition.h"
|
||||||
#include "queryserv.h"
|
#include "queryserv.h"
|
||||||
#include "questmgr.h"
|
#include "questmgr.h"
|
||||||
#include "zone.h"
|
#include "zone.h"
|
||||||
@ -2792,6 +2793,29 @@ XS(XS__we) {
|
|||||||
XSRETURN_EMPTY;
|
XSRETURN_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XS(XS__message);
|
||||||
|
XS(XS__message) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 2)
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::message(int color, string message)");
|
||||||
|
|
||||||
|
int color = (int) SvIV(ST(0));
|
||||||
|
char *message = (char *) SvPV_nolen(ST(1));
|
||||||
|
quest_manager.message(color, message);
|
||||||
|
XSRETURN_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
XS(XS__whisper);
|
||||||
|
XS(XS__whisper) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 1)
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::whisper(string message)");
|
||||||
|
|
||||||
|
char *message = (char *) SvPV_nolen(ST(0));
|
||||||
|
quest_manager.whisper(message);
|
||||||
|
XSRETURN_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
XS(XS__getlevel);
|
XS(XS__getlevel);
|
||||||
XS(XS__getlevel) {
|
XS(XS__getlevel) {
|
||||||
dXSARGS;
|
dXSARGS;
|
||||||
@ -2926,6 +2950,22 @@ XS(XS__countitem) {
|
|||||||
XSRETURN_IV(quantity);
|
XSRETURN_IV(quantity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XS(XS__removeitem);
|
||||||
|
XS(XS__removeitem) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items < 1 || items > 2)
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::removeitem(int item_id, [int quantity = 1])");
|
||||||
|
|
||||||
|
uint32 item_id = (int) SvIV(ST(0));
|
||||||
|
uint32 quantity = 1;
|
||||||
|
if (items > 1)
|
||||||
|
quantity = (int) SvIV(ST(1));
|
||||||
|
|
||||||
|
quest_manager.removeitem(item_id, quantity);
|
||||||
|
|
||||||
|
XSRETURN_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
XS(XS__getitemname);
|
XS(XS__getitemname);
|
||||||
XS(XS__getitemname) {
|
XS(XS__getitemname) {
|
||||||
dXSARGS;
|
dXSARGS;
|
||||||
@ -3733,10 +3773,11 @@ XS(XS__GetZoneLongName) {
|
|||||||
if (items != 1)
|
if (items != 1)
|
||||||
Perl_croak(aTHX_ "Usage: quest::GetZoneLongName(string zone)");
|
Perl_croak(aTHX_ "Usage: quest::GetZoneLongName(string zone)");
|
||||||
dXSTARG;
|
dXSTARG;
|
||||||
char *zone = (char *) SvPV_nolen(ST(0));
|
|
||||||
Const_char *RETVAL = quest_manager.GetZoneLongName(zone);
|
|
||||||
|
|
||||||
sv_setpv(TARG, RETVAL);
|
std::string zone = (std::string) SvPV_nolen(ST(0));
|
||||||
|
std::string RETVAL = quest_manager.GetZoneLongName(zone);
|
||||||
|
|
||||||
|
sv_setpv(TARG, RETVAL.c_str());
|
||||||
XSprePUSH;
|
XSprePUSH;
|
||||||
PUSHTARG;
|
PUSHTARG;
|
||||||
XSRETURN(1);
|
XSRETURN(1);
|
||||||
@ -6042,6 +6083,265 @@ XS(XS__SetContentFlag)
|
|||||||
XSRETURN_EMPTY;
|
XSRETURN_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XS(XS__get_expedition);
|
||||||
|
XS(XS__get_expedition) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 0) {
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::get_expedition()");
|
||||||
|
}
|
||||||
|
|
||||||
|
Expedition* RETVAL = nullptr;
|
||||||
|
if (zone && zone->GetInstanceID() != 0)
|
||||||
|
{
|
||||||
|
RETVAL = Expedition::FindCachedExpeditionByZoneInstance(zone->GetZoneID(), zone->GetInstanceID());
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTEND(sp, 1); // grow stack, function had 0 arguments
|
||||||
|
ST(0) = sv_newmortal(); // PUSHs(sv_newmortal());
|
||||||
|
if (RETVAL) {
|
||||||
|
sv_setref_pv(ST(0), "Expedition", (void*)RETVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
XSRETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
XS(XS__get_expedition_by_char_id);
|
||||||
|
XS(XS__get_expedition_by_char_id) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 1) {
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::get_expedition_by_char_id(uint32 character_id)");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 character_id = (int)SvUV(ST(0));
|
||||||
|
|
||||||
|
Expedition* RETVAL = Expedition::FindCachedExpeditionByCharacterID(character_id);
|
||||||
|
|
||||||
|
ST(0) = sv_newmortal();
|
||||||
|
if (RETVAL) {
|
||||||
|
sv_setref_pv(ST(0), "Expedition", (void*)RETVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
XSRETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
XS(XS__get_expedition_by_dz_id);
|
||||||
|
XS(XS__get_expedition_by_dz_id) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 1) {
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::get_expedition_by_dz_id(uint32 dynamic_zone_id)");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 dz_id = (int)SvUV(ST(0));
|
||||||
|
|
||||||
|
Expedition* RETVAL = Expedition::FindCachedExpeditionByDynamicZoneID(dz_id);
|
||||||
|
|
||||||
|
ST(0) = sv_newmortal();
|
||||||
|
if (RETVAL) {
|
||||||
|
sv_setref_pv(ST(0), "Expedition", (void*)RETVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
XSRETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
XS(XS__get_expedition_by_zone_instance);
|
||||||
|
XS(XS__get_expedition_by_zone_instance) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 2) {
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::GetExpeditionByZoneInstance(uint16 zone_id, uint16 instance_id)");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 zone_id = (uint16)SvUV(ST(0));
|
||||||
|
uint16 instance_id = (uint16)SvUV(ST(1));
|
||||||
|
|
||||||
|
Expedition* RETVAL = Expedition::FindCachedExpeditionByZoneInstance(zone_id, instance_id);
|
||||||
|
|
||||||
|
ST(0) = sv_newmortal();
|
||||||
|
if (RETVAL) {
|
||||||
|
sv_setref_pv(ST(0), "Expedition", (void*)RETVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
XSRETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
XS(XS__get_expedition_lockout_by_char_id);
|
||||||
|
XS(XS__get_expedition_lockout_by_char_id) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 3) {
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::get_expedition_lockout_by_char_id(uint32 character_id, string expedition_name, string event_name)");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t character_id = static_cast<uint32_t>(SvUV(ST(0)));
|
||||||
|
std::string expedition_name = SvPV_nolen(ST(1));
|
||||||
|
std::string event_name = SvPV_nolen(ST(2));
|
||||||
|
|
||||||
|
auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(character_id);
|
||||||
|
auto it = std::find_if(lockouts.begin(), lockouts.end(), [&](const ExpeditionLockoutTimer& lockout) {
|
||||||
|
return lockout.IsSameLockout(expedition_name, event_name);
|
||||||
|
});
|
||||||
|
|
||||||
|
// mortalize so its refcnt is auto decremented on function exit to avoid leak
|
||||||
|
HV* hash = (HV*)sv_2mortal((SV*)newHV()); // hash refcnt +1 (mortal -1)
|
||||||
|
|
||||||
|
if (it != lockouts.end())
|
||||||
|
{
|
||||||
|
hv_store(hash, "remaining", strlen("remaining"), newSVuv(it->GetSecondsRemaining()), 0);
|
||||||
|
hv_store(hash, "uuid", strlen("uuid"), newSVpv(it->GetExpeditionUUID().c_str(), 0), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ST(0) = sv_2mortal(newRV((SV*)hash)); // hash refcnt: 2 (-1 mortal), reference: 1 (-1 mortal)
|
||||||
|
XSRETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
XS(XS__get_expedition_lockouts_by_char_id);
|
||||||
|
XS(XS__get_expedition_lockouts_by_char_id) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 1 && items != 2) {
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::get_expedition_lockouts_by_char_id(uint32 character_id, [string expedition_name])");
|
||||||
|
}
|
||||||
|
|
||||||
|
HV* hash = newHV(); // hash refcnt +1 (non-mortal, newRV_noinc to not inc)
|
||||||
|
SV* hash_ref = nullptr; // for expedition event hash if filtering on expedition
|
||||||
|
|
||||||
|
uint32_t character_id = static_cast<uint32_t>(SvUV(ST(0)));
|
||||||
|
std::string expedition_name;
|
||||||
|
if (items == 2)
|
||||||
|
{
|
||||||
|
expedition_name = SvPV_nolen(ST(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(character_id);
|
||||||
|
|
||||||
|
for (const auto& lockout : lockouts)
|
||||||
|
{
|
||||||
|
uint32_t name_len = static_cast<uint32_t>(lockout.GetExpeditionName().size());
|
||||||
|
uint32_t event_len = static_cast<uint32_t>(lockout.GetEventName().size());
|
||||||
|
|
||||||
|
// hashes are stored through references inside other hashes/arrays. we need
|
||||||
|
// to wrap newHV in newRV references when inserting nested hash values.
|
||||||
|
// we use newRV_noinc to not increment the hash's ref count; rv will own it
|
||||||
|
|
||||||
|
SV** entry = hv_fetch(hash, lockout.GetExpeditionName().c_str(), name_len, false);
|
||||||
|
if (!entry)
|
||||||
|
{
|
||||||
|
// create expedition entry in hash with its value as ref to event hash
|
||||||
|
SV* event_hash_ref = newRV_noinc((SV*)newHV()); // ref takes ownership
|
||||||
|
if (!expedition_name.empty() && lockout.GetExpeditionName() == expedition_name)
|
||||||
|
{
|
||||||
|
hash_ref = event_hash_ref; // save ref for filtered expedition return
|
||||||
|
}
|
||||||
|
entry = hv_store(hash, lockout.GetExpeditionName().c_str(), name_len, event_hash_ref, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// *entry is a reference to expedition's event hash (which it owns). the
|
||||||
|
// event entry in the hash will contain ref to a lockout detail hash
|
||||||
|
if (entry && SvROK(*entry) && SvTYPE(SvRV(*entry)) == SVt_PVHV) // is ref to hash type
|
||||||
|
{
|
||||||
|
HV* details_hash = newHV(); // refcnt +1, reference will take ownership
|
||||||
|
hv_store(details_hash, "remaining", strlen("remaining"), newSVuv(lockout.GetSecondsRemaining()), 0);
|
||||||
|
hv_store(details_hash, "uuid", strlen("uuid"), newSVpv(lockout.GetExpeditionUUID().c_str(), 0), 0);
|
||||||
|
|
||||||
|
HV* event_hash = (HV*)SvRV(*entry);
|
||||||
|
hv_store(event_hash, lockout.GetEventName().c_str(), event_len,
|
||||||
|
(SV*)newRV_noinc((SV*)details_hash), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SV* rv = &PL_sv_undef;
|
||||||
|
|
||||||
|
if (!expedition_name.empty())
|
||||||
|
{
|
||||||
|
rv = hash_ref ? sv_2mortal(hash_ref) : &PL_sv_undef; // ref that owns event hash for expedition
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = sv_2mortal(newRV_noinc((SV*)hash)); // takes ownership of expedition hash
|
||||||
|
}
|
||||||
|
|
||||||
|
ST(0) = rv;
|
||||||
|
XSRETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
XS(XS__add_expedition_lockout_all_clients);
|
||||||
|
XS(XS__add_expedition_lockout_all_clients) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 3 && items != 4) {
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::add_expedition_lockout_all_clients(string expedition_name, string event_name, uint32 seconds, [string uuid])");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string expedition_name = SvPV_nolen(ST(0));
|
||||||
|
std::string event_name = SvPV_nolen(ST(1));
|
||||||
|
uint32_t seconds = static_cast<uint32_t>(SvUV(ST(2)));
|
||||||
|
std::string uuid;
|
||||||
|
|
||||||
|
if (items == 4)
|
||||||
|
{
|
||||||
|
uuid = SvPV_nolen(ST(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds, uuid);
|
||||||
|
Expedition::AddLockoutClients(lockout);
|
||||||
|
|
||||||
|
XSRETURN_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
XS(XS__add_expedition_lockout_by_char_id);
|
||||||
|
XS(XS__add_expedition_lockout_by_char_id) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 4 && items != 5) {
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::add_expedition_lockout_by_char_id(uint32 character_id, string expedition_name, string event_name, uint32 seconds, [string uuid])");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string uuid;
|
||||||
|
if (items == 5)
|
||||||
|
{
|
||||||
|
uuid = SvPV_nolen(ST(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t character_id = static_cast<uint32_t>(SvUV(ST(0)));
|
||||||
|
std::string expedition_name = SvPV_nolen(ST(1));
|
||||||
|
std::string event_name = SvPV_nolen(ST(2));
|
||||||
|
uint32_t seconds = static_cast<uint32_t>(SvUV(ST(3)));
|
||||||
|
|
||||||
|
Expedition::AddLockoutByCharacterID(character_id, expedition_name, event_name, seconds, uuid);
|
||||||
|
|
||||||
|
XSRETURN_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
XS(XS__remove_expedition_lockout_by_char_id);
|
||||||
|
XS(XS__remove_expedition_lockout_by_char_id) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 3) {
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::remove_expedition_lockout_by_char_id(uint32 character_id, string expedition_name, string event_name)");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t character_id = static_cast<uint32_t>(SvUV(ST(0)));
|
||||||
|
std::string expedition_name = SvPV_nolen(ST(1));
|
||||||
|
std::string event_name = SvPV_nolen(ST(2));
|
||||||
|
|
||||||
|
Expedition::RemoveLockoutsByCharacterID(character_id, expedition_name, event_name);
|
||||||
|
|
||||||
|
XSRETURN_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
XS(XS__remove_all_expedition_lockouts_by_char_id);
|
||||||
|
XS(XS__remove_all_expedition_lockouts_by_char_id) {
|
||||||
|
dXSARGS;
|
||||||
|
if (items != 1 && items != 2) {
|
||||||
|
Perl_croak(aTHX_ "Usage: quest::remove_expedition_lockout_by_char_id(uint32 character_id, [string expedition_name])");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string expedition_name;
|
||||||
|
if (items == 2)
|
||||||
|
{
|
||||||
|
expedition_name = SvPV_nolen(ST(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t character_id = static_cast<uint32_t>(SvUV(ST(0)));
|
||||||
|
Expedition::RemoveLockoutsByCharacterID(character_id, expedition_name);
|
||||||
|
|
||||||
|
XSRETURN_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is the callback perl will look for to setup the
|
This is the callback perl will look for to setup the
|
||||||
quest package's XSUBs
|
quest package's XSUBs
|
||||||
@ -6112,6 +6412,8 @@ EXTERN_C XS(boot_quest) {
|
|||||||
newXS(strcpy(buf, "activespeakactivity"), XS__activespeakactivity, file);
|
newXS(strcpy(buf, "activespeakactivity"), XS__activespeakactivity, file);
|
||||||
newXS(strcpy(buf, "activespeaktask"), XS__activespeaktask, file);
|
newXS(strcpy(buf, "activespeaktask"), XS__activespeaktask, file);
|
||||||
newXS(strcpy(buf, "activetasksinset"), XS__activetasksinset, file);
|
newXS(strcpy(buf, "activetasksinset"), XS__activetasksinset, file);
|
||||||
|
newXS(strcpy(buf, "add_expedition_lockout_all_clients"), XS__add_expedition_lockout_all_clients, file);
|
||||||
|
newXS(strcpy(buf, "add_expedition_lockout_by_char_id"), XS__add_expedition_lockout_by_char_id, file);
|
||||||
newXS(strcpy(buf, "addldonloss"), XS__addldonpoints, file);
|
newXS(strcpy(buf, "addldonloss"), XS__addldonpoints, file);
|
||||||
newXS(strcpy(buf, "addldonpoints"), XS__addldonpoints, file);
|
newXS(strcpy(buf, "addldonpoints"), XS__addldonpoints, file);
|
||||||
newXS(strcpy(buf, "addldonwin"), XS__addldonpoints, file);
|
newXS(strcpy(buf, "addldonwin"), XS__addldonpoints, file);
|
||||||
@ -6246,6 +6548,12 @@ EXTERN_C XS(boot_quest) {
|
|||||||
newXS(strcpy(buf, "getcharidbyname"), XS__getcharidbyname, file);
|
newXS(strcpy(buf, "getcharidbyname"), XS__getcharidbyname, file);
|
||||||
newXS(strcpy(buf, "getclassname"), XS__getclassname, file);
|
newXS(strcpy(buf, "getclassname"), XS__getclassname, file);
|
||||||
newXS(strcpy(buf, "getcurrencyid"), XS__getcurrencyid, file);
|
newXS(strcpy(buf, "getcurrencyid"), XS__getcurrencyid, file);
|
||||||
|
newXS(strcpy(buf, "get_expedition"), XS__get_expedition, file);
|
||||||
|
newXS(strcpy(buf, "get_expedition_by_char_id"), XS__get_expedition_by_char_id, file);
|
||||||
|
newXS(strcpy(buf, "get_expedition_by_dz_id"), XS__get_expedition_by_dz_id, file);
|
||||||
|
newXS(strcpy(buf, "get_expedition_by_zone_instance"), XS__get_expedition_by_zone_instance, file);
|
||||||
|
newXS(strcpy(buf, "get_expedition_lockout_by_char_id"), XS__get_expedition_lockout_by_char_id, file);
|
||||||
|
newXS(strcpy(buf, "get_expedition_lockouts_by_char_id"), XS__get_expedition_lockouts_by_char_id, file);
|
||||||
newXS(strcpy(buf, "getinventoryslotid"), XS__getinventoryslotid, file);
|
newXS(strcpy(buf, "getinventoryslotid"), XS__getinventoryslotid, file);
|
||||||
newXS(strcpy(buf, "getitemname"), XS__getitemname, file);
|
newXS(strcpy(buf, "getitemname"), XS__getitemname, file);
|
||||||
newXS(strcpy(buf, "getItemName"), XS_qc_getItemName, file);
|
newXS(strcpy(buf, "getItemName"), XS_qc_getItemName, file);
|
||||||
@ -6284,6 +6592,7 @@ EXTERN_C XS(boot_quest) {
|
|||||||
newXS(strcpy(buf, "log"), XS__log, file);
|
newXS(strcpy(buf, "log"), XS__log, file);
|
||||||
newXS(strcpy(buf, "log_combat"), XS__log_combat, file);
|
newXS(strcpy(buf, "log_combat"), XS__log_combat, file);
|
||||||
newXS(strcpy(buf, "me"), XS__me, file);
|
newXS(strcpy(buf, "me"), XS__me, file);
|
||||||
|
newXS(strcpy(buf, "message"), XS__message, file);
|
||||||
newXS(strcpy(buf, "modifynpcstat"), XS__ModifyNPCStat, file);
|
newXS(strcpy(buf, "modifynpcstat"), XS__ModifyNPCStat, file);
|
||||||
newXS(strcpy(buf, "movegrp"), XS__movegrp, file);
|
newXS(strcpy(buf, "movegrp"), XS__movegrp, file);
|
||||||
newXS(strcpy(buf, "movepc"), XS__movepc, file);
|
newXS(strcpy(buf, "movepc"), XS__movepc, file);
|
||||||
@ -6311,6 +6620,9 @@ EXTERN_C XS(boot_quest) {
|
|||||||
newXS(strcpy(buf, "rain"), XS__rain, file);
|
newXS(strcpy(buf, "rain"), XS__rain, file);
|
||||||
newXS(strcpy(buf, "rebind"), XS__rebind, file);
|
newXS(strcpy(buf, "rebind"), XS__rebind, file);
|
||||||
newXS(strcpy(buf, "reloadzonestaticdata"), XS__reloadzonestaticdata, file);
|
newXS(strcpy(buf, "reloadzonestaticdata"), XS__reloadzonestaticdata, file);
|
||||||
|
newXS(strcpy(buf, "remove_all_expedition_lockouts_by_char_id"), XS__remove_all_expedition_lockouts_by_char_id, file);
|
||||||
|
newXS(strcpy(buf, "remove_expedition_lockout_by_char_id"), XS__remove_expedition_lockout_by_char_id, file);
|
||||||
|
newXS(strcpy(buf, "removeitem"), XS__removeitem, file);
|
||||||
newXS(strcpy(buf, "removetitle"), XS__removetitle, file);
|
newXS(strcpy(buf, "removetitle"), XS__removetitle, file);
|
||||||
newXS(strcpy(buf, "repopzone"), XS__repopzone, file);
|
newXS(strcpy(buf, "repopzone"), XS__repopzone, file);
|
||||||
newXS(strcpy(buf, "resettaskactivity"), XS__resettaskactivity, file);
|
newXS(strcpy(buf, "resettaskactivity"), XS__resettaskactivity, file);
|
||||||
@ -6377,6 +6689,7 @@ EXTERN_C XS(boot_quest) {
|
|||||||
newXS(strcpy(buf, "voicetell"), XS__voicetell, file);
|
newXS(strcpy(buf, "voicetell"), XS__voicetell, file);
|
||||||
newXS(strcpy(buf, "we"), XS__we, file);
|
newXS(strcpy(buf, "we"), XS__we, file);
|
||||||
newXS(strcpy(buf, "wearchange"), XS__wearchange, file);
|
newXS(strcpy(buf, "wearchange"), XS__wearchange, file);
|
||||||
|
newXS(strcpy(buf, "whisper"), XS__whisper, file);
|
||||||
newXS(strcpy(buf, "write"), XS__write, file);
|
newXS(strcpy(buf, "write"), XS__write, file);
|
||||||
newXS(strcpy(buf, "ze"), XS__ze, file);
|
newXS(strcpy(buf, "ze"), XS__ze, file);
|
||||||
newXS(strcpy(buf, "zone"), XS__zone, file);
|
newXS(strcpy(buf, "zone"), XS__zone, file);
|
||||||
|
|||||||
@ -37,6 +37,7 @@ EXTERN_C XS(boot_HateEntry);
|
|||||||
EXTERN_C XS(boot_Object);
|
EXTERN_C XS(boot_Object);
|
||||||
EXTERN_C XS(boot_Doors);
|
EXTERN_C XS(boot_Doors);
|
||||||
EXTERN_C XS(boot_PerlPacket);
|
EXTERN_C XS(boot_PerlPacket);
|
||||||
|
EXTERN_C XS(boot_Expedition);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -87,6 +88,7 @@ EXTERN_C void xs_init(pTHX)
|
|||||||
newXS(strcpy(buf, "HateEntry::boot_HateEntry"), boot_HateEntry, file);
|
newXS(strcpy(buf, "HateEntry::boot_HateEntry"), boot_HateEntry, file);
|
||||||
newXS(strcpy(buf, "Object::boot_Object"), boot_Object, file);
|
newXS(strcpy(buf, "Object::boot_Object"), boot_Object, file);
|
||||||
newXS(strcpy(buf, "Doors::boot_Doors"), boot_Doors, file);
|
newXS(strcpy(buf, "Doors::boot_Doors"), boot_Doors, file);
|
||||||
|
newXS(strcpy(buf, "Expedition::boot_Expedition"), boot_Expedition, file);
|
||||||
;
|
;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
150
zone/entity.cpp
150
zone/entity.cpp
@ -32,6 +32,7 @@
|
|||||||
#include "../common/features.h"
|
#include "../common/features.h"
|
||||||
#include "../common/guilds.h"
|
#include "../common/guilds.h"
|
||||||
|
|
||||||
|
#include "dynamiczone.h"
|
||||||
#include "guild_mgr.h"
|
#include "guild_mgr.h"
|
||||||
#include "petitions.h"
|
#include "petitions.h"
|
||||||
#include "quest_parser_collection.h"
|
#include "quest_parser_collection.h"
|
||||||
@ -712,6 +713,8 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
|
|||||||
npc_list.insert(std::pair<uint16, NPC *>(npc->GetID(), npc));
|
npc_list.insert(std::pair<uint16, NPC *>(npc->GetID(), npc));
|
||||||
mob_list.insert(std::pair<uint16, Mob *>(npc->GetID(), npc));
|
mob_list.insert(std::pair<uint16, Mob *>(npc->GetID(), npc));
|
||||||
|
|
||||||
|
entity_list.ScanCloseMobs(npc->close_mobs, npc, true);
|
||||||
|
|
||||||
/* Zone controller process EVENT_SPAWN_ZONE */
|
/* Zone controller process EVENT_SPAWN_ZONE */
|
||||||
if (RuleB(Zone, UseZoneController)) {
|
if (RuleB(Zone, UseZoneController)) {
|
||||||
if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && npc->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){
|
if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && npc->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){
|
||||||
@ -1322,8 +1325,8 @@ void EntityList::SendZoneSpawnsBulk(Client *client)
|
|||||||
const glm::vec4 &client_position = client->GetPosition();
|
const glm::vec4 &client_position = client->GetPosition();
|
||||||
const float distance_max = (600.0 * 600.0);
|
const float distance_max = (600.0 * 600.0);
|
||||||
|
|
||||||
for (auto it = mob_list.begin(); it != mob_list.end(); ++it) {
|
for (auto & it : mob_list) {
|
||||||
spawn = it->second;
|
spawn = it.second;
|
||||||
if (spawn && spawn->GetID() > 0 && spawn->Spawned()) {
|
if (spawn && spawn->GetID() > 0 && spawn->Spawned()) {
|
||||||
if (!spawn->ShouldISpawnFor(client)) {
|
if (!spawn->ShouldISpawnFor(client)) {
|
||||||
continue;
|
continue;
|
||||||
@ -2508,7 +2511,7 @@ void EntityList::DespawnAllDoors()
|
|||||||
auto outapp = new EQApplicationPacket(OP_RemoveAllDoors, 0);
|
auto outapp = new EQApplicationPacket(OP_RemoveAllDoors, 0);
|
||||||
for (auto it = client_list.begin(); it != client_list.end(); ++it) {
|
for (auto it = client_list.begin(); it != client_list.end(); ++it) {
|
||||||
if (it->second) {
|
if (it->second) {
|
||||||
it->second->QueuePacket(outapp);
|
it->second->QueuePacket(outapp, true, Client::CLIENT_CONNECTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
@ -2521,7 +2524,7 @@ void EntityList::RespawnAllDoors()
|
|||||||
if (it->second) {
|
if (it->second) {
|
||||||
auto outapp = new EQApplicationPacket();
|
auto outapp = new EQApplicationPacket();
|
||||||
MakeDoorSpawnPacket(outapp, it->second);
|
MakeDoorSpawnPacket(outapp, it->second);
|
||||||
it->second->FastQueuePacket(&outapp);
|
it->second->FastQueuePacket(&outapp, true, Client::CLIENT_CONNECTED);
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
@ -2690,6 +2693,36 @@ void EntityList::RemoveAuraFromMobs(Mob *aura)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* The purpose of this system is so that we cache relevant entities that are "close"
|
||||||
|
*
|
||||||
|
* In general; it becomes incredibly expensive to run zone-wide checks against every single mob in the zone when in reality
|
||||||
|
* we only care about entities closest to us
|
||||||
|
*
|
||||||
|
* A very simple example of where this is relevant is Aggro, the below example is skewed because the overall implementation
|
||||||
|
* of Aggro was also tweaked in conjunction with close lists. We also scan more aggressively when entities are moving (1-6 seconds)
|
||||||
|
* versus 60 seconds when idle. We also have entities that are moving add themselves to those closest to them so that their close
|
||||||
|
* lists remain always up to date
|
||||||
|
*
|
||||||
|
* Before: Aggro checks for NPC to Client aggro | (40 clients in zone) x (525 npcs) x 2 (times a second) = 2,520,000 checks a minute
|
||||||
|
* After: Aggro checks for NPC to Client aggro | (40 clients in zone) x (20-30 npcs) x 2 (times a second) = 144,000 checks a minute (This is actually far less today)
|
||||||
|
*
|
||||||
|
* Places in the code where this logic makes a huge impact
|
||||||
|
*
|
||||||
|
* Aggro checks (zone wide -> close)
|
||||||
|
* Aura processing (zone wide -> close)
|
||||||
|
* AE Taunt (zone wide -> close)
|
||||||
|
* AOE Spells (zone wide -> close)
|
||||||
|
* Bard Pulse AOE (zone wide -> close)
|
||||||
|
* Mass Group Buff (zone wide -> close)
|
||||||
|
* AE Attack (zone wide -> close)
|
||||||
|
* Packet QueueCloseClients (zone wide -> close)
|
||||||
|
* Check Close Beneficial Spells (Buffs; should I heal other npcs) (zone wide -> close)
|
||||||
|
* AI Yell for Help (NPC Assist other NPCs) (zone wide -> close)
|
||||||
|
*
|
||||||
|
* All of the above makes a tremendous impact on the bottom line of cpu cycle performance because we run an order of magnitude
|
||||||
|
* less checks by focusing our hot path logic down to a very small subset of relevant entities instead of looping an entire
|
||||||
|
* entity list (zone wide)
|
||||||
|
*
|
||||||
* @param close_mobs
|
* @param close_mobs
|
||||||
* @param scanning_mob
|
* @param scanning_mob
|
||||||
*/
|
*/
|
||||||
@ -4102,10 +4135,15 @@ void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy)
|
|||||||
NPC* n = it->second;
|
NPC* n = it->second;
|
||||||
if (n->GetSwarmInfo()) {
|
if (n->GetSwarmInfo()) {
|
||||||
if (n->GetSwarmInfo()->owner_id == owner->GetID()) {
|
if (n->GetSwarmInfo()->owner_id == owner->GetID()) {
|
||||||
if (!n->GetSpecialAbility(IMMUNE_AGGRO))
|
if (
|
||||||
|
!n->GetSpecialAbility(IMMUNE_AGGRO) &&
|
||||||
|
!(n->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient()) &&
|
||||||
|
!(n->GetSpecialAbility(IMMUNE_AGGRO_NPC) && other->IsNPC())
|
||||||
|
) {
|
||||||
n->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
n->hate_list.AddEntToHateList(other, 0, 0, bFrenzy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4206,7 +4244,7 @@ void EntityList::ForceGroupUpdate(uint32 gid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityList::SendGroupLeave(uint32 gid, const char *name)
|
void EntityList::SendGroupLeave(uint32 gid, const char *name, bool checkleader)
|
||||||
{
|
{
|
||||||
auto it = client_list.begin();
|
auto it = client_list.begin();
|
||||||
while (it != client_list.end()) {
|
while (it != client_list.end()) {
|
||||||
@ -4222,16 +4260,42 @@ void EntityList::SendGroupLeave(uint32 gid, const char *name)
|
|||||||
gj->action = groupActLeave;
|
gj->action = groupActLeave;
|
||||||
strcpy(gj->yourname, c->GetName());
|
strcpy(gj->yourname, c->GetName());
|
||||||
Mob *Leader = g->GetLeader();
|
Mob *Leader = g->GetLeader();
|
||||||
if (Leader)
|
if (Leader) {
|
||||||
Leader->CastToClient()->GetGroupAAs(&gj->leader_aas);
|
Leader->CastToClient()->GetGroupAAs(&gj->leader_aas);
|
||||||
|
}
|
||||||
c->QueuePacket(outapp);
|
c->QueuePacket(outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
g->DelMemberOOZ(name);
|
g->DelMemberOOZ(name, checkleader);
|
||||||
if (g->IsLeader(c) && c->IsLFP())
|
if (g->IsLeader(c) && c->IsLFP()) {
|
||||||
c->UpdateLFP();
|
c->UpdateLFP();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityList::SendGroupLeader(uint32 gid, const char *lname, const char *oldlname)
|
||||||
|
{
|
||||||
|
auto it = client_list.begin();
|
||||||
|
while (it != client_list.end()) {
|
||||||
|
if (it->second){
|
||||||
|
Group *g = nullptr;
|
||||||
|
g = it->second->GetGroup();
|
||||||
|
if (g) {
|
||||||
|
if (g->GetID() == gid) {
|
||||||
|
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct));
|
||||||
|
GroupJoin_Struct* gj = (GroupJoin_Struct*) outapp->pBuffer;
|
||||||
|
gj->action = groupActMakeLeader;
|
||||||
|
strcpy(gj->membername, lname);
|
||||||
|
strcpy(gj->yourname, oldlname);
|
||||||
|
it->second->QueuePacket(outapp);
|
||||||
|
Log(Logs::Detail, Logs::Group, "SendGroupLeader(): Entity loop leader update packet sent to: %s .", it->second->GetName());
|
||||||
|
safe_delete(outapp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4251,9 +4315,9 @@ void EntityList::SendGroupJoin(uint32 gid, const char *name)
|
|||||||
gj->action = groupActJoin;
|
gj->action = groupActJoin;
|
||||||
strcpy(gj->yourname, it->second->GetName());
|
strcpy(gj->yourname, it->second->GetName());
|
||||||
Mob *Leader = g->GetLeader();
|
Mob *Leader = g->GetLeader();
|
||||||
if (Leader)
|
if (Leader) {
|
||||||
Leader->CastToClient()->GetGroupAAs(&gj->leader_aas);
|
Leader->CastToClient()->GetGroupAAs(&gj->leader_aas);
|
||||||
|
}
|
||||||
it->second->QueuePacket(outapp);
|
it->second->QueuePacket(outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
@ -5187,6 +5251,8 @@ void EntityList::ReloadMerchants() {
|
|||||||
* If we have a distance requested that is greater than our scanning distance
|
* If we have a distance requested that is greater than our scanning distance
|
||||||
* then we return the full list
|
* then we return the full list
|
||||||
*
|
*
|
||||||
|
* See comments @EntityList::ScanCloseMobs for system explanation
|
||||||
|
*
|
||||||
* @param mob
|
* @param mob
|
||||||
* @param distance
|
* @param distance
|
||||||
* @return
|
* @return
|
||||||
@ -5200,3 +5266,65 @@ std::unordered_map<uint16, Mob *> &EntityList::GetCloseMobList(Mob *mob, float d
|
|||||||
return mob_list;
|
return mob_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityList::GateAllClientsToSafeReturn()
|
||||||
|
{
|
||||||
|
DynamicZone dz;
|
||||||
|
if (zone)
|
||||||
|
{
|
||||||
|
dz = zone->GetDynamicZone();
|
||||||
|
|
||||||
|
LogDynamicZones(
|
||||||
|
"Sending all clients in zone: [{}] instance: [{}] to dz safereturn or bind",
|
||||||
|
zone->GetZoneID(), zone->GetInstanceID()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& client_list_iter : client_list)
|
||||||
|
{
|
||||||
|
if (client_list_iter.second)
|
||||||
|
{
|
||||||
|
// falls back to gating clients to bind if dz invalid
|
||||||
|
client_list_iter.second->GoToDzSafeReturnOrBind(dz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int EntityList::MovePlayerCorpsesToGraveyard(bool force_move_from_instance)
|
||||||
|
{
|
||||||
|
if (!zone)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moved_count = 0;
|
||||||
|
|
||||||
|
for (auto it = corpse_list.begin(); it != corpse_list.end();)
|
||||||
|
{
|
||||||
|
bool moved = false;
|
||||||
|
if (it->second && it->second->IsPlayerCorpse())
|
||||||
|
{
|
||||||
|
if (zone->HasGraveyard())
|
||||||
|
{
|
||||||
|
moved = it->second->MovePlayerCorpseToGraveyard();
|
||||||
|
}
|
||||||
|
else if (force_move_from_instance && zone->GetInstanceID() != 0)
|
||||||
|
{
|
||||||
|
moved = it->second->MovePlayerCorpseToNonInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moved)
|
||||||
|
{
|
||||||
|
safe_delete(it->second);
|
||||||
|
free_ids.push(it->first);
|
||||||
|
it = corpse_list.erase(it);
|
||||||
|
++moved_count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return moved_count;
|
||||||
|
}
|
||||||
|
|||||||
@ -49,6 +49,7 @@ class Raid;
|
|||||||
class Spawn2;
|
class Spawn2;
|
||||||
class Trap;
|
class Trap;
|
||||||
|
|
||||||
|
struct DynamicZoneSafeReturn;
|
||||||
struct GuildBankItemUpdate_Struct;
|
struct GuildBankItemUpdate_Struct;
|
||||||
struct NewSpawn_Struct;
|
struct NewSpawn_Struct;
|
||||||
struct QGlobal;
|
struct QGlobal;
|
||||||
@ -477,8 +478,9 @@ public:
|
|||||||
void CameraEffect(uint32 duration, uint32 intensity);
|
void CameraEffect(uint32 duration, uint32 intensity);
|
||||||
Mob* GetClosestMobByBodyType(Mob* sender, bodyType BodyType);
|
Mob* GetClosestMobByBodyType(Mob* sender, bodyType BodyType);
|
||||||
void ForceGroupUpdate(uint32 gid);
|
void ForceGroupUpdate(uint32 gid);
|
||||||
void SendGroupLeave(uint32 gid, const char *name);
|
void SendGroupLeave(uint32 gid, const char *name, bool checkleader);
|
||||||
void SendGroupJoin(uint32 gid, const char *name);
|
void SendGroupJoin(uint32 gid, const char *name);
|
||||||
|
void SendGroupLeader(uint32 gid, const char *lname, const char *oldlname);
|
||||||
|
|
||||||
void SaveAllClientsTaskState();
|
void SaveAllClientsTaskState();
|
||||||
void ReloadAllClientsTaskState(int TaskID=0);
|
void ReloadAllClientsTaskState(int TaskID=0);
|
||||||
@ -496,6 +498,8 @@ public:
|
|||||||
void UpdateFindableNPCState(NPC *n, bool Remove);
|
void UpdateFindableNPCState(NPC *n, bool Remove);
|
||||||
void HideCorpses(Client *c, uint8 CurrentMode, uint8 NewMode);
|
void HideCorpses(Client *c, uint8 CurrentMode, uint8 NewMode);
|
||||||
|
|
||||||
|
void GateAllClientsToSafeReturn();
|
||||||
|
|
||||||
uint16 GetClientCount();
|
uint16 GetClientCount();
|
||||||
void GetMobList(std::list<Mob*> &m_list);
|
void GetMobList(std::list<Mob*> &m_list);
|
||||||
void GetNPCList(std::list<NPC*> &n_list);
|
void GetNPCList(std::list<NPC*> &n_list);
|
||||||
@ -534,6 +538,8 @@ public:
|
|||||||
void UpdateAllTraps(bool respawn, bool repopnow = false);
|
void UpdateAllTraps(bool respawn, bool repopnow = false);
|
||||||
void ClearTrapPointers();
|
void ClearTrapPointers();
|
||||||
|
|
||||||
|
int MovePlayerCorpsesToGraveyard(bool force_move_from_instance = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Zone;
|
friend class Zone;
|
||||||
void Depop(bool StartSpawnTimer = false);
|
void Depop(bool StartSpawnTimer = false);
|
||||||
|
|||||||
14
zone/exp.cpp
14
zone/exp.cpp
@ -664,11 +664,18 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
|
|||||||
m_pp.aapoints += last_unspentAA;
|
m_pp.aapoints += last_unspentAA;
|
||||||
|
|
||||||
//figure out how many points were actually gained
|
//figure out how many points were actually gained
|
||||||
/*uint32 gained = m_pp.aapoints - last_unspentAA;*/ //unused
|
uint32 gained = (m_pp.aapoints - last_unspentAA);
|
||||||
|
|
||||||
//Message(Chat::Yellow, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA);
|
//Message(Chat::Yellow, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA);
|
||||||
char val1[20] = { 0 };
|
char val1[20] = { 0 };
|
||||||
MessageString(Chat::Experience, GAIN_ABILITY_POINT, ConvertArray(m_pp.aapoints, val1),m_pp.aapoints == 1 ? "" : "(s)"); //You have gained an ability point! You now have %1 ability point%2.
|
char val2[20] = { 0 };
|
||||||
|
if (gained == 1 && m_pp.aapoints == 1)
|
||||||
|
MessageString(Chat::Experience, GAIN_SINGLE_AA_SINGLE_AA, ConvertArray(m_pp.aapoints, val1)); //You have gained an ability point! You now have %1 ability point.
|
||||||
|
else if (gained == 1 && m_pp.aapoints > 1)
|
||||||
|
MessageString(Chat::Experience, GAIN_SINGLE_AA_MULTI_AA, ConvertArray(m_pp.aapoints, val1)); //You have gained an ability point! You now have %1 ability points.
|
||||||
|
else
|
||||||
|
MessageString(Chat::Experience, GAIN_MULTI_AA_MULTI_AA, ConvertArray(gained, val1), ConvertArray(m_pp.aapoints, val2)); //You have gained %1 ability point(s)! You now have %2 ability point(s).
|
||||||
|
|
||||||
if (RuleB(AA, SoundForAAEarned)) {
|
if (RuleB(AA, SoundForAAEarned)) {
|
||||||
SendSound();
|
SendSound();
|
||||||
}
|
}
|
||||||
@ -718,7 +725,8 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
|
|||||||
else
|
else
|
||||||
Message(Chat::Yellow, "Welcome to level %i!", check_level);
|
Message(Chat::Yellow, "Welcome to level %i!", check_level);
|
||||||
|
|
||||||
if (check_level == RuleI(Character, DeathItemLossLevel))
|
if (check_level == RuleI(Character, DeathItemLossLevel) &&
|
||||||
|
m_ClientVersionBit & EQ::versions::maskUFAndEarlier)
|
||||||
MessageString(Chat::Yellow, CORPSE_ITEM_LOST);
|
MessageString(Chat::Yellow, CORPSE_ITEM_LOST);
|
||||||
|
|
||||||
if (check_level == RuleI(Character, DeathExpLossLevel))
|
if (check_level == RuleI(Character, DeathExpLossLevel))
|
||||||
|
|||||||
2293
zone/expedition.cpp
Normal file
2293
zone/expedition.cpp
Normal file
File diff suppressed because it is too large
Load Diff
242
zone/expedition.h
Normal file
242
zone/expedition.h
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXPEDITION_H
|
||||||
|
#define EXPEDITION_H
|
||||||
|
|
||||||
|
#include "dynamiczone.h"
|
||||||
|
#include "expedition_lockout_timer.h"
|
||||||
|
#include "../common/eq_constants.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Client;
|
||||||
|
class EQApplicationPacket;
|
||||||
|
struct ExpeditionInvite;
|
||||||
|
class ExpeditionRequest;
|
||||||
|
class MySQLRequestResult;
|
||||||
|
class ServerPacket;
|
||||||
|
|
||||||
|
extern const char* const DZ_YOU_NOT_ASSIGNED;
|
||||||
|
extern const char* const EXPEDITION_OTHER_BELONGS;
|
||||||
|
extern const char* const CREATE_NOT_ALL_ADDED;
|
||||||
|
|
||||||
|
enum class ExpeditionMemberStatus : uint8_t
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
Online,
|
||||||
|
Offline,
|
||||||
|
InDynamicZone,
|
||||||
|
LinkDead
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ExpeditionLockMessage : uint8_t
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Close,
|
||||||
|
Begin
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ExpeditionMember
|
||||||
|
{
|
||||||
|
uint32_t char_id = 0;
|
||||||
|
std::string name;
|
||||||
|
ExpeditionMemberStatus status = ExpeditionMemberStatus::Online;
|
||||||
|
|
||||||
|
ExpeditionMember() = default;
|
||||||
|
ExpeditionMember(uint32_t char_id_, const std::string& name_)
|
||||||
|
: char_id(char_id_), name(name_) {}
|
||||||
|
ExpeditionMember(uint32_t char_id_, const std::string& name_, ExpeditionMemberStatus status_)
|
||||||
|
: char_id(char_id_), name(name_), status(status_) {}
|
||||||
|
|
||||||
|
bool IsValid() const { return char_id != 0 && !name.empty(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class Expedition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Expedition() = delete;
|
||||||
|
Expedition(uint32_t id, const std::string& uuid, const DynamicZone& dz, const std::string& expedition_name,
|
||||||
|
const ExpeditionMember& leader, uint32_t min_players, uint32_t max_players);
|
||||||
|
|
||||||
|
static Expedition* TryCreate(Client* requester, DynamicZone& dynamiczone, ExpeditionRequest& request);
|
||||||
|
|
||||||
|
static void CacheFromDatabase(uint32_t expedition_id);
|
||||||
|
static bool CacheAllFromDatabase();
|
||||||
|
static Expedition* FindCachedExpeditionByCharacterID(uint32_t character_id);
|
||||||
|
static Expedition* FindCachedExpeditionByCharacterName(const std::string& char_name);
|
||||||
|
static Expedition* FindCachedExpeditionByDynamicZoneID(uint32_t dz_id);
|
||||||
|
static Expedition* FindCachedExpeditionByID(uint32_t expedition_id);
|
||||||
|
static Expedition* FindCachedExpeditionByZoneInstance(uint32_t zone_id, uint32_t instance_id);
|
||||||
|
static std::vector<ExpeditionLockoutTimer> GetExpeditionLockoutsByCharacterID(uint32_t character_id);
|
||||||
|
static void HandleWorldMessage(ServerPacket* pack);
|
||||||
|
static void AddLockoutByCharacterID(uint32_t character_id, const std::string& expedition_name,
|
||||||
|
const std::string& event_name, uint32_t seconds, const std::string& uuid = {});
|
||||||
|
static void AddLockoutByCharacterName(const std::string& character_name, const std::string& expedition_name,
|
||||||
|
const std::string& event_name, uint32_t seconds, const std::string& uuid = {});
|
||||||
|
static bool HasLockoutByCharacterID(uint32_t character_id,
|
||||||
|
const std::string& expedition_name, const std::string& event_name);
|
||||||
|
static bool HasLockoutByCharacterName(const std::string& character_name,
|
||||||
|
const std::string& expedition_name, const std::string& event_name);
|
||||||
|
static void RemoveLockoutsByCharacterID(uint32_t character_id,
|
||||||
|
const std::string& expedition_name = {}, const std::string& event_name = {});
|
||||||
|
static void RemoveLockoutsByCharacterName(const std::string& character_name,
|
||||||
|
const std::string& expedition_name = {}, const std::string& event_name = {});
|
||||||
|
static void AddLockoutClients(const ExpeditionLockoutTimer& lockout, uint32_t exclude_id = 0);
|
||||||
|
|
||||||
|
uint32_t GetDynamicZoneID() const { return m_dynamiczone.GetID(); }
|
||||||
|
uint32_t GetID() const { return m_id; }
|
||||||
|
uint16_t GetInstanceID() const { return m_dynamiczone.GetInstanceID(); }
|
||||||
|
uint32_t GetLeaderID() const { return m_leader.char_id; }
|
||||||
|
uint32_t GetMinPlayers() const { return m_min_players; }
|
||||||
|
uint32_t GetMaxPlayers() const { return m_max_players; }
|
||||||
|
uint32_t GetMemberCount() const { return static_cast<uint32_t>(m_members.size()); }
|
||||||
|
const DynamicZone& GetDynamicZone() const { return m_dynamiczone; }
|
||||||
|
const std::string& GetName() const { return m_expedition_name; }
|
||||||
|
const std::string& GetLeaderName() const { return m_leader.name; }
|
||||||
|
const std::string& GetUUID() const { return m_uuid; }
|
||||||
|
const std::unordered_map<std::string, ExpeditionLockoutTimer>& GetLockouts() const { return m_lockouts; }
|
||||||
|
const std::vector<ExpeditionMember>& GetMembers() const { return m_members; }
|
||||||
|
|
||||||
|
bool AddMember(const std::string& add_char_name, uint32_t add_char_id);
|
||||||
|
bool HasMember(const std::string& character_name);
|
||||||
|
bool HasMember(uint32_t character_id);
|
||||||
|
void RemoveAllMembers(bool enable_removal_timers = true);
|
||||||
|
bool RemoveMember(const std::string& remove_char_name);
|
||||||
|
void SetMemberStatus(Client* client, ExpeditionMemberStatus status);
|
||||||
|
void SwapMember(Client* add_client, const std::string& remove_char_name);
|
||||||
|
void SetLocked(bool lock_expedition, ExpeditionLockMessage lock_msg,
|
||||||
|
bool update_db = false, uint32_t msg_color = Chat::Yellow);
|
||||||
|
|
||||||
|
void AddLockout(const std::string& event_name, uint32_t seconds);
|
||||||
|
void AddLockoutDuration(const std::string& event_name, int seconds, bool members_only = true);
|
||||||
|
void AddReplayLockout(uint32_t seconds);
|
||||||
|
void AddReplayLockoutDuration(int seconds, bool members_only = true);
|
||||||
|
bool HasLockout(const std::string& event_name);
|
||||||
|
bool HasReplayLockout();
|
||||||
|
void RemoveLockout(const std::string& event_name);
|
||||||
|
void SetReplayLockoutOnMemberJoin(bool add_on_join, bool update_db = false);
|
||||||
|
void SyncCharacterLockouts(uint32_t character_id, std::vector<ExpeditionLockoutTimer>& client_lockouts);
|
||||||
|
void UpdateLockoutDuration(const std::string& event_name, uint32_t seconds, bool members_only = true);
|
||||||
|
|
||||||
|
bool CanClientLootCorpse(Client* client, uint32_t npc_type_id, uint32_t spawn_id);
|
||||||
|
std::string GetLootEventByNPCTypeID(uint32_t npc_id);
|
||||||
|
std::string GetLootEventBySpawnID(uint32_t spawn_id);
|
||||||
|
void SetLootEventByNPCTypeID(uint32_t npc_type_id, const std::string& event_name);
|
||||||
|
void SetLootEventBySpawnID(uint32_t spawn_id, const std::string& event_name);
|
||||||
|
|
||||||
|
void SendClientExpeditionInfo(Client* client);
|
||||||
|
void SendWorldMakeLeaderRequest(uint32_t requester_id, const std::string& new_leader_name);
|
||||||
|
void SendWorldPendingInvite(const ExpeditionInvite& invite, const std::string& add_name);
|
||||||
|
|
||||||
|
void DzAddPlayer(Client* requester, const std::string& add_char_name, const std::string& swap_remove_name = {});
|
||||||
|
void DzAddPlayerContinue(std::string leader_name, std::string add_char_name, std::string swap_remove_name = {});
|
||||||
|
void DzInviteResponse(Client* add_client, bool accepted, const std::string& swap_remove_name);
|
||||||
|
void DzMakeLeader(Client* requester, std::string new_leader_name);
|
||||||
|
void DzPlayerList(Client* requester);
|
||||||
|
void DzRemovePlayer(Client* requester, std::string remove_char_name);
|
||||||
|
void DzSwapPlayer(Client* requester, std::string remove_char_name, std::string add_char_name);
|
||||||
|
void DzQuit(Client* requester);
|
||||||
|
void DzKickPlayers(Client* requester);
|
||||||
|
|
||||||
|
void SetDzCompass(uint32_t zone_id, float x, float y, float z, bool update_db = false);
|
||||||
|
void SetDzCompass(const std::string& zone_name, float x, float y, float z, bool update_db = false);
|
||||||
|
void SetDzSafeReturn(uint32_t zone_id, float x, float y, float z, float heading, bool update_db = false);
|
||||||
|
void SetDzSafeReturn(const std::string& zone_name, float x, float y, float z, float heading, bool update_db = false);
|
||||||
|
void SetDzSecondsRemaining(uint32_t seconds_remaining);
|
||||||
|
void SetDzZoneInLocation(float x, float y, float z, float heading, bool update_db = false);
|
||||||
|
|
||||||
|
static const int32_t REPLAY_TIMER_ID;
|
||||||
|
static const int32_t EVENT_TIMER_ID;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void CacheExpeditions(MySQLRequestResult& results);
|
||||||
|
static void SendWorldGetOnlineMembers(const std::vector<std::pair<uint32_t, uint32_t>>& expedition_character_ids);
|
||||||
|
static void SendWorldCharacterLockout(uint32_t character_id, const ExpeditionLockoutTimer& lockout, bool remove);
|
||||||
|
|
||||||
|
void AddLockout(const ExpeditionLockoutTimer& lockout, bool members_only = false);
|
||||||
|
void AddLockoutDurationClients(const ExpeditionLockoutTimer& lockout, int seconds, uint32_t exclude_id = 0);
|
||||||
|
void AddInternalMember(const std::string& char_name, uint32_t char_id, ExpeditionMemberStatus status);
|
||||||
|
bool ConfirmLeaderCommand(Client* requester);
|
||||||
|
bool ProcessAddConflicts(Client* leader_client, Client* add_client, bool swapping);
|
||||||
|
void ProcessLeaderChanged(uint32_t new_leader_id);
|
||||||
|
void ProcessLockoutDuration(const ExpeditionLockoutTimer& lockout, int seconds, bool members_only = false);
|
||||||
|
void ProcessLockoutUpdate(const ExpeditionLockoutTimer& lockout, bool remove, bool members_only = false);
|
||||||
|
void ProcessMakeLeader(Client* old_leader, Client* new_leader,
|
||||||
|
const std::string& new_leader_name, bool is_success, bool is_online);
|
||||||
|
void ProcessMemberAdded(const std::string& added_char_name, uint32_t added_char_id);
|
||||||
|
void ProcessMemberRemoved(const std::string& removed_char_name, uint32_t removed_char_id);
|
||||||
|
void SaveLockouts(ExpeditionRequest& request);
|
||||||
|
void SaveMembers(ExpeditionRequest& request);
|
||||||
|
void SendClientExpeditionInvite(
|
||||||
|
Client* client, const std::string& inviter_name, const std::string& swap_remove_name);
|
||||||
|
void SendLeaderMessage(Client* leader_client, uint16_t chat_type, uint32_t string_id,
|
||||||
|
const std::initializer_list<std::string>& args = {});
|
||||||
|
void SendMembersExpireWarning(uint32_t minutes);
|
||||||
|
void SendNewMemberAddedToZoneMembers(const std::string& added_name);
|
||||||
|
void SendUpdatesToZoneMembers(bool clear = false, bool message_on_clear = true);
|
||||||
|
void SendWorldDzLocationUpdate(uint16_t server_opcode, const DynamicZoneLocation& location);
|
||||||
|
void SendWorldExpeditionUpdate(uint16_t server_opcode);
|
||||||
|
void SendWorldAddPlayerInvite(const std::string& inviter_name, const std::string& swap_remove_name,
|
||||||
|
const std::string& add_name, bool pending = false);
|
||||||
|
void SendWorldLockoutDuration(
|
||||||
|
const ExpeditionLockoutTimer& lockout, int seconds, bool members_only = false);
|
||||||
|
void SendWorldLockoutUpdate(
|
||||||
|
const ExpeditionLockoutTimer& lockout, bool remove, bool members_only = false);
|
||||||
|
void SendWorldMemberChanged(const std::string& char_name, uint32_t char_id, bool remove);
|
||||||
|
void SendWorldMemberStatus(uint32_t character_id, ExpeditionMemberStatus status);
|
||||||
|
void SendWorldMemberSwapped(const std::string& remove_char_name, uint32_t remove_char_id,
|
||||||
|
const std::string& add_char_name, uint32_t add_char_id);
|
||||||
|
void SendWorldSetSecondsRemaining(uint32_t seconds_remaining);
|
||||||
|
void SendWorldSettingChanged(uint16_t server_opcode, bool setting_value);
|
||||||
|
void TryAddClient(Client* add_client, const std::string& inviter_name,
|
||||||
|
const std::string& swap_remove_name, Client* leader_client = nullptr);
|
||||||
|
void UpdateDzDuration(uint32_t new_duration) { m_dynamiczone.SetUpdatedDuration(new_duration); }
|
||||||
|
void UpdateMemberStatus(uint32_t update_character_id, ExpeditionMemberStatus status);
|
||||||
|
|
||||||
|
ExpeditionMember GetMemberData(uint32_t character_id);
|
||||||
|
ExpeditionMember GetMemberData(const std::string& character_name);
|
||||||
|
std::unique_ptr<EQApplicationPacket> CreateExpireWarningPacket(uint32_t minutes_remaining);
|
||||||
|
std::unique_ptr<EQApplicationPacket> CreateInfoPacket(bool clear = false);
|
||||||
|
std::unique_ptr<EQApplicationPacket> CreateInvitePacket(const std::string& inviter_name, const std::string& swap_remove_name);
|
||||||
|
std::unique_ptr<EQApplicationPacket> CreateMemberListPacket(bool clear = false);
|
||||||
|
std::unique_ptr<EQApplicationPacket> CreateMemberListNamePacket(const std::string& name, bool remove_name);
|
||||||
|
std::unique_ptr<EQApplicationPacket> CreateMemberListStatusPacket(const std::string& name, ExpeditionMemberStatus status);
|
||||||
|
std::unique_ptr<EQApplicationPacket> CreateLeaderNamePacket();
|
||||||
|
|
||||||
|
uint32_t m_id = 0;
|
||||||
|
uint32_t m_min_players = 0;
|
||||||
|
uint32_t m_max_players = 0;
|
||||||
|
bool m_is_locked = false;
|
||||||
|
bool m_add_replay_on_join = true;
|
||||||
|
std::string m_uuid;
|
||||||
|
std::string m_expedition_name;
|
||||||
|
DynamicZone m_dynamiczone { DynamicZoneType::Expedition };
|
||||||
|
ExpeditionMember m_leader;
|
||||||
|
std::vector<ExpeditionMember> m_members;
|
||||||
|
std::unordered_map<std::string, ExpeditionLockoutTimer> m_lockouts;
|
||||||
|
std::unordered_map<uint32_t, std::string> m_npc_loot_events; // only valid inside dz zone
|
||||||
|
std::unordered_map<uint32_t, std::string> m_spawn_loot_events; // only valid inside dz zone
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
685
zone/expedition_database.cpp
Normal file
685
zone/expedition_database.cpp
Normal file
@ -0,0 +1,685 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "expedition_database.h"
|
||||||
|
#include "expedition.h"
|
||||||
|
#include "expedition_lockout_timer.h"
|
||||||
|
#include "zonedb.h"
|
||||||
|
#include "../common/database.h"
|
||||||
|
#include "../common/string_util.h"
|
||||||
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
uint32_t ExpeditionDatabase::InsertExpedition(
|
||||||
|
const std::string& uuid, uint32_t dz_id, const std::string& expedition_name,
|
||||||
|
uint32_t leader_id, uint32_t min_players, uint32_t max_players)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail(
|
||||||
|
"Inserting new expedition [{}] leader [{}] uuid [{}]", expedition_name, leader_id, uuid
|
||||||
|
);
|
||||||
|
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
INSERT INTO expeditions
|
||||||
|
(uuid, dynamic_zone_id, expedition_name, leader_id, min_players, max_players)
|
||||||
|
VALUES
|
||||||
|
('{}', {}, '{}', {}, {}, {});
|
||||||
|
), uuid, dz_id, EscapeString(expedition_name), leader_id, min_players, max_players);
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (!results.Success())
|
||||||
|
{
|
||||||
|
LogExpeditions("Failed to obtain an expedition id for [{}]", expedition_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return results.LastInsertedID();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ExpeditionDatabase::LoadExpeditionsSelectQuery()
|
||||||
|
{
|
||||||
|
return std::string(SQL(
|
||||||
|
SELECT
|
||||||
|
expeditions.id,
|
||||||
|
expeditions.uuid,
|
||||||
|
expeditions.dynamic_zone_id,
|
||||||
|
expeditions.expedition_name,
|
||||||
|
expeditions.leader_id,
|
||||||
|
expeditions.min_players,
|
||||||
|
expeditions.max_players,
|
||||||
|
expeditions.add_replay_on_join,
|
||||||
|
expeditions.is_locked,
|
||||||
|
character_data.name leader_name,
|
||||||
|
expedition_members.character_id,
|
||||||
|
member_data.name
|
||||||
|
FROM expeditions
|
||||||
|
INNER JOIN character_data ON expeditions.leader_id = character_data.id
|
||||||
|
INNER JOIN expedition_members ON expeditions.id = expedition_members.expedition_id
|
||||||
|
AND expedition_members.is_current_member = TRUE
|
||||||
|
INNER JOIN character_data member_data ON expedition_members.character_id = member_data.id
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
MySQLRequestResult ExpeditionDatabase::LoadExpedition(uint32_t expedition_id)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Loading expedition [{}]", expedition_id);
|
||||||
|
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
{} WHERE expeditions.id = {};
|
||||||
|
), LoadExpeditionsSelectQuery(), expedition_id);
|
||||||
|
|
||||||
|
return database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
MySQLRequestResult ExpeditionDatabase::LoadAllExpeditions()
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Loading all expeditions from database");
|
||||||
|
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
{} ORDER BY expeditions.id;
|
||||||
|
), LoadExpeditionsSelectQuery());
|
||||||
|
|
||||||
|
return database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ExpeditionLockoutTimer> ExpeditionDatabase::LoadCharacterLockouts(uint32_t character_id)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Loading character [{}] lockouts", character_id);
|
||||||
|
|
||||||
|
std::vector<ExpeditionLockoutTimer> lockouts;
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
SELECT
|
||||||
|
from_expedition_uuid,
|
||||||
|
expedition_name,
|
||||||
|
event_name,
|
||||||
|
UNIX_TIMESTAMP(expire_time),
|
||||||
|
duration
|
||||||
|
FROM character_expedition_lockouts
|
||||||
|
WHERE character_id = {} AND expire_time > NOW();
|
||||||
|
), character_id);
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (results.Success())
|
||||||
|
{
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row)
|
||||||
|
{
|
||||||
|
lockouts.emplace_back(
|
||||||
|
row[0], // expedition_uuid
|
||||||
|
row[1], // expedition_name
|
||||||
|
row[2], // event_name
|
||||||
|
strtoull(row[3], nullptr, 10), // expire_time
|
||||||
|
static_cast<uint32_t>(strtoul(row[4], nullptr, 10)) // duration
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lockouts;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ExpeditionLockoutTimer> ExpeditionDatabase::LoadCharacterLockouts(
|
||||||
|
uint32_t character_id, const std::string& expedition_name)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Loading character [{}] lockouts for [{}]", character_id, expedition_name);
|
||||||
|
|
||||||
|
std::vector<ExpeditionLockoutTimer> lockouts;
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
SELECT
|
||||||
|
from_expedition_uuid,
|
||||||
|
event_name,
|
||||||
|
UNIX_TIMESTAMP(expire_time),
|
||||||
|
duration
|
||||||
|
FROM character_expedition_lockouts
|
||||||
|
WHERE
|
||||||
|
character_id = {}
|
||||||
|
AND expire_time > NOW()
|
||||||
|
AND expedition_name = '{}';
|
||||||
|
), character_id, EscapeString(expedition_name));
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (results.Success())
|
||||||
|
{
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row)
|
||||||
|
{
|
||||||
|
lockouts.emplace_back(
|
||||||
|
row[0], // expedition_uuid
|
||||||
|
expedition_name,
|
||||||
|
row[1], // event_name
|
||||||
|
strtoull(row[2], nullptr, 10), // expire_time
|
||||||
|
static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) // duration
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lockouts;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<uint32_t, std::unordered_map<std::string, ExpeditionLockoutTimer>>
|
||||||
|
ExpeditionDatabase::LoadMultipleExpeditionLockouts(
|
||||||
|
const std::vector<uint32_t>& expedition_ids)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Loading internal lockouts for [{}] expeditions", expedition_ids.size());
|
||||||
|
|
||||||
|
std::string in_expedition_ids_query = fmt::format("{}", fmt::join(expedition_ids, ","));
|
||||||
|
|
||||||
|
// these are loaded into the same container type expeditions use to store lockouts
|
||||||
|
std::unordered_map<uint32_t, std::unordered_map<std::string, ExpeditionLockoutTimer>> lockouts;
|
||||||
|
|
||||||
|
if (!in_expedition_ids_query.empty())
|
||||||
|
{
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
SELECT
|
||||||
|
expedition_lockouts.expedition_id,
|
||||||
|
expedition_lockouts.from_expedition_uuid,
|
||||||
|
expeditions.expedition_name,
|
||||||
|
expedition_lockouts.event_name,
|
||||||
|
UNIX_TIMESTAMP(expedition_lockouts.expire_time),
|
||||||
|
expedition_lockouts.duration
|
||||||
|
FROM expedition_lockouts
|
||||||
|
INNER JOIN expeditions ON expedition_lockouts.expedition_id = expeditions.id
|
||||||
|
WHERE expedition_id IN ({})
|
||||||
|
ORDER BY expedition_id;
|
||||||
|
), in_expedition_ids_query);
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
|
||||||
|
if (results.Success())
|
||||||
|
{
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row)
|
||||||
|
{
|
||||||
|
auto expedition_id = strtoul(row[0], nullptr, 10);
|
||||||
|
lockouts[expedition_id].emplace(row[3], ExpeditionLockoutTimer{
|
||||||
|
row[1], // expedition_uuid
|
||||||
|
row[2], // expedition_name
|
||||||
|
row[3], // event_name
|
||||||
|
strtoull(row[4], nullptr, 10), // expire_time
|
||||||
|
static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) // original duration
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lockouts;
|
||||||
|
}
|
||||||
|
|
||||||
|
MySQLRequestResult ExpeditionDatabase::LoadMembersForCreateRequest(
|
||||||
|
const std::vector<std::string>& character_names, const std::string& expedition_name)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail(
|
||||||
|
"Loading data of [{}] characters for [{}] request", character_names.size(), expedition_name
|
||||||
|
);
|
||||||
|
|
||||||
|
std::string in_character_names_query;
|
||||||
|
for (const auto& character_name : character_names)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(in_character_names_query), "'{}',", character_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
MySQLRequestResult results;
|
||||||
|
|
||||||
|
if (!in_character_names_query.empty())
|
||||||
|
{
|
||||||
|
in_character_names_query.pop_back(); // trailing comma
|
||||||
|
|
||||||
|
// for create validation, loads each character's lockouts and possible current expedition
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
SELECT
|
||||||
|
character_data.id,
|
||||||
|
character_data.name,
|
||||||
|
member.expedition_id,
|
||||||
|
lockout.from_expedition_uuid,
|
||||||
|
UNIX_TIMESTAMP(lockout.expire_time),
|
||||||
|
lockout.duration,
|
||||||
|
lockout.event_name
|
||||||
|
FROM character_data
|
||||||
|
LEFT JOIN character_expedition_lockouts lockout
|
||||||
|
ON character_data.id = lockout.character_id
|
||||||
|
AND lockout.expire_time > NOW()
|
||||||
|
AND lockout.expedition_name = '{}'
|
||||||
|
LEFT JOIN expedition_members member
|
||||||
|
ON character_data.id = member.character_id
|
||||||
|
AND member.is_current_member = TRUE
|
||||||
|
WHERE character_data.name IN ({})
|
||||||
|
ORDER BY FIELD(character_data.name, {})
|
||||||
|
), EscapeString(expedition_name), in_character_names_query, in_character_names_query);
|
||||||
|
|
||||||
|
results = database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::DeleteAllCharacterLockouts(uint32_t character_id)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Deleting all character [{}] lockouts", character_id);
|
||||||
|
|
||||||
|
if (character_id != 0)
|
||||||
|
{
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
DELETE FROM character_expedition_lockouts
|
||||||
|
WHERE character_id = {};
|
||||||
|
), character_id);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::DeleteAllCharacterLockouts(
|
||||||
|
uint32_t character_id, const std::string& expedition_name)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Deleting all character [{}] lockouts for [{}]", character_id, expedition_name);
|
||||||
|
|
||||||
|
if (character_id != 0 && !expedition_name.empty())
|
||||||
|
{
|
||||||
|
std::string query = fmt::format(SQL(
|
||||||
|
DELETE FROM character_expedition_lockouts
|
||||||
|
WHERE character_id = {} AND expedition_name = '{}';
|
||||||
|
), character_id, EscapeString(expedition_name));
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::DeleteCharacterLockout(
|
||||||
|
uint32_t character_id, const std::string& expedition_name, const std::string& event_name)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail(
|
||||||
|
"Deleting character [{}] lockout: [{}]:[{}]", character_id, expedition_name, event_name
|
||||||
|
);
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
DELETE FROM character_expedition_lockouts
|
||||||
|
WHERE
|
||||||
|
character_id = {}
|
||||||
|
AND expedition_name = '{}'
|
||||||
|
AND event_name = '{}';
|
||||||
|
), character_id, EscapeString(expedition_name), EscapeString(event_name));
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::DeleteMembersLockout(
|
||||||
|
const std::vector<ExpeditionMember>& members,
|
||||||
|
const std::string& expedition_name, const std::string& event_name)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Deleting members lockout: [{}]:[{}]", expedition_name, event_name);
|
||||||
|
|
||||||
|
std::string query_character_ids;
|
||||||
|
for (const auto& member : members)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(query_character_ids), "{},", member.char_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!query_character_ids.empty())
|
||||||
|
{
|
||||||
|
query_character_ids.pop_back(); // trailing comma
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
DELETE FROM character_expedition_lockouts
|
||||||
|
WHERE character_id
|
||||||
|
IN ({})
|
||||||
|
AND expedition_name = '{}'
|
||||||
|
AND event_name = '{}';
|
||||||
|
), query_character_ids, EscapeString(expedition_name), EscapeString(event_name));
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::DeleteLockout(uint32_t expedition_id, const std::string& event_name)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Deleting expedition [{}] lockout event [{}]", expedition_id, event_name);
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
DELETE FROM expedition_lockouts
|
||||||
|
WHERE expedition_id = {} AND event_name = '{}';
|
||||||
|
), expedition_id, EscapeString(event_name));
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ExpeditionDatabase::GetExpeditionIDFromCharacterID(uint32_t character_id)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Getting expedition id for character [{}]", character_id);
|
||||||
|
|
||||||
|
uint32_t expedition_id = 0;
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
SELECT expedition_id FROM expedition_members
|
||||||
|
WHERE character_id = {} AND is_current_member = TRUE;
|
||||||
|
), character_id);
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (results.Success() && results.RowCount() > 0)
|
||||||
|
{
|
||||||
|
auto row = results.begin();
|
||||||
|
expedition_id = strtoul(row[0], nullptr, 10);
|
||||||
|
}
|
||||||
|
return expedition_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ExpeditionDatabase::GetMemberCount(uint32_t expedition_id)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Getting expedition [{}] member count from db", expedition_id);
|
||||||
|
|
||||||
|
uint32_t member_count = 0;
|
||||||
|
if (expedition_id != 0)
|
||||||
|
{
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM expedition_members
|
||||||
|
WHERE expedition_id = {} AND is_current_member = TRUE;
|
||||||
|
), expedition_id);
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (results.Success() && results.RowCount() > 0)
|
||||||
|
{
|
||||||
|
auto row = results.begin();
|
||||||
|
member_count = strtoul(row[0], nullptr, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return member_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExpeditionDatabase::HasMember(uint32_t expedition_id, uint32_t character_id)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Checking db expedition [{}] for character [{}]", expedition_id, character_id);
|
||||||
|
|
||||||
|
if (expedition_id == 0 || character_id == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
SELECT id
|
||||||
|
FROM expedition_members
|
||||||
|
WHERE expedition_id = {} AND character_id = {} AND is_current_member = TRUE;
|
||||||
|
), expedition_id, character_id);
|
||||||
|
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
return (results.Success() && results.RowCount() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::InsertCharacterLockouts(uint32_t character_id,
|
||||||
|
const std::vector<ExpeditionLockoutTimer>& lockouts)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Inserting [{}] lockouts for character [{}]", lockouts.size(), character_id);
|
||||||
|
|
||||||
|
std::string insert_values;
|
||||||
|
for (const auto& lockout : lockouts)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(insert_values),
|
||||||
|
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),",
|
||||||
|
character_id,
|
||||||
|
lockout.GetExpireTime(),
|
||||||
|
lockout.GetDuration(),
|
||||||
|
lockout.GetExpeditionUUID(),
|
||||||
|
EscapeString(lockout.GetExpeditionName()),
|
||||||
|
EscapeString(lockout.GetEventName())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!insert_values.empty())
|
||||||
|
{
|
||||||
|
insert_values.pop_back(); // trailing comma
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
INSERT INTO character_expedition_lockouts
|
||||||
|
(character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name)
|
||||||
|
VALUES {}
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
from_expedition_uuid = VALUES(from_expedition_uuid),
|
||||||
|
expire_time = VALUES(expire_time),
|
||||||
|
duration = VALUES(duration);
|
||||||
|
), insert_values);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::InsertMembersLockout(
|
||||||
|
const std::vector<ExpeditionMember>& members, const ExpeditionLockoutTimer& lockout)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail(
|
||||||
|
"Inserting members lockout [{}]:[{}] with expire time [{}]",
|
||||||
|
lockout.GetExpeditionName(), lockout.GetEventName(), lockout.GetExpireTime()
|
||||||
|
);
|
||||||
|
|
||||||
|
std::string insert_values;
|
||||||
|
for (const auto& member : members)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(insert_values),
|
||||||
|
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),",
|
||||||
|
member.char_id,
|
||||||
|
lockout.GetExpireTime(),
|
||||||
|
lockout.GetDuration(),
|
||||||
|
lockout.GetExpeditionUUID(),
|
||||||
|
EscapeString(lockout.GetExpeditionName()),
|
||||||
|
EscapeString(lockout.GetEventName())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!insert_values.empty())
|
||||||
|
{
|
||||||
|
insert_values.pop_back(); // trailing comma
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
INSERT INTO character_expedition_lockouts
|
||||||
|
(character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name)
|
||||||
|
VALUES {}
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
from_expedition_uuid = VALUES(from_expedition_uuid),
|
||||||
|
expire_time = VALUES(expire_time),
|
||||||
|
duration = VALUES(duration);
|
||||||
|
), insert_values);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::InsertLockout(
|
||||||
|
uint32_t expedition_id, const ExpeditionLockoutTimer& lockout)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail(
|
||||||
|
"Inserting expedition [{}] lockout: [{}]:[{}] expire time: [{}]",
|
||||||
|
expedition_id, lockout.GetExpeditionName(), lockout.GetEventName(), lockout.GetExpireTime()
|
||||||
|
);
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
INSERT INTO expedition_lockouts
|
||||||
|
(expedition_id, from_expedition_uuid, event_name, expire_time, duration)
|
||||||
|
VALUES
|
||||||
|
({}, '{}', '{}', FROM_UNIXTIME({}), {})
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
from_expedition_uuid = VALUES(from_expedition_uuid),
|
||||||
|
expire_time = VALUES(expire_time),
|
||||||
|
duration = VALUES(duration);
|
||||||
|
),
|
||||||
|
expedition_id,
|
||||||
|
lockout.GetExpeditionUUID(),
|
||||||
|
EscapeString(lockout.GetEventName()),
|
||||||
|
lockout.GetExpireTime(),
|
||||||
|
lockout.GetDuration()
|
||||||
|
);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::InsertLockouts(
|
||||||
|
uint32_t expedition_id, const std::unordered_map<std::string, ExpeditionLockoutTimer>& lockouts)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Inserting expedition [{}] lockouts", expedition_id);
|
||||||
|
|
||||||
|
std::string insert_values;
|
||||||
|
for (const auto& lockout : lockouts)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(insert_values),
|
||||||
|
"({}, '{}', '{}', FROM_UNIXTIME({}), {}),",
|
||||||
|
expedition_id,
|
||||||
|
lockout.second.GetExpeditionUUID(),
|
||||||
|
EscapeString(lockout.second.GetEventName()),
|
||||||
|
lockout.second.GetExpireTime(),
|
||||||
|
lockout.second.GetDuration()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!insert_values.empty())
|
||||||
|
{
|
||||||
|
insert_values.pop_back(); // trailing comma
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
INSERT INTO expedition_lockouts
|
||||||
|
(expedition_id, from_expedition_uuid, event_name, expire_time, duration)
|
||||||
|
VALUES {}
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
from_expedition_uuid = VALUES(from_expedition_uuid),
|
||||||
|
expire_time = VALUES(expire_time),
|
||||||
|
duration = VALUES(duration);
|
||||||
|
), insert_values);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::InsertMember(uint32_t expedition_id, uint32_t character_id)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Inserting character [{}] into expedition [{}]", character_id, expedition_id);
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
INSERT INTO expedition_members
|
||||||
|
(expedition_id, character_id)
|
||||||
|
VALUES
|
||||||
|
({}, {})
|
||||||
|
ON DUPLICATE KEY UPDATE is_current_member = TRUE;
|
||||||
|
), expedition_id, character_id);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::InsertMembers(
|
||||||
|
uint32_t expedition_id, const std::vector<ExpeditionMember>& members)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Inserting characters into expedition [{}]", expedition_id);
|
||||||
|
|
||||||
|
std::string insert_values;
|
||||||
|
for (const auto& member : members)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(insert_values),
|
||||||
|
"({}, {}),",
|
||||||
|
expedition_id, member.char_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!insert_values.empty())
|
||||||
|
{
|
||||||
|
insert_values.pop_back(); // trailing comma
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
INSERT INTO expedition_members
|
||||||
|
(expedition_id, character_id)
|
||||||
|
VALUES {}
|
||||||
|
ON DUPLICATE KEY UPDATE is_current_member = TRUE;
|
||||||
|
), insert_values);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::UpdateLockState(uint32_t expedition_id, bool is_locked)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Updating lock state [{}] for expedition [{}]", is_locked, expedition_id);
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
UPDATE expeditions SET is_locked = {} WHERE id = {};
|
||||||
|
), is_locked, expedition_id);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::DeleteMember(uint32_t expedition_id, uint32_t character_id)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Removing member [{}] from expedition [{}]", character_id, expedition_id);
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
UPDATE expedition_members SET is_current_member = FALSE
|
||||||
|
WHERE expedition_id = {} AND character_id = {};
|
||||||
|
), expedition_id, character_id);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::DeleteAllMembers(uint32_t expedition_id)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Removing all members of expedition [{}]", expedition_id);
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
UPDATE expedition_members SET is_current_member = FALSE WHERE expedition_id = {};
|
||||||
|
), expedition_id);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::UpdateReplayLockoutOnJoin(uint32_t expedition_id, bool add_on_join)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail("Updating replay lockout on join [{}] for expedition [{}]", add_on_join, expedition_id);
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
UPDATE expeditions SET add_replay_on_join = {} WHERE id = {};
|
||||||
|
), add_on_join, expedition_id);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionDatabase::AddLockoutDuration(const std::vector<ExpeditionMember>& members,
|
||||||
|
const ExpeditionLockoutTimer& lockout, int seconds)
|
||||||
|
{
|
||||||
|
LogExpeditionsDetail(
|
||||||
|
"Adding duration [{}] seconds to members lockouts [{}]:[{}]",
|
||||||
|
seconds, lockout.GetExpeditionName(), lockout.GetEventName());
|
||||||
|
|
||||||
|
std::string insert_values;
|
||||||
|
for (const auto& member : members)
|
||||||
|
{
|
||||||
|
fmt::format_to(std::back_inserter(insert_values),
|
||||||
|
"({}, FROM_UNIXTIME({}), {}, '{}', '{}', '{}'),",
|
||||||
|
member.char_id,
|
||||||
|
lockout.GetExpireTime(),
|
||||||
|
lockout.GetDuration(),
|
||||||
|
lockout.GetExpeditionUUID(),
|
||||||
|
EscapeString(lockout.GetExpeditionName()),
|
||||||
|
EscapeString(lockout.GetEventName())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!insert_values.empty())
|
||||||
|
{
|
||||||
|
insert_values.pop_back(); // trailing comma
|
||||||
|
|
||||||
|
auto query = fmt::format(SQL(
|
||||||
|
INSERT INTO character_expedition_lockouts
|
||||||
|
(character_id, expire_time, duration, from_expedition_uuid, expedition_name, event_name)
|
||||||
|
VALUES {}
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
from_expedition_uuid = VALUES(from_expedition_uuid),
|
||||||
|
expire_time = DATE_ADD(expire_time, INTERVAL {} SECOND),
|
||||||
|
duration = GREATEST(0, CAST(duration AS SIGNED) + {});
|
||||||
|
), insert_values, seconds, seconds);
|
||||||
|
|
||||||
|
database.QueryDatabase(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
111
zone/expedition_database.h
Normal file
111
zone/expedition_database.h
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXPEDITION_DATABASE_H
|
||||||
|
#define EXPEDITION_DATABASE_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Expedition;
|
||||||
|
class ExpeditionLockoutTimer;
|
||||||
|
struct ExpeditionMember;
|
||||||
|
class MySQLRequestResult;
|
||||||
|
|
||||||
|
namespace ExpeditionDatabase
|
||||||
|
{
|
||||||
|
uint32_t InsertExpedition(
|
||||||
|
const std::string& uuid, uint32_t instance_id, const std::string& expedition_name,
|
||||||
|
uint32_t leader_id, uint32_t min_players, uint32_t max_players);
|
||||||
|
std::string LoadExpeditionsSelectQuery();
|
||||||
|
MySQLRequestResult LoadExpedition(uint32_t expedition_id);
|
||||||
|
MySQLRequestResult LoadAllExpeditions();
|
||||||
|
MySQLRequestResult LoadMembersForCreateRequest(
|
||||||
|
const std::vector<std::string>& character_names, const std::string& expedition_name);
|
||||||
|
std::vector<ExpeditionLockoutTimer> LoadCharacterLockouts(uint32_t character_id);
|
||||||
|
std::vector<ExpeditionLockoutTimer> LoadCharacterLockouts(uint32_t character_id,
|
||||||
|
const std::string& expedition_name);
|
||||||
|
std::unordered_map<uint32_t, std::unordered_map<std::string, ExpeditionLockoutTimer>>
|
||||||
|
LoadMultipleExpeditionLockouts(const std::vector<uint32_t>& expedition_ids);
|
||||||
|
void DeleteAllMembers(uint32_t expedition_id);
|
||||||
|
void DeleteMember(uint32_t expedition_id, uint32_t character_id);
|
||||||
|
void DeleteAllCharacterLockouts(uint32_t character_id);
|
||||||
|
void DeleteAllCharacterLockouts(uint32_t character_id, const std::string& expedition_name);
|
||||||
|
void DeleteCharacterLockout(uint32_t character_id, const std::string& expedition_name,
|
||||||
|
const std::string& event_name);
|
||||||
|
void DeleteLockout(uint32_t expedition_id, const std::string& event_name);
|
||||||
|
void DeleteMembersLockout(const std::vector<ExpeditionMember>& members,
|
||||||
|
const std::string& expedition_name, const std::string& event_name);
|
||||||
|
uint32_t GetExpeditionIDFromCharacterID(uint32_t character_id);
|
||||||
|
uint32_t GetMemberCount(uint32_t expedition_id);
|
||||||
|
bool HasMember(uint32_t expedition_id, uint32_t character_id);
|
||||||
|
void InsertCharacterLockouts(uint32_t character_id,
|
||||||
|
const std::vector<ExpeditionLockoutTimer>& lockouts);
|
||||||
|
void InsertMembersLockout(const std::vector<ExpeditionMember>& members,
|
||||||
|
const ExpeditionLockoutTimer& lockout);
|
||||||
|
void InsertLockout(uint32_t expedition_id, const ExpeditionLockoutTimer& lockout);
|
||||||
|
void InsertLockouts(uint32_t expedition_id,
|
||||||
|
const std::unordered_map<std::string, ExpeditionLockoutTimer>& lockouts);
|
||||||
|
void InsertMember(uint32_t expedition_id, uint32_t character_id);
|
||||||
|
void InsertMembers(uint32_t expedition_id, const std::vector<ExpeditionMember>& members);
|
||||||
|
void UpdateLockState(uint32_t expedition_id, bool is_locked);
|
||||||
|
void UpdateReplayLockoutOnJoin(uint32_t expedition_id, bool add_on_join);
|
||||||
|
void AddLockoutDuration(const std::vector<ExpeditionMember>& members,
|
||||||
|
const ExpeditionLockoutTimer& lockout, int seconds);
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace LoadExpeditionColumns
|
||||||
|
{
|
||||||
|
enum eLoadExpeditionColumns
|
||||||
|
{
|
||||||
|
id = 0,
|
||||||
|
uuid,
|
||||||
|
dz_id,
|
||||||
|
expedition_name,
|
||||||
|
leader_id,
|
||||||
|
min_players,
|
||||||
|
max_players,
|
||||||
|
add_replay_on_join,
|
||||||
|
is_locked,
|
||||||
|
leader_name,
|
||||||
|
member_id,
|
||||||
|
member_name
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace LoadMembersForCreateRequestColumns
|
||||||
|
{
|
||||||
|
enum eLoadMembersForCreateRequestColumns
|
||||||
|
{
|
||||||
|
character_id = 0,
|
||||||
|
character_name,
|
||||||
|
character_expedition_id,
|
||||||
|
lockout_uuid,
|
||||||
|
lockout_expire_time,
|
||||||
|
lockout_duration,
|
||||||
|
lockout_event_name
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
101
zone/expedition_lockout_timer.cpp
Normal file
101
zone/expedition_lockout_timer.cpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "expedition_lockout_timer.h"
|
||||||
|
#include "../common/string_util.h"
|
||||||
|
#include "../common/rulesys.h"
|
||||||
|
#include "../common/util/uuid.h"
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
const char* const DZ_REPLAY_TIMER_NAME = "Replay Timer"; // see December 14, 2016 patch notes
|
||||||
|
|
||||||
|
ExpeditionLockoutTimer::ExpeditionLockoutTimer(
|
||||||
|
const std::string& expedition_uuid, const std::string& expedition_name,
|
||||||
|
const std::string& event_name, uint64_t expire_time, uint32_t duration
|
||||||
|
) :
|
||||||
|
m_expedition_uuid(expedition_uuid),
|
||||||
|
m_expedition_name(expedition_name),
|
||||||
|
m_event_name(event_name),
|
||||||
|
m_expire_time(std::chrono::system_clock::from_time_t(expire_time)),
|
||||||
|
m_duration(duration)
|
||||||
|
{
|
||||||
|
if (event_name == DZ_REPLAY_TIMER_NAME)
|
||||||
|
{
|
||||||
|
m_is_replay_timer = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpeditionLockoutTimer ExpeditionLockoutTimer::CreateLockout(
|
||||||
|
const std::string& expedition_name, const std::string& event_name, uint32_t seconds, std::string uuid)
|
||||||
|
{
|
||||||
|
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||||
|
|
||||||
|
if (uuid.empty())
|
||||||
|
{
|
||||||
|
uuid = EQ::Util::UUID::Generate().ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpeditionLockoutTimer lockout{uuid, expedition_name, event_name, 0, seconds};
|
||||||
|
lockout.Reset(); // sets expire time
|
||||||
|
return lockout;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ExpeditionLockoutTimer::GetSecondsRemaining() const
|
||||||
|
{
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
if (m_expire_time > now)
|
||||||
|
{
|
||||||
|
auto remaining = m_expire_time - now;
|
||||||
|
return static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(remaining).count());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpeditionLockoutTimer::DaysHoursMinutes ExpeditionLockoutTimer::GetDaysHoursMinutesRemaining() const
|
||||||
|
{
|
||||||
|
auto seconds = GetSecondsRemaining();
|
||||||
|
return ExpeditionLockoutTimer::DaysHoursMinutes{
|
||||||
|
fmt::format_int(seconds / 86400).str(), // days
|
||||||
|
fmt::format_int((seconds / 3600) % 24).str(), // hours
|
||||||
|
fmt::format_int((seconds / 60) % 60).str() // minutes
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExpeditionLockoutTimer::IsSameLockout(const ExpeditionLockoutTimer& compare_lockout) const
|
||||||
|
{
|
||||||
|
return compare_lockout.IsSameLockout(GetExpeditionName(), GetEventName());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExpeditionLockoutTimer::IsSameLockout(
|
||||||
|
const std::string& expedition_name, const std::string& event_name) const
|
||||||
|
{
|
||||||
|
return GetExpeditionName() == expedition_name && GetEventName() == event_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionLockoutTimer::AddLockoutTime(int seconds)
|
||||||
|
{
|
||||||
|
seconds = static_cast<uint32_t>(seconds * RuleR(Expedition, LockoutDurationMultiplier));
|
||||||
|
|
||||||
|
auto new_duration = std::max(0, static_cast<int>(m_duration.count()) + seconds);
|
||||||
|
|
||||||
|
auto start_time = m_expire_time - m_duration;
|
||||||
|
m_duration = std::chrono::seconds(new_duration);
|
||||||
|
m_expire_time = start_time + m_duration;
|
||||||
|
}
|
||||||
76
zone/expedition_lockout_timer.h
Normal file
76
zone/expedition_lockout_timer.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXPEDITION_LOCKOUT_TIMER_H
|
||||||
|
#define EXPEDITION_LOCKOUT_TIMER_H
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
extern const char* const DZ_REPLAY_TIMER_NAME;
|
||||||
|
|
||||||
|
class ExpeditionLockoutTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExpeditionLockoutTimer() = default;
|
||||||
|
ExpeditionLockoutTimer(
|
||||||
|
const std::string& expedition_uuid, const std::string& expedition_name,
|
||||||
|
const std::string& event_name, uint64_t expire_time, uint32_t duration);
|
||||||
|
|
||||||
|
static ExpeditionLockoutTimer CreateLockout(
|
||||||
|
const std::string& expedition_name, const std::string& event_name,
|
||||||
|
uint32_t seconds, std::string uuid = {});
|
||||||
|
|
||||||
|
struct DaysHoursMinutes
|
||||||
|
{
|
||||||
|
std::string days;
|
||||||
|
std::string hours;
|
||||||
|
std::string mins;
|
||||||
|
};
|
||||||
|
|
||||||
|
void AddLockoutTime(int seconds);
|
||||||
|
uint32_t GetDuration() const { return static_cast<uint32_t>(m_duration.count()); }
|
||||||
|
uint64_t GetExpireTime() const { return std::chrono::system_clock::to_time_t(m_expire_time); }
|
||||||
|
uint64_t GetStartTime() const { return std::chrono::system_clock::to_time_t(m_expire_time - m_duration); }
|
||||||
|
uint32_t GetSecondsRemaining() const;
|
||||||
|
DaysHoursMinutes GetDaysHoursMinutesRemaining() const;
|
||||||
|
const std::string& GetExpeditionName() const { return m_expedition_name; }
|
||||||
|
const std::string& GetExpeditionUUID() const { return m_expedition_uuid; }
|
||||||
|
const std::string& GetEventName() const { return m_event_name; }
|
||||||
|
bool IsExpired() const { return GetSecondsRemaining() == 0; }
|
||||||
|
bool IsFromExpedition(const std::string& uuid) const { return uuid == m_expedition_uuid; }
|
||||||
|
bool IsReplayTimer() const { return m_is_replay_timer; }
|
||||||
|
bool IsSameLockout(const ExpeditionLockoutTimer& compare_lockout) const;
|
||||||
|
bool IsSameLockout(const std::string& expedition_name, const std::string& event_name) const;
|
||||||
|
void Reset() { m_expire_time = std::chrono::system_clock::now() + m_duration; }
|
||||||
|
void SetDuration(uint32_t seconds) { m_duration = std::chrono::seconds(seconds); }
|
||||||
|
void SetExpireTime(uint64_t expire_time) { m_expire_time = std::chrono::system_clock::from_time_t(expire_time); }
|
||||||
|
void SetUUID(const std::string& uuid) { m_expedition_uuid = uuid; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_is_replay_timer = false;
|
||||||
|
std::string m_expedition_uuid; // expedition received in
|
||||||
|
std::string m_expedition_name;
|
||||||
|
std::string m_event_name;
|
||||||
|
std::chrono::seconds m_duration;
|
||||||
|
std::chrono::time_point<std::chrono::system_clock> m_expire_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
397
zone/expedition_request.cpp
Normal file
397
zone/expedition_request.cpp
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "expedition_request.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "expedition.h"
|
||||||
|
#include "expedition_database.h"
|
||||||
|
#include "expedition_lockout_timer.h"
|
||||||
|
#include "groups.h"
|
||||||
|
#include "raids.h"
|
||||||
|
#include "string_ids.h"
|
||||||
|
#include "worldserver.h"
|
||||||
|
|
||||||
|
extern WorldServer worldserver;
|
||||||
|
|
||||||
|
constexpr char SystemName[] = "expedition";
|
||||||
|
|
||||||
|
struct ExpeditionRequestConflict
|
||||||
|
{
|
||||||
|
std::string character_name;
|
||||||
|
ExpeditionLockoutTimer lockout;
|
||||||
|
};
|
||||||
|
|
||||||
|
ExpeditionRequest::ExpeditionRequest(
|
||||||
|
std::string expedition_name, uint32_t min_players, uint32_t max_players, bool disable_messages
|
||||||
|
) :
|
||||||
|
m_expedition_name(expedition_name),
|
||||||
|
m_min_players(min_players),
|
||||||
|
m_max_players(max_players),
|
||||||
|
m_disable_messages(disable_messages)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExpeditionRequest::Validate(Client* requester)
|
||||||
|
{
|
||||||
|
m_requester = requester;
|
||||||
|
if (!m_requester)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// a message is sent to leader for every member that fails a requirement
|
||||||
|
|
||||||
|
BenchTimer benchmark;
|
||||||
|
|
||||||
|
bool requirements_met = false;
|
||||||
|
|
||||||
|
Raid* raid = m_requester->GetRaid();
|
||||||
|
Group* group = m_requester->GetGroup();
|
||||||
|
if (raid)
|
||||||
|
{
|
||||||
|
requirements_met = CanRaidRequest(raid);
|
||||||
|
}
|
||||||
|
else if (group)
|
||||||
|
{
|
||||||
|
requirements_met = CanGroupRequest(group);
|
||||||
|
}
|
||||||
|
else // solo request
|
||||||
|
{
|
||||||
|
m_leader = m_requester;
|
||||||
|
m_leader_id = m_requester->CharacterID();
|
||||||
|
m_leader_name = m_requester->GetName();
|
||||||
|
requirements_met = CanMembersJoin({m_leader_name});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto elapsed = benchmark.elapsed();
|
||||||
|
LogExpeditions("Create validation for [{}] members took [{}s]", m_members.size(), elapsed);
|
||||||
|
|
||||||
|
return requirements_met;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExpeditionRequest::CanRaidRequest(Raid* raid)
|
||||||
|
{
|
||||||
|
m_leader = raid->GetLeader();
|
||||||
|
m_leader_name = raid->leadername;
|
||||||
|
m_leader_id = m_leader ? m_leader->CharacterID() : database.GetCharacterID(raid->leadername);
|
||||||
|
|
||||||
|
// live (as of September 16, 2020) supports creation even if raid count exceeds
|
||||||
|
// expedition max. members are added up to the max ordered by group number.
|
||||||
|
auto raid_members = raid->GetMembers();
|
||||||
|
|
||||||
|
if (raid_members.size() > m_max_players)
|
||||||
|
{
|
||||||
|
// stable_sort not needed, order within a raid group may not be what is displayed
|
||||||
|
std::sort(raid_members.begin(), raid_members.end(),
|
||||||
|
[&](const RaidMember& lhs, const RaidMember& rhs) {
|
||||||
|
if (m_leader_name == lhs.membername) { // leader always added first
|
||||||
|
return true;
|
||||||
|
} else if (m_leader_name == rhs.membername) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return lhs.GroupNumber < rhs.GroupNumber;
|
||||||
|
});
|
||||||
|
|
||||||
|
m_not_all_added_msg = fmt::format(CREATE_NOT_ALL_ADDED, "raid", SystemName,
|
||||||
|
SystemName, m_max_players, "raid", raid_members.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// live still performs conflict checks for all members even those beyond max
|
||||||
|
std::vector<std::string> member_names;
|
||||||
|
for (int i = 0; i < raid_members.size(); ++i)
|
||||||
|
{
|
||||||
|
member_names.emplace_back(raid_members[i].membername);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CanMembersJoin(member_names);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExpeditionRequest::CanGroupRequest(Group* group)
|
||||||
|
{
|
||||||
|
m_leader = nullptr;
|
||||||
|
if (group->GetLeader() && group->GetLeader()->IsClient())
|
||||||
|
{
|
||||||
|
m_leader = group->GetLeader()->CastToClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group::GetLeaderName() is broken if group formed across zones, ask database instead
|
||||||
|
m_leader_name = m_leader ? m_leader->GetName() : GetGroupLeaderName(group->GetID()); // group->GetLeaderName();
|
||||||
|
m_leader_id = m_leader ? m_leader->CharacterID() : database.GetCharacterID(m_leader_name.c_str());
|
||||||
|
|
||||||
|
std::vector<std::string> member_names;
|
||||||
|
member_names.emplace_back(m_leader_name); // leader always added first
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_GROUP_MEMBERS; ++i)
|
||||||
|
{
|
||||||
|
if (group->membername[i][0] && m_leader_name != group->membername[i])
|
||||||
|
{
|
||||||
|
member_names.emplace_back(group->membername[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (member_names.size() > m_max_players)
|
||||||
|
{
|
||||||
|
m_not_all_added_msg = fmt::format(CREATE_NOT_ALL_ADDED, "group", SystemName,
|
||||||
|
SystemName, m_max_players, "group", member_names.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return CanMembersJoin(member_names);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ExpeditionRequest::GetGroupLeaderName(uint32_t group_id)
|
||||||
|
{
|
||||||
|
char leader_name_buffer[64] = { 0 };
|
||||||
|
database.GetGroupLeadershipInfo(group_id, leader_name_buffer);
|
||||||
|
return std::string(leader_name_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExpeditionRequest::CanMembersJoin(const std::vector<std::string>& member_names)
|
||||||
|
{
|
||||||
|
if (member_names.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool requirements_met = true;
|
||||||
|
|
||||||
|
if (CheckMembersForConflicts(member_names))
|
||||||
|
{
|
||||||
|
requirements_met = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// live only checks player count requirement after other expensive checks pass (?)
|
||||||
|
// maybe it's done intentionally as a way to preview lockout conflicts
|
||||||
|
if (requirements_met)
|
||||||
|
{
|
||||||
|
requirements_met = IsPlayerCountValidated();
|
||||||
|
}
|
||||||
|
|
||||||
|
return requirements_met;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExpeditionRequest::LoadLeaderLockouts()
|
||||||
|
{
|
||||||
|
// leader's lockouts are used to check member conflicts and later stored in expedition
|
||||||
|
auto lockouts = ExpeditionDatabase::LoadCharacterLockouts(m_leader_id, m_expedition_name);
|
||||||
|
|
||||||
|
for (auto& lockout : lockouts)
|
||||||
|
{
|
||||||
|
if (!lockout.IsExpired())
|
||||||
|
{
|
||||||
|
m_lockouts.emplace(lockout.GetEventName(), lockout);
|
||||||
|
|
||||||
|
// on live if leader has a replay lockout it never bothers checking for event conflicts
|
||||||
|
if (m_check_event_lockouts && lockout.IsReplayTimer())
|
||||||
|
{
|
||||||
|
m_check_event_lockouts = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExpeditionRequest::CheckMembersForConflicts(const std::vector<std::string>& member_names)
|
||||||
|
{
|
||||||
|
// load data for each member and compare with leader lockouts
|
||||||
|
auto results = ExpeditionDatabase::LoadMembersForCreateRequest(member_names, m_expedition_name);
|
||||||
|
if (!results.Success() || !LoadLeaderLockouts())
|
||||||
|
{
|
||||||
|
LogExpeditions("Failed to load data to verify members for expedition request");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_solo = (member_names.size() == 1);
|
||||||
|
bool has_conflicts = false;
|
||||||
|
|
||||||
|
using col = LoadMembersForCreateRequestColumns::eLoadMembersForCreateRequestColumns;
|
||||||
|
|
||||||
|
std::vector<ExpeditionRequestConflict> member_lockout_conflicts;
|
||||||
|
|
||||||
|
uint32_t last_character_id = 0;
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row)
|
||||||
|
{
|
||||||
|
uint32_t character_id = std::strtoul(row[col::character_id], nullptr, 10);
|
||||||
|
std::string character_name = row[col::character_name];
|
||||||
|
bool has_expedition = (row[col::character_expedition_id] != nullptr);
|
||||||
|
|
||||||
|
if (character_id != last_character_id)
|
||||||
|
{
|
||||||
|
// defaults to online status, if offline group members implemented this needs to change
|
||||||
|
m_members.emplace_back(character_id, character_name);
|
||||||
|
|
||||||
|
// process event lockout conflict messages from the previous character
|
||||||
|
for (const auto& member_lockout : member_lockout_conflicts)
|
||||||
|
{
|
||||||
|
SendLeaderMemberEventLockout(member_lockout.character_name, member_lockout.lockout);
|
||||||
|
}
|
||||||
|
member_lockout_conflicts.clear();
|
||||||
|
|
||||||
|
if (has_expedition)
|
||||||
|
{
|
||||||
|
has_conflicts = true;
|
||||||
|
SendLeaderMemberInExpedition(character_name, is_solo);
|
||||||
|
|
||||||
|
// solo requests break out early if requester in an expedition
|
||||||
|
if (is_solo)
|
||||||
|
{
|
||||||
|
return has_conflicts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
last_character_id = character_id;
|
||||||
|
|
||||||
|
// compare member lockouts with leader lockouts
|
||||||
|
if (row[col::lockout_uuid]) // lockout results may be null
|
||||||
|
{
|
||||||
|
auto expire_time = strtoull(row[col::lockout_expire_time], nullptr, 10);
|
||||||
|
uint32_t duration = strtoul(row[col::lockout_duration], nullptr, 10);
|
||||||
|
|
||||||
|
ExpeditionLockoutTimer lockout{
|
||||||
|
row[col::lockout_uuid], m_expedition_name, row[col::lockout_event_name], expire_time, duration
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!lockout.IsExpired())
|
||||||
|
{
|
||||||
|
if (lockout.IsReplayTimer())
|
||||||
|
{
|
||||||
|
// replay timer conflict messages always show up before event conflicts
|
||||||
|
has_conflicts = true;
|
||||||
|
SendLeaderMemberReplayLockout(character_name, lockout, is_solo);
|
||||||
|
}
|
||||||
|
else if (m_check_event_lockouts && character_id != m_leader_id)
|
||||||
|
{
|
||||||
|
if (m_lockouts.find(lockout.GetEventName()) == m_lockouts.end())
|
||||||
|
{
|
||||||
|
// leader doesn't have this lockout. queue instead of messaging
|
||||||
|
// now so message comes after any replay lockout messages
|
||||||
|
has_conflicts = true;
|
||||||
|
member_lockout_conflicts.push_back({character_name, lockout});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// event lockout messages for last processed character
|
||||||
|
for (const auto& member_lockout : member_lockout_conflicts)
|
||||||
|
{
|
||||||
|
SendLeaderMemberEventLockout(member_lockout.character_name, member_lockout.lockout);
|
||||||
|
}
|
||||||
|
|
||||||
|
return has_conflicts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionRequest::SendLeaderMessage(
|
||||||
|
uint16_t chat_type, uint32_t string_id, const std::initializer_list<std::string>& args)
|
||||||
|
{
|
||||||
|
if (!m_disable_messages)
|
||||||
|
{
|
||||||
|
Client::SendCrossZoneMessageString(m_leader, m_leader_name, chat_type, string_id, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionRequest::SendLeaderMemberInExpedition(const std::string& member_name, bool is_solo)
|
||||||
|
{
|
||||||
|
if (m_disable_messages)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_solo)
|
||||||
|
{
|
||||||
|
SendLeaderMessage(Chat::Red, EXPEDITION_YOU_BELONG);
|
||||||
|
}
|
||||||
|
else if (m_requester)
|
||||||
|
{
|
||||||
|
std::string message = fmt::format(EXPEDITION_OTHER_BELONGS, m_requester->GetName(), member_name);
|
||||||
|
Client::SendCrossZoneMessage(m_leader, m_leader_name, Chat::Red, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionRequest::SendLeaderMemberReplayLockout(
|
||||||
|
const std::string& member_name, const ExpeditionLockoutTimer& lockout, bool is_solo)
|
||||||
|
{
|
||||||
|
if (m_disable_messages)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto time_remaining = lockout.GetDaysHoursMinutesRemaining();
|
||||||
|
if (is_solo)
|
||||||
|
{
|
||||||
|
SendLeaderMessage(Chat::Red, EXPEDITION_YOU_PLAYED_HERE, {
|
||||||
|
time_remaining.days, time_remaining.hours, time_remaining.mins
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendLeaderMessage(Chat::Red, EXPEDITION_REPLAY_TIMER, {
|
||||||
|
member_name, time_remaining.days, time_remaining.hours, time_remaining.mins
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpeditionRequest::SendLeaderMemberEventLockout(
|
||||||
|
const std::string& member_name, const ExpeditionLockoutTimer& lockout)
|
||||||
|
{
|
||||||
|
if (m_disable_messages)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto time_remaining = lockout.GetDaysHoursMinutesRemaining();
|
||||||
|
SendLeaderMessage(Chat::Red, EXPEDITION_EVENT_TIMER, {
|
||||||
|
member_name,
|
||||||
|
lockout.GetEventName(),
|
||||||
|
time_remaining.days,
|
||||||
|
time_remaining.hours,
|
||||||
|
time_remaining.mins,
|
||||||
|
lockout.GetEventName()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ExpeditionRequest::IsPlayerCountValidated()
|
||||||
|
{
|
||||||
|
// note: offline group members count towards requirement but not added to expedition
|
||||||
|
bool requirements_met = true;
|
||||||
|
|
||||||
|
auto bypass_status = RuleI(Expedition, MinStatusToBypassPlayerCountRequirements);
|
||||||
|
auto gm_bypass = (m_requester && m_requester->GetGM() && m_requester->Admin() >= bypass_status);
|
||||||
|
|
||||||
|
if (m_members.size() > m_max_players)
|
||||||
|
{
|
||||||
|
// members were sorted at start, truncate after conflict checks to act like live
|
||||||
|
m_members.resize(m_max_players);
|
||||||
|
}
|
||||||
|
else if (!gm_bypass && m_members.size() < m_min_players)
|
||||||
|
{
|
||||||
|
requirements_met = false;
|
||||||
|
|
||||||
|
SendLeaderMessage(Chat::System, REQUIRED_PLAYER_COUNT, {
|
||||||
|
fmt::format_int(m_members.size()).str(),
|
||||||
|
fmt::format_int(m_min_players).str(),
|
||||||
|
fmt::format_int(m_max_players).str()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return requirements_met;
|
||||||
|
}
|
||||||
83
zone/expedition_request.h
Normal file
83
zone/expedition_request.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXPEDITION_REQUEST_H
|
||||||
|
#define EXPEDITION_REQUEST_H
|
||||||
|
|
||||||
|
#include "expedition.h"
|
||||||
|
#include "expedition_lockout_timer.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class Client;
|
||||||
|
class Group;
|
||||||
|
class MySQLRequestResult;
|
||||||
|
class Raid;
|
||||||
|
class ServerPacket;
|
||||||
|
|
||||||
|
class ExpeditionRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExpeditionRequest(
|
||||||
|
std::string expedition_name, uint32_t min_players, uint32_t max_players,
|
||||||
|
bool disable_messages = false);
|
||||||
|
|
||||||
|
bool Validate(Client* requester);
|
||||||
|
|
||||||
|
const std::string& GetExpeditionName() const { return m_expedition_name; }
|
||||||
|
Client* GetLeaderClient() const { return m_leader; }
|
||||||
|
uint32_t GetLeaderID() const { return m_leader_id; }
|
||||||
|
const std::string& GetLeaderName() const { return m_leader_name; }
|
||||||
|
const std::string& GetNotAllAddedMessage() const { return m_not_all_added_msg; }
|
||||||
|
uint32_t GetMinPlayers() const { return m_min_players; }
|
||||||
|
uint32_t GetMaxPlayers() const { return m_max_players; }
|
||||||
|
std::vector<ExpeditionMember> GetMembers() const { return m_members; }
|
||||||
|
std::unordered_map<std::string, ExpeditionLockoutTimer> GetLockouts() const { return m_lockouts; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool CanMembersJoin(const std::vector<std::string>& member_names);
|
||||||
|
bool CanRaidRequest(Raid* raid);
|
||||||
|
bool CanGroupRequest(Group* group);
|
||||||
|
bool CheckMembersForConflicts(const std::vector<std::string>& member_names);
|
||||||
|
std::string GetGroupLeaderName(uint32_t group_id);
|
||||||
|
bool IsPlayerCountValidated();
|
||||||
|
bool LoadLeaderLockouts();
|
||||||
|
void SendLeaderMemberInExpedition(const std::string& member_name, bool is_solo);
|
||||||
|
void SendLeaderMemberReplayLockout(const std::string& member_name, const ExpeditionLockoutTimer& lockout, bool is_solo);
|
||||||
|
void SendLeaderMemberEventLockout(const std::string& member_name, const ExpeditionLockoutTimer& lockout);
|
||||||
|
void SendLeaderMessage(uint16_t chat_type, uint32_t string_id, const std::initializer_list<std::string>& args = {});
|
||||||
|
|
||||||
|
Client* m_requester = nullptr;
|
||||||
|
Client* m_leader = nullptr;
|
||||||
|
uint32_t m_leader_id = 0;
|
||||||
|
uint32_t m_min_players = 0;
|
||||||
|
uint32_t m_max_players = 0;
|
||||||
|
bool m_check_event_lockouts = true;
|
||||||
|
bool m_disable_messages = false;
|
||||||
|
std::string m_expedition_name;
|
||||||
|
std::string m_leader_name;
|
||||||
|
std::string m_not_all_added_msg;
|
||||||
|
std::vector<ExpeditionMember> m_members;
|
||||||
|
std::unordered_map<std::string, ExpeditionLockoutTimer> m_lockouts;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
138
zone/groups.cpp
138
zone/groups.cpp
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "../common/global_define.h"
|
#include "../common/global_define.h"
|
||||||
#include "../common/eqemu_logsys.h"
|
#include "../common/eqemu_logsys.h"
|
||||||
|
#include "expedition.h"
|
||||||
#include "masterentity.h"
|
#include "masterentity.h"
|
||||||
#include "npc_ai.h"
|
#include "npc_ai.h"
|
||||||
#include "../common/packet_functions.h"
|
#include "../common/packet_functions.h"
|
||||||
@ -58,9 +59,13 @@ Group::Group(uint32 gid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(gid != 0) {
|
if(gid != 0) {
|
||||||
if(!LearnMembers())
|
if(!LearnMembers()) {
|
||||||
SetID(0);
|
SetID(0);
|
||||||
}
|
}
|
||||||
|
if(GetLeader() != nullptr) {
|
||||||
|
SetOldLeaderName(GetLeaderName());
|
||||||
|
}
|
||||||
|
}
|
||||||
for(int i = 0; i < MAX_MARKED_NPCS; ++i)
|
for(int i = 0; i < MAX_MARKED_NPCS; ++i)
|
||||||
MarkedNPCs[i] = 0;
|
MarkedNPCs[i] = 0;
|
||||||
|
|
||||||
@ -77,6 +82,8 @@ Group::Group(Mob* leader)
|
|||||||
members[0] = leader;
|
members[0] = leader;
|
||||||
leader->SetGrouped(true);
|
leader->SetGrouped(true);
|
||||||
SetLeader(leader);
|
SetLeader(leader);
|
||||||
|
SetOldLeaderName(leader->GetName());
|
||||||
|
Log(Logs::Detail, Logs::Group, "Group:Group() Setting OldLeader to: %s and Leader to: %s", GetOldLeaderName(), leader->GetName());
|
||||||
AssistTargetID = 0;
|
AssistTargetID = 0;
|
||||||
TankTargetID = 0;
|
TankTargetID = 0;
|
||||||
PullerTargetID = 0;
|
PullerTargetID = 0;
|
||||||
@ -603,39 +610,61 @@ void Group::SendGroupJoinOOZ(Mob* NewMember) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Group::DelMemberOOZ(const char *Name) {
|
bool Group::DelMemberOOZ(const char *Name, bool checkleader) {
|
||||||
|
|
||||||
if (!Name) return false;
|
if (!Name) return false;
|
||||||
|
|
||||||
|
bool removed = false;
|
||||||
// If a member out of zone has disbanded, clear out their name.
|
// If a member out of zone has disbanded, clear out their name.
|
||||||
//
|
|
||||||
for (unsigned int i = 0; i < MAX_GROUP_MEMBERS; i++) {
|
for (unsigned int i = 0; i < MAX_GROUP_MEMBERS; i++) {
|
||||||
if(!strcasecmp(Name, membername[i]))
|
if (!strcasecmp(Name, membername[i])) {
|
||||||
// This shouldn't be called if the member is in this zone.
|
// This shouldn't be called if the member is in this zone.
|
||||||
if (!members[i]) {
|
if (!members[i]) {
|
||||||
if(!strncmp(GetLeaderName(), Name, 64))
|
if (!strncmp(GetLeaderName(), Name, 64)) {
|
||||||
{
|
|
||||||
//TODO: Transfer leadership if leader disbands OOZ.
|
//TODO: Transfer leadership if leader disbands OOZ.
|
||||||
UpdateGroupAAs();
|
UpdateGroupAAs();
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(membername[i], 0, 64);
|
if (GroupCount() < 3) {
|
||||||
MemberRoles[i] = 0;
|
|
||||||
if(GroupCount() < 3)
|
|
||||||
{
|
|
||||||
UnDelegateMarkNPC(NPCMarkerName.c_str());
|
UnDelegateMarkNPC(NPCMarkerName.c_str());
|
||||||
if (GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->ClientVersion() < EQ::versions::ClientVersion::SoD) {
|
if (GetLeader() && GetLeader()->IsClient() &&
|
||||||
|
GetLeader()->CastToClient()->ClientVersion() < EQ::versions::ClientVersion::SoD) {
|
||||||
UnDelegateMainAssist(MainAssistName.c_str());
|
UnDelegateMainAssist(MainAssistName.c_str());
|
||||||
}
|
}
|
||||||
ClearAllNPCMarks();
|
ClearAllNPCMarks();
|
||||||
}
|
}
|
||||||
if (Name == mentoree_name)
|
if (Name == mentoree_name) {
|
||||||
ClearGroupMentor();
|
ClearGroupMentor();
|
||||||
return true;
|
}
|
||||||
|
|
||||||
|
memset(membername[i], 0, 64);
|
||||||
|
MemberRoles[i] = 0;
|
||||||
|
removed = true;
|
||||||
|
Log(Logs::Detail, Logs::Group, "DelMemberOOZ: Removed Member: %s", Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if (GroupCount() < 2) {
|
||||||
|
DisbandGroup();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkleader) {
|
||||||
|
Log(Logs::Detail, Logs::Group, "DelMemberOOZ: Checking leader...");
|
||||||
|
if (strcmp(GetOldLeaderName(), Name) == 0 && GroupCount() >= 2) {
|
||||||
|
for (uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++) {
|
||||||
|
if (members[nl]) {
|
||||||
|
if (members[nl]->IsClient()) {
|
||||||
|
ChangeLeader(members[nl]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Group::DelMember(Mob* oldmember, bool ignoresender)
|
bool Group::DelMember(Mob* oldmember, bool ignoresender)
|
||||||
@ -645,16 +674,6 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: fix this shit
|
|
||||||
// okay, so there is code below that tries to handle this. It does not.
|
|
||||||
// So instead of figuring it out now, lets just disband the group so the client doesn't
|
|
||||||
// sit there with a broken group and there isn't any group leader shuffling going on
|
|
||||||
// since the code below doesn't work.
|
|
||||||
if (oldmember == GetLeader()) {
|
|
||||||
DisbandGroup();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++)
|
for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++)
|
||||||
{
|
{
|
||||||
if (members[i] == oldmember)
|
if (members[i] == oldmember)
|
||||||
@ -663,25 +682,22 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender)
|
|||||||
membername[i][0] = '\0';
|
membername[i][0] = '\0';
|
||||||
memset(membername[i],0,64);
|
memset(membername[i],0,64);
|
||||||
MemberRoles[i] = 0;
|
MemberRoles[i] = 0;
|
||||||
|
Log(Logs::Detail, Logs::Group, "DelMember: Removed Member: %s", oldmember->GetCleanName());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This may seem pointless but the case above does not cover the following situation:
|
if(GroupCount() < 2)
|
||||||
* Group has Leader a, member b, member c
|
|
||||||
* b and c are out of zone
|
|
||||||
* a disconnects/quits
|
|
||||||
* b or c zone back in and disconnects/quits
|
|
||||||
* a is still "leader" from GetLeader()'s perspective and will crash the zone when we DelMember(b)
|
|
||||||
* Ultimately we should think up a better solution to this.
|
|
||||||
*/
|
|
||||||
if(oldmember == GetLeader())
|
|
||||||
{
|
{
|
||||||
SetLeader(nullptr);
|
DisbandGroup();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//handle leader quitting group gracefully
|
// If the leader has quit and we have 2 or more players left in group, we want to first check the zone the old leader was in for a new leader.
|
||||||
if (oldmember == GetLeader() && GroupCount() >= 2)
|
// If a suitable replacement cannot be found, we need to go out of zone. If checkleader remains true after this method completes, another
|
||||||
|
// loop will be run in DelMemberOOZ.
|
||||||
|
bool checkleader = true;
|
||||||
|
if (strcmp(GetOldLeaderName(),oldmember->GetCleanName()) == 0 && GroupCount() >= 2)
|
||||||
{
|
{
|
||||||
for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++)
|
for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++)
|
||||||
{
|
{
|
||||||
@ -690,24 +706,20 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender)
|
|||||||
if (members[nl]->IsClient())
|
if (members[nl]->IsClient())
|
||||||
{
|
{
|
||||||
ChangeLeader(members[nl]);
|
ChangeLeader(members[nl]);
|
||||||
|
checkleader = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetLeaderName())
|
|
||||||
{
|
|
||||||
DisbandGroup();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct));
|
auto pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct));
|
||||||
ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer;
|
ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer;
|
||||||
gl->gid = GetID();
|
gl->gid = GetID();
|
||||||
gl->zoneid = zone->GetZoneID();
|
gl->zoneid = zone->GetZoneID();
|
||||||
gl->instance_id = zone->GetInstanceID();
|
gl->instance_id = zone->GetInstanceID();
|
||||||
strcpy(gl->member_name, oldmember->GetCleanName());
|
strcpy(gl->member_name, oldmember->GetCleanName());
|
||||||
|
gl->checkleader = checkleader;
|
||||||
worldserver.SendPacket(pack);
|
worldserver.SendPacket(pack);
|
||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
|
|
||||||
@ -799,6 +811,7 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender)
|
|||||||
Bot::UpdateGroupCastingRoles(this);
|
Bot::UpdateGroupCastingRoles(this);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
safe_delete(outapp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2329,17 +2342,16 @@ void Group::ChangeLeader(Mob* newleader)
|
|||||||
// this changes the current group leader, notifies other members, and updates leadship AA
|
// this changes the current group leader, notifies other members, and updates leadship AA
|
||||||
|
|
||||||
// if the new leader is invalid, do nothing
|
// if the new leader is invalid, do nothing
|
||||||
if (!newleader || !newleader->IsClient())
|
if (!newleader) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
Mob* oldleader = GetLeader();
|
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct));
|
auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct));
|
||||||
GroupJoin_Struct* gu = (GroupJoin_Struct*) outapp->pBuffer;
|
GroupJoin_Struct* gu = (GroupJoin_Struct*) outapp->pBuffer;
|
||||||
gu->action = groupActMakeLeader;
|
gu->action = groupActMakeLeader;
|
||||||
|
|
||||||
strcpy(gu->membername, newleader->GetName());
|
strcpy(gu->membername, newleader->GetName());
|
||||||
strcpy(gu->yourname, oldleader->GetName());
|
strcpy(gu->yourname, GetOldLeaderName());
|
||||||
SetLeader(newleader);
|
SetLeader(newleader);
|
||||||
database.SetGroupLeaderName(GetID(), newleader->GetName());
|
database.SetGroupLeaderName(GetID(), newleader->GetName());
|
||||||
UpdateGroupAAs();
|
UpdateGroupAAs();
|
||||||
@ -2351,9 +2363,22 @@ void Group::ChangeLeader(Mob* newleader)
|
|||||||
members[i]->CastToClient()->SendGroupLeaderChangePacket(newleader->GetName());
|
members[i]->CastToClient()->SendGroupLeaderChangePacket(newleader->GetName());
|
||||||
|
|
||||||
members[i]->CastToClient()->QueuePacket(outapp);
|
members[i]->CastToClient()->QueuePacket(outapp);
|
||||||
|
Log(Logs::Detail, Logs::Group, "ChangeLeader(): Local leader update packet sent to: %s .", members[i]->GetName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
|
|
||||||
|
Log(Logs::Detail, Logs::Group, "ChangeLeader(): Old Leader is: %s New leader is: %s", GetOldLeaderName(), newleader->GetName());
|
||||||
|
|
||||||
|
ServerPacket* pack = new ServerPacket(ServerOP_ChangeGroupLeader, sizeof(ServerGroupLeader_Struct));
|
||||||
|
ServerGroupLeader_Struct* fgu = (ServerGroupLeader_Struct*)pack->pBuffer;
|
||||||
|
fgu->zoneid = zone->GetZoneID();
|
||||||
|
fgu->gid = GetID();
|
||||||
|
strcpy(fgu->leader_name, newleader->GetName());
|
||||||
|
strcpy(fgu->oldleader_name, GetOldLeaderName());
|
||||||
|
worldserver.SendPacket(pack);
|
||||||
|
|
||||||
|
SetOldLeaderName(newleader->GetName());
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *Group::GetClientNameByIndex(uint8 index)
|
const char *Group::GetClientNameByIndex(uint8 index)
|
||||||
@ -2503,3 +2528,24 @@ void Group::QueueClients(Mob *sender, const EQApplicationPacket *app, bool ack_r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Group::DoesAnyMemberHaveExpeditionLockout(
|
||||||
|
const std::string& expedition_name, const std::string& event_name, int max_check_count)
|
||||||
|
{
|
||||||
|
if (max_check_count <= 0)
|
||||||
|
{
|
||||||
|
max_check_count = MAX_GROUP_MEMBERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_GROUP_MEMBERS && i < max_check_count; ++i)
|
||||||
|
{
|
||||||
|
if (membername[i][0])
|
||||||
|
{
|
||||||
|
if (Expedition::HasLockoutByCharacterName(membername[i], expedition_name, event_name))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@ -37,6 +37,8 @@ public:
|
|||||||
GroupIDConsumer() { id = 0; }
|
GroupIDConsumer() { id = 0; }
|
||||||
GroupIDConsumer(uint32 gid) { id = gid; }
|
GroupIDConsumer(uint32 gid) { id = gid; }
|
||||||
inline const uint32 GetID() const { return id; }
|
inline const uint32 GetID() const { return id; }
|
||||||
|
void SetOldLeaderName(const char* oldleader) { strcpy(oldleadername, oldleader); }
|
||||||
|
char* GetOldLeaderName() { return oldleadername; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class EntityList;
|
friend class EntityList;
|
||||||
@ -44,6 +46,7 @@ protected:
|
|||||||
inline void SetID(uint32 set_id) { id = set_id; }
|
inline void SetID(uint32 set_id) { id = set_id; }
|
||||||
private:
|
private:
|
||||||
uint32 id;
|
uint32 id;
|
||||||
|
char oldleadername[64]; // Keeps the previous leader name, so when the entity is destroyed we can still transfer leadership.
|
||||||
};
|
};
|
||||||
|
|
||||||
class Group : public GroupIDConsumer {
|
class Group : public GroupIDConsumer {
|
||||||
@ -58,6 +61,7 @@ public:
|
|||||||
void SendLeadershipAAUpdate();
|
void SendLeadershipAAUpdate();
|
||||||
void SendWorldGroup(uint32 zone_id,Mob* zoningmember);
|
void SendWorldGroup(uint32 zone_id,Mob* zoningmember);
|
||||||
bool DelMemberOOZ(const char *Name);
|
bool DelMemberOOZ(const char *Name);
|
||||||
|
bool DelMemberOOZ(const char *Name, bool checkleader);
|
||||||
bool DelMember(Mob* oldmember,bool ignoresender = false);
|
bool DelMember(Mob* oldmember,bool ignoresender = false);
|
||||||
void DisbandGroup(bool joinraid = false);
|
void DisbandGroup(bool joinraid = false);
|
||||||
void GetMemberList(std::list<Mob*>& member_list, bool clear_list = true);
|
void GetMemberList(std::list<Mob*>& member_list, bool clear_list = true);
|
||||||
@ -153,6 +157,8 @@ public:
|
|||||||
inline int GetMentorPercent() { return mentor_percent; }
|
inline int GetMentorPercent() { return mentor_percent; }
|
||||||
inline Client *GetMentoree() { return mentoree; }
|
inline Client *GetMentoree() { return mentoree; }
|
||||||
|
|
||||||
|
bool DoesAnyMemberHaveExpeditionLockout(const std::string& expedition_name, const std::string& event_name, int max_check_count = 0);
|
||||||
|
|
||||||
Mob* members[MAX_GROUP_MEMBERS];
|
Mob* members[MAX_GROUP_MEMBERS];
|
||||||
char membername[MAX_GROUP_MEMBERS][64];
|
char membername[MAX_GROUP_MEMBERS][64];
|
||||||
uint8 MemberRoles[MAX_GROUP_MEMBERS];
|
uint8 MemberRoles[MAX_GROUP_MEMBERS];
|
||||||
|
|||||||
@ -1154,10 +1154,35 @@ bool Client::AutoPutLootInInventory(EQ::ItemInstance& inst, bool try_worn, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if( i == EQ::invslot::slotPrimary && m_inv[EQ::invslot::slotSecondary] ) {
|
||||||
|
uint8 instrument = m_inv[EQ::invslot::slotSecondary]->GetItem()->ItemType;
|
||||||
|
if(
|
||||||
|
instrument == EQ::item::ItemTypeWindInstrument ||
|
||||||
|
instrument == EQ::item::ItemTypeStringedInstrument ||
|
||||||
|
instrument == EQ::item::ItemTypeBrassInstrument ||
|
||||||
|
instrument == EQ::item::ItemTypePercussionInstrument
|
||||||
|
) {
|
||||||
|
LogInventory("Cannot equip a primary item with [{}] already in the secondary.", m_inv[EQ::invslot::slotSecondary]->GetItem()->Name);
|
||||||
|
continue; // Do not auto-equip Primary when instrument is in Secondary
|
||||||
|
}
|
||||||
|
}
|
||||||
if (i == EQ::invslot::slotSecondary && m_inv[EQ::invslot::slotPrimary]) { // check to see if primary slot is a two hander
|
if (i == EQ::invslot::slotSecondary && m_inv[EQ::invslot::slotPrimary]) { // check to see if primary slot is a two hander
|
||||||
if (m_inv[EQ::invslot::slotPrimary]->GetItem()->IsType2HWeapon())
|
uint8 instrument = inst.GetItem()->ItemType;
|
||||||
|
if(
|
||||||
|
instrument == EQ::item::ItemTypeWindInstrument ||
|
||||||
|
instrument == EQ::item::ItemTypeStringedInstrument ||
|
||||||
|
instrument == EQ::item::ItemTypeBrassInstrument ||
|
||||||
|
instrument == EQ::item::ItemTypePercussionInstrument
|
||||||
|
) {
|
||||||
|
LogInventory("Cannot equip a secondary instrument with [{}] already in the primary.", m_inv[EQ::invslot::slotPrimary]->GetItem()->Name);
|
||||||
|
continue; // Do not auto-equip instrument in Secondary when Primary is equipped.
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 use = m_inv[EQ::invslot::slotPrimary]->GetItem()->ItemType;
|
||||||
|
if(use == EQ::item::ItemType2HSlash || use == EQ::item::ItemType2HBlunt || use == EQ::item::ItemType2HPiercing) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (i == EQ::invslot::slotSecondary && inst.IsWeapon() && !CanThisClassDualWield()) {
|
if (i == EQ::invslot::slotSecondary && inst.IsWeapon() && !CanThisClassDualWield()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1169,7 +1194,6 @@ bool Client::AutoPutLootInInventory(EQ::ItemInstance& inst, bool try_worn, bool
|
|||||||
if (worn_slot_material != EQ::textures::materialInvalid) {
|
if (worn_slot_material != EQ::textures::materialInvalid) {
|
||||||
SendWearChange(worn_slot_material);
|
SendWearChange(worn_slot_material);
|
||||||
}
|
}
|
||||||
|
|
||||||
parse->EventItem(EVENT_EQUIP_ITEM, this, &inst, nullptr, "", i);
|
parse->EventItem(EVENT_EQUIP_ITEM, this, &inst, nullptr, "", i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,11 @@
|
|||||||
#include <luabind/luabind.hpp>
|
#include <luabind/luabind.hpp>
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
#include "dynamiczone.h"
|
||||||
|
#include "expedition_lockout_timer.h"
|
||||||
|
#include "expedition_request.h"
|
||||||
#include "lua_client.h"
|
#include "lua_client.h"
|
||||||
|
#include "lua_expedition.h"
|
||||||
#include "lua_npc.h"
|
#include "lua_npc.h"
|
||||||
#include "lua_item.h"
|
#include "lua_item.h"
|
||||||
#include "lua_iteminst.h"
|
#include "lua_iteminst.h"
|
||||||
@ -130,6 +134,16 @@ void Lua_Client::SetBaseGender(int v) {
|
|||||||
self->SetBaseGender(v);
|
self->SetBaseGender(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Lua_Client::GetClassBitmask() {
|
||||||
|
Lua_Safe_Call_Int();
|
||||||
|
return GetPlayerClassBit(self->GetClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
int Lua_Client::GetRaceBitmask() {
|
||||||
|
Lua_Safe_Call_Int();
|
||||||
|
return GetPlayerRaceBit(self->GetBaseRace());
|
||||||
|
}
|
||||||
|
|
||||||
int Lua_Client::GetBaseFace() {
|
int Lua_Client::GetBaseFace() {
|
||||||
Lua_Safe_Call_Int();
|
Lua_Safe_Call_Int();
|
||||||
return self->GetBaseFace();
|
return self->GetBaseFace();
|
||||||
@ -325,6 +339,21 @@ uint32 Lua_Client::GetBindZoneID(int index) {
|
|||||||
return self->GetBindZoneID(index);
|
return self->GetBindZoneID(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Lua_Client::GetTargetRingX() {
|
||||||
|
Lua_Safe_Call_Real();
|
||||||
|
return self->GetTargetRingX();
|
||||||
|
}
|
||||||
|
|
||||||
|
float Lua_Client::GetTargetRingY() {
|
||||||
|
Lua_Safe_Call_Real();
|
||||||
|
return self->GetTargetRingY();
|
||||||
|
}
|
||||||
|
|
||||||
|
float Lua_Client::GetTargetRingZ() {
|
||||||
|
Lua_Safe_Call_Real();
|
||||||
|
return self->GetTargetRingZ();
|
||||||
|
}
|
||||||
|
|
||||||
void Lua_Client::MovePC(int zone, float x, float y, float z, float heading) {
|
void Lua_Client::MovePC(int zone, float x, float y, float z, float heading) {
|
||||||
Lua_Safe_Call_Void();
|
Lua_Safe_Call_Void();
|
||||||
self->MovePC(zone, x, y, z, heading);
|
self->MovePC(zone, x, y, z, heading);
|
||||||
@ -605,6 +634,132 @@ int Lua_Client::MemmedCount() {
|
|||||||
return self->MemmedCount();
|
return self->MemmedCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
luabind::object Lua_Client::GetLearnableDisciplines(lua_State* L) {
|
||||||
|
auto lua_table = luabind::newtable(L);
|
||||||
|
if (d_) {
|
||||||
|
auto self = reinterpret_cast<NativeType*>(d_);
|
||||||
|
auto learnable_disciplines = self->GetLearnableDisciplines();
|
||||||
|
int index = 0;
|
||||||
|
for (auto spell_id : learnable_disciplines) {
|
||||||
|
lua_table[index] = spell_id;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object Lua_Client::GetLearnableDisciplines(lua_State* L, uint8 min_level) {
|
||||||
|
auto lua_table = luabind::newtable(L);
|
||||||
|
if (d_) {
|
||||||
|
auto self = reinterpret_cast<NativeType*>(d_);
|
||||||
|
auto learnable_disciplines = self->GetLearnableDisciplines(min_level);
|
||||||
|
int index = 0;
|
||||||
|
for (auto spell_id : learnable_disciplines) {
|
||||||
|
lua_table[index] = spell_id;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object Lua_Client::GetLearnableDisciplines(lua_State* L, uint8 min_level, uint8 max_level) {
|
||||||
|
auto lua_table = luabind::newtable(L);
|
||||||
|
if (d_) {
|
||||||
|
auto self = reinterpret_cast<NativeType*>(d_);
|
||||||
|
auto learnable_disciplines = self->GetLearnableDisciplines(min_level, max_level);
|
||||||
|
int index = 0;
|
||||||
|
for (auto spell_id : learnable_disciplines) {
|
||||||
|
lua_table[index] = spell_id;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object Lua_Client::GetLearnedDisciplines(lua_State* L) {
|
||||||
|
auto lua_table = luabind::newtable(L);
|
||||||
|
if (d_) {
|
||||||
|
auto self = reinterpret_cast<NativeType*>(d_);
|
||||||
|
auto learned_disciplines = self->GetLearnedDisciplines();
|
||||||
|
int index = 0;
|
||||||
|
for (auto spell_id : learned_disciplines) {
|
||||||
|
lua_table[index] = spell_id;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object Lua_Client::GetMemmedSpells(lua_State* L) {
|
||||||
|
auto lua_table = luabind::newtable(L);
|
||||||
|
if (d_) {
|
||||||
|
auto self = reinterpret_cast<NativeType*>(d_);
|
||||||
|
auto memmed_spells = self->GetMemmedSpells();
|
||||||
|
int index = 0;
|
||||||
|
for (auto spell_id : memmed_spells) {
|
||||||
|
lua_table[index] = spell_id;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object Lua_Client::GetScribeableSpells(lua_State* L) {
|
||||||
|
auto lua_table = luabind::newtable(L);
|
||||||
|
if (d_) {
|
||||||
|
auto self = reinterpret_cast<NativeType*>(d_);
|
||||||
|
auto scribeable_spells = self->GetScribeableSpells();
|
||||||
|
int index = 0;
|
||||||
|
for (auto spell_id : scribeable_spells) {
|
||||||
|
lua_table[index] = spell_id;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object Lua_Client::GetScribeableSpells(lua_State* L, uint8 min_level) {
|
||||||
|
auto lua_table = luabind::newtable(L);
|
||||||
|
if (d_) {
|
||||||
|
auto self = reinterpret_cast<NativeType*>(d_);
|
||||||
|
auto scribeable_spells = self->GetScribeableSpells(min_level);
|
||||||
|
int index = 0;
|
||||||
|
for (auto spell_id : scribeable_spells) {
|
||||||
|
lua_table[index] = spell_id;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object Lua_Client::GetScribeableSpells(lua_State* L, uint8 min_level, uint8 max_level) {
|
||||||
|
auto lua_table = luabind::newtable(L);
|
||||||
|
if (d_) {
|
||||||
|
auto self = reinterpret_cast<NativeType*>(d_);
|
||||||
|
auto scribeable_spells = self->GetScribeableSpells(min_level, max_level);
|
||||||
|
int index = 0;
|
||||||
|
for (auto spell_id : scribeable_spells) {
|
||||||
|
lua_table[index] = spell_id;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object Lua_Client::GetScribedSpells(lua_State* L) {
|
||||||
|
auto lua_table = luabind::newtable(L);
|
||||||
|
if (d_) {
|
||||||
|
auto self = reinterpret_cast<NativeType*>(d_);
|
||||||
|
auto scribed_spells = self->GetScribedSpells();
|
||||||
|
int index = 0;
|
||||||
|
for (auto spell_id : scribed_spells) {
|
||||||
|
lua_table[index] = spell_id;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
void Lua_Client::ScribeSpell(int spell_id, int slot) {
|
void Lua_Client::ScribeSpell(int spell_id, int slot) {
|
||||||
Lua_Safe_Call_Void();
|
Lua_Safe_Call_Void();
|
||||||
self->ScribeSpell(spell_id, slot);
|
self->ScribeSpell(spell_id, slot);
|
||||||
@ -900,6 +1055,11 @@ bool Lua_Client::UseDiscipline(int spell_id, int target_id) {
|
|||||||
return self->UseDiscipline(spell_id, target_id);
|
return self->UseDiscipline(spell_id, target_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Lua_Client::HasDisciplineLearned(uint16 spell_id) {
|
||||||
|
Lua_Safe_Call_Bool();
|
||||||
|
return self->HasDisciplineLearned(spell_id);
|
||||||
|
}
|
||||||
|
|
||||||
int Lua_Client::GetCharacterFactionLevel(int faction_id) {
|
int Lua_Client::GetCharacterFactionLevel(int faction_id) {
|
||||||
Lua_Safe_Call_Int();
|
Lua_Safe_Call_Int();
|
||||||
return self->GetCharacterFactionLevel(faction_id);
|
return self->GetCharacterFactionLevel(faction_id);
|
||||||
@ -1040,6 +1200,16 @@ void Lua_Client::AddCrystals(uint32 radiant, uint32 ebon) {
|
|||||||
self->AddCrystals(radiant, ebon);
|
self->AddCrystals(radiant, ebon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Lua_Client::SetEbonCrystals(uint32 value) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetEbonCrystals(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::SetRadiantCrystals(uint32 value) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetRadiantCrystals(value);
|
||||||
|
}
|
||||||
|
|
||||||
uint32 Lua_Client::GetPVPPoints() {
|
uint32 Lua_Client::GetPVPPoints() {
|
||||||
Lua_Safe_Call_Int();
|
Lua_Safe_Call_Int();
|
||||||
return self->GetPVPPoints();
|
return self->GetPVPPoints();
|
||||||
@ -1160,6 +1330,11 @@ int Lua_Client::GetNextAvailableSpellBookSlot() {
|
|||||||
return self->GetNextAvailableSpellBookSlot();
|
return self->GetNextAvailableSpellBookSlot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 Lua_Client::GetSpellIDByBookSlot(int slot_id) {
|
||||||
|
Lua_Safe_Call_Int();
|
||||||
|
return self->GetSpellIDByBookSlot(slot_id);
|
||||||
|
}
|
||||||
|
|
||||||
int Lua_Client::GetNextAvailableSpellBookSlot(int start) {
|
int Lua_Client::GetNextAvailableSpellBookSlot(int start) {
|
||||||
Lua_Safe_Call_Int();
|
Lua_Safe_Call_Int();
|
||||||
return self->GetNextAvailableSpellBookSlot(start);
|
return self->GetNextAvailableSpellBookSlot(start);
|
||||||
@ -1629,7 +1804,249 @@ int Lua_Client::GetClientMaxLevel() {
|
|||||||
return self->GetClientMaxLevel();
|
return self->GetClientMaxLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DynamicZoneLocation GetDynamicZoneLocationFromTable(const luabind::object& lua_table)
|
||||||
|
{
|
||||||
|
DynamicZoneLocation zone_location;
|
||||||
|
|
||||||
|
if (luabind::type(lua_table) == LUA_TTABLE)
|
||||||
|
{
|
||||||
|
luabind::object lua_zone = lua_table["zone"];
|
||||||
|
|
||||||
|
// default invalid/missing args to 0
|
||||||
|
uint32_t zone_id = 0;
|
||||||
|
if (luabind::type(lua_zone) == LUA_TSTRING)
|
||||||
|
{
|
||||||
|
zone_id = ZoneID(luabind::object_cast<std::string>(lua_zone));
|
||||||
|
}
|
||||||
|
else if (luabind::type(lua_zone) == LUA_TNUMBER)
|
||||||
|
{
|
||||||
|
zone_id = luabind::object_cast<uint32_t>(lua_zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
float x = (luabind::type(lua_table["x"]) != LUA_TNIL) ? luabind::object_cast<float>(lua_table["x"]) : 0.0f;
|
||||||
|
float y = (luabind::type(lua_table["y"]) != LUA_TNIL) ? luabind::object_cast<float>(lua_table["y"]) : 0.0f;
|
||||||
|
float z = (luabind::type(lua_table["z"]) != LUA_TNIL) ? luabind::object_cast<float>(lua_table["z"]) : 0.0f;
|
||||||
|
float h = (luabind::type(lua_table["h"]) != LUA_TNIL) ? luabind::object_cast<float>(lua_table["h"]) : 0.0f;
|
||||||
|
|
||||||
|
zone_location = { zone_id, x, y, z, h };
|
||||||
|
}
|
||||||
|
|
||||||
|
return zone_location;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lua_Expedition Lua_Client::CreateExpedition(luabind::object expedition_table) {
|
||||||
|
Lua_Safe_Call_Class(Lua_Expedition);
|
||||||
|
|
||||||
|
if (luabind::type(expedition_table) != LUA_TTABLE)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// luabind will catch thrown cast_failed exceptions for invalid/missing args
|
||||||
|
luabind::object instance_info = expedition_table["instance"];
|
||||||
|
luabind::object zone = instance_info["zone"];
|
||||||
|
|
||||||
|
uint32_t zone_id = 0;
|
||||||
|
if (luabind::type(zone) == LUA_TSTRING)
|
||||||
|
{
|
||||||
|
zone_id = ZoneID(luabind::object_cast<std::string>(zone));
|
||||||
|
}
|
||||||
|
else if (luabind::type(zone) == LUA_TNUMBER)
|
||||||
|
{
|
||||||
|
zone_id = luabind::object_cast<uint32_t>(zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t zone_version = luabind::object_cast<uint32_t>(instance_info["version"]);
|
||||||
|
uint32_t zone_duration = luabind::object_cast<uint32_t>(instance_info["duration"]);
|
||||||
|
|
||||||
|
DynamicZone dz{ zone_id, zone_version, zone_duration, DynamicZoneType::Expedition };
|
||||||
|
|
||||||
|
// the dz_info table supports optional hash entries for 'compass', 'safereturn', and 'zonein' data
|
||||||
|
if (luabind::type(expedition_table["compass"]) == LUA_TTABLE)
|
||||||
|
{
|
||||||
|
auto compass_loc = GetDynamicZoneLocationFromTable(expedition_table["compass"]);
|
||||||
|
dz.SetCompass(compass_loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (luabind::type(expedition_table["safereturn"]) == LUA_TTABLE)
|
||||||
|
{
|
||||||
|
auto safereturn_loc = GetDynamicZoneLocationFromTable(expedition_table["safereturn"]);
|
||||||
|
dz.SetSafeReturn(safereturn_loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (luabind::type(expedition_table["zonein"]) == LUA_TTABLE)
|
||||||
|
{
|
||||||
|
auto zonein_loc = GetDynamicZoneLocationFromTable(expedition_table["zonein"]);
|
||||||
|
dz.SetZoneInLocation(zonein_loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object expedition_info = expedition_table["expedition"];
|
||||||
|
|
||||||
|
std::string expedition_name = luabind::object_cast<std::string>(expedition_info["name"]);
|
||||||
|
uint32_t min_players = luabind::object_cast<uint32_t>(expedition_info["min_players"]);
|
||||||
|
uint32_t max_players = luabind::object_cast<uint32_t>(expedition_info["max_players"]);
|
||||||
|
bool disable_messages = false;
|
||||||
|
|
||||||
|
if (luabind::type(expedition_info["disable_messages"]) == LUA_TBOOLEAN)
|
||||||
|
{
|
||||||
|
disable_messages = luabind::object_cast<bool>(expedition_info["disable_messages"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpeditionRequest request{ expedition_name, min_players, max_players, disable_messages };
|
||||||
|
|
||||||
|
return self->CreateExpedition(dz, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
Lua_Expedition Lua_Client::CreateExpedition(std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players) {
|
||||||
|
Lua_Safe_Call_Class(Lua_Expedition);
|
||||||
|
return self->CreateExpedition(zone_name, version, duration, expedition_name, min_players, max_players);
|
||||||
|
}
|
||||||
|
|
||||||
|
Lua_Expedition Lua_Client::CreateExpedition(std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players, bool disable_messages) {
|
||||||
|
Lua_Safe_Call_Class(Lua_Expedition);
|
||||||
|
return self->CreateExpedition(zone_name, version, duration, expedition_name, min_players, max_players, disable_messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
Lua_Expedition Lua_Client::GetExpedition() {
|
||||||
|
Lua_Safe_Call_Class(Lua_Expedition);
|
||||||
|
return self->GetExpedition();
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object Lua_Client::GetExpeditionLockouts(lua_State* L)
|
||||||
|
{
|
||||||
|
auto lua_table = luabind::newtable(L);
|
||||||
|
if (d_)
|
||||||
|
{
|
||||||
|
auto self = reinterpret_cast<NativeType*>(d_);
|
||||||
|
auto lockouts = self->GetExpeditionLockouts();
|
||||||
|
|
||||||
|
for (const auto& lockout : lockouts)
|
||||||
|
{
|
||||||
|
auto lockout_table = lua_table[lockout.GetExpeditionName()];
|
||||||
|
if (luabind::type(lockout_table) != LUA_TTABLE)
|
||||||
|
{
|
||||||
|
lockout_table = luabind::newtable(L);
|
||||||
|
}
|
||||||
|
lockout_table[lockout.GetEventName()] = lockout.GetSecondsRemaining();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object Lua_Client::GetExpeditionLockouts(lua_State* L, std::string expedition_name)
|
||||||
|
{
|
||||||
|
auto lua_table = luabind::newtable(L);
|
||||||
|
if (d_)
|
||||||
|
{
|
||||||
|
auto self = reinterpret_cast<NativeType*>(d_);
|
||||||
|
auto lockouts = self->GetExpeditionLockouts();
|
||||||
|
|
||||||
|
for (const auto& lockout : lockouts)
|
||||||
|
{
|
||||||
|
if (lockout.GetExpeditionName() == expedition_name)
|
||||||
|
{
|
||||||
|
lua_table[lockout.GetEventName()] = lockout.GetSecondsRemaining();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Lua_Client::GetLockoutExpeditionUUID(std::string expedition_name, std::string event_name) {
|
||||||
|
Lua_Safe_Call_String();
|
||||||
|
std::string uuid;
|
||||||
|
auto lockout = self->GetExpeditionLockout(expedition_name, event_name);
|
||||||
|
if (lockout)
|
||||||
|
{
|
||||||
|
uuid = lockout->GetExpeditionUUID();
|
||||||
|
}
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::AddExpeditionLockout(std::string expedition_name, std::string event_name, uint32 seconds) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->AddNewExpeditionLockout(expedition_name, event_name, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::AddExpeditionLockout(std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->AddNewExpeditionLockout(expedition_name, event_name, seconds, uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::AddExpeditionLockoutDuration(std::string expedition_name, std::string event_name, int seconds) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->AddExpeditionLockoutDuration(expedition_name, event_name, seconds, {}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::AddExpeditionLockoutDuration(std::string expedition_name, std::string event_name, int seconds, std::string uuid) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->AddExpeditionLockoutDuration(expedition_name, event_name, seconds, uuid, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::RemoveAllExpeditionLockouts() {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->RemoveAllExpeditionLockouts({}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::RemoveAllExpeditionLockouts(std::string expedition_name) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->RemoveAllExpeditionLockouts(expedition_name, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::RemoveExpeditionLockout(std::string expedition_name, std::string event_name) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->RemoveExpeditionLockout(expedition_name, event_name, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Lua_Client::HasExpeditionLockout(std::string expedition_name, std::string event_name) {
|
||||||
|
Lua_Safe_Call_Bool();
|
||||||
|
return self->HasExpeditionLockout(expedition_name, event_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::MovePCDynamicZone(uint32 zone_id) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
return self->MovePCDynamicZone(zone_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::MovePCDynamicZone(uint32 zone_id, int zone_version) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
return self->MovePCDynamicZone(zone_id, zone_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::MovePCDynamicZone(uint32 zone_id, int zone_version, bool msg_if_invalid) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
return self->MovePCDynamicZone(zone_id, zone_version, msg_if_invalid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::MovePCDynamicZone(std::string zone_name) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
return self->MovePCDynamicZone(zone_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::MovePCDynamicZone(std::string zone_name, int zone_version) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
return self->MovePCDynamicZone(zone_name, zone_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::MovePCDynamicZone(std::string zone_name, int zone_version, bool msg_if_invalid) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
return self->MovePCDynamicZone(zone_name, zone_version, msg_if_invalid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::Fling(float value, float target_x, float target_y, float target_z) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->Fling(value, target_x, target_y, target_z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->Fling(value, target_x, target_y, target_z, ignore_los);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Client::Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clipping) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->Fling(value, target_x, target_y, target_z, ignore_los, clipping);
|
||||||
|
}
|
||||||
|
|
||||||
luabind::scope lua_register_client() {
|
luabind::scope lua_register_client() {
|
||||||
return luabind::class_<Lua_Client, Lua_Mob>("Client")
|
return luabind::class_<Lua_Client, Lua_Mob>("Client")
|
||||||
@ -1657,6 +2074,8 @@ luabind::scope lua_register_client() {
|
|||||||
.def("SetBaseClass", (void(Lua_Client::*)(int))&Lua_Client::SetBaseClass)
|
.def("SetBaseClass", (void(Lua_Client::*)(int))&Lua_Client::SetBaseClass)
|
||||||
.def("SetBaseRace", (void(Lua_Client::*)(int))&Lua_Client::SetBaseRace)
|
.def("SetBaseRace", (void(Lua_Client::*)(int))&Lua_Client::SetBaseRace)
|
||||||
.def("SetBaseGender", (void(Lua_Client::*)(int))&Lua_Client::SetBaseGender)
|
.def("SetBaseGender", (void(Lua_Client::*)(int))&Lua_Client::SetBaseGender)
|
||||||
|
.def("GetClassBitmask", (int(Lua_Client::*)(void))&Lua_Client::GetClassBitmask)
|
||||||
|
.def("GetRaceBitmask", (int(Lua_Client::*)(void))&Lua_Client::GetRaceBitmask)
|
||||||
.def("GetBaseFace", (int(Lua_Client::*)(void))&Lua_Client::GetBaseFace)
|
.def("GetBaseFace", (int(Lua_Client::*)(void))&Lua_Client::GetBaseFace)
|
||||||
.def("GetLanguageSkill", (int(Lua_Client::*)(int))&Lua_Client::GetLanguageSkill)
|
.def("GetLanguageSkill", (int(Lua_Client::*)(int))&Lua_Client::GetLanguageSkill)
|
||||||
.def("GetLastName", (const char *(Lua_Client::*)(void))&Lua_Client::GetLastName)
|
.def("GetLastName", (const char *(Lua_Client::*)(void))&Lua_Client::GetLastName)
|
||||||
@ -1696,6 +2115,9 @@ luabind::scope lua_register_client() {
|
|||||||
.def("GetBindHeading", (float(Lua_Client::*)(int))&Lua_Client::GetBindHeading)
|
.def("GetBindHeading", (float(Lua_Client::*)(int))&Lua_Client::GetBindHeading)
|
||||||
.def("GetBindZoneID", (uint32(Lua_Client::*)(void))&Lua_Client::GetBindZoneID)
|
.def("GetBindZoneID", (uint32(Lua_Client::*)(void))&Lua_Client::GetBindZoneID)
|
||||||
.def("GetBindZoneID", (uint32(Lua_Client::*)(int))&Lua_Client::GetBindZoneID)
|
.def("GetBindZoneID", (uint32(Lua_Client::*)(int))&Lua_Client::GetBindZoneID)
|
||||||
|
.def("GetTargetRingX", (float(Lua_Client::*)(void))&Lua_Client::GetTargetRingX)
|
||||||
|
.def("GetTargetRingY", (float(Lua_Client::*)(void))&Lua_Client::GetTargetRingY)
|
||||||
|
.def("GetTargetRingZ", (float(Lua_Client::*)(void))&Lua_Client::GetTargetRingZ)
|
||||||
.def("SetPrimaryWeaponOrnamentation", (void(Lua_Client::*)(uint32))&Lua_Client::SetPrimaryWeaponOrnamentation)
|
.def("SetPrimaryWeaponOrnamentation", (void(Lua_Client::*)(uint32))&Lua_Client::SetPrimaryWeaponOrnamentation)
|
||||||
.def("SetSecondaryWeaponOrnamentation", (void(Lua_Client::*)(uint32))&Lua_Client::SetSecondaryWeaponOrnamentation)
|
.def("SetSecondaryWeaponOrnamentation", (void(Lua_Client::*)(uint32))&Lua_Client::SetSecondaryWeaponOrnamentation)
|
||||||
.def("MovePC", (void(Lua_Client::*)(int,float,float,float,float))&Lua_Client::MovePC)
|
.def("MovePC", (void(Lua_Client::*)(int,float,float,float,float))&Lua_Client::MovePC)
|
||||||
@ -1754,6 +2176,15 @@ luabind::scope lua_register_client() {
|
|||||||
.def("UnmemSpellAll", (void(Lua_Client::*)(bool))&Lua_Client::UnmemSpellAll)
|
.def("UnmemSpellAll", (void(Lua_Client::*)(bool))&Lua_Client::UnmemSpellAll)
|
||||||
.def("FindMemmedSpellBySlot", (uint16(Lua_Client::*)(int))&Lua_Client::FindMemmedSpellBySlot)
|
.def("FindMemmedSpellBySlot", (uint16(Lua_Client::*)(int))&Lua_Client::FindMemmedSpellBySlot)
|
||||||
.def("MemmedCount", (int(Lua_Client::*)(void))&Lua_Client::MemmedCount)
|
.def("MemmedCount", (int(Lua_Client::*)(void))&Lua_Client::MemmedCount)
|
||||||
|
.def("GetLearnableDisciplines", (luabind::object(Lua_Client::*)(lua_State* L))&Lua_Client::GetLearnableDisciplines)
|
||||||
|
.def("GetLearnableDisciplines", (luabind::object(Lua_Client::*)(lua_State* L,uint8))&Lua_Client::GetLearnableDisciplines)
|
||||||
|
.def("GetLearnableDisciplines", (luabind::object(Lua_Client::*)(lua_State* L,uint8,uint8))&Lua_Client::GetLearnableDisciplines)
|
||||||
|
.def("GetLearnedDisciplines", (luabind::object(Lua_Client::*)(lua_State* L))&Lua_Client::GetLearnedDisciplines)
|
||||||
|
.def("GetMemmedSpells", (luabind::object(Lua_Client::*)(lua_State* L))&Lua_Client::GetMemmedSpells)
|
||||||
|
.def("GetScribedSpells", (luabind::object(Lua_Client::*)(lua_State* L))&Lua_Client::GetScribedSpells)
|
||||||
|
.def("GetScribeableSpells", (luabind::object(Lua_Client::*)(lua_State* L))&Lua_Client::GetScribeableSpells)
|
||||||
|
.def("GetScribeableSpells", (luabind::object(Lua_Client::*)(lua_State* L,uint8))&Lua_Client::GetScribeableSpells)
|
||||||
|
.def("GetScribeableSpells", (luabind::object(Lua_Client::*)(lua_State* L,uint8,uint8))&Lua_Client::GetScribeableSpells)
|
||||||
.def("ScribeSpell", (void(Lua_Client::*)(int,int))&Lua_Client::ScribeSpell)
|
.def("ScribeSpell", (void(Lua_Client::*)(int,int))&Lua_Client::ScribeSpell)
|
||||||
.def("ScribeSpell", (void(Lua_Client::*)(int,int,bool))&Lua_Client::ScribeSpell)
|
.def("ScribeSpell", (void(Lua_Client::*)(int,int,bool))&Lua_Client::ScribeSpell)
|
||||||
.def("UnscribeSpell", (void(Lua_Client::*)(int))&Lua_Client::UnscribeSpell)
|
.def("UnscribeSpell", (void(Lua_Client::*)(int))&Lua_Client::UnscribeSpell)
|
||||||
@ -1813,6 +2244,7 @@ luabind::scope lua_register_client() {
|
|||||||
.def("GetDisciplineTimer", (uint32(Lua_Client::*)(uint32))&Lua_Client::GetDisciplineTimer)
|
.def("GetDisciplineTimer", (uint32(Lua_Client::*)(uint32))&Lua_Client::GetDisciplineTimer)
|
||||||
.def("ResetDisciplineTimer", (void(Lua_Client::*)(uint32))&Lua_Client::ResetDisciplineTimer)
|
.def("ResetDisciplineTimer", (void(Lua_Client::*)(uint32))&Lua_Client::ResetDisciplineTimer)
|
||||||
.def("UseDiscipline", (bool(Lua_Client::*)(int,int))&Lua_Client::UseDiscipline)
|
.def("UseDiscipline", (bool(Lua_Client::*)(int,int))&Lua_Client::UseDiscipline)
|
||||||
|
.def("HasDisciplineLearned", (bool(Lua_Client::*)(uint16))&Lua_Client::HasDisciplineLearned)
|
||||||
.def("GetCharacterFactionLevel", (int(Lua_Client::*)(int))&Lua_Client::GetCharacterFactionLevel)
|
.def("GetCharacterFactionLevel", (int(Lua_Client::*)(int))&Lua_Client::GetCharacterFactionLevel)
|
||||||
.def("SetZoneFlag", (void(Lua_Client::*)(int))&Lua_Client::SetZoneFlag)
|
.def("SetZoneFlag", (void(Lua_Client::*)(int))&Lua_Client::SetZoneFlag)
|
||||||
.def("ClearZoneFlag", (void(Lua_Client::*)(int))&Lua_Client::ClearZoneFlag)
|
.def("ClearZoneFlag", (void(Lua_Client::*)(int))&Lua_Client::ClearZoneFlag)
|
||||||
@ -1841,6 +2273,8 @@ luabind::scope lua_register_client() {
|
|||||||
.def("KeyRingCheck", (bool(Lua_Client::*)(uint32))&Lua_Client::KeyRingCheck)
|
.def("KeyRingCheck", (bool(Lua_Client::*)(uint32))&Lua_Client::KeyRingCheck)
|
||||||
.def("AddPVPPoints", (void(Lua_Client::*)(uint32))&Lua_Client::AddPVPPoints)
|
.def("AddPVPPoints", (void(Lua_Client::*)(uint32))&Lua_Client::AddPVPPoints)
|
||||||
.def("AddCrystals", (void(Lua_Client::*)(uint32,uint32))&Lua_Client::AddCrystals)
|
.def("AddCrystals", (void(Lua_Client::*)(uint32,uint32))&Lua_Client::AddCrystals)
|
||||||
|
.def("SetEbonCrystals", (void(Lua_Client::*)(uint32))&Lua_Client::SetEbonCrystals)
|
||||||
|
.def("SetRadiantCrystals", (void(Lua_Client::*)(uint32))&Lua_Client::SetRadiantCrystals)
|
||||||
.def("GetPVPPoints", (uint32(Lua_Client::*)(void))&Lua_Client::GetPVPPoints)
|
.def("GetPVPPoints", (uint32(Lua_Client::*)(void))&Lua_Client::GetPVPPoints)
|
||||||
.def("GetRadiantCrystals", (uint32(Lua_Client::*)(void))&Lua_Client::GetRadiantCrystals)
|
.def("GetRadiantCrystals", (uint32(Lua_Client::*)(void))&Lua_Client::GetRadiantCrystals)
|
||||||
.def("GetEbonCrystals", (uint32(Lua_Client::*)(void))&Lua_Client::GetEbonCrystals)
|
.def("GetEbonCrystals", (uint32(Lua_Client::*)(void))&Lua_Client::GetEbonCrystals)
|
||||||
@ -1866,6 +2300,7 @@ luabind::scope lua_register_client() {
|
|||||||
.def("ClearCompassMark",(void(Lua_Client::*)(void))&Lua_Client::ClearCompassMark)
|
.def("ClearCompassMark",(void(Lua_Client::*)(void))&Lua_Client::ClearCompassMark)
|
||||||
.def("GetNextAvailableSpellBookSlot", (int(Lua_Client::*)(void))&Lua_Client::GetNextAvailableSpellBookSlot)
|
.def("GetNextAvailableSpellBookSlot", (int(Lua_Client::*)(void))&Lua_Client::GetNextAvailableSpellBookSlot)
|
||||||
.def("GetNextAvailableSpellBookSlot", (int(Lua_Client::*)(int))&Lua_Client::GetNextAvailableSpellBookSlot)
|
.def("GetNextAvailableSpellBookSlot", (int(Lua_Client::*)(int))&Lua_Client::GetNextAvailableSpellBookSlot)
|
||||||
|
.def("GetSpellIDByBookSlot", (uint32(Lua_Client::*)(int))& Lua_Client::GetSpellIDByBookSlot)
|
||||||
.def("FindSpellBookSlotBySpellID", (int(Lua_Client::*)(int))&Lua_Client::FindSpellBookSlotBySpellID)
|
.def("FindSpellBookSlotBySpellID", (int(Lua_Client::*)(int))&Lua_Client::FindSpellBookSlotBySpellID)
|
||||||
.def("UpdateTaskActivity", (void(Lua_Client::*)(int,int,int))&Lua_Client::UpdateTaskActivity)
|
.def("UpdateTaskActivity", (void(Lua_Client::*)(int,int,int))&Lua_Client::UpdateTaskActivity)
|
||||||
.def("AssignTask", (void(Lua_Client::*)(int,int))&Lua_Client::AssignTask)
|
.def("AssignTask", (void(Lua_Client::*)(int,int))&Lua_Client::AssignTask)
|
||||||
@ -1934,7 +2369,31 @@ luabind::scope lua_register_client() {
|
|||||||
.def("EnableAreaRegens", &Lua_Client::EnableAreaRegens)
|
.def("EnableAreaRegens", &Lua_Client::EnableAreaRegens)
|
||||||
.def("DisableAreaRegens", &Lua_Client::DisableAreaRegens)
|
.def("DisableAreaRegens", &Lua_Client::DisableAreaRegens)
|
||||||
.def("SetClientMaxLevel", (void(Lua_Client::*)(int))&Lua_Client::SetClientMaxLevel)
|
.def("SetClientMaxLevel", (void(Lua_Client::*)(int))&Lua_Client::SetClientMaxLevel)
|
||||||
.def("GetClientMaxLevel", (int(Lua_Client::*)(void))&Lua_Client::GetClientMaxLevel);
|
.def("GetClientMaxLevel", (int(Lua_Client::*)(void))&Lua_Client::GetClientMaxLevel)
|
||||||
|
.def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(luabind::object))&Lua_Client::CreateExpedition)
|
||||||
|
.def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32))&Lua_Client::CreateExpedition)
|
||||||
|
.def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32, bool))&Lua_Client::CreateExpedition)
|
||||||
|
.def("GetExpedition", (Lua_Expedition(Lua_Client::*)(void))&Lua_Client::GetExpedition)
|
||||||
|
.def("GetExpeditionLockouts", (luabind::object(Lua_Client::*)(lua_State* L))&Lua_Client::GetExpeditionLockouts)
|
||||||
|
.def("GetExpeditionLockouts", (luabind::object(Lua_Client::*)(lua_State* L, std::string))&Lua_Client::GetExpeditionLockouts)
|
||||||
|
.def("GetLockoutExpeditionUUID", (std::string(Lua_Client::*)(std::string, std::string))&Lua_Client::GetLockoutExpeditionUUID)
|
||||||
|
.def("AddExpeditionLockout", (void(Lua_Client::*)(std::string, std::string, uint32))&Lua_Client::AddExpeditionLockout)
|
||||||
|
.def("AddExpeditionLockout", (void(Lua_Client::*)(std::string, std::string, uint32, std::string))&Lua_Client::AddExpeditionLockout)
|
||||||
|
.def("AddExpeditionLockoutDuration", (void(Lua_Client::*)(std::string, std::string, int))&Lua_Client::AddExpeditionLockoutDuration)
|
||||||
|
.def("AddExpeditionLockoutDuration", (void(Lua_Client::*)(std::string, std::string, int, std::string))&Lua_Client::AddExpeditionLockoutDuration)
|
||||||
|
.def("RemoveAllExpeditionLockouts", (void(Lua_Client::*)(void))&Lua_Client::RemoveAllExpeditionLockouts)
|
||||||
|
.def("RemoveAllExpeditionLockouts", (void(Lua_Client::*)(std::string))&Lua_Client::RemoveAllExpeditionLockouts)
|
||||||
|
.def("RemoveExpeditionLockout", (void(Lua_Client::*)(std::string, std::string))&Lua_Client::RemoveExpeditionLockout)
|
||||||
|
.def("HasExpeditionLockout", (bool(Lua_Client::*)(std::string, std::string))&Lua_Client::HasExpeditionLockout)
|
||||||
|
.def("MovePCDynamicZone", (void(Lua_Client::*)(uint32))&Lua_Client::MovePCDynamicZone)
|
||||||
|
.def("MovePCDynamicZone", (void(Lua_Client::*)(uint32, int))&Lua_Client::MovePCDynamicZone)
|
||||||
|
.def("MovePCDynamicZone", (void(Lua_Client::*)(uint32, int, bool))&Lua_Client::MovePCDynamicZone)
|
||||||
|
.def("MovePCDynamicZone", (void(Lua_Client::*)(std::string))&Lua_Client::MovePCDynamicZone)
|
||||||
|
.def("MovePCDynamicZone", (void(Lua_Client::*)(std::string, int))&Lua_Client::MovePCDynamicZone)
|
||||||
|
.def("MovePCDynamicZone", (void(Lua_Client::*)(std::string, int, bool))&Lua_Client::MovePCDynamicZone)
|
||||||
|
.def("Fling", (void(Lua_Client::*)(float,float,float,float))&Lua_Client::Fling)
|
||||||
|
.def("Fling", (void(Lua_Client::*)(float,float,float,float,bool))&Lua_Client::Fling)
|
||||||
|
.def("Fling", (void(Lua_Client::*)(float,float,float,float,bool,bool))&Lua_Client::Fling);
|
||||||
}
|
}
|
||||||
|
|
||||||
luabind::scope lua_register_inventory_where() {
|
luabind::scope lua_register_inventory_where() {
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include "lua_mob.h"
|
#include "lua_mob.h"
|
||||||
|
|
||||||
class Client;
|
class Client;
|
||||||
|
class Lua_Expedition;
|
||||||
class Lua_Group;
|
class Lua_Group;
|
||||||
class Lua_Raid;
|
class Lua_Raid;
|
||||||
class Lua_Inventory;
|
class Lua_Inventory;
|
||||||
@ -52,6 +53,8 @@ public:
|
|||||||
void SetBaseClass(int v);
|
void SetBaseClass(int v);
|
||||||
void SetBaseRace(int v);
|
void SetBaseRace(int v);
|
||||||
void SetBaseGender(int v);
|
void SetBaseGender(int v);
|
||||||
|
int GetClassBitmask();
|
||||||
|
int GetRaceBitmask();
|
||||||
int GetBaseFace();
|
int GetBaseFace();
|
||||||
int GetLanguageSkill(int skill_id);
|
int GetLanguageSkill(int skill_id);
|
||||||
const char *GetLastName();
|
const char *GetLastName();
|
||||||
@ -91,6 +94,9 @@ public:
|
|||||||
float GetBindHeading(int index);
|
float GetBindHeading(int index);
|
||||||
uint32 GetBindZoneID();
|
uint32 GetBindZoneID();
|
||||||
uint32 GetBindZoneID(int index);
|
uint32 GetBindZoneID(int index);
|
||||||
|
float GetTargetRingX();
|
||||||
|
float GetTargetRingY();
|
||||||
|
float GetTargetRingZ();
|
||||||
void MovePC(int zone, float x, float y, float z, float heading);
|
void MovePC(int zone, float x, float y, float z, float heading);
|
||||||
void MovePCInstance(int zone, int instance, float x, float y, float z, float heading);
|
void MovePCInstance(int zone, int instance, float x, float y, float z, float heading);
|
||||||
void MoveZone(const char *zone_short_name);
|
void MoveZone(const char *zone_short_name);
|
||||||
@ -146,6 +152,15 @@ public:
|
|||||||
void UnmemSpellAll(bool update_client);
|
void UnmemSpellAll(bool update_client);
|
||||||
uint16 FindMemmedSpellBySlot(int slot);
|
uint16 FindMemmedSpellBySlot(int slot);
|
||||||
int MemmedCount();
|
int MemmedCount();
|
||||||
|
luabind::object GetLearnableDisciplines(lua_State* L);
|
||||||
|
luabind::object GetLearnableDisciplines(lua_State* L, uint8 min_level);
|
||||||
|
luabind::object GetLearnableDisciplines(lua_State* L, uint8 min_level, uint8 max_level);
|
||||||
|
luabind::object GetLearnedDisciplines(lua_State* L);
|
||||||
|
luabind::object GetMemmedSpells(lua_State* L);
|
||||||
|
luabind::object GetScribedSpells(lua_State* L);
|
||||||
|
luabind::object GetScribeableSpells(lua_State* L);
|
||||||
|
luabind::object GetScribeableSpells(lua_State* L, uint8 min_level);
|
||||||
|
luabind::object GetScribeableSpells(lua_State* L, uint8 min_level, uint8 max_level);
|
||||||
void ScribeSpell(int spell_id, int slot);
|
void ScribeSpell(int spell_id, int slot);
|
||||||
void ScribeSpell(int spell_id, int slot, bool update_client);
|
void ScribeSpell(int spell_id, int slot, bool update_client);
|
||||||
void UnscribeSpell(int slot);
|
void UnscribeSpell(int slot);
|
||||||
@ -207,6 +222,7 @@ public:
|
|||||||
uint32 GetDisciplineTimer(uint32 timer_id);
|
uint32 GetDisciplineTimer(uint32 timer_id);
|
||||||
void ResetDisciplineTimer(uint32 timer_id);
|
void ResetDisciplineTimer(uint32 timer_id);
|
||||||
bool UseDiscipline(int spell_id, int target_id);
|
bool UseDiscipline(int spell_id, int target_id);
|
||||||
|
bool HasDisciplineLearned(uint16 spell_id);
|
||||||
int GetCharacterFactionLevel(int faction_id);
|
int GetCharacterFactionLevel(int faction_id);
|
||||||
void SetZoneFlag(int zone_id);
|
void SetZoneFlag(int zone_id);
|
||||||
void ClearZoneFlag(int zone_id);
|
void ClearZoneFlag(int zone_id);
|
||||||
@ -235,6 +251,8 @@ public:
|
|||||||
bool KeyRingCheck(uint32 item);
|
bool KeyRingCheck(uint32 item);
|
||||||
void AddPVPPoints(uint32 points);
|
void AddPVPPoints(uint32 points);
|
||||||
void AddCrystals(uint32 radiant, uint32 ebon);
|
void AddCrystals(uint32 radiant, uint32 ebon);
|
||||||
|
void SetEbonCrystals(uint32 value);
|
||||||
|
void SetRadiantCrystals(uint32 value);
|
||||||
uint32 GetPVPPoints();
|
uint32 GetPVPPoints();
|
||||||
uint32 GetRadiantCrystals();
|
uint32 GetRadiantCrystals();
|
||||||
uint32 GetEbonCrystals();
|
uint32 GetEbonCrystals();
|
||||||
@ -260,6 +278,7 @@ public:
|
|||||||
void ClearCompassMark();
|
void ClearCompassMark();
|
||||||
int GetNextAvailableSpellBookSlot();
|
int GetNextAvailableSpellBookSlot();
|
||||||
int GetNextAvailableSpellBookSlot(int start);
|
int GetNextAvailableSpellBookSlot(int start);
|
||||||
|
uint32 GetSpellIDByBookSlot(int book_slot);
|
||||||
int FindSpellBookSlotBySpellID(int spell_id);
|
int FindSpellBookSlotBySpellID(int spell_id);
|
||||||
void UpdateTaskActivity(int task, int activity, int count);
|
void UpdateTaskActivity(int task, int activity, int count);
|
||||||
void AssignTask(int task, int npc_id);
|
void AssignTask(int task, int npc_id);
|
||||||
@ -329,12 +348,36 @@ public:
|
|||||||
void EnableAreaRegens(int value);
|
void EnableAreaRegens(int value);
|
||||||
void DisableAreaRegens();
|
void DisableAreaRegens();
|
||||||
|
|
||||||
|
|
||||||
void SetPrimaryWeaponOrnamentation(uint32 model_id);
|
void SetPrimaryWeaponOrnamentation(uint32 model_id);
|
||||||
void SetSecondaryWeaponOrnamentation(uint32 model_id);
|
void SetSecondaryWeaponOrnamentation(uint32 model_id);
|
||||||
|
|
||||||
void SetClientMaxLevel(int value);
|
void SetClientMaxLevel(int value);
|
||||||
int GetClientMaxLevel();
|
int GetClientMaxLevel();
|
||||||
|
|
||||||
|
Lua_Expedition CreateExpedition(luabind::object expedition_info);
|
||||||
|
Lua_Expedition CreateExpedition(std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players);
|
||||||
|
Lua_Expedition CreateExpedition(std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players, bool disable_messages);
|
||||||
|
Lua_Expedition GetExpedition();
|
||||||
|
luabind::object GetExpeditionLockouts(lua_State* L);
|
||||||
|
luabind::object GetExpeditionLockouts(lua_State* L, std::string expedition_name);
|
||||||
|
std::string GetLockoutExpeditionUUID(std::string expedition_name, std::string event_name);
|
||||||
|
void AddExpeditionLockout(std::string expedition_name, std::string event_name, uint32 seconds);
|
||||||
|
void AddExpeditionLockout(std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid);
|
||||||
|
void AddExpeditionLockoutDuration(std::string expedition_name, std::string event_name, int seconds);
|
||||||
|
void AddExpeditionLockoutDuration(std::string expedition_name, std::string event_name, int seconds, std::string uuid);
|
||||||
|
void RemoveAllExpeditionLockouts();
|
||||||
|
void RemoveAllExpeditionLockouts(std::string expedition_name);
|
||||||
|
void RemoveExpeditionLockout(std::string expedition_name, std::string event_name);
|
||||||
|
bool HasExpeditionLockout(std::string expedition_name, std::string event_name);
|
||||||
|
void MovePCDynamicZone(uint32 zone_id);
|
||||||
|
void MovePCDynamicZone(uint32 zone_id, int zone_version);
|
||||||
|
void MovePCDynamicZone(uint32 zone_id, int zone_version, bool msg_if_invalid);
|
||||||
|
void MovePCDynamicZone(std::string zone_name);
|
||||||
|
void MovePCDynamicZone(std::string zone_name, int zone_version);
|
||||||
|
void MovePCDynamicZone(std::string zone_name, int zone_version, bool msg_if_invalid);
|
||||||
|
void Fling(float value, float target_x, float target_y, float target_z);
|
||||||
|
void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los);
|
||||||
|
void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los, bool clipping);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
301
zone/lua_expedition.cpp
Normal file
301
zone/lua_expedition.cpp
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef LUA_EQEMU
|
||||||
|
|
||||||
|
#include "lua_expedition.h"
|
||||||
|
#include "expedition.h"
|
||||||
|
#include "zone_store.h"
|
||||||
|
#include "lua.hpp"
|
||||||
|
#include <luabind/luabind.hpp>
|
||||||
|
#include <luabind/object.hpp>
|
||||||
|
|
||||||
|
void Lua_Expedition::AddLockout(std::string event_name, uint32_t seconds) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->AddLockout(event_name, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::AddLockoutDuration(std::string event_name, int seconds) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->AddLockoutDuration(event_name, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::AddLockoutDuration(std::string event_name, int seconds, bool members_only) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->AddLockoutDuration(event_name, seconds, members_only);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::AddReplayLockout(uint32_t seconds) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->AddReplayLockout(seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::AddReplayLockoutDuration(int seconds) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->AddReplayLockoutDuration(seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::AddReplayLockoutDuration(int seconds, bool members_only) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->AddReplayLockoutDuration(seconds, members_only);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Lua_Expedition::GetDynamicZoneID() {
|
||||||
|
Lua_Safe_Call_Int();
|
||||||
|
return self->GetDynamicZoneID();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Lua_Expedition::GetID() {
|
||||||
|
Lua_Safe_Call_Int();
|
||||||
|
return self->GetID();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Lua_Expedition::GetInstanceID() {
|
||||||
|
Lua_Safe_Call_Int();
|
||||||
|
return self->GetDynamicZone().GetInstanceID();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Lua_Expedition::GetLeaderName() {
|
||||||
|
Lua_Safe_Call_String();
|
||||||
|
return self->GetLeaderName();
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object Lua_Expedition::GetLockouts(lua_State* L) {
|
||||||
|
luabind::object lua_table = luabind::newtable(L);
|
||||||
|
|
||||||
|
if (d_)
|
||||||
|
{
|
||||||
|
auto self = reinterpret_cast<NativeType*>(d_);
|
||||||
|
auto lockouts = self->GetLockouts();
|
||||||
|
for (const auto& lockout : lockouts)
|
||||||
|
{
|
||||||
|
lua_table[lockout.first] = lockout.second.GetSecondsRemaining();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Lua_Expedition::GetLootEventByNPCTypeID(uint32_t npc_type_id) {
|
||||||
|
Lua_Safe_Call_String();
|
||||||
|
return self->GetLootEventByNPCTypeID(npc_type_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Lua_Expedition::GetLootEventBySpawnID(uint32_t spawn_id) {
|
||||||
|
Lua_Safe_Call_String();
|
||||||
|
return self->GetLootEventBySpawnID(spawn_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Lua_Expedition::GetMemberCount() {
|
||||||
|
Lua_Safe_Call_Int();
|
||||||
|
return self->GetMemberCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object Lua_Expedition::GetMembers(lua_State* L) {
|
||||||
|
luabind::object lua_table = luabind::newtable(L);
|
||||||
|
|
||||||
|
if (d_)
|
||||||
|
{
|
||||||
|
auto self = reinterpret_cast<NativeType*>(d_);
|
||||||
|
for (const auto& member : self->GetMembers())
|
||||||
|
{
|
||||||
|
lua_table[member.name] = member.char_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Lua_Expedition::GetName() {
|
||||||
|
Lua_Safe_Call_String();
|
||||||
|
return self->GetName();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Lua_Expedition::GetSecondsRemaining() {
|
||||||
|
Lua_Safe_Call_Int();
|
||||||
|
return self->GetDynamicZone().GetSecondsRemaining();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Lua_Expedition::GetUUID() {
|
||||||
|
Lua_Safe_Call_String();
|
||||||
|
return self->GetUUID();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Lua_Expedition::GetZoneID() {
|
||||||
|
Lua_Safe_Call_Int();
|
||||||
|
return self->GetDynamicZone().GetZoneID();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Lua_Expedition::GetZoneName() {
|
||||||
|
Lua_Safe_Call_String();
|
||||||
|
return ZoneName(self->GetDynamicZone().GetZoneID());
|
||||||
|
}
|
||||||
|
|
||||||
|
int Lua_Expedition::GetZoneVersion() {
|
||||||
|
Lua_Safe_Call_Int();
|
||||||
|
return self->GetDynamicZone().GetZoneVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Lua_Expedition::HasLockout(std::string event_name) {
|
||||||
|
Lua_Safe_Call_Bool();
|
||||||
|
return self->HasLockout(event_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Lua_Expedition::HasReplayLockout() {
|
||||||
|
Lua_Safe_Call_Bool();
|
||||||
|
return self->HasReplayLockout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::RemoveCompass() {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetDzCompass(0, 0, 0, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::RemoveLockout(std::string event_name) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->RemoveLockout(event_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::SetCompass(uint32_t zone_id, float x, float y, float z) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetDzCompass(zone_id, x, y, z, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::SetCompass(std::string zone_name, float x, float y, float z) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetDzCompass(zone_name, x, y, z, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::SetLocked(bool lock_expedition) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetLocked(lock_expedition, ExpeditionLockMessage::None, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::SetLocked(bool lock_expedition, int lock_msg) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetLocked(lock_expedition, static_cast<ExpeditionLockMessage>(lock_msg), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::SetLocked(bool lock_expedition, int lock_msg, uint32_t msg_color) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetLocked(lock_expedition, static_cast<ExpeditionLockMessage>(lock_msg), true, msg_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::SetLootEventByNPCTypeID(uint32_t npc_type_id, std::string event_name) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetLootEventByNPCTypeID(npc_type_id, event_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::SetLootEventBySpawnID(uint32_t spawn_id, std::string event_name) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetLootEventBySpawnID(spawn_id, event_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::SetReplayLockoutOnMemberJoin(bool enable) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetReplayLockoutOnMemberJoin(enable, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetDzSafeReturn(zone_id, x, y, z, heading, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::SetSafeReturn(std::string zone_name, float x, float y, float z, float heading) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetDzSafeReturn(zone_name, x, y, z, heading, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::SetSecondsRemaining(uint32_t seconds_remaining)
|
||||||
|
{
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetDzSecondsRemaining(seconds_remaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::SetZoneInLocation(float x, float y, float z, float heading) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->SetDzZoneInLocation(x, y, z, heading, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::UpdateLockoutDuration(std::string event_name, uint32_t duration) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->UpdateLockoutDuration(event_name, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lua_Expedition::UpdateLockoutDuration(std::string event_name, uint32_t duration, bool members_only) {
|
||||||
|
Lua_Safe_Call_Void();
|
||||||
|
self->UpdateLockoutDuration(event_name, duration, members_only);
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::scope lua_register_expedition() {
|
||||||
|
return luabind::class_<Lua_Expedition>("Expedition")
|
||||||
|
.def(luabind::constructor<>())
|
||||||
|
.property("null", &Lua_Expedition::Null)
|
||||||
|
.property("valid", &Lua_Expedition::Valid)
|
||||||
|
.def("AddLockout", (void(Lua_Expedition::*)(std::string, uint32_t))&Lua_Expedition::AddLockout)
|
||||||
|
.def("AddLockoutDuration", (void(Lua_Expedition::*)(std::string, int))&Lua_Expedition::AddLockoutDuration)
|
||||||
|
.def("AddLockoutDuration", (void(Lua_Expedition::*)(std::string, int, bool))&Lua_Expedition::AddLockoutDuration)
|
||||||
|
.def("AddReplayLockout", (void(Lua_Expedition::*)(uint32_t))&Lua_Expedition::AddReplayLockout)
|
||||||
|
.def("AddReplayLockoutDuration", (void(Lua_Expedition::*)(int))&Lua_Expedition::AddReplayLockoutDuration)
|
||||||
|
.def("AddReplayLockoutDuration", (void(Lua_Expedition::*)(int, bool))&Lua_Expedition::AddReplayLockoutDuration)
|
||||||
|
.def("GetDynamicZoneID", &Lua_Expedition::GetDynamicZoneID)
|
||||||
|
.def("GetID", (uint32_t(Lua_Expedition::*)(void))&Lua_Expedition::GetID)
|
||||||
|
.def("GetInstanceID", (int(Lua_Expedition::*)(void))&Lua_Expedition::GetInstanceID)
|
||||||
|
.def("GetLeaderName", (std::string(Lua_Expedition::*)(void))&Lua_Expedition::GetLeaderName)
|
||||||
|
.def("GetLockouts", &Lua_Expedition::GetLockouts)
|
||||||
|
.def("GetLootEventByNPCTypeID", (std::string(Lua_Expedition::*)(uint32_t))&Lua_Expedition::GetLootEventByNPCTypeID)
|
||||||
|
.def("GetLootEventBySpawnID", (std::string(Lua_Expedition::*)(uint32_t))&Lua_Expedition::GetLootEventBySpawnID)
|
||||||
|
.def("GetMemberCount", (uint32_t(Lua_Expedition::*)(void))&Lua_Expedition::GetMemberCount)
|
||||||
|
.def("GetMembers", &Lua_Expedition::GetMembers)
|
||||||
|
.def("GetName", (std::string(Lua_Expedition::*)(void))&Lua_Expedition::GetName)
|
||||||
|
.def("GetSecondsRemaining", (int(Lua_Expedition::*)(void))&Lua_Expedition::GetSecondsRemaining)
|
||||||
|
.def("GetUUID", (std::string(Lua_Expedition::*)(void))&Lua_Expedition::GetUUID)
|
||||||
|
.def("GetZoneID", (int(Lua_Expedition::*)(void))&Lua_Expedition::GetZoneID)
|
||||||
|
.def("GetZoneName", &Lua_Expedition::GetZoneName)
|
||||||
|
.def("GetZoneVersion", &Lua_Expedition::GetZoneVersion)
|
||||||
|
.def("HasLockout", (bool(Lua_Expedition::*)(std::string))&Lua_Expedition::HasLockout)
|
||||||
|
.def("HasReplayLockout", (bool(Lua_Expedition::*)(void))&Lua_Expedition::HasReplayLockout)
|
||||||
|
.def("RemoveCompass", (void(Lua_Expedition::*)(void))&Lua_Expedition::RemoveCompass)
|
||||||
|
.def("RemoveLockout", (void(Lua_Expedition::*)(std::string))&Lua_Expedition::RemoveLockout)
|
||||||
|
.def("SetCompass", (void(Lua_Expedition::*)(uint32_t, float, float, float))&Lua_Expedition::SetCompass)
|
||||||
|
.def("SetCompass", (void(Lua_Expedition::*)(std::string, float, float, float))&Lua_Expedition::SetCompass)
|
||||||
|
.def("SetLocked", (void(Lua_Expedition::*)(bool))&Lua_Expedition::SetLocked)
|
||||||
|
.def("SetLocked", (void(Lua_Expedition::*)(bool, int))&Lua_Expedition::SetLocked)
|
||||||
|
.def("SetLocked", (void(Lua_Expedition::*)(bool, int, uint32_t))&Lua_Expedition::SetLocked)
|
||||||
|
.def("SetLootEventByNPCTypeID", (void(Lua_Expedition::*)(uint32_t, std::string))&Lua_Expedition::SetLootEventByNPCTypeID)
|
||||||
|
.def("SetLootEventBySpawnID", (void(Lua_Expedition::*)(uint32_t, std::string))&Lua_Expedition::SetLootEventBySpawnID)
|
||||||
|
.def("SetReplayLockoutOnMemberJoin", (void(Lua_Expedition::*)(bool))&Lua_Expedition::SetReplayLockoutOnMemberJoin)
|
||||||
|
.def("SetSafeReturn", (void(Lua_Expedition::*)(uint32_t, float, float, float, float))&Lua_Expedition::SetSafeReturn)
|
||||||
|
.def("SetSafeReturn", (void(Lua_Expedition::*)(std::string, float, float, float, float))&Lua_Expedition::SetSafeReturn)
|
||||||
|
.def("SetSecondsRemaining", &Lua_Expedition::SetSecondsRemaining)
|
||||||
|
.def("SetZoneInLocation", (void(Lua_Expedition::*)(float, float, float, float))&Lua_Expedition::SetZoneInLocation)
|
||||||
|
.def("UpdateLockoutDuration", (void(Lua_Expedition::*)(std::string, uint32_t))&Lua_Expedition::UpdateLockoutDuration)
|
||||||
|
.def("UpdateLockoutDuration", (void(Lua_Expedition::*)(std::string, uint32_t, bool))&Lua_Expedition::UpdateLockoutDuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::scope lua_register_expedition_lock_messages() {
|
||||||
|
return luabind::class_<ExpeditionLockMessage>("ExpeditionLockMessage")
|
||||||
|
.enum_("constants")
|
||||||
|
[
|
||||||
|
luabind::value("None", static_cast<int>(ExpeditionLockMessage::None)),
|
||||||
|
luabind::value("Close", static_cast<int>(ExpeditionLockMessage::Close)),
|
||||||
|
luabind::value("Begin", static_cast<int>(ExpeditionLockMessage::Begin))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // LUA_EQEMU
|
||||||
98
zone/lua_expedition.h
Normal file
98
zone/lua_expedition.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/**
|
||||||
|
* EQEmulator: Everquest Server Emulator
|
||||||
|
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||||
|
* are required to give you total support for your newly bought product;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EQEMU_LUA_EXPEDITION_H
|
||||||
|
#define EQEMU_LUA_EXPEDITION_H
|
||||||
|
#ifdef LUA_EQEMU
|
||||||
|
|
||||||
|
#include "lua_ptr.h"
|
||||||
|
#include "../common/types.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Expedition;
|
||||||
|
class Lua_Client;
|
||||||
|
struct lua_State;
|
||||||
|
|
||||||
|
namespace luabind {
|
||||||
|
struct scope;
|
||||||
|
namespace adl {
|
||||||
|
class object;
|
||||||
|
}
|
||||||
|
using adl::object;
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::scope lua_register_expedition();
|
||||||
|
luabind::scope lua_register_expedition_lock_messages();
|
||||||
|
|
||||||
|
class Lua_Expedition : public Lua_Ptr<Expedition>
|
||||||
|
{
|
||||||
|
typedef Expedition NativeType;
|
||||||
|
public:
|
||||||
|
Lua_Expedition() : Lua_Ptr(nullptr) { }
|
||||||
|
Lua_Expedition(Expedition *d) : Lua_Ptr(d) { }
|
||||||
|
virtual ~Lua_Expedition() { }
|
||||||
|
|
||||||
|
operator Expedition*() {
|
||||||
|
return reinterpret_cast<Expedition*>(GetLuaPtrData());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddLockout(std::string event_name, uint32_t seconds);
|
||||||
|
void AddLockoutDuration(std::string event_name, int seconds);
|
||||||
|
void AddLockoutDuration(std::string event_name, int seconds, bool members_only);
|
||||||
|
void AddReplayLockout(uint32_t seconds);
|
||||||
|
void AddReplayLockoutDuration(int seconds);
|
||||||
|
void AddReplayLockoutDuration(int seconds, bool members_only);
|
||||||
|
uint32_t GetDynamicZoneID();
|
||||||
|
uint32_t GetID();
|
||||||
|
int GetInstanceID();
|
||||||
|
std::string GetLeaderName();
|
||||||
|
luabind::object GetLockouts(lua_State* L);
|
||||||
|
std::string GetLootEventByNPCTypeID(uint32_t npc_type_id);
|
||||||
|
std::string GetLootEventBySpawnID(uint32_t spawn_id);
|
||||||
|
uint32_t GetMemberCount();
|
||||||
|
luabind::object GetMembers(lua_State* L);
|
||||||
|
std::string GetName();
|
||||||
|
int GetSecondsRemaining();
|
||||||
|
std::string GetUUID();
|
||||||
|
int GetZoneID();
|
||||||
|
std::string GetZoneName();
|
||||||
|
int GetZoneVersion();
|
||||||
|
bool HasLockout(std::string event_name);
|
||||||
|
bool HasReplayLockout();
|
||||||
|
void RemoveCompass();
|
||||||
|
void RemoveLockout(std::string event_name);
|
||||||
|
void SetCompass(uint32_t zone_id, float x, float y, float z);
|
||||||
|
void SetCompass(std::string zone_name, float x, float y, float z);
|
||||||
|
void SetLocked(bool lock_expedition);
|
||||||
|
void SetLocked(bool lock_expedition, int lock_msg);
|
||||||
|
void SetLocked(bool lock_expedition, int lock_msg, uint32_t color);
|
||||||
|
void SetLootEventByNPCTypeID(uint32_t npc_type_id, std::string event_name);
|
||||||
|
void SetLootEventBySpawnID(uint32_t spawn_id, std::string event_name);
|
||||||
|
void SetReplayLockoutOnMemberJoin(bool enable);
|
||||||
|
void SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading);
|
||||||
|
void SetSafeReturn(std::string zone_name, float x, float y, float z, float heading);
|
||||||
|
void SetSecondsRemaining(uint32_t seconds_remaining);
|
||||||
|
void SetZoneInLocation(float x, float y, float z, float heading);
|
||||||
|
void UpdateLockoutDuration(std::string event_name, uint32_t duration);
|
||||||
|
void UpdateLockoutDuration(std::string event_name, uint32_t duration, bool members_only);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LUA_EQEMU
|
||||||
|
#endif // EQEMU_LUA_EXPEDITION_H
|
||||||
@ -18,12 +18,14 @@
|
|||||||
#include "lua_client.h"
|
#include "lua_client.h"
|
||||||
#include "lua_npc.h"
|
#include "lua_npc.h"
|
||||||
#include "lua_entity_list.h"
|
#include "lua_entity_list.h"
|
||||||
|
#include "lua_expedition.h"
|
||||||
#include "quest_parser_collection.h"
|
#include "quest_parser_collection.h"
|
||||||
#include "questmgr.h"
|
#include "questmgr.h"
|
||||||
#include "qglobals.h"
|
#include "qglobals.h"
|
||||||
#include "encounter.h"
|
#include "encounter.h"
|
||||||
#include "lua_encounter.h"
|
#include "lua_encounter.h"
|
||||||
#include "data_bucket.h"
|
#include "data_bucket.h"
|
||||||
|
#include "expedition.h"
|
||||||
|
|
||||||
struct Events { };
|
struct Events { };
|
||||||
struct Factions { };
|
struct Factions { };
|
||||||
@ -766,6 +768,14 @@ void lua_world_emote(int type, const char *str) {
|
|||||||
quest_manager.we(type, str);
|
quest_manager.we(type, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lua_message(int color, const char *message) {
|
||||||
|
quest_manager.message(color, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lua_whisper(const char *message) {
|
||||||
|
quest_manager.whisper(message);
|
||||||
|
}
|
||||||
|
|
||||||
int lua_get_level(int type) {
|
int lua_get_level(int type) {
|
||||||
return quest_manager.getlevel(type);
|
return quest_manager.getlevel(type);
|
||||||
}
|
}
|
||||||
@ -806,6 +816,14 @@ int lua_count_item(uint32 item_id) {
|
|||||||
return quest_manager.countitem(item_id);
|
return quest_manager.countitem(item_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lua_remove_item(uint32 item_id) {
|
||||||
|
quest_manager.removeitem(item_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lua_remove_item(uint32 item_id, uint32 quantity) {
|
||||||
|
quest_manager.removeitem(item_id, quantity);
|
||||||
|
}
|
||||||
|
|
||||||
void lua_update_spawn_timer(uint32 id, uint32 new_time) {
|
void lua_update_spawn_timer(uint32 id, uint32 new_time) {
|
||||||
quest_manager.UpdateSpawnTimer(id, new_time);
|
quest_manager.UpdateSpawnTimer(id, new_time);
|
||||||
}
|
}
|
||||||
@ -2170,6 +2188,118 @@ void lua_set_content_flag(std::string flag_name, bool enabled){
|
|||||||
ZoneStore::SetContentFlag(flag_name, enabled);
|
ZoneStore::SetContentFlag(flag_name, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lua_Expedition lua_get_expedition() {
|
||||||
|
if (zone && zone->GetInstanceID() != 0)
|
||||||
|
{
|
||||||
|
return Expedition::FindCachedExpeditionByZoneInstance(zone->GetZoneID(), zone->GetInstanceID());
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lua_Expedition lua_get_expedition_by_char_id(uint32 char_id) {
|
||||||
|
return Expedition::FindCachedExpeditionByCharacterID(char_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Lua_Expedition lua_get_expedition_by_dz_id(uint32 dz_id) {
|
||||||
|
return Expedition::FindCachedExpeditionByDynamicZoneID(dz_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Lua_Expedition lua_get_expedition_by_zone_instance(uint32 zone_id, uint32 instance_id) {
|
||||||
|
return Expedition::FindCachedExpeditionByZoneInstance(zone_id, instance_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object lua_get_expedition_lockout_by_char_id(lua_State* L, uint32 char_id, std::string expedition_name, std::string event_name) {
|
||||||
|
luabind::adl::object lua_table = luabind::newtable(L);
|
||||||
|
|
||||||
|
auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id);
|
||||||
|
|
||||||
|
auto it = std::find_if(lockouts.begin(), lockouts.end(), [&](const ExpeditionLockoutTimer& lockout) {
|
||||||
|
return lockout.IsSameLockout(expedition_name, event_name);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != lockouts.end())
|
||||||
|
{
|
||||||
|
lua_table["remaining"] = it->GetSecondsRemaining();
|
||||||
|
lua_table["uuid"] = it->GetExpeditionUUID();
|
||||||
|
}
|
||||||
|
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object lua_get_expedition_lockouts_by_char_id(lua_State* L, uint32 char_id) {
|
||||||
|
luabind::adl::object lua_table = luabind::newtable(L);
|
||||||
|
|
||||||
|
auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id);
|
||||||
|
for (const auto& lockout : lockouts)
|
||||||
|
{
|
||||||
|
auto lockout_table = lua_table[lockout.GetExpeditionName()];
|
||||||
|
if (luabind::type(lockout_table) != LUA_TTABLE)
|
||||||
|
{
|
||||||
|
lockout_table = luabind::newtable(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto event_table = lockout_table[lockout.GetEventName()];
|
||||||
|
if (luabind::type(event_table) != LUA_TTABLE)
|
||||||
|
{
|
||||||
|
event_table = luabind::newtable(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
event_table["remaining"] = lockout.GetSecondsRemaining();
|
||||||
|
event_table["uuid"] = lockout.GetExpeditionUUID();
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
luabind::object lua_get_expedition_lockouts_by_char_id(lua_State* L, uint32 char_id, std::string expedition_name) {
|
||||||
|
luabind::adl::object lua_table = luabind::newtable(L);
|
||||||
|
|
||||||
|
auto lockouts = Expedition::GetExpeditionLockoutsByCharacterID(char_id);
|
||||||
|
for (const auto& lockout : lockouts)
|
||||||
|
{
|
||||||
|
if (lockout.GetExpeditionName() == expedition_name)
|
||||||
|
{
|
||||||
|
auto event_table = lua_table[lockout.GetEventName()];
|
||||||
|
if (luabind::type(event_table) != LUA_TTABLE)
|
||||||
|
{
|
||||||
|
event_table = luabind::newtable(L);
|
||||||
|
}
|
||||||
|
event_table["remaining"] = lockout.GetSecondsRemaining();
|
||||||
|
event_table["uuid"] = lockout.GetExpeditionUUID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lua_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lua_add_expedition_lockout_all_clients(std::string expedition_name, std::string event_name, uint32 seconds) {
|
||||||
|
auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds);
|
||||||
|
Expedition::AddLockoutClients(lockout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lua_add_expedition_lockout_all_clients(std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid) {
|
||||||
|
auto lockout = ExpeditionLockoutTimer::CreateLockout(expedition_name, event_name, seconds, uuid);
|
||||||
|
Expedition::AddLockoutClients(lockout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lua_add_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name, uint32 seconds) {
|
||||||
|
Expedition::AddLockoutByCharacterID(char_id, expedition_name, event_name, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lua_add_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name, uint32 seconds, std::string uuid) {
|
||||||
|
Expedition::AddLockoutByCharacterID(char_id, expedition_name, event_name, seconds, uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lua_remove_expedition_lockout_by_char_id(uint32 char_id, std::string expedition_name, std::string event_name) {
|
||||||
|
Expedition::RemoveLockoutsByCharacterID(char_id, expedition_name, event_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lua_remove_all_expedition_lockouts_by_char_id(uint32 char_id) {
|
||||||
|
Expedition::RemoveLockoutsByCharacterID(char_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lua_remove_all_expedition_lockouts_by_char_id(uint32 char_id, std::string expedition_name) {
|
||||||
|
Expedition::RemoveLockoutsByCharacterID(char_id, expedition_name);
|
||||||
|
}
|
||||||
|
|
||||||
#define LuaCreateNPCParse(name, c_type, default_value) do { \
|
#define LuaCreateNPCParse(name, c_type, default_value) do { \
|
||||||
cur = table[#name]; \
|
cur = table[#name]; \
|
||||||
if(luabind::type(cur) != LUA_TNIL) { \
|
if(luabind::type(cur) != LUA_TNIL) { \
|
||||||
@ -2477,6 +2607,8 @@ luabind::scope lua_register_general() {
|
|||||||
luabind::def("clear_spawn_timers", &lua_clear_spawn_timers),
|
luabind::def("clear_spawn_timers", &lua_clear_spawn_timers),
|
||||||
luabind::def("zone_emote", &lua_zone_emote),
|
luabind::def("zone_emote", &lua_zone_emote),
|
||||||
luabind::def("world_emote", &lua_world_emote),
|
luabind::def("world_emote", &lua_world_emote),
|
||||||
|
luabind::def("message", &lua_message),
|
||||||
|
luabind::def("whisper", &lua_whisper),
|
||||||
luabind::def("get_level", &lua_get_level),
|
luabind::def("get_level", &lua_get_level),
|
||||||
luabind::def("create_ground_object", (void(*)(uint32,float,float,float,float))&lua_create_ground_object),
|
luabind::def("create_ground_object", (void(*)(uint32,float,float,float,float))&lua_create_ground_object),
|
||||||
luabind::def("create_ground_object", (void(*)(uint32,float,float,float,float,uint32))&lua_create_ground_object),
|
luabind::def("create_ground_object", (void(*)(uint32,float,float,float,float,uint32))&lua_create_ground_object),
|
||||||
@ -2487,6 +2619,8 @@ luabind::scope lua_register_general() {
|
|||||||
luabind::def("modify_npc_stat", &lua_modify_npc_stat),
|
luabind::def("modify_npc_stat", &lua_modify_npc_stat),
|
||||||
luabind::def("collect_items", &lua_collect_items),
|
luabind::def("collect_items", &lua_collect_items),
|
||||||
luabind::def("count_item", &lua_count_item),
|
luabind::def("count_item", &lua_count_item),
|
||||||
|
luabind::def("remove_item", (void(*)(uint32))&lua_remove_item),
|
||||||
|
luabind::def("remove_item", (void(*)(uint32,uint32))&lua_remove_item),
|
||||||
luabind::def("update_spawn_timer", &lua_update_spawn_timer),
|
luabind::def("update_spawn_timer", &lua_update_spawn_timer),
|
||||||
luabind::def("merchant_set_item", (void(*)(uint32,uint32))&lua_merchant_set_item),
|
luabind::def("merchant_set_item", (void(*)(uint32,uint32))&lua_merchant_set_item),
|
||||||
luabind::def("merchant_set_item", (void(*)(uint32,uint32,uint32))&lua_merchant_set_item),
|
luabind::def("merchant_set_item", (void(*)(uint32,uint32,uint32))&lua_merchant_set_item),
|
||||||
@ -2765,7 +2899,22 @@ luabind::scope lua_register_general() {
|
|||||||
* Content flags
|
* Content flags
|
||||||
*/
|
*/
|
||||||
luabind::def("is_content_flag_enabled", (bool(*)(std::string))&lua_is_content_flag_enabled),
|
luabind::def("is_content_flag_enabled", (bool(*)(std::string))&lua_is_content_flag_enabled),
|
||||||
luabind::def("set_content_flag", (void(*)(std::string, bool))&lua_set_content_flag)
|
luabind::def("set_content_flag", (void(*)(std::string, bool))&lua_set_content_flag),
|
||||||
|
|
||||||
|
luabind::def("get_expedition", &lua_get_expedition),
|
||||||
|
luabind::def("get_expedition_by_char_id", &lua_get_expedition_by_char_id),
|
||||||
|
luabind::def("get_expedition_by_dz_id", &lua_get_expedition_by_dz_id),
|
||||||
|
luabind::def("get_expedition_by_zone_instance", &lua_get_expedition_by_zone_instance),
|
||||||
|
luabind::def("get_expedition_lockout_by_char_id", &lua_get_expedition_lockout_by_char_id),
|
||||||
|
luabind::def("get_expedition_lockouts_by_char_id", (luabind::object(*)(lua_State*, uint32))&lua_get_expedition_lockouts_by_char_id),
|
||||||
|
luabind::def("get_expedition_lockouts_by_char_id", (luabind::object(*)(lua_State*, uint32, std::string))&lua_get_expedition_lockouts_by_char_id),
|
||||||
|
luabind::def("add_expedition_lockout_all_clients", (void(*)(std::string, std::string, uint32))&lua_add_expedition_lockout_all_clients),
|
||||||
|
luabind::def("add_expedition_lockout_all_clients", (void(*)(std::string, std::string, uint32, std::string))&lua_add_expedition_lockout_all_clients),
|
||||||
|
luabind::def("add_expedition_lockout_by_char_id", (void(*)(uint32, std::string, std::string, uint32))&lua_add_expedition_lockout_by_char_id),
|
||||||
|
luabind::def("add_expedition_lockout_by_char_id", (void(*)(uint32, std::string, std::string, uint32, std::string))&lua_add_expedition_lockout_by_char_id),
|
||||||
|
luabind::def("remove_expedition_lockout_by_char_id", &lua_remove_expedition_lockout_by_char_id),
|
||||||
|
luabind::def("remove_all_expedition_lockouts_by_char_id", (void(*)(uint32))&lua_remove_all_expedition_lockouts_by_char_id),
|
||||||
|
luabind::def("remove_all_expedition_lockouts_by_char_id", (void(*)(uint32, std::string))&lua_remove_all_expedition_lockouts_by_char_id)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3254,7 +3403,24 @@ luabind::scope lua_register_message_types() {
|
|||||||
return luabind::class_<MessageTypes>("MT")
|
return luabind::class_<MessageTypes>("MT")
|
||||||
.enum_("constants")
|
.enum_("constants")
|
||||||
[
|
[
|
||||||
|
luabind::value("White", Chat::White),
|
||||||
|
luabind::value("DimGray", Chat::DimGray),
|
||||||
|
luabind::value("Default", Chat::Default),
|
||||||
|
luabind::value("Green", Chat::Green),
|
||||||
|
luabind::value("BrightBlue", Chat::BrightBlue),
|
||||||
|
luabind::value("LightBlue", Chat::LightBlue),
|
||||||
|
luabind::value("Magenta", Chat::Magenta),
|
||||||
|
luabind::value("Gray", Chat::Gray),
|
||||||
|
luabind::value("LightGray", Chat::LightGray),
|
||||||
luabind::value("NPCQuestSay", Chat::NPCQuestSay),
|
luabind::value("NPCQuestSay", Chat::NPCQuestSay),
|
||||||
|
luabind::value("DarkGray", Chat::DarkGray),
|
||||||
|
luabind::value("Red", Chat::Red),
|
||||||
|
luabind::value("Lime", Chat::Lime),
|
||||||
|
luabind::value("Yellow", Chat::Yellow),
|
||||||
|
luabind::value("Blue", Chat::Blue),
|
||||||
|
luabind::value("LightNavy", Chat::LightNavy),
|
||||||
|
luabind::value("Cyan", Chat::Cyan),
|
||||||
|
luabind::value("Black", Chat::Black),
|
||||||
luabind::value("Say", Chat::Say),
|
luabind::value("Say", Chat::Say),
|
||||||
luabind::value("Tell", Chat::Tell),
|
luabind::value("Tell", Chat::Tell),
|
||||||
luabind::value("Group", Chat::Group),
|
luabind::value("Group", Chat::Group),
|
||||||
|
|||||||
@ -107,6 +107,18 @@ Lua_Mob Lua_Group::GetMember(int index) {
|
|||||||
return self->members[index];
|
return self->members[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Lua_Group::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name)
|
||||||
|
{
|
||||||
|
Lua_Safe_Call_Bool();
|
||||||
|
return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Lua_Group::DoesAnyMemberHaveExpeditionLockout(std::string expedition_name, std::string event_name, int max_check_count)
|
||||||
|
{
|
||||||
|
Lua_Safe_Call_Bool();
|
||||||
|
return self->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name, max_check_count);
|
||||||
|
}
|
||||||
|
|
||||||
luabind::scope lua_register_group() {
|
luabind::scope lua_register_group() {
|
||||||
return luabind::class_<Lua_Group>("Group")
|
return luabind::class_<Lua_Group>("Group")
|
||||||
.def(luabind::constructor<>())
|
.def(luabind::constructor<>())
|
||||||
@ -129,7 +141,9 @@ luabind::scope lua_register_group() {
|
|||||||
.def("GetLowestLevel", (int(Lua_Group::*)(void))&Lua_Group::GetLowestLevel)
|
.def("GetLowestLevel", (int(Lua_Group::*)(void))&Lua_Group::GetLowestLevel)
|
||||||
.def("TeleportGroup", (void(Lua_Group::*)(Lua_Mob,uint32,uint32,float,float,float,float))&Lua_Group::TeleportGroup)
|
.def("TeleportGroup", (void(Lua_Group::*)(Lua_Mob,uint32,uint32,float,float,float,float))&Lua_Group::TeleportGroup)
|
||||||
.def("GetID", (int(Lua_Group::*)(void))&Lua_Group::GetID)
|
.def("GetID", (int(Lua_Group::*)(void))&Lua_Group::GetID)
|
||||||
.def("GetMember", (Lua_Mob(Lua_Group::*)(int))&Lua_Group::GetMember);
|
.def("GetMember", (Lua_Mob(Lua_Group::*)(int))&Lua_Group::GetMember)
|
||||||
|
.def("DoesAnyMemberHaveExpeditionLockout", (bool(Lua_Group::*)(std::string, std::string))&Lua_Group::DoesAnyMemberHaveExpeditionLockout)
|
||||||
|
.def("DoesAnyMemberHaveExpeditionLockout", (bool(Lua_Group::*)(std::string, std::string, int))&Lua_Group::DoesAnyMemberHaveExpeditionLockout);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user