Terraria ist ein super cooles Spiel, jedoch hat die deutsche Version von 1.1.2 noch ein paar miese Bugs drin. Leider wird das Spiel nicht mehr weiterentwickelt und was bleibt uns als Reverse Engineer da übrig und selbst Hand anzulegen. Ein Glück wurde es in C# geschrieben und dafür gibt es geniale Decompiler. Also was benötigen wir:
- Terraria muss installiert sein
- .net Framwork 4.0
- XNA Framework 4.0
- ILSpy 2.1.0 (Download-Link)
- Visual Studio C# Express (Link)
- Programmierkenntnisse in C# (:P)
Der Schritt zum Decompiling ist Recht einfach. Kurz gesagt ILSpy starten und dann die Terraria.exe in dem Programm öffnen. Nun Terraria in der Liste auswählen und unter "Datei --> Save Code..."
auswählen und einen Speicherort auswählen, wo das C# Projekt hinkopiert werden soll. Danach beginnt der Decompiling Vorgang und der kann je nach PC, ganz schön lange dauern. Also erstmal abwarten und Tee/Kaffee trinken ist angesagt.
Fehler über Fehler
Da der Decompiler nicht alles weiß, sind erst einmal ein paar Fehler mit in den C# Code gelangt, aber diese sind halb so schlimm. Wir starten das C# Projekt in Visual Studio und versuchen das Projekt zunächst zu kompilieren. Nun haben wir eine große Liste an Fehlern und so werden sie behoben:
Fehler: Der Operator „??“ kann nicht auf Operanden vom Typ „int“ und „int“ angewendet werden.
Code:
int num61 = num56 ?? -1;
fixing Code:
int = (num56 != null) ? num56 : -1;
Erklärung: http://msdn.microsoft.com/de-DE/library/ms173224.aspx
http://csharp-tricks.blogspot.de/2010/06/if-abfrage-mit-fragezeichen-bedingung.html
Fehler: Der Typ „int“ kann nicht implizit in „byte“ konvertiert werden. …
Code:
byte arg_1567_0 = b5 & 2;
fixing Code:
byte arg_1567_0 = (byte) (b5 & 2);
Erklärung: http://msdn.microsoft.com/de-DE/library/ms173105%28v=vs.80%29.aspx
Auch für andere Fehlertypen einfach nur die Typumwandlung anpassen und fertig.
Fehler: Nur assignment-, call-, ….
Code:
this.velocity != value2;
fixing Code:
//this.velocity != value2;
Erklärung: Diese Zeile Code ist irgendwie total unsinnig, deswegen kann sie weg. Außerdem war es der letzte Fehler und ein Versuch war erfolgreich :D
Auch im Internet gibt es etliche Tutorials die beschreiben, wie man Terraria dekompilieren kann. Vielen Dank an dieser Stelle für atom0s, an dessen Anleitung ich mich zuerst orientiert hatte und auf ILSpy gestoßen bin: http://www.unknowncheats.me/forum/other-games/73344-terraria-1-1-2-decompiling-recompiling.html
Ich habe es zuerst mit dem ".net Reflector"
probiert, aber da dieses Programm wohl sehr schlecht im decompilieren ist, ist ILSpy die kostengünstigste und beste alternative. ".net Reflactor"
hat bei mir ständig Fehler im Dekompilationsvorgang gehabt.
Die Drei
Nachdem wir die Kompilierungsfehler behoben haben, stelle ich euch kurz die die drei gemeinen Bugs vor, die ich fixen will.
Nummer 1 – Waffe erneuern? Ohne mich.
Terraria bietet allerlei Waffen im Spiel und alle Waffen haben bestimmte Stats und diese können positiv oder negativ sein. Im Laufe des Spieles findet man einen Goblin. Dieser ist Meister seines Handwerkes und kann unsere Waffen neuschmieden und damit die Stats auf der Waffe erneuern. Nun ja, hat man die Englische Sprache an funktioniert es einwandfrei. In deutsch verschwindet einfach das Item :(
Nummer 2 – Besoffen oder was
Der zweite Bug ist nur ein kleiner Anzeige Fehler in alles Geschäften. Dieser kommt zustande wenn mehr als eine Münzart angezeigt wird.
Nummer 3 – Boom! Du darfst nicht Sozial sein!
Der dritte Bug ist echt doof. In Terraria gibt es rechts im Inventar ein Ausrüstungsinventar. Hier gibt es sogenannte Social-Slots, diese bewirken das man beispielsweise einen Helm nur so tragen kann, weil er geil aussieht. Die Stats die auf dem Helm sind, werden dabei ignoriert, lediglich das aussehen wird halt geändert.
Ich hasse Steam und Beschränkungen
Es gibt zum einen eine Collectors Edition von Terraria. Käufer dieser Edition bekommen ein kleines Gimmick geschenkt. Hierbei handelt es sich um Karotten die dann in der Welt wachsen. Mit diesen kann man sich dann einen Hasen als Haustier züchten. Ganz ehrlich, von digitalem extra Schnickschnack halte ich nicht viel. Ich bin ein Käufer der die Gegenstände aus einer Collectors Edition am besten findet. Die man sich zu Hause hinstellen kann und jedes mal anschauen kann. Egal, folgendes finden wir in der Main.cs:
protected void CheckBunny() //Zeile 986 { try { RegistryKey registryKey = Registry.CurrentUser; registryKey = registryKey.CreateSubKey("Software\\Terraria"); if (registryKey != null && registryKey.GetValue("Bunny") != null && registryKey.GetValue("Bunny").ToString() == "1") { Main.cEd = true; } } catch { Main.cEd = false; } }
Hier brauchen wir nur folgendes stehen lassen und fertig:
protected void CheckBunny() { Main.cEd = true; }
Desweiteren ist Terraria an Steam gebunden. Wie ihr bestimmt schon mit bekommen habt, bin ich ein Steam-Hasser. Man installiert sich doch glatt noch eine weitere Spionage-Software mit und ist dann noch an so einen Kram gebunden, aber das ist ein anderes Thema. In der Program.cs
gibt es folgenden Code:
Steam.Init(); if (Steam.SteamInit) { main.Run(); }
Nun braucht man nur noch main.Run();
stehen lassen und fertig. Steam ist entfernt und man braucht diesen Kackhaufen von Steam nicht mehr :D
Die Suche
Ich fange zunächst mit Bug-Nummer 2 an, da dieser nur ein einfacher Anzeigefehler ist, doch wie kann ich diesen am besten finden. Nun ja das einzige was hilft ist die Suche. Nachdem mich der Begriff "shop"
an die richtige stelle geworfen haben können wir diese nun anpassen. Kleiner Tip hier am Rande, man kann das Spiel auch super debuggen. Den Ordner "Contents"
von Terraria in den "Bin\Debug\"
Ordner der Projekt-Umgebung schieben und schon kann das Spiel gestartet werden. In der Main.cs
ab Zeile 5586 Sehen wir folgenden Code:
if (Main.npcShop > 0) { if (Main.toolTip.value > 0) { string text2 = ""; int num15 = 0; int num16 = 0; int num17 = 0; int num18 = 0; int num19 = Main.toolTip.value * Main.toolTip.stack; if (!Main.toolTip.buy) { num19 = Main.toolTip.value / 5 * Main.toolTip.stack; } if (num19 < 1) { num19 = 1; } if (num19 >= 1000000) { num15 = num19 / 1000000; num19 -= num15 * 1000000; } if (num19 >= 10000) { num16 = num19 / 10000; num19 -= num16 * 10000; } if (num19 >= 100) { num17 = num19 / 100; num19 -= num17 * 100; } if (num19 >= 1) { num18 = num19; } if (num15 > 0) { object obj2 = text2; text2 = string.Concat(new object[] { obj2, num15, " ", Lang.inter[15] }); } if (num16 > 0) { object obj3 = text2; text2 = string.Concat(new object[] { obj3, num16, " ", Lang.inter[16] }); } if (num17 > 0) { object obj4 = text2; text2 = string.Concat(new object[] { obj4, num17, " ", Lang.inter[17] }); } if (num18 > 0) { object obj = text2; text2 = string.Concat(new object[] { obj, num18, " ", Lang.inter[18] }); } if (!Main.toolTip.buy) { array[num4] = Lang.tip[49] + " " + text2; } else { array[num4] = Lang.tip[50] + " " + text2; } num4++; num20 = (float)Main.mouseTextColor / 255f; if (num15 > 0) { color = new Color((int)((byte)(220f * num20)), (int)((byte)(220f * num20)), (int)((byte)(198f * num20)), (int)Main.mouseTextColor); } else { if (num16 > 0) { color = new Color((int)((byte)(224f * num20)), (int)((byte)(201f * num20)), (int)((byte)(92f * num20)), (int)Main.mouseTextColor); } else { if (num17 > 0) { color = new Color((int)((byte)(181f * num20)), (int)((byte)(192f * num20)), (int)((byte)(193f * num20)), (int)Main.mouseTextColor); } else { if (num18 > 0) { color = new Color((int)((byte)(246f * num20)), (int)((byte)(138f * num20)), (int)((byte)(96f * num20)), (int)Main.mouseTextColor); } } } } } else { num20 = (float)Main.mouseTextColor / 255f; array[num4] = Lang.tip[51]; num4++; color = new Color((int)((byte)(120f * num20)), (int)((byte)(120f * num20)), (int)((byte)(120f * num20)), (int)Main.mouseTextColor); } }
Sieht ersteinmal kompliziert aus, aber die Funktion berechnet Einfach nur, wie viel Platin-, Gold-, Silber- und Kupfermünzen benötigt werden und fügt die Strings aneinander. Leider werden sie nur zusammengefügt, ohne das berücksichtigt wird, wenn schon vorher Text in der Variable ist. Hier also der gefixte Code mit anderen Variablennamen zum besseren Verständnis:
if (Main.npcShop > 0) { if (Main.toolTip.value > 0) { string text2 = ""; int platin_muenze = 0; int gold_muenze = 0; int silber_muenze = 0; int kupfer_muenze = 0; int wert = Main.toolTip.value * Main.toolTip.stack; if (!Main.toolTip.buy) { wert = Main.toolTip.value / 5 * Main.toolTip.stack; } if (wert < 1) { wert = 1; } if (wert >= 1000000) { platin_muenze = wert / 1000000; wert -= platin_muenze * 1000000; } if (wert >= 10000) { gold_muenze = wert / 10000; wert -= gold_muenze * 10000; } if (wert >= 100) { silber_muenze = wert / 100; wert -= silber_muenze * 100; } if (wert >= 1) { kupfer_muenze = wert; } if (platin_muenze > 0) { text2 += platin_muenze + " " + Lang.inter[15]; } if (gold_muenze > 0) { text2 += (text2 != "") ? " " : ""; text2 += gold_muenze + " " + Lang.inter[16]; } if (silber_muenze > 0) { text2 += (text2 != "") ? " " : ""; text2 += silber_muenze + " " + Lang.inter[17]; } if (kupfer_muenze > 0) { text2 += (text2 != "") ? " " : ""; text2 += kupfer_muenze + " " + Lang.inter[18]; } if (!Main.toolTip.buy) { array[num4] = Lang.tip[49] + " " + text2; } else { array[num4] = Lang.tip[50] + " " + text2; } num4++; num20 = (float)Main.mouseTextColor / 255f; if (platin_muenze > 0) { color = new Color((int)((byte)(220f * num20)), (int)((byte)(220f * num20)), (int)((byte)(198f * num20)), (int)Main.mouseTextColor); } else { if (gold_muenze > 0) { color = new Color((int)((byte)(224f * num20)), (int)((byte)(201f * num20)), (int)((byte)(92f * num20)), (int)Main.mouseTextColor); } else { if (silber_muenze > 0) { color = new Color((int)((byte)(181f * num20)), (int)((byte)(192f * num20)), (int)((byte)(193f * num20)), (int)Main.mouseTextColor); } else { if (kupfer_muenze > 0) { color = new Color((int)((byte)(246f * num20)), (int)((byte)(138f * num20)), (int)((byte)(96f * num20)), (int)Main.mouseTextColor); } } } } } else { num20 = (float)Main.mouseTextColor / 255f; array[num4] = Lang.tip[51]; num4++; color = new Color((int)((byte)(120f * num20)), (int)((byte)(120f * num20)), (int)((byte)(120f * num20)), (int)Main.mouseTextColor); } }
Damit wäre dann die Ausgabe gefixt und wir haben eine schöne Ausgabe. Ich versuche nun den Bug-Nummer 3 zu beheben, weil ich die Lösung durch einen Zufall gefunden habe. Durch das herumspielen der Sprachen ist mir aufgefallen das der Bug in der englischen Version nicht vorhanden ist. Also hab ich wieder zurück auf deutsch gestellt und siehe da, der Bug war weg. Wer ein wenig länger das Bild anschaut bemerkt es vielleicht.
Was hat englischer Text in einer deutschen Version zu suchen. Genau! Das Spiel lädt zuerst alle englischen Sachen in den Speicher, danach wieder alle deutschen und eine Stelle wird nicht überschrieben. Schauen wir uns einmal die Lang.cs
an.
Lang.inter[54] = "Heilen"; Lang.tip[1] = "Keine Werte werden gewonnen";
Nun noch einmal mit dem Englischen vergleichen
Lang.inter[54] = "Heal"; Lang.tip[0] = "Equipped in social slot"; Lang.tip[1] = "No stats will be gained";
Wer hätte das Gedacht, da fehlt ne Zeile Code. Hier also die verbesserte Version:
Lang.inter[54] = "Heilen"; Lang.tip[0] = "Ausgeruestet im sozialen Slot"; // in dem Spiel gibts keine Sonderzeichen :P Lang.tip[1] = "Keine Werte werden gewonnen";
Kommen wir nun zum letzten Bug, der Nachschmiede Bug. Im englischen Reforge, also suchen wir den Code in der Main.cs
nach Reforge ab. Nun bin ich an folgende Stelle angekommen.
if (Main.mouseLeftRelease && Main.mouseLeft && Main.player[Main.myPlayer].BuyItem(value2)) { Main.reforgeItem.SetDefaults(Main.reforgeItem.name); //Setzt das Item neu Main.reforgeItem.Prefix(-2); Main.reforgeItem.position.X = Main.player[Main.myPlayer].position.X + (float)(Main.player[Main.myPlayer].width / 2) - (float)(Main.reforgeItem.width / 2); Main.reforgeItem.position.Y = Main.player[Main.myPlayer].position.Y + (float)(Main.player[Main.myPlayer].height / 2) - (float)(Main.reforgeItem.height / 2); ItemText.NewText(Main.reforgeItem, Main.reforgeItem.stack); Main.PlaySound(2, -1, -1, 37); }
Also schauen wir uns nun die SetDefaults
an. Da ich weiß das reforgeItem = new Item();
ist müssen wir an dieser Stelle in die Item.cs
schauen und hier die SetDefaults(string ItemName)
genauer anschauen:
public void SetDefaults(string ItemName) { this.name = ""; bool flag = false; if (ItemName == "Gold Pickaxe") { this.SetDefaults(1, false); this.color = new Color(210, 190, 0, 100); this.useTime = 17; this.pick = 55; this.useAnimation = 20; this.scale = 1.05f; this.damage = 6; this.value = 10000; this.toolTip = "Can mine Meteorite"; this.netID = -1; } else { if (ItemName == "Gold Broadsword") { this.SetDefaults(4, false); this.color = new Color(210, 190, 0, 100); this.useAnimation = 20; this.damage = 13; this.scale = 1.05f; this.value = 9000; this.netID = -2; } else { if (ItemName == "Gold Shortsword") { this.SetDefaults(6, false); this.color = new Color(210, 190, 0, 100); this.damage = 11; this.useAnimation = 11; this.scale = 0.95f; this.value = 7000; this.netID = -3; } else { if (ItemName == "Gold Axe") { this.SetDefaults(10, false); this.color = new Color(210, 190, 0, 100); this.useTime = 18; this.axe = 11; this.useAnimation = 26; this.scale = 1.15f; this.damage = 7; this.value = 8000; this.netID = -4; } else { if (ItemName == "Gold Hammer") { this.SetDefaults(7, false); this.color = new Color(210, 190, 0, 100); this.useAnimation = 28; this.useTime = 23; this.scale = 1.25f; this.damage = 9; this.hammer = 55; this.value = 8000; this.netID = -5; } else { if (ItemName == "Gold Bow") { this.SetDefaults(99, false); this.useAnimation = 26; this.useTime = 26; this.color = new Color(210, 190, 0, 100); this.damage = 11; this.value = 7000; this.netID = -6; } else { if (ItemName == "Silver Pickaxe") { this.SetDefaults(1, false); this.color = new Color(180, 180, 180, 100); this.useTime = 11; this.pick = 45; this.useAnimation = 19; this.scale = 1.05f; this.damage = 6; this.value = 5000; this.netID = -7; } else { if (ItemName == "Silver Broadsword") { this.SetDefaults(4, false); this.color = new Color(180, 180, 180, 100); this.useAnimation = 21; this.damage = 11; this.value = 4500; this.netID = -8; } else { if (ItemName == "Silver Shortsword") { this.SetDefaults(6, false); this.color = new Color(180, 180, 180, 100); this.damage = 9; this.useAnimation = 12; this.scale = 0.95f; this.value = 3500; this.netID = -9; } else { if (ItemName == "Silver Axe") { this.SetDefaults(10, false); this.color = new Color(180, 180, 180, 100); this.useTime = 18; this.axe = 10; this.useAnimation = 26; this.scale = 1.15f; this.damage = 6; this.value = 4000; this.netID = -10; } else { if (ItemName == "Silver Hammer") { this.SetDefaults(7, false); this.color = new Color(180, 180, 180, 100); this.useAnimation = 29; this.useTime = 19; this.scale = 1.25f; this.damage = 9; this.hammer = 45; this.value = 4000; this.netID = -11; } else { if (ItemName == "Silver Bow") { this.SetDefaults(99, false); this.useAnimation = 27; this.useTime = 27; this.color = new Color(180, 180, 180, 100); this.damage = 9; this.value = 3500; this.netID = -12; } else { if (ItemName == "Copper Pickaxe") { this.SetDefaults(1, false); this.color = new Color(180, 100, 45, 80); this.useTime = 15; this.pick = 35; this.useAnimation = 23; this.damage = 4; this.scale = 0.9f; this.tileBoost = -1; this.value = 500; this.netID = -13; } else { if (ItemName == "Copper Broadsword") { this.SetDefaults(4, false); this.color = new Color(180, 100, 45, 80); this.useAnimation = 23; this.damage = 8; this.value = 450; this.netID = -14; } else { if (ItemName == "Copper Shortsword") { this.SetDefaults(6, false); this.color = new Color(180, 100, 45, 80); this.damage = 5; this.useAnimation = 13; this.scale = 0.8f; this.value = 350; this.netID = -15; } else { if (ItemName == "Copper Axe") { this.SetDefaults(10, false); this.color = new Color(180, 100, 45, 80); this.useTime = 21; this.axe = 7; this.useAnimation = 30; this.scale = 1f; this.damage = 3; this.tileBoost = -1; this.value = 400; this.netID = -16; } else { if (ItemName == "Copper Hammer") { this.SetDefaults(7, false); this.color = new Color(180, 100, 45, 80); this.useAnimation = 33; this.useTime = 23; this.scale = 1.1f; this.damage = 4; this.hammer = 35; this.tileBoost = -1; this.value = 400; this.netID = -17; } else { if (ItemName == "Copper Bow") { this.SetDefaults(99, false); this.useAnimation = 29; this.useTime = 29; this.color = new Color(180, 100, 45, 80); this.damage = 6; this.value = 350; this.netID = -18; } else { if (ItemName == "Blue Phasesaber") { this.SetDefaults(198, false); this.damage = 41; this.scale = 1.15f; flag = true; this.autoReuse = true; this.useTurn = true; this.rare = 4; this.netID = -19; } else { if (ItemName == "Red Phasesaber") { this.SetDefaults(199, false); this.damage = 41; this.scale = 1.15f; flag = true; this.autoReuse = true; this.useTurn = true; this.rare = 4; this.netID = -20; } else { if (ItemName == "Green Phasesaber") { this.SetDefaults(200, false); this.damage = 41; this.scale = 1.15f; flag = true; this.autoReuse = true; this.useTurn = true; this.rare = 4; this.netID = -21; } else { if (ItemName == "Purple Phasesaber") { this.SetDefaults(201, false); this.damage = 41; this.scale = 1.15f; flag = true; this.autoReuse = true; this.useTurn = true; this.rare = 4; this.netID = -22; } else { if (ItemName == "White Phasesaber") { this.SetDefaults(202, false); this.damage = 41; this.scale = 1.15f; flag = true; this.autoReuse = true; this.useTurn = true; this.rare = 4; this.netID = -23; } else { if (ItemName == "Yellow Phasesaber") { this.SetDefaults(203, false); this.damage = 41; this.scale = 1.15f; flag = true; this.autoReuse = true; this.useTurn = true; this.rare = 4; this.netID = -24; } else { if (ItemName != "") { for (int i = 0; i < 604; i++) { if (Main.itemName[i] == ItemName) { this.SetDefaults(i, false); this.checkMat(); return; } } this.name = ""; this.stack = 0; this.type = 0; } } } } } } } } } } } } } } } } } } } } } } } } }
Tut mir Leid für den Augenkrebs, aber es ist nun mal richtig beschissener Code. Ich hoffe der Decompiler hat uns das eingebrockt! (*nicht das es wirklich so kacke programmiert wurde*) Hier müsste man doch glatt noch viel refactoring (schauen wo befindet sich doppelter Code und diesen in seperate Funktionen auslagern/zusammenfassen) betreiben, damit es wieder lesbarer und sinniger wird!
public void SetDefaults(string ItemName) { this.name = ""; bool flag = false; if (ItemName == Lang.itemName(-1)) { this.SetDefaults(1, false); this.color = new Color(210, 190, 0, 100); this.useTime = 17; this.pick = 55; this.useAnimation = 20; this.scale = 1.05f; this.damage = 6; this.value = 10000; this.toolTip = "Can mine Meteorite"; this.netID = -1; } else { if (ItemName == Lang.itemName(-2)) { this.SetDefaults(4, false); this.color = new Color(210, 190, 0, 100); this.useAnimation = 20; this.damage = 13; this.scale = 1.05f; this.value = 9000; this.netID = -2; } else { if (ItemName == Lang.itemName(-3)) { this.SetDefaults(6, false); this.color = new Color(210, 190, 0, 100); this.damage = 11; this.useAnimation = 11; this.scale = 0.95f; this.value = 7000; this.netID = -3; } else { if (ItemName == Lang.itemName(-4)) { this.SetDefaults(10, false); this.color = new Color(210, 190, 0, 100); this.useTime = 18; this.axe = 11; this.useAnimation = 26; this.scale = 1.15f; this.damage = 7; this.value = 8000; this.netID = -4; } else { if (ItemName == Lang.itemName(-5)) { this.SetDefaults(7, false); this.color = new Color(210, 190, 0, 100); this.useAnimation = 28; this.useTime = 23; this.scale = 1.25f; this.damage = 9; this.hammer = 55; this.value = 8000; this.netID = -5; } else { if (ItemName == Lang.itemName(-6)) { this.SetDefaults(99, false); this.useAnimation = 26; this.useTime = 26; this.color = new Color(210, 190, 0, 100); this.damage = 11; this.value = 7000; this.netID = -6; } else { if (ItemName == Lang.itemName(-7)) { this.SetDefaults(1, false); this.color = new Color(180, 180, 180, 100); this.useTime = 11; this.pick = 45; this.useAnimation = 19; this.scale = 1.05f; this.damage = 6; this.value = 5000; this.netID = -7; } else { if (ItemName == Lang.itemName(-8)) { this.SetDefaults(4, false); this.color = new Color(180, 180, 180, 100); this.useAnimation = 21; this.damage = 11; this.value = 4500; this.netID = -8; } else { if (ItemName == Lang.itemName(-9)) { this.SetDefaults(6, false); this.color = new Color(180, 180, 180, 100); this.damage = 9; this.useAnimation = 12; this.scale = 0.95f; this.value = 3500; this.netID = -9; } else { if (ItemName == Lang.itemName(-10)) { this.SetDefaults(10, false); this.color = new Color(180, 180, 180, 100); this.useTime = 18; this.axe = 10; this.useAnimation = 26; this.scale = 1.15f; this.damage = 6; this.value = 4000; this.netID = -10; } else { if (ItemName == Lang.itemName(-11)) { this.SetDefaults(7, false); this.color = new Color(180, 180, 180, 100); this.useAnimation = 29; this.useTime = 19; this.scale = 1.25f; this.damage = 9; this.hammer = 45; this.value = 4000; this.netID = -11; } else { if (ItemName == Lang.itemName(-12)) { this.SetDefaults(99, false); this.useAnimation = 27; this.useTime = 27; this.color = new Color(180, 180, 180, 100); this.damage = 9; this.value = 3500; this.netID = -12; } else { if (ItemName == Lang.itemName(-13)) { this.SetDefaults(1, false); this.color = new Color(180, 100, 45, 80); this.useTime = 15; this.pick = 35; this.useAnimation = 23; this.damage = 4; this.scale = 0.9f; this.tileBoost = -1; this.value = 500; this.netID = -13; } else { if (ItemName == Lang.itemName(-14)) { this.SetDefaults(4, false); this.color = new Color(180, 100, 45, 80); this.useAnimation = 23; this.damage = 8; this.value = 450; this.netID = -14; } else { if (ItemName == Lang.itemName(-15)) { this.SetDefaults(6, false); this.color = new Color(180, 100, 45, 80); this.damage = 5; this.useAnimation = 13; this.scale = 0.8f; this.value = 350; this.netID = -15; } else { if (ItemName == Lang.itemName(-16)) { this.SetDefaults(10, false); this.color = new Color(180, 100, 45, 80); this.useTime = 21; this.axe = 7; this.useAnimation = 30; this.scale = 1f; this.damage = 3; this.tileBoost = -1; this.value = 400; this.netID = -16; } else { if (ItemName == Lang.itemName(-17)) { this.SetDefaults(7, false); this.color = new Color(180, 100, 45, 80); this.useAnimation = 33; this.useTime = 23; this.scale = 1.1f; this.damage = 4; this.hammer = 35; this.tileBoost = -1; this.value = 400; this.netID = -17; } else { if (ItemName == Lang.itemName(-18)) { this.SetDefaults(99, false); this.useAnimation = 29; this.useTime = 29; this.color = new Color(180, 100, 45, 80); this.damage = 6; this.value = 350; this.netID = -18; } else { if (ItemName == Lang.itemName(-19)) { this.SetDefaults(198, false); this.damage = 41; this.scale = 1.15f; flag = true; this.autoReuse = true; this.useTurn = true; this.rare = 4; this.netID = -19; } else { if (ItemName == Lang.itemName(-20)) { this.SetDefaults(199, false); this.damage = 41; this.scale = 1.15f; flag = true; this.autoReuse = true; this.useTurn = true; this.rare = 4; this.netID = -20; } else { if (ItemName == Lang.itemName(-21)) { this.SetDefaults(200, false); this.damage = 41; this.scale = 1.15f; flag = true; this.autoReuse = true; this.useTurn = true; this.rare = 4; this.netID = -21; } else { if (ItemName == Lang.itemName(-22)) { this.SetDefaults(201, false); this.damage = 41; this.scale = 1.15f; flag = true; this.autoReuse = true; this.useTurn = true; this.rare = 4; this.netID = -22; } else { if (ItemName == Lang.itemName(-23)) { this.SetDefaults(202, false); this.damage = 41; this.scale = 1.15f; flag = true; this.autoReuse = true; this.useTurn = true; this.rare = 4; this.netID = -23; } else { if (ItemName == Lang.itemName(-24)) { this.SetDefaults(203, false); this.damage = 41; this.scale = 1.15f; flag = true; this.autoReuse = true; this.useTurn = true; this.rare = 4; this.netID = -24; } else { if (ItemName != "") { for (int i = 0; i < 604; i++) { if (Lang.itemName(i) == ItemName) { this.SetDefaults(i, false); this.checkMat(); return; } } this.name = ""; this.stack = 0; this.type = 0; } } } } } } } } } } } } } } } } } } } } } } } } }
Außerdem ist nun noch eine andere Stelle im Code dadurch falsch:
public void netDefaults(int type) { if (type < 0) { if (type == -1) { this.SetDefaults("Gold Pickaxe"); return; } if (type == -2) { this.SetDefaults("Gold Broadsword"); return; } if (type == -3) { this.SetDefaults("Gold Shortsword"); return; } if (type == -4) { this.SetDefaults("Gold Axe"); return; } if (type == -5) { this.SetDefaults("Gold Hammer"); return; } if (type == -6) { this.SetDefaults("Gold Bow"); return; } if (type == -7) { this.SetDefaults("Silver Pickaxe"); return; } if (type == -8) { this.SetDefaults("Silver Broadsword"); return; } if (type == -9) { this.SetDefaults("Silver Shortsword"); return; } if (type == -10) { this.SetDefaults("Silver Axe"); return; } if (type == -11) { this.SetDefaults("Silver Hammer"); return; } if (type == -12) { this.SetDefaults("Silver Bow"); return; } if (type == -13) { this.SetDefaults("Copper Pickaxe"); return; } if (type == -14) { this.SetDefaults("Copper Broadsword"); return; } if (type == -15) { this.SetDefaults("Copper Shortsword"); return; } if (type == -16) { this.SetDefaults("Copper Axe"); return; } if (type == -17) { this.SetDefaults("Copper Hammer"); return; } if (type == -18) { this.SetDefaults("Copper Bow"); return; } if (type == -19) { this.SetDefaults("Blue Phasesaber"); return; } if (type == -20) { this.SetDefaults("Red Phasesaber"); return; } if (type == -21) { this.SetDefaults("Green Phasesaber"); return; } if (type == -22) { this.SetDefaults("Purple Phasesaber"); return; } if (type == -23) { this.SetDefaults("White Phasesaber"); return; } if (type == -24) { this.SetDefaults("Yellow Phasesaber"); return; } }
Diesen Code müssen wir nun auch beheben. Zur Übersichtlichkeit hab ich es kürzer gemacht ;)
public void netDefaults(int type) { if (type < 0 && type >= -24) { this.SetDefaults(Lang.itemName(type)); return; } else { this.SetDefaults(type, false); } }
Der krönende Abschluss
Soviel dazu. Nun haben wir alle drei Bugs beseitigt, aber man könnte nun selber Mods für Terraria schreiben, aber erst einmal würde ich ein riesen Refactoring betreiben, damit der Code viel viel übersichtlicher wird. Eines werde ich noch machen! In der Main.cs findet man folgendes:
public static string versionNumber = "v1.1.2"; public static string versionNumber2 = "v1.1.2";
das ändere ich zu
public static string versionNumber = "v1.1.3 by TheVamp"; public static string versionNumber2 = "v1.1.3 by TheVamp";
nun weiß ich das es 1.1.3 ist :D und es steht auch wunderschön da. Ich hoffe ihr werdet auch so viel Spaß haben und vielleicht auch ein paar Mods machen.
Viel Spaß wünscht,
TheVamp
Nachtrag: Einfach die Terraria.exe ersetzen und schon ist das Spiel gepatched. Wer sehen will, was für ein Chaos teilweise in dem Source Code ist, der kann sich ihn hier runterladen.
Nachtrag 2: Der Laden Bug ist nun behoben. Ich werde mit dem Refactoring beginnen und bei Zeiten den Source Code aktualisieren. Have Fun.
Download: Terraria.exe 1.1.3 (6181 Downloads)
Download: Terraria - Source Code Patched (6125 Downloads)
Greetz TheVamp
@TheVamp – vielen Dank für die schnelle Reaktion. Ich muss zugeben, ich habe nicht mit so einen schnellen Reaktion gerechnet. Und weil ich ein ungeduldiger Mensch bin, habe ich mich (mit deiner wunderbaren Anleitung hier) selbst ans neu Bauen deines Patches gewagt.
Habe diesen auch, mit zusätzlichen Änderungen, in einem Forum veröffentlicht. Ich hoffe dies ist für Dich in Ordnung. Du bist natürlich auch namentlich mehrfach erwähnt und deinen Blog hier habe ich ebenfalls verlinkt. Wie gesagt, ich hoffe das ist OK für Dich. Hatte nicht damit gerechnet das Du so schnell reagierst.
Gruß, Parley
PS: Hier noch der Link zum Thread, falls Du an den dortigen Reaktionen zu deinem Werk interessiert bist.
http://www.terrariaforum.de/index.php?page=Thread&threadID=153
Danke, hab es wieder angepasst ;)
Leider ist der Download inzwischen wohl nicht mehr erreichbar. Führt nur zu einem „Not found..“. Kann man den vllt. noch einmal neu hochladen? Würde mich sehr drüber freuen. Endlich Terraria wieder auf Deutsch spielen.
Beste Grüße.
Vielen herzlichen Dank erstmall.
Ich habe das Problem wen ich etwas verkaufen will wird bei mir nicht der ganze Preis angezeigt sondern nur wie viel Kupfercoins ich dafür bekomme. Were nett wenn du mal nachschauen könntest an was das liegt den ich bin nicht so gut in .exe ich bin eher der shell Tüp.
Es könnte sein das Steam das Spiel neu lädt, da das Spiel verändert ist. Am besten eine neue Verknüpfung direkt zur exe machen. Ansonsten einfach ausprobieren ;)
Ich wollte fragen, ob das spiel nach dem patch immernoch bei steam bleibt oder sich da was ändert.
Hallo
könntest du auch neue monster oder solche sachen reinimpleminieren?
du scheinst echt alles zu können :D
Vielen Dank,
das du dich nochmal drum gekümmert hast, das die einigen Items, die vorher bei deinen Patch dann verschwunden waren wieder da sind bei den Update!
Das war ein Problem, besonders bei einen neuanfang, da Kupferspitzhacke und Axt fehlten! ;)
Vielen Dank für den Bug Fix!
Ich hab den Shop Bug behoben. In der Chest.cs sind noch ein paar Items per englischen Namen konfiguriert worden. Nun werden sie per eingestellte Sprache konfiguriert. Have Fun
Und berichtet weiter von Bugs und erzählt euren Freunden davon. Verbreitet meinen Patch :D das Feedback motiviert mich weiter zu machen und jeden Bug auszumerzen ;)
Jap. Hab das gleiche Problem mit dem Ladeninhalt. Aber immerhin kann ich jetzt nach bedarf zwischen den Versionen switchen. :D
Wäre echt super, wenn du dienen kleinen Fehler noch beheben könntest, da ich das selbst bestimmt nicht hinkriegen würde…
Danke dir! =)
Danke für diese gefixte Version allerdings ist mir auch ein weiterer Bug aufgefallen, denn manche Läden sind wie leer gefegt z.b vom demolitionist.