In-memory inventory

Runes of Magic/Radiant Arcana (http://www.runesofmagic.com)
Message
Author
User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: In-memory inventory

#21 Post by rock5 » Wed Jul 14, 2010 1:22 am

VoidMain wrote:The functions that use BagID are mostly client functions, if anyone wants to use those functios can still use GetBagItemInfo to get the bag id and problema solved
True, but if people have a lot of scripts that use the bagid from the rombot inventory, then those scripts will stop working. Then we have a backward compatibility issue. Is it really that hard to find?
VoidMain wrote:
Rock5 wrote:You're right, don't need stats. You probably still need the color of the card though (for autosell filter).
Again, the autosell is handled by IGF, and we dont have any problems getting that info in game...
That's not really true. igf is needed for dura and stat checks. Autosell expects .color to already be there. Color is taken from the itemlink which is collected with most of the other info on line 81 of item.lua;

Code: Select all

	local itemLink, bagId, icon, name, itemCount = RoMScript("GetBagItemLink(GetBagItemInfo("..self.SlotNumber..")),GetBagItemInfo("..self.SlotNumber..")");
Your ultimate goal is to make that line obsolete. If it still needs to run to get the color of cards then you've accomplished nothing. Unless we put a condition saying 'if its a card, get color using this command'. That's starting to get messy though. Or maybe we could get card colors another way.

Again, ultimately you want to be able to provide the same information. I don't think Administrator would want to implement a faster inventory update if it can't provide all the information the current version provides. Have you been in contact with Administrator? What does he think?
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

User avatar
Administrator
Site Admin
Posts: 5307
Joined: Sat Jan 05, 2008 4:21 pm

Re: In-memory inventory

#22 Post by Administrator » Wed Jul 14, 2010 2:31 am

Are the cards really that big of a deal? Last I knew, the cards did absolutely nothing other than give you the satisfaction of collecting them. I don't know why anyone would bother. Unless the cards actually do something now, I'd say we just let them get auto-sold unless the user specifically asks to keep cards.

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: In-memory inventory

#23 Post by rock5 » Wed Jul 14, 2010 4:58 am

Administrator wrote:Are the cards really that big of a deal? Last I knew, the cards did absolutely nothing other than give you the satisfaction of collecting them. I don't know why anyone would bother. Unless the cards actually do something now, I'd say we just let them get auto-sold unless the user specifically asks to keep cards.
The cards give bonus stats now.

As it is now, if you specify that you don't want to sell blue items, cards don't get sold. So you can sell them at Auction. You don't want cards to be autosold.
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

VoidMain
Posts: 187
Joined: Wed Apr 21, 2010 12:21 pm

Re: In-memory inventory

#24 Post by VoidMain » Wed Jul 14, 2010 6:26 am

rock5 wrote:
VoidMain wrote:The functions that use BagID are mostly client functions, if anyone wants to use those functios can still use GetBagItemInfo to get the bag id and problema solved
True, but if people have a lot of scripts that use the bagid from the rombot inventory, then those scripts will stop working. Then we have a backward compatibility issue. Is it really that hard to find?
VoidMain wrote:
Rock5 wrote:You're right, don't need stats. You probably still need the color of the card though (for autosell filter).
Again, the autosell is handled by IGF, and we dont have any problems getting that info in game...
That's not really true. igf is needed for dura and stat checks. Autosell expects .color to already be there. Color is taken from the itemlink which is collected with most of the other info on line 81 of item.lua;

Code: Select all

	local itemLink, bagId, icon, name, itemCount = RoMScript("GetBagItemLink(GetBagItemInfo("..self.SlotNumber..")),GetBagItemInfo("..self.SlotNumber..")");
Your ultimate goal is to make that line obsolete. If it still needs to run to get the color of cards then you've accomplished nothing. Unless we put a condition saying 'if its a card, get color using this command'. That's starting to get messy though. Or maybe we could get card colors another way.
Well, color is not a problem, color is not stored because the game doesn't need it, it have quality (and i found it), color can be infered from that, and if we only use color to check for quality, is not better to have quality instead? I know, i know, backwards compatibility... Well i can easily get the color from the quality, so color will be there.
BagId... dont see it in inventory, is not there, i'm sure there has to be somewhere but is not on inventory struct, and you can easily see that because when a slot is empty it is, well, empty...
I don't really think anyone will sell cards based on quality, the bot can hardly get a boss card by itself...

User avatar
Administrator
Site Admin
Posts: 5307
Joined: Sat Jan 05, 2008 4:21 pm

Re: In-memory inventory

#25 Post by Administrator » Wed Jul 14, 2010 12:21 pm

Quality should be fine. For compatibility reasons, we can manage to make something to convert from color to quality. Shouldn't be too hard.

VoidMain
Posts: 187
Joined: Wed Apr 21, 2010 12:21 pm

Re: In-memory inventory

#26 Post by VoidMain » Wed Jul 14, 2010 8:49 pm

Stupid me!!! How i didn't think of it before!!! BagId is so easy, thats why is not anywhere, BagId is memory inventory order!!! Tested, need more testing to be aboslutely sure but for now i can say 99.99% sure that it is, it works in my pc, my brothers one and on another acount to, so it has to be that, so simple... its inventory in memory order, think of it as "1" based index, so its 60 + inventory position, its so easy and mades so much sense...
Ok, now i have a really nice function, overwriting inventory (via 2nd include after) and testing, i'll post results very soon ^^

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: In-memory inventory

#27 Post by rock5 » Wed Jul 14, 2010 11:00 pm

VoidMain wrote:Stupid me!!! How i didn't think of it before!!! BagId is so easy, thats why is not anywhere, BagId is memory inventory order!!! Tested, need more testing to be aboslutely sure but for now i can say 99.99% sure that it is, it works in my pc, my brothers one and on another acount to, so it has to be that, so simple... its inventory in memory order, think of it as "1" based index, so its 60 + inventory position, its so easy and mades so much sense...
Ok, now i have a really nice function, overwriting inventory (via 2nd include after) and testing, i'll post results very soon ^^
You do realize there are 2 indexes that ingame functions use? One is a Bag Index used with functions like GetBagItemInfo which is in order. I think this this is the 1 you can infer using the method you mentioned above. The other is an Inventory Index used with functions like UseBagItem, GetBagItemLink, and PickupBagItem which is not in order and may change from session to session.

Ingame you would find the Inventory index by using GetBagItemInfo. So for example if you wanted to use the first bag item you would type;

Code: Select all

UseBagItem(GetBagItemInfo(1))
You can't assume it will have an Inventory index of 61 even though most of the time it will.

Hm... Maybe you haven't been able to find the index because you are searching for numbers 61-120 etc but like you said they are in inventory index order? If so then you should be searching for the Bag Index which are numbers 1-60.
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

VoidMain
Posts: 187
Joined: Wed Apr 21, 2010 12:21 pm

Re: In-memory inventory

#28 Post by VoidMain » Thu Jul 15, 2010 1:05 am

rock5 wrote:
VoidMain wrote:Stupid me!!! How i didn't think of it before!!! BagId is so easy, thats why is not anywhere, BagId is memory inventory order!!! Tested, need more testing to be aboslutely sure but for now i can say 99.99% sure that it is, it works in my pc, my brothers one and on another acount to, so it has to be that, so simple... its inventory in memory order, think of it as "1" based index, so its 60 + inventory position, its so easy and mades so much sense...
Ok, now i have a really nice function, overwriting inventory (via 2nd include after) and testing, i'll post results very soon ^^
You do realize there are 2 indexes that ingame functions use? One is a Bag Index used with functions like GetBagItemInfo which is in order. I think this this is the 1 you can infer using the method you mentioned above. The other is an Inventory Index used with functions like UseBagItem, GetBagItemLink, and PickupBagItem which is not in order and may change from session to session.
No, here your asumption is wrong, the index (61+) is exactly the index returned by GetItemInfo(numberOfSlot) in fact, thats the only reason for that function to be...
rock5 wrote: Ingame you would find the Inventory index by using GetBagItemInfo. So for example if you wanted to use the first bag item you would type;

Code: Select all

UseBagItem(GetBagItemInfo(1))
You can't assume it will have an Inventory index of 61 even though most of the time it will.

Hm... Maybe you haven't been able to find the index because you are searching for numbers 61-120 etc but like you said they are in inventory index order? If so then you should be searching for the Bag Index which are numbers 1-60.
No, and no again, i was searching fo BagIg wich is, in fact, the number returned by that tricky function GetItemInfo, and i got it, its working ^^ GetbagItemInfo just maps a visual representation of the inventory to the real id the game is using, it is 61+ because 1-50 indexes are used by item shop backpack and 51 60 by arcane transmutor, dont worry, the BagId is correct, probed, I dont have, tho the mapping to bagslot but that is not used anywhere in bot i can see, and therefore is not a problem because if someone is using a custom script based on GetItemInfo the yhave no problems at all.

Now i have a little problem parsing the quality, quality and tier are stored in one single byte, both, the first digit is quality and the second one is tier, and i don't know how to shift bits here... So for now on i think i'll use a string but that is far from optimus...
Any thougths?

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: In-memory inventory

#29 Post by rock5 » Thu Jul 15, 2010 6:11 am

VoidMain wrote:No, here your asumption is wrong, the index (61+) is exactly the index returned by GetItemInfo(numberOfSlot) in fact, thats the only reason for that function to be...
It returns more information than just the Inventory Index but you are probably correct. That may be the only function that needs the Bag Index. I think there has been a bit of confusion with all the different names for the indexes. I'm even confusing myself sometimes. :)
VoidMain wrote:
rock5 wrote:Hm... Maybe you haven't been able to find the index because you are searching for numbers 61-120 etc but like you said they are in inventory index order? If so then you should be searching for the Bag Index which are numbers 1-60.
No, and no again, i was searching fo BagIg wich is, in fact, the number returned by that tricky function GetItemInfo
I think you misunderstood me here. Let me try to explain it again.

You were searching for the numbers 61-120 which is what is stored in item.BagId (what the romwiki calls Inventory Index). You didn't find those numbers because the list is in that order so the Inventory Index can be inferred by the order, which is what I understand you have done. If so then the item.SlotNumber (what the romwiki calls the Bag Index) ie values 1-60, should be stored somewhere in the item data. Have you searched for matching 1-60 numbers in the item table? If you can find them then we will also have the item.SlotNumbers.
VoidMain wrote:I dont have, tho the mapping to bagslot but that is not used anywhere in bot i can see.
What you are saying is we don't need item.SlotNumber but the slotnumber (ie. Bag Index) is used in a few places in the rombot eg with the profile settings 'INV_AUTOSELL_FROMSLOT' and 'INV_AUTOSELL_TOSLOT' which I use. Those options won't work without the slotnumbers.
VoidMain wrote:Now i have a little problem parsing the quality, quality and tier are stored in one single byte, both, the first digit is quality and the second one is tier, and i don't know how to shift bits here... So for now on i think i'll use a string but that is far from optimus...
Any thougths?
Simple to do it mathematically. If you have 75 decimal and you want the first digit you divide by 10 then truncate the fraction. Same with hex. Divide by 16 then truncate. eg. math.floor(0xD4/16) should return 0xD ie 13.

Or maybe you could use this instead to get both values;

Code: Select all

quality, tier = math.modf (ByTE/16); tier =tier *16
ps. You look like you answered in a rush. If so please, relax, take your time. There's no rush.
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

User avatar
Administrator
Site Admin
Posts: 5307
Joined: Sat Jan 05, 2008 4:21 pm

Re: In-memory inventory

#30 Post by Administrator » Thu Jul 15, 2010 7:30 am

I'm pretty sure Lua will convert the hex to decimal before applying any math to it, so it should still be dividing or multiplying by 10.

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: In-memory inventory

#31 Post by rock5 » Thu Jul 15, 2010 8:27 am

Administrator wrote:I'm pretty sure Lua will convert the hex to decimal before applying any math to it, so it should still be dividing or multiplying by 10.
To get the first digit of a 2 digit hex number you have to divide by 16 or 0x10.
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

VoidMain
Posts: 187
Joined: Wed Apr 21, 2010 12:21 pm

Re: In-memory inventory

#32 Post by VoidMain » Thu Jul 15, 2010 8:32 am

rock5 wrote:I think you misunderstood me here. Let me try to explain it again.

You were searching for the numbers 61-120 which is what is stored in item.BagId (what the romwiki calls Inventory Index). You didn't find those numbers because the list is in that order so the Inventory Index can be inferred by the order, which is what I understand you have done. If so then the item.SlotNumber (what the romwiki calls the Bag Index) ie values 1-60, should be stored somewhere in the item data. Have you searched for matching 1-60 numbers in the item table? If you can find them then we will also have the item.SlotNumbers.
You're absolutely right, misundestood your sentence, and i was in a rush because i was leaving and wanted to post an answer ^^

No, slot numbers are not that easy to find, i checked for numbers starting at 1 to 240 and have absolutely no luck finding any type of "map" or table, nothing points to an address in inventory nor maps numbers that way, not that i can see and i have seen alot of this game memory lately... I'm not saying it doesn't exist but i belive its that function what does the trick (GetItemInfo) well, no particulary that one, but the function that one uses to map indexes i can, maybe, debug the assembler to check it but that has to be another time, i think with what we have now we can work pretty well, i'll say much better than old inventory... we even have more data, as cost an dura, no eed to parse tooltip to get dura anymore, we can get stats from inv data too (not done yet but data is there), we have the cost (how much it cost to buy from an NPC) and worth (how much an NPC will pay for it (is just 10% of cost), we can check if item is in use, we get itemcount, no need to manually decrease consumables anymore...
If we work a bit on it i think we can get this done in no time...

[quote="rock5W]What you are saying is we don't need item.SlotNumber but the slotnumber (ie. Bag Index) is used in a few places in the rombot eg with the profile settings 'INV_AUTOSELL_FROMSLOT' and 'INV_AUTOSELL_TOSLOT' which I use. Those options won't work without the slotnumbers.[/quote]
Yes, slotNumber are used for autosell but that is almost all done by igf, only checks are done in the inventory and i think we can safelly move it completely to igf and we have no problems...
rock5 wrote:Or maybe you could use this instead to get both values;

Code: Select all

quality, tier = math.modf (ByTE/16); tier =tier *16
Nice, i'll try that, my string method works but is far from optimal :P
Thing is i'm so used to shift bits that i forgot math exists just for that, solving problems ^^

Ok then i have almost everything working i'm even mapping quality to color to keep backwards compatibility...

VoidMain
Posts: 187
Joined: Wed Apr 21, 2010 12:21 pm

Re: In-memory inventory

#33 Post by VoidMain » Thu Jul 15, 2010 9:23 am

Ok, here is something to test, i need help testing this to check that i'm not missing table parts...
Attachments
addresses.lua
And this is modified addresses...
(1.65 KiB) Downloaded 130 times
TestTables.lua
This one goes to rom root.
(301 Bytes) Downloaded 133 times
MemoryTable.lua
This one goes to classes.
(8.47 KiB) Downloaded 128 times
MemoryItem.lua
This one goes to classes.
(11.15 KiB) Downloaded 142 times
MemoryInventory.lua
This one goes to classes.
(1.07 KiB) Downloaded 130 times

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: In-memory inventory

#34 Post by rock5 » Thu Jul 15, 2010 11:19 am

VoidMain wrote:Ok, here is something to test, i need help testing this to check that i'm not missing table parts...
Sorry but what do I do with these files?
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

VoidMain
Posts: 187
Joined: Wed Apr 21, 2010 12:21 pm

Re: In-memory inventory

#35 Post by VoidMain » Thu Jul 15, 2010 11:44 am

rock5 wrote:
VoidMain wrote:Ok, here is something to test, i need help testing this to check that i'm not missing table parts...
Sorry but what do I do with these files?
Put the "Memory..." in classes folder, replace your addresses.lua, copy TestTables.lua to rombot root folder (micromacro/scripts/rom) and execute rom/TestTables.lua from micromacro prompt, it will output your inventory content and debug info about tables, for now i mainly need testing to check if it misses some ids ranges (you will notice the error message if it can't find something on your inventory)
I hope this info is enough, and sorry for not posting it before ^^

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: In-memory inventory

#36 Post by rock5 » Thu Jul 15, 2010 2:12 pm

VoidMain wrote:Put the "Memory..." in classes folder, replace your addresses.lua, copy TestTables.lua to rombot root folder (micromacro/scripts/rom) and execute rom/TestTables.lua from micromacro prompt, it will output your inventory content and debug info about tables, for now i mainly need testing to check if it misses some ids ranges (you will notice the error message if it can't find something on your inventory)
I hope this info is enough, and sorry for not posting it before ^^
Ok. First I had to change the 3 dots to 2 in the following 2 lines of 'MemoryTable.lua' cos of an error;

Code: Select all

include(".../addresses.lua");
include(".../functions.lua");
Tested with my 2 main characters. Didn't see any errors.

Displayed some item data. The only values that were wrong or missing were;
- SlotNumber
- Icon
- RequiredLvl
- BoundStatus
I realize that some of the values you are not supporting but I suspect 'RequiredLvl' and 'BoundStatus' are supposed to work but they both have the same value as 'Quality' and have the same address offset. A typo I suspect?
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: In-memory inventory

#37 Post by rock5 » Thu Jul 15, 2010 4:12 pm

I just thought of something. It looks like Bag Index to Inventory Index (SlotNumber to BagId) mapping doesn't change in a session. Maybe we could collect the SlotNumber and BagId when first starting the bot and just remembering them? You know, something like;

Code: Select all

for i = 1,60 do
    _bagid = RoMScript("GetBagItemInfo("..i..")")
    inventory.BagSlot[i].BagId = _bagid
end
That should work. And the values shouldn't change until you change character.
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

Starrider
Posts: 164
Joined: Sat May 01, 2010 7:04 am
Location: Germany

Re: In-memory inventory

#38 Post by Starrider » Thu Jul 15, 2010 4:46 pm

I have no idea about what you are coding, but I see many passion and I am ure you make a great work!

VoidMain
Posts: 187
Joined: Wed Apr 21, 2010 12:21 pm

Re: In-memory inventory

#39 Post by VoidMain » Thu Jul 15, 2010 5:03 pm

rock5 wrote:I just thought of something. It looks like Bag Index to Inventory Index (SlotNumber to BagId) mapping doesn't change in a session. Maybe we could collect the SlotNumber and BagId when first starting the bot and just remembering them? You know, something like;

Code: Select all

for i = 1,60 do
    _bagid = RoMScript("GetBagItemInfo("..i..")")
    inventory.BagSlot[i].BagId = _bagid
end
That should work. And the values shouldn't change until you change character.
Unfortunately, no, if you move around some items and press sort, BagId changes...
rock5 wrote:Displayed some item data. The only values that were wrong or missing were;
- SlotNumber
- Icon
- RequiredLvl
- BoundStatus
I realize that some of the values you are not supporting but I suspect 'RequiredLvl' and 'BoundStatus' are supposed to work but they both have the same value as 'Quality' and have the same address offset. A typo I suspect?
You we're right, type there fixing those now.
As for SlotNumber, well, is not there, at least not yet, can you check with me if there is any other function than the autosell that uses it? If its just that one we can move it fully to igf...

Icon i'm not getting it because i didn't see it used anywhere but maybe i missed something but, honestly, we have no use for icon... I mean, as users, only uses for icon might be for an addon but outside the game has little to no meaning at all...

About speed: What you noticed, how it behaves? In here it takes abot 26ms when printing the data and then 2-3ms to update...

User avatar
rock5
Posts: 12173
Joined: Tue Jan 05, 2010 3:30 am
Location: Australia

Re: In-memory inventory

#40 Post by rock5 » Thu Jul 15, 2010 6:42 pm

VoidMain wrote:Unfortunately, no, if you move around some items and press sort, BagId changes...
I wasn't aware of that. I have never ever used sort (and probably never will)^^.
VoidMain wrote:As for SlotNumber, well, is not there, at least not yet, can you check with me if there is any other function than the autosell that uses it? If its just that one we can move it fully to igf...
The only places I see SlotNumber used will become obsolete. Looks like AutoSell is the only thing that actually needs it.
VoidMain wrote:Icon i'm not getting it because i didn't see it used anywhere but maybe i missed something but, honestly, we have no use for icon... I mean, as users, only uses for icon might be for an addon but outside the game has little to no meaning at all...
I think icon was just added because it was a value returned by GetBagItemInfo. I'm sure it has never and will never be used in rombot.
VoidMain wrote:About speed: What you noticed, how it behaves? In here it takes abot 26ms when printing the data and then 2-3ms to update...
I'm not sure what you mean. The yellow data takes about 6s. The white data takes a fraction of a second. Or do you mean this?

Code: Select all

Inventory update took: 167
Inventory update took: 9
  • Please consider making a small donation to me to support my continued contributions to the bot and this forum. Thank you. Donate
  • I check all posts before reading PMs. So if you want a fast reply, don't PM me but post a topic instead. PM me for private or personal topics only.
  • How to: copy and paste in micromacro
    ________________________
    Quote:
    • “They say hard work never hurt anybody, but I figure, why take the chance.”
          • Ronald Reagan

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 22 guests