Jessecar96 / SteamBot

Automated bot software for interacting with Steam Trade
http://scrap.tf
MIT License
1.33k stars 910 forks source link

Help with crafting #289

Closed michaeldquach closed 11 years ago

michaeldquach commented 11 years ago

I'm rather new to programming, but I've got some of the basics down for SteamBot. I can set up a bot so that it trades and everything, but I'm unable to make crafting refined metal work. I know that the crafting code was released recently, but I'm unsure of how to use it in my UserHandler script. Would anyone be able to give me pointers?

waylaidwanderer commented 11 years ago

In your UserHandler, you'll want to first use Bot.SetGamePlaying(440); to launch TF2. After that, you need to construct an array of itemIDs (if you don't know how, please Google it). Let's pretend you've named it craftItems. Then you can call the crafting code via Crafting.CraftItems(Bot, craftItems);. Once you're done, quit TF2 via Bot.SetGamePlaying(0);.

Note that I typed this out from looking at the code, so it's not guaranteed to work.

Edit: I just noticed in Bot.cs that SetGamePlaying is not public and thus inaccessible from outside the class; you'd need to change it from void SetGamePlaying(int id) to public void SetGamePlaying(int id) in Bot.cs.

NarryG commented 11 years ago

I've been messing around with this for hours and even if I force the IDs it doesn't actually craft. Do the items have to be in a backpack slot or do invalid slots count?

waylaidwanderer commented 11 years ago

The crafting code I used (before geel9 decided to push his) was similar to the current one, and it doesn't matter.

Here's what I wrote for smelting down 1 ref, untested:

ulong refID = 0;
foreach (var item in Trade.MyInventory.Items)
{
    if (item.Defindex == 5002)
        refID = item.Id;
}
if (refID != 0)
{
    ulong[] toCraft = new ulong[1];
    toCraft[0] = refID;
    Bot.SetGamePlaying(440);
    Crafting.CraftItems(Bot, toCraft);
    // Update bot's inventory
    Bot.GetInventory();
    Trade.MyInventory = Bot.MyInventory;
}

Let me know if it works, but I'll be testing it soon as well.

NarryG commented 11 years ago

Your code has a ton of conflicting static and non-statics.

waylaidwanderer commented 11 years ago

SetGamePlaying needs to be changed to a public function in Bot.cs if you haven't done so. It compiles fine on my end though.

NarryG commented 11 years ago

Geel's code is sending the GC server a message, but I'm not sure if it's correct

I did throw a print line in there and got this

SteamKit2.GC.ClientGCMsg`1[SteamBot.MsgCraft]

I feel like the "'1" shouldn't be in there but I can't figure out what is causing it

NarryG commented 11 years ago

What namespaces are you using? I may have missed one.

waylaidwanderer commented 11 years ago

Oh and I forgot to mention that the code I wrote up there only works in trade. You can modify it to work outside of trade if you use foreach (var item in Bot.MyInventory.Items) and remove the line Trade.MyInventory = Bot.MyInventory;.

Can you paste a screenshot of your errors? I haven't changed any namespaces.

NarryG commented 11 years ago

Which cs file should it be inside of?

waylaidwanderer commented 11 years ago

Your SimpleUserHandler or whatever userhandler you're currently working with.

NarryG commented 11 years ago

Got it to compile but it throws errors on run.

 System.NullReferenceException: Object reference not set to an instance of an object
  at SteamBot.KeyUserHandler.craftref () [0x00000] in <filename unknown>:0
  at SteamBot.KeyUserHandler.OnMessage (System.String message, EChatEntryType type) [0x00000] in <filename unknown>:0
  at SteamBot.Bot.<HandleSteamMessage>b__8 (SteamKit2.FriendMsgCallback callback) [0x00000] in <filename unknown>:0
  at SteamKit2.CallbackMsg.Handle[FriendMsgCallback] (System.Action`1 handler) [0x00000] in <filename unknown>:0
  at SteamBot.Bot.HandleSteamMessage (SteamKit2.CallbackMsg msg) [0x00000] in <filename unknown>:0
  at SteamBot.Bot.BackgroundWorkerOnDoWork (System.Object sender, System.ComponentModel.DoWorkEventArgs doWorkEventArgs) [0x00000] in <filename unknown>:0
  at System.ComponentModel.BackgroundWorker.OnDoWork (System.ComponentModel.DoWorkEventArgs e) [0x00000] in <filename unknown>:0
  at System.ComponentModel.BackgroundWorker.ProcessWorker (System.Object argument, System.ComponentModel.AsyncOperation async, System.Threading.SendOrPostCallback callback) [0x00000] in <filename unknown>:0
waylaidwanderer commented 11 years ago

Can you show me your relevant code?

NarryG commented 11 years ago

I just pasted your code into KeyUserHandler and fixed the public thing, ran it and tested it through a simple

     else if (message == ".craftref" )
                {
                    craftref();
                }
waylaidwanderer commented 11 years ago

Make sure you call Bot.GetInventory(); first before foreach (var item in Bot.MyInventory.Items)

NarryG commented 11 years ago

It works!

waylaidwanderer commented 11 years ago

Glad we resolved the issue :)

NarryG commented 11 years ago

It seems to only allow me to run it once and then I have to reboot the bot.

waylaidwanderer commented 11 years ago

Any errors?

NarryG commented 11 years ago

Nope. If you open and close a trade it allows you to do it again though.

waylaidwanderer commented 11 years ago

What are you trying to do?

cwhelchel commented 11 years ago

@danne2 Why do this in trade? Why not do it on a regular chat message?

NarryG commented 11 years ago

I'm not doing it with trade. I changed it to work with normal chat messages.

On Tue, May 21, 2013 at 8:33 AM, Cainan Whelchel notifications@github.comwrote:

@danne2 https://github.com/danne2 Why do this in trade? Why not do it on a regular chat message?

— Reply to this email directly or view it on GitHubhttps://github.com/Jessecar96/SteamBot/issues/289#issuecomment-18205651 .

NarryG commented 11 years ago

What I meant was I set it up to use a chat message. I send it .craftref and it works. I send it again and it doesn't work the second time. If I initiate and close a trade it then allows me to do .craftref in chat one more time before it stops working.

geel9 commented 11 years ago

Probably because the inventory is out of date until you open the trade.

NarryG commented 11 years ago

Having an issue. I updated it so the array has 3 values (scrap metal) so it'll can craft up, but when I do anything with more than 1 value it just doesn't work.

The code public void craftrec() { ulong scrapID = 0; Bot.GetInventory(); foreach (var item in Bot.MyInventory.Items) { if (item.Defindex == 5000) scrapID = item.Id; } if (scrapID != 0) { ulong[] toCraft = new ulong[] {5000, 5000, 5000}; Bot.SetGamePlaying(440); Crafting.CraftItems(Bot, toCraft); // Update bot's inventory Bot.GetInventory(); foreach (var item in Bot.MyInventory.Items) ; // Console.WriteLine(scrapID ); // Console.WriteLine(toCraft); Array.ForEach( toCraft , x => Console.WriteLine(x) ); scrapID = 0; } }

Any idea what I did wrong with this?

waylaidwanderer commented 11 years ago

The array "toCraft" must contain the item IDs of the items you want you craft. You've initialized it with the defindexes, and furthermore you aren't storing any values in it.

danne2 notifications@github.com wrote:

Having an issue. I updated it so the array has 3 values (scrap metal) so it'll can craft up, but when I do anything with more than 1 value it just doesn't work.

The code public void craftrec() { ulong scrapID = 0; Bot.GetInventory(); foreach (var item in Bot.MyInventory.Items) { if (item.Defindex == 5000) scrapID = item.Id; } if (scrapID != 0) { ulong[] toCraft = new ulong[] {5000, 5000, 5000}; Bot.SetGamePlaying(440); Crafting.CraftItems(Bot, toCraft); // Update bot's inventory Bot.GetInventory(); foreach (var item in Bot.MyInventory.Items) ; // Console.WriteLine(scrapID ); // Console.WriteLine(toCraft); Array.ForEach( toCraft , x => Console.WriteLine(x) ); scrapID = 0; } }

Any idea what I did wrong with this?


Reply to this email directly or view it on GitHub: https://github.com/Jessecar96/SteamBot/issues/289#issuecomment-18251242

NarryG commented 11 years ago

Sorry about that mess. Gmail response killed the formatting. Here's a repost

Whoopsie, still fairly new to coding. I see what you're saying. I managed to get it so it pulls the item IDs, but it's pulling the same ID for all 3 values. How would I go about making it choose different items for each id?

I noticed this public List GetItemsByDefindex (int defindex) exists. Is this what I need?

My current code: ulong scrapID = 0; ulong scrapID2 = 0; ulong scrapID3 = 0; Bot.GetInventory(); foreach (var item in Bot.MyInventory.Items) { if (item.Defindex == 5000) scrapID = item.Id; } foreach (var item in Bot.MyInventory.Items) { if (item.Defindex == 5000) scrapID2 = item.Id; } foreach (var item in Bot.MyInventory.Items) { if (item.Defindex == 5000) scrapID3 = item.Id; } if (scrapID != 0) { ulong[] toCraft = new ulong[3]; toCraft[0] = scrapID; toCraft[1] = scrapID2; toCraft[2] = scrapID3; Bot.SetGamePlaying(440); short craftrecipe = 6; Crafting.CraftItems(Bot, craftrecipe, toCraft); // Update bot's inventory Bot.GetInventory(); foreach (var item in Bot.MyInventory.Items) ; //logging Console.WriteLine(scrapID); Console.WriteLine(craftrecipe); Console.WriteLine(toCraft); Array.ForEach( toCraft , x => Console.WriteLine(x) ); scrapID = 0; scrapID2 = 0; scrapID3 = 0; } }

waylaidwanderer commented 11 years ago

This should work:

List<ulong> scraps = new List<ulong>(); // we will store the scrap IDs here
Bot.GetInventory();
foreach (var item in Bot.MyInventory.Items)
{
    if (scraps.Count == 3)
        break; // stop looking for more scrap metal when we already have 3
    if (item.Defindex == 5000 && !scraps.Contains(item.Id))
        scraps.Add(item.Id); // This code checks to make sure ID doesn't exist already, then adds to list
}
if (scraps.Count == 3)
{
    Bot.SetGamePlaying(440);
    Crafting.CraftItems(Bot, scraps.ToArray()); // Here we transform the list object into an array
    // Update bot's inventory
    Bot.GetInventory();
}
waylaidwanderer commented 11 years ago

Can this issue be closed now?