hedgewars/GSHandlers.inc
changeset 5024 1e332947147c
parent 5016 9347d82a26cc
child 5025 ac1691d35cf2
equal deleted inserted replaced
5023:8c16c0534b3c 5024:1e332947147c
   566         end
   566         end
   567 end;
   567 end;
   568 
   568 
   569 procedure doStepSnowflake(Gear: PGear);
   569 procedure doStepSnowflake(Gear: PGear);
   570 var xx, yy, px, py, i: LongInt;
   570 var xx, yy, px, py, i: LongInt;
   571     move, allpx: Boolean;
   571     move, draw, allpx: Boolean;
   572     s: PSDL_Surface;
   572     s: PSDL_Surface;
   573     p: PLongwordArray;
   573     p: PLongwordArray;
   574     oAlpha, nAlpha: byte;
   574     oAlpha, nAlpha: byte;
   575 begin
   575 begin
   576 if GameTicks and $7 = 0 then
   576 move:= false;
       
   577 draw:= false;
       
   578 if (Gear^.State and gstTmpFlag) <> 0 then
       
   579     begin
       
   580     doStepFallingGear(Gear);
       
   581     CheckCollision(Gear);
       
   582     if ((Gear^.State and gstCollision) <> 0) or ((Gear^.State and gstMoving) = 0) then draw:= true;
       
   583     xx:= hwRound(Gear^.X);
       
   584     yy:= hwRound(Gear^.Y);
       
   585     end
       
   586 else if GameTicks and $7 = 0 then
   577     begin
   587     begin
   578     with Gear^ do
   588     with Gear^ do
   579         begin
   589         begin
   580         X:= X + cWindSpeed * 1600 + dX;
   590         X:= X + cWindSpeed * 1600 + dX;
   581         Y:= Y + dY + cGravity * vobFallSpeed * 8;  // using same value as flakes to try and get similar results
   591         Y:= Y + dY + cGravity * vobFallSpeed * 8;  // using same value as flakes to try and get similar results
   593             begin
   603             begin
   594             dec(Health, vobFrameTicks);
   604             dec(Health, vobFrameTicks);
   595             inc(Timer);
   605             inc(Timer);
   596             if Timer = vobFramesCount then Timer:= 0
   606             if Timer = vobFramesCount then Timer:= 0
   597             end;
   607             end;
   598 
       
   599         move:= false;
       
   600     // move back to cloud layer
   608     // move back to cloud layer
   601         if yy > cWaterLine then move:= true
   609         if yy > cWaterLine then move:= true
   602         else if ((yy and LAND_HEIGHT_MASK) <> 0) or ((xx and LAND_WIDTH_MASK) <> 0) then move:=true
   610         else if ((yy and LAND_HEIGHT_MASK) <> 0) or ((xx and LAND_WIDTH_MASK) <> 0) then move:=true
   603         // Solid pixel encountered
   611         // Solid pixel encountered
   604         else if (Land[yy, xx] <> 0) then
   612         else if (Land[yy, xx] <> 0) then
   630                 Y:= Y - dY - cGravity * vobFallSpeed * 8;
   638                 Y:= Y - dY - cGravity * vobFallSpeed * 8;
   631                 end
   639                 end
   632             // if there's an hog/object below do nothing
   640             // if there's an hog/object below do nothing
   633             else if ((((yy+1) and LAND_HEIGHT_MASK) = 0) and ((Land[yy+1, xx] and $FF) <> 0))
   641             else if ((((yy+1) and LAND_HEIGHT_MASK) = 0) and ((Land[yy+1, xx] and $FF) <> 0))
   634                 then move:=true
   642                 then move:=true
       
   643             else draw:= true
       
   644             end
       
   645         end
       
   646     end;
       
   647 if draw then 
       
   648     with Gear^ do
       
   649         begin
       
   650         // we've collided with land. draw some stuff and get back into the clouds
       
   651         move:= true;
       
   652         if (CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtRope) then
       
   653             begin
       
   654 ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS ////////////////////////////////////
       
   655             if (State and gstTmpFlag) = 0 then
       
   656                 begin
       
   657                 dec(yy,3);
       
   658                 dec(xx,1)
       
   659                 end;
       
   660             s:= SpritesData[sprSnow].Surface;
       
   661             p:= s^.pixels;
       
   662             allpx:= true;
       
   663             for py:= 0 to Pred(s^.h) do
       
   664                 begin
       
   665                 for px:= 0 to Pred(s^.w) do
       
   666                     if ((((yy + py) and LAND_HEIGHT_MASK) = 0) and (((xx + px) and LAND_WIDTH_MASK) = 0)) and ((Land[yy + py, xx + px] and $FF) = 0) then
       
   667                         begin
       
   668                         Land[yy + py, xx + px]:= Land[yy + py, xx + px] or lfObject;
       
   669                         if (cReducedQuality and rqBlurryLand) = 0 then
       
   670                             begin
       
   671                             if (State and gstTmpFlag) <> 0 then
       
   672                                 LandPixels[yy + py, xx + px]:= addBgColor(LandPixels[yy + py, xx + px], (cExplosionBorderColor and $00FFFFFF) or (p^[px] and $FF000000))
       
   673                             else LandPixels[yy + py, xx + px]:= addBgColor(LandPixels[yy + py, xx + px], p^[px]);
       
   674                             end
       
   675                         else
       
   676                             begin
       
   677                             if (State and gstTmpFlag) <> 0 then
       
   678                                 LandPixels[(yy + py) div 2, (xx + px) div 2]:= addBgColor(LandPixels[(yy + py) div 2, (xx + px) div 2], (cExplosionBorderColor and $00FFFFFF) or (p^[px] and $FF000000))
       
   679                             else LandPixels[(yy + py) div 2, (xx + px) div 2]:= addBgColor(LandPixels[(yy + py) div 2, (xx + px) div 2], p^[px]);
       
   680                             end;
       
   681                         end
       
   682                     else allpx:= false;
       
   683                 p:= @(p^[s^.pitch shr 2])
       
   684                 end;
       
   685             
       
   686             
       
   687             Land[py, px+1]:= lfBasic;
       
   688             
       
   689             if allpx then UpdateLandTexture(xx, Pred(s^.h), yy, Pred(s^.w))
   635             else
   690             else
   636                 begin
   691                 begin
   637                 // we've collided with land. draw some stuff and get back into the clouds
   692                 UpdateLandTexture(
   638                 move:= true;
   693                     max(0, min(LAND_WIDTH, xx)),
   639                 if (CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtRope) then
   694                     min(LAND_WIDTH - xx, Pred(s^.w)),
   640                     begin
   695                     max(0, min(LAND_WIDTH, yy)),
   641     ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS ////////////////////////////////////
   696                     min(LAND_HEIGHT - yy, Pred(s^.h))
   642                     dec(yy,3);
   697                 );
   643                     dec(xx,1);
       
   644                     s:= SpritesData[sprSnow].Surface;
       
   645                     p:= s^.pixels;
       
   646                     allpx:= true;
       
   647                     for py:= 0 to Pred(s^.h) do
       
   648                         begin
       
   649                         for px:= 0 to Pred(s^.w) do
       
   650                             if ((((yy + py) and LAND_HEIGHT_MASK) = 0) and (((xx + px) and LAND_WIDTH_MASK) = 0)) and ((Land[yy + py, xx + px] and $FF) = 0) then
       
   651                                 begin
       
   652                                 Land[yy + py, xx + px]:= Land[yy + py, xx + px] or lfObject;
       
   653                                 if (cReducedQuality and rqBlurryLand) = 0 then
       
   654                                     begin
       
   655                                     LandPixels[yy + py, xx + px]:= addBgColor(LandPixels[yy + py, xx + px], p^[px]);
       
   656                                     end
       
   657                                 else
       
   658                                     begin
       
   659                                     LandPixels[(yy + py) div 2, (xx + px) div 2]:= addBgColor(LandPixels[(yy + py) div 2, (xx + px) div 2], p^[px]);
       
   660                                     end;
       
   661                                 end
       
   662                             else allpx:= false;
       
   663                         p:= @(p^[s^.pitch shr 2])
       
   664                         end;
       
   665                     
       
   666                     
       
   667                     Land[py, px+1]:= lfBasic;
       
   668                     
       
   669                     if allpx then UpdateLandTexture(xx, Pred(s^.h), yy, Pred(s^.w))
       
   670                     else
       
   671                         begin
       
   672                         UpdateLandTexture(
       
   673                             max(0, min(LAND_WIDTH, xx)),
       
   674                             min(LAND_WIDTH - xx, Pred(s^.w)),
       
   675                             max(0, min(LAND_WIDTH, yy)),
       
   676                             min(LAND_HEIGHT - yy, Pred(s^.h))
       
   677                         );
       
   678                         end;
       
   679     ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS ////////////////////////////////////
       
   680                     end
       
   681                 end;
   698                 end;
   682             end;
   699 ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS ////////////////////////////////////
   683         if move then
       
   684             begin
       
   685             X:= int2hwFloat(GetRandom(LAND_WIDTH+1024)-512);
       
   686             Y:= int2hwFloat(750+(GetRandom(50)-25))
       
   687             end
   700             end
   688         end
   701         end;
       
   702 
       
   703 if move then
       
   704     begin
       
   705     if ((Gear^.State and gstTmpFlag) <> 0) then
       
   706         begin
       
   707         DeleteGear(Gear);
       
   708         exit
       
   709         end;
       
   710     Gear^.X:= int2hwFloat(GetRandom(LAND_WIDTH+1024)-512);
       
   711     Gear^.Y:= int2hwFloat(750+(GetRandom(50)-25))
   689     end
   712     end
   690 end;
   713 end;
   691 
   714 
   692 ////////////////////////////////////////////////////////////////////////////////
   715 ////////////////////////////////////////////////////////////////////////////////
   693 procedure doStepGrave(Gear: PGear);
   716 procedure doStepGrave(Gear: PGear);
  2111         end
  2134         end
  2112     end
  2135     end
  2113     else
  2136     else
  2114     begin
  2137     begin
  2115         if sticky then
  2138         if sticky then
  2116         begin
  2139             begin
  2117             Gear^.Radius := 7;
  2140             Gear^.Radius := 7;
  2118             AmmoShove(Gear, 2, 30);
  2141             AmmoShove(Gear, 2, 30);
  2119             Gear^.Radius := 1
  2142             Gear^.Radius := 1
  2120         end;
  2143             end;
  2121         if Gear^.Timer > 0 then
  2144         if Gear^.Timer > 0 then
  2122         begin
  2145             begin
  2123             dec(Gear^.Timer);
  2146             dec(Gear^.Timer);
  2124             inc(Gear^.Damage)
  2147             inc(Gear^.Damage)
  2125         end
  2148             end
  2126         else
  2149         else
  2127         begin
  2150         begin
  2128             gX := hwRound(Gear^.X);
  2151             gX := hwRound(Gear^.X);
  2129             gY := hwRound(Gear^.Y);
  2152             gY := hwRound(Gear^.Y);
  2130             // Standard fire
  2153             // Standard fire
  2131             if not sticky then
  2154             if not sticky then
  2132             begin
  2155                 begin
  2133                 if ((GameTicks and $1) = 0) then
  2156                 if ((GameTicks and $1) = 0) then
  2134                     begin
  2157                     begin
  2135                     Gear^.Radius := 7;
  2158                     Gear^.Radius := 7;
  2136                     AmmoShove(Gear, 4, 150);
  2159                     AmmoShove(Gear, 4, 150);
  2137                     Gear^.Radius := 1;
  2160                     Gear^.Radius := 1;
  2141                 if ((GameTicks and $7) = 0) and (Random(2) = 0) then
  2164                 if ((GameTicks and $7) = 0) and (Random(2) = 0) then
  2142                     for i:= 1 to Random(2)+1 do
  2165                     for i:= 1 to Random(2)+1 do
  2143                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2166                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2144                 if Gear^.Health > 0 then dec(Gear^.Health);
  2167                 if Gear^.Health > 0 then dec(Gear^.Health);
  2145                 Gear^.Timer := 450 - Gear^.Tag * 8
  2168                 Gear^.Timer := 450 - Gear^.Tag * 8
  2146             end
  2169                 end
  2147             else
  2170             else
  2148             begin
  2171                 begin
  2149                 // Modified fire
  2172                 // Modified fire
  2150                 if ((GameTicks and $7FF) = 0) and ((GameFlags and gfSolidLand) = 0) then
  2173                 if ((GameTicks and $7FF) = 0) and ((GameFlags and gfSolidLand) = 0) then
  2151                 begin
  2174                     begin
  2152                     DrawExplosion(gX, gY, 4);
  2175                     DrawExplosion(gX, gY, 4);
  2153 
  2176 
  2154                     for i:= 0 to Random(3) do
  2177                     for i:= 0 to Random(3) do
  2155                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2178                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2156                 end;
  2179                     end;
  2157 
  2180 
  2158 // This one is interesting.  I think I understand the purpose, but I wonder if a bit more fuzzy of kicking could be done with getrandom.
  2181 // This one is interesting.  I think I understand the purpose, but I wonder if a bit more fuzzy of kicking could be done with getrandom.
  2159                 Gear^.Timer := 100 - Gear^.Tag * 3;
  2182                 Gear^.Timer := 100 - Gear^.Tag * 3;
  2160                 if (Gear^.Damage > 3000+Gear^.Tag*1500) then Gear^.Health := 0
  2183                 if (Gear^.Damage > 3000+Gear^.Tag*1500) then Gear^.Health := 0
  2161             end
  2184             end
  4339     HHGear^.Message := HHGear^.Message and not (gmUp or gmDown or gmLeft or gmRight);
  4362     HHGear^.Message := HHGear^.Message and not (gmUp or gmDown or gmLeft or gmRight);
  4340     HHGear^.State := HHGear^.State or gstNotKickable;
  4363     HHGear^.State := HHGear^.State or gstNotKickable;
  4341     Gear^.doStep := @doStepFlamethrowerWork
  4364     Gear^.doStep := @doStepFlamethrowerWork
  4342 end;
  4365 end;
  4343 
  4366 
       
  4367 procedure doStepLandGunWork(Gear: PGear);
       
  4368 var 
       
  4369     HHGear: PGear;
       
  4370     rx, ry, speed: hwFloat;
       
  4371     i, gX, gY: LongInt;
       
  4372     Flake: PGear;
       
  4373 begin
       
  4374     AllInactive := false;
       
  4375     HHGear := Gear^.Hedgehog^.Gear;
       
  4376     HedgehogChAngle(HHGear);
       
  4377     gX := hwRound(Gear^.X) + GetLaunchX(amBallgun, hwSign(HHGear^.dX), HHGear^.Angle);
       
  4378     gY := hwRound(Gear^.Y) + GetLaunchY(amBallgun, HHGear^.Angle);
       
  4379     
       
  4380     if (GameTicks and $FF) = 0 then
       
  4381         begin
       
  4382         if (HHGear^.Message and gmRight) <> 0 then
       
  4383             begin
       
  4384             if HHGear^.dX.isNegative and (Gear^.Tag < 20) then inc(Gear^.Tag)
       
  4385             else if Gear^.Tag > 5 then dec(Gear^.Tag);
       
  4386             end
       
  4387         else if (HHGear^.Message and gmLeft) <> 0 then
       
  4388             begin
       
  4389             if HHGear^.dX.isNegative and (Gear^.Tag > 5) then dec(Gear^.Tag)
       
  4390             else if Gear^.Tag < 20 then inc(Gear^.Tag);
       
  4391             end
       
  4392         end;
       
  4393     
       
  4394     dec(Gear^.Timer);
       
  4395     if Gear^.Timer = 0 then
       
  4396         begin
       
  4397         dec(Gear^.Health);
       
  4398         if (Gear^.Health mod 5) = 0 then
       
  4399             begin
       
  4400             rx := rndSign(getRandom * _0_1);
       
  4401             ry := rndSign(getRandom * _0_1);
       
  4402             speed := (_3 / Gear^.Tag);
       
  4403     
       
  4404             Flake := AddGear(gx, gy, gtFlake, 0, _0, _0, 0);
       
  4405             Flake^.dX:= SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx;
       
  4406             Flake^.dY:= AngleCos(HHGear^.Angle) * ( - speed) + ry;
       
  4407             Flake^.State := Flake^.State or gsttmpFlag;
       
  4408             
       
  4409             end;
       
  4410         Gear^.Timer:= Gear^.Tag
       
  4411         end;
       
  4412 
       
  4413     if (Gear^.Health = 0) or (HHGear^.Damage <> 0) then
       
  4414         begin
       
  4415         DeleteGear(Gear);
       
  4416         AfterAttack
       
  4417         end
       
  4418     else
       
  4419         begin
       
  4420         i:= Gear^.Health div 10;
       
  4421         if (i <> Gear^.Damage) and ((GameTicks and $3F) = 0) then
       
  4422             begin
       
  4423             Gear^.Damage:= i;
       
  4424             if Gear^.Tex <> nil then FreeTexture(Gear^.Tex);
       
  4425             Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(i) +
       
  4426                          '%', cWhiteColor, fntSmall)
       
  4427             end
       
  4428         end
       
  4429 end;
       
  4430 
       
  4431 procedure doStepLandGun(Gear: PGear);
       
  4432 var 
       
  4433     HHGear: PGear;
       
  4434 begin
       
  4435     HHGear := Gear^.Hedgehog^.Gear;
       
  4436     HHGear^.Message := HHGear^.Message and not (gmUp or gmDown or gmLeft or gmRight);
       
  4437     HHGear^.State := HHGear^.State or gstNotKickable;
       
  4438     Gear^.doStep := @doStepLandGunWork
       
  4439 end;
       
  4440 
  4344 procedure doStepPoisonCloud(Gear: PGear);
  4441 procedure doStepPoisonCloud(Gear: PGear);
  4345 begin
  4442 begin
  4346     if Gear^.Timer = 0 then
  4443     if Gear^.Timer = 0 then
  4347     begin
  4444     begin
  4348         DeleteGear(Gear);
  4445         DeleteGear(Gear);