Skip to content
Open
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 @@ -20,6 +20,7 @@
// not const -- we might override from INI
static PoolSizeRec PoolSizes[] =
{
{ "ArmorTemplatePool", 64, 8 },
{ "PartitionContactListNode", 2048, 512 },
{ "BattleshipUpdate", 32, 32 },
{ "FlyToDestAndDestroyUpdate", 32, 32 },
Expand Down
22 changes: 18 additions & 4 deletions GeneralsMD/Code/GameEngine/Include/GameLogic/Armor.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/NameKeyGenerator.h"
#include "Common/STLTypedefs.h"
#include "Common/Overridable.h"
#include "GameLogic/Damage.h"

// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
Expand All @@ -43,8 +44,19 @@ class ArmorStore;
to simulate different materials, and to help make game balance easier to adjust.
*/
//-------------------------------------------------------------------------------------------------
class ArmorTemplate
class ArmorTemplate : public Overridable
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(ArmorTemplate, "ArmorTemplatePool")

#if defined(_MSC_VER) && _MSC_VER < 1300
ArmorTemplate(const ArmorTemplate&)
{
DEBUG_CRASH(("This should never be called"));
}
#else
ArmorTemplate(const ArmorTemplate& that) = delete;
#endif

public:

ArmorTemplate();
Expand Down Expand Up @@ -99,10 +111,10 @@ class ArmorStore : public SubsystemInterface
public:

ArmorStore();
~ArmorStore();
virtual ~ArmorStore();

void init() { }
void reset() { }
void reset();
void update() { }

const ArmorTemplate* findArmorTemplate(NameKeyType namekey) const;
Expand All @@ -121,7 +133,9 @@ class ArmorStore : public SubsystemInterface

private:

typedef std::hash_map< NameKeyType, ArmorTemplate, rts::hash<NameKeyType>, rts::equal_to<NameKeyType> > ArmorTemplateMap;
ArmorTemplate* newOverride(ArmorTemplate *armorTemplate, const char* name);

typedef std::hash_map< NameKeyType, ArmorTemplate*, rts::hash<NameKeyType>, rts::equal_to<NameKeyType> > ArmorTemplateMap;
ArmorTemplateMap m_armorTemplates;

};
Expand Down
97 changes: 91 additions & 6 deletions GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Armor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ ArmorTemplate::ArmorTemplate()
clear();
}

//-------------------------------------------------------------------------------------------------
ArmorTemplate::~ArmorTemplate()
{

}

//-------------------------------------------------------------------------------------------------
void ArmorTemplate::clear()
{
Expand Down Expand Up @@ -112,6 +118,11 @@ ArmorStore::ArmorStore()
//-------------------------------------------------------------------------------------------------
ArmorStore::~ArmorStore()
{
for (ArmorTemplateMap::iterator it = m_armorTemplates.begin(); it != m_armorTemplates.end(); ++it)
{
deleteInstance(it->second);
}

m_armorTemplates.clear();
}

Expand All @@ -125,7 +136,7 @@ const ArmorTemplate* ArmorStore::findArmorTemplate(NameKeyType namekey) const
}
else
{
return &(*it).second;
return (*it).second;
}
}

Expand All @@ -149,11 +160,85 @@ const ArmorTemplate* ArmorStore::findArmorTemplate(const char* name) const
{ "Armor", ArmorTemplate::parseArmorCoefficients, NULL, 0 }
};

const char *c = ini->getNextToken();
NameKeyType key = TheNameKeyGenerator->nameToKey(c);
ArmorTemplate& armorTmpl = TheArmorStore->m_armorTemplates[key];
armorTmpl.clear();
ini->initFromINI(&armorTmpl, myFieldParse);
const char *name = ini->getNextToken();
const NameKeyType key = TheNameKeyGenerator->nameToKey(name);

// TheSuperHackers @bugfix Caball009 04/01/2025 Avoid mismatches by creating overrides instead of overwriting the default data.
// The code resembles the code of the ThingFactory.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not directly related:

Can we perhaps make a change to streamline the override code between classes and then provide some code to avoid this boiler plate code in each of these classes that do overrides? Perhaps some template functions that help set it up.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was also thinking along those lines. I figured I'd start with the simplest of the classes that need overrides to see what it's required and what the review comments would be.

@Mauller I'll see if I can find a way to reuse the same code for all these INI parsers that require overrides.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok how do you wish to proceed with this matter?

Possible strategy:

  1. Clean up all existing INI override code and streamline their implementions
  2. Provide helper code for all INI override boiler plate code and place them in EA code
  3. Add INI overrides with helper code to all remaining classes that need INI overrides (very complex)

Copy link
Author

@Caball009 Caball009 Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've started with this. I need to check out all INI overrides, though, because some classes do stuff that others don't.

I think I can show the code I'm working on in a couple of days.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xezon #2083 I'm thinking of streamlining it like this.

ArmorTemplate *armorTmpl = TheArmorStore->m_armorTemplates[key];
if (!armorTmpl)
{
// no item is present, create a new one
armorTmpl = newInstance(ArmorTemplate);
armorTmpl->clear();

if (ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES)
{
// This ArmorTemplate is actually an override, so we will mark it as such so that it properly
// gets deleted on ::reset().
armorTmpl->markAsOverride();
}

TheArmorStore->m_armorTemplates[key] = armorTmpl;
}
else if (ini->getLoadType() != INI_LOAD_CREATE_OVERRIDES)
{
DEBUG_CRASH(( "[LINE: %d in '%s'] Duplicate armor definition %s found!", ini->getLineNum(), ini->getFilename().str(), name ));
}
else
{
armorTmpl = TheArmorStore->newOverride(armorTmpl, name);
}

ini->initFromINI(armorTmpl, myFieldParse);
}

//-------------------------------------------------------------------------------------------------
ArmorTemplate* ArmorStore::newOverride(ArmorTemplate *armorTemplate, const char *name)
{
// sanity
DEBUG_ASSERTCRASH( armorTemplate, ("newOverride(): NULL 'parent' armor template") );

// sanity just for debuging, the armor must be in the master list to do overrides
DEBUG_ASSERTCRASH( findArmorTemplate( name ) != NULL,
("newOverride(): Armor template '%s' not in master list", name) );

// find final override of the 'parent' template
ArmorTemplate *child = static_cast<ArmorTemplate*>(armorTemplate->friend_getFinalOverride());

// allocate new template
ArmorTemplate *newTemplate = newInstance(ArmorTemplate);

// copy data from final override to 'newTemplate' as a set of initial default values
*newTemplate = *child;

newTemplate->markAsOverride();
child->setNextOverride(newTemplate);

// return the newly created override for us to set values with etc
return newTemplate;
}

//-------------------------------------------------------------------------------------------------
void ArmorStore::reset()
{
ArmorTemplateMap::iterator it = m_armorTemplates.begin();

while (it != m_armorTemplates.end())
{
ArmorTemplateMap::iterator next = it;
++next;

const Overridable *stillValid = it->second->deleteOverrides();

if (stillValid == NULL)
{
// Also needs to be removed from the Hash map.
m_armorTemplates.erase(it);
}

it = next;
}
}

//-------------------------------------------------------------------------------------------------
Expand Down
Loading