@@ -489,6 +489,31 @@ class TerrainScorchFXNugget : public FXNugget
489489 {
490490 if (primary)
491491 {
492+ // If scormarks are high above the ground
493+ if (TheGlobalData->m_hideScorchmarksAboveGround && TheTerrainLogic) {
494+ /* PathfindLayerEnum layer = TheTerrainLogic->getLayerForDestination(primary);
495+ Real groundHeight = 0;
496+ if (layer != LAYER_GROUND) {
497+ TheTerrainLogic->getLayerHeight(primary->x, primary->y, layer);
498+ }
499+ else {
500+ Real waterZ;
501+ Real terrainZ;
502+ if (TheTerrainLogic->isUnderwater(primary->x, primary->y, &waterZ, &terrainZ))
503+ groundHeight = waterZ;
504+ else
505+ groundHeight = terrainZ;
506+ }*/
507+
508+ PathfindLayerEnum layer = TheTerrainLogic->getLayerForDestination (primary);
509+ if (layer != LAYER_GROUND)
510+ return ;
511+
512+ Real groundHeight = TheTerrainLogic->getLayerHeight (primary->x , primary->y , layer);
513+ if (primary->z - groundHeight > m_radius)
514+ return ;
515+ }
516+
492517 Int scorch = m_scorch;
493518 if (scorch < 0 )
494519 {
@@ -541,6 +566,21 @@ class TerrainScorchFXNugget : public FXNugget
541566};
542567EMPTY_DTOR (TerrainScorchFXNugget)
543568
569+ // -------------------------------------------------------------------------------------------------
570+ static const char* const AllowedSurfaceNames[] =
571+ {
572+ " ALL" ,
573+ " LAND" ,
574+ " WATER" ,
575+ NULL
576+ };
577+
578+ enum AllowedSurfaceType CPP_11 (: Int) {
579+ SURFACE_ALL = 0 ,
580+ SURFACE_LAND,
581+ SURFACE_WATER
582+ };
583+
544584// -------------------------------------------------------------------------------------------------
545585class ParticleSystemFXNugget : public FXNugget
546586{
@@ -561,6 +601,11 @@ class ParticleSystemFXNugget : public FXNugget
561601 m_createAtGroundHeight = FALSE ;
562602 m_useCallersRadius = FALSE ;
563603 m_rotateX = m_rotateY = m_rotateZ = 0 ;
604+
605+ m_maxAllowedHeight = INFINITY;
606+ m_minAllowedHeight = -INFINITY;
607+ // m_createAtWaterHeight = FALSE;
608+ m_allowedSurfaceType = SURFACE_ALL;
564609 }
565610
566611 virtual void doFXPos (const Coord3D *primary, const Matrix3D* primaryMtx, const Real /* primarySpeed*/ , const Coord3D * /* secondary*/ , const Real overrideRadius ) const
@@ -623,6 +668,11 @@ class ParticleSystemFXNugget : public FXNugget
623668 { " AttachToObject" , INI::parseBool, NULL , offsetof ( ParticleSystemFXNugget, m_attachToObject ) },
624669 { " CreateAtGroundHeight" , INI::parseBool, NULL , offsetof ( ParticleSystemFXNugget, m_createAtGroundHeight ) },
625670 { " UseCallersRadius" , INI::parseBool, NULL , offsetof ( ParticleSystemFXNugget, m_useCallersRadius ) },
671+ // New height controls
672+ // { "CreateAtWaterHeight", INI::parseBool, NULL, offsetof(ParticleSystemFXNugget, m_createAtWaterHeight) },
673+ { " MinAllowedHeight" , INI::parseReal, NULL , offsetof (ParticleSystemFXNugget, m_minAllowedHeight) },
674+ { " MaxAllowedHeight" , INI::parseReal, NULL , offsetof (ParticleSystemFXNugget, m_maxAllowedHeight) },
675+ { " AllowedSurface" , INI::parseIndexList, AllowedSurfaceNames, offsetof (ParticleSystemFXNugget, m_allowedSurfaceType) },
626676 { 0 , 0 , 0 , 0 }
627677 };
628678
@@ -650,6 +700,38 @@ class ParticleSystemFXNugget : public FXNugget
650700 DEBUG_ASSERTCRASH (tmp, (" ParticleSystem %s not found" ,m_name.str ()));
651701 if (tmp)
652702 {
703+ Real groundHeight = 0 ; // we might need it later
704+
705+ // Evaluate Height and allowed surfaces first.
706+ if ((TheTerrainLogic != NULL ) && (m_minAllowedHeight > -INFINITY || m_maxAllowedHeight < INFINITY || m_allowedSurfaceType != SURFACE_ALL || m_createAtGroundHeight)) {
707+ PathfindLayerEnum layer = TheTerrainLogic->getLayerForDestination (primary);
708+
709+ if (layer != LAYER_GROUND) { // Bridge
710+ if (m_allowedSurfaceType == SURFACE_WATER) return ; // No water effects over bridges.
711+ groundHeight = TheTerrainLogic->getLayerHeight (primary->x , primary->y , layer);
712+ }
713+ else { // Ground (Water or Land)
714+ Real waterZ = 0 ;
715+ Real terrainZ = 0 ;
716+ if (m_allowedSurfaceType != SURFACE_ALL || TheGlobalData->m_heightAboveTerrainIncludesWater ) { // Do water check
717+ Bool isWater = TheTerrainLogic->isUnderwater (primary->x , primary->y , &waterZ, &terrainZ);
718+
719+ if (isWater) {
720+ if (m_allowedSurfaceType == SURFACE_LAND) return ;
721+ groundHeight = waterZ;
722+ }
723+ else {
724+ if (m_allowedSurfaceType == SURFACE_WATER) return ;
725+ groundHeight = terrainZ;
726+ }
727+ }
728+ }
729+
730+ Real zOffset = primary->z - groundHeight;
731+ if (zOffset < m_minAllowedHeight || zOffset > m_maxAllowedHeight) return ;
732+ }
733+
734+
653735 for (Int i = 0 ; i < m_count; i++ )
654736 {
655737 ParticleSystem *sys = TheParticleSystemManager->createParticleSystem (tmp);
@@ -661,25 +743,35 @@ class ParticleSystemFXNugget : public FXNugget
661743
662744 newPos.x = primary->x + offset.x + radius * cos (angle);
663745 newPos.y = primary->y + offset.y + radius * sin (angle);
664- if ( m_createAtGroundHeight && TheTerrainLogic )
665- {
666- // old way:
667- // newPos.z = TheTerrainLogic->getGrsoundHeight( newPos.x, newPos.y ) + 1;// The plus one prevents scissoring with terrain
668- // new way: now we allow bridges in the GroundHeight.
669- // newer way: include water
670-
671- PathfindLayerEnum layer = TheTerrainLogic->getLayerForDestination (&newPos);
672-
673- if (Real waterZ = 0 ; TheGlobalData->m_heightAboveTerrainIncludesWater && layer == LAYER_GROUND &&
674- TheTerrainLogic->isUnderwater (newPos.x , newPos.y , &waterZ)) {
675- newPos.z = waterZ;
676- }
677- else {
678- newPos.z = TheTerrainLogic->getLayerHeight (newPos.x , newPos.y , layer);
679- }
746+
747+
748+ if (m_createAtGroundHeight) {
749+ newPos.z = groundHeight + offset.z + m_height.getValue ();
680750 }
681- else
751+ else {
682752 newPos.z = primary->z + offset.z + m_height.getValue ();
753+ }
754+
755+ // if( m_createAtGroundHeight && TheTerrainLogic )
756+ // {
757+ // //old way:
758+ // //newPos.z = TheTerrainLogic->getGrsoundHeight( newPos.x, newPos.y ) + 1;// The plus one prevents scissoring with terrain
759+ // //new way: now we allow bridges in the GroundHeight.
760+ // //newer way: include water
761+ // //newest way: include height limits and surface check
762+
763+ // PathfindLayerEnum layer = TheTerrainLogic->getLayerForDestination(&newPos);
764+ //
765+ // if (Real waterZ = 0; TheGlobalData->m_heightAboveTerrainIncludesWater && layer == LAYER_GROUND &&
766+ // TheTerrainLogic->isUnderwater(newPos.x, newPos.y, &waterZ)) {
767+ // newPos.z = waterZ + offset.z + m_height.getValue();
768+ // }
769+ // else {
770+ // newPos.z = TheTerrainLogic->getLayerHeight(newPos.x, newPos.y, layer) + offset.z + m_height.getValue();
771+ // }
772+ // }
773+ // else
774+ // newPos.z = primary->z + offset.z + m_height.getValue();
683775
684776
685777 if (m_orientToObject && mtx)
@@ -738,6 +830,11 @@ class ParticleSystemFXNugget : public FXNugget
738830 Bool m_createAtGroundHeight;
739831 Bool m_useCallersRadius;
740832 Bool m_ricochet;
833+
834+ Real m_maxAllowedHeight;
835+ Real m_minAllowedHeight;
836+ // Bool m_createAtWaterHeight;
837+ AllowedSurfaceType m_allowedSurfaceType;
741838};
742839EMPTY_DTOR (ParticleSystemFXNugget)
743840
0 commit comments