Mass refactoring part 1/2: establishing multiple subprojects, moving source files to their new location, adding resources/templates to version control

This commit is contained in:
parax0
2015-12-14 18:33:16 -07:00
parent b4b134d55b
commit 8805baaee1
1116 changed files with 129200 additions and 546 deletions

View File

@@ -0,0 +1,259 @@
#include "CDamageableTriggerExtra.h"
#include <Core/CDrawUtil.h>
#include <Core/CRenderer.h>
CDamageableTriggerExtra::CDamageableTriggerExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent)
: CScriptExtra(pInstance, pScene, pParent)
, mpRenderSideProp(nullptr)
, mpMat(nullptr)
{
for (u32 iTex = 0; iTex < 3; iTex++)
mpTextures[iTex] = nullptr;
SetInheritance(true, false, false);
CreateMaterial();
CPropertyStruct *pBaseStruct = pInstance->Properties();
// Fetch render side
mpRenderSideProp = (CEnumProperty*) pBaseStruct->PropertyByIndex(0x5);
if (mpRenderSideProp && mpRenderSideProp->Type() != eEnumProperty)
mpRenderSideProp = nullptr;
if (mpRenderSideProp) PropertyModified(mpRenderSideProp);
// Fetch scale
mpSizeProp = (CVector3Property*) pBaseStruct->PropertyByIndex(0x2);
if (mpSizeProp && mpSizeProp->Type() != eVector3Property)
mpSizeProp = nullptr;
if (mpSizeProp) PropertyModified (mpSizeProp);
// Fetch textures
for (u32 iTex = 0; iTex < 3; iTex++)
{
mpTextureProps[iTex] = (CFileProperty*) pBaseStruct->PropertyByIndex(0x6 + iTex);
if (mpTextureProps[iTex])
{
if (mpTextureProps[iTex]->Type() == eFileProperty)
PropertyModified(mpTextureProps[iTex]);
else
mpTextureProps[iTex] = nullptr;
}
else
mpTextures[iTex] = nullptr;
}
}
CDamageableTriggerExtra::~CDamageableTriggerExtra()
{
delete mpMat;
}
void CDamageableTriggerExtra::CreateMaterial()
{
if (mpMat) delete mpMat;
mpMat = new CMaterial(mGame, ePosition | eNormal | eTex0);
// Most values/TEV setup were found from the executable + from graphics debuggers
// Animation parameters are estimates from eyeballing the values ingame
mpMat->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
mpMat->SetLightingEnabled(true);
mpMat->SetOptions(CMaterial::eTransparent);
mpMat->SetKonst(CColor((float) 1.f, 1.f, 1.f, 0.2f), 0);
mpMat->SetNumPasses(3);
CMaterialPass *pPassA = mpMat->Pass(0);
pPassA->SetKColorSel(eKonst0_RGB);
pPassA->SetTexCoordSource(4);
pPassA->SetTexture(mpTextures[0]);
pPassA->SetColorInputs(eZeroRGB, eTextureRGB, eKonstRGB, eZeroRGB);
pPassA->SetAnimMode(eUVScroll);
pPassA->SetAnimParam(3, -0.48f);
CMaterialPass *pPassB = mpMat->Pass(1);
pPassB->SetTexCoordSource(4);
pPassB->SetTexture(mpTextures[1]);
pPassB->SetColorInputs(eZeroRGB, eTextureRGB, ePrevRGB, eZeroRGB);
pPassB->SetAnimMode(eUVScroll);
pPassB->SetAnimParam(2, 0.25f);
pPassB->SetAnimParam(3, -0.3f);
CMaterialPass *pPassC = mpMat->Pass(2);
pPassC->SetTexCoordSource(4);
pPassC->SetTexture(mpTextures[2]);
pPassC->SetRasSel(eRasColor0A0);
pPassC->SetKAlphaSel(eKonst0_A);
pPassC->SetColorInputs(eZeroRGB, eTextureRGB, eOneRGB, ePrevRGB);
pPassC->SetAlphaInputs(eZeroAlpha, eZeroAlpha, eZeroAlpha, eKonstAlpha);
pPassC->SetAnimMode(eUVScroll);
pPassC->SetAnimParam(3, -0.16f);
}
void CDamageableTriggerExtra::UpdatePlaneTransform()
{
CVector3f Extent = mPlaneSize / 2.f;
switch (mRenderSide)
{
case eNorth:
case eSouth:
{
float Scalar = (mRenderSide == eNorth ? 1.f : -1.f);
mPosition = CVector3f(0.f, Extent.y * Scalar, 0.f);
mRotation = CQuaternion::FromEuler(CVector3f(90.f * Scalar, 0.f, 0.f));
mScale = CVector3f(Extent.x, Extent.z, 0.f);
mCoordScale = mPlaneSize.xz();
break;
}
case eWest:
case eEast:
{
float Scalar = (mRenderSide == eWest ? 1.f : -1.f);
mPosition = CVector3f(-Extent.x * Scalar, 0.f, 0.f);
mRotation = CQuaternion::FromEuler(CVector3f(0.f, 90.f * Scalar, 0.f));
mScale = CVector3f(Extent.z, Extent.y, 0.f);
mCoordScale = -mPlaneSize.yz();
break;
}
case eUp:
case eDown:
{
float Scalar = (mRenderSide == eUp ? 1.f : -1.f);
float RotAngle = (mRenderSide == eUp ? 180.f : 0.f);
mPosition = CVector3f(0.f, 0.f, Extent.z * Scalar);
mRotation = CQuaternion::FromEuler(CVector3f(0.f, RotAngle, 0.f));
mScale = CVector3f(Extent.x, Extent.y, 0.f);
mCoordScale = -mPlaneSize.xy();
break;
}
}
if (mRenderSide == eNoRender)
mLocalAABox = CAABox::skZero;
else
mLocalAABox = CAABox(CVector3f(-1.f, -1.f, 0.f), CVector3f(1.f, 1.f, 0.f));
MarkTransformChanged();
}
void CDamageableTriggerExtra::PropertyModified(CPropertyBase *pProperty)
{
if (pProperty == mpRenderSideProp)
{
mRenderSide = (ERenderSide) mpRenderSideProp->Get();
UpdatePlaneTransform();
}
else if (pProperty == mpSizeProp)
{
mPlaneSize = mpSizeProp->Get();
UpdatePlaneTransform();
}
else
{
for (u32 iTex = 0; iTex < 3; iTex++)
{
if (pProperty == mpTextureProps[iTex])
{
mpTextures[iTex] = mpTextureProps[iTex]->Get();
if (mpTextures[iTex] && mpTextures[iTex]->Type() != eTexture)
mpTextures[iTex] = nullptr;
mpMat->Pass(iTex)->SetTexture(mpTextures[iTex]);
break;
}
}
}
}
bool CDamageableTriggerExtra::ShouldDrawNormalAssets()
{
return (mRenderSide == eNoRender);
}
void CDamageableTriggerExtra::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{
if (ViewInfo.GameMode && !mpInstance->IsActive())
return;
if (mRenderSide != eNoRender)
{
if (ViewInfo.ViewFrustum.BoxInFrustum(AABox()))
pRenderer->AddTransparentMesh(this, -1, AABox(), eDrawMesh);
if (mpParent->IsSelected() && !ViewInfo.GameMode)
pRenderer->AddOpaqueMesh(this, -1, AABox(), eDrawSelection);
}
}
void CDamageableTriggerExtra::Draw(ERenderOptions Options, int /*ComponentIndex*/, const SViewInfo& ViewInfo)
{
LoadModelMatrix();
CGraphics::sPixelBlock.TintColor = mpParent->TintColor(ViewInfo).ToVector4f();
mpMat->SetCurrent(Options);
// Note: The plane the game renders this onto is 5x4.5, which is why we divide the tex coords by this value
CVector2f TexUL(0.f, mCoordScale.y / 4.5f);
CVector2f TexUR(mCoordScale.x / 5.f, mCoordScale.y / 4.5f);
CVector2f TexBR(mCoordScale.x / 5.f, 0.f);
CVector2f TexBL(0.f, 0.f);
CDrawUtil::DrawSquare(TexUL, TexUR, TexBR, TexBL);
}
void CDamageableTriggerExtra::DrawSelection()
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBlendFunc(GL_ONE, GL_ZERO);
LoadModelMatrix();
CDrawUtil::UseColorShader(WireframeColor());
CDrawUtil::DrawSquare();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
void CDamageableTriggerExtra::RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo)
{
if (mRenderSide == eNoRender) return;
if (ViewInfo.GameMode && !mpInstance->IsActive()) return;
const CRay& Ray = Tester.Ray();
if (ViewInfo.pRenderer->RenderOptions() & eEnableBackfaceCull)
{
// We're guaranteed to be axis-aligned, so we can take advantage of that
// to perform a very simple backface check.
switch (mRenderSide)
{
case eNorth: if (Ray.Origin().y > AbsolutePosition().y) return; break;
case eSouth: if (Ray.Origin().y < AbsolutePosition().y) return; break;
case eWest: if (Ray.Origin().x < AbsolutePosition().x) return; break;
case eEast: if (Ray.Origin().x > AbsolutePosition().x) return; break;
case eUp: if (Ray.Origin().z > AbsolutePosition().z) return; break;
case eDown: if (Ray.Origin().z < AbsolutePosition().z) return; break;
}
}
std::pair<bool,float> Result = AABox().IntersectsRay(Ray);
if (Result.first)
Tester.AddNode(this, -1, Result.second);
}
SRayIntersection CDamageableTriggerExtra::RayNodeIntersectTest(const CRay& Ray, u32 /*ComponentIndex*/, const SViewInfo& /*ViewInfo*/)
{
// The bounding box and all other tests already passed in RayAABoxIntersectTest, so we
// already know that we have a positive. We just need the distance again.
std::pair<bool,float> Result = AABox().IntersectsRay(Ray);
return SRayIntersection(true, Result.second, mpParent, -1);
}

View File

@@ -0,0 +1,45 @@
#ifndef CDAMAGEABLETRIGGEREXTRA_H
#define CDAMAGEABLETRIGGEREXTRA_H
#include "CScriptExtra.h"
class CDamageableTriggerExtra : public CScriptExtra
{
// Render fluid planes for doors in MP1
enum ERenderSide
{
eNoRender = 0,
eNorth = 1,
eSouth = 2,
eWest = 3,
eEast = 4,
eUp = 5,
eDown = 6
};
CVector3Property *mpSizeProp;
CEnumProperty *mpRenderSideProp;
CFileProperty *mpTextureProps[3];
CVector3f mPlaneSize;
ERenderSide mRenderSide;
TResPtr<CTexture> mpTextures[3];
CMaterial *mpMat;
CVector2f mCoordScale;
public:
explicit CDamageableTriggerExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent = 0);
~CDamageableTriggerExtra();
void CreateMaterial();
void UpdatePlaneTransform();
void PropertyModified(CPropertyBase *pProperty);
bool ShouldDrawNormalAssets();
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void Draw(ERenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo);
void DrawSelection();
void RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo);
SRayIntersection RayNodeIntersectTest(const CRay& Ray, u32 ComponentIndex, const SViewInfo& ViewInfo);
};
#endif // CDAMAGEABLETRIGGEREXTRA_H

View File

@@ -0,0 +1,121 @@
#include "CDoorExtra.h"
#include <Core/CRenderer.h>
CDoorExtra::CDoorExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent)
: CScriptExtra(pInstance, pScene, pParent)
, mpShieldModelProp(nullptr)
, mpShieldColorProp(nullptr)
, mpShieldModel(nullptr)
{
CPropertyStruct *pBaseStruct = pInstance->Properties();
mpShieldModelProp = (CFileProperty*) pBaseStruct->PropertyByID(0xB20CC271);
if (mpShieldModelProp && (mpShieldModelProp->Type() != eFileProperty))
mpShieldModelProp = nullptr;
mpShieldColorProp = (CColorProperty*) pBaseStruct->PropertyByID(0x47B4E863);
if (mpShieldColorProp && (mpShieldColorProp->Type() != eColorProperty))
mpShieldColorProp = nullptr;
if (mpShieldModelProp)
PropertyModified(mpShieldModelProp);
}
void CDoorExtra::PropertyModified(CPropertyBase *pProperty)
{
if (pProperty == mpShieldModelProp)
{
mpShieldModel = mpShieldModelProp->Get();
if (mpShieldModel)
mLocalAABox = mpShieldModel->AABox();
else
mLocalAABox = CAABox::skInfinite;
MarkTransformChanged();
}
}
void CDoorExtra::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{
if (!mpShieldModel) return;
if (ViewInfo.GameMode && !mpInstance->IsActive()) return;
if (mpParent->IsVisible() && ViewInfo.ViewFrustum.BoxInFrustum(AABox()))
{
if (mpShieldModel->HasTransparency(0))
AddSurfacesToRenderer(pRenderer, mpShieldModel, 0, ViewInfo);
else
pRenderer->AddOpaqueMesh(this, -1, AABox(), eDrawMesh);
if (mpParent->IsSelected())
pRenderer->AddOpaqueMesh(this, -1, AABox(), eDrawSelection);
}
}
void CDoorExtra::Draw(ERenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo)
{
LoadModelMatrix();
mpParent->LoadLights(ViewInfo);
CGraphics::SetupAmbientColor();
CGraphics::UpdateVertexBlock();
CColor Tint = mpParent->TintColor(ViewInfo);
if (mpShieldColorProp)
Tint *= mpShieldColorProp->Get();
CGraphics::sPixelBlock.TintColor = Tint.ToVector4f();
CGraphics::sPixelBlock.TevColor = CColor::skWhite.ToVector4f();
CGraphics::UpdatePixelBlock();
if (ComponentIndex < 0)
mpShieldModel->Draw(Options, 0);
else
mpShieldModel->DrawSurface(Options, ComponentIndex, 0);
}
void CDoorExtra::DrawSelection()
{
LoadModelMatrix();
glBlendFunc(GL_ONE, GL_ZERO);
mpShieldModel->DrawWireframe(eNoRenderOptions, mpParent->WireframeColor());
}
void CDoorExtra::RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo)
{
if (!mpShieldModel) return;
if (ViewInfo.GameMode && !mpInstance->IsActive()) return;
const CRay& Ray = Tester.Ray();
std::pair<bool,float> BoxResult = AABox().IntersectsRay(Ray);
if (BoxResult.first)
Tester.AddNodeModel(this, mpShieldModel);
}
SRayIntersection CDoorExtra::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo)
{
ERenderOptions Options = ViewInfo.pRenderer->RenderOptions();
SRayIntersection out;
out.pNode = mpParent;
out.ComponentIndex = AssetID;
CRay TransformedRay = Ray.Transformed(Transform().Inverse());
std::pair<bool,float> Result = mpShieldModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((Options & eEnableBackfaceCull) == 0));
if (Result.first)
{
out.Hit = true;
CVector3f HitPoint = TransformedRay.PointOnRay(Result.second);
CVector3f WorldHitPoint = Transform() * HitPoint;
out.Distance = Ray.Origin().Distance(WorldHitPoint);
}
else out.Hit = false;
return out;
}

View File

@@ -0,0 +1,23 @@
#ifndef CDOOREXTRA_H
#define CDOOREXTRA_H
#include "CScriptExtra.h"
class CDoorExtra : public CScriptExtra
{
// Render colored door shield in MP2/3
CFileProperty *mpShieldModelProp;
CColorProperty *mpShieldColorProp;
TResPtr<CModel> mpShieldModel;
public:
explicit CDoorExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent = 0);
void PropertyModified(CPropertyBase *pProperty);
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void Draw(ERenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo);
void DrawSelection();
void RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo);
};
#endif // CDOOREXTRA_H

View File

@@ -0,0 +1,55 @@
#include "CPointOfInterestExtra.h"
const CColor CPointOfInterestExtra::skRegularColor((u32) 0xFF7000FF);
const CColor CPointOfInterestExtra::skImportantColor((u32) 0xFF0000FF);
CPointOfInterestExtra::CPointOfInterestExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent)
: CScriptExtra(pInstance, pScene, pParent)
, mpScanProperty(nullptr)
, mpScanData(nullptr)
{
// Fetch scan data property
CPropertyStruct *pBaseProp = pInstance->Properties();
switch (mGame)
{
case ePrimeDemo:
case ePrime:
mpScanProperty = (CFileProperty*) pBaseProp->PropertyByIDString("0x04:0x00");
break;
case eEchoesDemo:
case eEchoes:
case eCorruptionProto:
case eCorruption:
mpScanProperty = (CFileProperty*) pBaseProp->PropertyByIDString("0xBDBEC295:0xB94E9BE7");
break;
default:
mpScanProperty = nullptr;
break;
}
if (mpScanProperty)
{
if (mpScanProperty->Type() == eFileProperty)
PropertyModified(mpScanProperty);
else
mpScanProperty = nullptr;
}
}
void CPointOfInterestExtra::PropertyModified(CPropertyBase* pProperty)
{
if (mpScanProperty == pProperty)
mpScanData = mpScanProperty->Get();
}
void CPointOfInterestExtra::ModifyTintColor(CColor& Color)
{
if (mpScanData)
{
if (mpScanData->IsImportant()) Color *= skImportantColor;
else Color *= skRegularColor;
}
}

View File

@@ -0,0 +1,23 @@
#ifndef CPOINTOFINTERESTEXTRA_H
#define CPOINTOFINTERESTEXTRA_H
#include "CScriptExtra.h"
#include <Common/CColor.h>
#include <Resource/CScan.h>
class CPointOfInterestExtra : public CScriptExtra
{
// Tint POI billboard orange/red depending on scan importance
CFileProperty *mpScanProperty;
TResPtr<CScan> mpScanData;
public:
explicit CPointOfInterestExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent = 0);
void PropertyModified(CPropertyBase* pProperty);
void ModifyTintColor(CColor& Color);
static const CColor skRegularColor;
static const CColor skImportantColor;
};
#endif // CPOINTOFINTERESTEXTRA_H

View File

@@ -0,0 +1,49 @@
#include "CScriptExtra.h"
#include "CWaypointExtra.h"
#include "CDamageableTriggerExtra.h"
#include "CSpacePirateExtra.h"
#include "CPointOfInterestExtra.h"
#include "CDoorExtra.h"
CScriptExtra* CScriptExtra::CreateExtra(CScriptNode *pNode)
{
CScriptExtra *pExtra = nullptr;
CScriptObject *pObj = pNode->Object();
if (pObj)
{
switch (pObj->ObjectTypeID())
{
case 0x02: // Waypoint (MP1)
case 0x0D: // CameraWaypoint (MP1)
case 0x2C: // SpiderBallWaypoint (MP1)
case 0x32: // DebugCameraWaypoint(MP1)
case 0x41495750: // "AIWP" AIWaypoint (MP2/MP3/DKCR)
case 0x42414C57: // "BALW" SpiderBallWaypoint (MP2/MP3)
case 0x43414D57: // "CAMW" CameraWaypoint (MP2)
case 0x57415950: // "WAYP" Waypoint (MP2/MP3/DKCR)
pExtra = new CWaypointExtra(pObj, pNode->Scene(), pNode);
break;
case 0x1A: // DamageableTrigger (MP1)
pExtra = new CDamageableTriggerExtra(pObj, pNode->Scene(), pNode);
break;
case 0x24: // SpacePirate (MP1)
pExtra = new CSpacePirateExtra(pObj, pNode->Scene(), pNode);
break;
case 0x42: // PointOfInterest (MP1)
case 0x504F494E: // "POIN" PointOfInterest (MP2/MP3)
pExtra = new CPointOfInterestExtra(pObj, pNode->Scene(), pNode);
break;
case 0x444F4F52: // "DOOR" Door (MP2/MP3)
pExtra = new CDoorExtra(pObj, pNode->Scene(), pNode);
break;
}
}
return pExtra;
}

View File

@@ -0,0 +1,54 @@
#ifndef CSCRIPTEXTRA_H
#define CSCRIPTEXTRA_H
#include "../CSceneNode.h"
#include "../CScriptNode.h"
/* CScriptExtra is a class that allows for additional coded behavior on any given
* script object type. Subclass IScriptExtra, add the new class to CScriptExtra.cpp,
* and reimplement whatever functions are needed to create the desired behavior. Note
* that in addition to the functions here you can also reimplement IRenderable functions
* (to render additional geometry) and CSceneNode functions (primarily for raycast
* intersections).
*/
class CScriptExtra : public CSceneNode
{
protected:
CScriptObject *mpInstance;
EGame mGame;
public:
explicit CScriptExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent = 0)
: CSceneNode(pScene, pParent),
mpInstance(pInstance),
mGame(pInstance->Template()->Game())
{
}
virtual ~CScriptExtra() {}
// Default implementations for CSceneNode
virtual ENodeType NodeType() { return eScriptExtraNode; }
virtual SRayIntersection RayNodeIntersectTest(const CRay& /*Ray*/, u32 /*AssetID*/, const SViewInfo& /*ViewInfo*/)
{
SRayIntersection out;
out.Hit = false;
return out;
}
virtual CColor WireframeColor() const { return mpParent->WireframeColor(); }
// Virtual CScriptExtra functions
virtual void InstanceTransformed() {}
virtual void PropertyModified(CPropertyBase* /*pProperty*/) {}
virtual void LinksModified() {}
virtual bool ShouldDrawNormalAssets() { return true; }
virtual bool ShouldDrawVolume() { return true; }
virtual CColor TevColor() { return CColor::skWhite; }
virtual void ModifyTintColor(CColor& /*Color*/) {}
// Create Script Extra
static CScriptExtra* CreateExtra(CScriptNode *pNode);
};
#endif // CSCRIPTEXTRA_H

View File

@@ -0,0 +1,49 @@
#include "CSpacePirateExtra.h"
CSpacePirateExtra::CSpacePirateExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent)
: CScriptExtra(pInstance, pScene ,pParent)
, mpPowerVuln(nullptr)
, mpWaveVuln(nullptr)
, mpIceVuln(nullptr)
, mpPlasmaVuln(nullptr)
{
CPropertyStruct *pBaseStruct = pInstance->Properties();
CPropertyStruct *pVulns = (CPropertyStruct*) pBaseStruct->PropertyByIDString("0x04:0x10");
if (pVulns && pVulns->Type() == eStructProperty)
{
mpPowerVuln = (CLongProperty*) pVulns->PropertyByID(0x0);
if (mpPowerVuln && mpPowerVuln->Type() != eLongProperty && mpPowerVuln->Type() != eEnumProperty)
mpPowerVuln = nullptr;
mpWaveVuln = (CLongProperty*) pVulns->PropertyByID(0x2);
if (mpWaveVuln && mpWaveVuln->Type() != eLongProperty && mpWaveVuln->Type() != eEnumProperty)
mpWaveVuln = nullptr;
mpIceVuln = (CLongProperty*) pVulns->PropertyByID(0x1);
if (mpIceVuln && mpIceVuln->Type() != eLongProperty && mpIceVuln->Type() != eEnumProperty)
mpIceVuln = nullptr;
mpPlasmaVuln = (CLongProperty*) pVulns->PropertyByID(0x3);
if (mpPlasmaVuln && mpPlasmaVuln->Type() != eLongProperty && mpPlasmaVuln->Type() != eEnumProperty)
mpPlasmaVuln = nullptr;
}
}
CColor CSpacePirateExtra::TevColor()
{
// Priority: Plasma -> Ice -> Power -> Wave
if (mpPlasmaVuln && mpPlasmaVuln->Get() == 1)
return CColor::skRed;
if (mpIceVuln && mpIceVuln->Get() == 1)
return CColor::skWhite;
if (mpPowerVuln && mpPowerVuln->Get() == 1)
return CColor::skYellow;
if (mpWaveVuln && mpWaveVuln->Get() == 1)
return CColor::skPurple;
return CColor::skWhite;
}

View File

@@ -0,0 +1,20 @@
#ifndef CSPACEPIRATEEXTRA_H
#define CSPACEPIRATEEXTRA_H
#include "CScriptExtra.h"
#include <Resource/script/CProperty.h>
class CSpacePirateExtra : public CScriptExtra
{
// Render beam troopers with the correct color
CLongProperty *mpPowerVuln;
CLongProperty *mpWaveVuln;
CLongProperty *mpIceVuln;
CLongProperty *mpPlasmaVuln;
public:
explicit CSpacePirateExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent = 0);
CColor TevColor();
};
#endif // CSPACEPIRATEEXTRA_H

View File

@@ -0,0 +1,106 @@
#include "CWaypointExtra.h"
#include <Core/CDrawUtil.h>
#include <Core/CRenderer.h>
#include <Core/CSceneManager.h>
CWaypointExtra::CWaypointExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent)
: CScriptExtra(pInstance, pScene, pParent)
, mColor(CColor::skBlack)
, mLinksBuilt(false)
{
// Fetch color from parent node's model
CScriptNode *pScript = static_cast<CScriptNode*>(pParent);
CModel *pModel = pScript->ActiveModel();
if (pModel && (pModel->GetMatSetCount() > 0) && (pModel->GetMatCount() > 0))
{
CMaterial *pMat = pModel->GetMaterialByIndex(0, 0);
mColor = pMat->Konst(0);
mColor.a = 0;
}
}
void CWaypointExtra::BuildLinks()
{
mLinks.clear();
for (u32 iLink = 0; iLink < mpInstance->NumOutLinks(); iLink++)
{
const SLink& rkLink = mpInstance->OutLink(iLink);
if (IsPathLink(rkLink))
{
CScriptNode *pNode = mpScene->ScriptNodeByID(rkLink.ObjectID);
SWaypointLink Link;
Link.pWaypoint = pNode;
Link.LineAABB.ExpandBounds(AbsolutePosition());
Link.LineAABB.ExpandBounds(pNode->AbsolutePosition());
mLinks.push_back(Link);
}
}
mLinksBuilt = true;
}
bool CWaypointExtra::IsPathLink(const SLink& rkLink)
{
bool Valid = false;
if (rkLink.State < 0xFF)
{
if (rkLink.State == 0x1 && rkLink.Message == 0x8) Valid = true; // Arrived / Next (MP1)
}
else
{
CFourCC State(rkLink.State);
CFourCC Message(rkLink.Message);
if (State == "ARRV" && Message == "NEXT") Valid = true; // Arrived / Next (MP2)
if (State == "NEXT" && Message == "ATCH") Valid = true; // Next / Attach (MP3/DKCR)
}
if (Valid)
{
CScriptNode *pNode = mpScene->ScriptNodeByID(rkLink.ObjectID);
if (pNode)
return pNode->Object()->ObjectTypeID() == mpInstance->ObjectTypeID();
}
return false;
}
void CWaypointExtra::LinksModified()
{
BuildLinks();
}
void CWaypointExtra::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{
// This call is necessary because if we try to build links in the constructor, it
// won't work properly because we haven't finished loading the scene yet.
if (!mLinksBuilt) BuildLinks();
if (!ViewInfo.GameMode && mpParent->IsVisible() && !mpParent->IsSelected())
{
for (u32 iLink = 0; iLink < mLinks.size(); iLink++)
{
CScriptNode *pNode = mLinks[iLink].pWaypoint;
if (pNode->IsVisible() && !pNode->IsSelected() && ViewInfo.ViewFrustum.BoxInFrustum(mLinks[iLink].LineAABB))
pRenderer->AddOpaqueMesh(this, iLink, mLinks[iLink].LineAABB, eDrawMesh);
}
}
}
void CWaypointExtra::Draw(ERenderOptions /*Options*/, int ComponentIndex, const SViewInfo& /*ViewInfo*/)
{
glBlendFunc(GL_ONE, GL_ZERO);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
CGraphics::sMVPBlock.ModelMatrix = CMatrix4f::skIdentity;
CGraphics::UpdateMVPBlock();
CDrawUtil::DrawLine(mpParent->AABox().Center(), mLinks[ComponentIndex].pWaypoint->AABox().Center(), mColor);
}

View File

@@ -0,0 +1,30 @@
#ifndef CWAYPOINTEXTRA_H
#define CWAYPOINTEXTRA_H
#include "CScriptExtra.h"
#include <Common/CColor.h>
class CWaypointExtra : public CScriptExtra
{
// Draw waypoint paths formed by script connections
CColor mColor;
bool mLinksBuilt;
struct SWaypointLink
{
CScriptNode *pWaypoint;
CAABox LineAABB;
};
std::vector<SWaypointLink> mLinks;
public:
explicit CWaypointExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent = 0);
void BuildLinks();
bool IsPathLink(const SLink& rkLink);
void LinksModified();
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void Draw(ERenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo);
};
#endif // CWAYPOINTEXTRA_H