/* Copyright 2003-2007 ROBLOX Corporation, All Rights Reserved */ #pragma once #include "V8DataModel/IEquipable.h" #include "V8DataModel/Hopper.h" #include "GfxBase/IAdornable.h" #include "Util/IHasLocation.h" #include "Util/Selectable.h" #include "Util/ContentFilter.h" #include "Gui/ProfanityFilter.h" namespace RBX { class PartInstance; class ModelInstance; class ToolMouseCommand; class Mouse; class ServiceProvider; class Workspace; class Attachment; namespace Network { class Player; } extern const char *const sTool; class Tool : public DescribedCreatable , public IEquipable // TODO - move stuff here that's common with Accoutrement , public IAdornable , public IHasLocation { public: // subclass signal to implement special logic for equipped: // * track weather the tool is currently equipped // * when a new connection is made to this signal, if the tool is // equipped then fire the signal to the new listener class special_equipped_signal : public rbx::signals::signal_with_args<1, void(shared_ptr)> //rbx::signal)> { private: typedef rbx::signals::signal_with_args<1, void(shared_ptr)> Super; bool currentlyEquipped; weak_ptr lastArg; public: special_equipped_signal(); // Note: this operator throws. See Implementation. void operator()(shared_ptr instance); void equipped(shared_ptr instance); void unequipped(); template rbx::signals::connection connect(Delegate& function) { rbx::signals::connection result = Super::connect(function); if (currentlyEquipped) { function(lastArg.lock()); } return result; } }; private: typedef DescribedCreatable Super; int getNumToolsInCharacter(); // debugging typedef enum { NOTHING, HAS_HANDLE, IN_WORKSPACE, IN_CHARACTER, HAS_TORSO, EQUIPPED } ToolState; // Replicated Properties ToolState backendToolState; // backend writes, frontend reads int frontendActivationState; // frontend writes, backend reads CoordinateFrame grip; // replicates, stores - the grip point on the tool bool enabled; // Tool is ready to go (cooldown property) bool droppable; bool requiresHandle; std::string toolTip; bool manualActivationOnly; bool ownWeld; // owner means it's responsible for creating and deleting the weld // "Backend" connections rbx::signals::scoped_connection_logged handleTouched; // watches for handle touched rbx::signals::scoped_connection characterChildAdded; rbx::signals::scoped_connection characterChildRemoved; rbx::signals::scoped_connection torsoChildAdded; rbx::signals::scoped_connection torsoChildRemoved; rbx::signals::scoped_connection armChildAdded; // Event handlers - hooked to these signals void onEvent_AddedBackend(shared_ptr child); void onEvent_RemovedBackend(shared_ptr child); void onEvent_AddedToArmBackend(shared_ptr child, Instance *handle); void onEvent_HandleTouched(shared_ptr other); static void moveAllToolsToBackpack(Network::Player* player); void moveOtherToolsToBackpack(weak_ptr player_weak_ptr); void setTimerCallback(weak_ptr player); static ToolState characterCanPickUpTool(Instance* touchingCharacter); Workspace* workspaceForToolMouseCommand; shared_ptr createMouse(); shared_ptr currentMouse; shared_ptr currentToolMouseCommand; void setMousePositionForInputType(); /////////////////////////////////////////////////////////////// // // Backend side // ToolState computeDesiredState(); ToolState computeDesiredState(Instance* testParent); void setDesiredState(ToolState desiredState, const ServiceProvider* serviceProvider); void rebuildBackendState(); void connectTouchEvent(); // Backend - climbing state void upTo_Activated(); void upTo_Equipped(); void upTo_HasTorso(); void upTo_InCharacter(); void upTo_InWorkspace(); void upTo_HasHandle(); // Backend - dropping state void downFrom_Activated(); void downFrom_Equipped(bool connectTouchEvent = true); void downFrom_HasTorso(); void downFrom_InCharacter(); void downFrom_InWorkspace(); void downFrom_HasHandle(); // state short cuts void fromNothingToEquipped(bool isBackend); void fromEquippedToNothing(); /////////////////////////////////////////////////////////////////////// // // Frontend side shared_ptr onEquipping(); void onUnequipped(); // Instance /*override*/ void onChildAdded(Instance* child); /*override*/ void onChildRemoved(Instance* child); /*override*/ void onAncestorChanged(const AncestorChanged& event); /*override*/ bool askSetParent(const Instance* instance) const {return true;} /*override*/ bool askAddChild(const Instance* instance) const {return true;} // IHasLocation /*override*/ const CoordinateFrame getLocation(); // BackpackItem /*override*/ bool drawSelected() const {return (backendToolState >= EQUIPPED);} /*override*/ void onLocalClicked(); /*override*/ void onLocalOtherClicked(); // IAdornable /*override*/ void render3dSelect(Adorn* adorn, SelectState selectState); static bool characterCanUnequipTool(ModelInstance *character); public: Tool(); ~Tool(); special_equipped_signal equippedSignal; rbx::remote_signal activatedSignal; rbx::signal unequippedSignal; rbx::remote_signal deactivatedSignal; static void dropAll(Network::Player* player); bool isDroppable() const { return droppable; } void setDroppable( bool newDroppable ){ droppable = newDroppable; } bool getRequiresHandle() const { return requiresHandle; } void setRequiresHandle(bool value); virtual bool canUnequip() {return true;} virtual bool canBePickedUpByPlayer(Network::Player *p) {return true;} /* override */ bool isSelectable3d(); PartInstance* getHandle(); const PartInstance* getHandleConst() const; ////////////////////////////////////////////////////////// // // REPLICATION Signals void setFrontendActivationState(int value); int getFrontendActivationState() const {return frontendActivationState;} void setToolTip(std::string value); std::string getToolTip() const { return toolTip; } void setBackendToolState(int value); int getBackendToolState() const {return backendToolState;} static Reflection::BoundProp prop_Enabled; const CoordinateFrame& getGrip() const {return grip;} void setGrip(const CoordinateFrame& value); ////////////////////////////////////////////////////////// // void luaActivate(); void activate(bool manuallyActivated = false); void deactivate(); bool getManualActivationOnly() const { return manualActivationOnly; } void setManualActivationOnly(bool value); // Auxillary UI props const Vector3 getGripPos() const; const Vector3 getGripForward() const; const Vector3 getGripUp() const; const Vector3 getGripRight() const; void setGripPos(const Vector3& v); void setGripForward(const Vector3& v); void setGripUp(const Vector3& v); void setGripRight(const Vector3& v); static Attachment *findFirstAttachmentByName(const Instance *part, const std::string& findName); static Attachment *findFirstAttachmentByNameRecursive(const Instance *part, const std::string& findName); }; } // namespace