Ejemplo n.º 1
0
/**
**  Apply the modifiers of an upgrade.
**
**  This function will mark upgrade done and do all required modifications
**  to unit types and will modify allow/forbid maps
**
**  @param player  Player that get all the upgrades.
**  @param um      Upgrade modifier that do the effects
*/
static void ApplyUpgradeModifier(CPlayer *player, const CUpgradeModifier *um)
{
	int z;                      // iterator on upgrade or unittype.
	int j;                      // iterator on cost or variable.
	int pn;                     // player number.
	int varModified;            // 0 if variable is not modified.
	int numunits;               // number of unit of the current type.
	CUnit *unitupgrade[UnitMax]; // array of unit of the current type
	CUnit *unit;                 // current unit.

	Assert(player);
	Assert(um);
	pn = player->Index;
	for (z = 0; z < UpgradeMax; ++z) {
		// allow/forbid upgrades for player.  only if upgrade is not acquired

		// FIXME: check if modify is allowed

		if (player->Allow.Upgrades[z] != 'R') {
			if (um->ChangeUpgrades[z] == 'A') {
				player->Allow.Upgrades[z] = 'A';
			}
			if (um->ChangeUpgrades[z] == 'F') {
				player->Allow.Upgrades[z] = 'F';
			}
			// we can even have upgrade acquired w/o costs
			if (um->ChangeUpgrades[z] == 'R') {
				player->Allow.Upgrades[z] = 'R';
			}
		}
	}

	for (z = 0; z < UnitTypeMax; ++z) {
		// add/remove allowed units

		// FIXME: check if modify is allowed

		player->Allow.Units[z] += um->ChangeUnits[z];

		Assert(um->ApplyTo[z] == '?' || um->ApplyTo[z] == 'X');

		// this modifier should be applied to unittype id == z
		if (um->ApplyTo[z] == 'X') {

			// If Sight range is upgraded, we need to change EVERY unit
			// to the new range, otherwise the counters get confused.
			if (um->Modifier.Variables[SIGHTRANGE_INDEX].Value) {
				numunits = FindUnitsByType(UnitTypes[z], unitupgrade);
				for (numunits--; numunits >= 0; --numunits) {
					unit = unitupgrade[numunits];
					if (unit->Player->Index == pn && !unit->Removed) {
						MapUnmarkUnitSight(unit);
						unit->CurrentSightRange = UnitTypes[z]->Stats[pn].Variables[SIGHTRANGE_INDEX].Max +
							um->Modifier.Variables[SIGHTRANGE_INDEX].Value;
						MapMarkUnitSight(unit);
					}
				}
			}
			// upgrade costs :)
			for (j = 0; j < MaxCosts; ++j) {
				UnitTypes[z]->Stats[pn].Costs[j] += um->Modifier.Costs[j];
			}

			varModified = 0;
			for (j = 0; j < UnitTypeVar.NumberVariable; j++) {
				varModified |= um->Modifier.Variables[j].Value
					| um->Modifier.Variables[j].Max
					| um->Modifier.Variables[j].Increase;
				UnitTypes[z]->Stats[pn].Variables[j].Value += um->Modifier.Variables[j].Value;
				if (UnitTypes[z]->Stats[pn].Variables[j].Value < 0) {
					UnitTypes[z]->Stats[pn].Variables[j].Value = 0;
				}
				UnitTypes[z]->Stats[pn].Variables[j].Max += um->Modifier.Variables[j].Max;
				if (UnitTypes[z]->Stats[pn].Variables[j].Max < 0) {
					UnitTypes[z]->Stats[pn].Variables[j].Max = 0;
				}
				if (UnitTypes[z]->Stats[pn].Variables[j].Value > UnitTypes[z]->Stats[pn].Variables[j].Max) {
					UnitTypes[z]->Stats[pn].Variables[j].Value = UnitTypes[z]->Stats[pn].Variables[j].Max;
				}
				UnitTypes[z]->Stats[pn].Variables[j].Increase += um->Modifier.Variables[j].Increase;
			}

			// And now modify ingame units
			if (varModified) {
				numunits = FindUnitsByType(UnitTypes[z], unitupgrade);
				numunits--; // Change to 0 Start not 1 start
				for (; numunits >= 0; --numunits) {
					unit = unitupgrade[numunits];
					if (unit->Player->Index != player->Index) {
						continue;
					}
					for (j = 0; j < UnitTypeVar.NumberVariable; j++) {
						unit->Variable[j].Value += um->Modifier.Variables[j].Value;
						if (unit->Variable[j].Value < 0) {
							unit->Variable[j].Value = 0;
						}
						unit->Variable[j].Max += um->Modifier.Variables[j].Max;
						if (unit->Variable[j].Max < 0) {
							unit->Variable[j].Max = 0;
						}
						if (unit->Variable[j].Value > unit->Variable[j].Max) {
							unit->Variable[j].Value = unit->Variable[j].Max;
						}
						unit->Variable[j].Increase += um->Modifier.Variables[j].Increase;
					}
				}
			}
			if (um->ConvertTo) {
				ConvertUnitTypeTo(player,UnitTypes[z], um->ConvertTo);
			}
		}
	}
}
Ejemplo n.º 2
0
/**
**  Remove the modifiers of an upgrade.
**
**  This function will unmark upgrade as done and undo all required modifications
**  to unit types and will modify allow/forbid maps back
**
**  @param player  Player that get all the upgrades.
**  @param um      Upgrade modifier that do the effects
*/
static void RemoveUpgradeModifier(CPlayer &player, const CUpgradeModifier *um)
{
	Assert(um);

	int pn = player.Index;

	if (um->SpeedResearch != 0) {
		player.SpeedResearch -= um->SpeedResearch;
	}

	for (int z = 0; z < UpgradeMax; ++z) {
		// allow/forbid upgrades for player.  only if upgrade is not acquired

		// FIXME: check if modify is allowed

		if (player.Allow.Upgrades[z] != 'R') {
			if (um->ChangeUpgrades[z] == 'A') {
				player.Allow.Upgrades[z] = 'F';
			}
			if (um->ChangeUpgrades[z] == 'F') {
				player.Allow.Upgrades[z] = 'A';
			}
			// we can even have upgrade acquired w/o costs
			if (um->ChangeUpgrades[z] == 'R') {
				player.Allow.Upgrades[z] = 'A';
			}
		}
	}

	for (size_t z = 0; z < UnitTypes.size(); ++z) {
		CUnitStats &stat = UnitTypes[z]->Stats[pn];
		// add/remove allowed units

		// FIXME: check if modify is allowed

		player.Allow.Units[z] -= um->ChangeUnits[z];

		Assert(um->ApplyTo[z] == '?' || um->ApplyTo[z] == 'X');

		// this modifier should be applied to unittype id == z
		if (um->ApplyTo[z] == 'X') {

			// If Sight range is upgraded, we need to change EVERY unit
			// to the new range, otherwise the counters get confused.
			if (um->Modifier.Variables[SIGHTRANGE_INDEX].Value) {
				std::vector<CUnit *> unitupgrade;

				FindUnitsByType(*UnitTypes[z], unitupgrade);
				for (size_t j = 0; j != unitupgrade.size(); ++j) {
					CUnit &unit = *unitupgrade[j];
					if (unit.Player->Index == pn && !unit.Removed) {
						MapUnmarkUnitSight(unit);
						unit.CurrentSightRange = stat.Variables[SIGHTRANGE_INDEX].Max -
							um->Modifier.Variables[SIGHTRANGE_INDEX].Value;
						MapMarkUnitSight(unit);
					}
				}
			}
			// upgrade costs :)
			for (unsigned int j = 0; j < MaxCosts; ++j) {
				stat.Costs[j] -= um->Modifier.Costs[j];
				stat.Storing[j] -= um->Modifier.Storing[j];
			}

			int varModified = 0;
			for (unsigned int j = 0; j < UnitTypeVar.GetNumberVariable(); j++) {
				varModified |= um->Modifier.Variables[j].Value
					| um->Modifier.Variables[j].Max
					| um->Modifier.Variables[j].Increase
					| um->Modifier.Variables[j].Enable
					| um->ModifyPercent[j];
				stat.Variables[j].Enable |= um->Modifier.Variables[j].Enable;
				if (um->ModifyPercent[j]) {
					stat.Variables[j].Value = stat.Variables[j].Value * 100 / (100 + um->ModifyPercent[j]);
					stat.Variables[j].Max = stat.Variables[j].Max * 100 / (100 + um->ModifyPercent[j]);
				} else {
					stat.Variables[j].Value -= um->Modifier.Variables[j].Value;
					stat.Variables[j].Max -= um->Modifier.Variables[j].Max;
					stat.Variables[j].Increase -= um->Modifier.Variables[j].Increase;
				}

				stat.Variables[j].Max = std::max(stat.Variables[j].Max, 0);
				clamp(&stat.Variables[j].Value, 0, stat.Variables[j].Max);
			}

			// And now modify ingame units
			if (varModified) {
				std::vector<CUnit *> unitupgrade;

				FindUnitsByType(*UnitTypes[z], unitupgrade, true);
				for (size_t j = 0; j != unitupgrade.size(); ++j) {
					CUnit &unit = *unitupgrade[j];

					if (unit.Player->Index != player.Index) {
						continue;
					}
					for (unsigned int j = 0; j < UnitTypeVar.GetNumberVariable(); j++) {
						unit.Variable[j].Enable |= um->Modifier.Variables[j].Enable;
						if (um->ModifyPercent[j]) {
							unit.Variable[j].Value = unit.Variable[j].Value * 100 / (100 + um->ModifyPercent[j]);
							unit.Variable[j].Max = unit.Variable[j].Max * 100 / (100 + um->ModifyPercent[j]);
						} else {
							unit.Variable[j].Value -= um->Modifier.Variables[j].Value;
							unit.Variable[j].Increase -= um->Modifier.Variables[j].Increase;
						}

						unit.Variable[j].Max -= um->Modifier.Variables[j].Max;
						unit.Variable[j].Max = std::max(unit.Variable[j].Max, 0);

						clamp(&unit.Variable[j].Value, 0, unit.Variable[j].Max);
					}
				}
			}
			if (um->ConvertTo) {
				ConvertUnitTypeTo(player, *um->ConvertTo, *UnitTypes[z]);
			}
		}
	}
}