Esempio n. 1
0
int AddButton( int pos, int level, const char* IconIdent,
	enum _button_cmd_ action, const char* value,
	const void* func, const void* allow,
	int key, const char* hint, const char* umask )
{
  char buf[2048];
  ButtonAction* ba = (ButtonAction*)malloc(sizeof(ButtonAction));
  DebugCheck(!ba); //FIXME: perhaps should return error?
  ba->Pos = pos;
  ba->Level = level;
  ba->Icon.Name = (char*)IconIdent;
  ba->Icon.Icon = IconByIdent( IconIdent );
  ba->Action = action;
  if( value ) {
      ba->ValueStr = strdup( value );
      switch( action )
	{
	case B_Magic:	 ba->Value = UpgradeIdByIdent( value ); break;
	case B_Train:	 ba->Value = UnitTypeIdByIdent( value ); break;
	case B_Research: ba->Value = UpgradeIdByIdent( value ); break;
	case B_UpgradeTo: ba->Value = UnitTypeIdByIdent( value ); break;
	case B_Build:	 ba->Value = UnitTypeIdByIdent( value ); break;
	default:	ba->Value = atoi( value ); break;
	}
  } else {
      ba->ValueStr = NULL;
      ba->Value = 0;
  }

  ba->Allowed = func;
  if( allow ) {
      ba->AllowStr=strdup(allow);
  } else {
      ba->AllowStr=NULL;
  }

  ba->Key = key;
  ba->Hint = strdup( hint );
  //FIXME: here should be added costs to the hint
  //FIXME: johns: show should be nice done?
  if ( umask[0] == '*' )
    strcpy( buf, umask );
  else
    sprintf( buf, ",%s,", umask );
  ba->UMask = strdup( buf );
  UnitButtonTable[UnitButtonCount++] = ba;

  DebugCheck( ba->Icon.Icon==-1 );	// just checks, that's why at the end
  return 1;
};
Esempio n. 2
0
/**
**  Define which units are allowed and how much.
*/
static int CclDefineUnitAllow(lua_State *l)
{
	const char *ident;
	int i;
	int args;
	int j;
	int id;

	args = lua_gettop(l);
	j = 0;
	ident = LuaToString(l, j + 1);
	++j;

	if (strncmp(ident, "unit-", 5)) {
		DebugPrint(" wrong ident %s\n" _C_ ident);
		return 0;
	}
	id = UnitTypeIdByIdent(ident);

	i = 0;
	for (; j < args && i < PlayerMax; ++j) {
		AllowUnitId(&Players[i], id, LuaToNumber(l, j + 1));
		++i;
	}

	return 0;
}
Esempio n. 3
0
/**
**  Define which units/upgrades are allowed.
*/
static int CclDefineAllow(lua_State *l)
{
	const char *ident;
	const char *ids;
	int i;
	int n;
	int args;
	int j;
	int id;

	args = lua_gettop(l);
	for (j = 0; j < args; ++j) {
		ident = LuaToString(l, j + 1);
		++j;
		ids = LuaToString(l, j + 1);

		n = strlen(ids);
		if (n > PlayerMax) {
			fprintf(stderr, "%s: Allow string too long %d\n", ident, n);
			n = PlayerMax;
		}

		if (!strncmp(ident, "unit-", 5)) {
			id = UnitTypeIdByIdent(ident);
			for (i = 0; i < n; ++i) {
				if (ids[i] == 'A') {
					AllowUnitId(&Players[i], id, UnitMax);
				} else if (ids[i] == 'F') {
					AllowUnitId(&Players[i], id, 0);
				}
			}
		} else if (!strncmp(ident, "upgrade-", 8)) {
			id = UpgradeIdByIdent(ident);
			for (i = 0; i < n; ++i) {
				AllowUpgradeId(&Players[i], id, ids[i]);
			}
		} else {
			DebugPrint(" wrong ident %s\n" _C_ ident);
		}
	}

	return 0;
}
Esempio n. 4
0
/**
**	@brief	Process data provided by a configuration file
**
**	@param	config_data	The configuration data
*/
void CUpgradeModifier::ProcessConfigData(const CConfigData *config_data)
{
	for (size_t i = 0; i < config_data->Properties.size(); ++i) {
		std::string key = config_data->Properties[i].first;
		std::string value = config_data->Properties[i].second;
		
		if (key == "apply_to") {
			value = FindAndReplaceString(value, "_", "-");
			const int unit_type_id = UnitTypeIdByIdent(value.c_str());
			if (unit_type_id != -1) {
				this->ApplyTo[unit_type_id] = 'X';
			} else {
				fprintf(stderr, "Invalid unit type: \"%s\".\n", value.c_str());
			}
		} else if (key == "remove_upgrade") {
			value = FindAndReplaceString(value, "_", "-");
			CUpgrade *removed_upgrade = CUpgrade::Get(value);
			if (removed_upgrade) {
				this->RemoveUpgrades.push_back(removed_upgrade);
			} else {
				fprintf(stderr, "Invalid upgrade: \"%s\".\n", value.c_str());
			}
		} else {
			key = SnakeCaseToPascalCase(key);
			
			int index = UnitTypeVar.VariableNameLookup[key.c_str()]; // variable index
			if (index != -1) { // valid index
				if (IsStringNumber(value)) {
					this->Modifier.Variables[index].Enable = 1;
					this->Modifier.Variables[index].Value = std::stoi(value);
					this->Modifier.Variables[index].Max = std::stoi(value);
				} else { // error
					fprintf(stderr, "Invalid value (\"%s\") for variable \"%s\" when defining modifier for upgrade \"%s\".\n", value.c_str(), key.c_str(), AllUpgrades[this->UpgradeId]->Ident.c_str());
				}
			} else {
				fprintf(stderr, "Invalid upgrade modifier property: \"%s\".\n", key.c_str());
			}
		}
	}
}
Esempio n. 5
0
/**
**  Define a province.
**
**  @param l  Lua state.
*/
static int CclDefineProvince(lua_State *l)
{
	LuaCheckArgs(l, 2);
	if (!lua_istable(l, 2)) {
		LuaError(l, "incorrect argument (expected table)");
	}

	std::string province_name = LuaToString(l, 1);
	CProvince *province = GetProvince(province_name);
	if (!province) {
		province = new CProvince;
		province->Name = province_name;
		province->ID = Provinces.size();
		Provinces.push_back(province);
	}
	
	std::string name_type = "province";
	
	//  Parse the list:
	for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) {
		const char *value = LuaToString(l, -2);
		
		if (!strcmp(value, "World")) {
			CWorld *world = CWorld::GetWorld(LuaToString(l, -1));
			if (world != nullptr) {
				province->World = world;
				world->Provinces.push_back(province);
			} else {
				LuaError(l, "World doesn't exist.");
			}
		} else if (!strcmp(value, "Water")) {
			province->Water = LuaToBoolean(l, -1);
		} else if (!strcmp(value, "Coastal")) {
			province->Coastal = LuaToBoolean(l, -1);
		} else if (!strcmp(value, "CulturalNames")) {
			if (!lua_istable(l, -1)) {
				LuaError(l, "incorrect argument (expected table)");
			}
			const int subargs = lua_rawlen(l, -1);
			for (int j = 0; j < subargs; ++j) {
				CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, -1, j + 1));
				++j;
				if (!civilization) {
					continue;
				}

				std::string cultural_name = LuaToString(l, -1, j + 1);
				
				province->CulturalNames[civilization->ID] = TransliterateText(cultural_name);
			}
		} else if (!strcmp(value, "FactionCulturalNames")) {
			if (!lua_istable(l, -1)) {
				LuaError(l, "incorrect argument (expected table)");
			}
			const int subargs = lua_rawlen(l, -1);
			for (int j = 0; j < subargs; ++j) {
				++j;

				int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1));
				if (faction == -1) {
					LuaError(l, "Faction doesn't exist.");
				}
				++j;
				
				std::string cultural_name = LuaToString(l, -1, j + 1);
				
				province->FactionCulturalNames[PlayerRaces.Factions[faction]] = TransliterateText(cultural_name);
			}
		} else if (!strcmp(value, "Claims")) {
			if (!lua_istable(l, -1)) {
				LuaError(l, "incorrect argument (expected table)");
			}
			const int subargs = lua_rawlen(l, -1);
			for (int j = 0; j < subargs; ++j) {
				++j;
				
				int faction = PlayerRaces.GetFactionIndexByName(LuaToString(l, -1, j + 1));
				if (faction == -1) {
					LuaError(l, "Faction doesn't exist.");
				}
				
				province->FactionClaims.push_back(PlayerRaces.Factions[faction]);
			}
		} else if (!strcmp(value, "Regions")) {
			if (!lua_istable(l, -1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, -1);
			for (int j = 0; j < subargs; ++j) {
				CRegion *region = GetRegion(LuaToString(l, -1, j + 1));
				if (region == nullptr) {
					LuaError(l, "Region doesn't exist.");
				}
				province->Regions.push_back(region);
				region->Provinces.push_back(province);
			}
		} else if (!strcmp(value, "HistoricalOwners")) {
			if (!lua_istable(l, -1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, -1);
			for (int j = 0; j < subargs; ++j) {
				int year = LuaToNumber(l, -1, j + 1);
				++j;
				++j;
				std::string owner_faction_name = LuaToString(l, -1, j + 1);
				if (!owner_faction_name.empty()) {
					int owner_faction = PlayerRaces.GetFactionIndexByName(owner_faction_name);
					if (owner_faction == -1) {
						LuaError(l, "Faction \"%s\" doesn't exist." _C_ owner_faction_name.c_str());
					}
					province->HistoricalOwners[year] = PlayerRaces.Factions[owner_faction];
				} else {
					province->HistoricalOwners[year] = nullptr;
				}
			}
		} else if (!strcmp(value, "HistoricalClaims")) {
			if (!lua_istable(l, -1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, -1);
			for (int j = 0; j < subargs; ++j) {
				int year = LuaToNumber(l, -1, j + 1);
				++j;
				++j;
				std::string claimant_faction_name = LuaToString(l, -1, j + 1);
				int claimant_faction = PlayerRaces.GetFactionIndexByName(claimant_faction_name);
				if (claimant_faction == -1) {
					LuaError(l, "Faction \"%s\" doesn't exist." _C_ claimant_faction_name.c_str());
				}
				province->HistoricalClaims[year] = PlayerRaces.Factions[claimant_faction];
			}
		} else if (!strcmp(value, "HistoricalCultures")) {
			if (!lua_istable(l, -1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, -1);
			for (int j = 0; j < subargs; ++j) {
				int year = LuaToNumber(l, -1, j + 1);
				++j;
				std::string historical_civilization_name = LuaToString(l, -1, j + 1);
				if (!historical_civilization_name.empty()) {
					CCivilization *historical_civilization = CCivilization::GetCivilization(historical_civilization_name);
					if (historical_civilization) {
						province->HistoricalCultures[year] = historical_civilization->ID;
					}
				}
			}
		} else if (!strcmp(value, "HistoricalPopulation")) {
			if (!lua_istable(l, -1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, -1);
			for (int j = 0; j < subargs; ++j) {
				int year = LuaToNumber(l, -1, j + 1);
				++j;
				int historical_population = LuaToNumber(l, -1, j + 1);
				province->HistoricalPopulation[year] = historical_population;
			}
		} else if (!strcmp(value, "HistoricalSettlementBuildings")) {
			if (!lua_istable(l, -1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, -1);
			for (int j = 0; j < subargs; ++j) {
				int year = LuaToNumber(l, -1, j + 1);
				++j;
				std::string building_type_ident = LuaToString(l, -1, j + 1);
				int building_type = UnitTypeIdByIdent(building_type_ident);
				if (building_type == -1) {
					LuaError(l, "Unit type \"%s\" doesn't exist." _C_ building_type_ident.c_str());
				}
				++j;
				province->HistoricalSettlementBuildings[building_type][year] = LuaToBoolean(l, -1, j + 1);
			}
		} else if (!strcmp(value, "HistoricalModifiers")) {
			if (!lua_istable(l, -1)) {
				LuaError(l, "incorrect argument");
			}
			const int subargs = lua_rawlen(l, -1);
			for (int j = 0; j < subargs; ++j) {
				int year = LuaToNumber(l, -1, j + 1);
				++j;
				std::string upgrade_ident = LuaToString(l, -1, j + 1);
				CUpgrade *modifier = CUpgrade::Get(upgrade_ident);
				if (modifier == nullptr) {
					LuaError(l, "Upgrade \"%s\" doesn't exist." _C_ upgrade_ident.c_str());
				}
				++j;
				province->HistoricalModifiers[modifier][year] = LuaToBoolean(l, -1, j + 1);
			}
		} else {
			LuaError(l, "Unsupported tag: %s" _C_ value);
		}
	}
	
	if (province->World == nullptr) {
		LuaError(l, "Province \"%s\" is not assigned to any world." _C_ province->Name.c_str());
	}
	
	return 0;
}
Esempio n. 6
0
/**
**  FIXME: docu
*/
int AddButton(int pos, int level, const std::string &icon_ident,
			  ButtonCmd action, const std::string &value, void* actionCb, const ButtonCheckFunc func,
			  const std::string &allow, const int key, const std::string &hint, const std::string &descr,
			  const std::string &sound, const std::string &cursor, const std::string &umask,
			  const std::string &popup, bool alwaysShow)
{
	char buf[2048];
	ButtonAction *ba = new ButtonAction;
	Assert(ba);

	ba->Pos = pos;
	ba->Level = level;
	ba->AlwaysShow = alwaysShow;
	ba->Icon.Name = icon_ident;
	ba->Payload = actionCb;
	// FIXME: check if already initited
	//ba->Icon.Load();
	ba->Action = action;
	if (!value.empty()) {
		ba->ValueStr = value;
		switch (action) {
			case ButtonSpellCast:
				ba->Value = SpellTypeByIdent(value)->Slot;
#ifdef DEBUG
				if (ba->Value < 0) {
					DebugPrint("Spell %s does not exist?\n" _C_ value.c_str());
					Assert(ba->Value >= 0);
				}
#endif
				break;
			case ButtonTrain:
				ba->Value = UnitTypeIdByIdent(value);
				break;
			case ButtonResearch:
				ba->Value = UpgradeIdByIdent(value);
				break;
			case ButtonUpgradeTo:
				ba->Value = UnitTypeIdByIdent(value);
				break;
			case ButtonBuild:
				ba->Value = UnitTypeIdByIdent(value);
				break;
			default:
				ba->Value = atoi(value.c_str());
				break;
		}
	} else {
		ba->ValueStr.clear();
		ba->Value = 0;
	}

	ba->Allowed = func;
	ba->AllowStr = allow;
	ba->Key = key;
	ba->Hint = hint;
	ba->Description = descr;
	ba->CommentSound.Name = sound;
	if (!ba->CommentSound.Name.empty()) {
		ba->CommentSound.MapSound();
	}
	if (!ba->Popup.empty()) {
		CPopup *popup = PopupByIdent(ba->Popup);
		if (!popup) {
			fprintf(stderr, "Popup \"%s\" hasn't defined.\n ", ba->Popup.c_str());
			Exit(1);
		}
	}
	ba->ButtonCursor = cursor;
	ba->Popup = popup;
	// FIXME: here should be added costs to the hint
	// FIXME: johns: show should be nice done?
	if (umask[0] == '*') {
		strcpy_s(buf, sizeof(buf), umask.c_str());
	} else {
		sprintf(buf, ",%s,", umask.c_str());
	}
	ba->UnitMask = buf;
	UnitButtonTable.push_back(ba);
	// FIXME: check if already initited
	//Assert(ba->Icon.Icon != NULL);// just checks, that's why at the end
	return 1;
}
Esempio n. 7
0
/**
**  Define a new upgrade modifier.
**
**  @param l  List of modifiers.
*/
static int CclDefineModifier(lua_State *l)
{
	const char *key;
	const char *value;
	CUpgradeModifier *um;
	int args;
	int j;

	args = lua_gettop(l);

	um = new CUpgradeModifier;

	memset(um->ChangeUpgrades, '?', sizeof(um->ChangeUpgrades));
	memset(um->ApplyTo, '?', sizeof(um->ApplyTo));
	um->Modifier.Variables = new CVariable[UnitTypeVar.NumberVariable];

	um->UpgradeId = UpgradeIdByIdent(LuaToString(l, 1));

	for (j = 1; j < args; ++j) {
		if (!lua_istable(l, j + 1)) {
			LuaError(l, "incorrect argument");
		}
		lua_rawgeti(l, j + 1, 1);
		key = LuaToString(l, -1);
		lua_pop(l, 1);
#if 1 // To be removed. must modify lua file.
		if (!strcmp(key, "attack-range")) {
			key = "AttackRange";
		} else if (!strcmp(key, "sight-range")) {
			key = "SightRange";
		} else if (!strcmp(key, "basic-damage")) {
			key = "BasicDamage";
		} else if (!strcmp(key, "piercing-damage")) {
			key = "PiercingDamage";
		} else if (!strcmp(key, "armor")) {
			key = "Armor";
		} else if (!strcmp(key, "hit-points")) {
			key = "HitPoints";
		}
#endif
		if (!strcmp(key, "regeneration-rate")) {
			lua_rawgeti(l, j + 1, 2);
			um->Modifier.Variables[HP_INDEX].Increase = LuaToNumber(l, -1);
			lua_pop(l, 1);
		} else if (!strcmp(key, "cost")) {
			int i;

			if (!lua_istable(l, j + 1) || luaL_getn(l, j + 1) != 2) {
				LuaError(l, "incorrect argument");
			}
			lua_rawgeti(l, j + 1, 1);
			value = LuaToString(l, -1);
			lua_pop(l, 1);
			for (i = 0; i < MaxCosts; ++i) {
				if (!strcmp(value, DefaultResourceNames[i])) {
					break;
				}
			}
			if (i == MaxCosts) {
				LuaError(l, "Resource not found: %s" _C_ value);
			}
			lua_rawgeti(l, j + 1, 2);
			um->Modifier.Costs[i] = LuaToNumber(l, -1);
			lua_pop(l, 1);
		} else if (!strcmp(key, "allow-unit")) {
			lua_rawgeti(l, j + 1, 2);
			value = LuaToString(l, -1);
			lua_pop(l, 1);
			if (!strncmp(value, "unit-", 5)) {
				lua_rawgeti(l, j + 1, 3);
				um->ChangeUnits[UnitTypeIdByIdent(value)] = LuaToNumber(l, -1);
				lua_pop(l, 1);
			} else {
				LuaError(l, "unit expected");
			}
		} else if (!strcmp(key, "allow")) {
			lua_rawgeti(l, j + 1, 2);
			value = LuaToString(l, -1);
			lua_pop(l, 1);
			if (!strncmp(value, "upgrade-", 8)) {
				lua_rawgeti(l, j + 1, 3);
				um->ChangeUpgrades[UpgradeIdByIdent(value)] = LuaToNumber(l, -1);
				lua_pop(l, 1);
			} else {
				LuaError(l, "upgrade expected");
			}
		} else if (!strcmp(key, "apply-to")) {
			lua_rawgeti(l, j + 1, 2);
			value = LuaToString(l, -1);
			lua_pop(l, 1);
			um->ApplyTo[UnitTypeIdByIdent(value)] = 'X';
		} else if (!strcmp(key, "convert-to")) {
			lua_rawgeti(l, j + 1, 2);
			value = LuaToString(l, -1);
			lua_pop(l, 1);
			um->ConvertTo = UnitTypeByIdent(value);
		} else {
			int index; // variable index;

			index = GetVariableIndex(key);
			if (index != -1) {
				lua_rawgeti(l, j + 1, 2);
				if (lua_istable(l, -1)) {
					DefineVariableField(l, um->Modifier.Variables + index, -1);
				} else if (lua_isnumber(l, -1)) {
					um->Modifier.Variables[index].Enable = 1;
					um->Modifier.Variables[index].Value = LuaToNumber(l, -1);
					um->Modifier.Variables[index].Max = LuaToNumber(l, -1);
				} else {
					LuaError(l, "bad argument type for '%s'\n" _C_ key);
				}
				lua_pop(l, 1);
			} else {
				LuaError(l, "wrong tag: %s" _C_ key);
			}
		}
	}

	UpgradeModifiers[NumUpgradeModifiers++] = um;

	return 0;
}
Esempio n. 8
0
/**
**  Define a new upgrade modifier.
**
**  @param l  List of modifiers.
*/
static int CclDefineModifier(lua_State *l)
{
	const int args = lua_gettop(l);

	CUpgradeModifier *um = new CUpgradeModifier;

	memset(um->ChangeUpgrades, '?', sizeof(um->ChangeUpgrades));
	memset(um->ApplyTo, '?', sizeof(um->ApplyTo));
	um->Modifier.Variables = new CVariable[UnitTypeVar.GetNumberVariable()];
	um->ModifyPercent = new int[UnitTypeVar.GetNumberVariable()];
	memset(um->ModifyPercent, 0, UnitTypeVar.GetNumberVariable() * sizeof(int));

	std::string upgrade_ident = LuaToString(l, 1);
	um->UpgradeId = UpgradeIdByIdent(upgrade_ident);
	if (um->UpgradeId == -1) {
		LuaError(l, "Error when defining upgrade modifier: upgrade \"%s\" doesn't exist." _C_ upgrade_ident.c_str());
	}

	for (int j = 1; j < args; ++j) {
		if (!lua_istable(l, j + 1)) {
			LuaError(l, "incorrect argument");
		}
		const char *key = LuaToString(l, j + 1, 1);
#if 0 // To be removed. must modify lua file.
		if (!strcmp(key, "attack-range")) {
			key = "AttackRange";
		} else if (!strcmp(key, "sight-range")) {
			key = "SightRange";
		} else if (!strcmp(key, "basic-damage")) {
			key = "BasicDamage";
		} else if (!strcmp(key, "piercing-damage")) {
			key = "PiercingDamage";
		} else if (!strcmp(key, "armor")) {
			key = "Armor";
		} else if (!strcmp(key, "hit-points")) {
			key = "HitPoints";
		}
#endif
		if (!strcmp(key, "regeneration-rate")) {
			um->Modifier.Variables[HP_INDEX].Increase = LuaToNumber(l, j + 1, 2);
		} else if (!strcmp(key, "cost")) {
			if (!lua_istable(l, j + 1) || lua_rawlen(l, j + 1) != 2) {
				LuaError(l, "incorrect argument");
			}
			const char *value = LuaToString(l, j + 1, 1);
			const int resId = GetResourceIdByName(l, value);
			um->Modifier.Costs[resId] = LuaToNumber(l, j + 1, 2);
		} else if (!strcmp(key, "storing")) {
			if (!lua_istable(l, j + 1) || lua_rawlen(l, j + 1) != 2) {
				LuaError(l, "incorrect argument");
			}
			const char *value = LuaToString(l, j + 1, 1);
			const int resId = GetResourceIdByName(l, value);
			um->Modifier.Storing[resId] = LuaToNumber(l, j + 1, 2);
		} else if (!strcmp(key, "allow-unit")) {
			const char *value = LuaToString(l, j + 1, 2);

			if (!strncmp(value, "unit-", 5)) {
				um->ChangeUnits[UnitTypeIdByIdent(value)] = LuaToNumber(l, j + 1, 3);
			} else {
				LuaError(l, "unit expected");
			}
		} else if (!strcmp(key, "allow")) {
			const char *value = LuaToString(l, j + 1, 2);
			if (!strncmp(value, "upgrade-", 8)) {
				um->ChangeUpgrades[UpgradeIdByIdent(value)] = LuaToNumber(l, j + 1, 3);
			} else {
				LuaError(l, "upgrade expected");
			}
		} else if (!strcmp(key, "apply-to")) {
			const char *value = LuaToString(l, j + 1, 2);
			um->ApplyTo[UnitTypeIdByIdent(value)] = 'X';
		} else if (!strcmp(key, "convert-to")) {
			const char *value = LuaToString(l, j + 1, 2);
			um->ConvertTo = UnitTypeByIdent(value);
		} else if (!strcmp(key, "research-speed")) {
			um->SpeedResearch = LuaToNumber(l, j + 1, 2);
		} else {
			int index = UnitTypeVar.VariableNameLookup[key]; // variable index;
			if (index != -1) {
				if (lua_rawlen(l, j + 1) == 3) {
					const char *value = LuaToString(l, j + 1, 3);
					if (!strcmp(value, "Percent")) {
						um->ModifyPercent[index] = LuaToNumber(l, j + 1, 2);
					}
				} else {
					lua_rawgeti(l, j + 1, 2);
					if (lua_istable(l, -1)) {
						DefineVariableField(l, um->Modifier.Variables + index, -1);
					} else if (lua_isnumber(l, -1)) {
						um->Modifier.Variables[index].Enable = 1;
						um->Modifier.Variables[index].Value = LuaToNumber(l, -1);
						um->Modifier.Variables[index].Max = LuaToNumber(l, -1);
					} else {
						LuaError(l, "bad argument type for '%s'\n" _C_ key);
					}
					lua_pop(l, 1);
				}
			} else {
				LuaError(l, "wrong tag: %s" _C_ key);
			}
		}
	}

	UpgradeModifiers[NumUpgradeModifiers++] = um;

	return 0;
}