diff -r a98984e4f458 -r dee31c5149e0 hedgewars/uVisualGears.pas --- a/hedgewars/uVisualGears.pas Thu May 06 20:59:15 2010 +0000 +++ b/hedgewars/uVisualGears.pas Thu May 06 22:02:56 2010 +0000 @@ -35,6 +35,7 @@ tdX: hwFloat; tdY: hwFloat; mdY: QWord; + State : Longword; Timer: Longword; Angle, dAngle: real; Kind: TVisualGearType; @@ -48,7 +49,7 @@ procedure initModule; procedure freeModule; -function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType): PVisualGear; +function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord = 0): PVisualGear; procedure ProcessVisualGears(Steps: Longword); procedure KickFlakes(Radius, X, Y: LongInt); procedure DrawVisualGears(Layer: LongWord); @@ -65,6 +66,8 @@ uses uWorld, uMisc, uStore, uTeams, uSound; const cExplFrameTicks = 110; +{$INCLUDE "VGSHandlers.inc"} + procedure AddDamageTag(X, Y, Damage, Color: LongWord); var s: shortstring; Gear: PVisualGear; @@ -83,398 +86,6 @@ // ================================================================== -procedure doStepFlake(Gear: PVisualGear; Steps: Longword); -var sign: hwFloat; -begin -sign:= _1; -with Gear^ do - begin - inc(FrameTicks, Steps); - if FrameTicks > vobFrameTicks then - begin - dec(FrameTicks, vobFrameTicks); - inc(Frame); - if Frame = vobFramesCount then Frame:= 0 - end; - X:= X + (cWindSpeed * 200 + dX + tdX) * Steps; - Y:= Y + (dY + tdY + cGravity * vobFallSpeed) * Steps; - Angle:= Angle + dAngle * Steps; - - if (hwRound(X) >= -cScreenWidth - 64) and - (hwRound(X) <= cScreenWidth + LAND_WIDTH) and - (hwRound(Y) <= (LAND_HEIGHT + 75)) and - (Timer > 0) and (Timer-Steps > 0) then - begin - sign.isNegative:=tdX.isNegative; - tdX:= tdX - _0_005*Steps*sign; - if (sign.isNegative and (tdX > _0)) or (not sign.isNegative and (tdX < _0)) then tdX:= _0; - sign.isNegative:=tdY.isNegative; - tdY:= tdY - _0_005*Steps*sign; - if (sign.isNegative and (tdY > _0)) or (not sign.isNegative and (tdY < _0)) then tdY:= _0; - dec(Timer, Steps) - end - else - begin - if hwRound(X) < -cScreenWidth - 64 then X:= int2hwFloat(cScreenWidth + LAND_WIDTH) else - if hwRound(X) > cScreenWidth + LAND_WIDTH then X:= int2hwFloat(-cScreenWidth - 64); - // if hwRound(Y) < (LAND_HEIGHT - 1024 - 75) then Y:= Y + int2hwFloat(25); // For if flag is set for flakes rising upwards? - if hwRound(Y) > (LAND_HEIGHT + 75) then Y:= Y - int2hwFloat(1024 + 150); // TODO - configure in theme (jellies for example could use limited range) - Timer:= 0; - tdX:= _0; - tdY:= _0 - end; - end; - -end; - -procedure doStepBeeTrace(Gear: PVisualGear; Steps: Longword); -begin -if Gear^.FrameTicks > Steps then - dec(Gear^.FrameTicks, Steps) -else - DeleteVisualGear(Gear); -end; - -procedure doStepCloud(Gear: PVisualGear; Steps: Longword); -var i: Longword; -begin -Gear^.X:= Gear^.X + (cWindSpeed * 200 + Gear^.dX) * Steps; - -for i:= 0 to Steps - 1 do - begin - if hwRound(Gear^.Y) > LAND_HEIGHT-1184 then // TODO - configure in theme - Gear^.dY:= Gear^.dY - _1div50000 - else - Gear^.dY:= Gear^.dY + _1div50000; - - Gear^.Y:= Gear^.Y + Gear^.dY - end; - -if hwRound(Gear^.X) < -cScreenWidth - 256 then Gear^.X:= int2hwFloat(cScreenWidth + LAND_WIDTH) else -if hwRound(Gear^.X) > cScreenWidth + LAND_WIDTH then Gear^.X:= int2hwFloat(-cScreenWidth - 256) -end; - -procedure doStepExpl(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; - -Gear^.Y:= Gear^.Y + Gear^.dY * Steps; -//Gear^.dY:= Gear^.dY + cGravity; - -if Gear^.FrameTicks <= Steps then - if Gear^.Frame = 0 then DeleteVisualGear(Gear) - else - begin - dec(Gear^.Frame); - Gear^.FrameTicks:= cExplFrameTicks - end - else dec(Gear^.FrameTicks, Steps) -end; - -procedure doStepEgg(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; - -Gear^.Y:= Gear^.Y + Gear^.dY * Steps; -Gear^.dY:= Gear^.dY + cGravity * Steps; - -Gear^.Angle:= round(Gear^.Angle + Steps) mod cMaxAngle; - -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps) -end; - -procedure doStepFire(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; - -Gear^.Y:= Gear^.Y + Gear^.dY * Steps;// + cGravity * (Steps * Steps); -Gear^.dY:= Gear^.dY + cGravity * Steps; - -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps) -end; - -procedure doStepShell(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; - -Gear^.Y:= Gear^.Y + Gear^.dY * Steps; -Gear^.dY:= Gear^.dY + cGravity * Steps; - -Gear^.Angle:= round(Gear^.Angle + Steps) mod cMaxAngle; - -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps) -end; - -procedure doStepSmallDamage(Gear: PVisualGear; Steps: Longword); -begin -Gear^.Y:= Gear^.Y - _0_02 * Steps; - -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps) -end; - -procedure doStepBubble(Gear: PVisualGear; Steps: Longword); -begin - Gear^.X:= Gear^.X + (cWindSpeed * 100 + Gear^.dX) * Steps; - Gear^.Y:= Gear^.Y - cDrownSpeed * Steps; - - if (Gear^.FrameTicks <= Steps) or (hwRound(Gear^.Y) < cWaterLine) then - DeleteVisualGear(Gear) - else - dec(Gear^.FrameTicks, Steps) -end; - -procedure doStepHealth(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; -Gear^.Y:= Gear^.Y - Gear^.dY * Steps; - -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps); -end; - -procedure doStepSteam(Gear: PVisualGear; Steps: Longword); -begin - Gear^.X:= Gear^.X + (cWindSpeed * 100 + Gear^.dX) * Steps; - Gear^.Y:= Gear^.Y - cDrownSpeed * Steps; - - if Gear^.FrameTicks <= Steps then - if Gear^.Frame = 0 then DeleteVisualGear(Gear) - else - begin - if Random(2) = 0 then dec(Gear^.Frame); - Gear^.FrameTicks:= cExplFrameTicks - end - else dec(Gear^.FrameTicks, Steps) -end; - -procedure doStepAmmo(Gear: PVisualGear; Steps: Longword); -begin - Gear^.Y:= Gear^.Y - cDrownSpeed * Steps; - - Gear^.scale:= Gear^.scale + 0.0025 * Steps; - Gear^.alpha:= Gear^.alpha - 0.0015 * Steps; - - if Gear^.alpha < 0 then DeleteVisualGear(Gear) -end; - -procedure doStepSmoke(Gear: PVisualGear; Steps: Longword); -begin - Gear^.X:= Gear^.X + (cWindSpeed + Gear^.dX) * Steps; - Gear^.Y:= Gear^.Y - (cDrownSpeed + Gear^.dY) * Steps; - - Gear^.dX := Gear^.dX + (cWindSpeed * _0_3 * Steps); - //Gear^.dY := Gear^.dY - (cDrownSpeed * _0_995); - - if Gear^.FrameTicks <= Steps then - if Gear^.Frame = 0 then DeleteVisualGear(Gear) - else - begin - if Random(2) = 0 then dec(Gear^.Frame); - Gear^.FrameTicks:= cExplFrameTicks - end - else dec(Gear^.FrameTicks, Steps) -end; - -procedure doStepDust(Gear: PVisualGear; Steps: Longword); -begin - Gear^.X:= Gear^.X + (cWindSpeed + (cWindSpeed * _0_03 * Steps) + Gear^.dX) * Steps; - Gear^.Y:= Gear^.Y - (Gear^.dY) * Steps; - - Gear^.dX := Gear^.dX - (Gear^.dX * _0_005 * Steps); - Gear^.dY := Gear^.dY - (cDrownSpeed * _0_001 * Steps); - - if Gear^.FrameTicks <= Steps then - if Gear^.Frame = 0 then DeleteVisualGear(Gear) - else - begin - dec(Gear^.Frame); - Gear^.FrameTicks:= cExplFrameTicks - end - else dec(Gear^.FrameTicks, Steps) -end; - -procedure doStepSplash(Gear: PVisualGear; Steps: Longword); -begin - if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) - else - dec(Gear^.FrameTicks, Steps); -end; - -procedure doStepDroplet(Gear: PVisualGear; Steps: Longword); -begin - Gear^.X:= Gear^.X + Gear^.dX * Steps; - - Gear^.Y:= Gear^.Y + Gear^.dY * Steps; - Gear^.dY:= Gear^.dY + cGravity * Steps; - - if hwRound(Gear^.Y) > cWaterLine then begin - DeleteVisualGear(Gear); - PlaySound(TSound(ord(sndDroplet1) + Random(3))); - end; -end; - -procedure doStepSmokeRing(Gear: PVisualGear; Steps: Longword); -begin -inc(Gear^.Timer, Steps); -if Gear^.Timer >= Gear^.FrameTicks then DeleteVisualGear(Gear) -else - begin - Gear^.scale := 1.25 * (-power(2, -10 * Int(Gear^.Timer)/Gear^.FrameTicks) + 1) + 0.4; - Gear^.alpha := 1 - power(Gear^.Timer / 350, 4); - if Gear^.alpha < 0 then Gear^.alpha:= 0; - end; -end; - -procedure doStepFeather(Gear: PVisualGear; Steps: Longword); -begin -Gear^.X:= Gear^.X + Gear^.dX * Steps; - -Gear^.Y:= Gear^.Y + Gear^.dY * Steps; -Gear^.dY:= Gear^.dY + cGravity * Steps; - -Gear^.Angle:= round(Gear^.Angle + Steps) mod cMaxAngle; - -if Gear^.FrameTicks <= Steps then - DeleteVisualGear(Gear) -else - dec(Gear^.FrameTicks, Steps) -end; -//////////////////////////////////////////////////////////////////////////////// -const cSorterWorkTime = 640; -var thexchar: array[0..cMaxTeams] of - record - dy, ny, dw: LongInt; - team: PTeam; - SortFactor: QWord; - end; - currsorter: PVisualGear = nil; - -procedure doStepTeamHealthSorterWork(Gear: PVisualGear; Steps: Longword); -var i, t: LongInt; -begin -for t:= 1 to Steps do - begin - dec(Gear^.Timer); - if (Gear^.Timer and 15) = 0 then - for i:= 0 to Pred(TeamsCount) do - with thexchar[i] do - begin - {$WARNINGS OFF} - team^.DrawHealthY:= ny + dy * LongInt(Gear^.Timer) div 640; - team^.TeamHealthBarWidth:= team^.NewTeamHealthBarWidth + dw * LongInt(Gear^.Timer) div cSorterWorkTime; - {$WARNINGS ON} - end; - - if (Gear^.Timer = 0) or (currsorter <> Gear) then - begin - if currsorter = Gear then currsorter:= nil; - DeleteVisualGear(Gear); - exit - end - end -end; - -procedure doStepTeamHealthSorter(Gear: PVisualGear; Steps: Longword); -var i: Longword; - b: boolean; - t: LongInt; -begin -Steps:= Steps; // avoid compiler hint -for t:= 0 to Pred(TeamsCount) do - with thexchar[t] do - begin - dy:= TeamsArray[t]^.DrawHealthY; - dw:= TeamsArray[t]^.TeamHealthBarWidth - TeamsArray[t]^.NewTeamHealthBarWidth; - team:= TeamsArray[t]; - SortFactor:= TeamsArray[t]^.Clan^.ClanHealth; - SortFactor:= (SortFactor shl 3) + TeamsArray[t]^.Clan^.ClanIndex; - SortFactor:= (SortFactor shl 30) + TeamsArray[t]^.TeamHealth; - end; - -if TeamsCount > 1 then - repeat - b:= true; - for t:= 0 to TeamsCount - 2 do - if (thexchar[t].SortFactor > thexchar[Succ(t)].SortFactor) then - begin - thexchar[cMaxTeams]:= thexchar[t]; - thexchar[t]:= thexchar[Succ(t)]; - thexchar[Succ(t)]:= thexchar[cMaxTeams]; - b:= false - end - until b; - -t:= - 4; -for i:= 0 to Pred(TeamsCount) do - with thexchar[i] do - begin - dec(t, team^.HealthTex^.h + 2); - ny:= t; - dy:= dy - ny - end; - -Gear^.Timer:= cSorterWorkTime; -Gear^.doStep:= @doStepTeamHealthSorterWork; -currsorter:= Gear; -//doStepTeamHealthSorterWork(Gear, Steps) -end; - -procedure doStepSpeechBubbleWork(Gear: PVisualGear; Steps: Longword); -begin -if Gear^.Timer > Steps then dec(Gear^.Timer, Steps) else Gear^.Timer:= 0; - -if (PHedgehog(Gear^.Hedgehog)^.Gear <> nil) then - begin - Gear^.X:= PHedgehog(Gear^.Hedgehog)^.Gear^.X + int2hwFloat(Gear^.Tex^.w div 2 - Gear^.FrameTicks); - Gear^.Y:= PHedgehog(Gear^.Hedgehog)^.Gear^.Y - int2hwFloat(16 + Gear^.Tex^.h); - end; - -if Gear^.Timer = 0 then - begin - if PHedgehog(Gear^.Hedgehog)^.SpeechGear = Gear then - PHedgehog(Gear^.Hedgehog)^.SpeechGear:= nil; - DeleteVisualGear(Gear) - end; -end; - -procedure doStepSpeechBubble(Gear: PVisualGear; Steps: Longword); -begin -Steps:= Steps; // avoid compiler hint - -with PHedgehog(Gear^.Hedgehog)^ do - if SpeechGear <> nil then SpeechGear^.Timer:= 0; - -PHedgehog(Gear^.Hedgehog)^.SpeechGear:= Gear; - -Gear^.Timer:= max(Length(Gear^.Text) * 150, 3000); - -Gear^.Tex:= RenderSpeechBubbleTex(Gear^.Text, Gear^.FrameTicks, fnt16); - -case Gear^.FrameTicks of - 1: Gear^.FrameTicks:= SpritesData[sprSpeechTail].Width-28; - 2: Gear^.FrameTicks:= SpritesData[sprThoughtTail].Width-20; - 3: Gear^.FrameTicks:= SpritesData[sprShoutTail].Width-10; - end; - -Gear^.doStep:= @doStepSpeechBubbleWork; - -Gear^.Y:= Gear^.Y - int2hwFloat(Gear^.Tex^.h) -end; // ================================================================== const doStepHandlers: array[TVisualGearType] of TVGearStepProcedure = @@ -500,10 +111,15 @@ @doStepSmokeRing, @doStepBeeTrace, @doStepEgg, - @doStepFeather + @doStepFeather, + @doStepHealthTag, + @doStepSmokeTrace, + @doStepSmokeTrace, + @doStepExplosion, + @doStepBigExplosion ); -function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType): PVisualGear; +function AddVisualGear(X, Y: LongInt; Kind: TVisualGearType; State: LongWord = 0): PVisualGear; var gear: PVisualGear; t: Longword; sp: hwFloat; @@ -530,6 +146,7 @@ gear^.Y:= int2hwFloat(Y); gear^.Kind := Kind; gear^.doStep:= doStepHandlers[Kind]; +gear^.State:= 0; with gear^ do case Kind of @@ -673,8 +290,24 @@ FrameTicks:= 650 + random(250); Frame:= 1 end; + vgtHealthTag: begin + gear^.Timer:= 1500; + //gear^.Z:= 2002; + end; + vgtSmokeTrace, + vgtEvilTrace: begin + gear^.X:= gear^.X - _16; + gear^.Y:= gear^.Y - _16; + gear^.State:= 8; + //gear^.Z:= cSmokeZ + end; +vgtBigExplosion: begin + gear^.Angle:= random(360); + end; end; +if State <> 0 then gear^.State:= State; + if VisualGearsList <> nil then begin VisualGearsList^.PrevGear:= gear; @@ -766,6 +399,16 @@ Tint($FF, $FF, $FF, $FF); end; end; + case Gear^.Kind of + vgtSmokeTrace: if Gear^.State < 8 then DrawSprite(sprSmokeTrace, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.State); + vgtEvilTrace: if Gear^.State < 8 then DrawSprite(sprEvilTrace, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.State); + vgtExplosion: DrawSprite(sprExplosion50, hwRound(Gear^.X) - 32 + WorldDx, hwRound(Gear^.Y) - 32 + WorldDy, Gear^.State); + vgtBigExplosion: begin + Tint($FF, $FF, $FF, floor($FF * (1 - power(Gear^.Timer / 250, 4)))); + DrawRotatedTextureF(SpritesData[sprBigExplosion].Texture, 0.85 * (-power(2, -10 * Int(Gear^.Timer)/250) + 1) + 0.4, 0, 0, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, 1, 385, 385, Gear^.Angle); + Tint($FF, $FF, $FF, $FF); + end; + end; Gear:= Gear^.NextGear end; 2: while Gear <> nil do @@ -824,6 +467,7 @@ case Gear^.Kind of vgtSmallDamageTag: DrawCentered(hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.Tex); vgtSpeechBubble: if Gear^.Tex <> nil then DrawCentered(hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.Tex); + vgtHealthTag: if Gear^.Tex <> nil then DrawCentered(hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.Tex); end; Gear:= Gear^.NextGear end