31 * |
31 * |
32 * Note: Gears that do not have an effect on the game but are just visual |
32 * Note: Gears that do not have an effect on the game but are just visual |
33 * effects are called "Visual Gears" and defined in the respective unit! |
33 * effects are called "Visual Gears" and defined in the respective unit! |
34 *) |
34 *) |
35 interface |
35 interface |
36 uses SDLh, uConsts, uFloat, uTypes; |
36 uses uConsts, uFloat, uTypes; |
37 |
37 |
38 procedure initModule; |
38 procedure initModule; |
39 procedure freeModule; |
39 procedure freeModule; |
40 function SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content, cnt: Longword): PGear; |
40 function SpawnCustomCrateAt(x, y: LongInt; crate: TCrateType; content, cnt: Longword): PGear; |
41 function SpawnFakeCrateAt(x, y: LongInt; crate: TCrateType; explode: boolean; poison: boolean ): PGear; |
41 function SpawnFakeCrateAt(x, y: LongInt; crate: TCrateType; explode: boolean; poison: boolean ): PGear; |
42 function GetAmmo(Hedgehog: PHedgehog): TAmmoType; |
|
43 function GetUtility(Hedgehog: PHedgehog): TAmmoType; |
|
44 procedure HideHog(HH: PHedgehog); |
|
45 procedure ProcessGears; |
42 procedure ProcessGears; |
46 procedure EndTurnCleanup; |
43 procedure EndTurnCleanup; |
47 procedure SetAllToActive; |
|
48 procedure SetAllHHToActive; inline; |
|
49 procedure SetAllHHToActive(Ice: boolean); |
|
50 procedure DrawGears; |
44 procedure DrawGears; |
51 procedure FreeGearsList; |
45 procedure FreeGearsList; |
52 procedure AddMiscGears; |
46 procedure AddMiscGears; |
53 procedure AssignHHCoords; |
47 procedure AssignHHCoords; |
54 function GearByUID(uid : Longword) : PGear; |
48 function GearByUID(uid : Longword) : PGear; |
55 procedure doStepDrowningGear(Gear: PGear); |
|
56 |
|
57 |
49 |
58 implementation |
50 implementation |
59 uses uStore, uSound, uTeams, uRandom, uCollisions, uIO, uLandGraphics, {$IFDEF SDL13}uTouch,{$ENDIF} |
51 uses uStore, uSound, uTeams, uRandom, uIO, uLandGraphics, {$IFDEF SDL13}uTouch,{$ENDIF} |
60 uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uVariables, |
52 uLocale, uAI, uAmmos, uStats, uVisualGears, uScript, GLunit, uVariables, |
61 uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture, |
53 uCommands, uUtils, uTextures, uRenderUtils, uGearsRender, uCaptions, uDebug, uLandTexture, |
62 uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlers, uGearsHandlersRope |
54 uGearsHedgehog, uGearsUtils, uGearsList, uGearsHandlersRope |
63 , uVisualGearsList; |
55 , uVisualGearsList, uGearsHandlersMess; |
64 |
56 |
65 var skipFlag: boolean; |
57 var skipFlag: boolean; |
66 |
|
67 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt); forward; |
|
68 //procedure AmmoFlameWork(Ammo: PGear); forward; |
|
69 function GearsNear(X, Y: hwFloat; Kind: TGearType; r: LongInt): PGearArrayS; forward; |
|
70 procedure SpawnBoxOfSmth; forward; |
|
71 procedure ShotgunShot(Gear: PGear); forward; |
|
72 procedure doStepCase(Gear: PGear); forward; |
|
73 |
|
74 |
58 |
75 var delay: LongWord; |
59 var delay: LongWord; |
76 delay2: LongWord; |
60 delay2: LongWord; |
77 step: (stDelay, stChDmg, stSweep, stTurnReact, |
61 step: (stDelay, stChDmg, stSweep, stTurnReact, |
78 stAfterDelay, stChWin, stWater, stChWin2, stHealth, |
62 stAfterDelay, stChWin, stWater, stChWin2, stHealth, |
79 stSpawn, stNTurn); |
63 stSpawn, stNTurn); |
80 upd: Longword; |
|
81 snowLeft,snowRight: LongInt; |
|
82 NewTurnTick: LongWord; |
64 NewTurnTick: LongWord; |
83 //SDMusic: shortstring; |
65 //SDMusic: shortstring; |
84 |
|
85 // For better maintainability the step handlers of gears are stored in |
|
86 // separate files. |
|
87 // Note: step handlers of gears that are hedgehogs are in a different file |
|
88 // than the handlers for all other gears. |
|
89 {$INCLUDE "GSHandlers.inc"} |
|
90 |
66 |
91 function CheckNoDamage: boolean; // returns TRUE in case of no damaged hhs |
67 function CheckNoDamage: boolean; // returns TRUE in case of no damaged hhs |
92 var Gear: PGear; |
68 var Gear: PGear; |
93 dmg: LongInt; |
69 dmg: LongInt; |
94 begin |
70 begin |
674 snowLeft:= -(snowRight-LAND_WIDTH); |
617 snowLeft:= -(snowRight-LAND_WIDTH); |
675 |
618 |
676 if (not hasBorder) and ((Theme = 'Snow') or (Theme = 'Christmas')) then |
619 if (not hasBorder) and ((Theme = 'Snow') or (Theme = 'Christmas')) then |
677 for i:= vobCount * Longword(max(LAND_WIDTH,4096)) div 2048 downto 1 do |
620 for i:= vobCount * Longword(max(LAND_WIDTH,4096)) div 2048 downto 1 do |
678 AddGear(LongInt(GetRandom(snowRight - snowLeft)) + snowLeft, LAND_HEIGHT + LongInt(GetRandom(750)) - 1300, gtFlake, 0, _0, _0, 0); |
621 AddGear(LongInt(GetRandom(snowRight - snowLeft)) + snowLeft, LAND_HEIGHT + LongInt(GetRandom(750)) - 1300, gtFlake, 0, _0, _0, 0); |
679 end; |
|
680 |
|
681 |
|
682 procedure ShotgunShot(Gear: PGear); |
|
683 var t: PGear; |
|
684 dmg, r, dist: LongInt; |
|
685 dx, dy: hwFloat; |
|
686 begin |
|
687 Gear^.Radius:= cShotgunRadius; |
|
688 t:= GearsList; |
|
689 while t <> nil do |
|
690 begin |
|
691 case t^.Kind of |
|
692 gtHedgehog, |
|
693 gtMine, |
|
694 gtSMine, |
|
695 gtKnife, |
|
696 gtCase, |
|
697 gtTarget, |
|
698 gtExplosives: begin//, |
|
699 // gtStructure: begin |
|
700 //addFileLog('ShotgunShot radius: ' + inttostr(Gear^.Radius) + ', t^.Radius = ' + inttostr(t^.Radius) + ', distance = ' + inttostr(dist) + ', dmg = ' + inttostr(dmg)); |
|
701 dmg:= 0; |
|
702 r:= Gear^.Radius + t^.Radius; |
|
703 dx:= Gear^.X-t^.X; |
|
704 dx.isNegative:= false; |
|
705 dy:= Gear^.Y-t^.Y; |
|
706 dy.isNegative:= false; |
|
707 if r-hwRound(dx+dy) > 0 then |
|
708 begin |
|
709 dist:= hwRound(Distance(dx, dy)); |
|
710 dmg:= ModifyDamage(min(r - dist, 25), t); |
|
711 end; |
|
712 if dmg > 0 then |
|
713 begin |
|
714 if (not t^.Invulnerable) then |
|
715 ApplyDamage(t, Gear^.Hedgehog, dmg, dsBullet) |
|
716 else |
|
717 Gear^.State:= Gear^.State or gstWinner; |
|
718 |
|
719 DeleteCI(t); |
|
720 t^.dX:= t^.dX + Gear^.dX * dmg * _0_01 + SignAs(cHHKick, Gear^.dX); |
|
721 t^.dY:= t^.dY + Gear^.dY * dmg * _0_01; |
|
722 t^.State:= t^.State or gstMoving; |
|
723 if t^.Kind = gtKnife then t^.State:= t^.State and (not gstCollision); |
|
724 t^.Active:= true; |
|
725 FollowGear:= t |
|
726 end |
|
727 end; |
|
728 gtGrave: begin |
|
729 dmg:= 0; |
|
730 r:= Gear^.Radius + t^.Radius; |
|
731 dx:= Gear^.X-t^.X; |
|
732 dx.isNegative:= false; |
|
733 dy:= Gear^.Y-t^.Y; |
|
734 dy.isNegative:= false; |
|
735 if r-hwRound(dx+dy) > 0 then |
|
736 begin |
|
737 dist:= hwRound(Distance(dx, dy)); |
|
738 dmg:= ModifyDamage(min(r - dist, 25), t); |
|
739 end; |
|
740 if dmg > 0 then |
|
741 begin |
|
742 t^.dY:= - _0_1; |
|
743 t^.Active:= true |
|
744 end |
|
745 end; |
|
746 end; |
|
747 t:= t^.NextGear |
|
748 end; |
|
749 if (GameFlags and gfSolidLand) = 0 then |
|
750 DrawExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), cShotgunRadius) |
|
751 end; |
|
752 |
|
753 procedure AmmoShove(Ammo: PGear; Damage, Power: LongInt); |
|
754 var t: PGearArray; |
|
755 Gear: PGear; |
|
756 i, j, tmpDmg: LongInt; |
|
757 VGear: PVisualGear; |
|
758 begin |
|
759 t:= CheckGearsCollision(Ammo); |
|
760 // Just to avoid hogs on rope dodging fire. |
|
761 if (CurAmmoGear <> nil) and ((CurAmmoGear^.Kind = gtRope) or (CurAmmoGear^.Kind = gtJetpack) or (CurAmmoGear^.Kind = gtBirdy)) |
|
762 and (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear^.CollisionIndex = -1) |
|
763 and (sqr(hwRound(Ammo^.X) - hwRound(CurrentHedgehog^.Gear^.X)) + sqr(hwRound(Ammo^.Y) - hwRound(CurrentHedgehog^.Gear^.Y)) <= sqr(cHHRadius + Ammo^.Radius)) then |
|
764 begin |
|
765 t^.ar[t^.Count]:= CurrentHedgehog^.Gear; |
|
766 inc(t^.Count) |
|
767 end; |
|
768 |
|
769 i:= t^.Count; |
|
770 |
|
771 if (Ammo^.Kind = gtFlame) and (i > 0) then |
|
772 Ammo^.Health:= 0; |
|
773 while i > 0 do |
|
774 begin |
|
775 dec(i); |
|
776 Gear:= t^.ar[i]; |
|
777 if ((Ammo^.Kind = gtFlame) or (Ammo^.Kind = gtBlowTorch)) and |
|
778 (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heFrozen] > 255) then |
|
779 Gear^.Hedgehog^.Effects[heFrozen]:= max(255,Gear^.Hedgehog^.Effects[heFrozen]-10000); |
|
780 tmpDmg:= ModifyDamage(Damage, Gear); |
|
781 if (Gear^.State and gstNoDamage) = 0 then |
|
782 begin |
|
783 |
|
784 if (Ammo^.Kind = gtDEagleShot) or (Ammo^.Kind = gtSniperRifleShot) then |
|
785 begin |
|
786 VGear := AddVisualGear(hwround(Ammo^.X), hwround(Ammo^.Y), vgtBulletHit); |
|
787 if VGear <> nil then |
|
788 VGear^.Angle := DxDy2Angle(-Ammo^.dX, Ammo^.dY); |
|
789 end; |
|
790 |
|
791 if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then |
|
792 Gear^.FlightTime:= 1; |
|
793 |
|
794 |
|
795 case Gear^.Kind of |
|
796 gtHedgehog, |
|
797 gtMine, |
|
798 gtSMine, |
|
799 gtKnife, |
|
800 gtTarget, |
|
801 gtCase, |
|
802 gtExplosives: //, |
|
803 //gtStructure: |
|
804 begin |
|
805 if (Ammo^.Kind = gtDrill) then |
|
806 begin |
|
807 Ammo^.Timer:= 0; |
|
808 exit; |
|
809 end; |
|
810 if (not Gear^.Invulnerable) then |
|
811 begin |
|
812 if (Ammo^.Kind = gtKnife) and (tmpDmg > 0) then |
|
813 for j:= 1 to max(1,min(3,tmpDmg div 5)) do |
|
814 begin |
|
815 VGear:= AddVisualGear(hwRound(Ammo^.X-((Ammo^.X-Gear^.X)/_2)), hwRound(Ammo^.Y-((Ammo^.Y-Gear^.Y)/_2)), vgtStraightShot); |
|
816 if VGear <> nil then |
|
817 with VGear^ do |
|
818 begin |
|
819 Tint:= $FFCC00FF; |
|
820 Angle:= random(360); |
|
821 dx:= 0.0005 * (random(100)); |
|
822 dy:= 0.0005 * (random(100)); |
|
823 if random(2) = 0 then |
|
824 dx := -dx; |
|
825 if random(2) = 0 then |
|
826 dy := -dy; |
|
827 FrameTicks:= 600+random(200); |
|
828 State:= ord(sprStar) |
|
829 end |
|
830 end; |
|
831 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg, dsShove) |
|
832 end |
|
833 else |
|
834 Gear^.State:= Gear^.State or gstWinner; |
|
835 if (Gear^.Kind = gtExplosives) and (Ammo^.Kind = gtBlowtorch) then |
|
836 begin |
|
837 if (Ammo^.Hedgehog^.Gear <> nil) then |
|
838 Ammo^.Hedgehog^.Gear^.State:= Ammo^.Hedgehog^.Gear^.State and (not gstNotKickable); |
|
839 ApplyDamage(Gear, Ammo^.Hedgehog, tmpDmg * 100, dsUnknown); // crank up damage for explosives + blowtorch |
|
840 end; |
|
841 |
|
842 if (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.King or (Gear^.Hedgehog^.Effects[heFrozen] > 0)) then |
|
843 begin |
|
844 Gear^.dX:= Ammo^.dX * Power * _0_005; |
|
845 Gear^.dY:= Ammo^.dY * Power * _0_005 |
|
846 end |
|
847 else if ((Ammo^.Kind <> gtFlame) or (Gear^.Kind = gtHedgehog)) and (Power <> 0) then |
|
848 begin |
|
849 Gear^.dX:= Ammo^.dX * Power * _0_01; |
|
850 Gear^.dY:= Ammo^.dY * Power * _0_01 |
|
851 end; |
|
852 |
|
853 if (not isZero(Gear^.dX)) or (not isZero(Gear^.dY)) then |
|
854 begin |
|
855 Gear^.Active:= true; |
|
856 DeleteCI(Gear); |
|
857 Gear^.State:= Gear^.State or gstMoving; |
|
858 if Gear^.Kind = gtKnife then Gear^.State:= Gear^.State and (not gstCollision); |
|
859 // move the gear upwards a bit to throw it over tiny obstacles at start |
|
860 if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then |
|
861 begin |
|
862 if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX)) |
|
863 or (TestCollisionYwithGear(Gear, -1) <> 0)) then |
|
864 Gear^.Y:= Gear^.Y - _1; |
|
865 if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) |
|
866 or (TestCollisionYwithGear(Gear, -1) <> 0)) then |
|
867 Gear^.Y:= Gear^.Y - _1; |
|
868 if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) |
|
869 or (TestCollisionYwithGear(Gear, -1) <> 0)) then |
|
870 Gear^.Y:= Gear^.Y - _1; |
|
871 end |
|
872 end; |
|
873 |
|
874 |
|
875 if (Ammo^.Kind <> gtFlame) or ((Ammo^.State and gsttmpFlag) = 0) then |
|
876 FollowGear:= Gear |
|
877 end; |
|
878 end |
|
879 end; |
|
880 end; |
|
881 if i <> 0 then |
|
882 SetAllToActive |
|
883 end; |
622 end; |
884 |
623 |
885 procedure AssignHHCoords; |
624 procedure AssignHHCoords; |
886 var i, t, p, j: LongInt; |
625 var i, t, p, j: LongInt; |
887 ar: array[0..Pred(cMaxHHs)] of PHedgehog; |
626 ar: array[0..Pred(cMaxHHs)] of PHedgehog; |
1076 |
775 |
1077 if ( (x = 0) and (y = 0) ) then |
776 if ( (x = 0) and (y = 0) ) then |
1078 FindPlace(FollowGear, true, 0, LAND_WIDTH); |
777 FindPlace(FollowGear, true, 0, LAND_WIDTH); |
1079 |
778 |
1080 SpawnFakeCrateAt := FollowGear; |
779 SpawnFakeCrateAt := FollowGear; |
1081 end; |
|
1082 |
|
1083 function GetAmmo(Hedgehog: PHedgehog): TAmmoType; |
|
1084 var t, aTot: LongInt; |
|
1085 i: TAmmoType; |
|
1086 begin |
|
1087 Hedgehog:= Hedgehog; // avoid hint |
|
1088 |
|
1089 aTot:= 0; |
|
1090 for i:= Low(TAmmoType) to High(TAmmoType) do |
|
1091 if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then |
|
1092 inc(aTot, Ammoz[i].Probability); |
|
1093 |
|
1094 t:= aTot; |
|
1095 i:= Low(TAmmoType); |
|
1096 if (t > 0) then |
|
1097 begin |
|
1098 t:= GetRandom(t); |
|
1099 while t >= 0 do |
|
1100 begin |
|
1101 inc(i); |
|
1102 if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then |
|
1103 dec(t, Ammoz[i].Probability) |
|
1104 end |
|
1105 end; |
|
1106 GetAmmo:= i |
|
1107 end; |
|
1108 |
|
1109 function GetUtility(Hedgehog: PHedgehog): TAmmoType; |
|
1110 var t, uTot: LongInt; |
|
1111 i: TAmmoType; |
|
1112 begin |
|
1113 |
|
1114 uTot:= 0; |
|
1115 for i:= Low(TAmmoType) to High(TAmmoType) do |
|
1116 if ((Ammoz[i].Ammo.Propz and ammoprop_Utility) <> 0) |
|
1117 and ((Hedgehog^.Team^.HedgehogsNumber > 1) or (Ammoz[i].Ammo.AmmoType <> amSwitch)) then |
|
1118 inc(uTot, Ammoz[i].Probability); |
|
1119 |
|
1120 t:= uTot; |
|
1121 i:= Low(TAmmoType); |
|
1122 if (t > 0) then |
|
1123 begin |
|
1124 t:= GetRandom(t); |
|
1125 while t >= 0 do |
|
1126 begin |
|
1127 inc(i); |
|
1128 if ((Ammoz[i].Ammo.Propz and ammoprop_Utility) <> 0) and ((Hedgehog^.Team^.HedgehogsNumber > 1) |
|
1129 or (Ammoz[i].Ammo.AmmoType <> amSwitch)) then |
|
1130 dec(t, Ammoz[i].Probability) |
|
1131 end |
|
1132 end; |
|
1133 GetUtility:= i |
|
1134 end; |
|
1135 |
|
1136 |
|
1137 |
|
1138 procedure SpawnBoxOfSmth; |
|
1139 var t, aTot, uTot, a, h: LongInt; |
|
1140 i: TAmmoType; |
|
1141 begin |
|
1142 if (PlacingHogs) or |
|
1143 (cCaseFactor = 0) |
|
1144 or (CountGears(gtCase) >= 5) |
|
1145 or (GetRandom(cCaseFactor) <> 0) then |
|
1146 exit; |
|
1147 |
|
1148 FollowGear:= nil; |
|
1149 aTot:= 0; |
|
1150 uTot:= 0; |
|
1151 for i:= Low(TAmmoType) to High(TAmmoType) do |
|
1152 if (Ammoz[i].Ammo.Propz and ammoprop_Utility) = 0 then |
|
1153 inc(aTot, Ammoz[i].Probability) |
|
1154 else |
|
1155 inc(uTot, Ammoz[i].Probability); |
|
1156 |
|
1157 t:=0; |
|
1158 a:=aTot; |
|
1159 h:= 1; |
|
1160 |
|
1161 if (aTot+uTot) <> 0 then |
|
1162 if ((GameFlags and gfInvulnerable) = 0) then |
|
1163 begin |
|
1164 h:= cHealthCaseProb * 100; |
|
1165 t:= GetRandom(10000); |
|
1166 a:= (10000-h)*aTot div (aTot+uTot) |
|
1167 end |
|
1168 else |
|
1169 begin |
|
1170 t:= GetRandom(aTot+uTot); |
|
1171 h:= 0 |
|
1172 end; |
|
1173 |
|
1174 |
|
1175 if t<h then |
|
1176 begin |
|
1177 FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0); |
|
1178 FollowGear^.Health:= cHealthCaseAmount; |
|
1179 FollowGear^.Pos:= posCaseHealth; |
|
1180 AddCaption(GetEventString(eidNewHealthPack), cWhiteColor, capgrpAmmoInfo); |
|
1181 end |
|
1182 else if (t<a+h) then |
|
1183 begin |
|
1184 t:= aTot; |
|
1185 if (t > 0) then |
|
1186 begin |
|
1187 FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0); |
|
1188 t:= GetRandom(t); |
|
1189 i:= Low(TAmmoType); |
|
1190 FollowGear^.Pos:= posCaseAmmo; |
|
1191 FollowGear^.AmmoType:= i; |
|
1192 AddCaption(GetEventString(eidNewAmmoPack), cWhiteColor, capgrpAmmoInfo); |
|
1193 end |
|
1194 end |
|
1195 else |
|
1196 begin |
|
1197 t:= uTot; |
|
1198 if (t > 0) then |
|
1199 begin |
|
1200 FollowGear:= AddGear(0, 0, gtCase, 0, _0, _0, 0); |
|
1201 t:= GetRandom(t); |
|
1202 i:= Low(TAmmoType); |
|
1203 FollowGear^.Pos:= posCaseUtility; |
|
1204 FollowGear^.AmmoType:= i; |
|
1205 AddCaption(GetEventString(eidNewUtilityPack), cWhiteColor, capgrpAmmoInfo); |
|
1206 end |
|
1207 end; |
|
1208 |
|
1209 // handles case of no ammo or utility crates - considered also placing booleans in uAmmos and altering probabilities |
|
1210 if (FollowGear <> nil) then |
|
1211 begin |
|
1212 FindPlace(FollowGear, true, 0, LAND_WIDTH); |
|
1213 |
|
1214 if (FollowGear <> nil) then |
|
1215 AddVoice(sndReinforce, CurrentTeam^.voicepack) |
|
1216 end |
|
1217 end; |
780 end; |
1218 |
781 |
1219 |
782 |
1220 function GearByUID(uid : Longword) : PGear; |
783 function GearByUID(uid : Longword) : PGear; |
1221 var gear: PGear; |
784 var gear: PGear; |