// set this value to however many units you think you will need
// or if you have a class that you intend to have many objects
const int INDEXER_MAX_INDEX = 5000;
// set this value higher if you plan on having many classes
const int INDEXER_MAX_INSTANCE_COUNT = 100;
int [INDEXER_MAX_INSTANCE_COUNT][INDEXER_MAX_INDEX] indexerFreeIndexes;
int [INDEXER_MAX_INSTANCE_COUNT] indexerFreeIndexCount;
int [INDEXER_MAX_INSTANCE_COUNT] indexerNextIndex;
int [INDEXER_MAX_INSTANCE_COUNT] indexerFreeInstances;
int indexerFreeInstanceCount = 0;
int indexerNextInstance = 0;
int [INDEXER_MAX_INSTANCE_COUNT][INDEXER_MAX_INDEX] indexerAllocatedIndexes;
bool [INDEXER_MAX_INSTANCE_COUNT][INDEXER_MAX_INDEX] indexerIndexIsAllocated;
int [INDEXER_MAX_INSTANCE_COUNT] indexerAllocatedIndexesCount;
int [INDEXER_MAX_INSTANCE_COUNT][INDEXER_MAX_INDEX] indexerIndOfAllocatedIndex;
int indexerCurrentIndex;
int IndexerNextIndex(int inst) {
int index;
int indOfAllocatedIndex;
if (indexerFreeIndexCount[inst] > 0) {
indexerFreeIndexCount[inst] -= 1;
index = indexerFreeIndexes[inst][indexerFreeIndexCount[inst]];
}
else {
index = indexerNextIndex[inst];
indexerNextIndex[inst] += 1;
}
indOfAllocatedIndex = indexerAllocatedIndexesCount[inst];
indexerAllocatedIndexes[inst][indOfAllocatedIndex] = index;
indexerIndOfAllocatedIndex[inst][index] = indOfAllocatedIndex;
indexerAllocatedIndexesCount[inst] += 1;
indexerIndexIsAllocated[inst][index] = true;
return index;
}
void IndexerFreeIndex(int inst, int index) {
int indOfAllocatedIndex = indexerIndOfAllocatedIndex[inst][index];
int allocatedIndexCount = indexerAllocatedIndexesCount[inst];
int lastAllocatedIndex = indexerAllocatedIndexes[inst][allocatedIndexCount - 1];
indexerFreeIndexes[inst][indexerFreeIndexCount[inst]] = index;
indexerFreeIndexCount[inst] += 1;
// swap out the allocated index
// move the last index in the allocated indexes array to the position of the index we're removing
indexerAllocatedIndexes[inst][indOfAllocatedIndex] = lastAllocatedIndex;
// update the ind of this index to be the ind of the index we're removing
indexerIndOfAllocatedIndex[inst][lastAllocatedIndex] = indOfAllocatedIndex;
// subtract the allocation count by 1
indexerAllocatedIndexesCount[inst] -= 1;
indexerIndexIsAllocated[inst][index] = false;
}
void IndexerForEachAllocatedIndex(int inst, trigger cb) {
int ind;
int allocatedIndexCount = indexerAllocatedIndexesCount[inst];
for (ind = 0; ind < allocatedIndexCount; ind += 1) {
indexerCurrentIndex = indexerAllocatedIndexes[inst][ind];
TriggerExecute(cb, true, true);
}
}
int IndexerCurrentIndex() {
return indexerCurrentIndex;
}
bool IndexerIndexIsAllocated(int inst, int index) {
return indexerIndexIsAllocated[inst][index];
}
int IndexerAllocatedIndicesCount(int inst) {
return indexerAllocatedIndexesCount[inst];
}
int IndexerCreate() {
int inst;
int index;
int i;
if (indexerFreeInstanceCount > 0) {
indexerFreeInstanceCount -= 1;
inst = indexerFreeInstances[indexerFreeInstanceCount];
}
else {
inst = indexerNextInstance;
indexerNextInstance += 1;
}
for (i = 0; i < INDEXER_MAX_INDEX; i += 1) {
indexerIndexIsAllocated[inst][i] = false;
}
indexerFreeIndexCount[inst] = 0;
indexerNextIndex[inst] = 0;
indexerAllocatedIndexesCount[inst] = 0;
return inst;
}
void IndexerDestroy(int inst) {
indexerFreeInstances[indexerFreeInstanceCount] = inst;
indexerFreeInstanceCount += 1;
}
// easilly assign indexes to units on creation and destruction
int unitIndexer;
const int UNIT_INDEXER_CUSTOM_VALUE_INDEX = 0; // set this to whatever you need to avoid collision with other systems
trigger unitIndexerOnUnitCreated;
trigger unitIndexerOnUnitDied;
trigger unitIndexerInitialUnitRegister;
// uncomment to start adding flags or other data associated with units
//bool [INDEXER_MAX_INDEX] unitIndexerSomeUnitFlag;
int UnitIndexerTotalRegisteredUnitCount() {
return IndexerAllocatedIndicesCount(unitIndexer);
}
void UnitIndexerRegisterUnit(unit u) {
UnitSetCustomValue(u, UNIT_INDEXER_CUSTOM_VALUE_INDEX, IndexerNextIndex(unitIndexer));
}
void UnitIndexerUnRegisterUnit(unit u) {
IndexerFreeIndex(unitIndexer, FixedToInt(UnitGetCustomValue(u, UNIT_INDEXER_CUSTOM_VALUE_INDEX)));
}
bool unitIndexerOnUnitCreatedCB(bool a, bool b) {
unit u = EventUnitCreatedUnit();
string uType = UnitGetType(u);
// do not register missiles...
if (!UnitTypeTestFlag(uType, c_unitFlagMissile)) {
UnitIndexerRegisterUnit(u);
}
return true;
}
bool unitIndexerOnUnitDiedCB(bool a, bool b) {
UnitIndexerUnRegisterUnit(EventUnit());
return true;
}
bool unitIndexerInitialUnitRegisterCB(bool a, bool b) {
// currently the unit filter is told to ignore dead or missile units, you can change the filter to whatever you need
// if you're confused, make a trigger. make a local variable of type unit filter
// go to value and change the filters/flags to whatever you like
// now do a custom script action and mash the keyboard.
// when you press save, an error will appear. You can copy the text for the unit filter local variable by highlighting it
// and right clicking the pressing copy from the context menu. cntrl c + cntrl v won't work here, you have to use the right click
// context menu
unitgroup un = UnitGroup(null, c_playerAny, RegionEntireMap(), UnitFilter(0, 0, (1 << c_targetFilterMissile), (1 << (c_targetFilterDead - 32))), c_noMaxCount);
UnitGroupLoopBegin(un);
while(!UnitGroupLoopDone()) {
UnitIndexerRegisterUnit(UnitGroupLoopCurrent());
UnitGroupLoopStep();
}
UnitGroupLoopEnd();
return true;
}
// set this as the custom script's initialization function
void initUnitIndexer() {
unitIndexer = IndexerCreate();
unitIndexerOnUnitCreated = TriggerCreate("unitIndexerOnUnitCreatedCB");
TriggerAddEventUnitCreated(unitIndexerOnUnitCreated, null, null, null);
unitIndexerOnUnitDied = TriggerCreate("unitIndexerOnUnitDiedCB");
TriggerAddEventUnitDied(unitIndexerOnUnitDied, null);
TriggerAddEventUnitRemoved(unitIndexerOnUnitDied, null);
unitIndexerInitialUnitRegister = TriggerCreate("unitIndexerInitialUnitRegisterCB");
TriggerAddEventTimeElapsed(unitIndexerInitialUnitRegister, 0, c_timeGame);
}
const int UNIT_ROSTER_MAX_INSTANCE = INDEXER_MAX_INDEX;
int unitRosterIndexer;
const string UNIT_ROSTER_TABLE_PREFIX = "UNIT_ROSTER";
string [UNIT_ROSTER_MAX_INSTANCE][100] unitRosterRegisteredUnitTypes;
string [100] unitRosterUnitTypesTmp;
int [UNIT_ROSTER_MAX_INSTANCE] unitRosterRegisteredUnitTypesCount;
int [UNIT_ROSTER_MAX_INSTANCE] unitRosterRegisteredUnitCount;
int unitRosterCurrentUnitTypeCount;
string unitRosterCurrentUnitType;
int tmpUnitRoster;
int unitRosterCompareOne;
int unitRosterCompareTwo;
int UnitRosterCreate() {
int inst = IndexerNextIndex(unitRosterIndexer);
unitRosterRegisteredUnitTypesCount[inst] = 0;
unitRosterRegisteredUnitCount[inst] = 0;
return inst;
}
void UnitRosterClear(int inst) {
int i;
string uType;
for (i = 0; i < unitRosterRegisteredUnitTypesCount[inst]; i += 1) {
uType = unitRosterRegisteredUnitTypes[inst][i];
DataTableValueRemove(true, UNIT_ROSTER_TABLE_PREFIX + IntToString(inst) + uType + "_COUNT");
}
unitRosterRegisteredUnitTypesCount[inst] = 0;
unitRosterRegisteredUnitCount[inst] = 0;
}
void UnitRosterDestroy(int inst) {
UnitRosterClear(inst);
IndexerFreeIndex(unitRosterIndexer, inst);
}
bool UnitRosterHasUnitType(int inst, string uType) {
return DataTableValueExists(true, UNIT_ROSTER_TABLE_PREFIX + IntToString(inst) + uType + "_COUNT");
}
int UnitRosterGetUnitTypeCount(int inst, string uType) {
return DataTableGetInt(true, UNIT_ROSTER_TABLE_PREFIX + IntToString(inst) + uType + "_COUNT");
}
void UnitRosterAddUnitType(int inst, string uType, int amount) {
int count;
if (UnitRosterHasUnitType(inst, uType)) {
count = UnitRosterGetUnitTypeCount(inst, uType);
DataTableSetInt(true, UNIT_ROSTER_TABLE_PREFIX + IntToString(inst) + uType + "_COUNT", count + amount);
}
else {
unitRosterRegisteredUnitTypes[inst][unitRosterRegisteredUnitTypesCount[inst]] = uType;
unitRosterRegisteredUnitTypesCount[inst] += 1;
DataTableSetInt(true, UNIT_ROSTER_TABLE_PREFIX + IntToString(inst) + uType + "_COUNT", amount);
}
unitRosterRegisteredUnitCount[inst] += amount;
}
void UnitRosterSubtractUnitType(int inst, string uType, int amount) {
UnitRosterAddUnitType(inst, uType, -1 * amount);
}
void UnitRosterAddUnit(int inst, unit u) {
UnitRosterAddUnitType(inst, UnitGetType(u), 1);
}
void UnitRosterSubtractUnit(int inst, unit u) {
UnitRosterSubtractUnitType(inst, UnitGetType(u), 1);
}
int UnitRosterGetTotalUnitCount(int inst) {
return unitRosterRegisteredUnitCount[inst];
}
int UnitRosterGetRegisteredUnitTypesCount(int inst) {
return unitRosterRegisteredUnitTypesCount[inst];
}
string UnitRosterGetUnitTypeIndex(int inst, int ind) {
return unitRosterRegisteredUnitTypes[inst][ind];
}
void UnitRosterSortBySupply(int inst) {
int i;
int j;
int n = unitRosterRegisteredUnitTypesCount[inst];
string tmp0;
string tmp1;
// copy the array
for (i = 0; i < n; i += 1) {
unitRosterUnitTypesTmp[i] = unitRosterRegisteredUnitTypes[inst][i];
}
// sort the array
for (i = 0; i < n - 1; i += 1) {
for (j = 0; j < n - i - 1; j += 1) {
if (UnitTypeGetProperty(unitRosterUnitTypesTmp[j], c_unitPropSuppliesUsed) > UnitTypeGetProperty(unitRosterUnitTypesTmp[j + 1], c_unitPropSuppliesUsed)) {
tmp0 = unitRosterUnitTypesTmp[j];
tmp1 = unitRosterUnitTypesTmp[j + 1];
unitRosterUnitTypesTmp[j] = tmp1;
unitRosterUnitTypesTmp[j + 1] = tmp0;
}
}
}
// copy the array back
for (i = 0; i < n; i += 1) {
unitRosterRegisteredUnitTypes[inst][i] = unitRosterUnitTypesTmp[i];
}
}
void UnitRosterAddUnitGroup(int inst, unitgroup un) {
UnitGroupLoopBegin(un);
while(!UnitGroupLoopDone()) {
UnitRosterAddUnit(inst, UnitGroupLoopCurrent());
UnitGroupLoopStep();
}
UnitGroupLoopEnd();
}
int UnitRosterCurrentUnitTypeCount() {
return unitRosterCurrentUnitTypeCount;
}
string UnitRosterCurrentUnitType() {
return unitRosterCurrentUnitType;
}
void UnitRosterForEachUnitCount(int inst, trigger cb) {
int i;
for (i = 0; i < unitRosterRegisteredUnitTypesCount[inst]; i += 1) {
unitRosterCurrentUnitType = unitRosterRegisteredUnitTypes[inst][i];
unitRosterCurrentUnitTypeCount = UnitRosterGetUnitTypeCount(inst, unitRosterCurrentUnitType);
TriggerExecute(cb, true, true);
}
}
// set this as the custom script's initialization function
void initUnitRoster() {
unitRosterIndexer = IndexerCreate();
}