anchor.diff:  //* or -1 if no such group was found.
   //* Result: Group ID
   function TKMScriptStates.ClosestGroupEx(aPlayer, X, Y: Integer; aGroupType: TKMGroupType): Integer;
  -begin
  -  try
  -    Result := _ClosestGroup(aPlayer, X, Y, aGroupType, 'States.ClosestGroupEx');
  -  except
  -    gScriptEvents.ExceptionOutsideScript := True; //Don't blame script for this exception
  -    raise;
  -  end;
  -end;
  -
  -
  -function TKMScriptStates._ClosestGroupMultipleTypes(aPlayer, X, Y: Integer; aGroupTypes: TKMGroupTypeSet; aMethodName: string): Integer;
  +var
  +  succeed: Boolean;
  +begin
  +  try
  +    Result := _ClosestGroup(aPlayer, X, Y, aGroupType, succeed);
  +    if not succeed then
  +      LogParamWarn('States.ClosestGroupEx', [aPlayer, X, Y, GetEnumName(TypeInfo(TKMGroupType), Integer(aGroupType))]);
  +  except
  +    gScriptEvents.ExceptionOutsideScript := True; //Don't blame script for this exception
  +    raise;
  +  end;
  +end;
  +
  +
  +function TKMScriptStates._ClosestGroupMultipleTypes(aPlayer, X, Y: Integer; aGroupTypes: TKMGroupTypeSet; out aSucceed: Boolean): Integer;
   var
     G: TKMUnitGroup;
   begin
     Result := -1;
  -  try
  -    if InRange(aPlayer, 0, gHands.Count - 1) and (gHands[aPlayer].Enabled)
  -      and gTerrain.TileInMapCoords(X, Y) then
  -    begin
  -      aGroupTypes := aGroupTypes * GROUP_TYPES_VALID;
  -
  -      G := gHands[aPlayer].UnitGroups.GetClosestGroup(KMPoint(X,Y), aGroupTypes);
  -      if G <> nil then
  -      begin
  -        Result := G.UID;
  -        fIDCache.CacheGroup(G, G.UID);
  -      end;
  -    end
  -    else
  -      LogIntParamWarn(aMethodName, [aPlayer, X, Y]);
  -  except
  -    gScriptEvents.ExceptionOutsideScript := True; //Don't blame script for this exception
  -    raise;
  +  aSucceed := False;
  +  if InRange(aPlayer, 0, gHands.Count - 1) and (gHands[aPlayer].Enabled)
  +    and gTerrain.TileInMapCoords(X, Y) then
  +  begin
  +    aGroupTypes := aGroupTypes * GROUP_TYPES_VALID;
  +    G := gHands[aPlayer].UnitGroups.GetClosestGroup(KMPoint(X,Y), aGroupTypes);
  +    if G <> nil then
  +    begin
  +      Result := G.UID;
  +      fIDCache.CacheGroup(G, G.UID);
  +    end;
  +    aSucceed := True;
     end;
   end;
   
  
positive.code: //* aGroupTypes: Set of group types
  //* Result: Group ID
  function TKMScriptStates.ClosestGroupMultipleTypesEx(aPlayer, X, Y: Integer; aGroupTypes: TKMGroupTypeSet): Integer;
  begin
    Result := _ClosestGroupMultipleTypes(aPlayer, X, Y, aGroupTypes, 'States.ClosestGroupMultipleTypesEx');
  end;
  
  
  function TKMScriptStates._ClosestHouse(aPlayer, X, Y: Integer; aHouseType: TKMHouseType; aMethodName: string): Integer;
  var
    HTS: TKMHouseTypeSet;
    H: TKMHouse;
  begin
    try
      Result := -1;
      if InRange(aPlayer, 0, gHands.Count - 1) and (gHands[aPlayer].Enabled)
      and gTerrain.TileInMapCoords(X, Y)
      and (aHouseType <> htNone) then
      begin
        if aHouseType = htAny then
          HTS := HOUSES_VALID
        else
          HTS := [aHouseType];
  
        H := gHands[aPlayer].Houses.FindHouse(HTS, X, Y);
        if H <> nil then
        begin
          Result := H.UID;
          fIDCache.CacheHouse(H, H.UID);
        end;
      end
      else
        LogIntParamWarn(aMethodName, [aPlayer, X, Y, Ord(aHouseType)]);
    except
      gScriptEvents.ExceptionOutsideScript := True; //Don't blame script for this exception
      raise;
    end;
  end;
  
  
negative.code: var
    B: Byte;
    HTS: TKMHouseTypeSet;
    str: string;
    succeed: Boolean;
  begin
    try
      HTS := [];
      for B := Low(HOUSE_ID_TO_TYPE) to High(HOUSE_ID_TO_TYPE) do
        if (B in aHouseTypes) and (HOUSE_ID_TO_TYPE[B] <> htNone) then
          HTS := HTS + [HOUSE_ID_TO_TYPE[B]];
  
      Result := _ClosestHouseMultipleTypes(aPlayer, X, Y, HTS, succeed);
      if not succeed then
      begin
        // Collect house types to string
        str := '';
        for B in aHouseTypes do
        begin
          if str <> '' then
            str := str + ', ';
          str := str + IntToStr(B);
        end;
  
        LogParamWarn('States.ClosestHouseMultipleTypes', [aPlayer, X, Y, str]);
      end;
    except
      gScriptEvents.ExceptionOutsideScript := True; //Don't blame script for this exception
      raise;
    end;
  end;
  
  
  