character properties not hard coded are now dynamically fed into the info struct string, we can now SetInfoStruct(Player, "somevar", "avalue") and it will save to the DB to persist cross zone with GetInfoStruct(Player, "somevar")
This commit is contained in:
parent
05f5061c19
commit
fae7cf7773
@ -32,6 +32,7 @@
|
||||
#include "Skills.h"
|
||||
#include "Rules/Rules.h"
|
||||
#include "LuaInterface.h"
|
||||
#include "WorldDatabase.h"
|
||||
|
||||
extern World world;
|
||||
extern MasterItemList master_item_list;
|
||||
@ -40,6 +41,7 @@ extern MasterSkillList master_skill_list;
|
||||
extern RuleManager rule_manager;
|
||||
extern Classes classes;
|
||||
extern LuaInterface* lua_interface;
|
||||
extern WorldDatabase database;
|
||||
|
||||
Entity::Entity(){
|
||||
MapInfoStruct();
|
||||
@ -616,6 +618,65 @@ void Entity::MapInfoStruct()
|
||||
set_float_funcs["max_chase_distance"] = l::bind(&InfoStruct::set_max_chase_distance, &info_struct, l::_1);
|
||||
}
|
||||
|
||||
void Entity::RegisterProperty(const std::string& name) {
|
||||
int32 charID = 0;
|
||||
|
||||
if(IsPlayer())
|
||||
charID = ((Player*)this)->GetCharacterID();
|
||||
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
if (set_string_funcs.find(name) != set_string_funcs.end() ||
|
||||
get_string_funcs.find(name) != get_string_funcs.end())
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> wlock(propertiesMutex);
|
||||
if (set_string_funcs.find(name) != set_string_funcs.end() ||
|
||||
get_string_funcs.find(name) != get_string_funcs.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_string_funcs.emplace(name, [this, name, database, charID](std::string v) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(GetInfoStruct()->classMutex);
|
||||
GetInfoStruct()->props[name] = v;
|
||||
}
|
||||
if(charID)
|
||||
database.insertCharacterProperty(charID, const_cast<char*>(name.c_str()), const_cast<char*>(v.c_str()));
|
||||
});
|
||||
|
||||
get_string_funcs.emplace(name, [this, name]() -> std::string {
|
||||
std::lock_guard<std::mutex> lk(GetInfoStruct()->classMutex);
|
||||
auto it = GetInfoStruct()->props.find(name);
|
||||
return (it == GetInfoStruct()->props.end()) ? std::string{} : it->second;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::SetProperty(const std::string& name, const std::string& value) {
|
||||
auto it = set_string_funcs.find(name);
|
||||
if (it == set_string_funcs.end())
|
||||
return;
|
||||
|
||||
int32 charID = 0;
|
||||
|
||||
if(IsPlayer())
|
||||
charID = ((Player*)this)->GetCharacterID();
|
||||
|
||||
if(charID)
|
||||
database.insertCharacterProperty(charID, const_cast<char*>(name.c_str()), const_cast<char*>(value.c_str()));
|
||||
|
||||
return it->second(value);
|
||||
}
|
||||
|
||||
std::optional<std::string> Entity::GetProperty(const std::string& name) const {
|
||||
auto it = get_string_funcs.find(name);
|
||||
if (it == get_string_funcs.end()) return std::nullopt;
|
||||
return it->second();
|
||||
}
|
||||
|
||||
bool Entity::HasMoved(bool include_heading){
|
||||
if(GetX() == last_x && GetY() == last_y && GetZ() == last_z && ((!include_heading) || (include_heading && GetHeading() == last_heading)))
|
||||
return false;
|
||||
@ -3780,251 +3841,271 @@ void Entity::HaltMovement()
|
||||
|
||||
std::string Entity::GetInfoStructString(std::string field)
|
||||
{
|
||||
map<string, boost::function<std::string()>>::const_iterator itr = get_string_funcs.find(field);
|
||||
if(itr != get_string_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<std::string()>>::const_iterator itr = get_string_funcs.find(field);
|
||||
if(itr != get_string_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
int8 Entity::GetInfoStructInt8(std::string field)
|
||||
{
|
||||
map<string, boost::function<int8()>>::const_iterator itr = get_int8_funcs.find(field);
|
||||
if(itr != get_int8_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<int8()>>::const_iterator itr = get_int8_funcs.find(field);
|
||||
if(itr != get_int8_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16 Entity::GetInfoStructInt16(std::string field)
|
||||
{
|
||||
map<string, boost::function<int16()>>::const_iterator itr = get_int16_funcs.find(field);
|
||||
if(itr != get_int16_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<int16()>>::const_iterator itr = get_int16_funcs.find(field);
|
||||
if(itr != get_int16_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 Entity::GetInfoStructInt32(std::string field)
|
||||
{
|
||||
map<string, boost::function<int32()>>::const_iterator itr = get_int32_funcs.find(field);
|
||||
if(itr != get_int32_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<int32()>>::const_iterator itr = get_int32_funcs.find(field);
|
||||
if(itr != get_int32_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64 Entity::GetInfoStructInt64(std::string field)
|
||||
{
|
||||
map<string, boost::function<int64()>>::const_iterator itr = get_int64_funcs.find(field);
|
||||
if(itr != get_int64_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<int64()>>::const_iterator itr = get_int64_funcs.find(field);
|
||||
if(itr != get_int64_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sint8 Entity::GetInfoStructSInt8(std::string field)
|
||||
{
|
||||
map<string, boost::function<sint8()>>::const_iterator itr = get_sint8_funcs.find(field);
|
||||
if(itr != get_sint8_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<sint8()>>::const_iterator itr = get_sint8_funcs.find(field);
|
||||
if(itr != get_sint8_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sint16 Entity::GetInfoStructSInt16(std::string field)
|
||||
{
|
||||
map<string, boost::function<sint16()>>::const_iterator itr = get_sint16_funcs.find(field);
|
||||
if(itr != get_sint16_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<sint16()>>::const_iterator itr = get_sint16_funcs.find(field);
|
||||
if(itr != get_sint16_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sint32 Entity::GetInfoStructSInt32(std::string field)
|
||||
{
|
||||
map<string, boost::function<sint32()>>::const_iterator itr = get_sint32_funcs.find(field);
|
||||
if(itr != get_sint32_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<sint32()>>::const_iterator itr = get_sint32_funcs.find(field);
|
||||
if(itr != get_sint32_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sint64 Entity::GetInfoStructSInt64(std::string field)
|
||||
{
|
||||
map<string, boost::function<sint64()>>::const_iterator itr = get_sint64_funcs.find(field);
|
||||
if(itr != get_sint64_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<sint64()>>::const_iterator itr = get_sint64_funcs.find(field);
|
||||
if(itr != get_sint64_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Entity::GetInfoStructFloat(std::string field)
|
||||
{
|
||||
map<string, boost::function<float()>>::const_iterator itr = get_float_funcs.find(field);
|
||||
if(itr != get_float_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<float()>>::const_iterator itr = get_float_funcs.find(field);
|
||||
if(itr != get_float_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
int64 Entity::GetInfoStructUInt(std::string field)
|
||||
{
|
||||
map<string, boost::function<int8()>>::const_iterator itr = get_int8_funcs.find(field);
|
||||
if(itr != get_int8_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
map<string, boost::function<int16()>>::const_iterator itr2 = get_int16_funcs.find(field);
|
||||
if(itr2 != get_int16_funcs.end())
|
||||
{
|
||||
auto func = (itr2->second)();
|
||||
return func;
|
||||
}
|
||||
map<string, boost::function<int32()>>::const_iterator itr3 = get_int32_funcs.find(field);
|
||||
if(itr3 != get_int32_funcs.end())
|
||||
{
|
||||
auto func = (itr3->second)();
|
||||
return func;
|
||||
}
|
||||
map<string, boost::function<int64()>>::const_iterator itr4 = get_int64_funcs.find(field);
|
||||
if(itr4 != get_int64_funcs.end())
|
||||
{
|
||||
auto func = (itr4->second)();
|
||||
return func;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<int8()>>::const_iterator itr = get_int8_funcs.find(field);
|
||||
if(itr != get_int8_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
map<string, boost::function<int16()>>::const_iterator itr2 = get_int16_funcs.find(field);
|
||||
if(itr2 != get_int16_funcs.end())
|
||||
{
|
||||
auto func = (itr2->second)();
|
||||
return func;
|
||||
}
|
||||
map<string, boost::function<int32()>>::const_iterator itr3 = get_int32_funcs.find(field);
|
||||
if(itr3 != get_int32_funcs.end())
|
||||
{
|
||||
auto func = (itr3->second)();
|
||||
return func;
|
||||
}
|
||||
map<string, boost::function<int64()>>::const_iterator itr4 = get_int64_funcs.find(field);
|
||||
if(itr4 != get_int64_funcs.end())
|
||||
{
|
||||
auto func = (itr4->second)();
|
||||
return func;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sint64 Entity::GetInfoStructSInt(std::string field)
|
||||
{
|
||||
map<string, boost::function<sint8()>>::const_iterator itr = get_sint8_funcs.find(field);
|
||||
if(itr != get_sint8_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
map<string, boost::function<sint16()>>::const_iterator itr2 = get_sint16_funcs.find(field);
|
||||
if(itr2 != get_sint16_funcs.end())
|
||||
{
|
||||
auto func = (itr2->second)();
|
||||
return func;
|
||||
}
|
||||
map<string, boost::function<sint32()>>::const_iterator itr3 = get_sint32_funcs.find(field);
|
||||
if(itr3 != get_sint32_funcs.end())
|
||||
{
|
||||
auto func = (itr3->second)();
|
||||
return func;
|
||||
}
|
||||
map<string, boost::function<sint64()>>::const_iterator itr4 = get_sint64_funcs.find(field);
|
||||
if(itr4 != get_sint64_funcs.end())
|
||||
{
|
||||
auto func = (itr4->second)();
|
||||
return func;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<sint8()>>::const_iterator itr = get_sint8_funcs.find(field);
|
||||
if(itr != get_sint8_funcs.end())
|
||||
{
|
||||
auto func = (itr->second)();
|
||||
return func;
|
||||
}
|
||||
map<string, boost::function<sint16()>>::const_iterator itr2 = get_sint16_funcs.find(field);
|
||||
if(itr2 != get_sint16_funcs.end())
|
||||
{
|
||||
auto func = (itr2->second)();
|
||||
return func;
|
||||
}
|
||||
map<string, boost::function<sint32()>>::const_iterator itr3 = get_sint32_funcs.find(field);
|
||||
if(itr3 != get_sint32_funcs.end())
|
||||
{
|
||||
auto func = (itr3->second)();
|
||||
return func;
|
||||
}
|
||||
map<string, boost::function<sint64()>>::const_iterator itr4 = get_sint64_funcs.find(field);
|
||||
if(itr4 != get_sint64_funcs.end())
|
||||
{
|
||||
auto func = (itr4->second)();
|
||||
return func;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool Entity::SetInfoStructString(std::string field, std::string value)
|
||||
{
|
||||
map<string, boost::function<void(std::string)>>::const_iterator itr = set_string_funcs.find(field);
|
||||
if(itr != set_string_funcs.end())
|
||||
{
|
||||
(itr->second)(value);
|
||||
return true;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<void(std::string)>>::const_iterator itr = set_string_funcs.find(field);
|
||||
if(itr != set_string_funcs.end())
|
||||
{
|
||||
(itr->second)(value);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
RegisterProperty(field);
|
||||
SetProperty(field, value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Entity::SetInfoStructUInt(std::string field, int64 value)
|
||||
{
|
||||
map<string, boost::function<void(int8)>>::const_iterator itr = set_int8_funcs.find(field);
|
||||
if(itr != set_int8_funcs.end())
|
||||
{
|
||||
(itr->second)((int8)value);
|
||||
return true;
|
||||
}
|
||||
map<string, boost::function<void(int16)>>::const_iterator itr2 = set_int16_funcs.find(field);
|
||||
if(itr2 != set_int16_funcs.end())
|
||||
{
|
||||
(itr2->second)((int16)value);
|
||||
return true;
|
||||
}
|
||||
map<string, boost::function<void(int32)>>::const_iterator itr3 = set_int32_funcs.find(field);
|
||||
if(itr3 != set_int32_funcs.end())
|
||||
{
|
||||
(itr3->second)((int32)value);
|
||||
return true;
|
||||
}
|
||||
map<string, boost::function<void(int64)>>::const_iterator itr4 = set_int64_funcs.find(field);
|
||||
if(itr4 != set_int64_funcs.end())
|
||||
{
|
||||
(itr4->second)(value);
|
||||
return true;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<void(int8)>>::const_iterator itr = set_int8_funcs.find(field);
|
||||
if(itr != set_int8_funcs.end())
|
||||
{
|
||||
(itr->second)((int8)value);
|
||||
return true;
|
||||
}
|
||||
map<string, boost::function<void(int16)>>::const_iterator itr2 = set_int16_funcs.find(field);
|
||||
if(itr2 != set_int16_funcs.end())
|
||||
{
|
||||
(itr2->second)((int16)value);
|
||||
return true;
|
||||
}
|
||||
map<string, boost::function<void(int32)>>::const_iterator itr3 = set_int32_funcs.find(field);
|
||||
if(itr3 != set_int32_funcs.end())
|
||||
{
|
||||
(itr3->second)((int32)value);
|
||||
return true;
|
||||
}
|
||||
map<string, boost::function<void(int64)>>::const_iterator itr4 = set_int64_funcs.find(field);
|
||||
if(itr4 != set_int64_funcs.end())
|
||||
{
|
||||
(itr4->second)(value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Entity::SetInfoStructSInt(std::string field, sint64 value)
|
||||
{
|
||||
map<string, boost::function<void(sint8)>>::const_iterator itr = set_sint8_funcs.find(field);
|
||||
if(itr != set_sint8_funcs.end())
|
||||
{
|
||||
(itr->second)((sint8)value);
|
||||
return true;
|
||||
}
|
||||
map<string, boost::function<void(sint16)>>::const_iterator itr2 = set_sint16_funcs.find(field);
|
||||
if(itr2 != set_sint16_funcs.end())
|
||||
{
|
||||
(itr2->second)((sint16)value);
|
||||
return true;
|
||||
}
|
||||
map<string, boost::function<void(sint32)>>::const_iterator itr3 = set_sint32_funcs.find(field);
|
||||
if(itr3 != set_sint32_funcs.end())
|
||||
{
|
||||
(itr3->second)((sint32)value);
|
||||
return true;
|
||||
}
|
||||
map<string, boost::function<void(sint64)>>::const_iterator itr4 = set_sint64_funcs.find(field);
|
||||
if(itr4 != set_sint64_funcs.end())
|
||||
{
|
||||
(itr4->second)(value);
|
||||
return true;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<void(sint8)>>::const_iterator itr = set_sint8_funcs.find(field);
|
||||
if(itr != set_sint8_funcs.end())
|
||||
{
|
||||
(itr->second)((sint8)value);
|
||||
return true;
|
||||
}
|
||||
map<string, boost::function<void(sint16)>>::const_iterator itr2 = set_sint16_funcs.find(field);
|
||||
if(itr2 != set_sint16_funcs.end())
|
||||
{
|
||||
(itr2->second)((sint16)value);
|
||||
return true;
|
||||
}
|
||||
map<string, boost::function<void(sint32)>>::const_iterator itr3 = set_sint32_funcs.find(field);
|
||||
if(itr3 != set_sint32_funcs.end())
|
||||
{
|
||||
(itr3->second)((sint32)value);
|
||||
return true;
|
||||
}
|
||||
map<string, boost::function<void(sint64)>>::const_iterator itr4 = set_sint64_funcs.find(field);
|
||||
if(itr4 != set_sint64_funcs.end())
|
||||
{
|
||||
(itr4->second)(value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Entity::SetInfoStructFloat(std::string field, float value)
|
||||
{
|
||||
map<string, boost::function<void(float)>>::const_iterator itr = set_float_funcs.find(field);
|
||||
if(itr != set_float_funcs.end())
|
||||
{
|
||||
(itr->second)(value);
|
||||
return true;
|
||||
}
|
||||
std::shared_lock<std::shared_mutex> rlock(propertiesMutex);
|
||||
map<string, boost::function<void(float)>>::const_iterator itr = set_float_funcs.find(field);
|
||||
if(itr != set_float_funcs.end())
|
||||
{
|
||||
(itr->second)(value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include <set>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <optional>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/lambda/bind.hpp>
|
||||
|
||||
@ -1110,6 +1112,9 @@ struct InfoStruct{
|
||||
// maintained via their own mutex
|
||||
SpellEffects spell_effects[45];
|
||||
MaintainedEffects maintained_effects[30];
|
||||
// when PacketStruct is fixed for C++17 this should become a shared_mutex and handle read/write lock
|
||||
std::mutex classMutex;
|
||||
std::unordered_map<std::string, std::string> props;
|
||||
private:
|
||||
std::string name_;
|
||||
int8 class1_;
|
||||
@ -1328,8 +1333,6 @@ private:
|
||||
int8 max_spell_reduction_override_;
|
||||
|
||||
float max_chase_distance_;
|
||||
// when PacketStruct is fixed for C++17 this should become a shared_mutex and handle read/write lock
|
||||
std::mutex classMutex;
|
||||
};
|
||||
|
||||
struct WardInfo {
|
||||
@ -1449,6 +1452,9 @@ public:
|
||||
void DeleteSpellEffects(bool removeClient = false);
|
||||
void RemoveSpells(bool unfriendlyOnly = false);
|
||||
void MapInfoStruct();
|
||||
void RegisterProperty(const std::string& name);
|
||||
void SetProperty(const std::string& name, const std::string& value);
|
||||
std::optional<std::string> GetProperty(const std::string& name) const;
|
||||
virtual float GetDodgeChance();
|
||||
virtual void AddMaintainedSpell(LuaSpell* spell);
|
||||
virtual void AddSpellEffect(LuaSpell* spell, int32 override_expire_time = 0);
|
||||
@ -2205,6 +2211,8 @@ private:
|
||||
map<string, boost::function<void(sint8)> > set_sint8_funcs;
|
||||
|
||||
map<string, boost::function<void(std::string)> > set_string_funcs;
|
||||
|
||||
mutable std::shared_mutex propertiesMutex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -2146,125 +2146,187 @@ bool WorldDatabase::insertCharacterProperty(Client* client, char* propName, char
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldDatabase::loadCharacterProperties(Client* client) {
|
||||
bool WorldDatabase::insertCharacterProperty(int32 charID, char* propName, char* propValue) {
|
||||
Query query, query2;
|
||||
|
||||
string update_status = string("update character_properties set propvalue='%s' where charid=%i and propname='%s'");
|
||||
query.RunQuery2(Q_UPDATE, update_status.c_str(), propValue, charID, propName);
|
||||
if (!query.GetAffectedRows())
|
||||
{
|
||||
query2.RunQuery2(Q_UPDATE, "insert into character_properties (charid, propname, propvalue) values(%i, '%s', '%s')", charID, propName, propValue);
|
||||
if (query2.GetErrorNumber() && query2.GetError() && query2.GetErrorNumber() < 0xFFFFFFFF) {
|
||||
LogWrite(WORLD__ERROR, 0, "World", "Error in insertCharacterProperty query '%s': %s", query.GetQuery(), query.GetError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldDatabase::loadCharacterProperties(Client* client, bool preload) {
|
||||
Query query;
|
||||
MYSQL_ROW row;
|
||||
int32 id = 0;
|
||||
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT propname, propvalue FROM character_properties where charid = %i", client->GetCharacterID());
|
||||
MYSQL_RES* result = query.RunQuery2(Q_SELECT,
|
||||
"SELECT propname, propvalue FROM character_properties WHERE charid = %i",
|
||||
client->GetCharacterID());
|
||||
|
||||
// no character found
|
||||
if (result == NULL) {
|
||||
LogWrite(PLAYER__ERROR, 0, "Player", "Error loading character properties for '%s'", client->GetPlayer()->GetName());
|
||||
LogWrite(PLAYER__ERROR, 0, "Player", "Error loading character properties for '%s'",
|
||||
client->GetPlayer()->GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
while (result && (row = mysql_fetch_row(result))) {
|
||||
char* prop_name = row[0];
|
||||
char* prop_name = row[0];
|
||||
char* prop_value = row[1];
|
||||
|
||||
if (!prop_name || !prop_value)
|
||||
continue;
|
||||
|
||||
if (!stricmp(prop_name, CHAR_PROPERTY_SPEED))
|
||||
{
|
||||
float new_speed = atof(prop_value);
|
||||
client->GetPlayer()->SetSpeed(new_speed, true);
|
||||
client->GetPlayer()->SetCharSheetChanged(true);
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_FLYMODE))
|
||||
{
|
||||
int8 flymode = atoul(prop_value);
|
||||
if (flymode) // avoid fly mode notification unless enabled
|
||||
ClientPacketFunctions::SendFlyMode(client, flymode, false);
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_INVUL))
|
||||
{
|
||||
int8 invul = atoul(prop_value);
|
||||
client->GetPlayer()->SetInvulnerable(invul == 1);
|
||||
if (client->GetPlayer()->GetInvulnerable())
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "You are now invulnerable!");
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GMVISION))
|
||||
{
|
||||
int8 val = atoul(prop_value);
|
||||
client->GetPlayer()->SetGMVision(val == 1);
|
||||
client->GetCurrentZone()->SendAllSpawnsForVisChange(client, false);
|
||||
if (val)
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "GM Vision Enabled!");
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_REGIONDEBUG))
|
||||
{
|
||||
int8 val = atoul(prop_value);
|
||||
bool matched = false;
|
||||
|
||||
client->SetRegionDebug(val == 1);
|
||||
if (val)
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Region Debug Enabled!");
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_LUADEBUG))
|
||||
{
|
||||
int8 val = atoul(prop_value);
|
||||
if (val)
|
||||
{
|
||||
client->SetLuaDebugClient(true);
|
||||
if (lua_interface)
|
||||
lua_interface->UpdateDebugClients(client);
|
||||
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "You will now receive LUA error messages.");
|
||||
if (!stricmp(prop_name, CHAR_PROPERTY_SPEED)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
float new_speed = (float)atof(prop_value);
|
||||
client->GetPlayer()->SetSpeed(new_speed, true);
|
||||
client->GetPlayer()->SetCharSheetChanged(true);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPLOOTMETHOD))
|
||||
{
|
||||
int8 val = atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_loot_method(val);
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_FLYMODE)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 flymode = (int8)atoul(prop_value);
|
||||
if (flymode) // avoid fly mode notification unless enabled
|
||||
ClientPacketFunctions::SendFlyMode(client, flymode, false);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPLOOTITEMRARITY))
|
||||
{
|
||||
int8 val = atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_loot_items_rarity(val);
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_INVUL)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 invul = (int8)atoul(prop_value);
|
||||
client->GetPlayer()->SetInvulnerable(invul == 1);
|
||||
if (client->GetPlayer()->GetInvulnerable())
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "You are now invulnerable!");
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPAUTOSPLIT))
|
||||
{
|
||||
int8 val = atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_auto_split(val);
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GMVISION)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 val = (int8)atoul(prop_value);
|
||||
client->GetPlayer()->SetGMVision(val == 1);
|
||||
client->GetCurrentZone()->SendAllSpawnsForVisChange(client, false);
|
||||
if (val)
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "GM Vision Enabled!");
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPDEFAULTYELL))
|
||||
{
|
||||
int8 val = atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_default_yell(val);
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_REGIONDEBUG)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 val = (int8)atoul(prop_value);
|
||||
client->SetRegionDebug(val == 1);
|
||||
if (val)
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Region Debug Enabled!");
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPAUTOLOCK))
|
||||
{
|
||||
int8 val = atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_autolock(val);
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_LUADEBUG)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 val = (int8)atoul(prop_value);
|
||||
if (val) {
|
||||
client->SetLuaDebugClient(true);
|
||||
if (lua_interface)
|
||||
lua_interface->UpdateDebugClients(client);
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "You will now receive LUA error messages.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPSOLOAUTOLOCK))
|
||||
{
|
||||
int8 val = atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_solo_autolock(val);
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPLOOTMETHOD)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 val = (int8)atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_loot_method(val);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_AUTOLOOTMETHOD))
|
||||
{
|
||||
int8 val = atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_auto_loot_method(val);
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPLOOTITEMRARITY)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 val = (int8)atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_loot_items_rarity(val);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPLOCKMETHOD))
|
||||
{
|
||||
int8 val = atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_lock_method(val);
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPAUTOSPLIT)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 val = (int8)atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_auto_split(val);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_ASSISTAUTOATTACK))
|
||||
{
|
||||
int8 val = atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_assist_auto_attack(val);
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPDEFAULTYELL)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 val = (int8)atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_default_yell(val);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_SETACTIVEFOOD))
|
||||
{
|
||||
int32 val = atoul(prop_value);
|
||||
client->GetPlayer()->SetActiveFoodUniqueID(val, false);
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPAUTOLOCK)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 val = (int8)atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_autolock(val);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_SETACTIVEDRINK))
|
||||
{
|
||||
int32 val = atoul(prop_value);
|
||||
client->GetPlayer()->SetActiveDrinkUniqueID(val, false);
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPSOLOAUTOLOCK)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 val = (int8)atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_solo_autolock(val);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_AUTOLOOTMETHOD)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 val = (int8)atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_auto_loot_method(val);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_GROUPLOCKMETHOD)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 val = (int8)atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_group_lock_method(val);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_ASSISTAUTOATTACK)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int8 val = (int8)atoul(prop_value);
|
||||
client->GetPlayer()->GetInfoStruct()->set_assist_auto_attack(val);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_SETACTIVEFOOD)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int32 val = (int32)atoul(prop_value);
|
||||
client->GetPlayer()->SetActiveFoodUniqueID(val, false);
|
||||
}
|
||||
}
|
||||
else if (!stricmp(prop_name, CHAR_PROPERTY_SETACTIVEDRINK)) {
|
||||
matched = true;
|
||||
if (!preload) {
|
||||
int32 val = (int32)atoul(prop_value);
|
||||
client->GetPlayer()->SetActiveDrinkUniqueID(val, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Unknown property: only act during preload AND only if no stricmp matched
|
||||
// (we're in the 'else', so matched == false by definition)
|
||||
if (preload) {
|
||||
client->GetPlayer()->RegisterProperty(std::string(prop_name));
|
||||
client->GetPlayer()->SetProperty(std::string(prop_name), std::string(prop_value));
|
||||
}
|
||||
// When preload == false, we intentionally ignore unknown properties.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,7 +333,8 @@ public:
|
||||
bool InsertCharacterStats(int32 character_id, int8 class_id, int8 race_id);
|
||||
bool UpdateCharacterTimeStamp(int32 account_id, int32 character_id, int32 timestamp);
|
||||
bool insertCharacterProperty(Client* client, char* propName, char* propValue);
|
||||
bool loadCharacterProperties(Client* client);
|
||||
bool insertCharacterProperty(int32 charID, char* propName, char* propValue);
|
||||
bool loadCharacterProperties(Client* client, bool preload = false);
|
||||
string GetPlayerName(char* name);
|
||||
int32 GetCharacterTimeStamp(int32 character_id, int32 account_id,bool* char_exists);
|
||||
int32 GetCharacterTimeStamp(int32 character_id);
|
||||
|
@ -12249,6 +12249,7 @@ bool Client::HandleNewLogin(int32 account_id, int32 access_code)
|
||||
new_client_login = NewLoginState::LOGIN_ALLOWED;
|
||||
}
|
||||
|
||||
database.loadCharacterProperties(this, true);
|
||||
// vault slots
|
||||
RefreshVaultSlotCount();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user