mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-05 13:17:49 +00:00
236 lines
7.2 KiB
C++
236 lines
7.2 KiB
C++
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
|
|
|
|
#pragma once
|
|
|
|
#include "V8DataModel/BasicPartInstance.h"
|
|
#include "V8DataModel/ActionStation.h"
|
|
#include "Network/Players.h"
|
|
|
|
namespace RBX {
|
|
|
|
class Humanoid;
|
|
class Motor6D;
|
|
|
|
template<class Base>
|
|
class PlatformImpl : public ActionStation<Base>
|
|
{
|
|
private:
|
|
typedef ActionStation<Base> Super;
|
|
// "Backend" connections
|
|
rbx::signals::scoped_connection platformTouched;
|
|
rbx::signals::scoped_connection humanoidDonePlatformStanding;
|
|
|
|
void onEvent_platformTouched(shared_ptr<Instance> other) {
|
|
if (Humanoid* h = Humanoid::humanoidFromBodyPart(other.get())) {
|
|
if (PartInstance* torso = h->getTorsoSlow()) {
|
|
if (this->sleepTimeUp()
|
|
&& !findPlatformMotor6D()
|
|
&& !h->getPlatformStanding()
|
|
&& !h->getDead()
|
|
&& !torso->computeNetworkOwnerIsSomeoneElse()
|
|
&& Workspace::contextInWorkspace(torso)
|
|
&& Workspace::contextInWorkspace(this))
|
|
{
|
|
RBXASSERT(h->getTorsoSlow()->getPartPrimitive()->getAssembly() != this->getPartPrimitive()->getAssembly());
|
|
if(this->getCoordinateFrame().rotation.column(1).y > 0.7f) // must be within 45 degrees of upright to mount
|
|
{
|
|
createPlatformMotor6D(h);
|
|
}
|
|
else
|
|
{
|
|
// this doesn't cut it. disable and do in lua for now.
|
|
/*// kick it, up and away from torso.
|
|
Vector3 torsopos = torso->getCoordinateFrame().translation;
|
|
Vector3 ppos = getCoordinateFrame().translation;
|
|
Vector3 dirv = ppos - torsopos;
|
|
dirv.y = 0; // neutralize up.
|
|
dirv.unitize();
|
|
static float away = 3.0f;
|
|
static float up = 30.0f;
|
|
Vector3 upimpulse = Vector3(0, up, 0);
|
|
applySpecificImpulse(upimpulse + dirv * away, torso->getCoordinateFrame().translation);
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Destroy platform - on event no longer platformed from humanoid state (simulator)
|
|
void onEvent_humanoidDonePlatformStanding() {
|
|
findAndDestroyPlatformMotor6D();
|
|
}
|
|
|
|
void createPlatformMotor6DInternal(Humanoid *h)
|
|
{
|
|
if (!h->getTorsoSlow())
|
|
return;
|
|
|
|
PartInstance *pTorsoPart = NULL;
|
|
pTorsoPart = h->getVisibleTorsoSlow();
|
|
RBXASSERT(pTorsoPart); // we just checked for this
|
|
|
|
CoordinateFrame originalPlatformCoord = this->getCoordinateFrame();
|
|
RBXASSERT(this->getCoordinateFrame() == this->getPartPrimitive()->getCoordinateFrame());
|
|
|
|
CoordinateFrame platformCoord;
|
|
platformCoord.lookAt(Vector3(0,-1,0), Vector3(0,0,-1));
|
|
platformCoord.translation = Vector3(0, this->getPartSizeXml().y *0.5f, 0); // at the surface.
|
|
|
|
CoordinateFrame torsoCoord;
|
|
torsoCoord.lookAt(Vector3(0,-1,0), Vector3(0,0,-1));
|
|
torsoCoord.translation = Vector3(0, -3.0, 0);
|
|
|
|
Primitive* torso = pTorsoPart->getPartPrimitive();
|
|
Assembly* torsoAssembly = torso->getAssembly();
|
|
if (!torsoAssembly)
|
|
return;
|
|
|
|
RBXASSERT(torsoAssembly != this->getPartPrimitive()->getAssembly());
|
|
Primitive* root = torsoAssembly->getAssemblyPrimitive();
|
|
|
|
root->setVelocity(Velocity::zero());
|
|
|
|
shared_ptr<Motor6D> tempMotor6D = Creatable<Instance>::create<Motor6D>();
|
|
|
|
tempMotor6D->setName("PlatformMotor6D");
|
|
tempMotor6D->setPart0(this);
|
|
tempMotor6D->setPart1(pTorsoPart);
|
|
|
|
tempMotor6D->setC0(platformCoord);
|
|
tempMotor6D->setC1(torsoCoord);
|
|
|
|
Instance::propArchivable.setValue(tempMotor6D.get(), false);
|
|
tempMotor6D->setParent(this);
|
|
}
|
|
|
|
void onChildRemoved(Instance* child)
|
|
{
|
|
if (Motor6D* childMotor6D = isChildPlatformMotor6D(child))
|
|
{
|
|
humanoidDonePlatformStanding.disconnect();
|
|
ActionStation<Base>::sleepTime = Time::now<Time::Fast>();
|
|
onPlatformStandingChanged(false, humanoidFromMotor6D(childMotor6D));
|
|
}
|
|
}
|
|
|
|
void onChildAdded(Instance* child)
|
|
{
|
|
if (Motor6D* childMotor6D = isChildPlatformMotor6D(child))
|
|
{
|
|
destroyOtherMotor6Ds(childMotor6D);
|
|
|
|
if (Humanoid* h = humanoidFromMotor6D(childMotor6D)) {
|
|
h->setPlatformStanding(true); // will fire this event
|
|
humanoidDonePlatformStanding = h->donePlatformStandingSignal.connect(boost::bind(&PlatformImpl::onEvent_humanoidDonePlatformStanding, this));
|
|
onPlatformStandingChanged(true, h);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected:
|
|
|
|
virtual void createPlatformMotor6D(Humanoid *h) {
|
|
createPlatformMotor6DInternal(h);
|
|
}
|
|
|
|
virtual void findAndDestroyPlatformMotor6D() {
|
|
findAndDestroyPlatformMotor6DInternal();
|
|
}
|
|
|
|
void createPlatformMotor6DInternal(shared_ptr<Instance> instance) {
|
|
createPlatformMotor6DInternal(Instance::fastSharedDynamicCast<Humanoid>(instance).get());
|
|
}
|
|
|
|
void findAndDestroyPlatformMotor6DInternal()
|
|
{
|
|
while (Motor6D* motor6D = findPlatformMotor6D()) {
|
|
motor6D->setParent(NULL);
|
|
}
|
|
}
|
|
|
|
Humanoid* humanoidFromMotor6D(Motor6D* motor6D) {
|
|
PartInstance* torso = motor6D ? motor6D->getPart1() : NULL;
|
|
return Humanoid::humanoidFromBodyPart(torso);
|
|
}
|
|
|
|
Motor6D* findPlatformMotor6D() {
|
|
for (size_t i = 0; i < this->numChildren(); ++i) {
|
|
if (Motor6D* answer = isChildPlatformMotor6D(this->getChild(i))) {
|
|
return answer;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
Motor6D* isChildPlatformMotor6D(Instance* child) {
|
|
if (child->getName() == "PlatformMotor6D") {
|
|
if (Motor6D* childMotor6D = child->fastDynamicCast<Motor6D>()) {
|
|
return childMotor6D;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void destroyOtherMotor6D(shared_ptr<Instance> child, Motor6D* childMotor6D) {
|
|
if ((child.get() != childMotor6D) && isChildPlatformMotor6D(child.get())) {
|
|
child->setParent(NULL);
|
|
}
|
|
}
|
|
|
|
void destroyOtherMotor6Ds(Motor6D* childMotor6D) {
|
|
this->visitChildren(boost::bind(&PlatformImpl::destroyOtherMotor6D, this, _1, childMotor6D));
|
|
}
|
|
|
|
void onServiceProvider(ServiceProvider* oldProvider, ServiceProvider* newProvider) {
|
|
if(oldProvider) {
|
|
platformTouched.disconnect(); // just to be safe
|
|
onPlatformStandingChanged(false, humanoidFromMotor6D(findPlatformMotor6D())); // platform is destroyed before motor6D in this case
|
|
}
|
|
|
|
Super::onServiceProvider(oldProvider, newProvider);
|
|
|
|
if(newProvider) {
|
|
platformTouched = ActionStation<Base>::onDemandWrite()->localSimulationTouchedSignal.connect(boost::bind(&PlatformImpl::onEvent_platformTouched, this, _1));
|
|
}
|
|
}
|
|
|
|
/*implement*/ virtual void onPlatformStandingChanged(bool platformed, Humanoid* humanoid) {}
|
|
|
|
// implement this if platform is "kickable"
|
|
virtual void applySpecificImpulse(Vector3 impulseWorld, Vector3 worldpos) {};
|
|
|
|
public:
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extern const char* const sPlatform;
|
|
// changed to described, we don't ship right now.
|
|
// need to fix dismount issue.
|
|
class Platform : public Reflection::Described<Platform, sPlatform, PlatformImpl<BasicPartInstance> >
|
|
{
|
|
typedef PlatformImpl<BasicPartInstance> Super;
|
|
public:
|
|
rbx::remote_signal<void(shared_ptr<Instance>)> createPlatformMotor6DSignal;
|
|
rbx::remote_signal<void()> destroyPlatformMotor6DSignal;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// PlatformImpl
|
|
/*override*/ void createPlatformMotor6D(Humanoid *h);
|
|
/*override*/ void findAndDestroyPlatformMotor6D();
|
|
|
|
Platform() {
|
|
setName(sPlatform);
|
|
|
|
createPlatformMotor6DSignal.connect(boost::bind(static_cast<void (Platform::*)(shared_ptr<Instance>)>(&Platform::createPlatformMotor6DInternal), this, _1));
|
|
destroyPlatformMotor6DSignal.connect(boost::bind(&Platform::findAndDestroyPlatformMotor6DInternal, this));
|
|
}
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|