Merge branch 'DarkflameUniverse:main' into PetFixes

This commit is contained in:
jadebenn
2023-11-21 21:20:22 -06:00
committed by GitHub
37 changed files with 340 additions and 151 deletions

View File

@@ -207,7 +207,7 @@ void UserManager::RequestCharacterList(const SystemAddress& sysAddr) {
chars[i]->SaveXMLToDatabase();
chars[i]->GetEntity()->SetCharacter(nullptr);
delete chars[i];
}
@@ -275,60 +275,58 @@ 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;
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\"/>";
do {
lwoidforpants = ObjectIDManager::GenerateRandomObjectID();
} while (lwoidforpants == lwoidforshirt); //Make sure we don't have the same ID for both shirt and pants
std::string xmlSave2 = xml2.str();
GeneralUtils::SetBit(lwoidforshirt, eObjectBits::CHARACTER);
GeneralUtils::SetBit(lwoidforshirt, eObjectBits::PERSISTENT);
GeneralUtils::SetBit(lwoidforpants, eObjectBits::CHARACTER);
GeneralUtils::SetBit(lwoidforpants, eObjectBits::PERSISTENT);
ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t idforpants) {
LWOOBJID lwoidforpants = idforpants;
GeneralUtils::SetBit(lwoidforpants, eObjectBits::CHARACTER);
GeneralUtils::SetBit(lwoidforpants, eObjectBits::PERSISTENT);
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\"/>";
std::stringstream xml3;
xml3 << xmlSave2 << "<i l=\"" << pantsLOT << "\" id=\"" << lwoidforpants << "\" s=\"1\" c=\"1\" eq=\"1\" b=\"1\"/>";
xml << "</in></items></inv><lvl l=\"1\" cv=\"1\" sb=\"500\"/><flag></flag></obj>";
xml3 << "</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);
if (!nameOk && u->GetMaxGMLevel() > eGameMasterLevel::FORUM_MODERATOR) nameOk = true;
//Check to see if our name was pre-approved:
bool nameOk = IsNamePreapproved(name);
if (!nameOk && u->GetMaxGMLevel() > eGameMasterLevel::FORUM_MODERATOR) nameOk = true;
std::string_view nameToAssign = !name.empty() && nameOk ? name : predefinedName;
std::string pendingName = !name.empty() && !nameOk ? name : "";
std::string_view nameToAssign = !name.empty() && nameOk ? name : predefinedName;
std::string pendingName = !name.empty() && !nameOk ? name : "";
ICharInfo::Info info;
info.name = nameToAssign;
info.pendingName = pendingName;
info.id = objectID;
info.accountId = u->GetAccountID();
ICharInfo::Info info;
info.name = nameToAssign;
info.pendingName = pendingName;
info.id = objectID;
info.accountId = u->GetAccountID();
Database::Get()->InsertNewCharacter(info);
Database::Get()->InsertNewCharacter(info);
//Now finally insert our character xml:
Database::Get()->InsertCharacterXml(objectID, xml.str());
//Now finally insert our character xml:
Database::Get()->InsertCharacterXml(objectID, xml3.str());
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::SUCCESS);
UserManager::RequestCharacterList(sysAddr);
});
});
});
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;
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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;