Ja ich nutze VS 2010 Express
Aber irgendwie funzt das bei mir nicht so wie du das beschreibst...
Ja ich nutze VS 2010 Express
Aber irgendwie funzt das bei mir nicht so wie du das beschreibst...
Tick tock goes the clock...
Also:
Schritt 1: Erstellen einer Debug-DLL
Schritt 2: Setzen von Haltepunkten (zu Beginn gerne reichlich, die können ja nachher sukzessive deaktiviert oder gelöscht werden)
Schritt 3: Ersetzen der normalen DLL mit der Debug-DLL
Schritt 4: Starten von Civ4
Schritt 5: in VS2010: Anhängen an den Prozess Civilization4.exe, oder wie immer die bei Civ4 dann heißen mag (ich spiele halt Colonization).
Nun sollte das Programm irgendwann bei einem der gesetzten Haltepunkte stehenbleiben. Dann kannst du mal über die Variablen in den Zeilen oberhalb des Haltepunktes fahren, die sollten dann nämlich mit Werten schon versorgt worden sein. Am rechten Rand des kleinen aufploppenden Fensterchens siehst du die vorher erwähnte "Reisszwecke".
Jetzt hab ich Volltrottel das Save mit dem Endlosturn überschrieben
Damit hat sich die ganze Sache erstmal erledigt. Für den Fall dass ich noch einen bekomme, probiere ichs nochmal mit dem Debuggen.
Tick tock goes the clock...
Hast du das Save stink nomral genannt? Sowas bezeichnet man so individuel, dass sowas garnicht passieren kann und man genau weiß, warum es das Save gibt.
Doch schon. Das ganze lief wie folgt ab:
Endlosturn unter einem speziellen Namen abgespeichert.
Dann hatte ich Lust auf ne normale Partie (soll neben dem modden auch mal vorkommen )
Damit waren die Autosaves schon mal weg.
Anschließend hab ich die Partie abgespeichert. Aus reiner Gewohnheit unter dem Namen, der als erstes in der Liste ganz oben stand. Also den Endlosturn. 2 Millisekunden danach hab ich dann schon gem,erkt wie bescheuert das von mir war
Tick tock goes the clock...
Dann speichere spezielle Save besser an einen Speziellen Ort ab. Der Ordner kannst du ja einfach ingame auswählen.
Ich habe hier eine Funktion f aus dem SDK, welche von verschiedenen Stellen in der Exe aufgerufen wird. Kann man irgendwie auf den Aufruf-Stack zugreifen, um zu unterscheiden welche Funktion/Position f aufgerufen hat?
Anders formuliert, bei einer Verschachtelung g(f()) und h(f()) will ich in f wissen ob g oder h genutzt wurde.
Bem.: Evtl. ist es so, dass g oder h selber im SDK liegt. Dann könnte ich ein Flag setzen. Muss ich aber noch untersuchen.
Ah, ich habe was. Da bei allen die Exe gleich ist, sollten doch auch die Pointer konstant sein?!
Code:void ** puEBP = NULL; __asm { mov puEBP, ebp }; void * pvReturn = puEBP[1]; // this is the caller of my function puEBP = (void**)puEBP[0]; // walk back to the previous frame void * pvReturn2 = puEBP[1]; // this is the caller's caller puEBP = (void**)puEBP[0]; // walk back to the previous frame void * pvReturn3 = puEBP[1]; // this is the caller's caller puEBP = (void**)puEBP[0]; // walk back to the previous frame void * pvReturn4 = puEBP[1]; // this is the caller's caller
Pointer sind iirc im Allgemeinen ungleich, auch bei zwei verschiedenen Aufrufen der selben Funktion.
Ich habe eine generelle Frage...
Ich habe eine Struktur angelegt
Die Elemente dieser Struktur sollen in der folgenden Funktion initialisiert werden:Code:struct CBM_CombatDetails { ... // from here on attack values int iBaseCombatStrAtt; ... };
Das funktioniert so weit wohl auch.Code:void CvUnit::initCombatDetails(CBM_CombatDetails* pCombatDetails) { if (pCombatDetails != NULL) { pCombatDetails->iBaseCombatStrAtt = 0; ... ... } }
Die Frage ist, kann ich das auch erreichen (und wenn ja, wie?), ohne dass ich Parameter übergeben muss?
Der Funktionskopf sollte dann so aussehen:
void CvUnit::initCombatDetails()
aber die Funktion soll wissen, dass es sich um die Struktur CBM_CombatDetails handeln wird.
Nachtrag:
Ich versuche gerade, das gewünschte Ergebnis auf folgende Weise zu erreichen:
erhalte dabei aber unter pCombatDetails.iBaseCombatStrAtt = 0; eine rote Linie mit dem Hinweis: "Error: Der Ausdruck muss einen Zeigertyp aufweisen"Code:void CvUnit::initCombatDetails() { CBM_CombatDetails pCombatDetails; pCombatDetails.iBaseCombatStrAtt = 0; }
Obige Zeile hat sich erledigt. Ich hatte irgendwo vergessen, eine Klammer } zu setzen...
Jetzt zeigt mir zumindest Intellisense keine Fehler mehr an.
Geändert von Commander Bello (20. Oktober 2014 um 20:52 Uhr)
Die Struktur (eher Strukturdeklaration) CBM_CombatDetails* pCombatDetails ist ja erst einmal nur eine Schablone. Du musst daher auch noch eine Variable mit diesem Typ definieren.
Gehen wir von dem Fall aus, dass du nur eine temporäre Variable benötigtst. Dann könntest du beispielsweise CvUnit ergänzen um
static CBM_CombatDetails combatDetails; // Achtung, kein Pointer. Es soll ja Speicher allokiert werden.
Auf diese Variable könntest du dann in deiner Initialisierungs-Funktion zugreifen:
CvUnit.combatDetails.xyz = 1;
Dazu aber gleich zwei Warnungen:
1. Damit hast du programmweit nur eine einzige Instanz. Alle Einheiten (CvUnit) greifen dann auf die gleichen Werte zu! (Aber ich glaube, dass du ja genau das haben wolltest.)
2. Ich will sie jetzt nicht auflisten, aber es hat eine Reihe von Nachteilen, wenn man statische Variablen benutzt. Man muss immer genau abwägen und nur einsetzen, wenn man genau die Eigenschaften braucht, die nur statische Variablen haben.
Hilfe. Ihr sprecht mit mir!
D.h., ihr sprecht mit einem sehr, sehr Ahnungslosen.
Kurz gesagt, möchte ich folgendes tun:
In einer Funktion CvUnit::CBM_CombatStr(const CvUnit* pAttacker, const CvUnit* pDefender, const CvPlot* pPlot, CBM_CombatDetails* pCombatDetails) ermittle ich zentral für jeweils pAttacker und pDefender alle Werte, die für die Stärkeberechnung von kämpfenden Einheiten notwendig sind (Basisstärke, "Gesundheit", Verteidigungswerte fürs Gelände, usw.).
(Hintergrund: die ursprüngliche Funktion maxCombatStr(...) wird nämlich für die Kampfberechnung bis zu 6mal in Folge aufgerufen)
Diese Werte speichere ich in den Elementen der Struktur CBM_CombatDetails ab, um nachfolgend in den Funktionen zur eigentlichen Kampfberechnung darauf zugreifen zu können.
Es werden aber nicht zwingend alle Elemente von CBM_CombatDetails pro Stärkeberechnung ermittelt, mit anderen Worten, es könnten Werte aus vorhergehenden Berechnung darin noch enthalten sein (genauere Erläuterungen mögen mir erspart bleiben, weil sonst das gesamte Kampfsystem besprochen werden müsste).
Um das zu vermeiden, möchte ich tatsächlich in der neuen Funktion initCombatDetails() alle Elemente von CBM_CombatDetails initialisieren.
Das sind meine Absichten.
Was du mit "Konstruktor" meinst, ist mir schon nur nebelhaft klar und wie es umzusetzen wäre, liegt z.Zt. sicherlich jenseits meines Horizontes.
Es geht schlicht um die Initialisierung von CBM_CombatDetails um nachfolgend die Elemente (d.h., deren Werte) innerhalb der Kampfberechnungen nutzen zu können.
Einfach mal ein Beispiel was ich meine:
Mögliche Anwendung:Code:struct Data { int x; int y; Data() { // Standardkonstruktor x = 0; y = 0; } Data(int a, int b) { // Konstruktor mit Parametern x = a; y = b; } };
Code:Data d1; // Standardkonstruktor wird aufgerufen Data d2(1, 2) // Der Konstruktor mit entsprechenden Parametern wird aufgerufen