diff --git a/CREDITS.md b/CREDITS.md index 57bdd1af2e..b0bfe6580f 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -417,6 +417,7 @@ This page lists all the individual contributions to the project by their author. - Fix the bug that damaged particle dont disappear after building has repaired by engineer - Display banner improvement - Electric/RadBeam trail for laser tails + - Ground line for select box - **Apollo** - Translucent SHP drawing patches - **ststl**: - Customizable `ShowTimer` priority of superweapons diff --git a/YRpp b/YRpp index 76e2005551..d1bb108f4a 160000 --- a/YRpp +++ b/YRpp @@ -1 +1 @@ -Subproject commit 76e2005551ab38a95902d8a48ab35e24137a10ac +Subproject commit d1bb108f4abe6a99e31603f783b9e9320c9d23ce diff --git a/docs/User-Interface.md b/docs/User-Interface.md index 7699b6dbe4..31220c200f 100644 --- a/docs/User-Interface.md +++ b/docs/User-Interface.md @@ -284,12 +284,16 @@ RealTimeTimers.Adaptive=false ; boolean ### Select Box +![selectbox](_static/images/selectbox.png) + - Now you can use and customize select box for infantry, vehicle and aircraft. No select box for buildings in default case, but you still can specific for some building if you want. - `Frames` can be used to list frames of `Shape` file that'll be drawn as a select box when the TechnoType's health is at or below full health/the percentage defined in `[AudioVisual] -> ConditionYellow/ConditionRed`, respectively. - If `Grounded` set to true, the select box will be drawn on the ground below the TechnoType. - Select box's translucency setting can be adjusted via `Translucency`. - `VisibleToHouses` and `VisibleToHouses.Observer` can limit visibility to specific players. - `DrawAboveTechno` specific whether the select box will be drawn before drawing the TechnoType. If set to false, the select box can be obscured by the TechnoType, and the draw location will ignore `PixelSelectionBracketDelta`. + - You can now use `GroundShape` to specific a image which always draw on ground, it will only draw when techno is in air if set `Ground.AlwaysDraw=false`, this also affect on `GroundLine`. + - If `GroundLine=true` , the game will draw a line from techno's position to its vertical projection, `GroundLine.Dashed=true` means the projection line is a dashed line. In `rulesmd.ini`: ```ini @@ -304,12 +308,21 @@ DefaultUnitSelectBox= ; Select box for vehicle and aircraft Shape=select.shp ; filename with .shp extension Palette=palette.pal ; filename with .pal extension Frames= ; List of integer, default 1,1,1 for infantry, 0,0,0 for vehicle and aircraft -Grounded=false ; boolean Offset=0,0 ; integers - horizontal, vertical Translucency=0 ; translucency level (0/25/50/75) VisibleToHouses=all ; Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all) VisibleToHouses.Observer=true ; boolean DrawAboveTechno=true ; boolean +GroundShape= ; filename with .shp extension +GroundPalette=palette.pal ; filename with .pal extension +GroundFrames= ; List of integer, default 1,1,1 for infantry, 0,0,0 for vehicle and aircraft +GroundOffset=0,0 ; integers - horizontal, vertical +Ground.AlwaysDraw=true ; boolean +GroundLine=false ; boolean +GroundLineColor=0,255,0 ; R, G, B +GroundLineColor.ConditionYellow= ; R, G, B +GroundLineColor.ConditionRed= ; R, G, B +GroundLine.Dashed=false ; boolean [SOMETECHNO] ; TechnoType SelectBox= ; Select box diff --git a/docs/Whats-New.md b/docs/Whats-New.md index b71bafd62b..a92ce9d91f 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -406,6 +406,7 @@ New: - [Display banner](AI-Scripting-and-Mapping.md#display-banner) (by Morton & ststl) - Allows refineries to use multiple ActiveAnim simultaneously (by TaranDahl) - Electric/RadBeam trail for laser tails (by NetsuNegi) +- Ground line for select box (by NetsuNegi) Vanilla fixes: - Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya) diff --git a/docs/_static/images/selectbox.png b/docs/_static/images/selectbox.png new file mode 100644 index 0000000000..b212e957e7 Binary files /dev/null and b/docs/_static/images/selectbox.png differ diff --git a/src/Ext/Techno/Body.Visuals.cpp b/src/Ext/Techno/Body.Visuals.cpp index 0eb5e3bffa..3c79779476 100644 --- a/src/Ext/Techno/Body.Visuals.cpp +++ b/src/Ext/Techno/Body.Visuals.cpp @@ -350,50 +350,63 @@ void TechnoExt::DrawSelectBox(TechnoClass* pThis, const Point2D* pLocation, cons if (!pSelectBox || pSelectBox->DrawAboveTechno == drawBefore) return; - const auto pShape = pSelectBox->Shape.Get(); - - if (!pShape) - return; - const bool canSee = HouseClass::IsCurrentPlayerObserver() ? pSelectBox->VisibleToHouses_Observer : EnumFunctions::CanTargetHouse(pSelectBox->VisibleToHouses, pThis->Owner, HouseClass::CurrentPlayer); if (!canSee) return; - const auto pPalette = pSelectBox->Palette.GetOrDefaultConvert(FileSystem::PALETTE_PAL); - const double healthPercentage = pThis->GetHealthPercentage(); - const Vector3D frames = pSelectBox->Frames.Get(whatAmI == AbstractType::Infantry ? CoordStruct { 1,1,1 } : CoordStruct { 0,0,0 }); - const int frame = healthPercentage > RulesClass::Instance->ConditionYellow ? frames.X : healthPercentage > RulesClass::Instance->ConditionRed ? frames.Y : frames.Z; + const auto defaultFrame = whatAmI == InfantryClass::AbsID ? Vector3D { 1, 1, 1 } : Vector3D { 0,0,0 }; - Point2D drawPoint = *pLocation; + const auto pSurface = DSurface::Temp; + const auto flags = (drawBefore ? BlitterFlags::Flat | BlitterFlags::Alpha : BlitterFlags::Nonzero | BlitterFlags::MultiPass) | BlitterFlags::Centered | pSelectBox->Translucency; + const int zAdjust = drawBefore ? pThis->GetZAdjustment() - 2 : 0; + const auto pGroundShape = pSelectBox->GroundShape.Get(); - if (pSelectBox->Grounded && whatAmI != BuildingClass::AbsID) + if ((pGroundShape || pSelectBox->GroundLine) && whatAmI != BuildingClass::AbsID && (pSelectBox->Ground_AlwaysDraw || pThis->IsInAir())) { CoordStruct coords = pThis->GetCenterCoords(); coords.Z = MapClass::Instance.GetCellFloorHeight(coords); + auto [point, visible] = TacticalClass::Instance->CoordsToClient(coords); - const auto& [outClient, visible] = TacticalClass::Instance->CoordsToClient(coords); + if (visible && pGroundShape) + { + const auto pPalette = pSelectBox->GroundPalette.GetOrDefaultConvert(FileSystem::PALETTE_PAL); - if (!visible) - return; + const Vector3D frames = pSelectBox->GroundFrames.Get(defaultFrame); + const int frame = healthPercentage > RulesClass::Instance->ConditionYellow ? frames.X : healthPercentage > RulesClass::Instance->ConditionRed ? frames.Y : frames.Z; + + const Point2D drawPoint = point + pSelectBox->GroundOffset; + pSurface->DrawSHP(pPalette, pGroundShape, frame, &drawPoint, pBounds, flags, 0, zAdjust, ZGradient::Ground, 1000, 0, nullptr, 0, 0, 0); + } - drawPoint = outClient; + if (pSelectBox->GroundLine) + { + Point2D start = *pLocation; // Copy to prevent be modified + const int color = Drawing::RGB_To_Int(pSelectBox->GroundLineColor.Get(healthPercentage)); + + if (pSelectBox->GroundLine_Dashed) + pSurface->DrawDashed(&start, &point, color, 0); + else + pSurface->DrawLine(&start, &point, color); + } } - drawPoint += pSelectBox->Offset; + if (const auto pShape = pSelectBox->Shape.Get()) + { + const auto pPalette = pSelectBox->Palette.GetOrDefaultConvert(FileSystem::PALETTE_PAL); - if (pSelectBox->DrawAboveTechno) - drawPoint.Y += pType->PixelSelectionBracketDelta; + const Vector3D frames = pSelectBox->Frames.Get(defaultFrame); + const int frame = healthPercentage > RulesClass::Instance->ConditionYellow ? frames.X : healthPercentage > RulesClass::Instance->ConditionRed ? frames.Y : frames.Z; - if (whatAmI == AbstractType::Infantry) - drawPoint += { 8, -3 }; - else - drawPoint += { 1, -4 }; + const Point2D offset = whatAmI == InfantryClass::AbsID ? Point2D { 8, -3 } : Point2D { 1, -4 }; + Point2D drawPoint = *pLocation + offset + pSelectBox->Offset; - const auto flags = BlitterFlags::Centered | BlitterFlags::Nonzero | BlitterFlags::MultiPass | pSelectBox->Translucency; + if (pSelectBox->DrawAboveTechno) + drawPoint.Y += pType->PixelSelectionBracketDelta; - DSurface::Composite->DrawSHP(pPalette, pShape, frame, &drawPoint, pBounds, flags, 0, 0, ZGradient::Ground, 1000, 0, nullptr, 0, 0, 0); + pSurface->DrawSHP(pPalette, pShape, frame, &drawPoint, pBounds, flags, 0, zAdjust, ZGradient::Ground, 1000, 0, nullptr, 0, 0, 0); + } } void TechnoExt::ProcessDigitalDisplays(TechnoClass* pThis) diff --git a/src/New/Type/SelectBoxTypeClass.cpp b/src/New/Type/SelectBoxTypeClass.cpp index a6fc346a7a..b2cf969bbf 100644 --- a/src/New/Type/SelectBoxTypeClass.cpp +++ b/src/New/Type/SelectBoxTypeClass.cpp @@ -18,12 +18,19 @@ void SelectBoxTypeClass::LoadFromINI(CCINIClass* pINI) this->Shape.Read(exINI, pSection, "Shape"); this->Palette.LoadFromINI(pINI, pSection, "Palette"); this->Frames.Read(exINI, pSection, "Frames"); - this->Grounded.Read(exINI, pSection, "Grounded"); this->Offset.Read(exINI, pSection, "Offset"); this->Translucency.Read(exINI, pSection, "Translucency"); this->VisibleToHouses.Read(exINI, pSection, "VisibleToHouses"); this->VisibleToHouses_Observer.Read(exINI, pSection, "VisibleToHouses.Observer"); this->DrawAboveTechno.Read(exINI, pSection, "DrawAboveTechno"); + this->GroundShape.Read(exINI, pSection, "GroundShape"); + this->GroundPalette.LoadFromINI(pINI, pSection, "GroundPalette"); + this->GroundFrames.Read(exINI, pSection, "GroundFrames"); + this->GroundOffset.Read(exINI, pSection, "GroundOffset"); + this->Ground_AlwaysDraw.Read(exINI, pSection, "Ground.AlwaysDraw"); + this->GroundLine.Read(exINI, pSection, "GroundLine"); + this->GroundLineColor.Read(exINI, pSection, "GroundLineColor.%s"); + this->GroundLine_Dashed.Read(exINI, pSection, "GroundLine.Dashed"); } template @@ -33,12 +40,19 @@ void SelectBoxTypeClass::Serialize(T& Stm) .Process(this->Shape) .Process(this->Palette) .Process(this->Frames) - .Process(this->Grounded) .Process(this->Offset) .Process(this->Translucency) .Process(this->VisibleToHouses) .Process(this->VisibleToHouses_Observer) .Process(this->DrawAboveTechno) + .Process(this->GroundShape) + .Process(this->GroundPalette) + .Process(this->GroundFrames) + .Process(this->GroundOffset) + .Process(this->Ground_AlwaysDraw) + .Process(this->GroundLine) + .Process(this->GroundLineColor) + .Process(this->GroundLine_Dashed) ; } diff --git a/src/New/Type/SelectBoxTypeClass.h b/src/New/Type/SelectBoxTypeClass.h index ed7ea90f12..1f0707e700 100644 --- a/src/New/Type/SelectBoxTypeClass.h +++ b/src/New/Type/SelectBoxTypeClass.h @@ -10,23 +10,37 @@ class SelectBoxTypeClass final : public Enumerable Valueable Shape; CustomPalette Palette; Nullable> Frames; - Valueable Grounded; Valueable Offset; TranslucencyLevel Translucency; Valueable VisibleToHouses; Valueable VisibleToHouses_Observer; Valueable DrawAboveTechno; + Valueable GroundShape; + CustomPalette GroundPalette; + Nullable> GroundFrames; + Valueable GroundOffset; + Valueable Ground_AlwaysDraw; + Valueable GroundLine; + Damageable GroundLineColor; + Valueable GroundLine_Dashed; SelectBoxTypeClass(const char* pTitle = NONE_STR) : Enumerable(pTitle) , Shape { FileSystem::LoadSHPFile("select.shp") } , Palette {} , Frames {} - , Grounded { false } , Offset { Point2D::Empty } , Translucency { 0 } , VisibleToHouses { AffectedHouse::All } , VisibleToHouses_Observer { true } , DrawAboveTechno { true } + , GroundShape { nullptr } + , GroundPalette {} + , GroundFrames {} + , GroundOffset { Point2D::Empty } + , Ground_AlwaysDraw { true } + , GroundLine { false } + , GroundLineColor { { 0,255,0 } } + , GroundLine_Dashed { false} { } void LoadFromINI(CCINIClass* pINI);