Inventory-Position ermitteln
Inventory-Position ermitteln
Jetzt gibt's im AGS 2.7 zwar die Möglichkeit, Inventar-Objekte an einer bestimmten Position einzufügen. Aber wie kann ich die Position erstmal ermitteln?
wenn ich z.B. den Inhalt eines Umschlags direkt hinter dem Umschlag einfügen will, muß ich ja erstmal die Position des Umschlags kennen.
wenn ich z.B. den Inhalt eines Umschlags direkt hinter dem Umschlag einfügen will, muß ich ja erstmal die Position des Umschlags kennen.
Das ist leider nicht ganz so einfach.
Hier ist ein (recht universell gehaltener) Lösungsvorschlag:
Hier ist ein (recht universell gehaltener) Lösungsvorschlag:
Code: Alles auswählen
// Interaktion für: Benutze Messer mit Umschlag
GUIControl *thecontrol = GUIControl.GetAtScreenXY(mouse.x, mouse.y); // über welchem InvWindow ist der Mauszeiger?
int mousex = mouse.x - (thecontrol.AsInvWindow.OwningGUI.X + thecontrol.AsInvWindow.X);
int mousey = mouse.y - (thecontrol.AsInvWindow.OwningGUI.Y + thecontrol.AsInvWindow.Y); // seperate Variablen um folgende Zeile zu kürzen (300 Zeichen Limit)
int umschlagindex = thecontrol.AsInvWindow.TopItem + (mousex / thecontrol.AsInvWindow.ItemWidth) + ((mousey / thecontrol.AsInvWindow.ItemHeight) * thecontrol.AsInvWindow.ItemsPerRow); // ermittle Index des Umschlages über die Mausposition
if (thecontrol.AsInvWindow.CharacterToUse == null) player.AddInventory(iUmschlaginhalt, umschlagindex + 1); // wenn dem InvWindow kein anderer Charakter zugewiesen ist, gib den Umschlaginhalt dem Spielercharakter
else thecontrol.AsInvWindow.CharacterToUse.AddInventory(iUmschlaginhalt, umschlagindex + 1); // wenn dem InvWindow ein anderer Charakter zugewiesen ist, gib diesem den Umschlaginhalt
- KhrisMUC
- Adventure-Gott
- Beiträge: 4674
- Registriert: 14.03.2005, 00:55
- Wohnort: München
@strazer: Wow, das schüttelst Du mal eben so aus dem Ärmel?
Gibt es eigentlich irgendwo im helpfile eine Liste der verfügbaren Pointertypen?
Und wie genau sieht die Syntax aus, wenn ich z.B. der unten genannten Funktion einen Character als Argument übergeben will?
Hier wäre noch eine Lösung:
Anfang des global scripts:
Script header:(Wenn der Inhalt auftaucht, nachdem man mit dem Umschlag im Inventar interagiert hat, kannst Du die im- und export-Zeilen weglassen.)
Jetzt musst Du im Script statt cEgo.AddInventory(iInhalt); einfach AddInhaltToInv(); schreiben.
Sollte auf blöd funktionieren.
Gibt es eigentlich irgendwo im helpfile eine Liste der verfügbaren Pointertypen?
Und wie genau sieht die Syntax aus, wenn ich z.B. der unten genannten Funktion einen Character als Argument übergeben will?
Hier wäre noch eine Lösung:
Anfang des global scripts:
Code: Alles auswählen
function AddInhaltToInv() {
int c=0;
while(c<invMain.ItemCount) {
if (invMain.ItemAtIndex[c]==iUmschlag) {
cEgo.AddInventory(iInhalt, c+1);
c=invMain.ItemCount;
}
c++;
}
}
export AddInhaltToInv();
Code: Alles auswählen
import AddInhaltToInv();
Jetzt musst Du im Script statt cEgo.AddInventory(iInhalt); einfach AddInhaltToInv(); schreiben.
Sollte auf blöd funktionieren.
Zuletzt geändert von KhrisMUC am 20.05.2005, 03:10, insgesamt 2-mal geändert.
Use gopher repellent on funny little man
Sehr gute Idee!
Ich habe den obigen Code abgewandelt aus meinem Test-Spiel übernommen. Ich wollte dass es auch funktioniert, wenn "Display multiple inventory items multiple times" aktiviert ist.
Bei deinem Code wird das Item nach dem ersten gefundenen Item hinzugefügt, was für die allermeisten Spiele natürlich völlig ok ist. Es ist sicherlich die einfachere Methode.
Ich habe den obigen Code abgewandelt aus meinem Test-Spiel übernommen. Ich wollte dass es auch funktioniert, wenn "Display multiple inventory items multiple times" aktiviert ist.
Bei deinem Code wird das Item nach dem ersten gefundenen Item hinzugefügt, was für die allermeisten Spiele natürlich völlig ok ist. Es ist sicherlich die einfachere Methode.
Pointer übergibt man z.B. so:Und wie genau sieht die Syntax aus, wenn ich z.B. der unten genannten Funktion einen Character als Argument übergeben will?
Code: Alles auswählen
function AddInhaltToInv(Character *thecharacter) {
//...
thecharacter.AddInventory(iInhalt, c+1);
//...
}
- KhrisMUC
- Adventure-Gott
- Beiträge: 4674
- Registriert: 14.03.2005, 00:55
- Wohnort: München
Also kann man sagen:
Wenn eine Funktion der Form A.B(); bzw. ein Property der Form A.B() existiert, kann man im Normalfall einen Pointer des Typs A verwenden.
Richtig?
Und wegen dem Stern:
Soweit ich es verstanden habe, taucht er im Sourcecode nur bei der Deklaration einer Referenz auf, also Pointertyp *Name, korrekt?
Wenn eine Funktion der Form A.B(); bzw. ein Property der Form A.B() existiert, kann man im Normalfall einen Pointer des Typs A verwenden.
Richtig?
Und wegen dem Stern:
Soweit ich es verstanden habe, taucht er im Sourcecode nur bei der Deklaration einer Referenz auf, also Pointertyp *Name, korrekt?
Use gopher repellent on funny little man
Ich meinte natürlich die Funktionsbeschreibungen in der AGS-Hilfe, etwas missverständlich ausgedrückt.Je nachdem, was man referenzieren möchte steht es ja meistens in den Funktionen:
Richtig.Wenn eine Funktion der Form A.B(); bzw. ein Property der Form A.B() existiert, kann man im Normalfall einen Pointer des Typs A verwenden. Richtig?
Richtig.Und wegen dem Stern:
Soweit ich es verstanden habe, taucht er im Sourcecode nur bei der Deklaration einer Referenz auf, also Pointertyp *Name, korrekt?
Vielen Dank für die Tips. Werd mich nachher ans Ausprobieren machen.
Wenn ich es richtig verstanden habe, funktioniert die Sache wohl nur mit dem aktiven Player, oder? Wenn ich also X spiele, und Y den Umschlag öffnet, geht's nicht, weil ItemAtIndex auf das Inventory von X und nicht von Y zugreift?
Und ich hätt noch eine Frage:
Ein Item an eine bestimmte Position zu adden, geht ja nur mit der objektorientierten Variante character.AddInventory(iFackel, pos), nicht wahr?
Wenn ich aber nur die Nummer des Items weiß (z.B. invnr) und nicht das Item selber (iFackel), kann ich normalerweise nur die alte Variante mit AddInventoryToCharacter(character, invnr) benutzen, wo ich keine Zielposition angeben kann.
Existiert irgendeine Möglichkeit, das Objekt zu ermitteln, wenn ich nur dessen Nummer habe? (quasi Umkehrfunktion zu objekt.ID)
Wenn ich es richtig verstanden habe, funktioniert die Sache wohl nur mit dem aktiven Player, oder? Wenn ich also X spiele, und Y den Umschlag öffnet, geht's nicht, weil ItemAtIndex auf das Inventory von X und nicht von Y zugreift?
Und ich hätt noch eine Frage:
Ein Item an eine bestimmte Position zu adden, geht ja nur mit der objektorientierten Variante character.AddInventory(iFackel, pos), nicht wahr?
Wenn ich aber nur die Nummer des Items weiß (z.B. invnr) und nicht das Item selber (iFackel), kann ich normalerweise nur die alte Variante mit AddInventoryToCharacter(character, invnr) benutzen, wo ich keine Zielposition angeben kann.
Existiert irgendeine Möglichkeit, das Objekt zu ermitteln, wenn ich nur dessen Nummer habe? (quasi Umkehrfunktion zu objekt.ID)
- KhrisMUC
- Adventure-Gott
- Beiträge: 4674
- Registriert: 14.03.2005, 00:55
- Wohnort: München
Ich wollte es noch einbauen, hab's vergessen, hier die erweiterte Funktion:
Ich hab keine Ahnung, ob das funktioniert!
Code: Alles auswählen
function AddInhaltToInv(Character *other) {
InvWindow *invOther;
invOther.CharacterToUse=other;
int c=0;
while(c<invOther.ItemCount) {
if (invOther.ItemAtIndex[c]==iUmschlag) {
other.AddInventory(iInhalt, c+1);
c=invOther.ItemCount;
}
c++;
}
}
Use gopher repellent on funny little man
Ja.Ein Item an eine bestimmte Position zu adden, geht ja nur mit der objektorientierten Variante character.AddInventory(iFackel, pos), nicht wahr?
Dazu sind die global Arrays da (zu finden im Handbuch -> Scripting -> Upgrading to AGS v2.7):Existiert irgendeine Möglichkeit, das Objekt zu ermitteln, wenn ich nur dessen Nummer habe? (quasi Umkehrfunktion zu objekt.ID)
Character.AddInventory(inventory[invnr]);
khrismuc:
Code: Alles auswählen
//...
InvWindow *invOther;
invOther.CharacterToUse=other;
//...
Du deklarierst den Pointer invOther, er verweist aber auf kein InvWindow (ist also null).
Wenn aber ein InvWindow mit dem Namen invOther bereits existiert, brauchst du keinen Pointer zu deklarieren.
Da man, glaube ich, mehrere InvWindows haben kann, die alle das Inventar desselben Charakters zeigen, kann man nicht so einfach von einem Charakter auf ein bestimmtes InvWindow schliessen.
Man könnte vielleicht alle InvWindows durchgehen und gucken, ob es den Charakter als Quelle benutzt, das ist aber ziemlicher Murks.
Es ist wahrscheinlich einfacher, man nutzt das Haupt-InvWindow kurz für diese Funktion (das wollte khrismuc glaube ich tun):
Code: Alles auswählen
function AddInhaltToInv(Character *dercharakter) {
Character *altercharakter = dashauptinvwindow.CharacterToUse; // speichere Charakter, den das InvWindow momentan benutzt
dashauptinvwindow.CharacterToUse = dercharakter; // benutze Inventar des übergebenen Charakters
int c = 0;
while(c < dashauptinvwindow.ItemCount) {
if (dashauptinvwindow.ItemAtIndex[c] == iUmschlag) {
dercharakter.AddInventory(iInhalt, c+1);
c = dashauptinvwindow.ItemCount;
}
c++;
}
dashauptinvwindow.CharacterToUse = altercharakter; // benutze wieder Inventar des vorherigen Charakters
}
- KhrisMUC
- Adventure-Gott
- Beiträge: 4674
- Registriert: 14.03.2005, 00:55
- Wohnort: München
Ich wollte erst Deine Lösung posten, hab aber befürchtet, dass man am Bildschirm sehen kann, wie das Inventar kurz wechselt. Dann fiel mir die andere Methode ein, ich hab aber schon befürchtet, dass das nicht hinhaut.
Meine vage Hoffnung war, dass durch das Setzen von CharacterToUse auch ItemCount usw. gesetzt werden. Is natürlich schmarrn.
Meine vage Hoffnung war, dass durch das Setzen von CharacterToUse auch ItemCount usw. gesetzt werden. Is natürlich schmarrn.
Use gopher repellent on funny little man