<commit_before>unit KM_FogOfWar;
{$I KaM_Remake.inc}
interface
uses
  Math, KM_CommonClasses, KM_CommonTypes, KM_Defaults, KM_Points;


{ FOW state for each player }
type
  TKMFogOfWarCommon = class
  public
    function CheckTileInitialRevelation(const X,Y: Word): Boolean; virtual; abstract;

    function CheckVerticeRevelation(const X,Y: Word): Byte; virtual; abstract;
    function CheckTileRevelation(const X,Y: Word): Byte; virtual; abstract;
    function CheckRevelation(const aPoint: TKMPointF): Byte; virtual; abstract;

    function CheckVerticeRenderRev(const X,Y: Word): Byte; virtual; abstract;
    function CheckTileRenderRev(const X,Y: Word): Byte; virtual; abstract;
    function CheckRenderRev(const aPoint: TKMPointF): Byte; virtual; abstract;
  end;

  TKMFogOfWar = class(TKMFogOfWarCommon)
  private
    fAnimStep: Cardinal;
    fMapX: Word;
    fMapY: Word;

    fDynamicFOW: Boolean; //Local copy for faster access, updated in UpdateState

    //Initial revealers from static script
    fInitialRevealAll: Boolean;
    fInitialRevealers: TKMPointTagList;

    // Used to optimize RevealCircle
    // It doesn't work if a cover function is called
    // No need to save/load it, it's just an optimisation
    fRevealedRadius: array [0..MAX_MAP_SIZE-1, 0..MAX_MAP_SIZE-1] of Word;
    fRenderRevRevealedRad: array [0..MAX_MAP_SIZE-1, 0..MAX_MAP_SIZE-1] of Word;
    fCoverHasBeenCalled: Boolean;
    fRevealedToMax: TBoolean2Array;

    (*Revelation: array of array of packed record
      //Lies within range 0, TERRAIN_FOG_OF_WAR_MIN..TERRAIN_FOG_OF_WAR_MAX.
      Visibility: Byte;
      {LastTerrain: Byte;
      LastHeight: Byte;
      LastObj: Byte;
      LastHouse: TKMHouseType;}
    end;*)
    procedure SetMapSize(X,Y: Word);
    function CheckVerticeRev(aRevArray: PKMByte2Array; const X,Y: Word): Byte; inline;
    function CheckTileRev(aRevArray: PKMByte2Array; const X,Y: Word): Byte; inline;
    function CheckRev(aRevArray: PKMByte2Array; const aPoint: TKMPointF): Byte; inline;
  public
    Revelation: TKMByte2Array; //Public for faster access from Render
    RenderRevelation: TKMByte2Array; //Revelation for render - we have to render sprites a bit around actual FOW revelation

    constructor Create(X,Y: Word);
    destructor Destroy; override;

    property InitialRevealAll: Boolean read fInitialRevealAll write fInitialRevealAll;
    property InitialRevealers: TKMPointTagList read fInitialRevealers;

    procedure RevealCircle(const Pos: TKMPoint; Radius,Amount: Word);
    procedure CoverCircle(const Pos: TKMPoint; Radius: Word);
    procedure RevealRect(const TL, BR: TKMPoint; Amount: Word);
    procedure CoverRect(const TL, BR: TKMPoint);
    procedure RevealEverything;
    procedure CoverEverything;

    function CheckTileInitialRevelation(const X,Y: Word): Boolean; override;

    function CheckVerticeRevelation(const X,Y: Word): Byte; override;
    function CheckTileRevelation(const X,Y: Word): Byte; override;
    function CheckRevelation(const aPoint: TKMPointF): Byte; override;

    function CheckVerticeRenderRev(const X,Y: Word): Byte; override;
    function CheckTileRenderRev(const X,Y: Word): Byte; override;
    function CheckRenderRev(const aPoint: TKMPointF): Byte; override;

    procedure SyncFOW(aFOW: TKMFogOfWar);

    procedure Save(SaveStream: TKMemoryStream);
    procedure Load(LoadStream: TKMemoryStream);

    procedure UpdateState;
  end;

  //FOW that is always revealed (used by MapEd, Replays)
  TKMFogOfWarOpen = class(TKMFogOfWarCommon)
  public
    function CheckTileInitialRevelation(const X,Y: Word): Boolean; override;

    function CheckVerticeRevelation(const X,Y: Word): Byte; override;
    function CheckTileRevelation(const X,Y: Word): Byte; override;
    function CheckRevelation(const aPoint: TKMPointF): Byte; override;

    function CheckVerticeRenderRev(const X,Y: Word): Byte; override;
    function CheckTileRenderRev(const X,Y: Word): Byte; override;
    function CheckRenderRev(const aPoint: TKMPointF): Byte; override;
  end;


const
  FOG_OF_WAR_MIN  = 80;           //Minimum value for explored but FOW terrain, MIN/ACT determines FOW darkness
  FOG_OF_WAR_ACT  = 160;          //Until this value FOW is not rendered at all
  FOG_OF_WAR_MAX  = 255;          //This is max value that FOW can be, MAX-ACT determines how long until FOW appears
  FOG_OF_WAR_INC  = 128;          //Increment for FOW
  FOG_OF_WAR_DEC  = 12;           //Decrement for FOW


implementation
uses
  SysUtils, KM_GameApp, KM_DevPerfLog, KM_DevPerfLogTypes;

const
  //Addition to Revelation radius for Render revelation
  RENDER_RADIUS_ADD = 4; //3 is not enought sometimes, 4 is looking good


{ TKMFogOfWar }
//Init with Terrain size only once on creation as terrain size never change during the game
constructor TKMFogOfWar.Create(X,Y: Word);
begin
  inherited Create;

  fInitialRevealAll := False;
  fInitialRevealers := TKMPointTagList.Create;
  SetMapSize(X,Y);

  fDynamicFOW := (gGameApp <> nil) and gGameApp.DynamicFOWEnabled;
end;

<commit_msg>FOW: We should set RENDER_RADIUS_ADD to 5 for some big houses<commit_after>unit KM_FogOfWar;
{$I KaM_Remake.inc}
interface
uses
  Math, KM_CommonClasses, KM_CommonTypes, KM_Defaults, KM_Points;


{ FOW state for each player }
type
  TKMFogOfWarCommon = class
  public
    function CheckTileInitialRevelation(const X,Y: Word): Boolean; virtual; abstract;

    function CheckVerticeRevelation(const X,Y: Word): Byte; virtual; abstract;
    function CheckTileRevelation(const X,Y: Word): Byte; virtual; abstract;
    function CheckRevelation(const aPoint: TKMPointF): Byte; virtual; abstract;

    function CheckVerticeRenderRev(const X,Y: Word): Byte; virtual; abstract;
    function CheckTileRenderRev(const X,Y: Word): Byte; virtual; abstract;
    function CheckRenderRev(const aPoint: TKMPointF): Byte; virtual; abstract;
  end;

  TKMFogOfWar = class(TKMFogOfWarCommon)
  private
    fAnimStep: Cardinal;
    fMapX: Word;
    fMapY: Word;

    fDynamicFOW: Boolean; //Local copy for faster access, updated in UpdateState

    //Initial revealers from static script
    fInitialRevealAll: Boolean;
    fInitialRevealers: TKMPointTagList;

    // Used to optimize RevealCircle
    // It doesn't work if a cover function is called
    // No need to save/load it, it's just an optimisation
    fRevealedRadius: array [0..MAX_MAP_SIZE-1, 0..MAX_MAP_SIZE-1] of Word;
    fRenderRevRevealedRad: array [0..MAX_MAP_SIZE-1, 0..MAX_MAP_SIZE-1] of Word;
    fCoverHasBeenCalled: Boolean;
    fRevealedToMax: TBoolean2Array;

    (*Revelation: array of array of packed record
      //Lies within range 0, TERRAIN_FOG_OF_WAR_MIN..TERRAIN_FOG_OF_WAR_MAX.
      Visibility: Byte;
      {LastTerrain: Byte;
      LastHeight: Byte;
      LastObj: Byte;
      LastHouse: TKMHouseType;}
    end;*)
    procedure SetMapSize(X,Y: Word);
    function CheckVerticeRev(aRevArray: PKMByte2Array; const X,Y: Word): Byte; inline;
    function CheckTileRev(aRevArray: PKMByte2Array; const X,Y: Word): Byte; inline;
    function CheckRev(aRevArray: PKMByte2Array; const aPoint: TKMPointF): Byte; inline;
  public
    Revelation: TKMByte2Array; //Public for faster access from Render
    RenderRevelation: TKMByte2Array; //Revelation for render - we have to render sprites a bit around actual FOW revelation

    constructor Create(X,Y: Word);
    destructor Destroy; override;

    property InitialRevealAll: Boolean read fInitialRevealAll write fInitialRevealAll;
    property InitialRevealers: TKMPointTagList read fInitialRevealers;

    procedure RevealCircle(const Pos: TKMPoint; Radius,Amount: Word);
    procedure CoverCircle(const Pos: TKMPoint; Radius: Word);
    procedure RevealRect(const TL, BR: TKMPoint; Amount: Word);
    procedure CoverRect(const TL, BR: TKMPoint);
    procedure RevealEverything;
    procedure CoverEverything;

    function CheckTileInitialRevelation(const X,Y: Word): Boolean; override;

    function CheckVerticeRevelation(const X,Y: Word): Byte; override;
    function CheckTileRevelation(const X,Y: Word): Byte; override;
    function CheckRevelation(const aPoint: TKMPointF): Byte; override;

    function CheckVerticeRenderRev(const X,Y: Word): Byte; override;
    function CheckTileRenderRev(const X,Y: Word): Byte; override;
    function CheckRenderRev(const aPoint: TKMPointF): Byte; override;

    procedure SyncFOW(aFOW: TKMFogOfWar);

    procedure Save(SaveStream: TKMemoryStream);
    procedure Load(LoadStream: TKMemoryStream);

    procedure UpdateState;
  end;

  //FOW that is always revealed (used by MapEd, Replays)
  TKMFogOfWarOpen = class(TKMFogOfWarCommon)
  public
    function CheckTileInitialRevelation(const X,Y: Word): Boolean; override;

    function CheckVerticeRevelation(const X,Y: Word): Byte; override;
    function CheckTileRevelation(const X,Y: Word): Byte; override;
    function CheckRevelation(const aPoint: TKMPointF): Byte; override;

    function CheckVerticeRenderRev(const X,Y: Word): Byte; override;
    function CheckTileRenderRev(const X,Y: Word): Byte; override;
    function CheckRenderRev(const aPoint: TKMPointF): Byte; override;
  end;


const
  FOG_OF_WAR_MIN  = 80;           //Minimum value for explored but FOW terrain, MIN/ACT determines FOW darkness
  FOG_OF_WAR_ACT  = 160;          //Until this value FOW is not rendered at all
  FOG_OF_WAR_MAX  = 255;          //This is max value that FOW can be, MAX-ACT determines how long until FOW appears
  FOG_OF_WAR_INC  = 128;          //Increment for FOW
  FOG_OF_WAR_DEC  = 12;           //Decrement for FOW


implementation
uses
  SysUtils, KM_GameApp, KM_DevPerfLog, KM_DevPerfLogTypes;

const
  //Addition to Revelation radius for Render revelation
  RENDER_RADIUS_ADD = 5; //4 is not enought sometimes (Barracks?), 5 looks good


{ TKMFogOfWar }
//Init with Terrain size only once on creation as terrain size never change during the game
constructor TKMFogOfWar.Create(X,Y: Word);
begin
  inherited Create;

  fInitialRevealAll := False;
  fInitialRevealers := TKMPointTagList.Create;
  SetMapSize(X,Y);

  fDynamicFOW := (gGameApp <> nil) and gGameApp.DynamicFOWEnabled;
end;


{'fraction_non_alphanumeric': 0.08169708929452393, 'fraction_numerical': 0.006216082881105082, 'mean_word_length': 4.292950391644909, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6917541', 'n_tokens_mistral': 3397, 'n_tokens_neox': 3219, 'n_words': 964}