Skip to content
This repository has been archived by the owner on May 11, 2023. It is now read-only.

Disabled logging out while in fight when using bed #43

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -14,3 +14,4 @@ vc14/theforgottenserver.vcxproj.user
vc14/.vs/
*.pdb
*.dll
build
2 changes: 1 addition & 1 deletion CMakeLists.txt
Expand Up @@ -9,7 +9,7 @@ list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

include(cotire)

add_compile_options(-Wall -Werror -pipe -fvisibility=hidden)
add_compile_options(-Wall -pipe -fvisibility=hidden)

if (CMAKE_COMPILER_IS_GNUCXX)
add_compile_options(-fno-strict-aliasing)
Expand Down
18 changes: 0 additions & 18 deletions data/globalevents/scripts/startup.lua
Expand Up @@ -17,24 +17,6 @@ function onStartup()
result.free(resultId)
end

-- Check house auctions
local resultId = db.storeQuery("SELECT `id`, `highest_bidder`, `last_bid`, (SELECT `balance` FROM `players` WHERE `players`.`id` = `highest_bidder`) AS `balance` FROM `houses` WHERE `owner` = 0 AND `bid_end` != 0 AND `bid_end` < " .. os.time())
if resultId ~= false then
repeat
local house = House(result.getDataInt(resultId, "id"))
if house ~= nil then
local highestBidder = result.getDataInt(resultId, "highest_bidder")
local balance = result.getDataLong(resultId, "balance")
local lastBid = result.getDataInt(resultId, "last_bid")
if balance >= lastBid then
db.query("UPDATE `players` SET `balance` = " .. (balance - lastBid) .. " WHERE `id` = " .. highestBidder)
house:setOwnerGuid(highestBidder)
end
db.asyncQuery("UPDATE `houses` SET `last_bid` = 0, `bid_end` = 0, `highest_bidder` = 0, `bid` = 0 WHERE `id` = " .. house:getId())
end
until not result.next(resultId)
result.free(resultId)
end

-- Remove murders that are more than 60 days old
local resultId = db.storeQuery("SELECT * FROM `player_murders` WHERE `date` <= " .. os.time() - 60 * 24 * 60 * 60)
Expand Down
1 change: 0 additions & 1 deletion src/CMakeLists.txt
Expand Up @@ -65,7 +65,6 @@ set(tfs_SRC
${CMAKE_CURRENT_LIST_DIR}/tools.cpp
${CMAKE_CURRENT_LIST_DIR}/vocation.cpp
${CMAKE_CURRENT_LIST_DIR}/waitlist.cpp
${CMAKE_CURRENT_LIST_DIR}/weapons.cpp
${CMAKE_CURRENT_LIST_DIR}/wildcardtree.cpp
)

5 changes: 5 additions & 0 deletions src/bed.cpp
Expand Up @@ -124,6 +124,11 @@ bool BedItem::trySleep(Player* player)
return false;
}

if (player->hasCondition(CONDITION_INFIGHT)){
player->sendCancelMessage(RETURNVALUE_YOUMAYNOTLOGOUTDURINGAFIGHT);
return false;
}

if (sleeperGUID != 0) {
if (Item::items[id].transformToFree != 0 && house->getOwner() == player->getGUID()) {
wakeUp(nullptr);
Expand Down
176 changes: 110 additions & 66 deletions src/house.cpp
Expand Up @@ -23,6 +23,7 @@

#include "house.h"
#include "iologindata.h"
#include "iomapserialize.h"
#include "game.h"
#include "configmanager.h"
#include "bed.h"
Expand Down Expand Up @@ -638,93 +639,136 @@ bool Houses::loadHousesXML(const std::string& filename)

void Houses::payHouses(RentPeriod_t rentPeriod) const
{
if (rentPeriod == RENTPERIOD_NEVER) {
return;
}

time_t currentTime = time(nullptr);
for (const auto& it : houseMap) {
House* house = it.second;
if (house->getOwner() == 0) {
continue;
}

const uint32_t rent = house->getRent();
if (rent == 0 || house->getPaidUntil() > currentTime) {
continue;
}

const uint32_t ownerId = house->getOwner();
Town* town = g_game.map.towns.getTown(house->getTownId());
if (!town) {
continue;
if (!town) {
continue;
}

time_t currentTime = time(nullptr);
time_t paidUntil = currentTime;

switch (rentPeriod) {
case RENTPERIOD_DAILY:
paidUntil += 24 * 60 * 60;
break;
case RENTPERIOD_WEEKLY:
paidUntil += 24 * 60 * 60 * 7;
break;
case RENTPERIOD_MONTHLY:
paidUntil += 24 * 60 * 60 * 30;
break;
case RENTPERIOD_YEARLY:
paidUntil += 24 * 60 * 60 * 365;
break;
default:
break;
}

Player player(nullptr);
if (!IOLoginData::loadPlayerById(&player, ownerId)) {
// Player doesn't exist, reset house owner
house->setOwner(0);
continue;


//If no owner then check if auction has ended
if (house->getOwner() == 0) {

if (house->getBidEnd() < currentTime && house->getHighestBidder() != 0){
const uint32_t highestBidderId = house->getHighestBidder();
const uint64_t toPay = house->getRent() + house->getLastBid();

if (!IOLoginData::loadPlayerById(&player, highestBidderId)) {
// Player doesn't exist, reset house owner
house->setOwner(0);
continue;
}

//Try to draw money from player depot
if (g_game.removeMoney(player.getDepotLocker(house->getTownId(), true), toPay, FLAG_NOLIMIT)){
house->setOwner(highestBidderId);
house->setPaidUntil(paidUntil);
}else{
house->setOwner(0);
house->setBid(0);
house->setLastBid(0);
house->setBidEnd(0);
house->setHighestBidder(0);
house->setPayRentWarnings(0);
house->setPaidUntil(0);
IOMapSerialize::updateHouseAuctionInfo(house);
}

//Save updates to player
IOLoginData::savePlayer(&player);
}
}
//House has owner, check if pay rent is needed
else{

if (g_game.removeMoney(player.getDepotLocker(house->getTownId(), true), house->getRent(), FLAG_NOLIMIT)) {
time_t paidUntil = currentTime;
switch (rentPeriod) {
case RENTPERIOD_DAILY:
paidUntil += 24 * 60 * 60;
break;
case RENTPERIOD_WEEKLY:
paidUntil += 24 * 60 * 60 * 7;
break;
case RENTPERIOD_MONTHLY:
paidUntil += 24 * 60 * 60 * 30;
break;
case RENTPERIOD_YEARLY:
paidUntil += 24 * 60 * 60 * 365;
break;
default:
break;
if (rentPeriod == RENTPERIOD_NEVER) {
continue;
}

house->setPaidUntil(paidUntil);
} else {
if (house->getPayRentWarnings() < 7) {
int32_t daysLeft = 7 - house->getPayRentWarnings();
const uint32_t rent = house->getRent();
if (rent == 0 || house->getPaidUntil() > currentTime) {
continue;
}

Item* letter = Item::CreateItem(ITEM_LETTER_STAMPED);
std::string period;
const uint32_t ownerId = house->getOwner();

switch (rentPeriod) {
case RENTPERIOD_DAILY:
period = "daily";
break;
if (!IOLoginData::loadPlayerById(&player, ownerId)) {
// Player doesn't exist, reset house owner
house->setOwner(0);
continue;
}

case RENTPERIOD_WEEKLY:
period = "weekly";
break;
if (g_game.removeMoney(player.getDepotLocker(house->getTownId(), true), house->getRent(), FLAG_NOLIMIT)) {
house->setPaidUntil(paidUntil);
} else {
if (house->getPayRentWarnings() < 7) {
int32_t daysLeft = 7 - house->getPayRentWarnings();

case RENTPERIOD_MONTHLY:
period = "monthly";
break;
Item* letter = Item::CreateItem(ITEM_LETTER_STAMPED);
std::string period;

case RENTPERIOD_YEARLY:
period = "annual";
break;
switch (rentPeriod) {
case RENTPERIOD_DAILY:
period = "daily";
break;

default:
break;
}
case RENTPERIOD_WEEKLY:
period = "weekly";
break;

std::ostringstream ss;
ss << "Warning! \nThe " << period << " rent of " << house->getRent() << " gold for your house \"" << house->getName() << "\" is payable. Have it within " << daysLeft << " days or you will lose this house.";
letter->setText(ss.str());
g_game.internalAddItem(player.getDepotLocker(house->getTownId(), true), letter, INDEX_WHEREEVER, FLAG_NOLIMIT);
house->setPayRentWarnings(house->getPayRentWarnings() + 1);
} else {
house->setOwner(0, true, &player);
case RENTPERIOD_MONTHLY:
period = "monthly";
break;

case RENTPERIOD_YEARLY:
period = "annual";
break;

default:
break;
}

std::ostringstream ss;
ss << "Warning! \nThe " << period << " rent of " << house->getRent() << " gold for your house \"" << house->getName() << "\" is payable. Have it within " << daysLeft << " days or you will lose this house.";
letter->setText(ss.str());
g_game.internalAddItem(player.getDepotLocker(house->getTownId(), true), letter, INDEX_WHEREEVER, FLAG_NOLIMIT);
house->setPayRentWarnings(house->getPayRentWarnings() + 1);
} else {
house->setOwner(0, true, &player);
}
}

IOLoginData::savePlayer(&player);
}

IOLoginData::savePlayer(&player);

}

//Finally save changes to database
IOMapSerialize::saveHouseInfo();
}
36 changes: 36 additions & 0 deletions src/house.h
Expand Up @@ -181,6 +181,38 @@ class House
return rent;
}

void setBid(uint32_t bid){
this->bid = bid;
}

uint32_t getBid() const {
return bid;
}

void setLastBid(uint32_t bid){
this->lastBid = bid;
}

uint32_t getLastBid() const {
return lastBid;
}

void setHighestBidder(uint32_t highestBidder){
this->highestBidder = highestBidder;
}

uint32_t getHighestBidder() const {
return highestBidder;
}

void setBidEnd(uint32_t timestamp){
this->bidEnd = timestamp;
}

uint32_t getBidEnd() const {
return bidEnd;
}

void setPayRentWarnings(uint32_t warnings) {
rentWarnings = warnings;
}
Expand Down Expand Up @@ -249,6 +281,10 @@ class House
uint32_t rentWarnings = 0;
uint32_t rent = 0;
uint32_t townId = 0;
uint32_t bid = 0;
uint32_t bidEnd = 0;
uint32_t highestBidder = 0;
uint32_t lastBid = 0;

Position posEntry = {};

Expand Down
22 changes: 21 additions & 1 deletion src/iomapserialize.cpp
Expand Up @@ -22,6 +22,7 @@
#include "iomapserialize.h"
#include "game.h"
#include "bed.h"
#include "house.h"

extern Game g_game;

Expand Down Expand Up @@ -272,7 +273,7 @@ bool IOMapSerialize::loadHouseInfo()
{
Database* db = Database::getInstance();

DBResult_ptr result = db->storeQuery("SELECT `id`, `owner`, `paid`, `warnings` FROM `houses`");
DBResult_ptr result = db->storeQuery("SELECT `id`, `owner`, `paid`, `warnings`, `bid`, `bid_end`, `last_bid`, `highest_bidder` FROM `houses`");
if (!result) {
return false;
}
Expand All @@ -283,6 +284,10 @@ bool IOMapSerialize::loadHouseInfo()
house->setOwner(result->getNumber<uint32_t>("owner"), false);
house->setPaidUntil(result->getNumber<time_t>("paid"));
house->setPayRentWarnings(result->getNumber<uint32_t>("warnings"));
house->setBid(result->getNumber<uint32_t>("bid"));
house->setBidEnd(result->getNumber<uint32_t>("bid_end"));
house->setLastBid(result->getNumber<uint32_t>("last_bid"));
house->setHighestBidder(result->getNumber<uint32_t>("highest_bidder"));
}
} while (result->next());

Expand Down Expand Up @@ -370,3 +375,18 @@ bool IOMapSerialize::saveHouseInfo()

return transaction.commit();
}

bool IOMapSerialize::updateHouseAuctionInfo(House * house){
Database* db = Database::getInstance();
std::ostringstream query;
query << "SELECT `id` FROM `houses` WHERE `id` = " << house->getId();
DBResult_ptr result = db->storeQuery(query.str());

if(result){
query.str(std::string());
query << "UPDATE `houses` SET `owner` = " << house->getOwner() << ", `paid` = " << house->getPaidUntil() << ", `warnings` = " << house->getPayRentWarnings() << ", `bid` = " << house->getBid() << ", `bid_end` = " << house->getBidEnd() << ", `last_bid` = " << house->getLastBid() << ", `highest_bidder` = " << house->getHighestBidder() << " WHERE `id` = " << house->getId();
return db->executeQuery(query.str());
}else{
return false;
}
}
2 changes: 2 additions & 0 deletions src/iomapserialize.h
Expand Up @@ -22,6 +22,7 @@

#include "database.h"
#include "map.h"
#include "house.h"

class IOMapSerialize
{
Expand All @@ -30,6 +31,7 @@ class IOMapSerialize
static bool saveHouseItems();
static bool loadHouseInfo();
static bool saveHouseInfo();
static bool updateHouseAuctionInfo(House * house);

protected:
static void saveItem(PropWriteStream& stream, const Item* item);
Expand Down