#pragma once #include "simulate.h" #include "origin.h" #include "linmtrx.h" class Player; class NotationFile; class DamageZone; class Damage; class Subsystem; #define ENTITY_CONTINUATION #include "entity2.h" //########################################################################## //########################### Entity ################################# //########################################################################## class Entity: public Simulation { friend class Entity__StaticVideoSocketIterator; friend class Entity__DynamicVideoSocketIterator; friend class Entity__AudioSocketIterator; friend class Entity__GaugeSocketIterator; friend class Entity__AudioLocationIterator; //########################################################################## // Shared Data support // public: typedef Entity__SharedData SharedData; SharedData* GetSharedData(); static Derivation *GetClassDerivations(); static SharedData DefaultData; //########################################################################## // Message Support // public: enum { MakeMessageID = Simulation::NextMessageID, MakeReadyMessageID, RemakeEntityMessageID, RemakeReadyMessageID, RemakeCompleteMessageID, RemakeIncompleteMessageID, DestroyEntityMessageID, TransferEntityMessageID, TransferCompleteMessageID, TransferIncompleteMessageID, BecomeInterestingMessageID, BecomeUninterestingMessageID, UpdateMessageID, SubscribeReplicantMessageID, UnsubscribeReplicantMessageID, TakeDamageMessageID, TakeDamageStreamMessageID, PlayerLinkMessageID, NextMessageID }; typedef Entity__Message Message; typedef Entity__MakeMessage MakeMessage; typedef Entity__MakeReadyMessage MakeReadyMessage; typedef Entity__RemakeEntityMessage RemakeEntityMessage; typedef Entity__RemakeReadyMessage RemakeReadyMessage; typedef Entity__RemakeCompleteMessage RemakeCompleteMessage; typedef Entity__RemakeIncompleteMessage RemakeIncompleteMessage; typedef Entity__DestroyEntityMessage DestroyEntityMessage; typedef Entity__TransferEntityMessage TransferEntityMessage; typedef Entity__TransferCompleteMessage TransferCompleteMessage; typedef Entity__TransferIncompleteMessage TransferIncompleteMessage; typedef Entity__BecomeInterestingMessage BecomeInterestingMessage; typedef Entity__BecomeUninterestingMessage BecomeUninterestingMessage; typedef Entity__UpdateMessage UpdateMessage; typedef Entity__SubscribeReplicantMessage SubscribeReplicantMessage; typedef Entity__UnsubscribeReplicantMessage UnsubscribeReplicantMessage; typedef Entity__TakeDamageMessage TakeDamageMessage; typedef Entity__TakeDamageStreamMessage TakeDamageStreamMessage; typedef Entity__PlayerLinkMessage PlayerLinkMessage; typedef Entity__DynamicMessage DynamicMessage; typedef Entity__MakeMapMessage MakeMapMessage; void Receive(Event *event); void LocalDispatch(Message *what) {Receiver::Receive(Cast_Object(Receiver::Message*,what));} void Dispatch(Receiver::Message *what); void DispatchToReplicant( Message *what, HostID host ); void DispatchToReplicants(Message *what); private: static const HandlerEntry MessageHandlerEntries[]; protected: //static MessageHandlerSet MessageHandlers; static MessageHandlerSet& GetMessageHandlers(); //########################################################################## // Attribute Support // public: enum { LocalToWorldAttributeID = Simulation::NextAttributeID, LocalOriginAttributeID, DamageZoneCountAttributeID, DamageZonesAttributeID, NextAttributeID }; private: static const IndexEntry AttributePointers[]; protected: //static AttributeIndexSet AttributeIndex static AttributeIndexSet& GetAttributeIndex(); // // public attribute declarations go here // public: LinearMatrix localToWorld; Origin localOrigin; int damageZoneCount; DamageZone **damageZones; //###################################################################### //################### Render interpolation ######################### //###################################################################### // // The simulation advances in whole fixed steps (RP412PHYSICSHZ) and the // renderer draws whenever it can, so at any frame rate that is not the // step rate the drawn position only changes 50 times a second and is // held for however many frames fall inside a step. That is visible as // stepping, and it gets WORSE the faster the machine: at 240 fps each // position is held for nearly five frames. // // So drawing interpolates. renderPreviousOrigin is this entity's origin // at the START of the step it is currently in, snapshotted by // Mover::BeginStep, and renderStepFraction is how far through that step // the frame being drawn falls. GetRenderToWorld blends the two. // // RENDER ONLY. localOrigin and localToWorld are untouched, so physics, // collision, scoring, the nav map's entity queries and the network // update records all keep seeing exact stepped values - which is what // keeps the simulation identical on every machine at every frame rate. // RP412PHYSTRACE is the proof of that and must not move. // // The picture therefore trails the simulation by up to one step (20 ms // at 50 Hz), which is the standard price and much the lesser evil: // extrapolating FORWARD instead has to guess, and overshoots into // shimmer every time the guess is corrected. // // A teleport must not be smoothed - sliding a pod 300 metres across the // map over 20 ms would be far worse than the cut it replaces. That // falls out for free: VTV::BeginStep applies a scheduled respawn and // THEN calls Mover::BeginStep, so the snapshot is taken after the // teleport and the blend has nothing to travel. // Origin renderPreviousOrigin; Scalar renderStepFraction; // // The transform to DRAW with. Falls back to localToWorld verbatim when // interpolation is off, when there is no fixed step to interpolate // within, or before the first snapshot exists - so the unfixed-step // path behaves exactly as it always did. // void GetRenderToWorld(LinearMatrix *out); // // Filled by Simulation::PerformTo around each fixed step, for locally // simulated entities and replicants alike. // void SnapshotRenderOrigin(); void SetRenderStepFraction(Scalar fraction); int GetDamageZoneIndex(const CString &damage_zone_name) const; // // virtual access // public: virtual Vector3D GetWorldLinearVelocity() {return Vector3D(0.0f, 0.0f, 0.0f);} virtual Vector3D GetWorldLinearAcceleration() {return Vector3D(0.0f, 0.0f, 0.0f);} //########################################################################## // Model Support // public: UpdateMessage* Execute(const Time &till); Subsystem* GetSubsystem(int index) { Check(this); Verify((unsigned)index < subsystemCount); return subsystemArray[index]; } Simulation* GetSimulation(int index); int GetSubsystemCount() {Check(this); return subsystemCount;} Subsystem* FindSubsystem(const char* name); typedef void (Entity::*Performance)(Scalar time_slice); typedef Entity__UpdateRecord UpdateRecord; void SetPerformance(Performance performance) { Check(this); activePerformance = (Simulation::Performance)performance; } enum { EntitySubsystemID = -1 }; static int FindSubsytemID( const char *model_name, const char *subsystem_name ); public: enum { DamageZoneUpdateModelBit = Simulation::NextUpdateModelBit, NextUpdateModelBit }; enum { DamageZoneUpdateModelFlag = 1 << DamageZoneUpdateModelBit }; Logical DamageZoneUpdateModelFlagSet() { Check(this); return ((updateModel & DamageZoneUpdateModelFlag) != 0); } protected: void WriteUpdateRecord( Simulation::UpdateRecord *message, int update_model ); void UpdateMessageHandler(UpdateMessage *message); void ReadUpdateRecord(Simulation::UpdateRecord *message); void ReadDamageUpdateRecord(Simulation::UpdateRecord *update_record); void WriteDamageUpdateRecord(Simulation::UpdateRecord *update_record); void PerformAndWatch( const Time &till, MemoryStream *update_stream ); int subsystemCount; Subsystem **subsystemArray; Origin updateOrigin; void TakeDamageStreamMessageHandler(TakeDamageStreamMessage *message); void TakeDamageMessageHandler(TakeDamageMessage *message); void PlayerLinkMessageHandler(PlayerLinkMessage *message); //########################################################################## // Renderer Support // public: void AddStaticVideoComponent(Component *component); void AddDynamicVideoComponent(Component *component); void AddAudioComponent(Component *component); typedef Entity__StaticVideoSocketIterator StaticVideoSocketIterator; typedef Entity__DynamicVideoSocketIterator DynamicVideoSocketIterator; typedef Entity__AudioSocketIterator AudioSocketIterator; virtual Enumeration GetAudioRepresentation(Entity *linked_entity); private: SChainOf staticVideoSocket; SChainOf dynamicVideoSocket; SChainOf audioSocket; //########################################################################## // Flag Support // public: // // MasterInstance - created on owning host, replicated on remote hosts, // sends updates to replicants // ReplicantInstance - created on remote hosts, receives updates from // MasterInstance // IndependantInstance - created on owning host, replicated on remote // hosts, never receives updates from MasterInstance // HermitInstance - created on owning host, is not replicated, does // send updates // enum { InstanceBits = Simulation::NextBit, ValidBit = InstanceBits+2, TransferableBit, InterestBit, InterestLockedBit, DynamicBit, TrappedBit, StatueBit, MapBit, PreRunBit, CondemnedBit, NextBit }; enum Instance { MasterInstance=0, ReplicantInstance=1<entityID = entityID; message->interestZoneID = interestZoneID; message->ownerID = ownerID; } #include "entity3.h" #undef ENTITY_CONTINUATION