mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-12-25 15:03:34 +00:00
Merge branch 'DarkflameUniverse:main' into PetFixes
This commit is contained in:
commit
1a6fb89c9c
@ -94,6 +94,8 @@ int main(int argc, char** argv) {
|
||||
uint32_t framesSinceMasterDisconnect = 0;
|
||||
uint32_t framesSinceLastSQLPing = 0;
|
||||
|
||||
AuthPackets::LoadClaimCodes();
|
||||
|
||||
while (!Game::shouldShutdown) {
|
||||
//Check if we're still connected to master:
|
||||
if (!Game::server->GetIsConnectedToMaster()) {
|
||||
|
@ -166,7 +166,8 @@ enum ePlayerFlag : int32_t {
|
||||
NJ_LIGHTNING_SPINJITZU = 2031,
|
||||
NJ_ICE_SPINJITZU = 2032,
|
||||
NJ_FIRE_SPINJITZU = 2033,
|
||||
NJ_WU_SHOW_DAILY_CHEST = 2099
|
||||
NJ_WU_SHOW_DAILY_CHEST = 2099,
|
||||
DLU_SKIP_CINEMATICS = 1'000'000,
|
||||
};
|
||||
|
||||
#endif //!__EPLAYERFLAG__H__
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "CDPropertyTemplateTable.h"
|
||||
#include "CDFeatureGatingTable.h"
|
||||
#include "CDRailActivatorComponent.h"
|
||||
#include "CDRewardCodesTable.h"
|
||||
|
||||
// Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory.
|
||||
// A vanilla CDClient takes about 46MB of memory + the regular world data.
|
||||
@ -82,6 +83,7 @@ CDClientManager::CDClientManager() {
|
||||
CDRailActivatorComponentTable::Instance().LoadValuesFromDatabase();
|
||||
CDRarityTableTable::Instance().LoadValuesFromDatabase();
|
||||
CDRebuildComponentTable::Instance().LoadValuesFromDatabase();
|
||||
CDRewardCodesTable::Instance().LoadValuesFromDatabase();
|
||||
CDRewardsTable::Instance().LoadValuesFromDatabase();
|
||||
CDScriptComponentTable::Instance().LoadValuesFromDatabase();
|
||||
CDSkillBehaviorTable::Instance().LoadValuesFromDatabase();
|
||||
|
@ -0,0 +1,47 @@
|
||||
#include "CDRewardCodesTable.h"
|
||||
|
||||
void CDRewardCodesTable::LoadValuesFromDatabase() {
|
||||
|
||||
// First, get the size of the table
|
||||
unsigned int size = 0;
|
||||
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM RewardCodes");
|
||||
while (!tableSize.eof()) {
|
||||
size = tableSize.getIntField(0, 0);
|
||||
|
||||
tableSize.nextRow();
|
||||
}
|
||||
|
||||
tableSize.finalize();
|
||||
|
||||
// Reserve the size
|
||||
this->entries.reserve(size);
|
||||
|
||||
// Now get the data
|
||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RewardCodes");
|
||||
while (!tableData.eof()) {
|
||||
CDRewardCode entry;
|
||||
entry.id = tableData.getIntField("id", -1);
|
||||
entry.code = tableData.getStringField("code", "");
|
||||
entry.attachmentLOT = tableData.getIntField("attachmentLOT", -1);
|
||||
UNUSED_COLUMN(entry.locStatus = tableData.getIntField("locStatus", -1));
|
||||
UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", ""));
|
||||
|
||||
this->entries.push_back(entry);
|
||||
tableData.nextRow();
|
||||
}
|
||||
}
|
||||
|
||||
LOT CDRewardCodesTable::GetAttachmentLOT(uint32_t rewardCodeId) const {
|
||||
for (auto const &entry : this->entries){
|
||||
if (rewardCodeId == entry.id) return entry.attachmentLOT;
|
||||
}
|
||||
return LOT_NULL;
|
||||
}
|
||||
|
||||
uint32_t CDRewardCodesTable::GetCodeID(std::string code) const {
|
||||
for (auto const &entry : this->entries){
|
||||
if (code == entry.code) return entry.id;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
// Custom Classes
|
||||
#include "CDTable.h"
|
||||
|
||||
|
||||
struct CDRewardCode {
|
||||
uint32_t id;
|
||||
std::string code;
|
||||
LOT attachmentLOT;
|
||||
UNUSED(uint32_t locStatus);
|
||||
UNUSED(std::string gate_version);
|
||||
};
|
||||
|
||||
|
||||
class CDRewardCodesTable : public CDTable<CDRewardCodesTable> {
|
||||
private:
|
||||
std::vector<CDRewardCode> entries;
|
||||
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
const std::vector<CDRewardCode>& GetEntries() const;
|
||||
LOT GetAttachmentLOT(uint32_t rewardCodeId) const;
|
||||
uint32_t GetCodeID(std::string code) const;
|
||||
};
|
@ -8,6 +8,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
|
||||
// CPPLinq
|
||||
#ifdef _WIN32
|
||||
|
@ -31,6 +31,7 @@ set(DDATABASE_CDCLIENTDATABASE_CDCLIENTTABLES_SOURCES "CDActivitiesTable.cpp"
|
||||
"CDRailActivatorComponent.cpp"
|
||||
"CDRarityTableTable.cpp"
|
||||
"CDRebuildComponentTable.cpp"
|
||||
"CDRewardCodesTable.cpp"
|
||||
"CDRewardsTable.cpp"
|
||||
"CDScriptComponentTable.cpp"
|
||||
"CDSkillBehaviorTable.cpp"
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "ICharInfo.h"
|
||||
#include "IAccounts.h"
|
||||
#include "IActivityLog.h"
|
||||
#include "IAccountsRewardCodes.h"
|
||||
|
||||
namespace sql {
|
||||
class Statement;
|
||||
@ -38,7 +39,7 @@ class GameDatabase :
|
||||
public IMail, public ICommandLog, public IPlayerCheatDetections, public IBugReports,
|
||||
public IPropertyContents, public IProperty, public IPetNames, public ICharXml,
|
||||
public IMigrationHistory, public IUgc, public IFriends, public ICharInfo,
|
||||
public IAccounts, public IActivityLog {
|
||||
public IAccounts, public IActivityLog, public IAccountsRewardCodes {
|
||||
public:
|
||||
virtual ~GameDatabase() = default;
|
||||
// TODO: These should be made private.
|
||||
|
13
dDatabase/GameDatabase/ITables/IAccountsRewardCodes.h
Normal file
13
dDatabase/GameDatabase/ITables/IAccountsRewardCodes.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef __IACCOUNTSREWARDCODES__H__
|
||||
#define __IACCOUNTSREWARDCODES__H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
class IAccountsRewardCodes {
|
||||
public:
|
||||
virtual void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) = 0;
|
||||
virtual std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) = 0;
|
||||
};
|
||||
|
||||
#endif //!__IACCOUNTSREWARDCODES__H__
|
@ -103,6 +103,8 @@ public:
|
||||
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
||||
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
||||
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
||||
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
||||
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
||||
private:
|
||||
|
||||
// Generic query functions that can be used for any query.
|
||||
|
17
dDatabase/GameDatabase/MySQL/Tables/AccountsRewardCodes.cpp
Normal file
17
dDatabase/GameDatabase/MySQL/Tables/AccountsRewardCodes.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
void MySQLDatabase::InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) {
|
||||
ExecuteInsert("INSERT IGNORE INTO accounts_rewardcodes (account_id, rewardcode) VALUES (?, ?);", account_id, reward_code);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> MySQLDatabase::GetRewardCodesByAccountID(const uint32_t account_id) {
|
||||
auto result = ExecuteSelect("SELECT rewardcode FROM accounts_rewardcodes WHERE account_id = ?;", account_id);
|
||||
|
||||
std::vector<uint32_t> toReturn;
|
||||
toReturn.reserve(result->rowsCount());
|
||||
while (result->next()) {
|
||||
toReturn.push_back(result->getUInt("rewardcode"));
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
set(DDATABASES_DATABASES_MYSQL_TABLES_SOURCES
|
||||
"Accounts.cpp"
|
||||
"AccountsRewardCodes.cpp"
|
||||
"ActivityLog.cpp"
|
||||
"BugReports.cpp"
|
||||
"CharInfo.cpp"
|
||||
|
@ -275,36 +275,36 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
|
||||
}
|
||||
|
||||
std::stringstream xml;
|
||||
xml << "<obj v=\"1\"><mf hc=\"" << hairColor << "\" hs=\"" << hairStyle << "\" hd=\"0\" t=\"" << shirtColor << "\" l=\"" << pantsColor;
|
||||
xml << "<obj v=\"1\">";
|
||||
|
||||
xml << "<mf hc=\"" << hairColor << "\" hs=\"" << hairStyle << "\" hd=\"0\" t=\"" << shirtColor << "\" l=\"" << pantsColor;
|
||||
xml << "\" hdc=\"0\" cd=\"" << shirtStyle << "\" lh=\"" << lh << "\" rh=\"" << rh << "\" es=\"" << eyebrows << "\" ";
|
||||
xml << "ess=\"" << eyes << "\" ms=\"" << mouth << "\"/>";
|
||||
|
||||
xml << "<char acct=\"" << u->GetAccountID() << "\" cc=\"0\" gm=\"0\" ft=\"0\" llog=\"" << time(NULL) << "\" ";
|
||||
xml << "ls=\"0\" lzx=\"-626.5847\" lzy=\"613.3515\" lzz=\"-28.6374\" lzrx=\"0.0\" lzry=\"0.7015\" lzrz=\"0.0\" lzrw=\"0.7126\" ";
|
||||
xml << "stt=\"0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;\"></char>";
|
||||
|
||||
xml << "<dest hm=\"4\" hc=\"4\" im=\"0\" ic=\"0\" am=\"0\" ac=\"0\" d=\"0\"/>";
|
||||
|
||||
xml << "<inv><bag><b t=\"0\" m=\"20\"/><b t=\"1\" m=\"40\"/><b t=\"2\" m=\"240\"/><b t=\"3\" m=\"240\"/><b t=\"14\" m=\"40\"/></bag><items><in t=\"0\">";
|
||||
std::string xmlSave1 = xml.str();
|
||||
|
||||
ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t idforshirt) {
|
||||
std::stringstream xml2;
|
||||
LWOOBJID lwoidforshirt = ObjectIDManager::GenerateRandomObjectID();
|
||||
LWOOBJID lwoidforpants;
|
||||
|
||||
do {
|
||||
lwoidforpants = ObjectIDManager::GenerateRandomObjectID();
|
||||
} while (lwoidforpants == lwoidforshirt); //Make sure we don't have the same ID for both shirt and pants
|
||||
|
||||
LWOOBJID lwoidforshirt = idforshirt;
|
||||
GeneralUtils::SetBit(lwoidforshirt, eObjectBits::CHARACTER);
|
||||
GeneralUtils::SetBit(lwoidforshirt, eObjectBits::PERSISTENT);
|
||||
xml2 << xmlSave1 << "<i l=\"" << shirtLOT << "\" id=\"" << lwoidforshirt << "\" s=\"0\" c=\"1\" eq=\"1\" b=\"1\"/>";
|
||||
|
||||
std::string xmlSave2 = xml2.str();
|
||||
|
||||
ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t idforpants) {
|
||||
LWOOBJID lwoidforpants = idforpants;
|
||||
GeneralUtils::SetBit(lwoidforpants, eObjectBits::CHARACTER);
|
||||
GeneralUtils::SetBit(lwoidforpants, eObjectBits::PERSISTENT);
|
||||
|
||||
std::stringstream xml3;
|
||||
xml3 << xmlSave2 << "<i l=\"" << pantsLOT << "\" id=\"" << lwoidforpants << "\" s=\"1\" c=\"1\" eq=\"1\" b=\"1\"/>";
|
||||
xml << "<i l=\"" << shirtLOT << "\" id=\"" << lwoidforshirt << "\" s=\"0\" c=\"1\" eq=\"1\" b=\"1\"/>";
|
||||
xml << "<i l=\"" << pantsLOT << "\" id=\"" << lwoidforpants << "\" s=\"1\" c=\"1\" eq=\"1\" b=\"1\"/>";
|
||||
|
||||
xml3 << "</in></items></inv><lvl l=\"1\" cv=\"1\" sb=\"500\"/><flag></flag></obj>";
|
||||
xml << "</in></items></inv><lvl l=\"1\" cv=\"1\" sb=\"500\"/><flag></flag></obj>";
|
||||
|
||||
//Check to see if our name was pre-approved:
|
||||
bool nameOk = IsNamePreapproved(name);
|
||||
@ -322,13 +322,11 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
|
||||
Database::Get()->InsertNewCharacter(info);
|
||||
|
||||
//Now finally insert our character xml:
|
||||
Database::Get()->InsertCharacterXml(objectID, xml3.str());
|
||||
Database::Get()->InsertCharacterXml(objectID, xml.str());
|
||||
|
||||
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::SUCCESS);
|
||||
UserManager::RequestCharacterList(sysAddr);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) {
|
||||
@ -466,16 +464,18 @@ void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID
|
||||
|
||||
uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) {
|
||||
try {
|
||||
std::string shirtQuery = "select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == \"character create shirt\" AND icc.color1 == ";
|
||||
shirtQuery += std::to_string(shirtColor);
|
||||
shirtQuery += " AND icc.decal == ";
|
||||
shirtQuery = shirtQuery + std::to_string(shirtStyle);
|
||||
auto tableData = CDClientDatabase::ExecuteQuery(shirtQuery);
|
||||
auto shirtLOT = tableData.getIntField(0, -1);
|
||||
auto stmt = CDClientDatabase::CreatePreppedStmt(
|
||||
"select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == ? AND icc.color1 == ? AND icc.decal == ?"
|
||||
);
|
||||
stmt.bind(1, "character create shirt");
|
||||
stmt.bind(2, static_cast<int>(shirtColor));
|
||||
stmt.bind(3, static_cast<int>(shirtStyle));
|
||||
auto tableData = stmt.execQuery();
|
||||
auto shirtLOT = tableData.getIntField(0, 4069);
|
||||
tableData.finalize();
|
||||
return shirtLOT;
|
||||
} catch (const std::exception&) {
|
||||
LOG("Failed to execute query! Using backup...");
|
||||
} catch (const std::exception& ex) {
|
||||
LOG("Could not look up shirt %i %i: %s", shirtColor, shirtStyle, ex.what());
|
||||
// in case of no shirt found in CDServer, return problematic red vest.
|
||||
return 4069;
|
||||
}
|
||||
@ -483,14 +483,17 @@ uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) {
|
||||
|
||||
uint32_t FindCharPantsID(uint32_t pantsColor) {
|
||||
try {
|
||||
std::string pantsQuery = "select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == \"cc pants\" AND icc.color1 == ";
|
||||
pantsQuery += std::to_string(pantsColor);
|
||||
auto tableData = CDClientDatabase::ExecuteQuery(pantsQuery);
|
||||
auto pantsLOT = tableData.getIntField(0, -1);
|
||||
auto stmt = CDClientDatabase::CreatePreppedStmt(
|
||||
"select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == ? AND icc.color1 == ?"
|
||||
);
|
||||
stmt.bind(1, "cc pants");
|
||||
stmt.bind(2, static_cast<int>(pantsColor));
|
||||
auto tableData = stmt.execQuery();
|
||||
auto pantsLOT = tableData.getIntField(0, 2508);
|
||||
tableData.finalize();
|
||||
return pantsLOT;
|
||||
} catch (const std::exception&) {
|
||||
LOG("Failed to execute query! Using backup...");
|
||||
} catch (const std::exception& ex) {
|
||||
LOG("Could not look up pants %i: %s", pantsColor, ex.what());
|
||||
// in case of no pants color found in CDServer, return red pants.
|
||||
return 2508;
|
||||
}
|
||||
|
@ -16,6 +16,10 @@
|
||||
#include "Amf3.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "eGameActivity.h"
|
||||
#include "User.h"
|
||||
#include "Database.h"
|
||||
#include "CDRewardCodesTable.h"
|
||||
#include "Mail.h"
|
||||
#include <ctime>
|
||||
|
||||
CharacterComponent::CharacterComponent(Entity* parent, Character* character) : Component(parent) {
|
||||
@ -74,10 +78,14 @@ CharacterComponent::~CharacterComponent() {
|
||||
void CharacterComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||
|
||||
if (bIsInitialUpdate) {
|
||||
outBitStream->Write0();
|
||||
outBitStream->Write0();
|
||||
outBitStream->Write0();
|
||||
outBitStream->Write0();
|
||||
outBitStream->Write(m_ClaimCodes[0] != 0);
|
||||
if (m_ClaimCodes[0] != 0) outBitStream->Write(m_ClaimCodes[0]);
|
||||
outBitStream->Write(m_ClaimCodes[1] != 0);
|
||||
if (m_ClaimCodes[1] != 0) outBitStream->Write(m_ClaimCodes[1]);
|
||||
outBitStream->Write(m_ClaimCodes[2] != 0);
|
||||
if (m_ClaimCodes[2] != 0) outBitStream->Write(m_ClaimCodes[2]);
|
||||
outBitStream->Write(m_ClaimCodes[3] != 0);
|
||||
if (m_ClaimCodes[3] != 0) outBitStream->Write(m_ClaimCodes[3]);
|
||||
|
||||
outBitStream->Write(m_Character->GetHairColor());
|
||||
outBitStream->Write(m_Character->GetHairStyle());
|
||||
@ -186,6 +194,13 @@ void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
||||
SetReputation(0);
|
||||
}
|
||||
|
||||
character->QueryUnsigned64Attribute("co", &m_ClaimCodes[0]);
|
||||
character->QueryUnsigned64Attribute("co1", &m_ClaimCodes[1]);
|
||||
character->QueryUnsigned64Attribute("co2", &m_ClaimCodes[2]);
|
||||
character->QueryUnsigned64Attribute("co3", &m_ClaimCodes[3]);
|
||||
|
||||
AwardClaimCodes();
|
||||
|
||||
character->QueryInt64Attribute("ls", &m_Uscore);
|
||||
|
||||
// Load the statistics
|
||||
@ -308,6 +323,11 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ClaimCodes[0] != 0) character->SetAttribute("co", m_ClaimCodes[0]);
|
||||
if (m_ClaimCodes[1] != 0) character->SetAttribute("co1", m_ClaimCodes[1]);
|
||||
if (m_ClaimCodes[2] != 0) character->SetAttribute("co2", m_ClaimCodes[2]);
|
||||
if (m_ClaimCodes[3] != 0) character->SetAttribute("co3", m_ClaimCodes[3]);
|
||||
|
||||
character->SetAttribute("ls", m_Uscore);
|
||||
// Custom attribute to keep track of reputation.
|
||||
character->SetAttribute("rpt", GetReputation());
|
||||
@ -738,3 +758,31 @@ void CharacterComponent::UpdateClientMinimap(bool showFaction, std::string ventu
|
||||
arrayToSend.Insert(ventureVisionType, showFaction);
|
||||
GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent ? m_Parent->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS, "SetFactionVisibility", arrayToSend);
|
||||
}
|
||||
|
||||
void CharacterComponent::AwardClaimCodes() {
|
||||
if (!m_Parent) return;
|
||||
auto* user = m_Parent->GetParentUser();
|
||||
if (!user) return;
|
||||
|
||||
auto rewardCodes = Database::Get()->GetRewardCodesByAccountID(user->GetAccountID());
|
||||
if (rewardCodes.empty()) return;
|
||||
|
||||
auto* cdrewardCodes = CDClientManager::Instance().GetTable<CDRewardCodesTable>();
|
||||
for (auto const rewardCode: rewardCodes){
|
||||
LOG_DEBUG("Processing RewardCode %i", rewardCode);
|
||||
const uint32_t rewardCodeIndex = rewardCode >> 6;
|
||||
const uint32_t bitIndex = rewardCode % 64;
|
||||
if (GeneralUtils::CheckBit(m_ClaimCodes[rewardCodeIndex], bitIndex)) continue;
|
||||
m_ClaimCodes[rewardCodeIndex] = GeneralUtils::SetBit(m_ClaimCodes[rewardCodeIndex], bitIndex);
|
||||
|
||||
// Don't send it on this one since it's default and the mail doesn't make sense
|
||||
if (rewardCode == 30) continue;
|
||||
|
||||
auto attachmentLOT = cdrewardCodes->GetAttachmentLOT(rewardCode);
|
||||
std::ostringstream subject;
|
||||
subject << "%[RewardCodes_" << rewardCode << "_subjectText]";
|
||||
std::ostringstream body;
|
||||
body << "%[RewardCodes_" << rewardCode << "_bodyText]";
|
||||
Mail::SendMail(LWOOBJID_EMPTY, "%[MAIL_SYSTEM_NOTIFICATION]", m_Parent, subject.str(), body.str(), attachmentLOT, 1);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "CDMissionsTable.h"
|
||||
#include "tinyxml2.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include <array>
|
||||
|
||||
enum class eGameActivity : uint32_t;
|
||||
|
||||
@ -566,6 +567,10 @@ private:
|
||||
LWOOBJID m_LastRocketItemID = LWOOBJID_EMPTY;
|
||||
|
||||
LWOOBJID m_CurrentInteracting = LWOOBJID_EMPTY;
|
||||
|
||||
std::array<uint64_t, 4> m_ClaimCodes{};
|
||||
|
||||
void AwardClaimCodes();
|
||||
};
|
||||
|
||||
#endif // CHARACTERCOMPONENT_H
|
||||
|
@ -402,10 +402,10 @@ void PhantomPhysicsComponent::SetDirection(const NiPoint3& pos) {
|
||||
void PhantomPhysicsComponent::SpawnVertices() {
|
||||
if (!m_dpEntity) return;
|
||||
|
||||
std::cout << m_Parent->GetObjectID() << std::endl;
|
||||
LOG("%llu", m_Parent->GetObjectID());
|
||||
auto box = static_cast<dpShapeBox*>(m_dpEntity->GetShape());
|
||||
for (auto vert : box->GetVertices()) {
|
||||
std::cout << vert.x << ", " << vert.y << ", " << vert.z << std::endl;
|
||||
LOG("%f, %f, %f", vert.x, vert.y, vert.z);
|
||||
|
||||
EntityInfo info;
|
||||
info.lot = 33;
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "eMissionTaskType.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "ePlayerFlag.h"
|
||||
#include "dConfig.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -173,6 +175,13 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System
|
||||
GameMessages::SendPlayerReady(entity, sysAddr);
|
||||
GameMessages::SendPlayerReady(Game::zoneManager->GetZoneControlObject(), sysAddr);
|
||||
|
||||
if (Game::config->GetValue("allow_players_to_skip_cinematics") != "1"
|
||||
|| !entity->GetCharacter()
|
||||
|| !entity->GetCharacter()->GetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS)) return;
|
||||
entity->AddCallbackTimer(0.5f, [entity, sysAddr]() {
|
||||
if (!entity) return;
|
||||
GameMessages::SendEndCinematic(entity->GetObjectID(), u"", sysAddr);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
@ -244,13 +253,6 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System
|
||||
|
||||
case eGameMessageType::REQUEST_RESURRECT: {
|
||||
GameMessages::SendResurrect(entity);
|
||||
/*auto* dest = static_cast<DestroyableComponent*>(entity->GetComponent(eReplicaComponentType::DESTROYABLE));
|
||||
if (dest) {
|
||||
dest->SetHealth(4);
|
||||
dest->SetArmor(0);
|
||||
dest->SetImagination(6);
|
||||
Game::entityManager->SerializeEntity(entity);
|
||||
}*/
|
||||
break;
|
||||
}
|
||||
case eGameMessageType::GET_HOT_PROPERTY_DATA: {
|
||||
@ -339,11 +341,8 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System
|
||||
RakNet::BitStream bitStreamLocal;
|
||||
BitStreamUtils::WriteHeader(bitStreamLocal, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
||||
bitStreamLocal.Write(entity->GetObjectID());
|
||||
//bitStreamLocal.Write((unsigned short)eGameMessageType::ECHO_SYNC_SKILL);
|
||||
//bitStreamLocal.Write(inStream);
|
||||
|
||||
SyncSkill sync = SyncSkill(inStream); // inStream replaced &bitStream
|
||||
//sync.Serialize(&bitStreamLocal);
|
||||
|
||||
ostringstream buffer;
|
||||
|
||||
@ -353,8 +352,6 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System
|
||||
buffer << setw(2) << hex << setfill('0') << (int)s << " ";
|
||||
}
|
||||
|
||||
//cout << buffer.str() << endl;
|
||||
|
||||
if (usr != nullptr) {
|
||||
RakNet::BitStream* bs = new RakNet::BitStream((unsigned char*)sync.sBitStream.c_str(), sync.sBitStream.size(), false);
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "eControlScheme.h"
|
||||
#include "eStateChangeType.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "ePlayerFlag.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <future>
|
||||
@ -5161,6 +5162,14 @@ void GameMessages::HandleMissionDialogOK(RakNet::BitStream* inStream, Entity* en
|
||||
} else if (iMissionState == eMissionState::READY_TO_COMPLETE || iMissionState == eMissionState::COMPLETE_READY_TO_COMPLETE) {
|
||||
missionComponent->CompleteMission(missionID);
|
||||
}
|
||||
|
||||
if (Game::config->GetValue("allow_players_to_skip_cinematics") != "1"
|
||||
|| !player->GetCharacter()
|
||||
|| !player->GetCharacter()->GetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS)) return;
|
||||
player->AddCallbackTimer(0.5f, [player]() {
|
||||
if (!player) return;
|
||||
GameMessages::SendEndCinematic(player->GetObjectID(), u"", player->GetSystemAddress());
|
||||
});
|
||||
}
|
||||
|
||||
void GameMessages::HandleRequestLinkedMission(RakNet::BitStream* inStream, Entity* entity) {
|
||||
|
@ -84,8 +84,10 @@
|
||||
#include "eChatInternalMessageType.h"
|
||||
#include "eMasterMessageType.h"
|
||||
|
||||
#include "CDRewardCodesTable.h"
|
||||
#include "CDObjectsTable.h"
|
||||
#include "CDZoneTableTable.h"
|
||||
#include "ePlayerFlag.h"
|
||||
|
||||
void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr) {
|
||||
auto commandCopy = command;
|
||||
@ -172,6 +174,21 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
||||
return;
|
||||
}
|
||||
|
||||
if (chatCommand == "toggleskipcinematics" && (Game::config->GetValue("allow_players_to_skip_cinematics") == "1" || entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER)) {
|
||||
auto* character = entity->GetCharacter();
|
||||
if (!character) return;
|
||||
bool current = character->GetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS);
|
||||
character->SetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS, !current);
|
||||
if (!current) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"You have elected to skip cinematics. Note that not all cinematics can be skipped, but most will be skipped now.");
|
||||
} else {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Cinematics will no longer be skipped.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
//HANDLE ALL NON GM SLASH COMMANDS RIGHT HERE!
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
@ -1453,7 +1470,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
||||
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"<" + (GeneralUtils::to_u16string(position.x)) + u", " + (GeneralUtils::to_u16string(position.y)) + u", " + (GeneralUtils::to_u16string(position.z)) + u">");
|
||||
|
||||
std::cout << position.x << ", " << position.y << ", " << position.z << std::endl;
|
||||
LOG("Position: %f, %f, %f", position.x, position.y, position.z);
|
||||
}
|
||||
|
||||
if (chatCommand == "rot" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
|
||||
@ -1461,14 +1478,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
||||
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"<" + (GeneralUtils::to_u16string(rotation.w)) + u", " + (GeneralUtils::to_u16string(rotation.x)) + u", " + (GeneralUtils::to_u16string(rotation.y)) + u", " + (GeneralUtils::to_u16string(rotation.z)) + u">");
|
||||
|
||||
std::cout << rotation.w << ", " << rotation.x << ", " << rotation.y << ", " << rotation.z << std::endl;
|
||||
LOG("Rotation: %f, %f, %f, %f", rotation.w, rotation.x, rotation.y, rotation.z);
|
||||
}
|
||||
|
||||
if (chatCommand == "locrow" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
|
||||
const auto position = entity->GetPosition();
|
||||
const auto rotation = entity->GetRotation();
|
||||
|
||||
std::cout << "<location x=\"" << position.x << "\" y=\"" << position.y << "\" z=\"" << position.z << "\" rw=\"" << rotation.w << "\" rx=\"" << rotation.x << "\" ry=\"" << rotation.y << "\" rz=\"" << rotation.z << "\" />" << std::endl;
|
||||
LOG("<location x=\"%f\" y=\"%f\" z=\"%f\" rw=\"%f\" rx=\"%f\" ry=\"%f\" rz=\"%f\" />", position.x, position.y, position.z, rotation.w, rotation.x, rotation.y, rotation.z);
|
||||
}
|
||||
|
||||
if (chatCommand == "playlvlfx" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
|
||||
@ -1733,7 +1750,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
||||
|
||||
auto sphere = static_cast<dpShapeSphere*>(prox.second->GetShape());
|
||||
auto pos = prox.second->GetPosition();
|
||||
std::cout << prox.first << ", r: " << sphere->GetRadius() << ", pos: " << pos.x << "," << pos.y << "," << pos.z << std::endl;
|
||||
LOG("Proximity: %s, r: %f, pos: %f, %f, %f", prox.first.c_str(), sphere->GetRadius(), pos.x, pos.y, pos.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1976,6 +1993,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
||||
}
|
||||
}
|
||||
|
||||
if (chatCommand == "setrewardcode" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() == 1) {
|
||||
auto* cdrewardCodes = CDClientManager::Instance().GetTable<CDRewardCodesTable>();
|
||||
|
||||
auto id = cdrewardCodes->GetCodeID(args[0]);
|
||||
if (id != -1) Database::Get()->InsertRewardCode(user->GetAccountID(), id);
|
||||
}
|
||||
|
||||
if (chatCommand == "inspect" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER && args.size() >= 1) {
|
||||
Entity* closest = nullptr;
|
||||
|
||||
|
@ -29,6 +29,22 @@
|
||||
#include "eMasterMessageType.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
|
||||
namespace {
|
||||
std::vector<uint32_t> claimCodes;
|
||||
}
|
||||
|
||||
void AuthPackets::LoadClaimCodes() {
|
||||
if(!claimCodes.empty()) return;
|
||||
auto rcstring = Game::config->GetValue("rewardcodes");
|
||||
auto codestrings = GeneralUtils::SplitString(rcstring, ',');
|
||||
for(auto const &codestring: codestrings){
|
||||
uint32_t code = -1;
|
||||
if(GeneralUtils::TryParse(codestring, code) && code != -1){
|
||||
claimCodes.push_back(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AuthPackets::HandleHandshake(dServer* server, Packet* packet) {
|
||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||
uint64_t header = inStream.Read(header);
|
||||
@ -129,6 +145,10 @@ void AuthPackets::HandleLoginRequest(dServer* server, Packet* packet) {
|
||||
AuthPackets::SendLoginResponse(server, system, eLoginResponse::SUCCESS, "", zoneIP, zonePort, username);
|
||||
});
|
||||
}
|
||||
|
||||
for(auto const code: claimCodes){
|
||||
Database::Get()->InsertRewardCode(accountInfo->id, code);
|
||||
}
|
||||
}
|
||||
|
||||
void AuthPackets::SendLoginResponse(dServer* server, const SystemAddress& sysAddr, eLoginResponse responseCode, const std::string& errorMsg, const std::string& wServerIP, uint16_t wServerPort, std::string username) {
|
||||
|
@ -15,6 +15,8 @@ namespace AuthPackets {
|
||||
|
||||
void HandleLoginRequest(dServer* server, Packet* packet);
|
||||
void SendLoginResponse(dServer* server, const SystemAddress& sysAddr, eLoginResponse responseCode, const std::string& errorMsg, const std::string& wServerIP, uint16_t wServerPort, std::string username);
|
||||
void LoadClaimCodes();
|
||||
|
||||
}
|
||||
|
||||
#endif // AUTHPACKETS_H
|
||||
|
@ -22,7 +22,7 @@ dpEntity::dpEntity(const LWOOBJID& objectID, dpShapeType shapeType, bool isStati
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cout << "No shape for shapeType: " << (int)shapeType << std::endl;
|
||||
LOG("No shape for shapeType: %d", static_cast<int32_t>(shapeType));
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,15 +83,9 @@ void dpEntity::CheckCollision(dpEntity* other) {
|
||||
if (isColliding && !wasFound) {
|
||||
m_CurrentlyCollidingObjects.emplace(other->GetObjectID(), other);
|
||||
m_NewObjects.push_back(other);
|
||||
|
||||
//if (m_CollisionShape->GetShapeType() == dpShapeType::Sphere && other->GetShape()->GetShapeType() == dpShapeType::Sphere)
|
||||
//std::cout << "started sphere col at: " << other->GetPosition().x << ", " << other->GetPosition().y << ", " << other->GetPosition().z << std::endl;
|
||||
} else if (!isColliding && wasFound) {
|
||||
m_CurrentlyCollidingObjects.erase(other->GetObjectID());
|
||||
m_RemovedObjects.push_back(other);
|
||||
|
||||
//if (m_CollisionShape->GetShapeType() == dpShapeType::Sphere && other->GetShape()->GetShapeType() == dpShapeType::Sphere)
|
||||
// std::cout << "stopped sphere col at: " << other->GetPosition().x << ", " << other->GetPosition().y << ", " << other->GetPosition().z << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,6 @@ dpGrid::dpGrid(int numCells, int cellSize) {
|
||||
CELL_SIZE = cellSize;
|
||||
m_DeleteGrid = true;
|
||||
|
||||
//dumb method but i can't be bothered
|
||||
|
||||
//fill x
|
||||
for (int i = 0; i < NUM_CELLS; i++) {
|
||||
m_Cells.push_back(std::vector<std::forward_list<dpEntity*>>());
|
||||
|
@ -10,7 +10,7 @@ dpShapeBase::~dpShapeBase() {
|
||||
}
|
||||
|
||||
bool dpShapeBase::IsColliding(dpShapeBase* other) {
|
||||
std::cout << "Base shapes do not have any *shape* to them, and thus cannot be overlapping." << std::endl;
|
||||
std::cout << "You should be using a shape class inherited from this base class." << std::endl;
|
||||
LOG("Base shapes do not have any *shape* to them, and thus cannot be overlapping.");
|
||||
LOG("You should be using a shape class inherited from this base class.");
|
||||
return false;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ bool dpShapeBox::IsColliding(dpShapeBase* other) {
|
||||
return dpCollisionChecks::CheckBoxes(m_ParentEntity, other->GetParentEntity());
|
||||
|
||||
default:
|
||||
std::cout << "No collision detection for: " << (int)m_ShapeType << "-to-" << (int)other->GetShapeType() << " collision!" << std::endl;
|
||||
LOG("No collision detection for: %i-to-%i collision!", static_cast<int32_t>(m_ShapeType), static_cast<int32_t>(other->GetShapeType()));
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -72,10 +72,7 @@ void dpShapeBox::SetScale(float scale) {
|
||||
m_Height *= scale;
|
||||
m_Depth *= scale;
|
||||
|
||||
//fuuuckkk yoouu
|
||||
InitVertices();
|
||||
|
||||
//SetRotation(m_ParentEntity->GetRotation());
|
||||
}
|
||||
|
||||
void dpShapeBox::SetRotation(const NiQuaternion& rotation) {
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "dpShapeSphere.h"
|
||||
#include "dpCollisionChecks.h"
|
||||
#include "Game.h"
|
||||
#include "Logger.h"
|
||||
#include <iostream>
|
||||
|
||||
dpShapeSphere::dpShapeSphere(dpEntity* parentEntity, float radius) :
|
||||
@ -22,7 +24,7 @@ bool dpShapeSphere::IsColliding(dpShapeBase* other) {
|
||||
return dpCollisionChecks::CheckSphereBox(m_ParentEntity, other->GetParentEntity());
|
||||
|
||||
default:
|
||||
std::cout << "No collision detection for: " << (int)m_ShapeType << "-to-" << (int)other->GetShapeType() << " collision!" << std::endl;
|
||||
LOG("No collision detection for: %i-to-%i collision!", static_cast<int32_t>(m_ShapeType), static_cast<int32_t>(other->GetShapeType()));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1,35 +0,0 @@
|
||||
//This file included for reference only
|
||||
|
||||
/*#include <iostream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include "dpWorld.h"
|
||||
|
||||
#include "NiQuaternion.hpp"
|
||||
#include "NiPoint3.hpp"
|
||||
|
||||
int main() {
|
||||
std::cout << "dPhysics test engine" << std::endl;
|
||||
|
||||
//Test rotation code:
|
||||
NiPoint3 p(1.0f, 0.0f, 0.0f);
|
||||
|
||||
float angle = 45.0f;
|
||||
NiQuaternion q = NiQuaternion::CreateFromAxisAngle(NiPoint3(0.0f, 0.0f, 1.0f), angle);
|
||||
|
||||
NiPoint3 rotated = p.RotateByQuaternion(q);
|
||||
|
||||
std::cout << "OG: " << p.x << ", " << p.y << ", " << p.z << std::endl;
|
||||
std::cout << "Quater: " << q.x << ", " << q.y << ", " << q.z << ", " << q.w << " angle: " << angle << std::endl;
|
||||
std::cout << "Rotated: " << rotated.x << ", " << rotated.y << ", " << rotated.z << std::endl;
|
||||
|
||||
//Test some collisions:
|
||||
dpWorld::GetInstance().Initialize(1000);
|
||||
|
||||
while (true) {
|
||||
dpWorld::GetInstance().StepWorld(1.0f/60.0f);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(16));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}*/
|
@ -1033,9 +1033,8 @@ void HandlePacket(Packet* packet) {
|
||||
Game::entityManager->ConstructAllEntities(packet->systemAddress);
|
||||
|
||||
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
||||
if (characterComponent) {
|
||||
player->GetComponent<CharacterComponent>()->RocketUnEquip(player);
|
||||
}
|
||||
if (!characterComponent) return;
|
||||
characterComponent->RocketUnEquip(player);
|
||||
|
||||
// Do charxml fixes here
|
||||
auto* levelComponent = player->GetComponent<LevelProgressionComponent>();
|
||||
|
@ -16,6 +16,12 @@
|
||||
#include "AssetManager.h"
|
||||
#include "dConfig.h"
|
||||
|
||||
void Level::SceneObjectDataChunk::PrintAllObjects() const {
|
||||
for (const auto& [id, sceneObj] : objects) {
|
||||
LOG("ID: %d LOT: %d", id, sceneObj.lot);
|
||||
}
|
||||
}
|
||||
|
||||
Level::Level(Zone* parentZone, const std::string& filepath) {
|
||||
m_ParentZone = parentZone;
|
||||
|
||||
@ -33,9 +39,9 @@ Level::Level(Zone* parentZone, const std::string& filepath) {
|
||||
}
|
||||
|
||||
Level::~Level() {
|
||||
for (std::map<uint32_t, Header>::iterator it = m_ChunkHeaders.begin(); it != m_ChunkHeaders.end(); ++it) {
|
||||
if (it->second.id == Level::ChunkTypeID::FileInfo) delete it->second.fileInfo;
|
||||
if (it->second.id == Level::ChunkTypeID::SceneObjectData) delete it->second.sceneObjects;
|
||||
for (auto& [id, header] : m_ChunkHeaders) {
|
||||
if (header.id == Level::ChunkTypeID::FileInfo) delete header.fileInfo;
|
||||
if (header.id == Level::ChunkTypeID::SceneObjectData) delete header.sceneObjects;
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,8 +254,8 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
|
||||
BinaryIO::BinaryRead(file, obj.id);
|
||||
BinaryIO::BinaryRead(file, obj.lot);
|
||||
|
||||
/*if (header.fileInfo->version >= 0x26)*/ BinaryIO::BinaryRead(file, obj.value1);
|
||||
/*if (header.fileInfo->version >= 0x20)*/ BinaryIO::BinaryRead(file, obj.value2);
|
||||
/*if (header.fileInfo->version >= 0x26)*/ BinaryIO::BinaryRead(file, obj.nodeType);
|
||||
/*if (header.fileInfo->version >= 0x20)*/ BinaryIO::BinaryRead(file, obj.glomId);
|
||||
|
||||
BinaryIO::BinaryRead(file, obj.position);
|
||||
BinaryIO::BinaryRead(file, obj.rotation);
|
||||
|
@ -30,11 +30,7 @@ public:
|
||||
struct SceneObjectDataChunk {
|
||||
std::map<LWOOBJID, SceneObject> objects;
|
||||
|
||||
const void PrintAllObjects() {
|
||||
for (std::map<LWOOBJID, SceneObject>::iterator it = objects.begin(); it != objects.end(); ++it) {
|
||||
std::cout << "\t ID: " << it->first << " LOT: " << it->second.lot << std::endl;
|
||||
}
|
||||
}
|
||||
void PrintAllObjects() const;
|
||||
|
||||
uint32_t GetObjectCount() { return objects.size(); }
|
||||
};
|
||||
|
@ -148,6 +148,8 @@ struct PropertyPath {
|
||||
float repMultiplier;
|
||||
PropertyRentalPeriod rentalPeriod;
|
||||
PropertyAchievmentRequired achievementRequired;
|
||||
|
||||
// Player respawn coordinates in the main zone (not the property zone)
|
||||
NiPoint3 playerZoneCoords;
|
||||
float maxBuildHeight;
|
||||
};
|
||||
|
@ -12,8 +12,8 @@ struct mapCompareLwoSceneIDs {
|
||||
struct SceneObject {
|
||||
LWOOBJID id;
|
||||
LOT lot;
|
||||
uint32_t value1;
|
||||
uint32_t value2;
|
||||
uint32_t nodeType;
|
||||
uint32_t glomId;
|
||||
NiPoint3 position;
|
||||
NiQuaternion rotation;
|
||||
float scale = 1.0f;
|
||||
|
@ -14,6 +14,8 @@
|
||||
|resurrect|`/resurrect`|Resurrects the player.||
|
||||
|requestmailcount|`/requestmailcount`|Sends notification with number of unread messages in the player's mailbox.||
|
||||
|who|`/who`|Displays in chat all players on the instance.||
|
||||
|togglenameplate|`/togglenameplate`|Turns the nameplate above your head that is visible to other players off and on.|8 or if `allow_nameplate_off` is set to exactly `1` in the settings|
|
||||
|toggleskipcinematics|`/toggleskipcinematics`|Skips mission and world load related cinematics.|8 or if `allow_players_to_skip_cinematics` is set to exactly `1` in the settings then 0|
|
||||
|
||||
## Moderation Commands
|
||||
|
||||
@ -49,7 +51,6 @@ These commands are primarily for development and testing. The usage of many of t
|
||||
|
||||
|Command|Usage|Description|Admin Level Requirement|
|
||||
|--- |--- |--- |--- |
|
||||
|togglenameplate|`/togglenameplate`|Turns the nameplate above your head that is visible to other players off and on.|8 or if `allow_nameplate_off` is set to exactly `1` in the settings|
|
||||
|fix-stats|`/fix-stats`|Resets skills, buffs, and destroyables.||
|
||||
|join|`/join <password>`|Joins a private zone with given password.||
|
||||
|leave-zone|`/leave-zone`|If you are in an instanced zone, transfers you to the closest main world. For example, if you are in an instance of Avant Gardens Survival or the Spider Queen Battle, you are sent to Avant Gardens. If you are in the Battle of Nimbus Station, you are sent to Nimbus Station.||
|
||||
@ -113,6 +114,7 @@ These commands are primarily for development and testing. The usage of many of t
|
||||
|setfaction|`/setfaction <faction id>`|Clears the users current factions and sets it|8|
|
||||
|addfaction|`/addfaction <faction id>`|Add the faction to the users list of factions|8|
|
||||
|getfactions|`/getfactions`|Shows the player's factions|8|
|
||||
|setrewardcode|`/setrewardcode <code>`|Sets the rewardcode for the account you are logged into if it's a valid rewardcode, See cdclient table `RewardCodes`|8|
|
||||
## Detailed `/inspect` Usage
|
||||
|
||||
`/inspect <component> (-m <waypoint> | -a <animation> | -s | -p | -f (faction) | -t)`
|
||||
|
5
migrations/dlu/14_reward_codes.sql
Normal file
5
migrations/dlu/14_reward_codes.sql
Normal file
@ -0,0 +1,5 @@
|
||||
CREATE TABLE IF NOT EXISTS accounts_rewardcodes (
|
||||
account_id INT NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
|
||||
rewardcode INT NOT NULL,
|
||||
PRIMARY KEY (account_id, rewardcode)
|
||||
);
|
@ -4,3 +4,11 @@ port=1001
|
||||
# 0 or 1, should ignore playkeys
|
||||
# If 1 everyone with an account will be able to login, regardless of if they have a key or not
|
||||
dont_use_keys=0
|
||||
|
||||
# list of rewardcodes to set on the accounts by default
|
||||
# ex: 30,1,0,3
|
||||
# See RewardCodes in the CDclient for what codes exist
|
||||
# Default 4,30
|
||||
# 4 allows LEGOClub access
|
||||
# 30 makes the client not consume bricks when in bbb mode
|
||||
rewardcodes=4,30
|
||||
|
@ -61,6 +61,7 @@ allow_nameplate_off=0
|
||||
# Turn logging of IP addresses for anti-cheat reporting on (1) or off(0)
|
||||
log_ip_addresses_for_anti_cheat=1
|
||||
|
||||
# These are the 5 items items that are shown in the "Help" menu in-game along with their coresponding descriptions below.
|
||||
help_0_summary=Got an issue?
|
||||
help_1_summary=Stuck loading?
|
||||
help_2_summary=Missing features?
|
||||
@ -72,3 +73,6 @@ help_1_description=Try switching networks, using a VPN, or using your phone's ho
|
||||
help_2_description=While DarkflameServer is a mostly complete emulator, there are still some features that aren't implemented. You can track these on the GitHub issues page.<br/><br/>
|
||||
help_3_description=Skill issue!<br/><br/>
|
||||
help_4_description=Visit Discussions on the DarkflameServer GitHub page<br/>to ask questions and collaborate with other devs!<br/><br/>
|
||||
|
||||
# Toggleable quality of life feature to allow users to skip most cinematics.
|
||||
allow_players_to_skip_cinematics=0
|
||||
|
@ -71,25 +71,15 @@ TEST(dCommonTests, AMF3InsertionAssociativeTest) {
|
||||
array.Insert<std::vector<uint32_t>>("Undefined", {});
|
||||
array.Insert("Null", nullptr);
|
||||
|
||||
std::cout << "test" << std::endl;
|
||||
ASSERT_EQ(array.Get<const char*>("CString")->GetValueType(), eAmf::String);
|
||||
std::cout << "test" << std::endl;
|
||||
ASSERT_EQ(array.Get<std::string>("String")->GetValueType(), eAmf::String);
|
||||
std::cout << "test" << std::endl;
|
||||
ASSERT_EQ(array.Get<bool>("False")->GetValueType(), eAmf::False);
|
||||
std::cout << "test" << std::endl;
|
||||
ASSERT_EQ(array.Get<bool>("True")->GetValueType(), eAmf::True);
|
||||
std::cout << "test" << std::endl;
|
||||
ASSERT_EQ(array.Get<int32_t>("Integer")->GetValueType(), eAmf::Integer);
|
||||
std::cout << "test" << std::endl;
|
||||
ASSERT_EQ(array.Get<double>("Double")->GetValueType(), eAmf::Double);
|
||||
std::cout << "test" << std::endl;
|
||||
ASSERT_EQ(array.GetArray("Array")->GetValueType(), eAmf::Array);
|
||||
std::cout << "test" << std::endl;
|
||||
ASSERT_EQ(array.Get<nullptr_t>("Null")->GetValueType(), eAmf::Null);
|
||||
std::cout << "test" << std::endl;
|
||||
ASSERT_EQ(array.Get<std::vector<uint32_t>>("Undefined")->GetValueType(), eAmf::Undefined);
|
||||
std::cout << "test" << std::endl;
|
||||
}
|
||||
|
||||
TEST(dCommonTests, AMF3InsertionDenseTest) {
|
||||
|
Loading…
Reference in New Issue
Block a user