Ezzz-dev / Nostalrius

Nostalrius is a 7.7 Tibia Clone Project based on The Forgotten Server 1.2 and CipSoft files.
100 stars 71 forks source link

House auction #47

Open V0RT4C opened 5 years ago

V0RT4C commented 5 years ago

Current behaviour: At startup server checks in global event startup.lua for houses on auction and if auction has ended. If auction has ended it finds the playerid with highest bid and then tries to draw money from players balance in database. Since the balance property isnt being used and balance property is most likely 0 the script will reset auction and player doesnt get the house. Keep in mind, this has nothing to do with the talkaction !buyhouse.

Desired behaviour: At startup server should check if player with highest bid has enough money in depot to pay rent + bid. Then server should decrement this amount from amount of money in players depot. If player doesnt have this amount in the depot the auction should be restarted and player does not receive the house.

Affected code: The affected lines of code can be found in data/globalevents/scripts/startup.lua on lines 20 to 37.

I've been trying to figure out how to fix this in a good way but I'm stuck.

tarantonio commented 5 years ago

Not a nostalrius server side issue, auctions should be managed on website. Btw you can add bank system to nostalrius, the only thing is that there is a value limit to deposit, withdraw, etc....

V0RT4C commented 5 years ago

Yes of course the auctioning should be managed by an external website. However this specific event "onStartup" is in fact part of the server side of Nostalrius. The behaviour that exists right now does not reflect how cip handled this in 7.7 as there was no banking system back then.

tarantonio commented 5 years ago

You have to change website too to make a bid because it looks for player balance, so I think that would be more suitable to add bank System to bank npcs.

V0RT4C commented 5 years ago

Well still, this is supposed to be a 7.7 clone so I dont think a banking system should be implemented if you want to keep it a 7.7 clone.

So the question is how to fix this in the best way? Should a sql request be performed from lua and try to count the money in the affected depot at startup and then remove the money with another sql statement or should this be performed in some other way.

The removing of rent is currently correctly being performed by the payHouses method on the House class. The server does this at startup in otserv.cpp on line 268. I figure, maybe the same can be done for when an auction has been won by somehow implementing a new method for this. But then we need to check who is highest bidder for house and when auction ends. These methods do not currently exist in the House class.

tarantonio commented 5 years ago

Nice workaround, you can replace that: (SELECTbalanceFROMplayersWHEREplayers.id=highest_bidder) ASbalanceFROMhousesWHEREowner= 0 ANDbid_end!= 0 ANDbid_end< " .. os.time() to a function where you check for money on depot and replace that: db.query("UPDATEplayersSETbalance= " .. (balance - lastBid) .. " WHEREid= " .. highestBidder) to a function deleting the amount needed. Not an easy work tough.

tarantonio commented 5 years ago

You need to change website too to look for depot instead balance.

V0RT4C commented 5 years ago

Yes I dont know how to implement this with sql because Im not sure exactly how the pid and sid work in the player_depotitems table, they dont seem logic to me. If I put items in the depot locker in thais it will get pid 101, however the pid for other containers in the same depot will differ and not in a logical way that is easy to understand. How would I query to only get the items in for example Thais depot? If I know how to do that then I can solve it easily.

I dont understand why I would need to change that on website though? The frontend doesnt need that information. Server will check at startup if enough money exists in depot, if not enough money the auction will simply be restarted by setting the bid, bid_end, highest_bid, last_bid, owner and highest_bidder to 0.

tarantonio commented 5 years ago

You have to look on RME for that, but I'm not sure atm.

How do you place a bid? Look at ZnoteAAC for example: $bid_char = &$_POST['char']; $bid_amount = &$_POST['amount']; if ($bid_amount && $bid_char) { $bid_char = (int)$bid_char; $bid_amount = (int)$bid_amount; $player = mysql_select_single("SELECTid,account_id,name,level,balanceFROMplayersWHEREid='$bid_char' LIMIT 1;");

V0RT4C commented 5 years ago

Im building a frontend from scratch. Im not using ZnoteAAC or any other prebuilt scripts. Everything will be handled through http requests via javascript from the frontend to a backend server that communicates with the database. I've got all of the bidding and every logic working with that. However the gameserver needs to check at startup for auctions that have ended and update the owners in that case and draw money from the depot in the affected city. I dont know how to do this in a good way with SQL as I dont know how to query for one specific city depot. I could easily implement a banking system but then it would not be an authentic 7.7 experience anymore.

tarantonio commented 5 years ago

I really like your approach but this issue fix cannot be applied to all, because almost all the people are using premade website frontends like Znote or gesior and they need to check for balance. Maybe a support request in otland it's more suitable.

V0RT4C commented 5 years ago

Yes maybe you are right. I think I finally understand how the table works now so I think I can implement this. So just to explain how the player_depotitems table works (according to my investigation):

Every depot that has items will get a new row in the table. Rows with itemtype = 3497 is the depotlocker Looking at that row we should focus on the sid and pid. The pid tells us the town_id of the depot and the sid tells us which pid all items that are direct children of this container has. For every container there will be a new sid telling us which pid the items in that container has and so on.

tarantonio commented 5 years ago

Despite your solution could not be suitable for all nostalrius users, I would like to see it and if you want to share it, it will be great!

tarantonio commented 5 years ago

In startup.lua there is this code:

if balance >= lastBid then db.query("UPDATEplayersSETbalance= " .. (balance - lastBid) .. " WHEREid= " .. highestBidder) house:setOwnerGuid(highestBidder) end

You only have to change that to a function to remove the required money from depot. In Medivia, if you don't have the money required it bans your character to avoid people abuse the system.

Something like:

Check depot money Depot money => lastbid? then remove money else ban

2019-05-14 10_18_15-E0iQ80W png (661×264)

V0RT4C commented 5 years ago

Thanks, I actually solved it in the cpp code, so I've got it all working now. Let me explain how: I changed in IOMapSerialize::loadHouseInfo to also get last_bid, highest_bidder and bid_end from the database. Then i created getters and setters for this in the House class. Then I just extended the logic in the Houses::payHouses method to also check for auctions that have ended and if winning player has money in the affected depot. If player has money I just remove money from his depot and set him as owner to house. Else I just reset auction.

This is how they did it in Tibia during 7.72, I dont know what they do today cause I dont play anymore :) However ofc I could ban them if not having money, I will think about that :)

tarantonio commented 5 years ago

Thanks, I actually solved it in the cpp code, so I've got it all working now. Let me explain how: I changed in IOMapSerialize::loadHouseInfo to also get last_bid, highest_bidder and bid_end from the database. Then i created getters and setters for this in the House class. Then I just extended the logic in the Houses::payHouses method to also check for auctions that have ended and if winning player has money in the affected depot. If player has money I just remove money from his depot and set him as owner to house. Else I just reset auction.

This is how they did it in Tibia during 7.72, I dont know what they do today cause I dont play anymore :) However ofc I could ban them if not having money, I will think about that :)

Well, now can you share the code to test on my server?

V0RT4C commented 5 years ago

Sure, see my latest commit on my fork of this repo. https://github.com/V0RT4C/Nostalrius/commit/a63f33b345cefcd1eabbbd4781ce2c01440c19e8

tarantonio commented 5 years ago

Working perfectly! For ZnoteAAC users:

renanluis90 commented 5 years ago

Working perfectly! For ZnoteAAC users:

  • You have to disable the balance check to bid on house.php

how disable? can u tell me? exactly? idk work with Znote system

tarantonio commented 5 years ago

Working perfectly! For ZnoteAAC users:

  • You have to disable the balance check to bid on house.php

how disable? can u tell me? exactly? idk work with Znote system

You have to look in the code where it checks for “balance” and comment or change that lines. I let the players bid without restrictions. It would be nice to have any system to prevent abuse like a ban when you bid and no money on your depot on startup checks for example.