From f0c0f3c42c3862b2e2250d18b19e00d78eccd95b Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Wed, 16 Apr 2025 13:08:39 -0500 Subject: [PATCH 1/4] projectile augs use impactforce to applyimpulse for stock physics too add an optional explodeOnTmeout for nonballistic projectiles, track if they hit something before their armingdelay is up, and delete them next simulation cycle --- Engine/source/T3D/projectile.cpp | 37 ++++++++++++++++++++++++++------ Engine/source/T3D/projectile.h | 4 ++-- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/Engine/source/T3D/projectile.cpp b/Engine/source/T3D/projectile.cpp index 56f8af638..58c6f3aa6 100644 --- a/Engine/source/T3D/projectile.cpp +++ b/Engine/source/T3D/projectile.cpp @@ -56,6 +56,7 @@ #include "T3D/decal/decalData.h" #include "T3D/lightDescription.h" #include "console/engineAPI.h" +#include "T3D/rigidShape.h" IMPLEMENT_CO_DATABLOCK_V1(ProjectileData); @@ -163,6 +164,7 @@ ProjectileData::ProjectileData() scale.set( 1.0f, 1.0f, 1.0f ); isBallistic = false; + mExplodeOnTmeout = false; velInheritFactor = 1.0f; muzzleVelocity = 50; @@ -203,6 +205,7 @@ ProjectileData::ProjectileData(const ProjectileData& other, bool temp_clone) : G muzzleVelocity = other.muzzleVelocity; impactForce = other.impactForce; isBallistic = other.isBallistic; + mExplodeOnTmeout = other.mExplodeOnTmeout; bounceElasticity = other.bounceElasticity; bounceFriction = other.bounceFriction; gravityMod = other.gravityMod; @@ -285,6 +288,8 @@ void ProjectileData::initPersistFields() addProtectedFieldV("fadeDelay", TypeRangedS32, Offset(fadeDelay, ProjectileData), &setFadeDelay, &getScaledValue, &CommonValidators::NaturalNumber, "@brief Amount of time, in milliseconds, before the projectile begins to fade out.\n\n" "This value must be smaller than the projectile's lifetime to have an affect."); + addField("explodeOnTmeout", TypeBool, Offset(mExplodeOnTmeout, ProjectileData), + "@brief Detetmines if the projectile should explode on timeout"); addField("isBallistic", TypeBool, Offset(isBallistic, ProjectileData), "@brief Detetmines if the projectile should be affected by gravity and whether or not " "it bounces before exploding.\n\n"); @@ -455,13 +460,14 @@ void ProjectileData::packData(BitStream* stream) stream->write(armingDelay); stream->write(fadeDelay); + stream->writeFlag(mExplodeOnTmeout); if(stream->writeFlag(isBallistic)) { stream->write(gravityMod); stream->write(bounceElasticity); stream->write(bounceFriction); } - + } void ProjectileData::unpackData(BitStream* stream) @@ -514,6 +520,7 @@ void ProjectileData::unpackData(BitStream* stream) stream->read(&armingDelay); stream->read(&fadeDelay); + mExplodeOnTmeout = stream->readFlag(); isBallistic = stream->readFlag(); if(isBallistic) { @@ -611,6 +618,7 @@ Projectile::Projectile() mProjectileShape( NULL ), mActivateThread( NULL ), mMaintainThread( NULL ), + mHasHit(false), mHasExploded( false ), mFadeValue( 1.0f ) { @@ -1128,10 +1136,18 @@ void Projectile::processTick( const Move *move ) void Projectile::simulate( F32 dt ) { - if ( isServerObject() && mCurrTick >= mDataBlock->lifetime ) + if ( isServerObject() ) { - deleteObject(); - return; + if (mCurrTick >= (mDataBlock->lifetime - TickMs)) + { + if (mDataBlock->mExplodeOnTmeout) + explode(mCurrPosition, Point3F::UnitZ, VehicleObjectType); + } + if (mCurrTick >= mDataBlock->lifetime || (mHasHit && mCurrTick < mDataBlock->armingDelay)) + { + deleteObject(); + return; + } } if ( mHasExploded ) @@ -1167,9 +1183,16 @@ void Projectile::simulate( F32 dt ) if ( mPhysicsWorld ) hit = mPhysicsWorld->castRay( oldPosition, newPosition, &rInfo, Point3F( newPosition - oldPosition) * mDataBlock->impactForce ); - else + else + { hit = getContainer()->castRay(oldPosition, newPosition, dynamicCollisionMask | staticCollisionMask, &rInfo); - + if (hit && rInfo.object->getTypeMask() & VehicleObjectType) + { + RigidShape* aRigid = dynamic_cast(rInfo.object); + if (aRigid) + aRigid->applyImpulse(rInfo.point, Point3F(newPosition - oldPosition) * mDataBlock->impactForce); + } + } if ( hit ) { // make sure the client knows to bounce @@ -1237,6 +1260,8 @@ void Projectile::simulate( F32 dt ) else { mCurrVelocity = Point3F::Zero; + newPosition = oldPosition = rInfo.point + rInfo.normal * 0.05f; + mHasHit = true; } } diff --git a/Engine/source/T3D/projectile.h b/Engine/source/T3D/projectile.h index 671c3f98f..04e91aa60 100644 --- a/Engine/source/T3D/projectile.h +++ b/Engine/source/T3D/projectile.h @@ -87,9 +87,9 @@ public: /// Force imparted on a hit object. F32 impactForce; + bool mExplodeOnTmeout; /// Should it arc? bool isBallistic; - /// How HIGH should it bounce (parallel to normal), [0,1] F32 bounceElasticity; /// How much momentum should be lost when it bounces (perpendicular to normal), [0,1] @@ -274,7 +274,7 @@ protected: LightInfo *mLight; LightState mLightState; - + bool mHasHit; bool mHasExploded; ///< Prevent rendering, lighting, and duplicate explosions. F32 mFadeValue; ///< set in processTick, interpolation between fadeDelay and lifetime ///< in data block From 7b7de1f10fdb0b3d9052202c875008b790b4e51d Mon Sep 17 00:00:00 2001 From: JeffR Date: Tue, 22 Apr 2025 18:20:12 -0500 Subject: [PATCH 2/4] Adjusts the handling of the disconnect call to not utilize package overrides, but instead a callOnModules invoke like most other cross-module calls. This allows the editor to issue a disconnect call properly again. --- .../scripts/client/connectionToServer.tscript | 6 ++- Templates/BaseGame/game/tools/tools.tscript | 9 +++++ .../worldEditor/scripts/editor.ed.tscript | 37 ------------------- 3 files changed, 14 insertions(+), 38 deletions(-) diff --git a/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.tscript b/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.tscript index cbd4b46cc..94f30857f 100644 --- a/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.tscript +++ b/Templates/BaseGame/game/core/clientServer/scripts/client/connectionToServer.tscript @@ -111,8 +111,12 @@ function handleConnectionErrorMessage(%msgType, %msgString, %msgError) //----------------------------------------------------------------------------- // Disconnect //----------------------------------------------------------------------------- - function disconnect() +{ + callOnModules("disconnect"); +} + +function Core_ClientServer::disconnect(%this) { // We need to stop the client side simulation // else physics resources will not cleanup properly. diff --git a/Templates/BaseGame/game/tools/tools.tscript b/Templates/BaseGame/game/tools/tools.tscript index 47101f55a..04ce56cad 100644 --- a/Templates/BaseGame/game/tools/tools.tscript +++ b/Templates/BaseGame/game/tools/tools.tscript @@ -23,4 +23,13 @@ function ToolsModule::onCreate(%this) function ToolsModule::onDestroy(%this) { +} + +function ToolsModule::disconnect(%this) +{ + if ( isObject( Editor ) && Editor.isEditorEnabled() ) + { + EditorGui.saveAs = false; //whatever edits we were doing are irrelevent now + Editor.close(MainMenuGui); + } } \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/editor.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/editor.ed.tscript index ff5696dd5..9f0bc5b77 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/editor.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/editor.ed.tscript @@ -164,40 +164,3 @@ function toggleEditor(%make) //------------------------------------------------------------------------------ // The editor action maps are defined in editor.bind.tscript GlobalActionMap.bind(keyboard, "f11", fastLoadWorldEdit); - - -// The scenario: -// The editor is open and the user closes the level by any way other than -// the file menu ( exit level ), eg. typing disconnect() in the console. -// -// The problem: -// Editor::close() is not called in this scenario which means onEditorDisable -// is not called on objects which hook into it and also gEditingMission will no -// longer be valid. -// -// The solution: -// Override the stock disconnect() function which is in game scripts from here -// in tools so we avoid putting our code in there. -// -// Disclaimer: -// If you think of a better way to do this feel free. The thing which could -// be dangerous about this is that no one will ever realize this code overriding -// a fairly standard and core game script from a somewhat random location. -// If it 'did' have unforscene sideeffects who would ever find it? - -package EditorDisconnectOverride -{ - function disconnect() - { - if ( isObject( Editor ) && Editor.isEditorEnabled() ) - { - EditorGui.saveAs = false; //whatever edits we were doing are irrelevent now - %mainMenuGUI = ProjectSettings.value("UI/mainMenuName"); - if (isObject( %mainMenuGUI )) - Editor.close( %mainMenuGUI ); - } - - Parent::disconnect(); - } -}; -activatePackage( EditorDisconnectOverride ); From f31acf774ed5a614c3a4f625b4d3e0c3a9931495 Mon Sep 17 00:00:00 2001 From: JeffR Date: Thu, 24 Apr 2025 00:58:20 -0500 Subject: [PATCH 3/4] Adds handling for datablocks to be reloaded if the assets they utilize have their files directly edited. --- Engine/source/T3D/assets/ShapeAsset.h | 8 +++++- Engine/source/T3D/debris.h | 5 +++- Engine/source/T3D/fx/explosion.h | 5 +++- Engine/source/T3D/fx/groundCover.h | 4 ++- Engine/source/T3D/fx/particle.h | 5 +++- Engine/source/T3D/fx/precipitation.h | 10 +++++-- Engine/source/T3D/fx/splash.h | 5 +++- Engine/source/T3D/lightFlareData.h | 5 +++- Engine/source/T3D/physics/physicsDebris.h | 5 +++- Engine/source/T3D/physics/physicsShape.h | 5 +++- Engine/source/T3D/player.h | 7 ++++- Engine/source/T3D/projectile.h | 5 +++- Engine/source/T3D/shapeBase.cpp | 12 ++++++++- Engine/source/T3D/shapeBase.h | 11 +++++--- Engine/source/T3D/vehicles/wheeledVehicle.h | 5 +++- Engine/source/afx/afxMagicMissile.h | 5 +++- Engine/source/afx/ce/afxBillboard.h | 5 +++- Engine/source/afx/ce/afxModel.h | 5 +++- Engine/source/afx/ce/afxZodiac.h | 5 +++- Engine/source/afx/ce/afxZodiacPlane.h | 5 +++- Engine/source/console/simDatablock.cpp | 29 ++++++++++++--------- Engine/source/console/simDatablock.h | 2 ++ Engine/source/forest/forestItem.h | 5 +++- 23 files changed, 121 insertions(+), 37 deletions(-) diff --git a/Engine/source/T3D/assets/ShapeAsset.h b/Engine/source/T3D/assets/ShapeAsset.h index afa39ca57..2d186346d 100644 --- a/Engine/source/T3D/assets/ShapeAsset.h +++ b/Engine/source/T3D/assets/ShapeAsset.h @@ -370,7 +370,7 @@ public: \ #pragma region Arrayed Asset Macros -#define DECLARE_SHAPEASSET_ARRAY(className,name,max) public: \ +#define DECLARE_SHAPEASSET_ARRAY(className,name,max,changeFunc) public: \ static const U32 sm##name##Count = max;\ Resourcem##name[max];\ StringTableEntry m##name##Name[max]; \ @@ -384,6 +384,10 @@ public: \ \ bool _set##name(StringTableEntry _in, const U32& index)\ {\ + if (m##name##Asset[index].notNull())\ + {\ + m##name##Asset[index]->getChangedSignal().remove(this, &className::changeFunc);\ + }\ if(m##name##AssetId[index] != _in || m##name##Name[index] != _in)\ {\ if(index >= sm##name##Count || index < 0)\ @@ -430,6 +434,8 @@ public: \ if (get##name(index) != StringTable->EmptyString() && m##name##Asset[index].notNull())\ {\ m##name[index] = m##name##Asset[index]->getShapeResource();\ + \ + m##name##Asset[index]->getChangedSignal().notify(this, &className::changeFunc);\ }\ else\ {\ diff --git a/Engine/source/T3D/debris.h b/Engine/source/T3D/debris.h index a0ff99520..1d1116031 100644 --- a/Engine/source/T3D/debris.h +++ b/Engine/source/T3D/debris.h @@ -111,7 +111,10 @@ public: void onPerformSubstitutions() override; bool allowSubstitutions() const override { return true; } - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } }; //************************************************************************** diff --git a/Engine/source/T3D/fx/explosion.h b/Engine/source/T3D/fx/explosion.h index 447b7747d..0ea4c63d7 100644 --- a/Engine/source/T3D/fx/explosion.h +++ b/Engine/source/T3D/fx/explosion.h @@ -143,7 +143,10 @@ public: ExplosionData* cloneAndPerformSubstitutions(const SimObject*, S32 index=0); bool allowSubstitutions() const override { return true; } - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } }; diff --git a/Engine/source/T3D/fx/groundCover.h b/Engine/source/T3D/fx/groundCover.h index b2ef23e05..dcc159096 100644 --- a/Engine/source/T3D/fx/groundCover.h +++ b/Engine/source/T3D/fx/groundCover.h @@ -341,7 +341,7 @@ protected: RectF mBillboardRects[MAX_COVERTYPES]; /// The cover shape filenames. - DECLARE_SHAPEASSET_ARRAY(GroundCover, Shape, MAX_COVERTYPES); + DECLARE_SHAPEASSET_ARRAY(GroundCover, Shape, MAX_COVERTYPES, onShapeChanged); DECLARE_ASSET_ARRAY_NET_SETGET(GroundCover, Shape, -1); /// The cover shape instances. @@ -409,6 +409,8 @@ protected: S32 randSeed ); void _debugRender( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ); + + void onShapeChanged(){} }; #endif // _GROUNDCOVER_H_ diff --git a/Engine/source/T3D/fx/particle.h b/Engine/source/T3D/fx/particle.h index 12e6a242a..0f328801a 100644 --- a/Engine/source/T3D/fx/particle.h +++ b/Engine/source/T3D/fx/particle.h @@ -92,7 +92,10 @@ class ParticleData : public SimDataBlock static bool protectedSetSizes(void* object, const char* index, const char* data); static bool protectedSetTimes(void* object, const char* index, const char* data); - void onImageChanged() {} + void onImageChanged() + { + reloadOnLocalClient(); + } public: ParticleData(); diff --git a/Engine/source/T3D/fx/precipitation.h b/Engine/source/T3D/fx/precipitation.h index 25aad8e60..a3ca97c40 100644 --- a/Engine/source/T3D/fx/precipitation.h +++ b/Engine/source/T3D/fx/precipitation.h @@ -69,8 +69,14 @@ class PrecipitationData : public GameBaseData void packData(BitStream* stream) override; void unpackData(BitStream* stream) override; - void onDropChanged() {} - void onSplashChanged() {} + void onDropChanged() + { + reloadOnLocalClient(); + } + void onSplashChanged() + { + reloadOnLocalClient(); + } }; struct Raindrop diff --git a/Engine/source/T3D/fx/splash.h b/Engine/source/T3D/fx/splash.h index de98a5bca..0a055ee2f 100644 --- a/Engine/source/T3D/fx/splash.h +++ b/Engine/source/T3D/fx/splash.h @@ -124,7 +124,10 @@ public: DECLARE_IMAGEASSET_ARRAY(SplashData, Texture, NUM_TEX, onTextureChanged); DECLARE_IMAGEASSET_ARRAY_SETGET(SplashData, Texture) - void onTextureChanged() {} + void onTextureChanged() + { + reloadOnLocalClient(); + } ExplosionData* explosion; S32 explosionId; diff --git a/Engine/source/T3D/lightFlareData.h b/Engine/source/T3D/lightFlareData.h index 5239bf3c1..baa74c39b 100644 --- a/Engine/source/T3D/lightFlareData.h +++ b/Engine/source/T3D/lightFlareData.h @@ -106,7 +106,10 @@ protected: void _makePrimBuffer( GFXPrimitiveBufferHandle *pb, U32 count ); void _renderCorona( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ); - void onImageChanged() {} + void onImageChanged() + { + reloadOnLocalClient(); + } protected: diff --git a/Engine/source/T3D/physics/physicsDebris.h b/Engine/source/T3D/physics/physicsDebris.h index 2626300e9..9b9ae6861 100644 --- a/Engine/source/T3D/physics/physicsDebris.h +++ b/Engine/source/T3D/physics/physicsDebris.h @@ -97,7 +97,10 @@ public: void packData( BitStream *stream ) override; void unpackData( BitStream *stream ) override; - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } DECLARE_CONOBJECT( PhysicsDebrisData ); diff --git a/Engine/source/T3D/physics/physicsShape.h b/Engine/source/T3D/physics/physicsShape.h index 144580c31..466e39ebf 100644 --- a/Engine/source/T3D/physics/physicsShape.h +++ b/Engine/source/T3D/physics/physicsShape.h @@ -135,7 +135,10 @@ public: SimObjectRef< ExplosionData > explosion; SimObjectRef< PhysicsShapeData > destroyedShape; - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } }; typedef PhysicsShapeData::SimType PhysicsSimType; diff --git a/Engine/source/T3D/player.h b/Engine/source/T3D/player.h index b80b3f0e5..ab242d862 100644 --- a/Engine/source/T3D/player.h +++ b/Engine/source/T3D/player.h @@ -76,7 +76,7 @@ struct PlayerData: public ShapeBaseData { /// that we don't create a TSThread on the player if we don't /// need to. - DECLARE_SHAPEASSET_ARRAY(PlayerData, ShapeFP, ShapeBase::MaxMountedImages); ///< Used to render with mounted images in first person [optional] + DECLARE_SHAPEASSET_ARRAY(PlayerData, ShapeFP, ShapeBase::MaxMountedImages, onShapeChanged); ///< Used to render with mounted images in first person [optional] DECLARE_ASSET_ARRAY_SETGET(PlayerData, ShapeFP); StringTableEntry imageAnimPrefixFP; ///< Passed along to mounted images to modify @@ -366,6 +366,11 @@ struct PlayerData: public ShapeBaseData { void packData(BitStream* stream) override; void unpackData(BitStream* stream) override; + void onShapeChanged() + { + reloadOnLocalClient(); + } + /// @name Callbacks /// @{ DECLARE_CALLBACK( void, onPoseChange, ( Player* obj, const char* oldPose, const char* newPose ) ); diff --git a/Engine/source/T3D/projectile.h b/Engine/source/T3D/projectile.h index 04e91aa60..2ca827ea7 100644 --- a/Engine/source/T3D/projectile.h +++ b/Engine/source/T3D/projectile.h @@ -154,7 +154,10 @@ public: ProjectileData(const ProjectileData&, bool = false); bool allowSubstitutions() const override { return true; } - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } }; diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index 968e8fb9b..e164c8394 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -345,7 +345,7 @@ bool ShapeBaseData::preload(bool server, String &errorStr) S32 i; U32 assetStatus = ShapeAsset::getAssetErrCode(mShapeAsset); - if (assetStatus == AssetBase::Ok|| assetStatus == AssetBase::UsingFallback) + if (assetStatus == AssetBase::Ok || assetStatus == AssetBase::UsingFallback) { if (!server && !mShape->preloadMaterialList(mShape.getPath()) && NetConnection::filesWereDownloaded()) shapeError = true; @@ -904,7 +904,17 @@ void ShapeBaseData::unpackData(BitStream* stream) silent_bbox_check = stream->readFlag(); } +// +// +void ShapeBaseData::onShapeChanged() +{ + reloadOnLocalClient(); +} +void ShapeBaseData::onDebrisChanged() +{ + reloadOnLocalClient(); +} //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- diff --git a/Engine/source/T3D/shapeBase.h b/Engine/source/T3D/shapeBase.h index 706f54b72..131992fa9 100644 --- a/Engine/source/T3D/shapeBase.h +++ b/Engine/source/T3D/shapeBase.h @@ -378,7 +378,7 @@ struct ShapeBaseImageData: public GameBaseData { F32 scriptAnimTransitionTime; ///< The amount of time to transition between the previous sequence and new sequence ///< when the script prefix has changed. - DECLARE_SHAPEASSET_ARRAY(ShapeBaseImageData, Shape, MaxShapes); ///< Name of shape to render. + DECLARE_SHAPEASSET_ARRAY(ShapeBaseImageData, Shape, MaxShapes, onShapeChanged); ///< Name of shape to render. DECLARE_ASSET_ARRAY_SETGET(ShapeBaseImageData, Shape); //DECLARE_SHAPEASSET(ShapeBaseImageData, ShapeFP); ///< Name of shape to render in first person (optional). @@ -505,6 +505,11 @@ struct ShapeBaseImageData: public GameBaseData { void handleStateSoundTrack(const U32& stateId); + void onShapeChanged() + { + reloadOnLocalClient(); + } + /// @} /// @name Callbacks @@ -681,8 +686,8 @@ public: Vector txr_tag_remappings; bool silent_bbox_check; - void onShapeChanged() {} - void onDebrisChanged() {} + void onShapeChanged(); + void onDebrisChanged(); public: ShapeBaseData(const ShapeBaseData&, bool = false); }; diff --git a/Engine/source/T3D/vehicles/wheeledVehicle.h b/Engine/source/T3D/vehicles/wheeledVehicle.h index 45161db12..f208fbf5b 100644 --- a/Engine/source/T3D/vehicles/wheeledVehicle.h +++ b/Engine/source/T3D/vehicles/wheeledVehicle.h @@ -74,7 +74,10 @@ struct WheeledVehicleTire: public SimDataBlock void packData(BitStream* stream) override; void unpackData(BitStream* stream) override; - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } }; diff --git a/Engine/source/afx/afxMagicMissile.h b/Engine/source/afx/afxMagicMissile.h index e3f6ee755..8aa8f8084 100644 --- a/Engine/source/afx/afxMagicMissile.h +++ b/Engine/source/afx/afxMagicMissile.h @@ -66,7 +66,10 @@ protected: public: enum { MaxLifetimeTicks = 4095 }; - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } public: // variables set in datablock definition: diff --git a/Engine/source/afx/ce/afxBillboard.h b/Engine/source/afx/ce/afxBillboard.h index 8918e2f26..81542f716 100644 --- a/Engine/source/afx/ce/afxBillboard.h +++ b/Engine/source/afx/ce/afxBillboard.h @@ -71,7 +71,10 @@ public: static void initPersistFields(); - void onChangeTexture() {} + void onChangeTexture() + { + reloadOnLocalClient(); + } DECLARE_CONOBJECT(afxBillboardData); }; diff --git a/Engine/source/afx/ce/afxModel.h b/Engine/source/afx/ce/afxModel.h index 521409735..de2656b8f 100644 --- a/Engine/source/afx/ce/afxModel.h +++ b/Engine/source/afx/ce/afxModel.h @@ -94,7 +94,10 @@ public: static void initPersistFields(); - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } void onSequenceChanged() {} DECLARE_CONOBJECT(afxModelData); diff --git a/Engine/source/afx/ce/afxZodiac.h b/Engine/source/afx/ce/afxZodiac.h index a7d14c2f1..16f4a8d79 100644 --- a/Engine/source/afx/ce/afxZodiac.h +++ b/Engine/source/afx/ce/afxZodiac.h @@ -56,7 +56,10 @@ public: static void convertGradientRangeFromDegrees(Point2F& gradrange, const Point2F& gradrange_deg); - void onImageChanged() {} + void onImageChanged() + { + reloadOnLocalClient(); + } public: DECLARE_IMAGEASSET(afxZodiacData, Texture, onImageChanged, AFX_GFXZodiacTextureProfile); diff --git a/Engine/source/afx/ce/afxZodiacPlane.h b/Engine/source/afx/ce/afxZodiacPlane.h index 13c9879b5..a32a14d26 100644 --- a/Engine/source/afx/ce/afxZodiacPlane.h +++ b/Engine/source/afx/ce/afxZodiacPlane.h @@ -56,7 +56,10 @@ public: FACES_BITS = 3 }; - void onImageChanged() {} + void onImageChanged() + { + reloadOnLocalClient(); + } public: DECLARE_IMAGEASSET(afxZodiacPlaneData, Texture, onImageChanged, AFX_GFXZodiacTextureProfile); diff --git a/Engine/source/console/simDatablock.cpp b/Engine/source/console/simDatablock.cpp index d3969a069..fc5070224 100644 --- a/Engine/source/console/simDatablock.cpp +++ b/Engine/source/console/simDatablock.cpp @@ -425,39 +425,42 @@ void SimDataBlock::write(Stream &stream, U32 tabStop, U32 flags) // MARK: ---- API ---- //----------------------------------------------------------------------------- - -DefineEngineMethod( SimDataBlock, reloadOnLocalClient, void, (),, - "Reload the datablock. This can only be used with a local client configuration." ) +void SimDataBlock::reloadOnLocalClient() { // Make sure we're running a local client. GameConnection* localClient = GameConnection::getLocalClientConnection(); - if( !localClient ) + if (!localClient) return; // Do an in-place pack/unpack/preload. - if( !object->preload( true, NetConnection::getErrorBuffer() ) ) + if (!preload(true, NetConnection::getErrorBuffer())) { - Con::errorf( NetConnection::getErrorBuffer() ); + Con::errorf(NetConnection::getErrorBuffer()); return; } - U8 buffer[ 16384 ]; - BitStream stream( buffer, 16384 ); + U8 buffer[16384]; + BitStream stream(buffer, 16384); - object->packData( &stream ); + packData(&stream); stream.setPosition(0); - object->unpackData( &stream ); + unpackData(&stream); - if( !object->preload( false, NetConnection::getErrorBuffer() ) ) + if (!preload(false, NetConnection::getErrorBuffer())) { - Con::errorf( NetConnection::getErrorBuffer() ); + Con::errorf(NetConnection::getErrorBuffer()); return; } // Trigger a post-apply so that change notifications respond. - object->inspectPostApply(); + inspectPostApply(); +} +DefineEngineMethod( SimDataBlock, reloadOnLocalClient, void, (),, + "Reload the datablock. This can only be used with a local client configuration." ) +{ + object->reloadOnLocalClient(); } //----------------------------------------------------------------------------- diff --git a/Engine/source/console/simDatablock.h b/Engine/source/console/simDatablock.h index 1b61822d7..2f5c8efcc 100644 --- a/Engine/source/console/simDatablock.h +++ b/Engine/source/console/simDatablock.h @@ -176,6 +176,8 @@ public: /// Used by the console system to automatically tell datablock classes apart /// from non-datablock classes. static const bool __smIsDatablock = true; + + void reloadOnLocalClient(); protected: struct SubstitutionStatement { diff --git a/Engine/source/forest/forestItem.h b/Engine/source/forest/forestItem.h index 42bf56a5f..64e6eb611 100644 --- a/Engine/source/forest/forestItem.h +++ b/Engine/source/forest/forestItem.h @@ -143,7 +143,10 @@ public: return theSignal; } - void onShapeChanged() {} + void onShapeChanged() + { + reloadOnLocalClient(); + } }; typedef Vector ForestItemDataVector; From 24db0305f64c491da382d375e558af9c49c97160 Mon Sep 17 00:00:00 2001 From: JeffR Date: Thu, 24 Apr 2025 13:24:26 -0500 Subject: [PATCH 4/4] Modified callback to ensure that when a shapeAsset changes, groundCovers properly re-initialize to reflect the change --- Engine/source/T3D/fx/groundCover.cpp | 5 ++++- Engine/source/T3D/fx/groundCover.h | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Engine/source/T3D/fx/groundCover.cpp b/Engine/source/T3D/fx/groundCover.cpp index 377f8bb63..072ef6463 100644 --- a/Engine/source/T3D/fx/groundCover.cpp +++ b/Engine/source/T3D/fx/groundCover.cpp @@ -852,8 +852,11 @@ void GroundCover::unpackUpdate( NetConnection *connection, BitStream *stream ) // It's sloppy, but it works for now. _freeCells(); - if ( isProperlyAdded() ) + if (isProperlyAdded()) + { _initMaterial(); + _initShapes(); + } } } diff --git a/Engine/source/T3D/fx/groundCover.h b/Engine/source/T3D/fx/groundCover.h index dcc159096..af5d02858 100644 --- a/Engine/source/T3D/fx/groundCover.h +++ b/Engine/source/T3D/fx/groundCover.h @@ -410,7 +410,11 @@ protected: void _debugRender( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ); - void onShapeChanged(){} + void onShapeChanged() + { + _initShapes(); + setMaskBits(U32(-1)); + } }; #endif // _GROUNDCOVER_H_