Skip to content

Dealing with CreateArea / DestroyArea and black screen

While trying, for over a day now, to use DestroyArea then CreateArea to recreate areas with truly basheable placeables, more often than not, the game screen turns almost all black.

Placeables such as doors, or other non static placeables, are still visible, but the screen stays black sometimes for a short time, sometimes a very long time.

I've tried adding RecomputeStaticLighting after Destroy/Create, tried other random things that I believed could refresh the screen, but to no avail.

I'm editing the module with wine, but playing on steam linux without wine. As long as I don't Destroy/Create, there are no black screens. Video card is "VGA compatible controller: NVIDIA Corporation GM204 [GeForce GTX 970] (rev a1)" (via 'lspci'), and the drivers are the default Debian Buster ones ("nouveau")

Does this happen to other modders who use these functions but who are under Windows?
Is this a Linux only issue?


Comments

  • ShadooowShadooow Member Posts: 402
    I saw this just yesterday. Windows server old version 8186.

    It happened in middle of gameplay inside instanced/copied area when we opened a drow chest placeable. And it lasted for about 10 seconds then lights turned on again.

    Btw it also blackened minimap.
  • nivniv Member, Moderator, Developer Posts: 410
    edited June 2020
    There are currently two known bugs on <8193.13 that affect DestroyArea:

    * If you call DestroyArea from an area event handler of the area that you want to destroy, it'll corrupt some heap memory. (Fixed in .13) To avoid this, either call it with DelayCommand or make sure to never run it from an area event.
    * Minimap handling is a bit broken, where it sometimes purges the wrong minimap data (will be fixed in .14..15+). This results in a black/unexplored minimap, which is also tied to visual exploration. Interior areas might appear black that way. Try ExploreAreaForPlayer() to reveal the full area to the player, and see if that fixes the blackness for a workaround.

    If that doesn't sound like your problem, or the ExploreArea() doesn't fix it on the latest dev patch, please provide more details. If you are technically inclined, you can report a bug here: https://github.com/Beamdog/nwn-issues (But please read the shown README.md first ..). Otherwise, just respond here with details.
    BlakBat
  • ShadooowShadooow Member Posts: 402
    @niv I encountered an issue where GetObjectByTag on something which has existed in instanced area returns valid object, but GetArea of that object returns invalid one (don't know yet if it is OBJECT_INVALID or just the object is invalid, but it has no variables it is supposed to have).

    Since I am running on old version 8186 I did not reported it as I thought this is probably fixed already. But I didn't notice anything related to instances in patch notes. I am definitely not destroying area from area events nor is that area OBJECT_SELF in a script that performs it.
  • BlakBatBlakBat Member Posts: 8
    I'm running the 8193.13 version, and I can easily reproduce the issue whenever I want while being out of an area event.

    In a matter of fact, I've scripted a chat command so when the PC talks: "/recreate area_l1a12", it recreates the area whose tag is "area_l1a12".

    The CreateArea / DestroyArea code is the following, which I simplified by removing some additional extra checks, and added additional comments
    // Full code can be downloaded here : https://gitlab.com/roum/module-scripts/-/tree/features-via-individual-commits in files libarea, mod_pc_chat
    
    // I've made it so all areas have resref == tag
    
    // DESTROY_AREA_GUARD is a global int initialized at 0 and set to 1 in area enter + exit events. 
    
    object AREA_RecreateArea(string sResRef)
    {
      /* ... extra checks */
      object oArea = GetObjectByTag(sResRef); 
    
      if (DESTROY_AREA_GUARD != 0)
        return WriteError("...");
    
      if (DestroyArea(oArea) < 0)
        return WriteError("...");
    
      oArea = CreateArea(sResRef, sResRef, sName);
      if (oArea == OBJECT_INVALID)
        return WriteError("AREA_RecreateArea: Failed to create area");
    
      // If the following is not done, then GetObjectInfo will actually return a string saying that oArea is invalid, even if it's not because of conditional above.
      
      oArea = GetObjectByTag(sResRef);
      WriteNotice("AREA_RecreateArea: Recreated area " + GetObjectInfo(oArea));
      
      return oArea;
    }
    


    For those who want to know what I trying to achieve: I'm trying to have respawnable doors and placeables which are bashable by the default game engine and that especially don't have the plot flag. Basically, you enter area Foobar, bash the doors and chests, and 60 minutes after, the area is recreated and you can rince and repeat the looting and bashing.
  • Strife_and_DiscordStrife_and_Discord Member Posts: 17
    @BlakBat Is it always the same area? If so wont it be easier to just respawn just the placeables themselves?
    Doors are easier of course, but you can set a script to respawn the door OnDeath. As for other placeables - I would recommend dropping a Waypoint again OnDeath event and append to it the Resref of the placeable and just respawn it on that waypoint with that resref after X time.

    Another option could be to take the placeable and OnDeath modify its appearance to an invisible and Static placeable for X time. And afterwards change the appearance again and make usable.
  • DazDaz Member Posts: 125
    Shadooow wrote: »
    @niv I encountered an issue where GetObjectByTag on something which has existed in instanced area returns valid object, but GetArea of that object returns invalid one (don't know yet if it is OBJECT_INVALID or just the object is invalid, but it has no variables it is supposed to have).

    Since I am running on old version 8186 I did not reported it as I thought this is probably fixed already. But I didn't notice anything related to instances in patch notes. I am definitely not destroying area from area events nor is that area OBJECT_SELF in a script that performs it.

    niv fixed the bug that caused this, it should be fixed in an upcoming build.
  • BlakBatBlakBat Member Posts: 8
    @Strife_and_Discord No, we're talking 250+ areas.

    I figured it would be easier to just recreate the area. Was I wrong.
  • BlakBatBlakBat Member Posts: 8
    @Strife_and_Discord How do you respawn / recreate a bashed door?
  • meaglynmeaglyn Member Posts: 146
    The trick is to set it not destroyable in the on_death handler of the door. And then you can close it, heal it and set it destroyable again when you "respawn" it. I.e. you don't let it actually get completely destroyed.
  • ShadooowShadooow Member Posts: 402
    meaglyn wrote: »
    The trick is to set it not destroyable in the on_death handler of the door. And then you can close it, heal it and set it destroyable again when you "respawn" it. I.e. you don't let it actually get completely destroyed.

    This, however it doesn't work well with large tileset specific doors. I am using this method and I am slowly switching to area instancing as well - it has more advantages than just "true destroyable objects". Fortunately I am not experiencing your issue...
  • meaglynmeaglyn Member Posts: 146
    Shadooow wrote: »
    This, however it doesn't work well with large tileset specific doors. I am using this method and I am slowly switching to area instancing as well - it has more advantages than just "true destroyable objects". Fortunately I am not experiencing your issue...

    Interesting... thanks, I'm not using it for any such doors so I haven't noticed any issues. I find for regular doors it works very nicely.
  • ShadooowShadooow Member Posts: 402
    meaglyn wrote: »
    Shadooow wrote: »
    This, however it doesn't work well with large tileset specific doors. I am using this method and I am slowly switching to area instancing as well - it has more advantages than just "true destroyable objects". Fortunately I am not experiencing your issue...

    Interesting... thanks, I'm not using it for any such doors so I haven't noticed any issues. I find for regular doors it works very nicely.

    Some of the tileset specific doors are missing some animations or some settings in model. Setting them to nondestroyable causes their destroy animation to be run in loop permanently.
  • BlakBatBlakBat Member Posts: 8
    niv wrote: »
    (...) Try ExploreAreaForPlayer() to reveal the full area to the player, and see if that fixes the blackness for a workaround.

    ExploreAreaForPlayer does workaround the blackness, but I noticed it doesn't have to reveal the whole area, just calling it is enough. I had tried setting SetCreatureExploresMinimap on and off, but that didn't work.

    The workaround of calling ExploreAreaForPlayer and nuking the player's minimap progress is acceptable to me.


  • BlakBatBlakBat Member Posts: 8
    For archival reasons, here's the code that I use to workaround this bug:
    void AREA_FIXME(object oPC)
    {
      object oArea = GetArea(oPC);
      string sData = NWNX_Player_GetAreaExplorationState(oPC, oArea);
    
      ExploreAreaForPlayer(oArea, oPC, FALSE);
      NWNX_Player_SetAreaExplorationState(oPC, oArea, sData);
    }
    

    and I call this function for every PC on the server:
      object oPC = GetFirstPC();
      while (oPC != OBJECT_INVALID)
      {
        DelayCommand(0.0f, AREA_FIXME(oPC));
        oPC = GetNextPC();
      }
    

    This, of course, requires NWNX if you don't want the player to lose his minimap progress.
  • BlakBatBlakBat Member Posts: 8
    Definitely not fixed in .14
Sign In or Register to comment.