Inventory-Position ermitteln

Fragen zu "Adventure Game Studio"? Hier rein!
Antworten
Hüter des Heiligen Krans

Inventory-Position ermitteln

Beitrag von Hüter des Heiligen Krans »

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.
strazer

Beitrag von strazer »

Das ist leider nicht ganz so einfach.

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

Benutzeravatar
KhrisMUC
Adventure-Gott
Adventure-Gott
Beiträge: 4674
Registriert: 14.03.2005, 00:55
Wohnort: München

Beitrag von KhrisMUC »

@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:

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();
Script header:

Code: Alles auswählen

import AddInhaltToInv();
(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.
Zuletzt geändert von KhrisMUC am 20.05.2005, 03:10, insgesamt 2-mal geändert.
Use gopher repellent on funny little man
strazer

Beitrag von strazer »

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.
Und wie genau sieht die Syntax aus, wenn ich z.B. der unten genannten Funktion einen Character als Argument übergeben will?
Pointer übergibt man z.B. so:

Code: Alles auswählen

function AddInhaltToInv(Character *thecharacter) {
  //...
  thecharacter.AddInventory(iInhalt, c+1); 
  //...
}
strazer

Beitrag von strazer »

Gibt es eigentlich irgendwo im helpfile eine Liste der verfügbaren Pointertypen?
Hm, ich glaube nicht an zentraler Stelle. Je nachdem, was man referenzieren möchte steht es ja meistens in den Funktionen:

Character.ChangeRoom(....
Benutzeravatar
KhrisMUC
Adventure-Gott
Adventure-Gott
Beiträge: 4674
Registriert: 14.03.2005, 00:55
Wohnort: München

Beitrag von KhrisMUC »

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?
Use gopher repellent on funny little man
strazer

Beitrag von strazer »

Je nachdem, was man referenzieren möchte steht es ja meistens in den Funktionen:
Ich meinte natürlich die Funktionsbeschreibungen in der AGS-Hilfe, etwas missverständlich ausgedrückt.
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?
Richtig.
Hüter des Heiligen Krans

Beitrag von Hüter des Heiligen Krans »

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: :oops: :D
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)
Benutzeravatar
KhrisMUC
Adventure-Gott
Adventure-Gott
Beiträge: 4674
Registriert: 14.03.2005, 00:55
Wohnort: München

Beitrag von KhrisMUC »

Ich wollte es noch einbauen, hab's vergessen, hier die erweiterte Funktion:

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++;
  }
}
Ich hab keine Ahnung, ob das funktioniert!
Use gopher repellent on funny little man
strazer

Beitrag von strazer »

Ein Item an eine bestimmte Position zu adden, geht ja nur mit der objektorientierten Variante character.AddInventory(iFackel, pos), nicht wahr?
Ja.
Existiert irgendeine Möglichkeit, das Objekt zu ermitteln, wenn ich nur dessen Nummer habe? (quasi Umkehrfunktion zu objekt.ID)
Dazu sind die global Arrays da (zu finden im Handbuch -> Scripting -> Upgrading to AGS v2.7):

Character.AddInventory(inventory[invnr]);

khrismuc:

Code: Alles auswählen

  //...
  InvWindow *invOther;
  invOther.CharacterToUse=other;
  //...
Das funktioniert nicht.
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
}
Benutzeravatar
KhrisMUC
Adventure-Gott
Adventure-Gott
Beiträge: 4674
Registriert: 14.03.2005, 00:55
Wohnort: München

Beitrag von KhrisMUC »

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.
Use gopher repellent on funny little man
Hüter des Heiligen Krans

Beitrag von Hüter des Heiligen Krans »

strazer hat geschrieben: Character.AddInventory(inventory[invnr]);
Manchmal sieht man den Wald vor Bäumen nicht :D

Jedenfalls Danke euch beiden.
Antworten