3042 exit |
3042 exit |
3043 end; |
3043 end; |
3044 end; |
3044 end; |
3045 |
3045 |
3046 //////////////////////////////////////////////////////////////////////////////// |
3046 //////////////////////////////////////////////////////////////////////////////// |
|
3047 procedure doPortalColorSwitch(); |
|
3048 var flags: LongWord; |
|
3049 begin |
|
3050 if (CurrentHedgehog <> nil) |
|
3051 and (CurrentHedgehog^.Gear <> nil) |
|
3052 and ((CurrentHedgehog^.Gear^.Message and gm_Switch) <> 0) then |
|
3053 With CurrentHedgehog^ do |
|
3054 if (Ammo^[CurSlot, CurAmmo].AmmoType = amPortalGun) then |
|
3055 begin |
|
3056 CurrentHedgehog^.Gear^.Message:= CurrentHedgehog^.Gear^.Message and not gm_Switch; |
|
3057 |
|
3058 flags:= Ammo^[CurSlot, CurAmmo].Timer and not 2; |
|
3059 if (flags and 1) = 0 then |
|
3060 Ammo^[CurSlot, CurAmmo].Timer:= flags or 1 |
|
3061 else |
|
3062 Ammo^[CurSlot, CurAmmo].Timer:= flags and not 1; |
|
3063 end; |
|
3064 end; |
|
3065 |
3047 procedure doStepPortal(Gear: PGear); |
3066 procedure doStepPortal(Gear: PGear); |
3048 var iterator, conPortal: PGear; |
3067 var iterator, conPortal: PGear; |
3049 s, acptRadius: hwFloat; |
3068 s, acptRadius, cdxy: hwFloat; |
3050 noTrap, hasdxy: Boolean; |
3069 noTrap, hasdxy: Boolean; |
3051 begin |
3070 begin |
|
3071 doPortalColorSwitch(); |
|
3072 |
3052 // destroy portal if ground it was attached too is gone |
3073 // destroy portal if ground it was attached too is gone |
3053 if (Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0 then deleteGear(Gear); |
3074 if ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0) |
|
3075 or (Gear^.Timer < 1) |
|
3076 or (hwRound(Gear^.Y) > cWaterLine) then |
|
3077 begin |
|
3078 deleteGear(Gear); |
|
3079 EXIT; |
|
3080 end; |
|
3081 |
|
3082 if (TurnTimeLeft < 1) |
|
3083 or (Gear^.Health < 1) then |
|
3084 dec(Gear^.Timer); |
|
3085 |
|
3086 if Gear^.Timer < 10000 then |
|
3087 gear^.RenderTimer:= true; |
3054 |
3088 |
3055 // abort if there is no other portal connected to this one |
3089 // abort if there is no other portal connected to this one |
3056 if Gear^.IntersectGear = nil then |
3090 if (Gear^.IntersectGear = nil) then |
|
3091 exit; |
|
3092 if ((Gear^.IntersectGear^.Tag and 1) = 0) then // or if it's still moving; |
3057 exit; |
3093 exit; |
3058 |
3094 |
3059 conPortal:= Gear^.IntersectGear; |
3095 conPortal:= Gear^.IntersectGear; |
3060 |
3096 |
3061 // check all gears for stuff to port through |
3097 // check all gears for stuff to port through |
3103 // wow! good candidate there, let's see if the distance really is small enough! |
3138 // wow! good candidate there, let's see if the distance really is small enough! |
3104 if (Distance(Gear^.X-iterator^.X,Gear^.Y-iterator^.Y) > acptRadius) then |
3139 if (Distance(Gear^.X-iterator^.X,Gear^.Y-iterator^.Y) > acptRadius) then |
3105 continue; |
3140 continue; |
3106 |
3141 |
3107 noTrap:= ((not Gear^.dY.isNegative or (Gear^.dY.QWordValue = 0)) // can't be entered from above |
3142 noTrap:= ((not Gear^.dY.isNegative or (Gear^.dY.QWordValue = 0)) // can't be entered from above |
3108 or ((conPortal^.dY.isNegative or (conPortal^.dY.QWordValue = 0)))); // can't be left downwards; |
3143 or ((conPortal^.dY.isNegative and not (conPortal^.dY.QWordValue = 0)))); // can't be left downwards; |
3109 |
3144 |
3110 |
3145 // prevent getting stuck in a ground portal loop |
3111 // lets see if this one is just stuck in a stuck-loop |
3146 if noTrap and (iterator^.dY.QWordValue < _0_08.QWordValue) then |
3112 if noTrap and (iterator^.dY.QWordValue < _0_1.QWordValue) then |
|
3113 continue; |
3147 continue; |
3114 |
3148 |
3115 iterator^.Active:= true; |
3149 iterator^.Active:= true; |
3116 iterator^.State:= iterator^.State or gstMoving; |
3150 iterator^.State:= iterator^.State or gstMoving; |
3117 DeleteCI(iterator); |
3151 DeleteCI(iterator); |
3118 |
3152 |
3119 s:= (_1+(Int2hwFloat(Gear^.Radius))) / Distance(conPortal^.dX, conPortal^.dY); |
3153 // TODO: more accurate porting |
|
3154 cdxy:= Distance(conPortal^.dX, conPortal^.dY); |
|
3155 s:= (Int2hwFloat(Gear^.Radius)) / cdxy; |
|
3156 |
3120 iterator^.X:= conPortal^.X + s * conPortal^.dX; |
3157 iterator^.X:= conPortal^.X + s * conPortal^.dX; |
3121 iterator^.Y:= conPortal^.Y + s * conPortal^.dY; |
3158 iterator^.Y:= conPortal^.Y + s * conPortal^.dY; |
3122 s:= Distance(iterator^.dX, iterator^.dY) / Distance(conPortal^.dX, conPortal^.dY); |
3159 |
|
3160 s:= Distance(iterator^.dX, iterator^.dY) / cdxy; |
|
3161 |
3123 iterator^.dX:= s * conPortal^.dX; |
3162 iterator^.dX:= s * conPortal^.dX; |
3124 iterator^.dY:= s * conPortal^.dY; |
3163 iterator^.dY:= s * conPortal^.dY; |
|
3164 |
|
3165 FollowGear:= iterator; |
|
3166 |
|
3167 s:= _0_2 + _0_008 * Gear^.Health; |
|
3168 iterator^.dX:= s * iterator^.dX; |
|
3169 iterator^.dY:= s * iterator^.dY; |
3125 |
3170 |
3126 if iterator^.dY.isNegative and (iterator^.dY.QWordValue <> 0) then |
3171 if Gear^.Health > 1 then |
3127 iterator^.dY:= iterator^.dY + hwAbs(Int2hwFloat(iterator^.Radius) / iterator^.dY) * cGravity; |
3172 begin |
|
3173 dec(Gear^.Health); |
|
3174 dec(iterator^.Health); |
|
3175 end; |
3128 |
3176 |
3129 // breaks (some) loops |
3177 // breaks (some) loops |
3130 if Distance(iterator^.dX, iterator^.dY) > _0_96 then |
3178 if Distance(iterator^.dX, iterator^.dY) > _0_96 then |
3131 begin |
3179 begin |
3132 iterator^.dX:= iterator^.dX + signAs(cGravity * getRandom(1000),iterator^.dX); |
3180 iterator^.dX:= iterator^.dX + signAs(cGravity * getRandom(1000),iterator^.dX); |
3133 iterator^.dY:= iterator^.dY + signAs(cGravity * getRandom(1000),iterator^.dY); |
3181 iterator^.dY:= iterator^.dY + signAs(cGravity * getRandom(1000),iterator^.dY); |
3134 s:= _0_995 / Distance(iterator^.dX, iterator^.dY); |
3182 s:= _0_96 / Distance(iterator^.dX, iterator^.dY); |
3135 iterator^.dX:= s * iterator^.dX; |
3183 iterator^.dX:= s * iterator^.dX; |
3136 iterator^.dY:= s * iterator^.dX; |
3184 iterator^.dY:= s * iterator^.dX; |
3137 end; |
3185 end; |
3138 |
|
3139 iterator:= iterator^.NextGear; |
|
3140 end; |
3186 end; |
3141 end; |
3187 end; |
3142 |
3188 |
3143 procedure doStepMovingPortal(Gear: PGear); |
3189 procedure doStepMovingPortal(Gear: PGear); |
3144 var x, y, tx, ty: LongInt;//, bx, by, tangle: LongInt; |
3190 var x, y, tx, ty: LongInt;//, bx, by, tangle: LongInt; |
3145 s, dx, dy: hwFloat; |
3191 s, dx, dy: hwFloat; |
3146 begin |
3192 |
|
3193 procedure loadNewPortalBall(oldPortal: PGear; destroyGear: Boolean); |
|
3194 var flags: LongWord; |
|
3195 begin |
|
3196 if CurrentHedgehog <> nil then |
|
3197 With CurrentHedgehog^ do |
|
3198 if (Ammo^[CurSlot, CurAmmo].AmmoType = amPortalGun) then |
|
3199 begin |
|
3200 flags:= Ammo^[CurSlot, CurAmmo].Timer; |
|
3201 |
|
3202 if destroyGear xor ((oldPortal^.Tag and 2) = 0) then |
|
3203 flags:= flags or 1 |
|
3204 else |
|
3205 flags:= flags and not 1; |
|
3206 |
|
3207 Ammo^[CurSlot, CurAmmo].Timer:= flags and not 2; // make the ball visible |
|
3208 end; |
|
3209 |
|
3210 if destroyGear then deleteGear(oldPortal); |
|
3211 end; |
|
3212 |
|
3213 begin |
|
3214 doPortalColorSwitch(); |
|
3215 |
3147 Gear^.X:= Gear^.X + Gear^.dX; |
3216 Gear^.X:= Gear^.X + Gear^.dX; |
3148 Gear^.Y:= Gear^.Y + Gear^.dY; |
3217 Gear^.Y:= Gear^.Y + Gear^.dY; |
3149 x:= hwRound(Gear^.X); |
3218 x:= hwRound(Gear^.X); |
3150 y:= hwRound(Gear^.Y); |
3219 y:= hwRound(Gear^.Y); |
3151 tx:= 0; ty:= 0; // avoid compiler hints |
3220 tx:= 0; ty:= 0; // avoid compiler hints |
3152 |
3221 |
3153 if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] > 255) then |
3222 if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] > 255) then |
3154 begin |
3223 begin |
3155 if not calcSlopeTangent(Gear, x, y, tx, ty, 255) then |
3224 if not calcSlopeTangent(Gear, x, y, tx, ty, 255) |
3156 begin |
3225 or (DistanceI(tx,ty) < _12) then // reject shots at too irregular terrain |
3157 deleteGear(Gear); |
3226 begin |
3158 EXIT; |
3227 loadNewPortalBall(Gear, true); |
3159 end; |
3228 EXIT; |
3160 |
3229 end; |
3161 // reject shots at too irregular terrain |
|
3162 if DistanceI(tx,ty) < _12 then |
|
3163 begin |
|
3164 deleteGear(Gear); |
|
3165 EXIT; |
|
3166 end; |
|
3167 |
3230 |
3168 // making a normal, normalized vector |
3231 // making a normalized normal vector |
3169 s:= _1/DistanceI(tx,ty); |
3232 s:= _1/DistanceI(tx,ty); |
3170 dx:= -s * ty; |
3233 dx:= -s * ty; |
3171 dy:= s * tx; |
3234 dy:= s * tx; |
3172 |
3235 |
3173 // make sure the vector is pointing outwards |
3236 // make sure the vector is pointing outwards |
3174 if not (Gear^.dX*dx + Gear^.dY*dy).isNegative then |
3237 if not (Gear^.dX*dx + Gear^.dY*dy).isNegative then |
3175 begin |
3238 begin |
3176 dx:= -dx; |
3239 dx:= -dx; |
3177 dy:= -dy; |
3240 dy:= -dy; |
3178 end; |
3241 end; |
3179 |
3242 |
3180 Gear^.dX:= dx; |
3243 Gear^.dX:= dx; |
3181 Gear^.dY:= dy; |
3244 Gear^.dY:= dy; |
3182 |
3245 |
3183 Gear^.DirAngle:= DxDy2Angle(-dy,dx); |
3246 Gear^.DirAngle:= DxDy2Angle(-dy,dx); |
3184 if not Gear^.dX.isNegative then Gear^.DirAngle:= 180-Gear^.DirAngle; |
3247 if not Gear^.dX.isNegative then Gear^.DirAngle:= 180-Gear^.DirAngle; |
3185 |
3248 |
3186 if ((Gear^.IntersectGear <> nil) and (hwRound(Distance(Gear^.X - Gear^.IntersectGear^.X,Gear^.Y-Gear^.IntersectGear^.Y)) < Gear^.Radius*2)) |
3249 if ((Gear^.IntersectGear = nil) |
|
3250 or (hwRound(Distance(Gear^.X - Gear^.IntersectGear^.X,Gear^.Y-Gear^.IntersectGear^.Y)) >= Gear^.Radius*2)) |
3187 then |
3251 then |
3188 begin |
3252 begin |
3189 if CurrentHedgehog <> nil then |
3253 loadNewPortalBall(Gear, false); |
3190 if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1 |
3254 inc(Gear^.Tag); |
3191 else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2 |
3255 Gear^.doStep:= @doStepPortal; |
3192 else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1; |
|
3193 deleteGear(Gear) |
|
3194 end |
3256 end |
3195 else |
3257 else |
3196 begin |
3258 loadNewPortalBall(Gear, true); |
3197 if CurrentHedgehog <> nil then |
3259 end |
3198 if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1 |
3260 else if (y > cWaterLine) or (y < -LAND_WIDTH) |
3199 else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2; |
3261 or (x > 2*LAND_WIDTH) or (x < -LAND_WIDTH) then |
3200 inc(Gear^.Tag); |
3262 loadNewPortalBall(Gear, true); |
3201 Gear^.doStep:= @doStepPortal; |
3263 end; |
3202 if Gear^.IntersectGear <> nil then Gear^.IntersectGear^.IntersectGear:= Gear; |
3264 |
3203 end |
3265 procedure doStepPortalShot(newPortal: PGear); |
3204 end |
3266 var iterator: PGear; |
3205 else if (y > cWaterLine + cVisibleWater + Gear^.Radius) or (y < -LAND_WIDTH) or (x > LAND_WIDTH + LAND_WIDTH) or (x < -LAND_WIDTH) then |
3267 begin |
3206 begin |
3268 newPortal^.IntersectGear:= nil; |
3207 if CurrentHedgehog <> nil then |
3269 |
3208 if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1 |
3270 if CurrentHedgehog <> nil then |
3209 else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2 |
3271 With CurrentHedgehog^ do |
3210 else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1; |
3272 begin |
3211 deleteGear(Gear); |
3273 // make portal gun look unloaded |
3212 end; |
3274 Ammo^[CurSlot, CurAmmo].Timer:= Ammo^[CurSlot, CurAmmo].Timer or 2; |
|
3275 |
|
3276 // set portal to the currently chosen color |
|
3277 if ((Ammo^[CurSlot, CurAmmo].Timer and 1) <> 0) then |
|
3278 newPortal^.Tag:= newPortal^.Tag or 2; |
|
3279 |
|
3280 iterator:= GearsList; |
|
3281 while iterator <> nil do |
|
3282 begin |
|
3283 if (iterator^.Kind = gtPortal) then |
|
3284 if (iterator <> newPortal) then |
|
3285 begin |
|
3286 if (iterator^.Tag and 2) = (newPortal^.Tag and 2) then |
|
3287 begin |
|
3288 iterator:= iterator^.PrevGear; |
|
3289 deleteGear(iterator^.NextGear); |
|
3290 continue; |
|
3291 end |
|
3292 else |
|
3293 begin // link portals with each other |
|
3294 newPortal^.IntersectGear:= iterator; |
|
3295 iterator^.IntersectGear:= newPortal; |
|
3296 iterator^.Health:= newPortal^.Health; |
|
3297 end; |
|
3298 end; |
|
3299 iterator:= iterator^.NextGear |
|
3300 end; |
|
3301 end; |
|
3302 newPortal^.doStep:= @doStepMovingPortal; |
3213 end; |
3303 end; |
3214 |
3304 |
3215 procedure doStepPiano(Gear: PGear); |
3305 procedure doStepPiano(Gear: PGear); |
3216 var r0, r1: LongInt; |
3306 var r0, r1: LongInt; |
3217 begin |
3307 begin |