/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #ifndef CRYINCLUDE_CRYCOMMON_MOVEMENTREQUEST_H #define CRYINCLUDE_CRYCOMMON_MOVEMENTREQUEST_H #pragma once #include <MovementRequestID.h> #include <MovementStyle.h> #include "IPathfinder.h" // MNMDangersFlags // Passed along as a parameter to movement request callbacks. struct MovementRequestResult { enum Result { Success, Failure, // Alias for 'Success' to increase readability in callback code. ReachedDestination = Success, }; enum FailureReason { NoReason, CouldNotFindPathToRequestedDestination, CouldNotMoveAlongDesignerDesignedPath, FailedToProduceSuccessfulPlanAfterMaximumNumberOfAttempts, }; MovementRequestResult( const MovementRequestID& _id, const Result _result, const FailureReason _failureReason) : requestID(_id) , result(_result) , failureReason(_failureReason) { } MovementRequestResult( const MovementRequestID& _id, const Result _result) : requestID(_id) , result(_result) , failureReason(NoReason) { } bool operator == (const Result& rhs) const { return result == rhs; } operator bool () const { return result == Success; } const MovementRequestID requestID; const Result result; const FailureReason failureReason; }; // Contains everything needed for the movement system to make informed // decisions about movement. You specify where you want to move // and how you want to do it. You can receive information about // your request by setting up a callback function. struct MovementRequest { typedef Functor1<const MovementRequestResult&> Callback; enum Type { MoveTo, Stop, CountTypes, // this has to stay the last one for places where the number of elements of this enum is relevant }; MovementRequest() : destination(ZERO) , type(MoveTo) , callback(0) , entityID(0) , dangersFlags(eMNMDangers_None) , considerActorsAsPathObstacles(false) , lengthToTrimFromThePathEnd(0.0f) { } #ifdef COMPILE_WITH_MOVEMENT_SYSTEM_DEBUG static const char* GetTypeAsDebugName(Type type) { COMPILE_TIME_ASSERT(CountTypes == 2); // if this fails, then most likely a new value in the Type enum got introduced if (type == MoveTo) { return "MoveTo"; } else if (type == Stop) { return "Stop"; } return "Undefined"; } #endif MovementStyle style; Vec3 destination; Type type; Callback callback; EntityId entityID; MNMDangersFlags dangersFlags; bool considerActorsAsPathObstacles; float lengthToTrimFromThePathEnd; }; // Contains information about the status of a request. // You'll see if it's in a queue, path finding, or // what block of a plan it's currently executing. struct MovementRequestStatus { MovementRequestStatus() : currentBlockIndex(0) , id(NotQueued) {} struct BlockInfo { BlockInfo() : name(0) {} BlockInfo(const char* _name) : name(_name) {} const char* name; }; typedef StaticDynArray<BlockInfo, 32> BlockInfos; enum ID { NotQueued, Queued, FindingPath, ExecutingPlan }; operator ID () const { return id; } BlockInfos blockInfos; uint32 currentBlockIndex; ID id; }; #if defined(COMPILE_WITH_MOVEMENT_SYSTEM_DEBUG) inline void ConstructHumanReadableText(IN const MovementRequestStatus& status, OUT stack_string& statusText) { switch (status) { case MovementRequestStatus::Queued: { statusText = "Request In Queue"; break; } case MovementRequestStatus::FindingPath: { statusText.Format("Finding Path"); break; } case MovementRequestStatus::ExecutingPlan: { statusText = "Executing Plan: "; const size_t totalBlockInfos = status.blockInfos.size(); for (size_t index = 0; index < totalBlockInfos; ++index) { if (index != 0) { statusText += " "; } const bool active = (index == status.currentBlockIndex); if (active) { statusText += "["; } statusText += status.blockInfos[index].name; if (active) { statusText += "]"; } } break; } case MovementRequestStatus::NotQueued: { statusText = "Request Not Queued"; break; } default: { statusText = "Unknown Status"; break; } } } #endif // COMPILE_WITH_MOVEMENT_SYSTEM_DEBUG #endif // CRYINCLUDE_CRYCOMMON_MOVEMENTREQUEST_H