Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ static PoolSizeRec PoolSizes[] =
{ "W3DTankDraw", 256, 32 },
{ "W3DTreeDraw", 16, 16 },
{ "W3DPropDraw", 16, 16 },
{ "W3DDecalDraw", 16, 16 },
{ "W3DTracerDraw", 64, 32 },
{ "W3DTruckDraw", 128, 32 },
{ "W3DTankTruckDraw", 32, 16 },
Expand Down Expand Up @@ -499,6 +500,7 @@ static PoolSizeRec PoolSizes[] =
{ "GenericObjectCreationNugget", 632, 32 },
{ "SoundFXNugget", 320, 32 },
{ "TracerFXNugget", 32, 32 },
{ "DecalFXNugget", 32, 32 },
{ "RayEffectFXNugget", 32, 32 },
{ "LightPulseFXNugget", 68, 32 },
{ "ViewShakeFXNugget", 140, 32 },
Expand Down
119 changes: 119 additions & 0 deletions Core/GameEngine/Source/GameClient/FXList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine

#define DEFINE_SHADOW_NAMES

#include "GameClient/FXList.h"

#include "Common/DrawModule.h"
Expand All @@ -50,6 +52,9 @@
#include "GameClient/Drawable.h"
#include "GameClient/ParticleSys.h"
#include "GameLogic/PartitionManager.h"
#include "GameClient/Shadow.h"
#include "../../../GameEngineDevice/Include/W3DDevice/GameClient/Module/W3DModelDraw.h"
#include "../../../GameEngineDevice/Include/W3DDevice/GameClient/W3DShadow.h"

///////////////////////////////////////////////////////////////////////////////////////////////////
// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -467,6 +472,119 @@ class RayEffectFXNugget : public FXNugget
};
EMPTY_DTOR(RayEffectFXNugget)


//-------------------------------------------------------------------------------------------------
class DecalFXNugget : public FXNugget
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(DecalFXNugget, "DecalFXNugget")
public:

DecalFXNugget()
{
m_templateName.set("GenericDecal"); // TODO
//m_templateName = AsciiString::TheEmptyString;
//m_textureName = AsciiString::TheEmptyString;
//m_opacity = 1.0; ///< value between 0 and 1
//m_color = 0; ///< color in ARGB format. (Alpha is ignored).
m_lifetime = 0;
/* m_fadeOutTime = 0;
m_fadeInTime = 0;
m_type = 0; /// type of projection
m_decalSizeX = 0.0; /// 1/(world space extent of texture in x direction)
m_decalSizeY = 0.0; /// 1/(world space extent of texture in y direction)*/
m_offset.x = m_offset.y = m_offset.z = 0;
m_angle = 0.0;
m_orientToObject = FALSE;
m_randomAngle = FALSE;
m_probability = 1.0f;
}

virtual void doFXPos(const Coord3D* primary, const Matrix3D* primaryMtx, const Real primarySpeed, const Coord3D* secondary, const Real /*overrideRadius*/, FXSurfaceInfo* /*surfaceInfo*/) const
{
if (m_probability <= GameClientRandomValueReal(0, 1))
return;

if (primary)
{
Coord3D offset = m_offset;
if (primaryMtx) {
if (m_orientToObject)
{
adjustVector(&offset, primaryMtx);
}
}

Drawable* drawable = TheThingFactory->newDrawable(TheThingFactory->findTemplate(m_templateName));
if (!drawable)
return;

// Does it even make sense to set the matrix?
if (primaryMtx && m_orientToObject)
drawable->setTransformMatrix(primaryMtx);

Coord3D newPos;
newPos.x = primary->x + offset.x;
newPos.y = primary->y + offset.y;
newPos.z = primary->z + offset.z;
drawable->setPosition(&newPos);

if (m_randomAngle)
drawable->setOrientation(GameClientRandomValueReal(0, PI * 2));

drawable->setExpirationDate(TheGameLogic->getFrame() + m_lifetime);
}
else
{
DEBUG_CRASH(("You must have a primary source for this effect"));
}
}

virtual void doFXObj(const Object* primary, const Object* secondary, FXSurfaceInfo* surfaceInfo) const
{
if (primary)
{
doFXPos(primary->getPosition(), primary->getTransformMatrix(), 0.0f, nullptr, 0.0f, surfaceInfo);
}
else
{
DEBUG_CRASH(("You must have a primary source for this effect"));
}
}

static void parse(INI* ini, void* instance, void* /*store*/, const void* /*userData*/)
{
static const FieldParse myFieldParse[] =
{
{ "DecalName", INI::parseAsciiString, nullptr, offsetof(DecalFXNugget, m_templateName) },
{ "Lifetime", INI::parseDurationUnsignedInt, nullptr, offsetof(DecalFXNugget, m_lifetime) },
{ "Offset", INI::parseCoord3D, nullptr, offsetof(DecalFXNugget, m_offset) },
{ "Angle", INI::parseReal, nullptr, offsetof(DecalFXNugget, m_angle) },
{ "RandomAngle", INI::parseBool, nullptr, offsetof(DecalFXNugget, m_randomAngle) },
{ "OrientToObject", INI::parseBool, nullptr, offsetof(DecalFXNugget, m_orientToObject) },
{ "Probability", INI::parseReal, nullptr, offsetof(DecalFXNugget, m_probability) },
{ nullptr, nullptr, nullptr, 0 }
};

DecalFXNugget* nugget = newInstance(DecalFXNugget);
ini->initFromINI(nugget, myFieldParse);
((FXList*)instance)->addFXNugget(nugget);
}

private:
AsciiString m_templateName;
UnsignedInt m_lifetime;
Coord3D m_offset;
Real m_angle;
Bool m_orientToObject;
Bool m_randomAngle;

// spawn parameters
Real m_probability;
// TODO: Height/Surface, etc.
};
EMPTY_DTOR(DecalFXNugget)


//-------------------------------------------------------------------------------------------------
class LightPulseFXNugget : public FXNugget
{
Expand Down Expand Up @@ -1025,6 +1143,7 @@ static const FieldParse TheFXListFieldParse[] =
{ "TerrainScorch", TerrainScorchFXNugget::parse, nullptr, 0},
{ "ParticleSystem", ParticleSystemFXNugget::parse, nullptr, 0},
{ "FXListAtBonePos", FXListAtBonePosFXNugget::parse, nullptr, 0},
{ "Decal", DecalFXNugget::parse, nullptr, 0},
{ nullptr, nullptr, nullptr, 0 }
};

Expand Down
2 changes: 2 additions & 0 deletions Core/GameEngineDevice/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ set(GAMEENGINEDEVICE_SRC
Include/W3DDevice/GameClient/Module/W3DPoliceCarDraw.h
Include/W3DDevice/GameClient/Module/W3DProjectileStreamDraw.h
Include/W3DDevice/GameClient/Module/W3DPropDraw.h
Include/W3DDevice/GameClient/Module/W3DDecalDraw.h
Include/W3DDevice/GameClient/Module/W3DRopeDraw.h
Include/W3DDevice/GameClient/Module/W3DScienceModelDraw.h
Include/W3DDevice/GameClient/Module/W3DSupplyDraw.h
Expand Down Expand Up @@ -110,6 +111,7 @@ set(GAMEENGINEDEVICE_SRC
Source/W3DDevice/GameClient/Drawable/Draw/W3DPoliceCarDraw.cpp
Source/W3DDevice/GameClient/Drawable/Draw/W3DProjectileStreamDraw.cpp
Source/W3DDevice/GameClient/Drawable/Draw/W3DPropDraw.cpp
Source/W3DDevice/GameClient/Drawable/Draw/W3DDecalDraw.cpp
Source/W3DDevice/GameClient/Drawable/Draw/W3DRopeDraw.cpp
Source/W3DDevice/GameClient/Drawable/Draw/W3DScienceModelDraw.cpp
Source/W3DDevice/GameClient/Drawable/Draw/W3DSupplyDraw.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////

// FILE: W3DDecalDraw.h //////////////////////////////////////////////////////////////////////////
// Author: Andi W, May 26
// Desc: Draw module for Decal FXNugget
///////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/DrawModule.h"
#include "WW3D2/line3d.h"
#include "W3DDevice/GameClient/W3DShadow.h"
#include "WW3D2/boxrobj.h"

//-------------------------------------------------------------------------------------------------
class W3DDecalDrawModuleData : public ModuleData
{
public:

AsciiString m_textureName;
Real m_opacity; ///< value between 0 and 1
UnsignedInt m_color; ///< color in ARGB format. (Alpha is ignored).
// UnsignedInt m_lifetime;
UnsignedInt m_fadeOutTime;
UnsignedInt m_fadeInTime;
ShadowType m_type; /// type of projection
Real m_decalSizeX; /// 1/(world space extent of texture in x direction)
Real m_decalSizeY; /// 1/(world space extent of texture in y direction)

W3DDecalDrawModuleData();
~W3DDecalDrawModuleData();
static void buildFieldParse(MultiIniFieldParse& p);
// ugh, hack
virtual const W3DDecalDrawModuleData* getAsW3DDecalDrawModuleData() const { return this; }
};

//-------------------------------------------------------------------------------------------------
/** W3D prop draw */
//-------------------------------------------------------------------------------------------------
class W3DDecalDraw : public DrawModule //, public DecalDrawInterface
{

MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( W3DDecalDraw, "W3DDecalDraw" )
MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( W3DDecalDraw, W3DDecalDrawModuleData )

public:

W3DDecalDraw( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype provided by memory pool declaration

virtual void doDrawModule(const Matrix3D* transformMtx);
virtual void setShadowsEnabled(Bool enable) { }
virtual void releaseShadows(void) {}; ///< we don't care about preserving temporary shadows.
virtual void allocateShadows(void) {}; ///< we don't care about preserving temporary shadows.
virtual void setFullyObscuredByShroud(Bool fullyObscured);
virtual void reactToTransformChange(const Matrix3D* oldMtx, const Coord3D* oldPos, Real oldAngle);
virtual void reactToGeometryChange() { }


//virtual DecalDrawInterface* getDecalDrawInterface() { return this; }
//virtual const DecalDrawInterface* getDecalDrawInterface() const { return this; }

//virtual void initDecal(AsciiString texture, Real opacity, Int color, ShadowType type, UnsignedInt lifetime, UnsignedInt fadeOutTime, UnsignedInt fadeInTime, Real sizeX, Real sizeY);


protected:
//Bool m_propAdded;

OBBoxRenderObjClass* m_renderBox; // The render object
Shadow* m_shadow; // the decal
Bool m_fullyObscuredByShroud;
UnsignedInt m_frameCreated;

private:
void init_shadow();
void init_renderBox(const Matrix3D* transformMtx);
};
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,16 @@ struct ParticleSysBoneInfo

typedef std::vector<ParticleSysBoneInfo> ParticleSysBoneInfoVector;

//-------------------------------------------------------------------------------------------------
struct FXEventInfo
{
AsciiString boneName;
const FXList* fx;
UnsignedInt frame;
};

typedef std::vector<FXEventInfo> FXEventInfoVector;

//-------------------------------------------------------------------------------------------------
struct PristineBoneInfo
{
Expand Down Expand Up @@ -222,12 +232,18 @@ struct ModelConditionInfo
Real m_animMinSpeedFactor; //Min speed factor (randomized each time it's played)
Real m_animMaxSpeedFactor; //Max speed factor (randomized each time it's played)

FXEventInfoVector m_fxEvents; ///<frames, Bone names and attached FXLists

mutable PristineBoneInfoMap m_pristineBones;
mutable TurretInfo m_turrets[MAX_TURRETS];
mutable WeaponBarrelInfoVec m_weaponBarrelInfoVec[WEAPONSLOT_COUNT];
mutable Bool m_hasRecoilBonesOrMuzzleFlashes[WEAPONSLOT_COUNT];
mutable Byte m_validStuff;

// Animation Blending (needs WalkerDraw)
UnsignedInt m_animBlendTime;


enum
{
PRISTINE_BONES_VALID = 0x0001,
Expand Down Expand Up @@ -316,6 +332,8 @@ class W3DModelDrawModuleData : public ModuleData

Bool m_showForOwnerOnly; ///< show this model only to the owning player

Bool m_keepRecoilAcrossStates; ///< Don't reset recoil bones when switching states

// Bool m_disableMoveEffectsOverWater; ///< disable track marks and tread/wheel anims over water

W3DModelDrawModuleData();
Expand Down Expand Up @@ -434,6 +452,8 @@ class W3DModelDraw : public DrawModule, public ObjectDrawInterface
RenderObjClass *getRenderObject() { return m_renderObject; }
virtual Bool updateBonesForClientParticleSystems( void );///< this will reposition particle systems on the fly ML

virtual void handleFXEvents(); // Check frame times and trigger FX events at correct positions

virtual void onDrawableBoundToObject();
virtual void setTerrainDecalSize(Real x, Real y);
virtual void setTerrainDecalOpacity(Real o);
Expand Down Expand Up @@ -492,6 +512,16 @@ class W3DModelDraw : public DrawModule, public ObjectDrawInterface
Int boneIndex;
};

struct AnimInfoHelper
{
Int frameNum;
Int mode;
float numFrames;
float fraction;
};
AnimInfoHelper m_prevAnimHelper;
AnimInfoHelper getCurrentAnimHelper() const;


typedef std::vector<WeaponRecoilInfo> WeaponRecoilInfoVec;
typedef std::vector<ParticleSysTrackerType> ParticleSystemIDVec;
Expand Down Expand Up @@ -522,7 +552,7 @@ class W3DModelDraw : public DrawModule, public ObjectDrawInterface
Real getCurrentAnimFraction() const;
void applyCorrectModelStateAnimation();
const ModelConditionInfo* findTransitionForSig(TransitionSig sig) const;
void rebuildWeaponRecoilInfo(const ModelConditionInfo* state);
void rebuildWeaponRecoilInfo(const ModelConditionInfo* state, bool clear = TRUE);
void doHideShowProjectileObjects( UnsignedInt showCount, UnsignedInt maxCount, WeaponSlotType slot );///< Means effectively, show m of n.
void nukeCurrentRender(Matrix3D* xform);
void doStartOrStopParticleSys();
Expand Down
Loading
Loading