mirror of
https://github.com/DarkflameUniverse/DarkflameServer
synced 2024-08-30 18:43:58 +00:00
commit
95010e791f
@ -3,6 +3,7 @@
|
||||
// Custom Classes
|
||||
#include "CDTable.h"
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
|
||||
/*!
|
||||
\file CDMissionsTable.hpp
|
||||
@ -17,9 +18,9 @@ struct CDMissions {
|
||||
int UISortOrder; //!< The UI Sort Order for the mission
|
||||
int offer_objectID; //!< The LOT of the mission giver
|
||||
int target_objectID; //!< The LOT of the mission's target
|
||||
__int64 reward_currency; //!< The amount of currency to reward the player
|
||||
int64_t reward_currency; //!< The amount of currency to reward the player
|
||||
int LegoScore; //!< The amount of LEGO Score to reward the player
|
||||
__int64 reward_reputation; //!< The reputation to award the player
|
||||
int64_t reward_reputation; //!< The reputation to award the player
|
||||
bool isChoiceReward; //!< Whether or not the user has the option to choose their loot
|
||||
int reward_item1; //!< The first rewarded item
|
||||
int reward_item1_count; //!< The count of the first item to be rewarded
|
||||
@ -40,7 +41,7 @@ struct CDMissions {
|
||||
int reward_maxwidget; //!< ???
|
||||
int reward_maxwallet; //!< ???
|
||||
bool repeatable; //!< Whether or not this mission can be repeated (for instance, is it a daily mission)
|
||||
__int64 reward_currency_repeatable; //!< The repeatable reward
|
||||
int64_t reward_currency_repeatable; //!< The repeatable reward
|
||||
int reward_item1_repeatable; //!< The first rewarded item
|
||||
int reward_item1_repeat_count; //!< The count of the first item to be rewarded
|
||||
int reward_item2_repeatable; //!< The second rewarded item
|
||||
@ -55,7 +56,7 @@ struct CDMissions {
|
||||
std::string prereqMissionID; //!< A '|' seperated list of prerequisite missions
|
||||
bool localize; //!< Whether or not to localize the mission
|
||||
bool inMOTD; //!< In Match of the Day(?)
|
||||
__int64 cooldownTime; //!< The mission cooldown time
|
||||
int64_t cooldownTime; //!< The mission cooldown time
|
||||
bool isRandom; //!< ???
|
||||
std::string randomPool; //!< ???
|
||||
int UIPrereqID; //!< ???
|
||||
|
@ -1,12 +1,15 @@
|
||||
#include <CDPropertyEntranceComponentTable.h>
|
||||
#include "PropertyEntranceComponent.h"
|
||||
#include "PropertyEntranceComponent.h"
|
||||
|
||||
#include <CDPropertyEntranceComponentTable.h>
|
||||
|
||||
#include "Character.h"
|
||||
#include "Database.h"
|
||||
#include "GameMessages.h"
|
||||
#include "PropertyManagementComponent.h"
|
||||
#include "PropertySelectQueryProperty.h"
|
||||
#include "RocketLaunchpadControlComponent.h"
|
||||
#include "Character.h"
|
||||
#include "GameMessages.h"
|
||||
#include "UserManager.h"
|
||||
#include "dLogger.h"
|
||||
#include "Database.h"
|
||||
#include "PropertyManagementComponent.h"
|
||||
|
||||
PropertyEntranceComponent::PropertyEntranceComponent(uint32_t componentID, Entity* parent) : Component(parent)
|
||||
{
|
||||
@ -49,6 +52,7 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index,
|
||||
}
|
||||
else if (index >= 0)
|
||||
{
|
||||
// Increment index once here because the first index of other player properties is 2 in the propertyQueries cache.
|
||||
index++;
|
||||
|
||||
const auto& pair = propertyQueries.find(entity->GetObjectID());
|
||||
@ -71,167 +75,269 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index,
|
||||
|
||||
launcher->SetSelectedCloneId(entity->GetObjectID(), cloneId);
|
||||
|
||||
launcher->Launch(entity, LWOOBJID_EMPTY, LWOMAPID_INVALID, cloneId);
|
||||
launcher->Launch(entity, LWOOBJID_EMPTY, launcher->GetTargetZone(), cloneId);
|
||||
}
|
||||
|
||||
void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity,
|
||||
bool includeNullAddress,
|
||||
bool includeNullDescription,
|
||||
bool playerOwn,
|
||||
bool updateUi,
|
||||
int32_t numResults,
|
||||
int32_t reputation,
|
||||
int32_t sortMethod,
|
||||
int32_t startIndex,
|
||||
std::string filterText,
|
||||
const SystemAddress& sysAddr)
|
||||
{
|
||||
Game::logger->Log("PropertyEntranceComponent", "On Sync %d %d %d %d %i %i %i %i %s\n",
|
||||
includeNullAddress,
|
||||
includeNullDescription,
|
||||
playerOwn,
|
||||
updateUi,
|
||||
numResults,
|
||||
reputation,
|
||||
sortMethod,
|
||||
startIndex,
|
||||
filterText.c_str()
|
||||
);
|
||||
PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, float reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, float performanceCost) {
|
||||
property.CloneId = cloneId;
|
||||
property.OwnerName = ownerName;
|
||||
property.Name = propertyName;
|
||||
property.Description = propertyDescription;
|
||||
property.Reputation = reputation;
|
||||
property.IsBestFriend = isBFF;
|
||||
property.IsFriend = isFriend;
|
||||
property.IsModeratorApproved = isModeratorApproved;
|
||||
property.IsAlt = isAlt;
|
||||
property.IsOwned = isOwned;
|
||||
property.AccessType = privacyOption;
|
||||
property.DateLastPublished = timeLastUpdated;
|
||||
property.PerformanceCost = performanceCost;
|
||||
|
||||
auto* launchpadComponent = m_Parent->GetComponent<RocketLaunchpadControlComponent>();
|
||||
if (launchpadComponent == nullptr)
|
||||
return;
|
||||
return property;
|
||||
}
|
||||
|
||||
std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod, std::string customQuery, bool wantLimits) {
|
||||
std::string base;
|
||||
if (customQuery == "") {
|
||||
base = baseQueryForProperties;
|
||||
} else {
|
||||
base = customQuery;
|
||||
}
|
||||
std::string orderBy = "";
|
||||
if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) {
|
||||
std::string friendsList = " AND p.owner_id IN (";
|
||||
|
||||
auto friendsListQuery = Database::CreatePreppedStmt("SELECT * FROM (SELECT CASE WHEN player_id = ? THEN friend_id WHEN friend_id = ? THEN player_id END AS requested_player FROM dlu.friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;");
|
||||
|
||||
friendsListQuery->setInt64(1, entity->GetObjectID());
|
||||
friendsListQuery->setInt64(2, entity->GetObjectID());
|
||||
|
||||
auto friendsListQueryResult = friendsListQuery->executeQuery();
|
||||
|
||||
while (friendsListQueryResult->next()) {
|
||||
auto playerIDToConvert = friendsListQueryResult->getInt64(1);
|
||||
playerIDToConvert = GeneralUtils::ClearBit(playerIDToConvert, OBJECT_BIT_CHARACTER);
|
||||
playerIDToConvert = GeneralUtils::ClearBit(playerIDToConvert, OBJECT_BIT_PERSISTENT);
|
||||
friendsList = friendsList + std::to_string(playerIDToConvert) + ",";
|
||||
}
|
||||
// Replace trailing comma with the closing parenthesis.
|
||||
if (friendsList.at(friendsList.size() - 1) == ',') friendsList.erase(friendsList.size() - 1, 1);
|
||||
friendsList += ") ";
|
||||
|
||||
// If we have no friends then use a -1 for the query.
|
||||
if (friendsList.find("()") != std::string::npos) friendsList = " AND p.owner_id IN (-1) ";
|
||||
|
||||
orderBy += friendsList + "ORDER BY ci.name ASC ";
|
||||
|
||||
delete friendsListQueryResult;
|
||||
friendsListQueryResult = nullptr;
|
||||
|
||||
delete friendsListQuery;
|
||||
friendsListQuery = nullptr;
|
||||
}
|
||||
else if (sortMethod == SORT_TYPE_RECENT) {
|
||||
orderBy = "ORDER BY p.last_updated DESC ";
|
||||
}
|
||||
else if (sortMethod == SORT_TYPE_REPUTATION) {
|
||||
orderBy = "ORDER BY p.reputation DESC, p.last_updated DESC ";
|
||||
}
|
||||
else {
|
||||
orderBy = "ORDER BY p.last_updated DESC ";
|
||||
}
|
||||
return base + orderBy + (wantLimits ? "LIMIT ? OFFSET ?;" : ";");
|
||||
}
|
||||
|
||||
void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool includeNullAddress, bool includeNullDescription, bool playerOwn, bool updateUi, int32_t numResults, int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, const SystemAddress& sysAddr){
|
||||
|
||||
std::vector<PropertySelectQueryProperty> entries {};
|
||||
PropertySelectQueryProperty playerEntry {};
|
||||
|
||||
auto* character = entity->GetCharacter();
|
||||
playerEntry.OwnerName = character->GetName();
|
||||
playerEntry.Description = "No description.";
|
||||
playerEntry.Name = "Your property!";
|
||||
playerEntry.IsModeratorApproved = true;
|
||||
playerEntry.AccessType = 2;
|
||||
playerEntry.CloneId = character->GetPropertyCloneID();
|
||||
auto character = entity->GetCharacter();
|
||||
if (!character) return;
|
||||
|
||||
// Player property goes in index 1 of the vector. This is how the client expects it.
|
||||
auto playerPropertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?");
|
||||
|
||||
playerPropertyLookup->setInt(1, character->GetID());
|
||||
playerPropertyLookup->setInt(2, this->m_MapID);
|
||||
|
||||
auto playerPropertyLookupResults = playerPropertyLookup->executeQuery();
|
||||
|
||||
// If the player has a property this query will have a single result.
|
||||
if (playerPropertyLookupResults->next()) {
|
||||
const auto cloneId = playerPropertyLookupResults->getUInt64(4);
|
||||
const auto propertyName = playerPropertyLookupResults->getString(5).asStdString();
|
||||
const auto propertyDescription = playerPropertyLookupResults->getString(6).asStdString();
|
||||
const auto privacyOption = playerPropertyLookupResults->getInt(9);
|
||||
const auto modApproved = playerPropertyLookupResults->getBoolean(10);
|
||||
const auto dateLastUpdated = playerPropertyLookupResults->getInt64(11);
|
||||
const auto reputation = playerPropertyLookupResults->getUInt(14);
|
||||
const auto performanceCost = (float)playerPropertyLookupResults->getDouble(16);
|
||||
|
||||
playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), propertyName, propertyDescription, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated, performanceCost);
|
||||
} else {
|
||||
playerEntry = SetPropertyValues(playerEntry, character->GetPropertyCloneID(), character->GetName(), "", "", 0, true, true);
|
||||
}
|
||||
|
||||
delete playerPropertyLookupResults;
|
||||
playerPropertyLookupResults = nullptr;
|
||||
|
||||
delete playerPropertyLookup;
|
||||
playerPropertyLookup = nullptr;
|
||||
|
||||
entries.push_back(playerEntry);
|
||||
|
||||
sql::ResultSet* propertyEntry;
|
||||
sql::PreparedStatement* propertyLookup;
|
||||
const auto query = BuildQuery(entity, sortMethod);
|
||||
|
||||
const auto moderating = entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR;
|
||||
|
||||
if (!moderating)
|
||||
{
|
||||
propertyLookup = Database::CreatePreppedStmt(
|
||||
"SELECT * FROM properties WHERE (name LIKE ? OR description LIKE ? OR "
|
||||
"((SELECT name FROM charinfo WHERE prop_clone_id = clone_id) LIKE ?)) AND "
|
||||
"(privacy_option = 2 AND mod_approved = true) OR (privacy_option >= 1 "
|
||||
"AND (owner_id IN (SELECT friend_id FROM friends WHERE player_id = ?) OR owner_id IN (SELECT player_id FROM "
|
||||
"friends WHERE friend_id = ?))) AND zone_id = ? LIMIT ? OFFSET ?;"
|
||||
);
|
||||
auto propertyLookup = Database::CreatePreppedStmt(query);
|
||||
|
||||
const auto searchString = "%" + filterText + "%";
|
||||
propertyLookup->setUInt(1, this->m_MapID);
|
||||
propertyLookup->setString(2, searchString.c_str());
|
||||
propertyLookup->setString(3, searchString.c_str());
|
||||
propertyLookup->setString(4, searchString.c_str());
|
||||
propertyLookup->setInt(5, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? (uint32_t)PropertyPrivacyOption::Friends : (uint32_t)PropertyPrivacyOption::Public);
|
||||
propertyLookup->setInt(6, numResults);
|
||||
propertyLookup->setInt(7, startIndex);
|
||||
|
||||
const std::string searchString = "%" + filterText + "%";
|
||||
Game::logger->Log("PropertyEntranceComponent", "%s\n", searchString.c_str());
|
||||
propertyLookup->setString(1, searchString.c_str());
|
||||
propertyLookup->setString(2, searchString.c_str());
|
||||
propertyLookup->setString(3, searchString.c_str());
|
||||
propertyLookup->setInt64(4, entity->GetObjectID());
|
||||
propertyLookup->setInt64(5, entity->GetObjectID());
|
||||
propertyLookup->setUInt(6, launchpadComponent->GetTargetZone());
|
||||
propertyLookup->setInt(7, numResults);
|
||||
propertyLookup->setInt(8, startIndex);
|
||||
auto propertyEntry = propertyLookup->executeQuery();
|
||||
|
||||
propertyEntry = propertyLookup->executeQuery();
|
||||
}
|
||||
else
|
||||
{
|
||||
propertyLookup = Database::CreatePreppedStmt(
|
||||
"SELECT * FROM properties WHERE privacy_option = 2 AND mod_approved = false AND zone_id = ?;"
|
||||
);
|
||||
|
||||
propertyLookup->setUInt(1, launchpadComponent->GetTargetZone());
|
||||
|
||||
propertyEntry = propertyLookup->executeQuery();
|
||||
}
|
||||
|
||||
while (propertyEntry->next())
|
||||
{
|
||||
const auto propertyId = propertyEntry->getUInt64(1);
|
||||
const auto owner = propertyEntry->getUInt64(2);
|
||||
while (propertyEntry->next()) {
|
||||
const auto propertyId = propertyEntry->getUInt64(1);
|
||||
const auto owner = propertyEntry->getInt(2);
|
||||
const auto cloneId = propertyEntry->getUInt64(4);
|
||||
const auto name = propertyEntry->getString(5).asStdString();
|
||||
const auto description = propertyEntry->getString(6).asStdString();
|
||||
const auto privacyOption = propertyEntry->getInt(9);
|
||||
const auto reputation = propertyEntry->getInt(15);
|
||||
const auto propertyNameFromDb = propertyEntry->getString(5).asStdString();
|
||||
const auto propertyDescriptionFromDb = propertyEntry->getString(6).asStdString();
|
||||
const auto privacyOption = propertyEntry->getInt(9);
|
||||
const auto modApproved = propertyEntry->getBoolean(10);
|
||||
const auto dateLastUpdated = propertyEntry->getInt(11);
|
||||
const float reputation = propertyEntry->getInt(14);
|
||||
const auto performanceCost = (float)propertyEntry->getDouble(16);
|
||||
|
||||
PropertySelectQueryProperty entry {};
|
||||
|
||||
auto* nameLookup = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;");
|
||||
PropertySelectQueryProperty entry{};
|
||||
|
||||
std::string ownerName = "";
|
||||
bool isOwned = true;
|
||||
auto nameLookup = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;");
|
||||
|
||||
nameLookup->setUInt64(1, cloneId);
|
||||
|
||||
auto* nameResult = nameLookup->executeQuery();
|
||||
auto nameResult = nameLookup->executeQuery();
|
||||
|
||||
if (!nameResult->next())
|
||||
{
|
||||
if (!nameResult->next()) {
|
||||
delete nameLookup;
|
||||
nameLookup = nullptr;
|
||||
|
||||
Game::logger->Log("PropertyEntranceComponent", "Failed to find property owner name for %llu!\n", cloneId);
|
||||
|
||||
continue;
|
||||
} else {
|
||||
isOwned = cloneId == character->GetPropertyCloneID();
|
||||
ownerName = nameResult->getString(1).asStdString();
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.IsOwner = owner == entity->GetObjectID();
|
||||
entry.OwnerName = nameResult->getString(1).asStdString();
|
||||
}
|
||||
|
||||
if (!moderating)
|
||||
{
|
||||
entry.Name = name;
|
||||
entry.Description = description;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.Name = "[Awaiting approval] " + name;
|
||||
entry.Description = "[Awaiting approval] " + description;
|
||||
}
|
||||
|
||||
entry.IsFriend = privacyOption == static_cast<int32_t>(PropertyPrivacyOption::Friends);
|
||||
entry.Reputation = reputation;
|
||||
entry.CloneId = cloneId;
|
||||
entry.IsModeratorApproved = true;
|
||||
entry.AccessType = 3;
|
||||
|
||||
entries.push_back(entry);
|
||||
delete nameResult;
|
||||
nameResult = nullptr;
|
||||
|
||||
delete nameLookup;
|
||||
}
|
||||
nameLookup = nullptr;
|
||||
|
||||
std::string propertyName = propertyNameFromDb;
|
||||
std::string propertyDescription = propertyDescriptionFromDb;
|
||||
|
||||
bool isBestFriend = false;
|
||||
bool isFriend = false;
|
||||
|
||||
// Convert owner char id to LWOOBJID
|
||||
LWOOBJID ownerObjId = owner;
|
||||
ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_CHARACTER);
|
||||
ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_PERSISTENT);
|
||||
|
||||
// Query to get friend and best friend fields
|
||||
auto friendCheck = Database::CreatePreppedStmt("SELECT best_friend FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)");
|
||||
|
||||
friendCheck->setInt64(1, entity->GetObjectID());
|
||||
friendCheck->setInt64(2, ownerObjId);
|
||||
friendCheck->setInt64(3, ownerObjId);
|
||||
friendCheck->setInt64(4, entity->GetObjectID());
|
||||
|
||||
auto friendResult = friendCheck->executeQuery();
|
||||
|
||||
// If we got a result than the two players are friends.
|
||||
if (friendResult->next()) {
|
||||
isFriend = true;
|
||||
if (friendResult->getInt(1) == 2) {
|
||||
isBestFriend = true;
|
||||
}
|
||||
}
|
||||
|
||||
delete friendCheck;
|
||||
friendCheck = nullptr;
|
||||
|
||||
delete friendResult;
|
||||
friendResult = nullptr;
|
||||
|
||||
bool isModeratorApproved = propertyEntry->getBoolean(10);
|
||||
|
||||
if (!isModeratorApproved && entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR) {
|
||||
propertyName = "[AWAITING APPROVAL]";
|
||||
propertyDescription = "[AWAITING APPROVAL]";
|
||||
isModeratorApproved = true;
|
||||
}
|
||||
|
||||
bool isAlt = false;
|
||||
// Query to determine whether this property is an alt character of the entity.
|
||||
auto isAltQuery = Database::CreatePreppedStmt("SELECT id FROM charinfo where account_id in (SELECT account_id from charinfo WHERE id = ?) AND id = ?;");
|
||||
|
||||
isAltQuery->setInt(1, character->GetID());
|
||||
isAltQuery->setInt(2, owner);
|
||||
|
||||
auto isAltQueryResults = isAltQuery->executeQuery();
|
||||
|
||||
if (isAltQueryResults->next()) {
|
||||
isAlt = true;
|
||||
}
|
||||
|
||||
delete isAltQueryResults;
|
||||
isAltQueryResults = nullptr;
|
||||
|
||||
delete isAltQuery;
|
||||
isAltQuery = nullptr;
|
||||
|
||||
entry = SetPropertyValues(entry, cloneId, ownerName, propertyName, propertyDescription, reputation, isBestFriend, isFriend, isModeratorApproved, isAlt, isOwned, privacyOption, dateLastUpdated, performanceCost);
|
||||
|
||||
entries.push_back(entry);
|
||||
}
|
||||
|
||||
delete propertyEntry;
|
||||
propertyEntry = nullptr;
|
||||
|
||||
delete propertyLookup;
|
||||
|
||||
/*
|
||||
const auto entriesSize = entries.size();
|
||||
|
||||
if (startIndex != 0 && entriesSize > startIndex)
|
||||
{
|
||||
for (size_t i = 0; i < startIndex; i++)
|
||||
{
|
||||
entries.erase(entries.begin());
|
||||
}
|
||||
}
|
||||
*/
|
||||
propertyLookup = nullptr;
|
||||
|
||||
propertyQueries[entity->GetObjectID()] = entries;
|
||||
|
||||
// Query here is to figure out whether or not to display the button to go to the next page or not.
|
||||
int32_t numberOfProperties = 0;
|
||||
|
||||
GameMessages::SendPropertySelectQuery(
|
||||
m_Parent->GetObjectID(),
|
||||
startIndex,
|
||||
entries.size() >= numResults,
|
||||
character->GetPropertyCloneID(),
|
||||
false,
|
||||
true,
|
||||
entries,
|
||||
sysAddr
|
||||
);
|
||||
auto buttonQuery = BuildQuery(entity, sortMethod, "SELECT COUNT(*) FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.privacy_option >= ? ", false);
|
||||
auto propertiesLeft = Database::CreatePreppedStmt(buttonQuery);
|
||||
|
||||
propertiesLeft->setUInt(1, this->m_MapID);
|
||||
propertiesLeft->setString(2, searchString.c_str());
|
||||
propertiesLeft->setString(3, searchString.c_str());
|
||||
propertiesLeft->setString(4, searchString.c_str());
|
||||
propertiesLeft->setInt(5, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2);
|
||||
|
||||
auto result = propertiesLeft->executeQuery();
|
||||
result->next();
|
||||
numberOfProperties = result->getInt(1);
|
||||
|
||||
delete result;
|
||||
result = nullptr;
|
||||
|
||||
delete propertiesLeft;
|
||||
propertiesLeft = nullptr;
|
||||
|
||||
GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, numberOfProperties - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr);
|
||||
}
|
@ -1,17 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "Component.h"
|
||||
#include "Entity.h"
|
||||
#include "EntityManager.h"
|
||||
#include "GameMessages.h"
|
||||
#include "Component.h"
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* Represents the launch pad that's used to select and browse properties
|
||||
*/
|
||||
class PropertyEntranceComponent : public Component
|
||||
{
|
||||
public:
|
||||
class PropertyEntranceComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_PROPERTY_ENTRANCE;
|
||||
explicit PropertyEntranceComponent(uint32_t componentID, Entity* parent);
|
||||
|
||||
@ -24,11 +24,11 @@ public:
|
||||
/**
|
||||
* Handles the event triggered when the entity selects a property to visit and makes the entity to there
|
||||
* @param entity the entity that triggered the event
|
||||
* @param index the clone ID of the property to visit
|
||||
* @param index the index of the property property
|
||||
* @param returnToZone whether or not the entity wishes to go back to the launch zone
|
||||
* @param sysAddr the address to send gamemessage responses to
|
||||
*/
|
||||
void OnEnterProperty(Entity* entity, uint32_t index, bool returnToZone, const SystemAddress &sysAddr);
|
||||
void OnEnterProperty(Entity* entity, uint32_t index, bool returnToZone, const SystemAddress& sysAddr);
|
||||
|
||||
/**
|
||||
* Handles a request for information on available properties when an entity lands on the property
|
||||
@ -38,23 +38,13 @@ public:
|
||||
* @param playerOwn only query properties owned by the entity
|
||||
* @param updateUi unused
|
||||
* @param numResults unused
|
||||
* @param reputation unused
|
||||
* @param lReputationTime unused
|
||||
* @param sortMethod unused
|
||||
* @param startIndex the minimum index to start the query off
|
||||
* @param filterText property names to search for
|
||||
* @param sysAddr the address to send gamemessage responses to
|
||||
*/
|
||||
void OnPropertyEntranceSync(Entity* entity,
|
||||
bool includeNullAddress,
|
||||
bool includeNullDescription,
|
||||
bool playerOwn,
|
||||
bool updateUi,
|
||||
int32_t numResults,
|
||||
int32_t reputation,
|
||||
int32_t sortMethod,
|
||||
int32_t startIndex,
|
||||
std::string filterText,
|
||||
const SystemAddress &sysAddr);
|
||||
void OnPropertyEntranceSync(Entity* entity, bool includeNullAddress, bool includeNullDescription, bool playerOwn, bool updateUi, int32_t numResults, int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, const SystemAddress& sysAddr);
|
||||
|
||||
/**
|
||||
* Returns the name of this property
|
||||
@ -68,8 +58,11 @@ public:
|
||||
*/
|
||||
[[nodiscard]] LWOMAPID GetMapID() const { return m_MapID; };
|
||||
|
||||
private:
|
||||
PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", float reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, float performanceCost = 0.0f);
|
||||
|
||||
std::string BuildQuery(Entity* entity, int32_t sortMethod, std::string customQuery = "", bool wantLimits = true);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Cache of property information that was queried for property launched, indexed by property ID
|
||||
*/
|
||||
@ -84,4 +77,13 @@ private:
|
||||
* The base map ID for this property (Avant Grove, etc).
|
||||
*/
|
||||
LWOMAPID m_MapID;
|
||||
|
||||
enum ePropertySortType : int32_t {
|
||||
SORT_TYPE_FRIENDS = 0,
|
||||
SORT_TYPE_REPUTATION = 1,
|
||||
SORT_TYPE_RECENT = 3,
|
||||
SORT_TYPE_FEATURED = 5
|
||||
};
|
||||
|
||||
std::string baseQueryForProperties = "SELECT p.* FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.privacy_option >= ? ";
|
||||
};
|
||||
|
@ -68,13 +68,18 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo
|
||||
this->owner = propertyEntry->getUInt64(2);
|
||||
this->owner = GeneralUtils::SetBit(this->owner, OBJECT_BIT_CHARACTER);
|
||||
this->owner = GeneralUtils::SetBit(this->owner, OBJECT_BIT_PERSISTENT);
|
||||
this->clone_Id = propertyEntry->getInt(2);
|
||||
this->propertyName = propertyEntry->getString(5).c_str();
|
||||
this->propertyDescription = propertyEntry->getString(6).c_str();
|
||||
this->privacyOption = static_cast<PropertyPrivacyOption>(propertyEntry->getUInt(9));
|
||||
this->claimedTime = propertyEntry->getUInt64(13);
|
||||
this->moderatorRequested = propertyEntry->getInt(10) == 0 && rejectionReason == "" && privacyOption == PropertyPrivacyOption::Public;
|
||||
this->LastUpdatedTime = propertyEntry->getUInt64(11);
|
||||
this->claimedTime = propertyEntry->getUInt64(12);
|
||||
this->rejectionReason = propertyEntry->getString(13).asStdString();
|
||||
this->reputation = propertyEntry->getUInt(14);
|
||||
|
||||
Load();
|
||||
}
|
||||
}
|
||||
|
||||
delete propertyLookup;
|
||||
}
|
||||
@ -152,12 +157,18 @@ void PropertyManagementComponent::SetPrivacyOption(PropertyPrivacyOption value)
|
||||
value = PropertyPrivacyOption::Private;
|
||||
}
|
||||
|
||||
if (value == PropertyPrivacyOption::Public && privacyOption != PropertyPrivacyOption::Public) {
|
||||
rejectionReason = "";
|
||||
moderatorRequested = true;
|
||||
}
|
||||
privacyOption = value;
|
||||
|
||||
auto* propertyUpdate = Database::CreatePreppedStmt("UPDATE properties SET privacy_option = ? WHERE id = ?;");
|
||||
auto* propertyUpdate = Database::CreatePreppedStmt("UPDATE properties SET privacy_option = ?, rejection_reason = ?, mod_approved = ? WHERE id = ?;");
|
||||
|
||||
propertyUpdate->setInt(1, static_cast<int32_t>(value));
|
||||
propertyUpdate->setInt64(2, propertyId);
|
||||
propertyUpdate->setString(2, "");
|
||||
propertyUpdate->setInt(3, 0);
|
||||
propertyUpdate->setInt64(4, propertyId);
|
||||
|
||||
propertyUpdate->executeUpdate();
|
||||
}
|
||||
@ -181,38 +192,46 @@ void PropertyManagementComponent::UpdatePropertyDetails(std::string name, std::s
|
||||
OnQueryPropertyData(GetOwner(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
void PropertyManagementComponent::Claim(const LWOOBJID playerId)
|
||||
bool PropertyManagementComponent::Claim(const LWOOBJID playerId)
|
||||
{
|
||||
if (owner != LWOOBJID_EMPTY)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
SetOwnerId(playerId);
|
||||
|
||||
auto* zone = dZoneManager::Instance()->GetZone();
|
||||
|
||||
const auto& worldId = zone->GetZoneID();
|
||||
const auto zoneId = worldId.GetMapID();
|
||||
const auto cloneId = worldId.GetCloneID();
|
||||
|
||||
auto* entity = EntityManager::Instance()->GetEntity(playerId);
|
||||
|
||||
auto* user = entity->GetParentUser();
|
||||
|
||||
auto character = entity->GetCharacter();
|
||||
if (!character) return false;
|
||||
|
||||
auto* zone = dZoneManager::Instance()->GetZone();
|
||||
|
||||
const auto& worldId = zone->GetZoneID();
|
||||
const auto propertyZoneId = worldId.GetMapID();
|
||||
const auto propertyCloneId = worldId.GetCloneID();
|
||||
|
||||
const auto playerCloneId = character->GetPropertyCloneID();
|
||||
|
||||
// If we are not on our clone do not allow us to claim the property
|
||||
if (propertyCloneId != playerCloneId) return false;
|
||||
|
||||
SetOwnerId(playerId);
|
||||
|
||||
propertyId = ObjectIDManager::GenerateRandomObjectID();
|
||||
|
||||
|
||||
auto* insertion = Database::CreatePreppedStmt(
|
||||
"INSERT INTO properties"
|
||||
"(id, owner_id, template_id, clone_id, name, description, rent_amount, rent_due, privacy_option, last_updated, time_claimed, rejection_reason, reputation, zone_id)"
|
||||
"VALUES (?, ?, ?, ?, ?, '', 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '', 0, ?)"
|
||||
"(id, owner_id, template_id, clone_id, name, description, rent_amount, rent_due, privacy_option, last_updated, time_claimed, rejection_reason, reputation, zone_id, performance_cost)"
|
||||
"VALUES (?, ?, ?, ?, ?, '', 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '', 0, ?, 0.0)"
|
||||
);
|
||||
insertion->setUInt64(1, propertyId);
|
||||
insertion->setUInt64(2, (uint32_t) playerId);
|
||||
insertion->setUInt(3, templateId);
|
||||
insertion->setUInt64(4, cloneId);
|
||||
insertion->setUInt64(4, playerCloneId);
|
||||
insertion->setString(5, zone->GetZoneName().c_str());
|
||||
insertion->setInt(6, zoneId);
|
||||
insertion->setInt(6, propertyZoneId);
|
||||
|
||||
// Try and execute the query, print an error if it fails.
|
||||
try
|
||||
@ -224,12 +243,14 @@ void PropertyManagementComponent::Claim(const LWOOBJID playerId)
|
||||
Game::logger->Log("PropertyManagementComponent", "Failed to execute query: (%s)!\n", exception.what());
|
||||
|
||||
throw exception;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* zoneControlObject = dZoneManager::Instance()->GetZoneControlObject();
|
||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControlObject)) {
|
||||
script->OnZonePropertyRented(zoneControlObject, entity);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PropertyManagementComponent::OnStartBuilding()
|
||||
@ -275,6 +296,8 @@ void PropertyManagementComponent::OnFinishBuilding()
|
||||
SetPrivacyOption(originalPrivacyOption);
|
||||
|
||||
UpdateApprovedStatus(false);
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const NiPoint3 position, NiQuaternion rotation)
|
||||
@ -685,9 +708,12 @@ void PropertyManagementComponent::Save()
|
||||
auto* remove = Database::CreatePreppedStmt("DELETE FROM properties_contents WHERE id = ?;");
|
||||
|
||||
lookup->setUInt64(1, propertyId);
|
||||
|
||||
auto* lookupResult = lookup->executeQuery();
|
||||
|
||||
sql::ResultSet* lookupResult = nullptr;
|
||||
try {
|
||||
lookupResult = lookup->executeQuery();
|
||||
} catch (sql::SQLException& ex) {
|
||||
Game::logger->Log("PropertyManagementComponent", "lookup error %s\n", ex.what());
|
||||
}
|
||||
std::vector<LWOOBJID> present;
|
||||
|
||||
while (lookupResult->next())
|
||||
@ -730,8 +756,11 @@ void PropertyManagementComponent::Save()
|
||||
insertion->setDouble(9, rotation.y);
|
||||
insertion->setDouble(10, rotation.z);
|
||||
insertion->setDouble(11, rotation.w);
|
||||
|
||||
insertion->execute();
|
||||
try {
|
||||
insertion->execute();
|
||||
} catch (sql::SQLException& ex) {
|
||||
Game::logger->Log("PropertyManagementComponent", "Error inserting into properties_contents. Error %s\n", ex.what());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -744,8 +773,11 @@ void PropertyManagementComponent::Save()
|
||||
update->setDouble(7, rotation.w);
|
||||
|
||||
update->setInt64(8, id);
|
||||
|
||||
update->executeUpdate();
|
||||
try {
|
||||
update->executeUpdate();
|
||||
} catch (sql::SQLException& ex) {
|
||||
Game::logger->Log("PropertyManagementComponent", "Error updating properties_contents. Error: %s\n", ex.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -757,8 +789,11 @@ void PropertyManagementComponent::Save()
|
||||
}
|
||||
|
||||
remove->setInt64(1, id);
|
||||
|
||||
remove->execute();
|
||||
try {
|
||||
remove->execute();
|
||||
} catch (sql::SQLException& ex) {
|
||||
Game::logger->Log("PropertyManagementComponent", "Error removing from properties_contents. Error %s\n", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
auto* removeUGC = Database::CreatePreppedStmt("DELETE FROM ugc WHERE id NOT IN (SELECT ugc_id FROM properties_contents);");
|
||||
@ -782,7 +817,7 @@ PropertyManagementComponent* PropertyManagementComponent::Instance()
|
||||
return instance;
|
||||
}
|
||||
|
||||
void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author) const
|
||||
void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author)
|
||||
{
|
||||
if (author == LWOOBJID_EMPTY) {
|
||||
author = m_Parent->GetObjectID();
|
||||
@ -821,18 +856,44 @@ void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const
|
||||
description = propertyDescription;
|
||||
claimed = claimedTime;
|
||||
privacy = static_cast<char>(this->privacyOption);
|
||||
}
|
||||
if (moderatorRequested) {
|
||||
auto checkStatus = Database::CreatePreppedStmt("SELECT rejection_reason, mod_approved FROM properties WHERE id = ?;");
|
||||
|
||||
checkStatus->setInt64(1, propertyId);
|
||||
|
||||
auto result = checkStatus->executeQuery();
|
||||
|
||||
result->next();
|
||||
|
||||
const auto reason = result->getString(1).asStdString();;
|
||||
const auto modApproved = result->getInt(2);
|
||||
if (reason != "") {
|
||||
moderatorRequested = false;
|
||||
rejectionReason = reason;
|
||||
} else if (reason == "" && modApproved == 1) {
|
||||
moderatorRequested = false;
|
||||
rejectionReason = "";
|
||||
} else {
|
||||
moderatorRequested = true;
|
||||
rejectionReason = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
message.moderatorRequested = moderatorRequested;
|
||||
message.reputation = reputation;
|
||||
message.LastUpdatedTime = LastUpdatedTime;
|
||||
message.OwnerId = ownerId;
|
||||
message.OwnerName = ownerName;
|
||||
message.Name = name;
|
||||
message.Description = description;
|
||||
message.ClaimedTime = claimed;
|
||||
message.PrivacyOption = privacy;
|
||||
|
||||
message.cloneId = clone_Id;
|
||||
message.rejectionReason = rejectionReason;
|
||||
message.Paths = GetPaths();
|
||||
|
||||
SendDownloadPropertyData(author, message, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
// send rejection here?
|
||||
}
|
||||
|
||||
void PropertyManagementComponent::OnUse(Entity* originator)
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
|
||||
@ -40,7 +41,7 @@ public:
|
||||
* @param sysAddr the address to send game message responses to
|
||||
* @param author optional explicit ID for the property, if not set defaults to the originator
|
||||
*/
|
||||
void OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author = LWOOBJID_EMPTY) const;
|
||||
void OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author = LWOOBJID_EMPTY);
|
||||
|
||||
/**
|
||||
* Handles an OnUse event, telling the client who owns this property, etc.
|
||||
@ -100,8 +101,10 @@ public:
|
||||
/**
|
||||
* Makes this property owned by the passed player ID, storing it in the database
|
||||
* @param playerId the ID of the entity that claimed the property
|
||||
*
|
||||
* @return If the claim is successful return true.
|
||||
*/
|
||||
void Claim(LWOOBJID playerId);
|
||||
bool Claim(LWOOBJID playerId);
|
||||
|
||||
/**
|
||||
* Event triggered when the owner of the property starts building, will kick other entities out
|
||||
@ -182,7 +185,7 @@ private:
|
||||
/**
|
||||
* The time since this property was claimed
|
||||
*/
|
||||
uint64_t claimedTime = 0;
|
||||
uint64_t claimedTime = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
|
||||
/**
|
||||
* The models that are placed on this property
|
||||
@ -194,11 +197,36 @@ private:
|
||||
*/
|
||||
std::string propertyName = "";
|
||||
|
||||
/**
|
||||
* The clone ID of this property
|
||||
*/
|
||||
LWOCLONEID clone_Id = 0;
|
||||
|
||||
/**
|
||||
* Whether a moderator was requested
|
||||
*/
|
||||
bool moderatorRequested = false;
|
||||
|
||||
/**
|
||||
* The rejection reason for the property
|
||||
*/
|
||||
std::string rejectionReason = "";
|
||||
|
||||
/**
|
||||
* The description of this property
|
||||
*/
|
||||
std::string propertyDescription = "";
|
||||
|
||||
/**
|
||||
* The reputation of this property
|
||||
*/
|
||||
uint32_t reputation = 0;
|
||||
|
||||
/**
|
||||
* The last time this property was updated
|
||||
*/
|
||||
uint32_t LastUpdatedTime = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
|
||||
/**
|
||||
* Determines which players may visit this property
|
||||
*/
|
||||
|
@ -41,13 +41,16 @@ void PropertyVendorComponent::OnBuyFromVendor(Entity* originator, const bool con
|
||||
{
|
||||
if (PropertyManagementComponent::Instance() == nullptr) return;
|
||||
|
||||
if (PropertyManagementComponent::Instance()->Claim(originator->GetObjectID()) == false) {
|
||||
Game::logger->Log("PropertyVendorComponent", "FAILED TO CLAIM PROPERTY. PLAYER ID IS %llu\n", originator->GetObjectID());
|
||||
return;
|
||||
}
|
||||
|
||||
GameMessages::SendPropertyRentalResponse(m_Parent->GetObjectID(), 0, 0, 0, 0, originator->GetSystemAddress());
|
||||
|
||||
auto* controller = dZoneManager::Instance()->GetZoneControlObject();
|
||||
|
||||
controller->OnFireEventServerSide(m_Parent, "propertyRented");
|
||||
|
||||
PropertyManagementComponent::Instance()->Claim(originator->GetObjectID());
|
||||
|
||||
PropertyManagementComponent::Instance()->SetOwner(originator);
|
||||
|
||||
|
@ -595,7 +595,9 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System
|
||||
case GAME_MSG_VEHICLE_NOTIFY_HIT_IMAGINATION_SERVER:
|
||||
GameMessages::HandleVehicleNotifyHitImaginationServer(inStream, entity, sysAddr);
|
||||
break;
|
||||
|
||||
case GAME_MSG_UPDATE_PROPERTY_PERFORMANCE_COST:
|
||||
GameMessages::HandleUpdatePropertyPerformanceCost(inStream, entity, sysAddr);
|
||||
break;
|
||||
// SG
|
||||
case GAME_MSG_UPDATE_SHOOTING_GALLERY_ROTATION:
|
||||
GameMessages::HandleUpdateShootingGalleryRotation(inStream, entity, sysAddr);
|
||||
|
@ -4137,6 +4137,41 @@ void GameMessages::HandleRacingPlayerInfoResetFinished(RakNet::BitStream* inStre
|
||||
}
|
||||
}
|
||||
|
||||
void GameMessages::SendUpdateReputation(const LWOOBJID objectId, const int64_t reputation, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(GAME_MSG::GAME_MSG_UPDATE_REPUTATION);
|
||||
|
||||
bitStream.Write(reputation);
|
||||
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::HandleUpdatePropertyPerformanceCost(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
float performanceCost = 0.0f;
|
||||
|
||||
if (inStream->ReadBit()) inStream->Read(performanceCost);
|
||||
|
||||
if (performanceCost == 0.0f) return;
|
||||
|
||||
auto zone = dZoneManager::Instance()->GetZone();
|
||||
const auto& worldId = zone->GetZoneID();
|
||||
const auto cloneId = worldId.GetCloneID();
|
||||
const auto zoneId = worldId.GetMapID();
|
||||
|
||||
auto updatePerformanceCostQuery = Database::CreatePreppedStmt("UPDATE properties SET performance_cost = ? WHERE clone_id = ? AND zone_id = ?");
|
||||
|
||||
updatePerformanceCostQuery->setDouble(1, performanceCost);
|
||||
updatePerformanceCostQuery->setInt(2, cloneId);
|
||||
updatePerformanceCostQuery->setInt(3, zoneId);
|
||||
|
||||
updatePerformanceCostQuery->executeUpdate();
|
||||
|
||||
delete updatePerformanceCostQuery;
|
||||
updatePerformanceCostQuery = nullptr;
|
||||
}
|
||||
|
||||
void GameMessages::HandleVehicleNotifyHitImaginationServer(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr)
|
||||
{
|
||||
|
@ -386,6 +386,8 @@ namespace GameMessages {
|
||||
bool bUseLeaderboards
|
||||
);
|
||||
|
||||
void HandleUpdatePropertyPerformanceCost(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
|
||||
void SendNotifyClientShootingGalleryScore(LWOOBJID objectId, const SystemAddress& sysAddr,
|
||||
float addTime,
|
||||
int32_t score,
|
||||
@ -395,6 +397,8 @@ namespace GameMessages {
|
||||
|
||||
void HandleUpdateShootingGalleryRotation(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
|
||||
void SendUpdateReputation(const LWOOBJID objectId, const int64_t reputation, const SystemAddress& sysAddr);
|
||||
|
||||
// Leaderboards
|
||||
void SendActivitySummaryLeaderboardData(const LWOOBJID& objectID, const Leaderboard* leaderboard,
|
||||
const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
@ -13,7 +13,7 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con
|
||||
stream.Write<int32_t>(TemplateID); // - template id
|
||||
stream.Write<uint16_t>(ZoneId); // - map id
|
||||
stream.Write<uint16_t>(VendorMapId); // - vendor map id
|
||||
stream.Write<uint32_t>(1);
|
||||
stream.Write<uint32_t>(cloneId); // clone id
|
||||
|
||||
const auto& name = GeneralUtils::ASCIIToUTF16(Name);
|
||||
stream.Write(uint32_t(name.size()));
|
||||
@ -40,11 +40,12 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con
|
||||
stream.Write<uint32_t>(0); // - minimum price
|
||||
stream.Write<uint32_t>(1); // - rent duration
|
||||
|
||||
stream.Write(ClaimedTime); // - timestamp
|
||||
stream.Write<uint64_t>(LastUpdatedTime); // - timestamp
|
||||
|
||||
stream.Write<uint32_t>(1);
|
||||
|
||||
stream.Write<uint64_t>(0);
|
||||
stream.Write<uint32_t>(reputation); // Reputation
|
||||
stream.Write<uint32_t>(0);
|
||||
|
||||
const auto& spawn = GeneralUtils::ASCIIToUTF16(SpawnName);
|
||||
stream.Write(uint32_t(spawn.size()));
|
||||
@ -63,9 +64,18 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con
|
||||
|
||||
stream.Write<uint64_t>(0);
|
||||
|
||||
stream.Write<uint32_t>(1);
|
||||
if (rejectionReason != "") stream.Write<uint32_t>(REJECTION_STATUS_REJECTED);
|
||||
else if (moderatorRequested == true && rejectionReason == "") stream.Write<uint32_t>(REJECTION_STATUS_APPROVED);
|
||||
else stream.Write<uint32_t>(REJECTION_STATUS_PENDING);
|
||||
|
||||
stream.Write<uint32_t>(0); // String length
|
||||
// Does this go here???
|
||||
// const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason);
|
||||
// stream.Write(uint32_t(rejectionReasonConverted.size()));
|
||||
// for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) {
|
||||
// stream.Write(uint16_t(rejectionReasonConverted[i]));
|
||||
// }
|
||||
|
||||
stream.Write<uint32_t>(0);
|
||||
|
||||
stream.Write<uint64_t>(0);
|
||||
|
||||
|
@ -28,12 +28,23 @@ namespace GameMessages
|
||||
|
||||
std::string Name = "";
|
||||
std::string Description = "";
|
||||
std::string rejectionReason = "";
|
||||
|
||||
bool moderatorRequested = 0;
|
||||
LWOCLONEID cloneId = 0;
|
||||
uint32_t reputation = 0;
|
||||
uint64_t ClaimedTime = 0;
|
||||
uint64_t LastUpdatedTime = 0;
|
||||
|
||||
NiPoint3 ZonePosition = { 548.0f, 406.0f, 178.0f };
|
||||
char PrivacyOption = 0;
|
||||
float MaxBuildHeight = 128.0f;
|
||||
std::vector<NiPoint3> Paths = {};
|
||||
private:
|
||||
enum RejectionStatus : uint32_t {
|
||||
REJECTION_STATUS_APPROVED = 0,
|
||||
REJECTION_STATUS_PENDING = 1,
|
||||
REJECTION_STATUS_REJECTED = 2
|
||||
};
|
||||
};
|
||||
}
|
@ -22,15 +22,16 @@ void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const
|
||||
stream.Write(static_cast<uint16_t>(description[i]));
|
||||
}
|
||||
|
||||
stream.Write(Reputation);
|
||||
stream.Write(IsBestFriend);
|
||||
stream.Write(IsFriend);
|
||||
stream.Write(IsModeratorApproved);
|
||||
stream.Write(IsAlt);
|
||||
stream.Write(IsOwner);
|
||||
stream.Write(AccessType);
|
||||
stream.Write(DatePublished);
|
||||
stream.Write(PerformanceCost);
|
||||
stream.Write(Reputation);
|
||||
stream.Write(IsBestFriend);
|
||||
stream.Write(IsFriend);
|
||||
stream.Write(IsModeratorApproved);
|
||||
stream.Write(IsAlt);
|
||||
stream.Write(IsOwned);
|
||||
stream.Write(AccessType);
|
||||
stream.Write(DateLastPublished);
|
||||
stream.Write(PerformanceIndex);
|
||||
stream.Write(PerformanceCost);
|
||||
}
|
||||
|
||||
void PropertySelectQueryProperty::Deserialize(RakNet::BitStream& stream) const
|
||||
|
@ -9,17 +9,18 @@ public:
|
||||
|
||||
void Deserialize(RakNet::BitStream& stream) const;
|
||||
|
||||
LWOCLONEID CloneId = LWOCLONEID_INVALID;
|
||||
std::string OwnerName = "";
|
||||
std::string Name = "";
|
||||
std::string Description = "";
|
||||
uint32_t Reputation = 0;
|
||||
bool IsBestFriend = false;
|
||||
bool IsFriend = false;
|
||||
bool IsModeratorApproved = false;
|
||||
bool IsAlt = false;
|
||||
bool IsOwner = false;
|
||||
uint32_t AccessType = 0;
|
||||
uint32_t DatePublished = 0;
|
||||
uint64_t PerformanceCost = 0;
|
||||
LWOCLONEID CloneId = LWOCLONEID_INVALID; // The cloneID of the property
|
||||
std::string OwnerName = ""; // The property owners name
|
||||
std::string Name = ""; // The property name
|
||||
std::string Description = ""; // The property description
|
||||
float Reputation = 0; // The reputation of the property
|
||||
bool IsBestFriend = false; // Whether or not the property belongs to a best friend
|
||||
bool IsFriend = false; // Whether or not the property belongs to a friend
|
||||
bool IsModeratorApproved = false; // Whether or not a moderator has approved this property
|
||||
bool IsAlt = false; // Whether or not the property is owned by an alt of the account owner
|
||||
bool IsOwned = false; // Whether or not the property is owned
|
||||
uint32_t AccessType = 0; // The privacy option of the property
|
||||
uint32_t DateLastPublished = 0; // The last day the property was published
|
||||
float PerformanceCost = 0; // The performance cost of the property
|
||||
uint32_t PerformanceIndex = 0; // The performance index of the property? Always 0?
|
||||
};
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "dLogger.h"
|
||||
#include "dServer.h"
|
||||
#include "dZoneManager.h"
|
||||
#include "Database.h"
|
||||
|
||||
Mission::Mission(MissionComponent* missionComponent, const uint32_t missionId) {
|
||||
m_MissionComponent = missionComponent;
|
||||
@ -516,8 +517,25 @@ void Mission::YieldRewards() {
|
||||
}
|
||||
|
||||
if (info->reward_reputation > 0) {
|
||||
// TODO: Track reputation in the character and database.
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_EARN_REPUTATION, 0, 0L, "", info->reward_reputation);
|
||||
auto character = entity->GetCharacter();
|
||||
if (!character) return;
|
||||
|
||||
auto charId = character->GetID();
|
||||
auto propertyCloneId = character->GetPropertyCloneID();
|
||||
|
||||
auto reputationUpdate = Database::CreatePreppedStmt("UPDATE properties SET reputation = reputation + ? where owner_id = ? AND clone_id = ?");
|
||||
|
||||
reputationUpdate->setInt64(1, info->reward_reputation);
|
||||
reputationUpdate->setInt(2, charId);
|
||||
reputationUpdate->setInt64(3, propertyCloneId);
|
||||
|
||||
reputationUpdate->executeUpdate();
|
||||
|
||||
delete reputationUpdate;
|
||||
reputationUpdate = nullptr;
|
||||
|
||||
GameMessages::SendUpdateReputation(entity->GetObjectID(), info->reward_reputation, entity->GetSystemAddress());
|
||||
}
|
||||
|
||||
if (info->reward_maxhealth > 0) {
|
||||
|
@ -382,6 +382,7 @@ enum GAME_MSG : unsigned short {
|
||||
GAME_MSG_PROPERTY_EDITOR_END = 725,
|
||||
GAME_MSG_START_PATHING = 735,
|
||||
GAME_MSG_NOTIFY_CLIENT_ZONE_OBJECT = 737,
|
||||
GAME_MSG_UPDATE_REPUTATION = 746,
|
||||
GAME_MSG_PROPERTY_RENTAL_RESPONSE = 750,
|
||||
GAME_MSG_REQUEST_PLATFORM_RESYNC = 760,
|
||||
GAME_MSG_PLATFORM_RESYNC = 761,
|
||||
@ -527,6 +528,7 @@ enum GAME_MSG : unsigned short {
|
||||
GAME_MSG_VEHICLE_NOTIFY_HIT_IMAGINATION_SERVER = 1606,
|
||||
GAME_MSG_ADD_RUN_SPEED_MODIFIER = 1505,
|
||||
GAME_MSG_REMOVE_RUN_SPEED_MODIFIER = 1506,
|
||||
GAME_MSG_UPDATE_PROPERTY_PERFORMANCE_COST = 1547,
|
||||
GAME_MSG_PROPERTY_ENTRANCE_BEGIN = 1553,
|
||||
GAME_MSG_REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1666,
|
||||
GAME_MSG_RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1667,
|
||||
|
1
migrations/dlu/3_add_performance_cost.sql
Normal file
1
migrations/dlu/3_add_performance_cost.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE properties ADD COLUMN performance_cost DOUBLE(20, 15) DEFAULT 0.0;
|
Loading…
Reference in New Issue
Block a user