diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 4e85f25dc..0e1bb877b 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -106,6 +106,7 @@ SET(zone_sources perl_client.cpp perl_doors.cpp perl_entity.cpp + perl_expedition.cpp perl_groups.cpp perl_hateentry.cpp perl_mob.cpp diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 671a26d9c..087e44663 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -971,6 +971,9 @@ void PerlembParser::MapFunctions() "package Doors;" "&boot_Doors;" // load quest Doors XS + "package Expedition;" + "&boot_Expedition;" + #endif "package main;" "}" diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 1ae4c22c1..706e7a9a0 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -29,6 +29,7 @@ #include "embparser.h" #include "embxs.h" #include "entity.h" +#include "expedition.h" #include "queryserv.h" #include "questmgr.h" #include "zone.h" @@ -6059,6 +6060,251 @@ XS(XS__SetContentFlag) 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::FindCachedExpeditionByInstanceID(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_instance_id); +XS(XS__get_expedition_by_instance_id) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: quest::GetExpeditionByInstanceID(uint16 instance_id)"); + } + + uint16 instance_id = (uint16)SvUV(ST(0)); + + Expedition* RETVAL = Expedition::FindCachedExpeditionByInstanceID(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(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", 9, newSVuv(it->GetSecondsRemaining()), 0); + hv_store(hash, "uuid", 4, 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(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(lockout.GetExpeditionName().size()); + uint32_t event_len = static_cast(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", 9, newSVuv(lockout.GetSecondsRemaining()), 0); + hv_store(details_hash, "uuid", 4, 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() && hash_ref) + { + rv = sv_2mortal(hash_ref); // ref that owns event hash + } + 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(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(SvUV(ST(0))); + std::string expedition_name = SvPV_nolen(ST(1)); + std::string event_name = SvPV_nolen(ST(2)); + uint32_t seconds = static_cast(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(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(SvUV(ST(0))); + Expedition::RemoveLockoutsByCharacterID(character_id, expedition_name); + + XSRETURN_EMPTY; +} + /* This is the callback perl will look for to setup the quest package's XSUBs @@ -6129,6 +6375,7 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "activespeakactivity"), XS__activespeakactivity, file); newXS(strcpy(buf, "activespeaktask"), XS__activespeaktask, file); newXS(strcpy(buf, "activetasksinset"), XS__activetasksinset, 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, "addldonpoints"), XS__addldonpoints, file); newXS(strcpy(buf, "addldonwin"), XS__addldonpoints, file); @@ -6263,6 +6510,11 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "getcharidbyname"), XS__getcharidbyname, file); newXS(strcpy(buf, "getclassname"), XS__getclassname, 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_instance_id"), XS__get_expedition_by_instance_id, 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, "getitemname"), XS__getitemname, file); newXS(strcpy(buf, "getItemName"), XS_qc_getItemName, file); @@ -6328,6 +6580,8 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "rain"), XS__rain, file); newXS(strcpy(buf, "rebind"), XS__rebind, 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, "repopzone"), XS__repopzone, file); diff --git a/zone/embperl.cpp b/zone/embperl.cpp index c7ebb8060..ce584c799 100644 --- a/zone/embperl.cpp +++ b/zone/embperl.cpp @@ -37,6 +37,7 @@ EXTERN_C XS(boot_HateEntry); EXTERN_C XS(boot_Object); EXTERN_C XS(boot_Doors); EXTERN_C XS(boot_PerlPacket); +EXTERN_C XS(boot_Expedition); #endif #endif @@ -87,6 +88,7 @@ EXTERN_C void xs_init(pTHX) newXS(strcpy(buf, "HateEntry::boot_HateEntry"), boot_HateEntry, file); newXS(strcpy(buf, "Object::boot_Object"), boot_Object, file); newXS(strcpy(buf, "Doors::boot_Doors"), boot_Doors, file); + newXS(strcpy(buf, "Expedition::boot_Expedition"), boot_Expedition, file); ; #endif #endif diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 82cf3b730..f7cb160be 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -37,12 +37,26 @@ #endif #include "client.h" +#include "expedition.h" #include "titles.h" #ifdef THIS /* this macro seems to leak out on some systems */ #undef THIS #endif +#define VALIDATE_THIS_IS_CLIENT \ + do { \ + if (sv_derived_from(ST(0), "Client")) { \ + IV tmp = SvIV((SV*)SvRV(ST(0))); \ + THIS = INT2PTR(Client*, tmp); \ + } else { \ + Perl_croak(aTHX_ "THIS is not of type Client"); \ + } \ + if (THIS == nullptr) { \ + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ + } \ + } while (0); + XS(XS_Client_SendSound); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_SendSound) { dXSARGS; @@ -6759,6 +6773,286 @@ XS(XS_Client_GetClientMaxLevel) { XSRETURN(1); } +XS(XS_Client_CreateExpedition); +XS(XS_Client_CreateExpedition) { + dXSARGS; + if (items != 7 && items != 8) { + Perl_croak(aTHX_ "Usage: Client::CreateExpedition(THIS, string zone_name, uint32 zone_version, " + "uint32 duration, string expedition_name, uint32 min_players, uint32 max_players, " + "[, bool disable_messages = false])"); + } + + Client* THIS = nullptr; + VALIDATE_THIS_IS_CLIENT; + + std::string zone_name(SvPV_nolen(ST(1))); + uint32 zone_version = (uint32)SvUV(ST(2)); + uint32 duration = (uint32)SvUV(ST(3)); + std::string expedition_name(SvPV_nolen(ST(4))); + uint32 min_players = (uint32)SvUV(ST(5)); + uint32 max_players = (uint32)SvUV(ST(6)); + bool disable_messages = (items > 7) ? (bool)SvTRUE(ST(7)) : false; + + Expedition* RETVAL = THIS->CreateExpedition(zone_name, zone_version, duration, + expedition_name, min_players, max_players, disable_messages); + + ST(0) = sv_newmortal(); + sv_setref_pv(ST(0), "Expedition", (void*)RETVAL); + + XSRETURN(1); +} + +XS(XS_Client_GetExpedition); +XS(XS_Client_GetExpedition) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Client::GetExpedition(THIS)"); + } + Client* THIS = nullptr; + VALIDATE_THIS_IS_CLIENT; + + Expedition* RETVAL = THIS->GetExpedition(); + + ST(0) = sv_newmortal(); + sv_setref_pv(ST(0), "Expedition", (void*)RETVAL); + + XSRETURN(1); +} + +XS(XS_Client_GetExpeditionLockouts); +XS(XS_Client_GetExpeditionLockouts) { + dXSARGS; + if (items != 1 && items != 2) { + Perl_croak(aTHX_ "Usage: Client::GetExpeditionLockouts(THIS [, string expedition_name])"); + } + + Client* THIS = nullptr; + VALIDATE_THIS_IS_CLIENT; + + HV* hash = newHV(); + SV* hash_ref = nullptr; // for expedition event hash if filtering on expedition + + std::string expedition_name; + if (items == 2) + { + expedition_name = SvPV_nolen(ST(1)); + } + + auto lockouts = THIS->GetExpeditionLockouts(); + + for (const auto& lockout : lockouts) + { + uint32_t name_len = static_cast(lockout.GetExpeditionName().size()); + uint32_t event_len = static_cast(lockout.GetEventName().size()); + + SV** entry = hv_fetch(hash, lockout.GetExpeditionName().c_str(), name_len, false); + if (!entry) + { + SV* event_hash_ref = newRV_noinc((SV*)newHV()); // takes ownership of hash + if (!expedition_name.empty() && lockout.GetExpeditionName() == expedition_name) + { + hash_ref = event_hash_ref; // save ref to event hash for return + } + entry = hv_store(hash, lockout.GetExpeditionName().c_str(), name_len, event_hash_ref, 0); + } + + if (entry && SvROK(*entry) && SvTYPE(SvRV(*entry)) == SVt_PVHV) + { + HV* event_hash = (HV*)SvRV(*entry); + hv_store(event_hash, lockout.GetEventName().c_str(), event_len, + newSVuv(lockout.GetSecondsRemaining()), 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)); // owns expedition hash + } + + ST(0) = rv; + XSRETURN(1); +} + +XS(XS_Client_GetLockoutExpeditionUUID); +XS(XS_Client_GetLockoutExpeditionUUID) { + dXSARGS; + if (items != 3) { + Perl_croak(aTHX_ "Usage: Client::GetLockoutExpeditionUUID(THIS, string expedition_name, string event_name)"); + } + + Client* THIS = nullptr; + VALIDATE_THIS_IS_CLIENT; + + std::string expedition_name = SvPV_nolen(ST(1)); + std::string event_name = SvPV_nolen(ST(2)); + + auto lockout = THIS->GetExpeditionLockout(expedition_name, event_name); + if (lockout) + { + XSRETURN_PV(lockout->GetExpeditionUUID().c_str()); + } + + XSRETURN_UNDEF; +} + +XS(XS_Client_AddExpeditionLockout); +XS(XS_Client_AddExpeditionLockout) { + dXSARGS; + if (items != 4 && items != 5) { + Perl_croak(aTHX_ "Usage: Client::AddExpeditionLockout(THIS, string expedition_name, string event_name, uint32 seconds [, string uuid])"); + } + + Client* THIS = nullptr; + VALIDATE_THIS_IS_CLIENT; + + std::string expedition_name(SvPV_nolen(ST(1))); + std::string event_name(SvPV_nolen(ST(2))); + uint32 seconds = (uint32)SvUV(ST(3)); + std::string uuid; + + if (items == 5) + { + uuid = SvPV_nolen(ST(4)); + } + + THIS->AddNewExpeditionLockout(expedition_name, event_name, seconds, uuid); + + XSRETURN_EMPTY; +} + +XS(XS_Client_AddExpeditionLockoutDuration); +XS(XS_Client_AddExpeditionLockoutDuration) { + dXSARGS; + if (items != 4 && items != 5) { + Perl_croak(aTHX_ "Usage: Client::AddExpeditionLockoutDuration(THIS, string expedition_name, string event_name, int seconds [, string uuid])"); + } + + Client* THIS = nullptr; + VALIDATE_THIS_IS_CLIENT; + + std::string expedition_name(SvPV_nolen(ST(1))); + std::string event_name(SvPV_nolen(ST(2))); + int seconds = static_cast(SvUV(ST(3))); + std::string uuid; + + if (items == 5) + { + uuid = SvPV_nolen(ST(4)); + } + + THIS->AddExpeditionLockoutDuration(expedition_name, event_name, seconds, uuid, true); + + XSRETURN_EMPTY; +} + +XS(XS_Client_RemoveAllExpeditionLockouts); +XS(XS_Client_RemoveAllExpeditionLockouts) { + dXSARGS; + if (items != 1 && items != 2) { + Perl_croak(aTHX_ "Usage: Client::RemoveAllExpeditionLockouts(THIS [, string expedition_name])"); + } + + Client* THIS = nullptr; + VALIDATE_THIS_IS_CLIENT; + + std::string expedition_name; + if (items == 2) + { + expedition_name = SvPV_nolen(ST(1)); + } + + THIS->RemoveAllExpeditionLockouts(expedition_name, true); + + XSRETURN_EMPTY; +} + +XS(XS_Client_RemoveExpeditionLockout); +XS(XS_Client_RemoveExpeditionLockout) { + dXSARGS; + if (items != 3) { + Perl_croak(aTHX_ "Usage: Client::RemoveExpeditionLockout(THIS, string expedition_name, string event_name)"); + } + + Client* THIS = nullptr; + VALIDATE_THIS_IS_CLIENT; + + std::string expedition_name(SvPV_nolen(ST(1))); + std::string event_name(SvPV_nolen(ST(2))); + + THIS->RemoveExpeditionLockout(expedition_name, event_name, true); + + XSRETURN_EMPTY; +} + +XS(XS_Client_HasExpeditionLockout); +XS(XS_Client_HasExpeditionLockout) { + dXSARGS; + if (items != 3) { + Perl_croak(aTHX_ "Usage: Client::HasExpeditionLockout(THIS, string expedition_name, string event_name)"); + } + + Client* THIS = nullptr; + VALIDATE_THIS_IS_CLIENT; + + std::string expedition_name(SvPV_nolen(ST(1))); + std::string event_name(SvPV_nolen(ST(2))); + + bool result = THIS->HasExpeditionLockout(expedition_name, event_name); + ST(0) = boolSV(result); + + XSRETURN(1); +} + +XS(XS_Client_MovePCDynamicZone); +XS(XS_Client_MovePCDynamicZone) { + dXSARGS; + if (items != 2 && items != 3 && items != 4) { + Perl_croak(aTHX_ "Usage: Client::MovePCDynamicZone(THIS, uint32 zone_id [, int zone_version = -1, bool message_if_invalid = true])\n" + "Usage: Client::MovePCDynamicZone(THIS, string zone_name [, int zone_version = -1, bool message_if_invalid = true])"); + } + + Client* THIS = nullptr; + VALIDATE_THIS_IS_CLIENT; + + if (SvTYPE(ST(1)) == SVt_PV) + { + std::string zone_name(SvPV_nolen(ST(1))); + int zone_version = (items >= 3) ? static_cast(SvIV(ST(2))) : -1; + if (items == 4) + { + THIS->MovePCDynamicZone(zone_name, zone_version, (bool)SvTRUE(ST(3))); + } + else + { + THIS->MovePCDynamicZone(zone_name, zone_version); + } + } + else if (SvTYPE(ST(1)) == SVt_IV) + { + uint32 zone_id = (uint32)SvUV(ST(1)); + int zone_version = (items >= 3) ? static_cast(SvIV(ST(2))) : -1; + if (items == 3) + { + THIS->MovePCDynamicZone(zone_id, zone_version, (bool)SvTRUE(ST(2))); + } + else + { + THIS->MovePCDynamicZone(zone_id, zone_version); + } + } + else + { + Perl_croak(aTHX_ "Client::MovePCDynamicZone expected an integer or string"); + } + + XSRETURN_EMPTY; +} #ifdef __cplusplus extern "C" @@ -6786,6 +7080,8 @@ XS(boot_Client) { newXSproto(strcpy(buf, "AddAlternateCurrencyValue"), XS_Client_AddAlternateCurrencyValue, file, "$$$"); newXSproto(strcpy(buf, "AddCrystals"), XS_Client_AddCrystals, file, "$$"); newXSproto(strcpy(buf, "AddEXP"), XS_Client_AddEXP, file, "$$;$$"); + newXSproto(strcpy(buf, "AddExpeditionLockout"), XS_Client_AddExpeditionLockout, file, "$$$$;$"); + newXSproto(strcpy(buf, "AddExpeditionLockoutDuration"), XS_Client_AddExpeditionLockoutDuration, file, "$$$$;$"); newXSproto(strcpy(buf, "AddLevelBasedExp"), XS_Client_AddLevelBasedExp, file, "$$;$$"); newXSproto(strcpy(buf, "AddMoneyToPP"), XS_Client_AddMoneyToPP, file, "$$$$$$"); newXSproto(strcpy(buf, "AddPVPPoints"), XS_Client_AddPVPPoints, file, "$$"); @@ -6804,6 +7100,7 @@ XS(boot_Client) { newXSproto(strcpy(buf, "CheckSpecializeIncrease"), XS_Client_CheckSpecializeIncrease, file, "$$"); newXSproto(strcpy(buf, "ClearCompassMark"), XS_Client_ClearCompassMark, file, "$"); newXSproto(strcpy(buf, "ClearZoneFlag"), XS_Client_ClearZoneFlag, file, "$$"); + newXSproto(strcpy(buf, "CreateExpedition"), XS_Client_CreateExpedition, file, "$$$$$$$;$"); newXSproto(strcpy(buf, "Connected"), XS_Client_Connected, file, "$"); newXSproto(strcpy(buf, "DecreaseByID"), XS_Client_DecreaseByID, file, "$$$"); newXSproto(strcpy(buf, "DeleteItemInInventory"), XS_Client_DeleteItemInInventory, file, "$$;$$"); @@ -6858,6 +7155,8 @@ XS(boot_Client) { newXSproto(strcpy(buf, "GetEndurance"), XS_Client_GetEndurance, file, "$"); newXSproto(strcpy(buf, "GetEnduranceRatio"), XS_Client_GetEnduranceRatio, file, "$"); newXSproto(strcpy(buf, "GetEXP"), XS_Client_GetEXP, file, "$"); + newXSproto(strcpy(buf, "GetExpedition"), XS_Client_GetExpedition, file, "$"); + newXSproto(strcpy(buf, "GetExpeditionLockouts"), XS_Client_GetExpeditionLockouts, file, "$;$"); newXSproto(strcpy(buf, "GetFace"), XS_Client_GetFace, file, "$"); newXSproto(strcpy(buf, "GetFactionLevel"), XS_Client_GetFactionLevel, file, "$$$$$$$$"); newXSproto(strcpy(buf, "GetFeigned"), XS_Client_GetFeigned, file, "$"); @@ -6880,6 +7179,7 @@ XS(boot_Client) { newXSproto(strcpy(buf, "GetLDoNPointsTheme"), XS_Client_GetLDoNPointsTheme, file, "$"); newXSproto(strcpy(buf, "GetLDoNWins"), XS_Client_GetLDoNWins, file, "$"); newXSproto(strcpy(buf, "GetLDoNWinsTheme"), XS_Client_GetLDoNWinsTheme, file, "$$"); + newXSproto(strcpy(buf, "GetLockoutExpeditionUUID"), XS_Client_GetLockoutExpeditionUUID, file, "$$$"); newXSproto(strcpy(buf, "GetMaxEndurance"), XS_Client_GetMaxEndurance, file, "$"); newXSproto(strcpy(buf, "GetModCharacterFactionLevel"), XS_Client_GetModCharacterFactionLevel, file, "$$"); newXSproto(strcpy(buf, "GetMoney"), XS_Client_GetMoney, file, "$$$"); @@ -6907,6 +7207,7 @@ XS(boot_Client) { newXSproto(strcpy(buf, "GrantAlternateAdvancementAbility"), XS_Client_GrantAlternateAdvancementAbility, file, "$$$;$"); newXSproto(strcpy(buf, "GuildID"), XS_Client_GuildID, file, "$"); newXSproto(strcpy(buf, "GuildRank"), XS_Client_GuildRank, file, "$"); + newXSproto(strcpy(buf, "HasExpeditionLockout"), XS_Client_HasExpeditionLockout, file, "$$$"); newXSproto(strcpy(buf, "HasSkill"), XS_Client_HasSkill, file, "$$"); newXSproto(strcpy(buf, "HasSpellScribed"), XS_Client_HasSkill, file, "$$"); newXSproto(strcpy(buf, "HasZoneFlag"), XS_Client_HasZoneFlag, file, "$$"); @@ -6938,6 +7239,7 @@ XS(boot_Client) { newXSproto(strcpy(buf, "MaxSkill"), XS_Client_MaxSkill, file, "$$;$$"); newXSproto(strcpy(buf, "MemSpell"), XS_Client_MemSpell, file, "$$$;$"); newXSproto(strcpy(buf, "MovePC"), XS_Client_MovePC, file, "$$$$$$"); + newXSproto(strcpy(buf, "MovePCDynamicZone"), XS_Client_MovePCDynamicZone, file, "$$;$$"); newXSproto(strcpy(buf, "MovePCInstance"), XS_Client_MovePCInstance, file, "$$$$$$$"); newXSproto(strcpy(buf, "MoveZone"), XS_Client_MoveZone, file, "$$"); newXSproto(strcpy(buf, "MoveZoneGroup"), XS_Client_MoveZoneGroup, file, "$$"); @@ -6954,6 +7256,8 @@ XS(boot_Client) { newXSproto(strcpy(buf, "QuestReward"), XS_Client_QuestReward, file, "$$;$$$$$$$"); newXSproto(strcpy(buf, "ReadBook"), XS_Client_ReadBook, file, "$$$"); newXSproto(strcpy(buf, "RefundAA"), XS_Client_RefundAA, file, "$$"); + newXSproto(strcpy(buf, "RemoveAllExpeditionLockouts"), XS_Client_RemoveAllExpeditionLockouts, file, "$;$"); + newXSproto(strcpy(buf, "RemoveExpeditionLockout"), XS_Client_RemoveExpeditionLockout, file, "$$$"); newXSproto(strcpy(buf, "RemoveNoRent"), XS_Client_RemoveNoRent, file, "$"); newXSproto(strcpy(buf, "ResetAA"), XS_Client_ResetAA, file, "$"); newXSproto(strcpy(buf, "ResetDisciplineTimer"), XS_Client_ResetDisciplineTimer, file, "$$"); diff --git a/zone/perl_expedition.cpp b/zone/perl_expedition.cpp new file mode 100644 index 000000000..468dce248 --- /dev/null +++ b/zone/perl_expedition.cpp @@ -0,0 +1,630 @@ +/** + * 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 "../common/features.h" + +#ifdef EMBPERL_XS_CLASSES + +#include "expedition.h" +#include "zone_store.h" +#include "embperl.h" +#include "../common/global_define.h" + +#ifdef seed +#undef seed +#endif + +#ifdef THIS /* this macro seems to leak out on some systems */ +#undef THIS +#endif + +#define VALIDATE_THIS_IS_EXPEDITION \ + do { \ + if (sv_derived_from(ST(0), "Expedition")) { \ + IV tmp = SvIV((SV*)SvRV(ST(0))); \ + THIS = INT2PTR(Expedition*, tmp); \ + } else { \ + Perl_croak(aTHX_ "THIS is not of type Expedition"); \ + } \ + if (THIS == nullptr) { \ + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); \ + } \ + } while (0); + +XS(XS_Expedition_AddLockout); +XS(XS_Expedition_AddLockout) { + dXSARGS; + if (items != 3) { + Perl_croak(aTHX_ "Usage: Expedition::AddLockout(THIS, string event_name, uint32 seconds)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + std::string event_name(SvPV_nolen(ST(1))); + uint32_t seconds = static_cast(SvUV(ST(2))); + + THIS->AddLockout(event_name, seconds); + + XSRETURN_EMPTY; +} + +XS(XS_Expedition_AddLockoutDuration); +XS(XS_Expedition_AddLockoutDuration) { + dXSARGS; + if (items != 3 && items != 4) { + Perl_croak(aTHX_ "Usage: Expedition::AddLockout(THIS, string event_name, int seconds [, bool members_only = true])"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + std::string event_name(SvPV_nolen(ST(1))); + int seconds = static_cast(SvUV(ST(2))); + if (items == 4) + { + bool members_only = (bool)SvTRUE(ST(3)); + THIS->AddLockoutDuration(event_name, seconds, members_only); + } + else + { + THIS->AddLockoutDuration(event_name, seconds); + } + + XSRETURN_EMPTY; +} +XS(XS_Expedition_AddReplayLockout); +XS(XS_Expedition_AddReplayLockout) { + dXSARGS; + if (items != 2) { + Perl_croak(aTHX_ "Usage: Expedition::AddReplayLockout(THIS, uint32 seconds)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + uint32_t seconds = static_cast(SvUV(ST(1))); + + THIS->AddReplayLockout(seconds); + + XSRETURN_EMPTY; +} + +XS(XS_Expedition_GetID); +XS(XS_Expedition_GetID) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::GetID(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + XSRETURN_UV(THIS->GetID()); +} + +XS(XS_Expedition_GetInstanceID); +XS(XS_Expedition_GetInstanceID) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::GetInstanceID(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + XSRETURN_UV(THIS->GetInstanceID()); +} + +XS(XS_Expedition_GetLeaderName); +XS(XS_Expedition_GetLeaderName) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::GetLeaderName(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + XSRETURN_PV(THIS->GetLeaderName().c_str()); +} + +XS(XS_Expedition_GetLockouts); +XS(XS_Expedition_GetLockouts) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::GetLockouts(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + HV* hash = newHV(); + + auto lockouts = THIS->GetLockouts(); + for (const auto& lockout : lockouts) + { + hv_store(hash, lockout.first.c_str(), static_cast(lockout.first.size()), + newSVuv(lockout.second.GetSecondsRemaining()), 0); + } + + ST(0) = sv_2mortal(newRV_noinc((SV*)hash)); // take ownership of hash (refcnt remains 1) + XSRETURN(1); +} + +XS(XS_Expedition_GetLootEventByNPCTypeID); +XS(XS_Expedition_GetLootEventByNPCTypeID) { + dXSARGS; + if (items != 2) { + Perl_croak(aTHX_ "Usage: Expedition::GetLootEventByNPCTypeID(THIS, uint32 npc_type_id)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + uint32_t npc_type_id = static_cast(SvUV(ST(1))); + + XSRETURN_PV(THIS->GetLootEventByNPCTypeID(npc_type_id).c_str()); +} + +XS(XS_Expedition_GetLootEventBySpawnID); +XS(XS_Expedition_GetLootEventBySpawnID) { + dXSARGS; + if (items != 2) { + Perl_croak(aTHX_ "Usage: Expedition::GetLootEventBySpawnID(THIS, uint32 spawn_id)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + uint32_t spawn_id = static_cast(SvUV(ST(1))); + + XSRETURN_PV(THIS->GetLootEventBySpawnID(spawn_id).c_str()); +} + +XS(XS_Expedition_GetMemberCount); +XS(XS_Expedition_GetMemberCount) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::GetMemberCount(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + XSRETURN_UV(THIS->GetMemberCount()); +} + +XS(XS_Expedition_GetMembers); +XS(XS_Expedition_GetMembers) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::GetMembers(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + HV* hash = newHV(); + + auto members = THIS->GetMembers(); + for (const auto& member : members) + { + hv_store(hash, member.name.c_str(), static_cast(member.name.size()), + newSVuv(member.char_id), 0); + } + + ST(0) = sv_2mortal(newRV_noinc((SV*)hash)); + XSRETURN(1); +} + +XS(XS_Expedition_GetName); +XS(XS_Expedition_GetName) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::GetName(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + XSRETURN_PV(THIS->GetName().c_str()); +} + +XS(XS_Expedition_GetSecondsRemaining); +XS(XS_Expedition_GetSecondsRemaining) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::GetSecondsRemaining(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + XSRETURN_UV(THIS->GetDynamicZone().GetSecondsRemaining()); +} + +XS(XS_Expedition_GetUUID); +XS(XS_Expedition_GetUUID) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::GetUUID(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + XSRETURN_PV(THIS->GetUUID().c_str()); +} + +XS(XS_Expedition_GetZoneID); +XS(XS_Expedition_GetZoneID) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::GetZoneID(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + XSRETURN_UV(THIS->GetDynamicZone().GetZoneID()); +} + +XS(XS_Expedition_GetZoneName); +XS(XS_Expedition_GetZoneName) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::GetZoneName(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + XSRETURN_PV(ZoneName(THIS->GetDynamicZone().GetZoneID())); +} + +XS(XS_Expedition_GetZoneVersion); +XS(XS_Expedition_GetZoneVersion) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::GetZoneVersion(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + XSRETURN_UV(THIS->GetDynamicZone().GetZoneVersion()); +} + +XS(XS_Expedition_HasLockout); +XS(XS_Expedition_HasLockout) { + dXSARGS; + if (items != 2) { + Perl_croak(aTHX_ "Usage: Expedition::HasLockout(THIS, string event_name)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + std::string event_name(SvPV_nolen(ST(1))); + + bool result = THIS->HasLockout(event_name); + ST(0) = boolSV(result); + XSRETURN(1); +} + +XS(XS_Expedition_HasReplayLockout); +XS(XS_Expedition_HasReplayLockout) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::HasReplayLockout(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + bool result = THIS->HasReplayLockout(); + ST(0) = boolSV(result); + XSRETURN(1); +} + +XS(XS_Expedition_RemoveCompass); +XS(XS_Expedition_RemoveCompass) { + dXSARGS; + if (items != 1) { + Perl_croak(aTHX_ "Usage: Expedition::RemoveCompass(THIS)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + THIS->SetDzCompass(0, 0, 0, 0, true); + + XSRETURN_EMPTY; +} + +XS(XS_Expedition_RemoveLockout); +XS(XS_Expedition_RemoveLockout) { + dXSARGS; + if (items != 2) { + Perl_croak(aTHX_ "Usage: Expedition::RemoveLockout(THIS, string event_name)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + std::string event_name(SvPV_nolen(ST(1))); + + THIS->RemoveLockout(event_name); + + XSRETURN_EMPTY; +} + +XS(XS_Expedition_SetCompass); +XS(XS_Expedition_SetCompass) { + dXSARGS; + if (items != 5) { + Perl_croak(aTHX_ "Usage: Expedition::SetCompass(THIS, uint32 zone_id|string zone_name, float x, float y, float z)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + float x = static_cast(SvNV(ST(2))); + float y = static_cast(SvNV(ST(3))); + float z = static_cast(SvNV(ST(4))); + + if (SvTYPE(ST(1)) == SVt_PV) + { + std::string zone_name(SvPV_nolen(ST(1))); + THIS->SetDzCompass(zone_name, x, y, z, true); + } + else if (SvTYPE(ST(1)) == SVt_IV) + { + uint32_t zone_id = static_cast(SvUV(ST(1))); + THIS->SetDzCompass(zone_id, x, y, z, true); + } + else + { + Perl_croak(aTHX_ "Expedition::SetCompass expected an integer or string"); + } + + XSRETURN_EMPTY; +} + +XS(XS_Expedition_SetLocked); +XS(XS_Expedition_SetLocked) { + dXSARGS; + if (items != 2 && items != 3 && items != 4) { + Perl_croak(aTHX_ "Usage: Expedition::SetLocked(THIS, bool locked [, int lock_msg = 0, uint32 color = 15])"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + bool locked = (bool)SvTRUE(ST(1)); + int lock_msg = (items == 3) ? static_cast(SvIV(ST(2))) : 0; + if (items == 4) + { + THIS->SetLocked(locked, static_cast(lock_msg), true, (uint32)SvUV(ST(3))); + } + else + { + THIS->SetLocked(locked, static_cast(lock_msg), true); + } + + XSRETURN_EMPTY; +} + +XS(XS_Expedition_SetLootEventByNPCTypeID); +XS(XS_Expedition_SetLootEventByNPCTypeID) { + dXSARGS; + if (items != 3) { + Perl_croak(aTHX_ "Usage: Expedition::SetLootEventByNPCTypeID(THIS, uint32 npc_type_id, string event_name)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + uint32_t npc_type_id = static_cast(SvUV(ST(1))); + std::string event_name(SvPV_nolen(ST(2))); + + THIS->SetLootEventByNPCTypeID(npc_type_id, event_name); + + XSRETURN_EMPTY; +} + +XS(XS_Expedition_SetLootEventBySpawnID); +XS(XS_Expedition_SetLootEventBySpawnID) { + dXSARGS; + if (items != 3) { + Perl_croak(aTHX_ "Usage: Expedition::SetLootEventBySpawnID(THIS, uint32 spawn_id, string event_name)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + uint32_t spawn_id = static_cast(SvUV(ST(1))); + std::string event_name(SvPV_nolen(ST(2))); + + THIS->SetLootEventBySpawnID(spawn_id, event_name); + + XSRETURN_EMPTY; +} + +XS(XS_Expedition_SetReplayLockoutOnMemberJoin); +XS(XS_Expedition_SetReplayLockoutOnMemberJoin) { + dXSARGS; + if (items != 2) { + Perl_croak(aTHX_ "Usage: Expedition::SetReplayLockoutOnMemberJoin(THIS, bool enable)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + bool enable = (bool)SvTRUE(ST(1)); + + THIS->SetReplayLockoutOnMemberJoin(enable, true); + + XSRETURN_EMPTY; +} + +XS(XS_Expedition_SetSafeReturn); +XS(XS_Expedition_SetSafeReturn) { + dXSARGS; + if (items != 6) { + Perl_croak(aTHX_ "Usage: Expedition::SetSafeReturn(THIS, uint32 zone_id|string zone_name, float x, float y, float z, float heading)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + float x = static_cast(SvNV(ST(2))); + float y = static_cast(SvNV(ST(3))); + float z = static_cast(SvNV(ST(4))); + float heading = static_cast(SvNV(ST(5))); + + if (SvTYPE(ST(1)) == SVt_PV) + { + std::string zone_name(SvPV_nolen(ST(1))); + THIS->SetDzSafeReturn(zone_name, x, y, z, heading, true); + } + else if (SvTYPE(ST(1)) == SVt_IV) + { + uint32_t zone_id = static_cast(SvUV(ST(1))); + THIS->SetDzSafeReturn(zone_id, x, y, z, heading, true); + } + else + { + Perl_croak(aTHX_ "Expedition::SetSafeReturn expected an integer or string"); + } + + XSRETURN_EMPTY; +} + +XS(XS_Expedition_SetSecondsRemaining); +XS(XS_Expedition_SetSecondsRemaining) { + dXSARGS; + if (items != 2) { + Perl_croak(aTHX_ "Usage: Expedition::SetSecondsRemaining(THIS, uint32 seconds_remaining)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + uint32_t seconds_remaining = static_cast(SvUV(ST(1))); + THIS->SetDzSecondsRemaining(seconds_remaining); + + XSRETURN_EMPTY; +} + +XS(XS_Expedition_SetZoneInLocation); +XS(XS_Expedition_SetZoneInLocation) { + dXSARGS; + if (items != 5) { + Perl_croak(aTHX_ "Usage: Expedition::SetZoneInLocation(THIS, float x, float y, float z, float heading)"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + float x = static_cast(SvNV(ST(1))); + float y = static_cast(SvNV(ST(2))); + float z = static_cast(SvNV(ST(3))); + float heading = static_cast(SvNV(ST(4))); + + THIS->SetDzZoneInLocation(x, y, z, heading, true); + + XSRETURN_EMPTY; +} + +XS(XS_Expedition_UpdateLockoutDuration); +XS(XS_Expedition_UpdateLockoutDuration) { + dXSARGS; + if (items != 3 && items != 4) { + Perl_croak(aTHX_ "Usage: Expedition::UpdateLockoutDuration(THIS, string event_name, uint32 seconds [, bool members_only])"); + } + + Expedition* THIS = nullptr; + VALIDATE_THIS_IS_EXPEDITION; + + std::string event_name(SvPV_nolen(ST(1))); + uint32_t seconds = static_cast(SvUV(ST(2))); + + if (items == 4) + { + bool members_only = (bool)SvTRUE(ST(3)); + THIS->UpdateLockoutDuration(event_name, seconds, members_only); + } + else + { + THIS->UpdateLockoutDuration(event_name, seconds); + } + + XSRETURN_EMPTY; +} + +XS(boot_Expedition); +XS(boot_Expedition) { + dXSARGS; + char file[256]; + strncpy(file, __FILE__, 256); + file[255] = 0; + + if (items != 1) { + fprintf(stderr, "boot_Expedition does not take any arguments."); + } + char buf[128]; + + XS_VERSION_BOOTCHECK; + newXSproto(strcpy(buf, "AddLockout"), XS_Expedition_AddLockout, file, "$$$"); + newXSproto(strcpy(buf, "AddLockoutDuration"), XS_Expedition_AddLockoutDuration, file, "$$$;$"); + newXSproto(strcpy(buf, "AddReplayLockout"), XS_Expedition_AddReplayLockout, file, "$$"); + newXSproto(strcpy(buf, "GetID"), XS_Expedition_GetID, file, "$"); + newXSproto(strcpy(buf, "GetInstanceID"), XS_Expedition_GetInstanceID, file, "$"); + newXSproto(strcpy(buf, "GetLeaderName"), XS_Expedition_GetLeaderName, file, "$"); + newXSproto(strcpy(buf, "GetLockouts"), XS_Expedition_GetLockouts, file, "$"); + newXSproto(strcpy(buf, "GetLootEventByNPCTypeID"), XS_Expedition_GetLootEventByNPCTypeID, file, "$$"); + newXSproto(strcpy(buf, "GetLootEventBySpawnID"), XS_Expedition_GetLootEventBySpawnID, file, "$$"); + newXSproto(strcpy(buf, "GetMemberCount"), XS_Expedition_GetMemberCount, file, "$"); + newXSproto(strcpy(buf, "GetMembers"), XS_Expedition_GetMembers, file, "$"); + newXSproto(strcpy(buf, "GetName"), XS_Expedition_GetName, file, "$"); + newXSproto(strcpy(buf, "GetSecondsRemaining"), XS_Expedition_GetSecondsRemaining, file, "$"); + newXSproto(strcpy(buf, "GetUUID"), XS_Expedition_GetUUID, file, "$"); + newXSproto(strcpy(buf, "GetZoneID"), XS_Expedition_GetZoneID, file, "$"); + newXSproto(strcpy(buf, "GetZoneName"), XS_Expedition_GetZoneName, file, "$"); + newXSproto(strcpy(buf, "GetZoneVersion"), XS_Expedition_GetZoneVersion, file, "$"); + newXSproto(strcpy(buf, "HasLockout"), XS_Expedition_HasLockout, file, "$$"); + newXSproto(strcpy(buf, "HasReplayLockout"), XS_Expedition_HasReplayLockout, file, "$"); + newXSproto(strcpy(buf, "RemoveCompass"), XS_Expedition_RemoveCompass, file, "$"); + newXSproto(strcpy(buf, "RemoveLockout"), XS_Expedition_RemoveLockout, file, "$$"); + newXSproto(strcpy(buf, "SetCompass"), XS_Expedition_SetCompass, file, "$$$$$"); + newXSproto(strcpy(buf, "SetLocked"), XS_Expedition_SetLocked, file, "$$;$$"); + newXSproto(strcpy(buf, "SetLootEventByNPCTypeID"), XS_Expedition_SetLootEventByNPCTypeID, file, "$$$"); + newXSproto(strcpy(buf, "SetLootEventBySpawnID"), XS_Expedition_SetLootEventBySpawnID, file, "$$$"); + newXSproto(strcpy(buf, "SetReplayLockoutOnMemberJoin"), XS_Expedition_SetReplayLockoutOnMemberJoin, file, "$$"); + newXSproto(strcpy(buf, "SetSafeReturn"), XS_Expedition_SetSafeReturn, file, "$$$$$$"); + newXSproto(strcpy(buf, "SetSecondsRemaining"), XS_Expedition_SetSecondsRemaining, file, "$$"); + newXSproto(strcpy(buf, "SetZoneInLocation"), XS_Expedition_SetZoneInLocation, file, "$$$$$"); + newXSproto(strcpy(buf, "UpdateLockoutDuration"), XS_Expedition_UpdateLockoutDuration, file, "$$$;$"); + XSRETURN_YES; +} + +#endif //EMBPERL_XS_CLASSES diff --git a/zone/perl_groups.cpp b/zone/perl_groups.cpp index c23246b4a..adac6ddae 100644 --- a/zone/perl_groups.cpp +++ b/zone/perl_groups.cpp @@ -576,6 +576,31 @@ XS(XS_Group_GetMember) { XSRETURN(1); } +XS(XS_Group_DoesAnyMemberHaveExpeditionLockout); +XS(XS_Group_DoesAnyMemberHaveExpeditionLockout) { + dXSARGS; + if (items != 3 && items != 4) { + Perl_croak(aTHX_ "Usage: Group::DoesAnyMemberHaveExpeditionLockout(THIS, string expedition_name, string event_name [, int max_check_count = 0])"); + } + + Group* THIS = nullptr; + if (sv_derived_from(ST(0), "Group")) { + IV tmp = SvIV((SV *) SvRV(ST(0))); + THIS = INT2PTR(Group *, tmp); + } else + Perl_croak(aTHX_ "THIS is not of type Group"); + if (THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + std::string expedition_name(SvPV_nolen(ST(1))); + std::string event_name(SvPV_nolen(ST(2))); + int max_check_count = (items == 4) ? static_cast(SvIV(ST(3))) : 0; + + bool result = THIS->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name, max_check_count); + ST(0) = boolSV(result); + XSRETURN(1); +} + #ifdef __cplusplus extern "C" #endif @@ -612,6 +637,7 @@ XS(boot_Group) { newXSproto(strcpy(buf, "TeleportGroup"), XS_Group_TeleportGroup, file, "$$$$$$$"); newXSproto(strcpy(buf, "GetID"), XS_Group_GetID, file, "$"); newXSproto(strcpy(buf, "GetMember"), XS_Group_GetMember, file, "$$"); + newXSproto(strcpy(buf, "DoesAnyMemberHaveExpeditionLockout"), XS_Group_DoesAnyMemberHaveExpeditionLockout, file, "$$$;$"); XSRETURN_YES; } diff --git a/zone/perl_raids.cpp b/zone/perl_raids.cpp index 670d445e5..2c2d8ff3c 100644 --- a/zone/perl_raids.cpp +++ b/zone/perl_raids.cpp @@ -545,6 +545,31 @@ XS(XS_Raid_GetMember) { XSRETURN(1); } +XS(XS_Raid_DoesAnyMemberHaveExpeditionLockout); +XS(XS_Raid_DoesAnyMemberHaveExpeditionLockout) { + dXSARGS; + if (items != 3 && items != 4) { + Perl_croak(aTHX_ "Usage: Raid::DoesAnyMemberHaveExpeditionLockout(THIS, string expedition_name, string event_name [, int max_check_count = 0])"); + } + + Raid* THIS = nullptr; + if (sv_derived_from(ST(0), "Raid")) { + IV tmp = SvIV((SV *) SvRV(ST(0))); + THIS = INT2PTR(Raid *, tmp); + } else + Perl_croak(aTHX_ "THIS is not of type Raid"); + if (THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + std::string expedition_name(SvPV_nolen(ST(1))); + std::string event_name(SvPV_nolen(ST(2))); + int max_check_count = (items == 4) ? static_cast(SvIV(ST(3))) : 0; + + bool result = THIS->DoesAnyMemberHaveExpeditionLockout(expedition_name, event_name, max_check_count); + ST(0) = boolSV(result); + XSRETURN(1); +} + #ifdef __cplusplus extern "C" #endif @@ -581,6 +606,7 @@ XS(boot_Raid) { newXSproto(strcpy(buf, "TeleportRaid"), XS_Raid_TeleportRaid, file, "$$$$$$$"); newXSproto(strcpy(buf, "GetID"), XS_Raid_GetID, file, "$"); newXSproto(strcpy(buf, "GetMember"), XS_Raid_GetMember, file, "$$"); + newXSproto(strcpy(buf, "DoesAnyMemberHaveExpeditionLockout"), XS_Raid_DoesAnyMemberHaveExpeditionLockout, file, "$$$;$"); XSRETURN_YES; }