diff --git a/Sources/Jazz2/Actors/Enemies/Fish.cpp b/Sources/Jazz2/Actors/Enemies/Fish.cpp index c0c9a4ea..b54c2e83 100644 --- a/Sources/Jazz2/Actors/Enemies/Fish.cpp +++ b/Sources/Jazz2/Actors/Enemies/Fish.cpp @@ -41,11 +41,17 @@ namespace Jazz2::Actors::Enemies void Fish::OnUpdate(float timeMult) { + float waterLevel = _levelHandler->WaterLevel(); + bool inWater = (_pos.Y > waterLevel - 160.0f); + if (!inWater) { + // Don't move if not in water + return; + } + EnemyBase::OnUpdate(timeMult); - float waterLevel = _levelHandler->WaterLevel(); - if (_pos.Y < waterLevel) { - MoveInstantly(Vector2f(_pos.X, waterLevel), MoveType::Absolute | MoveType::Force); + if (_pos.Y < waterLevel + 8.0f) { + MoveInstantly(Vector2f(_pos.X, waterLevel + 8.0f), MoveType::Absolute | MoveType::Force); } if (_frozenTimeLeft > 0.0f) { diff --git a/Sources/Jazz2/Actors/Solid/PinballPaddle.cpp b/Sources/Jazz2/Actors/Solid/PinballPaddle.cpp index 67a91aab..b57c7e0a 100644 --- a/Sources/Jazz2/Actors/Solid/PinballPaddle.cpp +++ b/Sources/Jazz2/Actors/Solid/PinballPaddle.cpp @@ -58,15 +58,17 @@ namespace Jazz2::Actors::Solid player->_speed.X = 0.0f; player->_speed.Y = (_levelHandler->IsReforged() ? -1.0f : -0.7f); - player->_externalForce.Y -= forceY; - player->_externalForceCooldown = 10.0f; - player->_controllable = true; - player->SetState(ActorState::CanJump, false); - player->EndDamagingMove(); + if (player->_activeModifier == Player::Modifier::None) { + if (player->_copterFramesLeft > 1.0f) { + player->_copterFramesLeft = 1.0f; + } - if (player->_copterFramesLeft > 1.0f) { - player->_copterFramesLeft = 1.0f; + player->_externalForce.Y -= forceY; + player->_externalForceCooldown = 10.0f; + player->_controllable = true; + player->SetState(ActorState::CanJump, false); + player->EndDamagingMove(); } // TODO: Check this diff --git a/Sources/Jazz2/Compatibility/JJ2Level.cpp b/Sources/Jazz2/Compatibility/JJ2Level.cpp index 0c542b70..94fcb62b 100644 --- a/Sources/Jazz2/Compatibility/JJ2Level.cpp +++ b/Sources/Jazz2/Compatibility/JJ2Level.cpp @@ -30,7 +30,10 @@ namespace Jazz2::Compatibility uint32_t magic = headerBlock.ReadUInt32(); RETURNF_ASSERT_MSG(magic == 0x4C56454C /*LEVL*/, "Invalid magic string"); - /*uint32_t passwordHash =*/ headerBlock.ReadUInt32(); + // passwordHash is 3 bytes + headerBlock.DiscardBytes(3); + + _isHidden = headerBlock.ReadBool(); DisplayName = headerBlock.ReadString(32, true); @@ -554,6 +557,9 @@ namespace Jazz2::Compatibility if (_useLevelPalette) { flags |= 0x04; } + if (_isHidden) { + flags |= 0x08; + } if (_isMpLevel) { flags |= 0x10; if (_hasLaps) { diff --git a/Sources/Jazz2/Compatibility/JJ2Level.h b/Sources/Jazz2/Compatibility/JJ2Level.h index 7fee9e3f..8ef4d184 100644 --- a/Sources/Jazz2/Compatibility/JJ2Level.h +++ b/Sources/Jazz2/Compatibility/JJ2Level.h @@ -137,7 +137,7 @@ namespace Jazz2::Compatibility JJ2Version _version; uint16_t _animCount; - bool _verticalMPSplitscreen, _isMpLevel; + bool _isHidden, _verticalMPSplitscreen, _isMpLevel; bool _hasPit, _hasPitInstantDeath, _hasCTF, _hasLaps; uint32_t _darknessColor; WeatherType _weatherType; diff --git a/Sources/Jazz2/UI/Menu/CustomLevelSelectSection.cpp b/Sources/Jazz2/UI/Menu/CustomLevelSelectSection.cpp index 9e955a5e..286035ce 100644 --- a/Sources/Jazz2/UI/Menu/CustomLevelSelectSection.cpp +++ b/Sources/Jazz2/UI/Menu/CustomLevelSelectSection.cpp @@ -298,7 +298,7 @@ namespace Jazz2::UI::Menu return; } - quicksort(_items.begin(), _items.end(), [](const ItemData& a, const ItemData& b) -> bool { + std::sort(_items.begin(), _items.end(), [](const ItemData& a, const ItemData& b) -> bool { return (a.LevelName < b.LevelName); }); } @@ -316,8 +316,14 @@ namespace Jazz2::UI::Menu uint8_t fileType = s->ReadValue(); RETURN_ASSERT_MSG(signature == 0x2095A59FF0BFBBEF && fileType == ContentResolver::LevelFile, "File has invalid signature"); - // TODO: Level flags - /*uint16_t flags =*/ s->ReadValue(); + uint16_t flags = s->ReadValue(); + +#if !defined(DEATH_DEBUG) + // Don't show hidden levels in Release build if unlock cheat is not active, but show all levels in Debug build + if ((flags & /*Hidden*/0x08) != 0 && !PreferencesCache::AllowCheatsUnlock) { + return; + } +#endif // Read compressed data int32_t compressedSize = s->ReadValue(); diff --git a/Sources/Jazz2/UI/Menu/EpisodeSelectSection.cpp b/Sources/Jazz2/UI/Menu/EpisodeSelectSection.cpp index c7fcec6d..5b8b14e0 100644 --- a/Sources/Jazz2/UI/Menu/EpisodeSelectSection.cpp +++ b/Sources/Jazz2/UI/Menu/EpisodeSelectSection.cpp @@ -3,7 +3,6 @@ #include "MainMenu.h" #include "MenuResources.h" #include "../../PreferencesCache.h" -#include "../../../nCine/Base/Algorithms.h" #include "../../../nCine/Base/FrameTimer.h" #if defined(WITH_MULTIPLAYER) @@ -42,7 +41,7 @@ namespace Jazz2::UI::Menu AddEpisode(item); } - quicksort(_items.begin(), _items.end(), [](const ListViewItem& a, const ListViewItem& b) -> bool { + std::sort(_items.begin(), _items.end(), [](const ListViewItem& a, const ListViewItem& b) -> bool { return (a.Item.Description.Position < b.Item.Description.Position); }); } diff --git a/Sources/nCine/Base/Algorithms.h b/Sources/nCine/Base/Algorithms.h index 440c3579..a29a169b 100644 --- a/Sources/nCine/Base/Algorithms.h +++ b/Sources/nCine/Base/Algorithms.h @@ -154,96 +154,6 @@ namespace nCine return last; } - /// Partition function for quicksort with iterators - template - inline Iterator partition(Iterator first, Iterator last, Compare comp) - { - Iterator pivot = last; - - while (first != last) { - while (comp(*first, *pivot)) { - ++first; - if (first == last) - return first; - } - - do { - --last; - if (first == last) - return first; - } while (!comp(*last, *pivot)); - - std::swap(*first, *last); - ++first; - } - - return first; - } - - namespace - { - /// Quicksort implementation with random access iterators and custom compare function - template - inline void quicksort(Iterator first, Iterator last, RandomAccessIteratorTag, Compare comp, int maxRecursion) - { - if (maxRecursion <= 0) { - return; - } - maxRecursion--; - - std::int32_t size = distance(first, last, RandomAccessIteratorTag()); - if (size > 1) { - Iterator p = prev(last); - std::swap(*next(first, size / 2), *p); - Iterator q = partition(first, p, comp); - std::swap(*q, *p); - quicksort(first, q, RandomAccessIteratorTag(), comp, maxRecursion); - quicksort(next(q), last, RandomAccessIteratorTag(), comp, maxRecursion); - } - } - - /// Quicksort implementation with bidirectional iterators and custom compare function - template - inline void quicksort(Iterator first, Iterator last, BidirectionalIteratorTag, Compare comp, int maxRecursion) - { - if (maxRecursion <= 0) { - return; - } - maxRecursion--; - - if (first != last) { - Iterator p = prev(last); - std::swap(*first, *p); - Iterator q = partition(first, p, comp); - std::swap(*q, *p); - quicksort(first, q, BidirectionalIteratorTag(), maxRecursion); - quicksort(next(q), last, BidirectionalIteratorTag(), maxRecursion); - } - } - - } - - /// Quicksort implementation with iterators and custom compare function - template - inline void quicksort(Iterator first, Iterator last, Compare comp, int maxRecursion = INT32_MAX) - { - quicksort(first, last, IteratorTraits::IteratorCategory(), comp, maxRecursion); - } - - /// Quicksort implementation with iterators, ascending order - template - inline void quicksort(Iterator first, Iterator last, int maxRecursion = INT32_MAX) - { - quicksort(first, last, IteratorTraits::IteratorCategory(), IsLess::ValueType>, maxRecursion); - } - - /// Quicksort implementation with iterators, descending order - template - inline void quicksortDesc(Iterator first, Iterator last) - { - quicksort(first, last, IteratorTraits::IteratorCategory(), IsNotLess::ValueType>); - } - /// A container for functions to destruct objects and arrays of objects template struct destructHelpers diff --git a/Sources/nCine/Graphics/RenderQueue.cpp b/Sources/nCine/Graphics/RenderQueue.cpp index 8fa4624f..0a0339bb 100644 --- a/Sources/nCine/Graphics/RenderQueue.cpp +++ b/Sources/nCine/Graphics/RenderQueue.cpp @@ -85,8 +85,8 @@ namespace nCine const bool batchingEnabled = theApplication().renderingSettings().batchingEnabled; // Sorting the queues with the relevant orders - quicksort(opaqueQueue_.begin(), opaqueQueue_.end(), descendingOrder, 256); - quicksort(transparentQueue_.begin(), transparentQueue_.end(), ascendingOrder, 256); + std::sort(opaqueQueue_.begin(), opaqueQueue_.end(), descendingOrder); + std::sort(transparentQueue_.begin(), transparentQueue_.end(), ascendingOrder); SmallVectorImpl* opaques = batchingEnabled ? &opaqueBatchedQueue_ : &opaqueQueue_; SmallVectorImpl* transparents = batchingEnabled ? &transparentBatchedQueue_ : &transparentQueue_;