Autor Thema: Kritischer GUI-Bug in den AGS-3-Starterpacks  (Gelesen 2010 mal)

Cone Arex

  • Mod
  • alter Tentakel
  • **
  • Beiträge: 2305
  • Geschlecht: Männlich
  • Skandal-Entwickler und Idiot
    • Profil anzeigen
    • Conequest
Kritischer GUI-Bug in den AGS-3-Starterpacks
« am: 11. August 2014, 12:20:26 »
Wenn man gMaingui.Visible = false setzt, crasht das Spiel wenn das Inventory nach oben gescrollt werden kann, also mindestens 9 Gegenstände hat und man auf der zweiten Seite ist.

AGS verweist auf eine Nullpointer-Referenz in diesem Code in der repeatedley_execute()-Funktion des Global Scripts:
[ags]if (invItem.ID < 0)
gMainInventory.ScrollUp();[/ags]

Getestet in den Bernard- und Kevin-SPs.
Ich kenne den Code vom Global Script leider so gut wie gar nicht und kann es daher auch nicht selbst beheben.

EDIT: Ich bin ein solcher Vollspast. SEKUNDEN nach dem Post habe ich ein Fix gefunden: Den obigen Code in einen if-Block packen und abfragen, ob gMaingui sichtbar ist. Falls jemand eine bessere bzw. saubere Methode hat, immer her damit.
« Letzte Änderung: 11. August 2014, 12:27:08 von ConeRX »


Folge mir auf X und itch.io

Kiwa

  • volljähriger Tentakel
  • *****
  • Beiträge: 779
  • Geschlecht: Männlich
    • Profil anzeigen
Re: Kritischer GUI-Bug in den AGS-3-Starterpacks
« Antwort #1 am: 11. August 2014, 18:29:59 »
Ich hatte beim Mansion-SP (AGS 3.2.1) auch mal einen Bug der mit dem Inventar zusammen hing. Es wurden die Scrollpfeile immer angezeigt, auch wenn das Inventar vorher völlig leer geräumt wurde (weil der Character all sein Zeug verloren hat). Wenn man dann ein neues Item bekam wurde es nicht direkt angezeigt sondern man musste erst im sonst völlig leerem Inventory einmal hochscrollen. Und am Ende des Spiels stürzte AGS ab und AGS mekerte ebenfalls über eine Nullpointer-Referenz im Zusammenhang mit dem Inventar.

Gelöst habe ich es mit der freundlichen Unterstützung eines Community-Mitglieds welcher mir folgenden Code gab. Man muss einen Teil der repeatedley_execute()-Funktion durch diesen Code ersetzen.

[ags]
InvWindow *invMain = gMainInventory;
  if (invMain.ItemAtIndex[0] != null)
  {
    if (gMainInventory.TopItem != 0)
    {
      // if inventory can scroll up
      int visible_items = (invMain.Width / invMain.ItemWidth) * (invMain.Height / invMain.ItemHeight);
      if (invMain.ItemCount > visible_items) gMainInvUp.NormalGraphic = invUparrowONsprite;
 
      InventoryItem *invItem = InventoryItem.GetAtScreenXY(180, 190);
      if (invItem == null)
        gMainInventory.ScrollUp();
    }
    else
      gMainInvUp.NormalGraphic = invUparrowOFFsprite;
  }
  else gMainInvUp.NormalGraphic = invUparrowOFFsprite;
[/ags]

Danach sieht die neue GESAMTE repeatedley_execute()-Funktion wie folgt aus:

[ags]
function repeatedly_execute ()
{
   DisplaySpeechQ_RE(); // place it before any other script code in rep. exec.
  
  if (IsGamePaused () != 1)
  {
    CheckTimers ();
      InventoryItem *invAt = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
    // --- for the MovePlayer function ---
    if (GScancelable == 1)
    {
      GScancelable = 0;
      if ( null == invAt ) on_mouse_click (eMouseLeft);
      else on_mouse_click (eMouseLeftInv);
    }
    else if (GScancelable == 2)
    {
      GScancelable = 0;
      CheckDefaultAction ();
      if ( null == invAt ) on_mouse_click (eMouseRight);
      else on_mouse_click (eMouseRightInv);
    }
    CheckDefaultAction ();
    UpdateActionBar ();
  }
  // change the arrows in the inventory to show if you
  // can scroll the inventory:
   //readonly InventoryItem* InvWindow.ItemAtIndex[];

  InvWindow *invMain = gMainInventory;
  if (invMain.ItemAtIndex[0] != null)
  {
    if (gMainInventory.TopItem != 0)
    {
      // if inventory can scroll up
      int visible_items = (invMain.Width / invMain.ItemWidth) * (invMain.Height / invMain.ItemHeight);
      if (invMain.ItemCount > visible_items) gMainInvUp.NormalGraphic = invUparrowONsprite;
 
      InventoryItem *invItem = InventoryItem.GetAtScreenXY(180, 190);
      if (invItem == null)
        gMainInventory.ScrollUp();
    }
    else
      gMainInvUp.NormalGraphic = invUparrowOFFsprite;
  }
  else gMainInvUp.NormalGraphic = invUparrowOFFsprite;
 
  if ((gMainInventory.TopItem + (gMainInventory.ItemsPerRow * gMainInventory.RowCount)) < gMainInventory.ItemCount)
    gMainInvDown.NormalGraphic = invDownarrowONsprite;
  else
    gMainInvDown.NormalGraphic = invDownarrowOFFsprite;
   
}
[/ags]

Vor dem beenden des Spiels habe ich das Inventar mit folgendem Code zur Sicherheit nochmal komplett leer geräumt (da GUI und Inventar sowieso ausgeblendet waren merkt es keiner):

[ags]
int i = 1;
while (i <= Game.InventoryItemCount) {
    player.InventoryQuantity = 0;
    i++;
}
UpdateInventory();
[/ags]

So konnte ich gut die besagten Probleme lösen. Welche Lösung nun besser ist muss jeder selber entscheiden, da bei mir noch das "Pfeilproblem" mit gelöst wurde.
« Letzte Änderung: 11. August 2014, 18:34:22 von Kiwa »
Das Leben ist ein Adventure. Aber ohne Komplettlösung.

Für fast alles gibt es eine logische Erklärung. Für alles andere ein Placebo.