hedgewars/GSHandlers.inc
changeset 4050 8e4f4b72c132
parent 4047 6c07a302b7c0
child 4076 7ca17cb94992
equal deleted inserted replaced
4049:fe799b5d601b 4050:8e4f4b72c132
  3340 end;
  3340 end;
  3341 
  3341 
  3342 procedure doStepPortal(Gear: PGear);
  3342 procedure doStepPortal(Gear: PGear);
  3343 var 
  3343 var 
  3344     iterator, conPortal: PGear;
  3344     iterator, conPortal: PGear;
  3345     s, acptRadius, nx, ny, ox, oy, poffs, noffs, pspeed, nspeed: hwFloat;
  3345     s, r, nx, ny, ox, oy, poffs, noffs, pspeed, nspeed: hwFloat;
  3346     hasdxy: Boolean;
  3346     hasdxy, isbullet: Boolean;
  3347 begin
  3347 begin
  3348     doPortalColorSwitch();
  3348     doPortalColorSwitch();
  3349 
  3349 
  3350     // destroy portal if ground it was attached too is gone
  3350     // destroy portal if ground it was attached too is gone
  3351     if ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0)
  3351     if ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0)
  3386         // end of list?
  3386         // end of list?
  3387         if iterator = nil then
  3387         if iterator = nil then
  3388             break;
  3388             break;
  3389 
  3389 
  3390         // don't port portals or other gear that wouldn't make sense
  3390         // don't port portals or other gear that wouldn't make sense
  3391         if (iterator^.Kind = gtPortal) or (iterator^.Kind = gtRope)
  3391         if (iterator^.Kind in [gtPortal, gtRope, gtRCPlane])
  3392         or (iterator^.Kind = gtRCPlane) or (iterator^.PortalCounter > 20) then
  3392             or (iterator^.PortalCounter > 20) then
  3393             continue;
  3393              continue;
  3394 
  3394 
  3395         // don't port hogs on rope
  3395         // don't port hogs on rope
  3396         if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil)
  3396         if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil)
  3397            and (iterator = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.Kind =
  3397            and (iterator = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.Kind =
  3398            gtRope) then
  3398            gtRope) then
  3401         // check if gear fits through portal
  3401         // check if gear fits through portal
  3402         if (iterator^.Radius > Gear^.Radius) then
  3402         if (iterator^.Radius > Gear^.Radius) then
  3403             continue;
  3403             continue;
  3404 
  3404 
  3405         // this is the max range we accept incoming gears in
  3405         // this is the max range we accept incoming gears in
  3406         acptRadius := Int2hwFloat(iterator^.Radius+Gear^.Radius);
  3406         r := Int2hwFloat(iterator^.Radius+Gear^.Radius);
  3407 
  3407 
  3408         // too far away?
  3408         // too far away?
  3409         if (iterator^.X < Gear^.X - acptRadius)
  3409         if (iterator^.X < Gear^.X - r)
  3410            or (iterator^.X > Gear^.X + acptRadius)
  3410            or (iterator^.X > Gear^.X + r)
  3411            or (iterator^.Y < Gear^.Y - acptRadius)
  3411            or (iterator^.Y < Gear^.Y - r)
  3412            or (iterator^.Y > Gear^.Y + acptRadius) then
  3412            or (iterator^.Y > Gear^.Y + r) then
  3413             continue;
  3413             continue;
  3414 
  3414 
  3415         hasdxy := ((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0));
  3415         hasdxy := ((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0));
  3416 
  3416 
  3417         // in case the object is not moving, let's asume it's moving towards the portal
  3417         // in case the object is not moving, let's asume it's moving towards the portal
  3424         begin
  3424         begin
  3425             ox:= iterator^.dX;
  3425             ox:= iterator^.dX;
  3426             oy:= iterator^.dY;
  3426             oy:= iterator^.dY;
  3427         end;
  3427         end;
  3428 
  3428 
  3429         // won't port stuff that moves away from me!
  3429         // won't port stuff that does not move towards the front/portal entrance
  3430         if not (Gear^.dX*ox + Gear^.dY*oy).isNegative then
  3430         if not (Gear^.dX*ox + Gear^.dY*oy).isNegative then
  3431                 continue;
  3431                 continue;
  3432 
  3432 
  3433         if (iterator^.Kind <> gtCake) then
  3433         isbullet:= (iterator^.Kind in [gtShotgunShot, gtDEagleShot, gtSniperRifleShot, gtSineGunShot]);
       
  3434 
       
  3435         r:= int2hwFloat(iterator^.Radius);
       
  3436 
       
  3437         if not isbullet and (iterator^.Kind <> gtCake) then
  3434         begin
  3438         begin
  3435             // wow! good candidate there, let's see if the distance and direction is okay!
  3439             // wow! good candidate there, let's see if the distance and direction is okay!
  3436             if hasdxy then
  3440             if hasdxy then
  3437             begin
  3441             begin
  3438                 s := int2hwFloat(iterator^.Radius) / Distance(iterator^.dX, iterator^.dY);
  3442                 s := r / Distance(iterator^.dX, iterator^.dY);
  3439                 ox:= iterator^.X + s * iterator^.dX;
  3443                 ox:= iterator^.X + s * iterator^.dX;
  3440                 oy:= iterator^.Y + s * iterator^.dY;
  3444                 oy:= iterator^.Y + s * iterator^.dY;
  3441             end
  3445             end
  3442             else
  3446             else
  3443             begin
  3447             begin
  3444                 ox:= iterator^.X;
  3448                 ox:= iterator^.X;
  3445                 oy:= iterator^.Y + Int2hwFloat(iterator^.Radius);
  3449                 oy:= iterator^.Y + r;
  3446             end;
  3450             end;
  3447 
  3451 
  3448             if (hwRound(Distance(Gear^.X-ox,Gear^.Y-oy)) > Gear^.Radius + 1 ) then
  3452             if (hwRound(Distance(Gear^.X-ox,Gear^.Y-oy)) > Gear^.Radius + 1 ) then
  3449                 continue;
  3453                 continue;
  3450         end;
  3454         end;
  3457 
  3461 
  3458         // prevent getting stuck in a ground portal loop       
  3462         // prevent getting stuck in a ground portal loop       
  3459         if noTrap and (iterator^.dY.QWordValue < _0_08.QWordValue) then
  3463         if noTrap and (iterator^.dY.QWordValue < _0_08.QWordValue) then
  3460             continue; *)
  3464             continue; *)
  3461 
  3465 
  3462         iterator^.Active := true;
  3466         // calc gear offset in portal vector direction
  3463         iterator^.State := iterator^.State or gstMoving;
       
  3464         DeleteCI(iterator);
       
  3465 
       
  3466         // Until loops are reliably broken
       
  3467         inc(iterator^.PortalCounter);
       
  3468 
       
  3469         // find out how much speed parallel to the portal vector
       
  3470         // the gear has, also get the vector offset
       
  3471         pspeed:= (Gear^.dX * iterator^.dX + Gear^.dY * iterator^.dY);
       
  3472         ox := (iterator^.X - Gear^.X);
  3467         ox := (iterator^.X - Gear^.X);
  3473         oy := (iterator^.Y - Gear^.Y);
  3468         oy := (iterator^.Y - Gear^.Y);
  3474         poffs:= (Gear^.dX * ox + Gear^.dY * oy);
  3469         poffs:= (Gear^.dX * ox + Gear^.dY * oy);
       
  3470 
       
  3471         if poffs < _0 then
       
  3472             continue;
       
  3473 
       
  3474         // don't port stuff that isn't really close;
       
  3475         if not isbullet and (poffs > (r + _3)) then
       
  3476             continue;
       
  3477 
       
  3478         if isbullet then
       
  3479             poffs:= _1_5;
       
  3480 
  3475         // create a normal of the portal vector, but ...
  3481         // create a normal of the portal vector, but ...
  3476         nx := Gear^.dY;
  3482         nx := Gear^.dY;
  3477         ny := Gear^.dX;
  3483         ny := Gear^.dX;
  3478         // ... decide where the top is based on the hog's direction when firing the portal
  3484         // ... decide where the top is based on the hog's direction when firing the portal
  3479         if Gear^.Elasticity.isNegative then
  3485         if Gear^.Elasticity.isNegative then
  3480             nx.isNegative := not nx.isNegative
  3486             nx.isNegative := not nx.isNegative
  3481         else
  3487         else
  3482             ny.isNegative := not ny.isNegative;
  3488             ny.isNegative := not ny.isNegative;
  3483 
  3489 
  3484         // now let's find out how much speed the gear has in the
  3490         // calc gear offset in portal normal vector direction
  3485         // direction of that normal
  3491         noffs:= (nx * ox + ny * oy);
       
  3492 
       
  3493         // don't port stuff that misses the portal entrance
       
  3494         if noffs > (r + _1_5) then
       
  3495             continue;
       
  3496 
       
  3497         // move stuff with high normal offset close to the portal's center
       
  3498         if not isbullet then
       
  3499         begin
       
  3500             s := hwAbs(noffs) + r - int2hwFloat(Gear^.Radius);
       
  3501             if s > _0 then
       
  3502                 noffs:= noffs - SignAs(s,noffs)
       
  3503         end;
       
  3504 
       
  3505         //
       
  3506         // gears that make it till here will definately be ported
       
  3507         //
       
  3508 
       
  3509         iterator^.Active := true;
       
  3510         iterator^.State := iterator^.State or gstMoving;
       
  3511         DeleteCI(iterator);
       
  3512 
       
  3513         // Until loops are reliably broken
       
  3514         inc(iterator^.PortalCounter);
       
  3515 
       
  3516         // calc gear speed along to the vector and the normal vector of the portal
       
  3517         pspeed:= (Gear^.dX * iterator^.dX + Gear^.dY * iterator^.dY);
  3486         nspeed:= (nx * iterator^.dX + ny * iterator^.dY);
  3518         nspeed:= (nx * iterator^.dX + ny * iterator^.dY);
  3487         noffs:= (nx * ox + ny * oy);
  3519 
  3488 
  3520         // creating normal vector of connected (exit) portal
  3489         // now let's project those back to the connected portal's vectors
       
  3490         nx := conPortal^.dY;
  3521         nx := conPortal^.dY;
  3491         ny := conPortal^.dX;
  3522         ny := conPortal^.dX;
  3492         if conPortal^.Elasticity.isNegative then
  3523         if conPortal^.Elasticity.isNegative then
  3493             nx.isNegative := not nx.isNegative
  3524             nx.isNegative := not nx.isNegative
  3494         else
  3525         else
  3496 
  3527 
  3497 //AddFileLog('poffs:'+cstr(poffs)+' noffs:'+cstr(noffs)+' pspeed:'+cstr(pspeed)+' nspeed:'+cstr(nspeed));
  3528 //AddFileLog('poffs:'+cstr(poffs)+' noffs:'+cstr(noffs)+' pspeed:'+cstr(pspeed)+' nspeed:'+cstr(nspeed));
  3498         iterator^.dX := -pspeed * conPortal^.dX + nspeed * nx;
  3529         iterator^.dX := -pspeed * conPortal^.dX + nspeed * nx;
  3499         iterator^.dY := -pspeed * conPortal^.dY + nspeed * ny;
  3530         iterator^.dY := -pspeed * conPortal^.dY + nspeed * ny;
  3500         if iterator^.Kind = gtCake then
  3531         if iterator^.Kind = gtCake then
  3501             poffs := poffs * _0_5;
  3532             poffs := poffs * _0_5
       
  3533         else
       
  3534         if poffs < r + _1_5 then
       
  3535             poffs := r + _1_5;
  3502         iterator^.X := conPortal^.X + poffs * conPortal^.dX + noffs * nx;
  3536         iterator^.X := conPortal^.X + poffs * conPortal^.dX + noffs * nx;
  3503         iterator^.Y := conPortal^.Y + poffs * conPortal^.dY + noffs * ny;
  3537         iterator^.Y := conPortal^.Y + poffs * conPortal^.dY + noffs * ny;
  3504 
  3538 
  3505         FollowGear := iterator;
  3539         if not isbullet then
       
  3540             FollowGear := iterator;
  3506 //AddFileLog('portal''d');
  3541 //AddFileLog('portal''d');
  3507 
  3542 
  3508 {
  3543 {
  3509         s := _0_2 + _0_008 * Gear^.Health;
  3544         s := _0_2 + _0_008 * Gear^.Health;
  3510         iterator^.dX := s * iterator^.dX;
  3545         iterator^.dX := s * iterator^.dX;
  3511         iterator^.dY := s * iterator^.dY;
  3546         iterator^.dY := s * iterator^.dY;
  3512 }
  3547 }
       
  3548         // This jiggles gears, to ensure a portal connection just placed under a gear takes effect.
       
  3549         iterator:= GearsList;
       
  3550         while iterator <> nil do
       
  3551             begin
       
  3552             if iterator^.Kind <> gtPortal then
       
  3553                 begin
       
  3554                 iterator^.Active:= true;
       
  3555                 if iterator^.dY.QWordValue = _0.QWordValue then iterator^.dY.isNegative:= false;
       
  3556                 iterator^.State:= iterator^.State or gstMoving;
       
  3557                 DeleteCI(iterator);
       
  3558                 inc(iterator^.dY.QWordValue,10);
       
  3559                 end;
       
  3560             iterator:= iterator^.NextGear
       
  3561             end;
  3513 
  3562 
  3514         if Gear^.Health > 1 then dec(Gear^.Health);
  3563         if Gear^.Health > 1 then dec(Gear^.Health);
  3515 
  3564 
  3516 {        // breaks (some) loops
  3565 {        // breaks (some) loops
  3517         if Distance(iterator^.dX, iterator^.dY) > _0_96 then
  3566         if Distance(iterator^.dX, iterator^.dY) > _0_96 then