`ScriptEntity` - Wrapper for an entity + it's handle (#1137)
* fix: Fix incorrect check in `AddCollisionSoundToList` * Implement `ScriptEntity` --------- Co-authored-by: Seemann <x87@users.noreply.github.com>
This commit is contained in:
parent
8da8f88717
commit
f1fc49a209
|
|
@ -446,4 +446,13 @@ F step_to(F x, F to, F step, bool useTimeStep = false) {
|
|||
//! See: https://stackoverflow.com/a/64228354/15363969
|
||||
template <typename R, typename T>
|
||||
concept range_of = rng::range<R> && std::same_as<rng::range_value_t<R>, T>;
|
||||
|
||||
// https://www.reddit.com/r/cpp/comments/1hw6a29/comment/m61d6wv
|
||||
template <class T, template <typename...> class Template>
|
||||
concept is_specialization_of = requires ( std::remove_cvref_t<T> t )
|
||||
{
|
||||
// Check an immediately invoked lambda can compile
|
||||
[]<typename... Args> ( Template<Args...>& ) {} ( t );
|
||||
};
|
||||
|
||||
}; // namespace notsa
|
||||
|
|
|
|||
|
|
@ -100,6 +100,17 @@ template<typename Base, typename Derived>
|
|||
constexpr auto is_derived_from_but_not_v = std::is_base_of_v<Base, Derived> && !std::is_same_v<Base, Derived>;
|
||||
};
|
||||
|
||||
//! Script entity (Not necessarily a derivative of `CEntity`, but any pooled type)
|
||||
template<typename T>
|
||||
struct ScriptEntity {
|
||||
static_assert(!std::is_pointer_v<T> && !std::is_reference_v<T>, "T must be a class type, not a pointer or reference.");
|
||||
|
||||
using EntityType = T;
|
||||
|
||||
EntityType* e; ///< Pointer to the actual entity (May be null if the handle is invalid)
|
||||
int32 h; ///< Script handle of the entity
|
||||
};
|
||||
|
||||
//! Read a value (Possibly from script => increases IP, or return a value (w/o increasing IP)
|
||||
template<typename T>
|
||||
inline T Read(CRunningScript* S) {
|
||||
|
|
@ -209,20 +220,29 @@ inline T Read(CRunningScript* S) {
|
|||
return static_cast<Y>(Read<std::underlying_type_t<Y>>(S));
|
||||
} else if constexpr (std::is_same_v<Y, CPlayerPed>) { // Special case for `CPlayerPed` (As the IDs for it aren't from the pool)
|
||||
return FindPlayerPed(Read<int32>(S));
|
||||
} else if constexpr (detail::PooledType<Y>) { // Pooled types (CVehicle, CPed, etc)
|
||||
T ptr = static_cast<T>(detail::PoolOf<Y>().GetAtRef(Read<int32>(S)));
|
||||
} else if constexpr (notsa::is_specialization_of<Y, ScriptEntity>) {
|
||||
using EntityType = typename Y::EntityType;
|
||||
|
||||
const auto handle = Read<int32>(S);
|
||||
auto entity = static_cast<EntityType*>(detail::PoolOf<EntityType>().GetAtRef(handle));
|
||||
|
||||
#ifdef NOTSA_DEBUG
|
||||
if (ptr) {
|
||||
if constexpr (detail::is_derived_from_but_not_v<CVehicle, Y>) {
|
||||
assert(Y::Type == ptr->m_nVehicleSubType); // check specialized type, in case of e.g. CAutomobile and one of its derived classes: CPlane, CHeli, etc
|
||||
} else if constexpr (detail::is_derived_from_but_not_v<CTask, Y>) {
|
||||
assert(Y::Type == ptr->GetTaskType());
|
||||
// Asserts for correct type
|
||||
if (entity) {
|
||||
if constexpr (detail::is_derived_from_but_not_v<CVehicle, EntityType>) {
|
||||
assert(EntityType::Type == entity->m_nVehicleSubType); // check specialized type, in case of e.g. CAutomobile and one of its derived classes: CPlane, CHeli, etc
|
||||
} else if constexpr (detail::is_derived_from_but_not_v<CTask, EntityType>) {
|
||||
assert(EntityType::Type == entity->GetTaskType());
|
||||
} // TODO: Eventually add this for `CEvent` too
|
||||
}
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
return {
|
||||
.e = entity,
|
||||
.h = handle
|
||||
};
|
||||
} else if constexpr (detail::PooledType<Y>) { // Pooled types (CVehicle, CPed, etc)
|
||||
return Read<ScriptEntity<Y>>(S).e;
|
||||
} else if constexpr (std::is_same_v<Y, CRunningScript>) { // Just return the script from where this command was invoked from
|
||||
return S;
|
||||
} else if constexpr (std::is_same_v<Y, CPlayerInfo>) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue