From f2122a04b48edfa8c7242760326b6057474b1984 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Wed, 1 Nov 2017 07:54:38 +0200 Subject: [PATCH] slightly better path and light tracing (try to trace line from both points before failing) --- src/felib/bitmap.cpp | 2 +- src/felib/felibdef.h | 2 ++ src/felib/femath.h | 18 +++++++++++++++--- src/game/char.cpp | 10 +++++----- src/game/level.cpp | 8 ++++---- src/game/lsquare.cpp | 2 +- 6 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/felib/bitmap.cpp b/src/felib/bitmap.cpp index 77a0e47..856998d 100644 --- a/src/felib/bitmap.cpp +++ b/src/felib/bitmap.cpp @@ -1568,7 +1568,7 @@ truth bitmap::CreateLightning (v2 StartPos, v2 Direction, int MaxLength, col16 C continue; } Counter = 0; - if (!mapmath::DoLine(StartPos.X, StartPos.Y, StartPos.X + Move.X, StartPos.Y + Move.Y) || feuLong(MaxLength) <= PixelVector.size()) { + if (!mapmath::DoLine(StartPos.X, StartPos.Y, StartPos.X + Move.X, StartPos.Y + Move.Y, LINE_BOTH_DIRS) || feuLong(MaxLength) <= PixelVector.size()) { int Limit = Min(PixelVector.size(), MaxLength); for (int c = 0; c < Limit; ++c) { PutPixel(PixelVector[c], Color); diff --git a/src/felib/felibdef.h b/src/felib/felibdef.h index 663037e..7b73850 100644 --- a/src/felib/felibdef.h +++ b/src/felib/felibdef.h @@ -169,6 +169,8 @@ using rcint = int; #define SKIP_FIRST 1 #define ALLOW_END_FAILURE 2 +#define SKIP_LAST 4 +#define LINE_BOTH_DIRS 8 #define MAX_RAND 0x7FFFFFFF diff --git a/src/felib/femath.h b/src/felib/femath.h index 588e533..f18ba60 100644 --- a/src/felib/femath.h +++ b/src/felib/femath.h @@ -135,12 +135,22 @@ inputfile &operator >> (inputfile &SaveFile, PRNGSeed &R); template class mapmath { public: static truth DoLine (int X1, int Y1, int X2, int Y2, int Flags=0); + static truth DoLineOneDir (int X1, int Y1, int X2, int Y2, int Flags=0); static void DoArea (); static void DoQuadriArea (int, int, int, int, int); }; template inline truth mapmath::DoLine (int X1, int Y1, int X2, int Y2, int Flags) { + truth res = DoLineOneDir(X1, Y1, X2, Y2, Flags); + if (!res && (Flags&LINE_BOTH_DIRS) != 0) { + if (Flags&SKIP_FIRST) Flags = (Flags&~SKIP_FIRST)|SKIP_LAST; + res = DoLineOneDir(X2, Y2, X1, Y1, Flags); + } + return res; +} + +template inline truth mapmath::DoLineOneDir (int X1, int Y1, int X2, int Y2, int Flags) { if (!(Flags & SKIP_FIRST)) controller::Handler(X1, Y1); cint DeltaX = abs(X2 - X1); cint DeltaY = abs(Y2 - Y1); @@ -159,7 +169,8 @@ template inline truth mapmath::DoLine (int X1, in c -= DoubleDeltaX; y += YChange; } - if (!controller::Handler(x, y)) return x == End && !(Flags & ALLOW_END_FAILURE); + if ((Flags&SKIP_LAST) && x == X2 && y == Y2) break; + if (!controller::Handler(x, y)) return (x == End && !(Flags & ALLOW_END_FAILURE)); } } else { int c = DeltaY; @@ -171,7 +182,8 @@ template inline truth mapmath::DoLine (int X1, in c -= DoubleDeltaY; x += XChange; } - if (!controller::Handler(x, y)) return y == End && !(Flags & ALLOW_END_FAILURE); + if ((Flags&SKIP_LAST) && x == X2 && y == Y2) break; + if (!controller::Handler(x, y)) return (y == End && !(Flags & ALLOW_END_FAILURE)); } } return true; @@ -215,7 +227,7 @@ template truth quadricontroller::Handler (int x, if (controller::Handler(x, y)) return true; SectorCompletelyClear = false; } else { - return mapmath::DoLine(StartX, StartY, x, y, SKIP_FIRST|ALLOW_END_FAILURE); + return mapmath::DoLine(StartX, StartY, x, y, SKIP_FIRST|ALLOW_END_FAILURE|LINE_BOTH_DIRS); } } } diff --git a/src/game/char.cpp b/src/game/char.cpp index e7865af..598bd74 100644 --- a/src/game/char.cpp +++ b/src/game/char.cpp @@ -4568,7 +4568,7 @@ truth character::SquareUnderCanBeSeenByPlayer (truth IgnoreDarkness) const { int LOSRangeSquare = PLAYER->GetLOSRangeSquare(); if ((GetPos() - PLAYER->GetPos()).GetLengthSquare() <= LOSRangeSquare) { eyecontroller::Map = GetLevel()->GetMap(); - return mapmath::DoLine(PLAYER->GetPos().X, PLAYER->GetPos().Y, GetPos().X, GetPos().Y, SKIP_FIRST); + return mapmath::DoLine(PLAYER->GetPos().X, PLAYER->GetPos().Y, GetPos().X, GetPos().Y, SKIP_FIRST|LINE_BOTH_DIRS); } } return false; @@ -4583,7 +4583,7 @@ truth character::SquareUnderCanBeSeenByPlayer (truth IgnoreDarkness) const { v2 PlayerPos = PLAYER->GetPos(c2); if ((Pos-PlayerPos).GetLengthSquare() <= LOSRangeSquare) { eyecontroller::Map = GetLevel()->GetMap(); - if (mapmath::DoLine(PlayerPos.X, PlayerPos.Y, Pos.X, Pos.Y, SKIP_FIRST)) return true; + if (mapmath::DoLine(PlayerPos.X, PlayerPos.Y, Pos.X, Pos.Y, SKIP_FIRST|LINE_BOTH_DIRS)) return true; } } } @@ -6416,8 +6416,8 @@ truth character::CreateRoute () { v2 CharGoingTo = Char->Route[0]; v2 iPos = Char->Route.back(); if ((GoingTo-CharGoingTo).GetLengthSquare() <= 100 && (Pos - iPos).GetLengthSquare() <= 100 && - mapmath::DoLine(CharGoingTo.X, CharGoingTo.Y, GoingTo.X, GoingTo.Y, SKIP_FIRST) && - mapmath::DoLine(Pos.X, Pos.Y, iPos.X, iPos.Y, SKIP_FIRST)) { + mapmath::DoLine(CharGoingTo.X, CharGoingTo.Y, GoingTo.X, GoingTo.Y, SKIP_FIRST|LINE_BOTH_DIRS) && + mapmath::DoLine(Pos.X, Pos.Y, iPos.X, iPos.Y, SKIP_FIRST|LINE_BOTH_DIRS)) { if (!Illegal.empty() && Illegal.find(Char->Route.back()) != Illegal.end()) continue; Node = GetLevel()->FindRoute(CharGoingTo, GoingTo, Illegal, GetMoveType()); if (Node) { while(Node->Last) { Route.push_back(Node->Pos); Node = Node->Last; } } @@ -7628,7 +7628,7 @@ truth character::HasClearRouteTo (v2 Pos) const { pathcontroller::Map = GetLevel()->GetMap(); pathcontroller::Character = this; v2 ThisPos = GetPos(); - return mapmath::DoLine(ThisPos.X, ThisPos.Y, Pos.X, Pos.Y, SKIP_FIRST); + return mapmath::DoLine(ThisPos.X, ThisPos.Y, Pos.X, Pos.Y, SKIP_FIRST|LINE_BOTH_DIRS); } diff --git a/src/game/level.cpp b/src/game/level.cpp index 06ad3df..d955e4f 100644 --- a/src/game/level.cpp +++ b/src/game/level.cpp @@ -2248,19 +2248,19 @@ void level::EmitSunBeam (v2 S, feuLong ID, int SourceFlags) const { sunbeamcontroller::ID = ID; if (SourceFlags&SP_TOP_LEFT) { sunbeamcontroller::SunLightBlockHeight = 0; - mapmath::DoLine(S.X, S.Y, D.X, D.Y, SKIP_FIRST); + mapmath::DoLine(S.X, S.Y, D.X, D.Y, SKIP_FIRST|LINE_BOTH_DIRS); } if (SourceFlags&SP_TOP_RIGHT) { sunbeamcontroller::SunLightBlockHeight = 0; - mapmath::DoLine(S.X+1, S.Y, D.X+1, D.Y, SKIP_FIRST); + mapmath::DoLine(S.X+1, S.Y, D.X+1, D.Y, SKIP_FIRST|LINE_BOTH_DIRS); } if (SourceFlags&SP_BOTTOM_LEFT) { sunbeamcontroller::SunLightBlockHeight = 0; - mapmath::DoLine(S.X, S.Y+1, D.X, D.Y+1, SKIP_FIRST); + mapmath::DoLine(S.X, S.Y+1, D.X, D.Y+1, SKIP_FIRST|LINE_BOTH_DIRS); } if (SourceFlags&SP_BOTTOM_RIGHT) { sunbeamcontroller::SunLightBlockHeight = 0; - mapmath::DoLine(S.X+1, S.Y+1, D.X+1, D.Y+1, SKIP_FIRST); + mapmath::DoLine(S.X+1, S.Y+1, D.X+1, D.Y+1, SKIP_FIRST|LINE_BOTH_DIRS); } } diff --git a/src/game/lsquare.cpp b/src/game/lsquare.cpp index 0c0c978..8ebd376 100644 --- a/src/game/lsquare.cpp +++ b/src/game/lsquare.cpp @@ -936,7 +936,7 @@ truth lsquare::CanBeSeenFrom (v2 FromPos, sLong MaxDistance, truth IgnoreDarknes return true; } eyecontroller::Map = GetLevel()->GetMap(); - return mapmath::DoLine(FromPos.X, FromPos.Y, GetPos().X, GetPos().Y, SKIP_FIRST); + return mapmath::DoLine(FromPos.X, FromPos.Y, GetPos().X, GetPos().Y, SKIP_FIRST|LINE_BOTH_DIRS); } return false; } -- 2.11.4.GIT