[HowTo]Learn Python with Metin2/Starting up your first bot

10/23/2012 20:16 .BaumKuchen#1
Heute möchte ich euch eine kleine Einleitung in die Python Programmierung mit Hilfe des Metin2 Clienten ein wenig näher bringen.

Aber erstmal ein paar kleinere Informationen zu mir:
Ich studiere aktuell Softwaretechnik an der Universität Stuttgart wobei sich dies mehr auf Java beläuft.
Aber der wichtigste Part der Informatik ist grundlegend nicht eine Sprache perfekt zu beherrschen, sondern sie zu verstehen.

Python scripte ich nun seit knapp 2,5 Jahren und habe auch schon verschiedene, bisher eher kleinere Projekte auf die Beine gestellt.
Ich bin auch noch nicht sehr lange im Metin2 Bereich aktiv, habe mich auch erst neulich auf Epvp registriert.
Nichts desto trotz habe ich mir bereits die Python Scripte im Clienten durchgeschaut, wodurch ich zumindest das Prinzip des Clienten verstanden habe.


Weiter geht es mit dem Tutorial:
Was ist Python überhaupt?
Python ist eine bisher einigermaßen unbekannte Programmiersprache, die 1991 von Guido von Rossum in seinen Ferien entwickelt wurde.
Sie gewann schnell an Beliebtheit und wurde stetig weiterentwickelt, sodass sie heute auch mit anderen großen Sprachen mithalten kann.

Warum benutzt Metin2 überhaupt Python als Schnittstelle?
Python ist eine recht performante Sprache, welche auch ab Python 2.3 effizient in Low-Level Interface Bereichen dank ctypes recht interessant geworden ist.
Auch aufgrund seines stabilen Aufbaus und den vielfältigen Möglichkeiten wird es nicht nur in Metin2, sondern auch oft in anderen größeren Spielen verwendet.
Metin2 benutzt Python 2.2.1, die aktuellste Version ist aber 2.7.3 in der 2.x Version und 3.3.0 in der 3.x Version.
Diese wurde bereits seit 2003 nicht mehr weiterentwickelt und erhält selten irgendwelche neuen Module, wobei diese für den Clienten zum Großteil sowieso uninteressant sind.

Wenn die verwendete Python Version über 9 Jahre alt ist, wäre es dann nicht sinnvoll zu updaten?
Ein wichtiger Punkt ist die Performance, worauf jeder gute Programmierer zu achten hat.
Metin2 ruft selber in den Scripts zwei Funktionen auf, die OnUpdate und OnRender heißen, diese werden in der Binary gecalled und sind somit nicht standardmäßig in Python enthalten.
Diese Funktions werden 20x(OnUpdate) und 60x(OnRender) pro Sekunde aufgerufen.
Dies entspricht einer Delay von 0.05 Sekunden und ~0.017 Sekunden.
D.h. die Performance wird sich nicht sichtbar verbessern, wenn ihr Python auf eine neuere Version updated.
Die Funktionen werden zwar schneller ablaufen, allerdings wird die menschliche Wahrnehmung das nicht merken, da diese bei 16 Bildern pro Sekunde liegt, wovon nichtmal alle verarbeitet werden.
Falls ihr die Python Version updaten wollt, könnt ihr zwar neue Module hinzufügen, die Performance wird davon aber nicht sichtbar beeinträchtigt.
Python hat in den neueren Versionen mit unter anderem mit ctypes starke Low-Level Module hinzugefügt, diese werden dadurch auch für "Hacker" nutzbar.
Auch ist die WSAIoctl Funktion ab Python 2.5 verfügbar, welche recht interessant fürs Packet Editing ist, diese wird bei z.B. bei einem Update ebenfalls ermöglicht.
Solange ihr selber also nicht neue Module braucht und Python updaten möchtet ohne dass ihr überhaupt einen gewissen Zweck verfolgt würde ich euch davon abraten.

An Modulen, die man in Metin2 brauchen könnte kamen bis auf z.B. sqlite3 nicht sonderlich viele Module hinzu.
Falls ihr diese Module trotzdem vermisst, gibt es meist noch von der damaligen Zeit Ersatzlösungen oder von neuerer Zeit Backports der demensprechenden Module.


Die Grundlagen von Python:
Ich setze hier bestimmte Grundlagen von Python vorraus, ihr müsst demnach zumindest den groben Syntax verstehen.
indented block(falsche Einrückung von den Tabs bzw. Leerzeichen), invalid syntax wenn jemand z.B. einen Doppelpunkt vergisst werde ich hier nicht erläutern, diese findet ihr bereits beim "Hello World", also dem absoluten Basic bei jedem Python HowTo.
Ich werde hier Metin2 spezifische Module erläutern und die Logik bzw. diskrete Funktionen(so lautet auch eine der wichtigsten Vorlesungen bei meinem Studium).

Eines der wichtigsten Punkte hierbei sind die Vids.
Dies sind virtuelle IDs welche jedem Spieler/Item/Mob zugewiesen werden um das ganze Spiel überhaupt erst in seiner Form zu ermöglichen.
Diese beinhalten alle möglichen Informationen, die der Spieler über die entsprechende Vid erhalten soll, teilweise sogar mehr als geplant war wie ich selber mitbekommen habe.


Gehen wir einmal davon aus, dass die Vid des gewünschten Monsters 1 sei:
Nun haben wir verschiedene Möglichkeiten um an die Informationen des Monsters zu kommen.
Falls man mit dem chr Modul arbeitet ist es erstmal wichtig, die gewünschte Instanz überhaupt erst einmal anzuwählen.
Dies passiert mit dem Command "chr.SelectInstance(vid)", vid ist eine Variable mit dem Datentyp Integrer, d.h. in unserem Beispiel könnten wir direkt über dem Command vid = 1 definieren.

Damit wir unterscheiden können ob es sich bei der erhaltenen Vid um einen Gegner, Npc, Monster, Spieler oder sonstiges unterscheidet überprüfen wir den Instance Type.
Gliedern wir das ganze etwas auf um etwas Ordnung in unsere Vid-Liste zu bekommen.
Dazu erstellen wir kurzerhand ein assoziatives Datenfeld, das folgendermaßen aussieht:

PHP Code:
#create an array with the possible instance types as keys
vid_array = {
    
chr.INSTANCE_TYPE_BUILDING: [],
    
chr.INSTANCE_TYPE_ENEMY: [],
    
chr.INSTANCE_TYPE_NPC: [],
    
chr.INSTANCE_TYPE_OBJECT: [],
    
chr.INSTANCE_TYPE_PLAYER: [],
    
6: [],

Wir haben hier einen bestimmten Key, der demnach die Vids in dem Array einem bestimmten Unterarray zuweist.
Diesen finden wir mit dem Command "chr.GetInstanceType(vid)" heraus.
Hierfür müssen wir die Instanz dieses mal nicht selecten.

Schauen wir einmal an was wir bisher so haben:

PHP Code:
import chrplayer
from chat import AppendChat

#create an array with the possible instance types as keys
vid_array = {
    
chr.INSTANCE_TYPE_BUILDING: [],
    
chr.INSTANCE_TYPE_ENEMY: [],
    
chr.INSTANCE_TYPE_NPC: [],
    
chr.INSTANCE_TYPE_OBJECT: [],
    
chr.INSTANCE_TYPE_PLAYER: [],
    
6: [],
}

#get main character index
vid player.GetMainCharacterIndex()

#get the instance type from the selected vid
instance_type chr.GetInstanceType(vid)

#check if vid is already in the array, else append it to the array
if not vid in vid_array[instance_type]:
    
vid_array[instance_type].append(vid
Okay so weit haben wir unsere Vid bereits ihren dementsprechenden Kategorien zugeordnet.
Solange wir aber nicht die Vids der restlichen Instanzen um uns herum herausfinden nutzt und das ganze aber leider recht wenig.
Leider gibt es unter Python 2.2 noch keine Möglichkeit die OnRegisterVID in der Binary zu hooken, demnach müssen wir uns auf die alte Methode Bruteforce(Raten) verlassen.

Hierbei haben die meisten Coder Probleme mit der Performance.
Um eben diese zu gewährleisten greifen wir auf das thread Modul zurück.
Multi-threading bedeutet, dass die Prozesse im selben Arbeitsspeicher ausgeführt werden, aber komplett unabhängig von seinem Parallel Prozess laufen.
Dadurch gewährleisten wir, dass es Ingame kein bisschen laggt, obwohl eine recht große Menge an Vids in einem kleinen Zeitraum abgefragt werden.

Ein Thread erstellt man recht einfach:
PHP Code:
#importing from the modules only the functions I need in my script
from thread import start_new_thread
from os import system

#we still need a function we can call, so I defined a new one
clear lambdasystem("cls")

#finally start the new thread
start_new_thread(clear, ()) 
Das Beispiel klappt in dem Fall zwar nur auf Windows und das auch nur in der Kommandozeile, soll aber auch nicht die function eine Rolle spielen sondern wie der Thread gestartet wird.
Kleine Ausname was den Thread betrifft:
Sofern nur 1 Parameter mitgeliefert wird ändert sich der 2. Parameter des Calls zu einem None, also z.b. so ein Aufruf

start_new_thread(cookies, (1, ))
Das letzte "," ist wichtig, sonst returned euch die function einen Syntax Fehler.


Genug zu der Funktionsweise der Threads, setzen wir das eben gelernte direkt um.
Zu allererst legen wir eine Range fest, in welcher die ganzen Vids gecheckt werden sollen.

In meinem Fall nehme ich einmal eine Range von 0 bis 2.700.000, da selbst bei Metin2 De auf den einigermaßen vollen Servern die Vid selten oder garnicht diesen Wert überschreitet.
Privat Server überlasten in diesem Fall gerne einmal ihre Server, aber das ist ja deren Sache.

Standardmäßig würden wir das ganze in 1 for loop abfragen, da es dann aber laggen würde, führen wir das ganze einfach in einem externen Thread aus.

PHP Code:
import chrplayer
from chat import AppendChat
from thread import start_new_thread

vid_array 
= {
    
chr.INSTANCE_TYPE_BUILDING: [],
    
chr.INSTANCE_TYPE_ENEMY: [],
    
chr.INSTANCE_TYPE_NPC: [],
    
chr.INSTANCE_TYPE_OBJECT: [],
    
chr.INSTANCE_TYPE_PLAYER: [],
    
: [],
}

final_range 36

def check_vid
(check_range):
    for 
vid in range(check_range 75000):
        
#get the instance type from the selected vid
        
instance_type chr.GetInstanceType(vid)

        
#check if vid is already in the array, else append it to the array
        
if not vid in vid_array[instance_type]:
            
vid_array[instance_type].append(vid)
    
    if 
check_range == final_range:
        
##here you can continue with your script^^
        
print("Scan finished...")

for 
check_range in range(final_range):
    
start_new_thread(check_vid, (check_range, )) 
Nun haben wir bereits unsere Aufgliederung und die umliegenden Vids mit denen wir arbeiten müssen, damit unser Bot laufen kann.
Zunächst wollen wir abfragen welches Monster überhaupt am nächsten zu uns liegt.
Dazu arbeiten wir mit dem Command "chr.GetPixelPosition()".
Natürlich wollen wir die Distanz zu unserem Charakter ermitteln, d.h. wir brauchen auch unsere eigenen Koordinaten, welche wir mit "player.GetMainCharacterPosition()" erhalten.
Damit wir auch die Koordinaten des gewünschten Monsters erhalten, visieren wir demnach unsere Ziel Vid erneut an und nutzen den oben geschriebenen Command.

PHP Code:
import playerchr

x
yplayer.GetMainCharacterPosition()
chr.SelectInstance(vid)
xychr.GetPixelPosition() 
Wir können diese 3 Variablen mit diesem einen Command nur nutzen, da GetPixelPosition ein Tuple der Länge 3 returned, also bereits (x, y, z).
Python unpacked das Tuple dann direkt, wenn die gewünschte Anzahl der Variablen der returnten Anzahl der Variablen entspricht.

Kommen wir ein bisschen zur Mathematik, der Vektorrechnung.
Diese brauchen wir um von unserem im 2D Raum betrachteten Aufstellung der Vid-Positionen die Distanz ermitteln zu können.
Die 3. Dimension der Vektorgeometrie benötigen wir nicht, da der Charakter nicht langsamer wird wenn er z.B. einen Berg hinaufläuft.
Hierzu stelle ich direkt die Funktion bereit, da dies nicht sonderlich viel mit der Sprache oder der Logik zu tun hat, sondern einfach eine mathematische Gegebenheit ist, die jeder im Laufe seiner Schulzeit mind. 2-3x lernt.

PHP Code:
import playermath

def get_distance
(mob_xmob_y):
    
#get main character position
    
player_xplayer_yplayer_z player.GetMainCharacterPosition()
    
    
#distance calculation
    
tmp_xtmp_y = (((player_x mob_x) ** 2/2), ((player_y mob_y) ** 2/2))
    return(
math.sqrt(tmp_x tmp_y)) 
Wir können das ganze sortieren indem wir die praktische Eigenschaft von Python nutzen ein Array nach der Value zu sortieren.
D.h. wir fügen unsere ganzen Vids in ein assotiatives Datenfeld und schreiben die Distanz als Value dahinter.

PHP Code:
import chr

distance_dict 
= {}
compare_array = []

#create a loop with the vids as variables
for vid in vid_list[chr.INSTANCE_TYPE_ENEMY]:

    
#calculate the distance
    
distance get_distance(vid)
    
    
#if distance isn't already in the dict create it
    
if not distance in distance_dict:
        
distance_dict[distance] = []
        
    
#append the values to the arrays
    
distance_dict.append(vid)
    
compare_array.append(distance
Damit erhalten wir jetzt zwei dicts, welche in etwa so aussehen dürften:
distance_dict = {34: [1], 25: [14, 2]}
compare_array = [34, 25]

Jetzt sortieren wir das compare_array und erhalten den kleinsten Wert an 1. Stelle, in unserem Beispiel die 25.
Dazu schreiben wir:
shortest_distance = sorted(compare_array)[0]

Damit wir jetzt die Vid erhalten nutzen wir die Distanz, die wir als Key genommen haben im distance_dict.
D.h. wir nehmen:
distance_dict[shortest_distance]

Dies returned jetzt die Werte 14 und 2, also nehmen wir den 1. indem wir ein [0] an unserem Wert oben anhängen.

Nun haben wir also unser Monster, welches uns am nächsten liegt.

Dann laufen wir einmal zu unserem Monster, indem wir den Befehl chr.MoveToDestPosition nehmen.
Übersetzt heißt der Command Bewege dich zur festgelegten Position, dementsprechend brauchen wir hierbei auch noch eine Position.
Desweiteren wird benötigt WER sich dorthin bewegen soll, d.h. wir brauchen auch noch eine Vid.
D.h. der Command ist so aufgebaut:
chr.MoveToDestPosition(vid, x, y)
die Höhen-Achse brauchen wir ja nicht, da diese automatisch angepasst wird vom Spiel.

Okay damit läuft der Charakter schon einmal zum nächst gelegenen Monster.
Mit der oben verwendeten Distance Berechnung könnt ihr jetzt auch ständig die Distanz zum Monster berechnen und somit bemerken, wann ihr festhängt oder wann ihr in Schlagreichweite seit.
Hierzu eignet sich die OnUpdate Funktion wunderbar, da damit das Monster perfekt verfolgt werden kann.

Die Schlagdistanz beläuft sich auf eine Distanz von 120-180, kommt auf die Größe der Monster an.
Diese könnt ihr auch mit "chr.GetBoundBoxXY(vid)" perfekt berechnen, das wird aber zu umfangreich um das auch noch alles zu erklären.

Angekommen beim Monster setzen wir den Attack Key State auf true, damit der Charakter auch das Monster schlägt.
Dies passiert mit dem Command player.SetAttackKeyState(TRUE).
Nebenbei bemerkt: Metin2 parsed das True aus Python anderst und verlangt ein TRUE anstatt ein True, sodass ein normales True keine Auswirkung hat.

The rest is up to you^^

Von mir werdet ihr übrigens weniger Releases sehen sondern mehr Tutorials, dies liegt an manchen Aktionen in der Community, die mir nicht allzu gut gefallen, wo einige probieren andere Mitglieder der Community zu "veräppeln".
Ich sehe nicht ein, warum ich Releases machen soll für User, welche meinen, dass sie ihren Spaß mit den anderen Usern haben können und dann noch alles leechen können.
Aufgefallen sind mir diese Aktionen in diesem Thread:
[Only registered and activated users can see links. Click Here To Register...]

Demnächst wird noch ein kleineres Tutorial für einen Auto Answer Bot kommen, welcher sich auf cleverbot bezieht und einige kleinere Tricks wie man seinen Bot unauffälliger gestalten kann, sodass er aus dem Pattern der Standard Bots fällt.
Desweiteren ist es wesentlich sinnvoller seinen Bot selber zu schreiben, da er damit nicht public ist und die verschiedenen Varianten sich differenzieren, was es sehr viel schwerer gestaltet Bots zu erkennen und einzugruppieren.
So läuft mein eigener Bot den ich letzte Woche geschrieben habe bereits seit über 92 Stunden nonstop durch.
Durch den Auto-Answer Bot hat der Bot auch eine Frage eines GameMasters überstanden, welcher zwischendurch eine PN geschrieben hat.

Fragen & Verbesserungsvorschläge einfach in den Thread posten.

Einen guten Tag noch
10/23/2012 20:23 |★|554#2
Ui, nicht schlecht, wo ich mich doch grade in Sachen GUI's für Metin2 schlau machen wollte :3
Sehr schön, würde mich über weitere Tutorials zum Thema Metin2-Python freuen!
10/23/2012 20:41 .Marcel#3
Sieht gut strukturiert aus !
Werde es mir später nochmal genau durchlesen , da Ich es nur überflogen habe .
Schauen wir mal ob es mich weiter bringt bei meinen 0% python Kenntnissen .

MFG
10/23/2012 20:42 Dröttning Arya#4
Quote:
Originally Posted by .Marcel View Post
Sieht gut strukturiert aus !
Werde es mir später nochmal genau durchlesen , da Ich es nur überflogen habe .
Schauen wir mal ob es mich weiter bringt bei meinen 0% python Kenntnissen .

MFG
Hehe , genauso denke ich gerade :D
10/23/2012 21:02 Syuki#5
Aua, meine Augen..
Danke für die Information, hat mir echt geholfen.
10/23/2012 21:07 xCPx#6
An sich ganz nett, nur bringt das Tut hier fast ausschließlich nur für Bots was ^^
10/23/2012 21:16 [uLow]Beni#7
nice, so viel arbeit ;)
jetzt ist das threading in mt2 auch mal public ...

kleine verbesserung:
True statt TRUE hat sowohl eine auswirkung:
- script abbruch ;)
ich würde dazu schreiben, dass man statt TRUE auch 1 verwenden kann oder statt FALSE 0.


trotzdem RESPEKT :), du musst dich fast für denn unterground bewerben.


blöde frage:
kann man also in metin2 python packet editieren, oder braucht man da trotzdem mehr "rechte"
10/23/2012 21:29 .BaumKuchen#8
Quote:
Originally Posted by xCPx View Post
An sich ganz nett, nur bringt das Tut hier fast ausschließlich nur für Bots was ^^
Das Thema heißt ja auch "Starting up your first bot".
Und warum sollte man keine Fortschritte machen, während man einen Bot schreibt, eine Automatisierung ist wesentlich anspruchsvoller als ein User Interface zu schreiben.

Quote:
Originally Posted by !Beni! View Post
nice, so viel arbeit ;)
jetzt ist das threading in mt2 auch mal public ...

kleine verbesserung:
True statt TRUE hat sowohl eine auswirkung:
- script abbruch ;)
ich würde dazu schreiben, dass man statt TRUE auch 1 verwenden kann oder statt FALSE 0.


trotzdem RESPEKT :), du musst dich fast für denn unterground bewerben.


blöde frage:
kann man also in metin2 python packet editieren, oder braucht man da trotzdem mehr "rechte"
True hat standardmäßig den Boolean Wert 1, während False 0 ist.
Es kann entweder 1 oder 0 sein und da es nicht 1 ist, ist es automatisch 0, somit entspricht True in Metin2 False und man muss auf TRUE zurückgreifen oder eben direkt eine Zahl > 0 nehmen.

Und man kann Packets editieren, allerdings benötigst du hierzu mind. Python 2.5.

Threading sollte ansich Standard sein, immerhin sind fast alle guten Patcher multi-threaded.

Ug will ich nichtmal rein, das was ich selber brauche probiere ich mir selber zu schreiben, wenn ich es lediglich von anderen abschaue bringt es mir garnichts.
Mit Hilfe von google kommt man bei fast jeder Problematik zurecht, alternativ probiere ich es einfach solange bis es funktioniert.
10/23/2012 21:45 [uLow]Beni#9
danke :)
vielleicht bring ich es mit deinem tutorial mal zusammen, meinen stepteleporter nur mit einem thread zum fertigstellen.

wieder ne blöde frage:
woher weißt du welche Parameter chr.MoveToDestPosition(???) nimmt ?

und noch was:
kann man nicht einfach player.GetCharacterDistance(vid) statt get_distance(x,y) nehmen ?
10/23/2012 21:55 .Colossus.#10
Geniales Tut....werds mir heute abend mal genauer anschauen
10/23/2012 22:01 .BaumKuchen#11
Quote:
Originally Posted by !Beni! View Post
danke :)
vielleicht bring ich es mit deinem tutorial mal zusammen, meinen stepteleporter nur mit einem thread zum fertigstellen.

wieder ne blöde frage:
woher weißt du welche Parameter chr.MoveToDestPosition(???) nimmt ?

und noch was:
kann man nicht einfach player.GetCharacterDistance(vid) statt get_distance(x,y) nehmen ?
chr.MoveToDest habe ich mittels OllyDbg ausgelesen, was deinen 2. Punkt betrifft habe ich diesen Command noch nicht gesehen bzw. genutzt und das ganze über eine eigene Vektorrechnung geregelt.

Falls player.GetCharacterDistance(vid) funktioniert ist dies auch eine gute Möglichkeit.

Die Rechnung habe ich auch zum Spaß benutzt um einen Bot Detector zu schreiben, in dem ich die Distanz von anderen Spielern zu den Monstern berechnet habe und ausgewertet habe wie oft und wie genau diese Spieler den nächsten Mob anvisieren.
So habe ich z.B. einige Botter entdeckt, da diese zu 100% immer den nächst gelegenen Mob anvisieren.

Code:
player:
*censored*

vid:
64474

next-group attack stats:
392/398

bot ratio:
98,49%
Die 6 anderen Gruppen kamen großteils durch Lags zustande.

Kein normaler Spieler greift immer in einem 360° Radius immer exakt den nächsten Mob an, das liegt teilweise nichtmal in der menschlichen Wahrnehmung durch der BoundBox bzw. der Größe des Models.
10/23/2012 22:15 xCPx#12
Quote:
Originally Posted by .BaumKuchen View Post
Das Thema heißt ja auch "Starting up your first bot".
Und warum sollte man keine Fortschritte machen, während man einen Bot schreibt, eine Automatisierung ist wesentlich anspruchsvoller als ein User Interface zu schreiben.



True hat standardmäßig den Boolean Wert 1, während False 0 ist.
Es kann entweder 1 oder 0 sein und da es nicht 1 ist, ist es automatisch 0, somit entspricht True in Metin2 False und man muss auf TRUE zurückgreifen oder eben direkt eine Zahl > 0 nehmen.

Und man kann Packets editieren, allerdings benötigst du hierzu mind. Python 2.5.

Threading sollte ansich Standard sein, immerhin sind fast alle guten Patcher multi-threaded.

Ug will ich nichtmal rein, das was ich selber brauche probiere ich mir selber zu schreiben, wenn ich es lediglich von anderen abschaue bringt es mir garnichts.
Mit Hilfe von google kommt man bei fast jeder Problematik zurecht, alternativ probiere ich es einfach solange bis es funktioniert.

kommt ganz auf das Userinterface drauf an.
Ich zb lasse mir alle generieren, was genauso eine automatisierung ist.

Aber egal.
Finde die idee an sich ganz gut.
Die Frage ist nur, ob sowas nicht kontraproduktiv für die Sektion ist.

BTW:

Die vid´s kriegt man über die Minimap total easy raus.
Damit spart man sich das "RATEN"
Da sich die minimap ja eh grundsätzlich aktualisiert.
(bFind, sName, iPosX, iPosY, dwTextColor) = miniMap.GetInfo(mouseX, mouseY)

so wäre unter bFind die vid.
Man müsste nurnoch mit einem neuen Thread alle punkte auf der Minimap durchgehen (was maximal 100x100 sind) und sich freuen ^^
10/23/2012 22:44 .BaumKuchen#13
Quote:
Originally Posted by xCPx View Post
Finde die idee an sich ganz gut.
Die Frage ist nur, ob sowas nicht kontraproduktiv für die Sektion ist.

BTW:

Die vid´s kriegt man über die Minimap total easy raus.
Damit spart man sich das "RATEN"
Da sich die minimap ja eh grundsätzlich aktualisiert.
(bFind, sName, iPosX, iPosY, dwTextColor) = miniMap.GetInfo(mouseX, mouseY)

so wäre unter bFind die vid.
Man müsste nurnoch mit einem neuen Thread alle punkte auf der Minimap durchgehen (was maximal 100x100 sind) und sich freuen ^^
Ein Spiel wird immer 2 Seiten haben:
Eine probiert sich Vorteile zu schaffen und die andere probiert dies zu verhindern.
Jede Seite die dies verhindert wird aber auch genau das Gegenteil probieren um eben die jeweiligen Pattern zu finden.
Die "Bösen" wollen das Pattern umgehen, welches ihre Bots/Hacks findet und die "Guten" wollen ein Pattern erstellen um die "Bösen" davon abzuhalten.
Aber das liegt im Sinne des Betrachters.

Zu deinem Punkt mit der Vid:
"bFind" ist ein boolean Wert, der 0 oder 1 ist.
Falls dieser 1 ist existiert unter diesen Koordinaten ein Monster/Npc oder eben etwas das einen Tooltip auf der Minimap hat, 0 eben nicht.

"sName" ist der dementsprechende Name, falls bFind den Wert 1 hat.

"iPosX" und "iPosY" muss ich denke ich nicht erklären und "dwTextColor" deklariert den dementsprechenden Punkt als z.B. Monster oder NPC indem es die Farbe des Tooltips definiert.

Die Minimap verwendet für Python lediglich eine bereits vordefinierte Funktion im Python Modul:
"miniMap.Update(x, y)" setzt die Minimap auf die richtige Stelle, sodass der Spieler immer in der Mitte steht.

"miniMap.Render(fx + 4.0, fy + 5.0)" aktualisiert alle gegnerischen/eigenen Funktionen.


Ohne win api hooking kommst du hier nicht sonderlich viel weiter.
Dies ist auf den Punkt von oben zurück zu führen, dass ymir sich solche Punkte bereits denken können sollte und präventiert, dass jemand so etwas ausnutzen kann.
10/23/2012 22:52 xCPx#14
Quote:
Originally Posted by .BaumKuchen View Post
Ein Spiel wird immer 2 Seiten haben:
Eine probiert sich Vorteile zu schaffen und die andere probiert dies zu verhindern.
Jede Seite die dies verhindert wird aber auch genau das Gegenteil probieren um eben die jeweiligen Pattern zu finden.
Die "Bösen" wollen das Pattern umgehen, welches ihre Bots/Hacks findet und die "Guten" wollen ein Pattern erstellen um die "Bösen" davon abzuhalten.
Aber das liegt im Sinne des Betrachters.

Zu deinem Punkt mit der Vid:
"bFind" ist ein boolean Wert, der 0 oder 1 ist.
Falls dieser 1 ist existiert unter diesen Koordinaten ein Monster/Npc oder eben etwas das einen Tooltip auf der Minimap hat, 0 eben nicht.

"sName" ist der dementsprechende Name, falls bFind den Wert 1 hat.

"iPosX" und "iPosY" muss ich denke ich nicht erklären und "dwTextColor" deklariert den dementsprechenden Punkt als z.B. Monster oder NPC indem es die Farbe des Tooltips definiert.

Die Minimap verwendet für Python lediglich eine bereits vordefinierte Funktion im Python Modul:
"miniMap.Update(x, y)" setzt die Minimap auf die richtige Stelle, sodass der Spieler immer in der Mitte steht.

"miniMap.Render(fx + 4.0, fy + 5.0)" aktualisiert alle gegnerischen/eigenen Funktionen.


Ohne win api hooking kommst du hier nicht sonderlich viel weiter.
Dies ist auf den Punkt von oben zurück zu führen, dass ymir sich solche Punkte bereits denken können sollte und präventiert, dass jemand so etwas ausnutzen kann.
achso ^^
ja ich habs nur iwo mal gesehen, dass man dadurch die VID kriegt, nur wusste nicht wie genau und hab einfach mal gesucht xD da stand dann !=0 was bei vid´s ja fast immer so definiert wird und joa ^^
10/23/2012 23:07 .Chuck#15
Wow, das How To gefällt mir echt sehr. Es wird den meisten einsteiger die sich mit Python beschäftigen helfen.

Danke dir und nochmal gefällt mir sehr.