also erase
authornemo
Wed, 08 Apr 2015 23:59:35 -0400
changeset 10901 fbf6fbe66092
parent 10899 de52c2b8b773
child 10903 c9a0cdee4267
also erase
hedgewars/uLandGraphics.pas
hedgewars/uScript.pas
--- a/hedgewars/uLandGraphics.pas	Wed Apr 08 15:10:44 2015 -0400
+++ b/hedgewars/uLandGraphics.pas	Wed Apr 08 23:59:35 2015 -0400
@@ -51,6 +51,7 @@
 function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace: boolean; LandFlags: Word): boolean; inline;
 function ForcePlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; LandFlags: Word; Tint: LongWord; Behind, flipHoriz, flipVert: boolean): boolean; inline;
 function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace, outOfMap, force, behind, flipHoriz, flipVert: boolean; LandFlags: Word; Tint: LongWord): boolean;
+procedure EraseLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; LandFlags: Word; eraseOnLFMatch, flipHoriz, flipVert: boolean);
 function GetPlaceCollisionTex(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt): PTexture;
 
 implementation
@@ -739,8 +740,8 @@
                        SDL_UnlockSurface(Image);
                    exit
                    end;
-        p:= PByteArray(@(p^[Image^.pitch]));
-        end;
+        p:= PByteArray(@(p^[Image^.pitch]))
+        end
     end;
 
 TryPlaceOnLand:= true;
@@ -815,6 +816,88 @@
 
 end;
 
+procedure EraseLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; LandFlags: Word; eraseOnLFMatch, flipHoriz, flipVert: boolean);
+var X, Y, bpp, h, w, row, col, gx, gy, numFramesFirstCol: LongInt;
+    p: PByteArray;
+    Image: PSDL_Surface;
+    pixel: LongWord;
+begin
+numFramesFirstCol:= SpritesData[Obj].imageHeight div SpritesData[Obj].Height;
+
+TryDo(SpritesData[Obj].Surface <> nil, 'Assert SpritesData[Obj].Surface failed', true);
+
+Image:= SpritesData[Obj].Surface;
+w:= SpritesData[Obj].Width;
+h:= SpritesData[Obj].Height;
+if flipVert then flipSurface(Image, true);
+if flipHoriz then flipSurface(Image, false);
+row:= Frame mod numFramesFirstCol;
+col:= Frame div numFramesFirstCol;
+
+if SDL_MustLock(Image) then
+    SDLTry(SDL_LockSurface(Image) >= 0, true);
+
+bpp:= Image^.format^.BytesPerPixel;
+TryDo(bpp = 4, 'It should be 32 bpp sprite', true);
+// Check that sprite fits free space
+p:= PByteArray(@(PByteArray(Image^.pixels)^[ Image^.pitch * row * h + col * w * 4 ]));
+case bpp of
+    4: for y:= 0 to Pred(h) do
+        begin
+        for x:= 0 to Pred(w) do
+            if ((PLongword(@(p^[x * 4]))^) and AMask) <> 0 then
+                if ((cpY + y) <= Longint(topY)) or ((cpY + y) >= LAND_HEIGHT) or
+                   ((cpX + x) <= Longint(leftX)) or ((cpX + x) >= Longint(rightX)) then
+                   begin
+                   if SDL_MustLock(Image) then
+                       SDL_UnlockSurface(Image);
+                   exit
+                   end;
+        p:= PByteArray(@(p^[Image^.pitch]))
+        end
+    end;
+
+// Checked, now place
+p:= PByteArray(@(PByteArray(Image^.pixels)^[ Image^.pitch * row * h + col * w * 4 ]));
+case bpp of
+    4: for y:= 0 to Pred(h) do
+        begin
+        for x:= 0 to Pred(w) do
+            if ((PLongword(@(p^[x * 4]))^) and AMask) <> 0 then
+                   begin
+                if (cReducedQuality and rqBlurryLand) = 0 then
+                    begin
+                    gX:= cpX + x;
+                    gY:= cpY + y;
+                    end
+                else
+                    begin
+                    gX:= (cpX + x) div 2;
+                    gY:= (cpY + y) div 2;
+                    end;
+		        if (not eraseOnLFMatch or (Land[cpY + y, cpX + x] and LandFlags <> 0)) and
+                    (PLongword(@(p^[x * 4]))^ and AMask <> 0) then
+                    begin
+                    LandPixels[gY, gX]:= 0;
+                    Land[cpY + y, cpX + x]:= 0
+                    end
+                end;
+        p:= PByteArray(@(p^[Image^.pitch]));
+        end;
+    end;
+if SDL_MustLock(Image) then
+    SDL_UnlockSurface(Image);
+
+if flipVert then flipSurface(Image, true);
+if flipHoriz then flipSurface(Image, false);
+
+x:= Max(cpX, leftX);
+w:= Min(cpX + Image^.w, LAND_WIDTH) - x;
+y:= Max(cpY, topY);
+h:= Min(cpY + Image^.h, LAND_HEIGHT) - y;
+UpdateLandTexture(x, w, y, h, true)
+end;
+
 function GetPlaceCollisionTex(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt): PTexture;
 var X, Y, bpp, h, w, row, col, numFramesFirstCol: LongInt;
     p, pt: PLongWordArray;
--- a/hedgewars/uScript.pas	Wed Apr 08 15:10:44 2015 -0400
+++ b/hedgewars/uScript.pas	Wed Apr 08 23:59:35 2015 -0400
@@ -2213,18 +2213,21 @@
     if CheckAndFetchLuaParamMinCount(L, 4, call, params, n) then
         begin
         if not lua_isnoneornil(L, 5) then
-	     tint := lua_tointeger(L, 5)
+	        tint := lua_tointeger(L, 5)
         else tint := $FFFFFFFF;
         if not lua_isnoneornil(L, 6) then
-	     flipHoriz := lua_toboolean(L, 6)
+	        behind := lua_toboolean(L, 6)
+        else behind := false;
+        if not lua_isnoneornil(L, 7) then
+	        flipHoriz := lua_toboolean(L, 7)
         else flipHoriz := false;
-        if not lua_isnoneornil(L, 7) then
-	     flipVert := lua_toboolean(L, 7)
+        if not lua_isnoneornil(L, 8) then
+	        flipVert := lua_toboolean(L, 8)
         else flipVert := false;
         lf:= 0;
 
         // accept any amount of landflags, loop is never executed if n>6
-        for i:= 8 to n do
+        for i:= 9 to n do
             lf:= lf or lua_tointeger(L, i);
 
         n:= LuaToSpriteOrd(L, 3, call, params);
@@ -2245,6 +2248,48 @@
     lc_placesprite:= 1
 end;
 
+function lc_erasesprite(L : Plua_State) : LongInt; Cdecl;
+var spr   : TSprite;
+    lf    : Word;
+    i, n : LongInt;
+    eraseOnLFMatch, flipHoriz, flipVert : boolean;
+const
+    call = 'EraseSprite';
+    params = 'x, y, sprite, frameIdx, eraseOnLFMatch, flipHoriz, flipVert, [, landFlag, ... ]';
+begin
+    if CheckAndFetchLuaParamMinCount(L, 4, call, params, n) then
+        begin
+        if not lua_isnoneornil(L, 5) then
+	        eraseOnLFMatch := lua_toboolean(L, 5)
+        else eraseOnLFMatch := false;
+        if not lua_isnoneornil(L, 6) then
+	        flipHoriz := lua_toboolean(L, 6)
+        else flipHoriz := false;
+        if not lua_isnoneornil(L, 7) then
+	        flipVert := lua_toboolean(L, 7)
+        else flipVert := false;
+        lf:= 0;
+
+        // accept any amount of landflags, loop is never executed if n>6
+        for i:= 8 to n do
+            lf:= lf or lua_tointeger(L, i);
+
+        n:= LuaToSpriteOrd(L, 3, call, params);
+        if n >= 0 then
+            begin
+            spr:= TSprite(n);
+            if SpritesData[spr].Surface = nil then
+                LuaError(call + ': ' + EnumToStr(spr) + ' cannot be placed! (required information not loaded)' )
+            else
+                EraseLand(
+                    lua_tointeger(L, 1) - SpritesData[spr].Width div 2,
+                    lua_tointeger(L, 2) - SpritesData[spr].Height div 2,
+                    spr, lua_tointeger(L, 4), lf, eraseOnLFMatch, flipHoriz, flipVert);
+            end;
+        end;
+    lc_erasesprite:= 0
+end;
+
 function lc_placegirder(L : Plua_State) : LongInt; Cdecl;
 var placed: boolean;
 begin
@@ -3166,6 +3211,7 @@
 lua_register(luaState, _P'MapHasBorder', @lc_maphasborder);
 lua_register(luaState, _P'GetHogHat', @lc_gethoghat);
 lua_register(luaState, _P'SetHogHat', @lc_sethoghat);
+lua_register(luaState, _P'EraseSprite', @lc_erasesprite);
 lua_register(luaState, _P'PlaceSprite', @lc_placesprite);
 lua_register(luaState, _P'PlaceGirder', @lc_placegirder);
 lua_register(luaState, _P'GetCurAmmoType', @lc_getcurammotype);