mirror of
https://gitlab.com/Scribble/gdlenhanced.git
synced 2026-08-17 14:23:04 -04:00
Pathing for mobs Hooker fix for mansion only items Fix for copper/silver Removed racial reqs on treasure Updated mutation process
1409 lines
35 KiB
C++
1409 lines
35 KiB
C++
#include <StdAfx.h>
|
|
#include "House.h"
|
|
#include "World.h"
|
|
#include "WeenieFactory.h"
|
|
#include "Player.h"
|
|
#include "InferredPortalData.h"
|
|
#include "AllegianceManager.h"
|
|
#include "Client.h"
|
|
#include "EmoteManager.h"
|
|
#include "HouseManager.h"
|
|
|
|
#define HOUSE_SAVE_INTERVAL 300.0
|
|
|
|
|
|
DEFINE_PACK(CHouseData)
|
|
{
|
|
pWriter->Write<uint32_t>(_slumLordId);
|
|
pWriter->Write<uint32_t>(_ownerId);
|
|
pWriter->Write<uint32_t>(_ownerAccount);
|
|
pWriter->Write<uint32_t>(_purchaseTimestamp);
|
|
pWriter->Write<uint32_t>(_currentMaintenancePeriod);
|
|
pWriter->Write<uint32_t>(_houseType);
|
|
_position.Pack(pWriter);
|
|
_buy.Pack(pWriter);
|
|
_rent.Pack(pWriter);
|
|
_accessList.Pack(pWriter);
|
|
_storageAccessList.Pack(pWriter);
|
|
pWriter->Write<bool>(_allegianceAccess);
|
|
pWriter->Write<bool>(_allegianceStorageAccess);
|
|
pWriter->Write<bool>(_everyoneAccess);
|
|
pWriter->Write<bool>(_everyoneStorageAccess);
|
|
pWriter->Write<bool>(_hooksVisible);
|
|
}
|
|
|
|
DEFINE_UNPACK(CHouseData)
|
|
{
|
|
_slumLordId = pReader->Read<uint32_t>();
|
|
_ownerId = pReader->Read<uint32_t>();
|
|
_ownerAccount = pReader->Read<uint32_t>();
|
|
_purchaseTimestamp = pReader->Read<uint32_t>();
|
|
_currentMaintenancePeriod = pReader->Read<uint32_t>();
|
|
_houseType = pReader->Read<uint32_t>();
|
|
_position.UnPack(pReader);
|
|
_buy.UnPack(pReader);
|
|
_rent.UnPack(pReader);
|
|
_accessList.UnPack(pReader);
|
|
_storageAccessList.UnPack(pReader);
|
|
_allegianceAccess = pReader->Read<bool>();
|
|
_allegianceStorageAccess = pReader->Read<bool>();
|
|
_everyoneAccess = pReader->Read<bool>();
|
|
_everyoneStorageAccess = pReader->Read<bool>();
|
|
_hooksVisible = pReader->Read<bool>();
|
|
|
|
return true;
|
|
}
|
|
|
|
void CHouseData::ClearOwnershipData()
|
|
{
|
|
_ownerId = 0;
|
|
_ownerAccount = 0;
|
|
_purchaseTimestamp = 0;
|
|
_currentMaintenancePeriod = 0;
|
|
_allegianceAccess = false;
|
|
_allegianceStorageAccess = false;
|
|
_everyoneAccess = false;
|
|
_everyoneStorageAccess = false;
|
|
_hooksVisible = true;
|
|
_rent.clear();
|
|
_buy.clear();
|
|
_accessList.clear();
|
|
_storageAccessList.clear();
|
|
}
|
|
|
|
void CHouseData::SetHookVisibility(bool newSetting)
|
|
{
|
|
_hooksVisible = newSetting;
|
|
|
|
for (auto hook_id : _hookList)
|
|
{
|
|
CWeenieObject *hookWeenie = g_pWorld->FindObject(hook_id, true);
|
|
|
|
if (!hookWeenie)
|
|
continue;
|
|
|
|
CHookWeenie *hook = hookWeenie->AsHook();
|
|
|
|
if (!hook)
|
|
continue;
|
|
|
|
hook->SetHookVisibility(newSetting);
|
|
}
|
|
Save();
|
|
}
|
|
|
|
void CHouseData::AbandonHouse()
|
|
{
|
|
CWeenieObject *owner = g_pWorld->FindObject(_ownerId);
|
|
if (owner)
|
|
{
|
|
//if the player is offline we won't find him but that's okay, we will just update his housing data when he logins in UpdateHouseData()
|
|
owner->m_Qualities.RemoveDataID(HOUSEID_DID);
|
|
owner->NotifyDIDStatUpdated(HOUSEID_DID);
|
|
}
|
|
|
|
ClearOwnershipData();
|
|
SetHookVisibility(true);
|
|
|
|
if (CWeenieObject *slumLord = g_pWorld->FindObject(_slumLordId))
|
|
{
|
|
slumLord->DoForcedMotion(Motion_Off);
|
|
CHouseWeenie* house = slumLord->AsSlumLord()->GetHouse();
|
|
if (house)
|
|
house->m_Qualities.SetString(HOUSE_OWNER_NAME_STRING, "");
|
|
}
|
|
|
|
if (owner)
|
|
g_pHouseManager->SendHouseData(owner->AsPlayer(), _houseId);
|
|
|
|
Save();
|
|
}
|
|
|
|
void CHouseData::Save()
|
|
{
|
|
BinaryWriter writer;
|
|
Pack(&writer);
|
|
g_pDBIO->CreateOrUpdateHouseData(_houseId, writer.GetData(), writer.GetSize());
|
|
}
|
|
|
|
|
|
CHouseWeenie::CHouseWeenie()
|
|
{
|
|
m_bDontClear = true;
|
|
}
|
|
|
|
void CHouseWeenie::EnsureLink(CWeenieObject *source)
|
|
{
|
|
source->m_Qualities.SetInstanceID(HOUSE_IID, GetID());
|
|
source->m_Qualities.SetDataID(HOUSEID_DID, GetHouseDID());
|
|
|
|
if (source->AsSlumLord())
|
|
{
|
|
m_Qualities.SetInstanceID(SLUMLORD_IID, source->GetID());
|
|
}
|
|
|
|
if (source->AsHook())
|
|
{
|
|
CHouseData *houseData = source->AsHook()->GetHouseData();
|
|
if (houseData)
|
|
houseData->_hookList.insert(source->GetID());
|
|
}
|
|
|
|
if (source->AsBootSpot())
|
|
{
|
|
m_Qualities.SetPosition(HOUSE_BOOT_POSITION, source->GetPosition());
|
|
}
|
|
|
|
|
|
|
|
// Deed_WeenieType
|
|
// BootSpot_WeenieType
|
|
// HousePortal_WeenieType
|
|
// Storage_WeenieType
|
|
}
|
|
|
|
CHouseData *CHouseWeenie::GetHouseData()
|
|
{
|
|
return g_pHouseManager->GetHouseData(GetHouseDID());
|
|
}
|
|
|
|
std::string CHouseWeenie::GetHouseOwnerName()
|
|
{
|
|
uint32_t owner = GetHouseOwner();
|
|
|
|
if (!owner)
|
|
return "";
|
|
|
|
std::string ownerName;
|
|
ownerName = g_pWorld->GetPlayerName(owner, true);
|
|
if (ownerName.empty())
|
|
{
|
|
if (!m_Qualities.InqString(HOUSE_OWNER_NAME_STRING, ownerName))
|
|
{
|
|
ownerName = g_pDBIO->GetPlayerCharacterName(GetHouseData()->_ownerId);
|
|
m_Qualities.SetString(HOUSE_OWNER_NAME_STRING, ownerName);
|
|
}
|
|
}
|
|
|
|
return ownerName;
|
|
}
|
|
|
|
uint32_t CHouseWeenie::GetHouseOwner()
|
|
{
|
|
return GetHouseData()->_ownerId;
|
|
//return InqIIDQuality(HOUSE_OWNER_IID, 0);
|
|
}
|
|
|
|
uint32_t CHouseWeenie::GetHouseDID()
|
|
{
|
|
return InqDIDQuality(HOUSEID_DID, 0);
|
|
}
|
|
|
|
int CHouseWeenie::GetHouseType()
|
|
{
|
|
return InqIntQuality(HOUSE_TYPE_INT, 0);
|
|
}
|
|
|
|
CSlumLordWeenie *CHouseWeenie::GetSlumLord()
|
|
{
|
|
if (CWeenieObject *slumlord = g_pWorld->FindObject(InqIIDQuality(SLUMLORD_IID, 0), true))
|
|
{
|
|
return slumlord->AsSlumLord();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
bool CHouseWeenie::HasAccess(CPlayerWeenie *requester)
|
|
{
|
|
if (!requester)
|
|
return false;
|
|
|
|
CHouseData *houseData = GetHouseData();
|
|
|
|
uint32_t requesterId = requester->GetID();
|
|
uint32_t houseOwnerId = GetHouseOwner();
|
|
|
|
if (requesterId == houseData->_ownerId)
|
|
return true;
|
|
|
|
if (houseData->_everyoneAccess)
|
|
return true;
|
|
|
|
if (requester->GetClient()->GetAccountInfo().id == houseData->_ownerAccount)
|
|
return true;
|
|
|
|
if (std::find(houseData->_accessList.begin(), houseData->_accessList.end(), requesterId) != houseData->_accessList.end())
|
|
return true;
|
|
|
|
if (houseData->_allegianceAccess)
|
|
{
|
|
std::string alleg;
|
|
if (requester->m_Qualities.InqString(ALLEGIANCE_NAME_STRING, alleg)) {
|
|
|
|
AllegianceTreeNode *ownerAllegianceNode = g_pAllegianceManager->GetTreeNode(houseOwnerId);
|
|
AllegianceTreeNode *requesterAllegianceNode = g_pAllegianceManager->GetTreeNode(requesterId);
|
|
|
|
if (ownerAllegianceNode && requesterAllegianceNode)
|
|
{
|
|
if (ownerAllegianceNode->_monarchID == requesterAllegianceNode->_monarchID)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if (!ownerAllegianceNode)
|
|
SERVER_ERROR << "House Owner:" << houseOwnerId << " may not exist. Check DB";
|
|
else
|
|
SERVER_ERROR << "Requestor:" << requesterId << " may not have or be in allegiance.";
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return HasStorageAccess(requester); //storage access automatically grants access.
|
|
}
|
|
|
|
bool CHouseWeenie::HasStorageAccess(CPlayerWeenie *requester)
|
|
{
|
|
if (!requester)
|
|
return false;
|
|
|
|
CHouseData *houseData = GetHouseData();
|
|
|
|
uint32_t requesterId = requester->GetID();
|
|
uint32_t houseOwnerId = GetHouseOwner();
|
|
|
|
if (requesterId == houseData->_ownerId)
|
|
return true;
|
|
|
|
if (houseData->_everyoneStorageAccess)
|
|
return true;
|
|
|
|
if (requester->GetClient()->GetAccountInfo().id == houseData->_ownerAccount)
|
|
return true;
|
|
|
|
if (std::find(houseData->_storageAccessList.begin(), houseData->_storageAccessList.end(), requesterId) != houseData->_storageAccessList.end())
|
|
return true;
|
|
|
|
if (houseData->_allegianceStorageAccess)
|
|
{
|
|
std::string alleg;
|
|
if (requester->m_Qualities.InqString(ALLEGIANCE_NAME_STRING, alleg)) {
|
|
AllegianceTreeNode *ownerAllegianceNode = g_pAllegianceManager->GetTreeNode(houseOwnerId);
|
|
AllegianceTreeNode *requesterAllegianceNode = g_pAllegianceManager->GetTreeNode(requesterId);
|
|
|
|
if (ownerAllegianceNode && requesterAllegianceNode)
|
|
{
|
|
if (ownerAllegianceNode->_monarchID == requesterAllegianceNode->_monarchID)
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
CSlumLordWeenie::CSlumLordWeenie()
|
|
{
|
|
m_bDontClear = true;
|
|
_nextHeartBeat = Timer::cur_time; //let's tick as soon as possible to establish if we have an owner.
|
|
}
|
|
|
|
void CSlumLordWeenie::Tick()
|
|
{
|
|
if (_nextHeartBeat != -1.0 && _nextHeartBeat <= Timer::cur_time)
|
|
{
|
|
if (!_initialized)
|
|
{
|
|
_nextHeartBeat = Timer::cur_time + Random::GenUInt(1, 10);
|
|
|
|
CHouseWeenie *house = GetHouse();
|
|
if (!house)
|
|
return;
|
|
|
|
CHouseData *houseData = house->GetHouseData();
|
|
houseData->_slumLordId = GetID();
|
|
houseData->_position = m_Position;
|
|
|
|
if (houseData->_ownerId)
|
|
DoForcedMotion(Motion_On);
|
|
else
|
|
DoForcedMotion(Motion_Off);
|
|
|
|
//for (auto hook_id : houseData->_hookList)
|
|
//{
|
|
// CWeenieObject *hook = g_pWorld->FindObject(hook_id, true);
|
|
|
|
// if (!hook)
|
|
// continue;
|
|
|
|
// if(hook->AsHook())
|
|
// hook->AsHook()->UpdateHookedObject();
|
|
//}
|
|
|
|
_initialized = true;
|
|
|
|
_nextSave = Timer::cur_time + HOUSE_SAVE_INTERVAL;
|
|
}
|
|
else
|
|
{
|
|
CHouseWeenie *house = GetHouse();
|
|
if (!house)
|
|
return;
|
|
CHouseData *houseData = house->GetHouseData();
|
|
if (houseData->_ownerId)
|
|
DoForcedMotion(Motion_On);
|
|
else
|
|
DoForcedMotion(Motion_Off);
|
|
|
|
//check global data and update if necessary
|
|
uint32_t now = g_pPhatSDK->GetCurrTimeStamp();
|
|
if (g_pHouseManager->_nextHouseMaintenancePeriod < now)
|
|
{
|
|
if (!g_pHouseManager->_freeHouseMaintenancePeriod)
|
|
g_pHouseManager->_currentHouseMaintenancePeriod = now;
|
|
g_pHouseManager->_freeHouseMaintenancePeriod = false;
|
|
g_pHouseManager->_nextHouseMaintenancePeriod = now + (30 * 24 * 60 * 60); //in 30 days.
|
|
}
|
|
|
|
CheckRentPeriod();
|
|
|
|
_nextHeartBeat = Timer::cur_time + Random::GenUInt(30 * 60, 60 * 60); //check again in 30 to 60 minutes.
|
|
}
|
|
}
|
|
}
|
|
|
|
CHouseWeenie *CSlumLordWeenie::GetHouse()
|
|
{
|
|
if (CWeenieObject *house = g_pWorld->FindObject(InqIIDQuality(HOUSE_IID, 0), true))
|
|
{
|
|
return house->AsHouse();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void CSlumLordWeenie::GetHouseProfile(HouseProfile &prof)
|
|
{
|
|
prof._slumlord = GetID();
|
|
prof._maintenance_free = 0;
|
|
prof._bitmask = Active_HouseBitmask;
|
|
prof._min_level = InqIntQuality(MIN_LEVEL_INT, -1);
|
|
prof._max_level = InqIntQuality(MAX_LEVEL_INT, -1);
|
|
prof._min_alleg_rank = 0;
|
|
|
|
if (m_Qualities._create_list)
|
|
{
|
|
for (auto &entry : *m_Qualities._create_list)
|
|
{
|
|
if (entry.regen_algorithm == HouseBuy_DestinationType)
|
|
{
|
|
HousePayment pay;
|
|
pay.wcid = entry.wcid;
|
|
pay.num = entry.amount;
|
|
pay.paid = 0;
|
|
|
|
CWeenieDefaults *weenieDef = g_pWeenieFactory->GetWeenieDefaults(entry.wcid);
|
|
if (weenieDef)
|
|
{
|
|
weenieDef->m_Qualities.InqString(NAME_STRING, pay.name);
|
|
weenieDef->m_Qualities.InqString(PLURAL_NAME_STRING, pay.pname);
|
|
}
|
|
prof._buy.push_back(pay);
|
|
}
|
|
else if (entry.regen_algorithm == HouseRent_DestinationType)
|
|
{
|
|
HousePayment pay;
|
|
pay.wcid = entry.wcid;
|
|
pay.num = entry.amount;
|
|
pay.paid = 0;
|
|
|
|
CWeenieDefaults *weenieDef = g_pWeenieFactory->GetWeenieDefaults(entry.wcid);
|
|
if (weenieDef)
|
|
{
|
|
weenieDef->m_Qualities.InqString(NAME_STRING, pay.name);
|
|
weenieDef->m_Qualities.InqString(PLURAL_NAME_STRING, pay.pname);
|
|
}
|
|
|
|
prof._rent.push_back(pay);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (CHouseWeenie *house = GetHouse())
|
|
{
|
|
prof._name = house->GetHouseOwnerName();
|
|
prof._owner = house->GetHouseOwner();
|
|
prof._id = house->GetHouseDID();
|
|
prof._type = house->GetHouseType();
|
|
}
|
|
}
|
|
|
|
int CSlumLordWeenie::DoUseResponse(CWeenieObject *other)
|
|
{
|
|
HouseProfile prof;
|
|
GetHouseProfile(prof);
|
|
|
|
if (CHouseWeenie *house = GetHouse())
|
|
{
|
|
CHouseData *houseData = house->GetHouseData();
|
|
if (houseData && houseData->_ownerId)
|
|
prof._rent = houseData->_rent; //get the real house rent information that may contain payments
|
|
|
|
uint32_t houseDID = 0;
|
|
if (other->GetID() == houseData->_ownerId && (!other->m_Qualities.InqDataID(HOUSEID_DID, houseDID) || houseDID == 0)) // player lost link
|
|
{
|
|
other->m_Qualities.SetDataID(HOUSEID_DID, houseData->_houseId);
|
|
}
|
|
}
|
|
|
|
BinaryWriter profMsg;
|
|
profMsg.Write<uint32_t>(0x21D);
|
|
prof.Pack(&profMsg);
|
|
other->SendNetMessage(&profMsg, PRIVATE_MSG, TRUE, FALSE);
|
|
|
|
return CWeenieObject::DoUseResponse(other);
|
|
}
|
|
|
|
void CSlumLordWeenie::BuyHouse(CPlayerWeenie *player, const PackableList<uint32_t> &items)
|
|
{
|
|
if (CHouseWeenie *house = GetHouse())
|
|
{
|
|
if (player->GetAccountHouseId())
|
|
{
|
|
player->SendText("You may only own one dwelling at a time.", LTT_DEFAULT); //made up message.
|
|
return;
|
|
}
|
|
|
|
if (house->GetHouseOwner())
|
|
{
|
|
player->SendText("That dwelling already has an owner.", LTT_DEFAULT); //made up message.
|
|
return;
|
|
}
|
|
|
|
if (int minLevel = InqIntQuality(MIN_LEVEL_INT, 0))
|
|
{
|
|
if (player->InqIntQuality(LEVEL_INT, 1) < minLevel)
|
|
{
|
|
player->SendText(csprintf("You must be at least level %d to purchase this dwelling.", minLevel), LTT_DEFAULT); //made up message.
|
|
return;
|
|
}
|
|
}
|
|
|
|
AllegianceTreeNode *allegianceNode = g_pAllegianceManager->GetTreeNode(player->GetID());
|
|
if (InqBoolQuality(HOUSE_REQUIRES_MONARCH_BOOL, false))
|
|
{
|
|
if (!allegianceNode || allegianceNode->_patronID != 0)
|
|
{
|
|
player->SendText("You must be a monarch to purchase this dwelling.", LTT_DEFAULT); //made up message.
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (int minAllegianceRank = InqIntQuality(ALLEGIANCE_MIN_LEVEL_INT, 0))
|
|
{
|
|
if (!allegianceNode || allegianceNode->_rank < minAllegianceRank)
|
|
{
|
|
player->SendText(csprintf("Your allegiance rank must be at least %d to purchase this dwelling.", minAllegianceRank), LTT_DEFAULT); //made up message.
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (house->GetHouseType() != Apartment_HouseType && player->InqIntQuality(HOUSE_PURCHASE_TIMESTAMP_INT, 0) + (30 * 24 * 60) > g_pPhatSDK->GetCurrTimeStamp())
|
|
{
|
|
player->SendText("You cannot buy another landscape house yet. This restriction does not apply to apartments.", LTT_DEFAULT); //made up message.
|
|
return;
|
|
}
|
|
|
|
HouseProfile prof;
|
|
GetHouseProfile(prof);
|
|
|
|
std::map<CWeenieObject *, int> consumeList;
|
|
|
|
for (HousePayment &payment : prof._buy)
|
|
{
|
|
for (auto &itemID : items)
|
|
{
|
|
CWeenieObject *item = g_pWorld->FindObject(itemID);
|
|
|
|
if (!item || !player->FindContainedItem(itemID))
|
|
continue;
|
|
|
|
if (payment.wcid == W_COINSTACK_CLASS)
|
|
{
|
|
if (payment.paid < payment.num)
|
|
{
|
|
if (item->m_Qualities.id == payment.wcid || item->InqIntQuality(ITEM_TYPE_INT, 0) == ITEM_TYPE::TYPE_PROMISSORY_NOTE)
|
|
{
|
|
payment.paid += item->InqIntQuality(VALUE_INT, 0);
|
|
consumeList[item] = item->InqIntQuality(STACK_SIZE_INT, 1); //add the complete stack, we will sort values later.
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (item->m_Qualities.id == payment.wcid && payment.paid < payment.num)
|
|
{
|
|
int amountToConsume = min(item->InqIntQuality(STACK_SIZE_INT, 1), payment.num - payment.paid);
|
|
payment.paid += amountToConsume;
|
|
consumeList[item] = amountToConsume;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (HousePayment &payment : prof._buy)
|
|
{
|
|
if (payment.paid < payment.num)
|
|
{
|
|
player->SendText("That's not everything you need to buy this dwelling.", LTT_DEFAULT); //made up message.
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (auto entry : consumeList)
|
|
{
|
|
CWeenieObject *item = entry.first;
|
|
int amount = entry.second;
|
|
|
|
if (item->m_Qualities.id == W_COINSTACK_CLASS || item->InqIntQuality(ITEM_TYPE_INT, 0) == ITEM_TYPE::TYPE_PROMISSORY_NOTE)
|
|
item->Remove(); //we remove the entire stack of coins/trade notes and then give back the appropriate amount.
|
|
else
|
|
{
|
|
int stackSize = item->InqIntQuality(STACK_SIZE_INT, 1);
|
|
item->DecrementStackNum(amount);
|
|
}
|
|
}
|
|
|
|
int timeStamp = g_pPhatSDK->GetCurrTimeStamp();
|
|
player->SendText("Congratulations! You now own this dwelling.", LTT_DEFAULT);
|
|
|
|
//Disabled the cooldown on purchasing houses
|
|
//if (house->GetHouseType() != 4)//apartments are not affected nor do the affect the house purchase frequency limitation
|
|
//{
|
|
// player->m_Qualities.SetInt(HOUSE_PURCHASE_TIMESTAMP_INT, timeStamp);
|
|
// player->NotifyIntStatUpdated(HOUSE_PURCHASE_TIMESTAMP_INT);
|
|
//}
|
|
|
|
player->m_Qualities.SetDataID(HOUSEID_DID, house->GetHouseDID());
|
|
player->NotifyDIDStatUpdated(HOUSEID_DID);
|
|
|
|
CHouseData *houseData = house->GetHouseData();
|
|
houseData->ClearOwnershipData();
|
|
houseData->_ownerId = player->GetID();
|
|
houseData->_ownerAccount = player->GetClient()->GetAccountInfo().id;
|
|
houseData->_purchaseTimestamp = timeStamp;
|
|
houseData->_currentMaintenancePeriod = g_pHouseManager->_currentHouseMaintenancePeriod;
|
|
houseData->_rent = prof._rent;
|
|
houseData->_buy = prof._buy;
|
|
houseData->_houseType = house->GetHouseType();
|
|
houseData->_position = GetPosition();
|
|
|
|
for (auto hook_id : houseData->_hookList)
|
|
{
|
|
CWeenieObject *hook = g_pWorld->FindObject(hook_id, true);
|
|
|
|
if (!hook)
|
|
continue;
|
|
|
|
hook->m_Qualities.SetInstanceID(HOUSE_OWNER_IID, player->GetID());
|
|
hook->NotifyIIDStatUpdated(HOUSE_OWNER_IID, false);
|
|
|
|
hook->Save();
|
|
}
|
|
houseData->SetHookVisibility(true);
|
|
|
|
DoForcedMotion(Motion_On);
|
|
g_pHouseManager->SendHouseData(player, house->GetHouseDID());
|
|
DoUseResponse(player);
|
|
player->RecalculateCoinAmount(W_COINSTACK_CLASS);
|
|
player->Save();
|
|
house->m_Qualities.SetString(HOUSE_OWNER_NAME_STRING, player->GetName());
|
|
house->Save();
|
|
houseData->Save();
|
|
|
|
HOUSE_LOG << "Player:" << player->GetName() << "bought house" << houseData->_houseId;
|
|
}
|
|
}
|
|
|
|
void CSlumLordWeenie::CheckRentPeriod()
|
|
{
|
|
if (CHouseWeenie *house = GetHouse())
|
|
{
|
|
CHouseData *houseData = house->GetHouseData();
|
|
|
|
if (!houseData->_ownerId)
|
|
return; //no owner no rent
|
|
|
|
if (houseData->_currentMaintenancePeriod < g_pHouseManager->_currentHouseMaintenancePeriod)
|
|
{
|
|
//check if we still meet the allegiance requirements to own this house.
|
|
AllegianceTreeNode *allegianceNode = g_pAllegianceManager->GetTreeNode(houseData->_ownerId);
|
|
if (InqBoolQuality(HOUSE_REQUIRES_MONARCH_BOOL, false))
|
|
{
|
|
if (!allegianceNode || allegianceNode->_patronID)
|
|
{
|
|
if (CWeenieObject *player = g_pWorld->FindObject(houseData->_ownerId)) //todo: a way to inform the allegiance and the player if he is offline.
|
|
player->SendText("You no longer meet the monarch requirement for your dwelling so it has been abandoned.", LTT_DEFAULT); //made up message.
|
|
houseData->AbandonHouse();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (int minAllegianceRank = InqIntQuality(ALLEGIANCE_MIN_LEVEL_INT, 0))
|
|
{
|
|
if (!allegianceNode || allegianceNode->_rank < minAllegianceRank)
|
|
{
|
|
if (CWeenieObject *player = g_pWorld->FindObject(houseData->_ownerId)) //todo: a way to inform the allegiance and the player if he is offline.
|
|
player->SendText(csprintf("You no longer meet the allegiance rank requirement for your dwelling so it has been abandoned.", minAllegianceRank), LTT_DEFAULT); //made up message.
|
|
houseData->AbandonHouse();
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool fullyPaid = true;
|
|
for (HousePayment &payment : houseData->_rent)
|
|
{
|
|
if (payment.paid < payment.num)
|
|
{
|
|
fullyPaid = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (fullyPaid)
|
|
{
|
|
HouseProfile prof;
|
|
GetHouseProfile(prof);
|
|
|
|
//update rent and buy values from house profile, maybe the prices have changed!
|
|
houseData->_rent = prof._rent;
|
|
houseData->_buy = prof._buy;
|
|
houseData->Save();
|
|
|
|
if (CWeenieObject *owner = g_pWorld->FindObject(houseData->_ownerId))
|
|
g_pHouseManager->SendHouseData(owner->AsPlayer(), house->GetHouseDID()); //update house's owner panel if the owner is online.
|
|
}
|
|
else
|
|
{
|
|
//houseData->AbandonHouse(); temporarily disable abandon house on rent not paid
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CSlumLordWeenie::RentHouse(CPlayerWeenie *player, const PackableList<uint32_t> &items)
|
|
{
|
|
if (CHouseWeenie *house = GetHouse())
|
|
{
|
|
CHouseData *houseData = house->GetHouseData();
|
|
|
|
if (!houseData->_ownerId)
|
|
{
|
|
player->SendText("That dwelling has no owner.", LTT_DEFAULT); //made up message.
|
|
return;
|
|
}
|
|
|
|
bool requiresRent = false;
|
|
for (HousePayment &payment : houseData->_rent)
|
|
{
|
|
if (payment.paid < payment.num)
|
|
{
|
|
requiresRent = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!requiresRent)
|
|
{
|
|
player->SendText("The maintenance has already been paid for this period. You may not prepay the next period's maintenance.", LTT_DEFAULT); //made up message.
|
|
return;
|
|
}
|
|
|
|
std::map<CWeenieObject *, int> consumeList;
|
|
|
|
for (HousePayment &payment : houseData->_rent)
|
|
{
|
|
for (auto &itemID : items)
|
|
{
|
|
CWeenieObject *item = g_pWorld->FindObject(itemID);
|
|
|
|
if (!item || !player->FindContainedItem(itemID))
|
|
continue;
|
|
|
|
if (payment.wcid == W_COINSTACK_CLASS)
|
|
{
|
|
if (payment.paid < payment.num)
|
|
{
|
|
if (item->m_Qualities.id == payment.wcid || item->InqIntQuality(ITEM_TYPE_INT, 0) == ITEM_TYPE::TYPE_PROMISSORY_NOTE)
|
|
{
|
|
payment.paid += item->InqIntQuality(VALUE_INT, 0);
|
|
consumeList[item] = item->InqIntQuality(STACK_SIZE_INT, 1); //add the complete stack, we will sort values later.
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (item->m_Qualities.id == payment.wcid && payment.paid < payment.num)
|
|
{
|
|
int amountToConsume = min(item->InqIntQuality(STACK_SIZE_INT, 1), payment.num - payment.paid);
|
|
payment.paid += amountToConsume;
|
|
consumeList[item] = amountToConsume;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto entry : consumeList)
|
|
{
|
|
CWeenieObject *item = entry.first;
|
|
int amount = entry.second;
|
|
|
|
if (item->m_Qualities.id == W_COINSTACK_CLASS || item->InqIntQuality(ITEM_TYPE_INT, 0) == ITEM_TYPE::TYPE_PROMISSORY_NOTE)
|
|
item->Remove(); //we remove the entire stack of coins/trade notes and then give back the appropriate amount.
|
|
else
|
|
{
|
|
int stackSize = item->InqIntQuality(STACK_SIZE_INT, 1);
|
|
item->DecrementStackNum(amount);
|
|
}
|
|
}
|
|
|
|
DoUseResponse(player);
|
|
player->RecalculateCoinAmount(W_COINSTACK_CLASS);
|
|
player->Save();
|
|
house->Save();
|
|
houseData->Save();
|
|
|
|
|
|
if (CWeenieObject *owner = g_pWorld->FindObject(houseData->_ownerId))
|
|
g_pHouseManager->SendHouseData(owner->AsPlayer(), house->GetHouseDID()); //update house's owner panel if the owner is online.
|
|
|
|
HOUSE_LOG << "Player:" << player->GetName() << "paid rent" << houseData->_houseId;
|
|
}
|
|
}
|
|
|
|
|
|
CHookWeenie::CHookWeenie()
|
|
{
|
|
m_bDontClear = true;
|
|
_nextInitCheck = Timer::cur_time;
|
|
}
|
|
|
|
void CHookWeenie::Tick()
|
|
{
|
|
//if (!_initialized && _nextInitCheck != -1.0 && _nextInitCheck <= Timer::cur_time)
|
|
//{
|
|
// _nextInitCheck = Timer::cur_time + Random::GenUInt(1, 10);
|
|
|
|
// CHouseData *houseData = GetHouseData();
|
|
|
|
// if (!houseData)
|
|
// return;
|
|
|
|
// if (houseData->_ownerId)
|
|
// {
|
|
// SetHookVisibility(houseData->_hooksVisible);
|
|
// m_Qualities.SetInstanceID(HOUSE_OWNER_IID, houseData->_ownerId);
|
|
// NotifyIIDStatUpdated(HOUSE_OWNER_IID, false);
|
|
// }
|
|
// else
|
|
// {
|
|
// m_Qualities.RemoveInstanceID(HOUSE_OWNER_IID);
|
|
// NotifyIIDStatUpdated(HOUSE_OWNER_IID, false);
|
|
// }
|
|
|
|
// UpdateHookedObject(NULL);
|
|
// SetHookVisibility(houseData->_hooksVisible);
|
|
|
|
// _nextInitCheck = -1.0;
|
|
// _initialized = true;
|
|
//}
|
|
|
|
CContainerWeenie::Tick();
|
|
}
|
|
|
|
void CHookWeenie::SaveEx(CWeenieSave & save)
|
|
{
|
|
//if we don't clear before saving some hooked item's position and rotation changes, not sure what is causing that.
|
|
ClearHookedObject(false);
|
|
CContainerWeenie::SaveEx(save);
|
|
|
|
m_bSaveMe = false;
|
|
|
|
UpdateHookedObject(NULL, false);
|
|
}
|
|
|
|
void CHookWeenie::LoadEx(CWeenieSave & save)
|
|
{
|
|
CContainerWeenie::LoadEx(save);
|
|
|
|
_nextInitCheck = Timer::cur_time;
|
|
}
|
|
|
|
void CHookWeenie::PreSpawnCreate()
|
|
{
|
|
CHouseData *houseData = GetHouseData();
|
|
|
|
if (!houseData)
|
|
return;
|
|
|
|
if (houseData->_ownerId)
|
|
{
|
|
//SetHookVisibility(houseData->_hooksVisible);
|
|
m_Qualities.SetInstanceID(HOUSE_OWNER_IID, houseData->_ownerId);
|
|
//NotifyIIDStatUpdated(HOUSE_OWNER_IID, false);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.RemoveInstanceID(HOUSE_OWNER_IID);
|
|
//NotifyIIDStatUpdated(HOUSE_OWNER_IID, false);
|
|
}
|
|
|
|
if (houseData->_hooksVisible)
|
|
{
|
|
m_Qualities.RemoveBool(VISIBILITY_BOOL);
|
|
}
|
|
else if (m_Items.empty())
|
|
{
|
|
m_Qualities.SetBool(VISIBILITY_BOOL, false);
|
|
}
|
|
|
|
UpdateHookedObject(NULL, false);
|
|
//SetHookVisibility(houseData->_hooksVisible);
|
|
}
|
|
|
|
int CHookWeenie::DoUseResponse(CWeenieObject *other)
|
|
{
|
|
CHouseWeenie *house = GetHouse();
|
|
if (!house)
|
|
return WERROR_NO_HOUSE;
|
|
|
|
CHouseData *houseData = house->GetHouseData();
|
|
if (!houseData)
|
|
return WERROR_NO_HOUSE;
|
|
|
|
if (houseData->_hooksVisible)
|
|
{
|
|
if (house->HasStorageAccess(other->AsPlayer()))
|
|
{
|
|
int useResponse = CContainerWeenie::DoUseResponse(other);
|
|
m_bSaveMe = true;
|
|
Save();
|
|
return useResponse;
|
|
}
|
|
else
|
|
{
|
|
other->SendText("You do not have permission to access that.", LTT_DEFAULT); //made up message.
|
|
return WERROR_ACTIVATION_NOT_ALLOWED_NO_NAME;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//if house hooks are off this means we're using the hooked item.
|
|
if (house->HasAccess(other->AsPlayer()))
|
|
{
|
|
CWeenieObject *hookedItem;
|
|
if (m_Items.empty())
|
|
return WERROR_OBJECT_GONE;
|
|
|
|
hookedItem = m_Items[0];
|
|
|
|
if (!hookedItem)
|
|
return WERROR_OBJECT_GONE;
|
|
|
|
if (hookedItem->InqIntQuality(HOOK_GROUP_INT, 0) == 4 && house->GetHouseType() != Mansion_HouseType)
|
|
{
|
|
other->SendText("That can only be activated when hooked in a mansion.", LTT_DEFAULT); //made up message.
|
|
return WERROR_OBJECT_GONE;
|
|
}
|
|
|
|
// Prevent hooked items from being usable if recently involved in PK Activity.
|
|
if (hookedItem->InqIntQuality(HOOK_GROUP_INT, 0) && other->_IsPlayer() && other->AsPlayer()->CheckPKActivity())
|
|
{
|
|
return WERROR_PORTAL_PK_ATTACKED_TOO_RECENTLY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
other->SendText("You do not have permission to access that.", LTT_DEFAULT); //made up message.
|
|
return WERROR_HOOK_NOT_PERMITED_TO_USE_HOOK;
|
|
}
|
|
}
|
|
|
|
return CWeenieObject::DoUseResponse(other);
|
|
}
|
|
|
|
void CHookWeenie::Identify(CWeenieObject *other, uint32_t overrideId)
|
|
{
|
|
CHouseData *houseData = GetHouseData();
|
|
|
|
if (!houseData || houseData->_hooksVisible)
|
|
CContainerWeenie::Identify(other, overrideId);
|
|
else
|
|
{
|
|
//if house hooks are off this means we're identifying the hooked item.
|
|
CWeenieObject *hookedItem;
|
|
if (m_Items.empty())
|
|
return;
|
|
|
|
hookedItem = m_Items[0];
|
|
|
|
if (!hookedItem)
|
|
return;
|
|
|
|
hookedItem->Identify(other, GetID());
|
|
}
|
|
}
|
|
|
|
uint32_t CHookWeenie::Container_InsertInventoryItem(uint32_t dwCell, CWeenieObject *pItem, uint32_t slot)
|
|
{
|
|
UpdateHookedObject(pItem);
|
|
|
|
return CContainerWeenie::Container_InsertInventoryItem(dwCell, pItem, slot);
|
|
}
|
|
|
|
void CHookWeenie::ReleaseContainedItemRecursive(CWeenieObject *item)
|
|
{
|
|
ClearHookedObject();
|
|
|
|
CContainerWeenie::ReleaseContainedItemRecursive(item);
|
|
}
|
|
|
|
void CHookWeenie::OnContainerClosed(CWeenieObject *requestedBy)
|
|
{
|
|
CContainerWeenie::OnContainerClosed(requestedBy);
|
|
|
|
m_bSaveMe = true;
|
|
Save();
|
|
}
|
|
|
|
void CHookWeenie::UpdateHookedObject(CWeenieObject *hookedItem, bool sendUpdate)
|
|
{
|
|
if (!hookedItem && !m_Items.empty())
|
|
hookedItem = m_Items[0];
|
|
|
|
if (!hookedItem)
|
|
return;
|
|
|
|
uint32_t value;
|
|
|
|
if (hookedItem->m_Qualities.InqDataID(SETUP_DID, value))
|
|
{
|
|
m_Qualities.SetDataID(SETUP_DID, value);
|
|
_phys_obj->part_array->SetSetupID(value, TRUE);
|
|
//NotifyDIDStatUpdated(SETUP_DID, false);
|
|
//SetPlacementFrame(Placement::Hook, FALSE);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.RemoveDataID(SETUP_DID);
|
|
//NotifyDIDStatUpdated(SETUP_DID, false);
|
|
}
|
|
|
|
if (hookedItem->m_Qualities.InqDataID(MOTION_TABLE_DID, value))
|
|
{
|
|
m_Qualities.SetDataID(MOTION_TABLE_DID, value);
|
|
//NotifyDIDStatUpdated(MOTION_TABLE_DID, false);
|
|
|
|
_phys_obj->SetMotionTableID(value);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.RemoveDataID(MOTION_TABLE_DID);
|
|
//NotifyDIDStatUpdated(MOTION_TABLE_DID, false);
|
|
}
|
|
|
|
if (hookedItem->m_Qualities.InqDataID(SOUND_TABLE_DID, value))
|
|
{
|
|
m_Qualities.SetDataID(SOUND_TABLE_DID, value);
|
|
//NotifyDIDStatUpdated(SOUND_TABLE_DID, false);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.RemoveDataID(SOUND_TABLE_DID);
|
|
//NotifyDIDStatUpdated(SOUND_TABLE_DID, false);
|
|
}
|
|
|
|
if (hookedItem->m_Qualities.InqDataID(PHYSICS_EFFECT_TABLE_DID, value))
|
|
{
|
|
m_Qualities.SetDataID(PHYSICS_EFFECT_TABLE_DID, value);
|
|
//NotifyDIDStatUpdated(PHYSICS_EFFECT_TABLE_DID, false);
|
|
|
|
set_phstable_id(value);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.RemoveDataID(PHYSICS_EFFECT_TABLE_DID);
|
|
//NotifyDIDStatUpdated(PHYSICS_EFFECT_TABLE_DID, false);
|
|
|
|
if (physics_script_table)
|
|
{
|
|
PhysicsScriptTable::Release(physics_script_table);
|
|
physics_script_table = NULL;
|
|
}
|
|
}
|
|
|
|
double floatValue;
|
|
if (hookedItem->m_Qualities.InqFloat(DEFAULT_SCALE_FLOAT, floatValue))
|
|
{
|
|
m_Qualities.SetFloat(DEFAULT_SCALE_FLOAT, floatValue);
|
|
//NotifyFloatStatUpdated(DEFAULT_SCALE_FLOAT, false);
|
|
|
|
_phys_obj->SetScaleStatic(floatValue);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.SetFloat(DEFAULT_SCALE_FLOAT, 1.0);
|
|
//NotifyFloatStatUpdated(DEFAULT_SCALE_FLOAT, false);
|
|
|
|
_phys_obj->SetScaleStatic(1.0);
|
|
}
|
|
|
|
if (hookedItem->m_Qualities.InqFloat(TRANSLUCENCY_FLOAT, floatValue))
|
|
{
|
|
m_Qualities.SetFloat(TRANSLUCENCY_FLOAT, floatValue);
|
|
//NotifyFloatStatUpdated(TRANSLUCENCY_FLOAT, false);
|
|
|
|
_phys_obj->SetTranslucencyInternal(floatValue);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.RemoveFloat(TRANSLUCENCY_FLOAT);
|
|
//NotifyFloatStatUpdated(TRANSLUCENCY_FLOAT, false);
|
|
|
|
_phys_obj->SetTranslucencyInternal(0.0);
|
|
}
|
|
|
|
set_state(PhysicsState::LIGHTING_ON_PS | PhysicsState::REPORT_COLLISIONS_PS, TRUE);
|
|
|
|
m_bObjDescOverride = true;
|
|
hookedItem->GetObjDesc(m_ObjDescOverride);
|
|
|
|
int32_t placement = hookedItem->InqIntQuality(HOOK_PLACEMENT_INT, Placement::Resting, TRUE);
|
|
if (placement != Placement::Resting)
|
|
SetPlacementFrame(placement, FALSE);
|
|
|
|
if (sendUpdate && InqBoolQuality(VISIBILITY_BOOL, true))
|
|
NotifyObjectUpdated(false);
|
|
}
|
|
|
|
void CHookWeenie::ClearHookedObject(bool sendUpdate)
|
|
{
|
|
CWeenieDefaults *defaults = g_pWeenieFactory->GetWeenieDefaults(m_Qualities.id);
|
|
|
|
uint32_t value;
|
|
|
|
if (defaults->m_Qualities.InqDataID(SETUP_DID, value))
|
|
{
|
|
m_Qualities.SetDataID(SETUP_DID, value);
|
|
//NotifyDIDStatUpdated(SETUP_DID, false);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.RemoveDataID(SETUP_DID);
|
|
//NotifyDIDStatUpdated(SETUP_DID, false);
|
|
}
|
|
|
|
if (defaults->m_Qualities.InqDataID(MOTION_TABLE_DID, value))
|
|
{
|
|
m_Qualities.SetDataID(MOTION_TABLE_DID, value);
|
|
//NotifyDIDStatUpdated(MOTION_TABLE_DID, false);
|
|
|
|
_phys_obj->SetMotionTableID(value);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.RemoveDataID(MOTION_TABLE_DID);
|
|
//NotifyDIDStatUpdated(MOTION_TABLE_DID, false);
|
|
}
|
|
|
|
if (defaults->m_Qualities.InqDataID(SOUND_TABLE_DID, value))
|
|
{
|
|
m_Qualities.SetDataID(SOUND_TABLE_DID, value);
|
|
//NotifyDIDStatUpdated(SOUND_TABLE_DID, false);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.RemoveDataID(SOUND_TABLE_DID);
|
|
//NotifyDIDStatUpdated(SOUND_TABLE_DID, false);
|
|
}
|
|
|
|
if (defaults->m_Qualities.InqDataID(PHYSICS_EFFECT_TABLE_DID, value))
|
|
{
|
|
m_Qualities.SetDataID(PHYSICS_EFFECT_TABLE_DID, value);
|
|
//NotifyDIDStatUpdated(PHYSICS_EFFECT_TABLE_DID, false);
|
|
|
|
set_phstable_id(value);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.RemoveDataID(PHYSICS_EFFECT_TABLE_DID);
|
|
//NotifyDIDStatUpdated(PHYSICS_EFFECT_TABLE_DID, false);
|
|
|
|
if (physics_script_table)
|
|
{
|
|
PhysicsScriptTable::Release(physics_script_table);
|
|
physics_script_table = NULL;
|
|
}
|
|
}
|
|
|
|
double floatValue;
|
|
if (defaults->m_Qualities.InqFloat(DEFAULT_SCALE_FLOAT, floatValue))
|
|
{
|
|
m_Qualities.SetFloat(DEFAULT_SCALE_FLOAT, floatValue);
|
|
//NotifyFloatStatUpdated(DEFAULT_SCALE_FLOAT, false);
|
|
|
|
_phys_obj->SetScaleStatic(floatValue);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.SetFloat(DEFAULT_SCALE_FLOAT, 1.0);
|
|
//NotifyFloatStatUpdated(DEFAULT_SCALE_FLOAT, false);
|
|
|
|
_phys_obj->SetScaleStatic(1.0);
|
|
}
|
|
|
|
if (defaults->m_Qualities.InqFloat(TRANSLUCENCY_FLOAT, floatValue))
|
|
{
|
|
m_Qualities.SetFloat(TRANSLUCENCY_FLOAT, floatValue);
|
|
//NotifyFloatStatUpdated(TRANSLUCENCY_FLOAT, false);
|
|
|
|
_phys_obj->SetTranslucencyInternal(floatValue);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.RemoveFloat(TRANSLUCENCY_FLOAT);
|
|
//NotifyFloatStatUpdated(TRANSLUCENCY_FLOAT, false);
|
|
|
|
_phys_obj->SetTranslucencyInternal(0.0);
|
|
}
|
|
|
|
set_state(ETHEREAL_PS | IGNORE_COLLISIONS_PS, TRUE);
|
|
|
|
m_bObjDescOverride = false;
|
|
m_ObjDescOverride.Clear();
|
|
|
|
SetPlacementFrame(Placement::Resting, FALSE);
|
|
|
|
if (sendUpdate && InqBoolQuality(VISIBILITY_BOOL, true))
|
|
NotifyObjectUpdated(false);
|
|
}
|
|
|
|
void CHookWeenie::SetHookVisibility(bool newSetting)
|
|
{
|
|
if (!m_Items.empty())
|
|
{
|
|
CWeenieObject *hookedItem = m_Items[0];
|
|
|
|
if (!hookedItem)
|
|
return;
|
|
|
|
m_Qualities.RemoveBool(VISIBILITY_BOOL); //if it's visible we remove the bool altogether.
|
|
//NotifyBoolStatUpdated(VISIBILITY_BOOL, false);
|
|
|
|
if (newSetting)
|
|
{
|
|
//revert to hook's info.
|
|
CWeenieDefaults *weenieDef = g_pWeenieFactory->GetWeenieDefaults(m_Qualities.id);
|
|
if (weenieDef)
|
|
{
|
|
if (m_Qualities._emote_table)
|
|
SafeDelete(m_Qualities._emote_table);
|
|
|
|
m_Qualities.SetString(NAME_STRING, weenieDef->m_Qualities.GetString(NAME_STRING, ""));
|
|
m_Qualities.SetInt(ITEMS_CAPACITY_INT, weenieDef->m_Qualities.GetInt(ITEMS_CAPACITY_INT, 0));
|
|
}
|
|
|
|
NotifyObjectUpdated(false);
|
|
}
|
|
else
|
|
{
|
|
//overwrite hook with hooked item's info.
|
|
if (hookedItem->m_Qualities._emote_table)
|
|
{
|
|
SafeDelete(m_Qualities._emote_table);
|
|
m_Qualities._emote_table = new CEmoteTable();
|
|
BinaryWriter w;
|
|
hookedItem->m_Qualities._emote_table->Pack(&w);
|
|
BinaryReader r(w.GetData(), w.GetSize());
|
|
m_Qualities._emote_table->UnPack(&r);
|
|
}
|
|
else
|
|
SafeDelete(m_Qualities._emote_table);
|
|
|
|
if (CWeenieObject *hookedItem = m_Items[0])
|
|
{
|
|
m_Qualities.SetString(NAME_STRING, hookedItem->GetName());
|
|
m_Qualities.SetInt(ITEMS_CAPACITY_INT, hookedItem->m_Qualities.GetInt(ITEMS_CAPACITY_INT, 0));
|
|
}
|
|
|
|
NotifyObjectUpdated(false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (newSetting)
|
|
{
|
|
m_Qualities.RemoveBool(VISIBILITY_BOOL); //if it's visible we remove the bool altogether.
|
|
//NotifyBoolStatUpdated(VISIBILITY_BOOL, false);
|
|
NotifyObjectCreated(false);
|
|
}
|
|
else
|
|
{
|
|
m_Qualities.SetBool(VISIBILITY_BOOL, false);
|
|
//NotifyBoolStatUpdated(VISIBILITY_BOOL, false);
|
|
NotifyObjectRemoved();
|
|
}
|
|
}
|
|
Save();
|
|
}
|
|
|
|
|
|
CHouseWeenie *CHookWeenie::GetHouse()
|
|
{
|
|
if (CWeenieObject *house = g_pWorld->FindObject(InqIIDQuality(HOUSE_IID, 0), true))
|
|
{
|
|
return house->AsHouse();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
CHouseData *CHookWeenie::GetHouseData()
|
|
{
|
|
if (uint32_t hid = InqDIDQuality(HOUSEID_DID, 0))
|
|
return g_pHouseManager->GetHouseData(hid);
|
|
|
|
CHouseWeenie *house = GetHouse();
|
|
if (house)
|
|
return house->GetHouseData();
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
CDeedWeenie::CDeedWeenie()
|
|
{
|
|
}
|
|
|
|
CHouseWeenie *CDeedWeenie::GetHouse()
|
|
{
|
|
if (CWeenieObject *house = g_pWorld->FindObject(InqIIDQuality(HOUSE_IID, 0), true))
|
|
{
|
|
return house->AsHouse();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
CBootSpotWeenie::CBootSpotWeenie()
|
|
{
|
|
m_bDontClear = true;
|
|
}
|
|
|
|
CHouseWeenie *CBootSpotWeenie::GetHouse()
|
|
{
|
|
if (CWeenieObject *house = g_pWorld->FindObject(InqIIDQuality(HOUSE_IID, 0), true))
|
|
{
|
|
return house->AsHouse();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
CHousePortalWeenie::CHousePortalWeenie()
|
|
{
|
|
m_bDontClear = true;
|
|
}
|
|
|
|
void CHousePortalWeenie::ApplyQualityOverrides()
|
|
{
|
|
SetRadarBlipColor(Portal_RadarBlipEnum);
|
|
}
|
|
|
|
CHouseWeenie *CHousePortalWeenie::GetHouse()
|
|
{
|
|
if (CWeenieObject *house = g_pWorld->FindObject(InqIIDQuality(HOUSE_IID, 0), true))
|
|
{
|
|
return house->AsHouse();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int CHousePortalWeenie::Use(CPlayerWeenie *other)
|
|
{
|
|
CHouseWeenie *house = GetHouse();
|
|
if (!house)
|
|
{
|
|
other->NotifyUseDone();
|
|
return WERROR_NO_HOUSE;
|
|
}
|
|
|
|
if (house->HasAccess(other->AsPlayer()))
|
|
return CPortal::Use(other);
|
|
else
|
|
{
|
|
other->SendText("You do not have permission to access that.", LTT_DEFAULT); //made up message.
|
|
other->NotifyUseDone();
|
|
return WERROR_NONE;
|
|
}
|
|
}
|
|
|
|
|
|
bool CHousePortalWeenie::GetDestination(Position &dest)
|
|
{
|
|
if (CHouseWeenie *house = GetHouse())
|
|
{
|
|
if (Position *pos = g_pPortalDataEx->GetHousePortalDest(house->GetHouseDID(), m_Position.objcell_id))
|
|
{
|
|
dest = *pos;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
CStorageWeenie::CStorageWeenie()
|
|
{
|
|
m_bDontClear = true;
|
|
}
|
|
|
|
int CStorageWeenie::DoUseResponse(CWeenieObject *other)
|
|
{
|
|
CHouseWeenie *house = GetHouse();
|
|
if (!house)
|
|
return WERROR_NO_HOUSE;
|
|
|
|
if (house->HasStorageAccess(other->AsPlayer()))
|
|
{
|
|
int storageUseResponse = CContainerWeenie::DoUseResponse(other);
|
|
return storageUseResponse;
|
|
}
|
|
else
|
|
{
|
|
other->SendText("You do not have permission to access that.", LTT_DEFAULT); //made up message.
|
|
}
|
|
|
|
return CWeenieObject::DoUseResponse(other);
|
|
}
|
|
|
|
void CStorageWeenie::OnContainerClosed(CWeenieObject *requestedBy)
|
|
{
|
|
CChestWeenie::OnContainerClosed(requestedBy);
|
|
|
|
m_bSaveMe = true;
|
|
Save();
|
|
}
|
|
|
|
CHouseWeenie *CStorageWeenie::GetHouse()
|
|
{
|
|
if (CWeenieObject *house = g_pWorld->FindObject(InqIIDQuality(HOUSE_IID, 0), true))
|
|
{
|
|
return house->AsHouse();
|
|
}
|
|
|
|
return NULL;
|
|
}
|