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
2 changes: 2 additions & 0 deletions Core/GameEngine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ set(GAMEENGINE_SRC
# Include/GameLogic/Module/FireSpreadUpdate.h
# Include/GameLogic/Module/FirestormDynamicGeometryInfoUpdate.h
# Include/GameLogic/Module/FireWeaponCollide.h
# Include/GameLogic/Module/AdvancedCollide.h
# Include/GameLogic/Module/FireWeaponPower.h
# Include/GameLogic/Module/FireWeaponUpdate.h
# Include/GameLogic/Module/FireWeaponWhenDamagedBehavior.h
Expand Down Expand Up @@ -907,6 +908,7 @@ set(GAMEENGINE_SRC
# Source/GameLogic/Object/Collide/CrateCollide/UnitCrateCollide.cpp
# Source/GameLogic/Object/Collide/CrateCollide/VeterancyCrateCollide.cpp
# Source/GameLogic/Object/Collide/FireWeaponCollide.cpp
# Source/GameLogic/Object/Collide/AdvancedCollide.cpp
# Source/GameLogic/Object/Collide/SquishCollide.cpp
# Source/GameLogic/Object/Contain/CaveContain.cpp
# Source/GameLogic/Object/Contain/GarrisonContain.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ static PoolSizeRec PoolSizes[] =
{ "FireSpreadUpdate", 2048, 128 },
{ "FirestormDynamicGeometryInfoUpdate", 16, 16 },
{ "FireWeaponCollide", 2048, 32 },
{ "AdvancedCollide", 512, 32 },
{ "FireWeaponUpdate", 32, 32 },
{ "FireWeaponAdvancedUpdate", 32, 32 },
{ "FlammableUpdate", 512, 256 },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@
#include "GameLogic/Module/ImmortalBody.h"
#include "GameLogic/Module/StructureBody.h"
#include "GameLogic/Module/HiveStructureBody.h"
#include "GameLogic/Module/ShieldBody.h"

// contain includes
// (none)
Expand Down
2 changes: 2 additions & 0 deletions GeneralsMD/Code/GameEngine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ set(GAMEENGINE_SRC
Include/GameLogic/Module/FireSpreadUpdate.h
Include/GameLogic/Module/FirestormDynamicGeometryInfoUpdate.h
Include/GameLogic/Module/FireWeaponCollide.h
Include/GameLogic/Module/AdvancedCollide.h
Include/GameLogic/Module/FireWeaponPower.h
Include/GameLogic/Module/FireWeaponUpdate.h
Include/GameLogic/Module/FireWeaponAdvancedUpdate.h
Expand Down Expand Up @@ -929,6 +930,7 @@ set(GAMEENGINE_SRC
Source/GameLogic/Object/Collide/CrateCollide/UnitCrateCollide.cpp
Source/GameLogic/Object/Collide/CrateCollide/VeterancyCrateCollide.cpp
Source/GameLogic/Object/Collide/FireWeaponCollide.cpp
Source/GameLogic/Object/Collide/AdvancedCollide.cpp
Source/GameLogic/Object/Collide/SquishCollide.cpp
Source/GameLogic/Object/Contain/CaveContain.cpp
Source/GameLogic/Object/Contain/GarrisonContain.cpp
Expand Down
110 changes: 110 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/GameLogic/Module/AdvancedCollide.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
** 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: AdvancedCollide.h ///////////////////////////////////////////////////////////////////////////
// Author: Andi W, Oct 25
// Desc: Do something if we collide with objects or the ground
///////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#ifndef __AdvancedCollide_H_
#define __AdvancedCollide_H_

// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "GameLogic/Module/CollideModule.h"
#include "GameLogic/Weapon.h"

// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Object;
class FXList;
class ObjectCreationList;

//-------------------------------------------------------------------------------------------------
class AdvancedCollideModuleData : public CollideModuleData
{
public:
const WeaponTemplate* m_collideWeaponTemplate; ///< Weapon To Fire
const FXList* m_fxlist; ///< FX to play
const ObjectCreationList* m_ocl; ///< object creaton list to make

KindOfMaskType m_kindof; ///< the kind(s) of units that can be collided with
KindOfMaskType m_kindofnot; ///< the kind(s) of units that CANNOT be collided with

ObjectStatusMaskType m_requiredStatus;
ObjectStatusMaskType m_forbiddenStatus;
ObjectStatusMaskType m_targetRequiredStatus;
ObjectStatusMaskType m_targetForbiddenStatus;

Bool m_fireOnce; ///< trigger effects only once
Bool m_collideWithGround; ///< trigger on collide with Ground
Bool m_collideWithObjects; ///< trigger on collide with Objects

Real m_triggerChance; ///< chance to trigger effects on a valid collission
Bool m_rollOnce; ///< Only Roll once to trigger effects; Or roll every frame.


AdvancedCollideModuleData()
{
m_collideWeaponTemplate = NULL;
m_fxlist = NULL;
m_ocl = NULL;
m_fireOnce = FALSE;
m_collideWithGround = FALSE;
m_collideWithObjects = TRUE;
m_triggerChance = 1.0;
m_rollOnce = FALSE;
}

static void buildFieldParse(MultiIniFieldParse& p);
};

//-------------------------------------------------------------------------------------------------
class AdvancedCollide : public CollideModule
{

MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( AdvancedCollide, AdvancedCollideModuleData );
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AdvancedCollide, "AdvancedCollide" )

public:

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

protected:

virtual void onCollide( Object *other, const Coord3D *loc, const Coord3D *normal );

virtual Bool shouldTrigger(Object* other);

private:
Weapon* m_collideWeapon;
Bool m_everFired;
Real m_roll;

};


#endif

Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@ class StickyBombCrateCollideModuleData : public CrateCollideModuleData
Bool m_allowMultiCollide; ///< if we are a crate, allow spawning multiple sticky bombs, or just single use
Bool m_showInfiltrationEvent; ///< show an infiltration map event for the target player
AsciiString m_stickyBombObjectName; ///< the object to create
Real m_triggerChance; ///< chance to create the bomb when triggering the module

StickyBombCrateCollideModuleData()
{
m_needsTarget = FALSE;
m_allowMultiCollide = FALSE;
m_showInfiltrationEvent = FALSE;
m_stickyBombObjectName = AsciiString::TheEmptyString;
m_triggerChance = 1.0;
}

static void buildFieldParse(MultiIniFieldParse& p)
Expand All @@ -70,6 +72,7 @@ class StickyBombCrateCollideModuleData : public CrateCollideModuleData
{ "AllowMultiCollide", INI::parseBool, NULL, offsetof(StickyBombCrateCollideModuleData, m_allowMultiCollide) },
{ "ShowInfiltrationEvent", INI::parseBool, NULL, offsetof(StickyBombCrateCollideModuleData, m_showInfiltrationEvent) },
{ "StickyBombObject", INI::parseAsciiString, NULL, offsetof(StickyBombCrateCollideModuleData, m_stickyBombObjectName) },
{ "ChanceToTriggerPercent", INI::parsePercentToReal, NULL, offsetof(StickyBombCrateCollideModuleData, m_triggerChance) },
{ 0, 0, 0, 0 }
};
p.add( dataFieldParse );
Expand All @@ -92,7 +95,7 @@ class StickyBombCrateCollide : public CrateCollide
protected:

/// This allows specific vetoes to certain types of crates and their data
virtual Bool isValidToExecute( const Object *other ) const;
// virtual Bool isValidToExecute( const Object *other ) const;

/// This is the game logic execution function that all real CrateCollides will implement
virtual Bool executeCrateBehavior( Object *other );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ class StickyBombUpdateModuleData : public UpdateModuleData

AsciiString m_animBaseTemplate;
AsciiString m_animTimedTemplate;
Bool m_showTimer;
Bool m_showTimer; ///< if this is disabled, only use animBase for timed bombs

Bool m_hideAnimBase; ///< will be set automatically if String is Null
Bool m_hideAnimTimed; ///< will be set automatically if String is Null

StickyBombUpdateModuleData()
{
Expand All @@ -62,6 +65,9 @@ class StickyBombUpdateModuleData : public UpdateModuleData
m_showTimer = TRUE;
}

static void parseAnimBaseName(INI* ini, void* instance, void* store, const void* userData);
static void parseAnimTimedName(INI* ini, void* instance, void* store, const void* userData);

static void buildFieldParse(MultiIniFieldParse& p)
{
UpdateModuleData::buildFieldParse(p);
Expand All @@ -71,8 +77,8 @@ class StickyBombUpdateModuleData : public UpdateModuleData
{ "OffsetZ", INI::parseReal, NULL, offsetof( StickyBombUpdateModuleData, m_offsetZ ) },
{ "GeometryBasedDamageWeapon",INI::parseWeaponTemplate, NULL, offsetof( StickyBombUpdateModuleData, m_geometryBasedDamageWeaponTemplate ) },
{ "GeometryBasedDamageFX", INI::parseFXList, NULL, offsetof( StickyBombUpdateModuleData, m_geometryBasedDamageFX ) },
{ "Animation2DBase", INI::parseAsciiString, NULL, offsetof( StickyBombUpdateModuleData, m_animBaseTemplate) },
{ "Animation2DTimed", INI::parseAsciiString, NULL, offsetof( StickyBombUpdateModuleData, m_animTimedTemplate) },
{ "Animation2DBase", parseAnimBaseName, NULL, 0 },
{ "Animation2DTimed", parseAnimTimedName, NULL, 0 },
{ "ShowTimer", INI::parseBool, NULL, offsetof( StickyBombUpdateModuleData, m_showTimer) },
{ 0, 0, 0, 0 }
};
Expand Down Expand Up @@ -109,6 +115,9 @@ class StickyBombUpdate : public UpdateModule
Anim2DTemplate* getAnimBaseTemplate();
Anim2DTemplate* getAnimTimedTemplate();

inline Bool showAnimBaseTemplate() { return !getStickyBombUpdateModuleData()->m_hideAnimBase; }
inline Bool showAnimTimedTemplate() { return !getStickyBombUpdateModuleData()->m_hideAnimTimed; }

private:

ObjectID m_targetID;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@

// collide includes
#include "GameLogic/Module/FireWeaponCollide.h"
#include "GameLogic/Module/AdvancedCollide.h"
#include "GameLogic/Module/SquishCollide.h"

#include "GameLogic/Module/ConvertToCarBombCrateCollide.h"
Expand Down Expand Up @@ -543,6 +544,7 @@ void ModuleFactory::init( void )

// collide modules
addModule( FireWeaponCollide );
addModule( AdvancedCollide );
addModule( SquishCollide );

addModule( HealCrateCollide );
Expand Down
40 changes: 28 additions & 12 deletions GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3744,8 +3744,8 @@ void Drawable::drawBombed(const IRegion2D* healthBarRegion)
{
if( update->isTimedBomb() )
{
//Timed bomb
if( !getIconInfo()->m_icon[ ICON_BOMB_TIMED ] )
//Timed bomb - Base layer
if (!getIconInfo()->m_icon[ICON_BOMB_REMOTE] && update->showAnimBaseTemplate())
{
Anim2DTemplate* templ = update->getAnimBaseTemplate();

Expand All @@ -3754,7 +3754,11 @@ void Drawable::drawBombed(const IRegion2D* healthBarRegion)

getIconInfo()->m_icon[ICON_BOMB_REMOTE] = newInstance(Anim2D)(templ, TheAnim2DCollection);

templ = update->getAnimTimedTemplate();
}
//Timed bomb - Timer
if( !getIconInfo()->m_icon[ ICON_BOMB_TIMED ] && update->showAnimTimedTemplate())
{
Anim2DTemplate* templ = update->getAnimTimedTemplate();

if (templ == NULL) // Default icon
templ = s_animationTemplates[ICON_BOMB_TIMED];
Expand Down Expand Up @@ -3785,7 +3789,9 @@ void Drawable::drawBombed(const IRegion2D* healthBarRegion)
getIconInfo()->m_icon[ ICON_BOMB_TIMED ]->setMinFrame(numFrames - seconds - 1);
getIconInfo()->m_icon[ ICON_BOMB_TIMED ]->reset();
}
if( getIconInfo()->m_icon[ ICON_BOMB_TIMED ] )
Bool showTimedAnim = (getIconInfo()->m_icon[ICON_BOMB_TIMED]) != NULL;
Bool showBaseAnim = (getIconInfo()->m_icon[ICON_BOMB_REMOTE]) != NULL;
if( showTimedAnim || showBaseAnim)
{
//
// we are going to draw the healing icon relative to the size of the health bar region
Expand All @@ -3796,8 +3802,15 @@ void Drawable::drawBombed(const IRegion2D* healthBarRegion)
Int barWidth = healthBarRegion->hi.x - healthBarRegion->lo.x;
Int barHeight = healthBarRegion->hi.y - healthBarRegion->lo.y;

Int frameWidth = getIconInfo()->m_icon[ ICON_BOMB_TIMED ]->getCurrentFrameWidth();
Int frameHeight = getIconInfo()->m_icon[ ICON_BOMB_TIMED ]->getCurrentFrameHeight();
Int frameWidth, frameHeight;
if (showTimedAnim) {
frameWidth = getIconInfo()->m_icon[ICON_BOMB_TIMED]->getCurrentFrameWidth();
frameHeight = getIconInfo()->m_icon[ICON_BOMB_TIMED]->getCurrentFrameHeight();
}
else {
frameWidth = getIconInfo()->m_icon[ICON_BOMB_REMOTE]->getCurrentFrameWidth();
frameHeight = getIconInfo()->m_icon[ICON_BOMB_REMOTE]->getCurrentFrameHeight();
}

// adjust the width to be a % of the health bar region size
Int size = REAL_TO_INT( barWidth * 0.65f );
Expand All @@ -3809,18 +3822,21 @@ void Drawable::drawBombed(const IRegion2D* healthBarRegion)
screen.x = REAL_TO_INT( healthBarRegion->lo.x + (barWidth * 0.5f) - (frameWidth * 0.5f) );
screen.y = REAL_TO_INT( healthBarRegion->lo.y + barHeight * 0.5f ) + BOMB_ICON_EXTRA_OFFSET;

getIconInfo()->m_icon[ ICON_BOMB_REMOTE ]->draw( screen.x, screen.y, frameWidth, frameHeight );
getIconInfo()->m_keepTillFrame[ ICON_BOMB_REMOTE ] = now + 1;
getIconInfo()->m_icon[ ICON_BOMB_TIMED ]->draw( screen.x, screen.y, frameWidth, frameHeight );
getIconInfo()->m_keepTillFrame[ ICON_BOMB_TIMED ] = now + 1;
if (showBaseAnim) {
getIconInfo()->m_icon[ICON_BOMB_REMOTE]->draw(screen.x, screen.y, frameWidth, frameHeight);
getIconInfo()->m_keepTillFrame[ICON_BOMB_REMOTE] = now + 1;
}
if (showTimedAnim) {
getIconInfo()->m_icon[ICON_BOMB_TIMED]->draw(screen.x, screen.y, frameWidth, frameHeight);
getIconInfo()->m_keepTillFrame[ICON_BOMB_TIMED] = now + 1;
}
}
}
}
else
{
//Remote charge
//Timed bomb
if( !getIconInfo()->m_icon[ ICON_BOMB_REMOTE ] )
if( !getIconInfo()->m_icon[ ICON_BOMB_REMOTE ] && update->showAnimBaseTemplate())
{
Anim2DTemplate* templ = update->getAnimBaseTemplate();

Expand Down
Loading