lately i got a few requests to make a refinement tool.
since this community helped me so much with coding some very useful scripts i want to share this with u.
it a very simple tool made with autohotkey (AHK). ofc without any mouse clicks or color read trash.
i call it Refine Center. here is a screenshot:
how to use it:
select the character you want to work with in the first combo box
open the Elder NPC and the refine window where u want to refine
the value "Item Position" should be the position of the item in your inventory. starting to count from 1 to 32 (64). default its the last inventory slot. the position of refinement aids doesnt matter.
the value "Refinement" should be the maximum refinement u want to get
use Tienkan and Tisha are the refinement level starting with 0 and separated by comma. default the item will be refined to +7, at +1 to +4 tienkan will be used and at +5 to +6 tisha will be used as refinement aid
the value "delay" is a fixed delay after the button refine is presses (well or the packet is send). it would be nice to read the status of this button for best performance but i was not able to find the offset chain
and thats it: press start
supported hotkeys:
ALT+P = Pause
ALT+ESC = Close App
offsets:
the offsets.ini contains the current offset of PWI Eclipse v.842
the app is only tested at this server (with windows 7). adjusting the offsets might work for others
the offsets.ini needs to be in same path as the exe
note that many offsets are not necessary for this app...was just to lazy to remove them
Feel free to report bugs or issues. And please no rocks at me if u fail with it and good luck :P
I made a version a while ago that's not pretty like yours but it's set up to auto-buy the tisha and tienkang from the event boutique when it runs out of any in the inventory. Here are the packets for that if you need (though I'm sure you can find these yourself).
;~ 1) in the GUI: read the playerID, processID and playername -> put them in a string (separated by |) and use it in the combo box
Gui, Add,Text, x40 y75 w50 h25 , Character:
gosub, getClientInfos
Gui, Add, ComboBox, AltSubmit x+32 yp-3 w170 h20 R10 gLoadAtSelection vhookedClient, %PlayerInfo%
;~ 2) in a function: now the array "ClientIDs" contains all processIDs. easy to access by using AltSubmit as combo box option. so to start a function with the choosen character use something like this and work with the processID:
gui, submit, nohide
global processID := ClientIDs[hookedClient]
createMemoryPointers()
Awesome work
That makes me actually curious, how you got the Playername offsets and how to actually memread it via Autoit or Hotkey as string oO Im using atm Playerid as Client selection, which is good but harder to see who is who....
I wasnt able to find the addresses myself. I tried finding it by converting the playername to Hex and search it via CE. Also hexdec didnt bring it :/
Would be cool if someone could give me a hint ^^
i think Interest explained how to find the offset here:
i myself use ReClass2012...search for the PlayerPointer (easy to find with hp value) and search for it... should be close to the classID and other stuff. another way would be to search in CE for the length of the name...log another char with different length and repeat till u find the offset for it. 0x8 after that should be the name (see function getPlayerName).
Code:
getPlayerName(processID,GetPlayerPointer=1)
{
global
playerName =
tempOffset = 0x0
if (GetPlayerPointer = 1)
{
baseAddress := ReadMemoryUint(realBaseAddress, processID)
structurePointer := ReadMemoryUint(baseAddress + baseOffset, processID)
playerPointer := ReadMemoryUint(structurePointer + playerOffset, processID)
}
playerNamePointer := ReadMemoryUint(playerPointer + playerNameOffset, processID)
playerNameLen := ReadMemoryUint(playerNamePointer - 4*0x2, processID)
loop, %playerNameLen%
{
character := ReadMemoryStr(playerNamePointer, tempOffset, processID)
; just in case
if character =
break
if (playerNameLen > 12)
break
tempOffset := tempOffset + 0x2
playerName := playerName character
}
return playerName
}
ReadMemoryStr(MADDRESS, offset, PID)
{
ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "Uint")
teststr =
Loop
{
Output := "x"
tempVar := DllCall("ReadProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS+offset, "str", Output, "Uint", 1, "Uint *", 0)
if (ErrorLevel or !tempVar)
{
DllCall("CloseHandle", "int", ProcessHandle)
return teststr
}
if Output =
break
teststr = %teststr%%Output%
MADDRESS++
}
DllCall("CloseHandle", "int", ProcessHandle)
return, teststr
}
Thank you very much Stark.
I tried ReClass a few weeks ago, but just to test it out a bit. I didnt think, that i could use it in an easy and more helpfull way.
Ill look into it when i have more time
If i understand your function getPlayerName() right, then you are looping through each character to get the full name right ?
I thought before, that you could just read out the full name(obviously not as String, maybe as hex dec or so) and then convert it to string.
Thanks for sharing your way, i am learning more and more here which is awesome
Thank you very much Stark.
I tried ReClass a few weeks ago, but just to test it out a bit. I didnt think, that i could use it in an easy and more helpfull way.
Ill look into it when i have more time
If i understand your function getPlayerName() right, then you are looping through each character to get the full name right ?
I thought before, that you could just read out the full name(obviously not as String, maybe as hex dec or so) and then convert it to string.
Thanks for sharing your way, i am learning more and more here which is awesome
This is a good resource for showing where things are located though the offsets are not current.
I use CE and try looking near the last known location for where the data is. Usually small offsets are not changed but the bigger ones get shifted down a few bytes when they add things to the player struct. So maybe that 0x6D8 offset will become 0x6E0, it won't be in a completely new place.
Hi, first tyvm for sharing such great work and maybe I can help with one detail.
I've been refining my stuff to +7 manually with Tienkan and Tisha, got 4 sets of gear to refined +7 and I saying this so you know that I really do have some hard experience with it to base my hypothesis that: The chance of success of each level is not a complex algorithm of randomizing according to e % rate but, merely a matter of timing.
As in. The percentage of success rate is a direct percentage of "a time cycle".
So, when refining from..
0 to 1, 50% of the cycle time.
1 to 2, 30% of the cycle time... and so on.
Then, as long as u know the beginning of the cycle, you also know the moment when its success and moment when its fail.
Now why do I think that.
Maybe you guys have heard of donkey refining.(rough translation of "refinando com mula")
Its a technique well noun between Brazilian players that consist in making attempts of refinement on a worthless piece of gear until u find a rhythm of fails and success and then you quickly switch the worthless gear to the real gear you want to refine when u "feel" like the next attempt is in a "success moment" of the rhythm.
Conclusion, if its truly a matter of timing instead of %rate, then you could implement this Refining Center with a time factor for the attempt.
Like, assume cycle is 1 sec and start after the cool down of the button to refine.
Then consider the lag between the client and the server doing a ping test to the server and take the average rate between a few tests.
And then make some tests to know if the success rate is at the beginning of the cycle or in the end.
Then finally, make the Refine Center make attempts only during the success moment.
Like, a routine that keep trying 20 times per second, but a second routine miscarries the attempts if the moment is considered a fail rate of the cycle.
And im sorry for the long text if im wrong x.x
Refining to +7 is no accomplishment to boast about. I've refined plenty of gear to +9 without any of your cycle gibberish. The fact you are unwilling to refine past an easily attainable level suggests your model lacks any actual predictive power.
Logically the devs of the game have better things to do than waste days of development time coding and testing a complicated scheme like that when there is literally no benefit in them doing so. While I haven't inspected the source code I'd wager the refine function looks something like
Oki doki master jasty, thank you so much for your lovely approach on the topic.
Not trying to refine post +7 only show my lack of try. Trying and failing would actually suggest failure.
Another point that makes me thing it is true, is that I've seen many times ppl say: "I spent x thousands of mirages to refine this or that".
Or ppl saying: "I spent these hundreds of mirages and only got +3".
And I just made last week 2 pieces +7 with about 250 mirages. I had 11xx mirages and in the end had 9xx mirages, can't remember the exactly number.
[FIX]DoRefineWithScroll: REFINE : Unknown refine scroll 07/27/2013 - Metin2 PServer Guides & Strategies - 9 Replies Hi, falls euch der fehler DoRefineWithScroll: REFINE : Unknown refine scroll item in der syserr auf den sack geht habe ich hier eine Lösung für euch wie ihr es fixt.
1. Player Datenbank öffnen
2. refine_proto tabelle öffnen
3. Oben links auf "file" und dann auf "Query Table.." klicken
4. folgendes einfügen und oben auf "Run" klicken
UPDATE player.refine_proto SET count0='0' WHERE vnum0='0';
UPDATE player.refine_proto SET count1='0' WHERE vnum1='0';
UPDATE player.refine_proto SET...