Exemple #1
0
void parseOptions(
		std::vector<Option>& options,
		const std::string& fileName,
		const std::string& fileModes,
		const std::string& accessModes,
		const std::string& mapName,
		std::set<std::string>* optionsSet,
		CLogSubsystem* logSubsystem) {

	if (!logSubsystem) {
		assert(logSubsystem);
	}

	LuaParser luaParser(fileName, fileModes, accessModes);

	const string configName = MapParser::GetMapConfigName(mapName);

	if (!mapName.empty() && !configName.empty()) {
		luaParser.GetTable("Map");
		luaParser.AddString("fileName", mapName);
		luaParser.AddString("fullName", "maps/" + mapName);
		luaParser.AddString("configFile", configName);
		luaParser.EndTable();
	}

	if (!luaParser.Execute()) {
		throw content_error("luaParser.Execute() failed: "
				+ luaParser.GetErrorLog());
	}

	const LuaTable root = luaParser.GetRoot();
	if (!root.IsValid()) {
		throw content_error("root table invalid");
	}

	std::set<std::string>* myOptionsSet = NULL;
	if (optionsSet == NULL) {
		myOptionsSet = new std::set<std::string>();
	} else {
		myOptionsSet = optionsSet;
	}
	for (int index = 1; root.KeyExists(index); index++) {
		Option opt;
		if (parseOption(root, index, opt, *myOptionsSet, *logSubsystem)) {
			options.push_back(opt);
		}
	}
	if (optionsSet == NULL) {
		delete myOptionsSet;
		myOptionsSet = NULL;
	}
}
Exemple #2
0
bool SideParser::Load()
{
	dataVec.clear();
	errorLog.clear();

	LuaParser parser("gamedata/sidedata.lua",
			SPRING_VFS_MOD_BASE, SPRING_VFS_MOD_BASE);
#if !defined UNITSYNC && !defined DEDICATED
	// this should not be included with unitsync:
	// 1. avoids linkage with LuaSyncedRead
	// 2. ModOptions are not valid during unitsync mod parsing
	parser.GetTable("Spring");
	parser.AddFunc("GetModOptions", LuaSyncedRead::GetModOptions);
	parser.EndTable();
#endif
	if (!parser.Execute()) {
		errorLog = "Side-Parser: " + parser.GetErrorLog();
		return false;
	}

	std::set<std::string> sideSet;

	const LuaTable root = parser.GetRoot();
	for (int i = 1; /* no-op */; i++) {
		const LuaTable sideTable = root.SubTable(i);
		if (!sideTable.IsValid()) {
			break;
		}

		Data data;
		data.caseName  = sideTable.GetString("name", "");
		data.sideName  = StringToLower(data.caseName);
		data.startUnit = sideTable.GetString("startUnit", "");
		data.startUnit = StringToLower(data.startUnit);

		if (data.sideName.empty()) {
			logOutput.Print("Missing side name: %i", i);
		} else if (data.startUnit.empty()) {
			logOutput.Print("Missing side start unit: " + data.sideName);
		} else if (sideSet.find(data.sideName) != sideSet.end()) {
			logOutput.Print("Duplicate side name: " + data.sideName);
		} else {
			sideSet.insert(data.sideName);
			dataVec.push_back(data);
		}
	}

	return true;
}
Exemple #3
0
bool MapParser::GetStartPos(int team, float3& pos) const
{
	if (!parser->IsValid()) {
		return false;
	}
	const LuaTable teamsTable = parser->GetRoot().SubTable("teams");
	const LuaTable posTable = teamsTable.SubTable(team).SubTable("startPos");
	if (!posTable.IsValid()) {
		return false;
	}

	pos.x = posTable.GetFloat("x", pos.x);
	pos.z = posTable.GetFloat("z", pos.z);

	return true;
}
Exemple #4
0
void parseOptions(
		std::vector<Option>& options,
		const std::string& fileName,
		const std::string& fileModes,
		const std::string& accessModes,
		std::set<std::string>* optionsSet,
		CLogSubsystem* logSubsystem) {

	if (!logSubsystem) {
		assert(logSubsystem);
	}

	LuaParser luaParser(fileName, fileModes, accessModes);

	if (!luaParser.Execute()) {
		throw content_error("luaParser.Execute() failed: "
				+ luaParser.GetErrorLog());
	}

	const LuaTable root = luaParser.GetRoot();
	if (!root.IsValid()) {
		throw content_error("root table invalid");
	}

	std::set<std::string>* myOptionsSet = NULL;
	if (optionsSet == NULL) {
		myOptionsSet = new std::set<std::string>();
	} else {
		myOptionsSet = optionsSet;
	}
	for (int index = 1; root.KeyExists(index); index++) {
		Option opt;
		try {
			parseOption(root, index, opt, *myOptionsSet);
			options.push_back(opt);
		} catch (content_error& err) {
			logOutput.Print(*logSubsystem,
					"Failed parsing option %d from %s: %s",
					index, fileName.c_str(), err.what());
		}
	}
	if (optionsSet == NULL) {
		delete myOptionsSet;
		myOptionsSet = NULL;
	}
}
Exemple #5
0
CArchiveScanner::ArchiveData CArchiveScanner::GetArchiveData(const LuaTable& archiveTable)
{
	ArchiveData md;
	if (!archiveTable.IsValid()) {
		return md;
	}

	md.name        = archiveTable.GetString("name",        "");
	md.shortName   = archiveTable.GetString("shortName",   "");
	md.version     = archiveTable.GetString("version",     "");
	md.mutator     = archiveTable.GetString("mutator",     "");
	md.game        = archiveTable.GetString("game",        "");
	md.shortGame   = archiveTable.GetString("shortGame",   "");
	md.description = archiveTable.GetString("description", "");
	md.modType     = archiveTable.GetInt("modType", 0);
	md.mapfile = archiveTable.GetString("mapfile", "");

	const LuaTable dependencies = archiveTable.SubTable("depend");
	for (int dep = 1; dependencies.KeyExists(dep); ++dep) {
		const std::string depend = dependencies.GetString(dep, "");
		md.dependencies.push_back(depend);
	}

	const LuaTable replaces = archiveTable.SubTable("replace");
	for (int rep = 1; replaces.KeyExists(rep); ++rep) {
		md.replaces.push_back(replaces.GetString(rep, ""));
	}

	// HACK needed until lobbies, lobbyserver and unitsync are sorted out
	// so they can uniquely identify different versions of the same mod.
	// (at time of this writing they use name only)

	// NOTE when changing this, this function is used both by the code that
	// reads ArchiveCache.lua and the code that reads modinfo.lua from the mod.
	// so make sure it doesn't keep adding stuff to the name everytime
	// Spring/unitsync is loaded.

	if (md.name.find(md.version) == std::string::npos && !md.version.empty()) {
		md.name += " " + md.version;
	}

	return md;
}
Exemple #6
0
bool MapParser::GetStartPos(int team, float3& pos) const
{
	errorLog.clear();

	if (!parser->IsValid()) {
		errorLog = "Map-Parser: Failed to get start position for team " + IntToString(team) + ", reason: " + parser->GetErrorLog();
		return false;
	}
	const LuaTable teamsTable = parser->GetRoot().SubTable("teams");
	const LuaTable posTable = teamsTable.SubTable(team).SubTable("startPos");
	if (!posTable.IsValid()) {
		errorLog = "Map-Parser: Failed to get start position for team " + IntToString(team) + ", reason: Not defined in the map's config!";
		return false;
	}

	pos.x = posTable.GetFloat("x", pos.x);
	pos.z = posTable.GetFloat("z", pos.z);

	return true;
}
Exemple #7
0
CFeatureHandler::CFeatureHandler()
{
	const LuaTable rootTable = game->defsParser->GetRoot().SubTable("FeatureDefs");
	if (!rootTable.IsValid()) {
		throw content_error("Error loading FeatureDefs");
	}

	// featureDefIDs start with 1
	featureDefsVector.push_back(NULL);

	// get most of the feature defs (missing trees and geovent from the map)
	vector<string> keys;
	rootTable.GetKeys(keys);
	for (int i = 0; i < (int)keys.size(); i++) {
		const string& nameMixedCase = keys[i];
		const string& nameLowerCase = StringToLower(nameMixedCase);
		const LuaTable& fdTable = rootTable.SubTable(nameMixedCase);

		AddFeatureDef(nameLowerCase, CreateFeatureDef(fdTable, nameLowerCase));
	}
}
CWeaponDefHandler::CWeaponDefHandler()
{
	const LuaTable rootTable = game->defsParser->GetRoot().SubTable("WeaponDefs");
	if (!rootTable.IsValid()) {
		throw content_error("Error loading WeaponDefs");
	}

	vector<string> weaponNames;
	rootTable.GetKeys(weaponNames);

	numWeaponDefs = weaponNames.size();
	weaponDefs = new WeaponDef[numWeaponDefs];

	for (int wid = 0; wid < numWeaponDefs; wid++) {
		WeaponDef& wd = weaponDefs[wid];
		wd.id = wid;
		wd.name = weaponNames[wid];
		weaponID[wd.name] = wid;

		const LuaTable wdTable = rootTable.SubTable(wd.name);
		ParseWeapon(wdTable, wd);
	}
}
Exemple #9
0
static void option_parseOptionsInternal(
		std::vector<Option>& options,
		LuaParser& luaParser,
		const std::string& luaSourceDesc,
		std::set<std::string>* optionsSet)
{
	if (!luaParser.Execute()) {
		throw content_error("luaParser.Execute() failed: "
				+ luaParser.GetErrorLog());
	}

	const LuaTable root = luaParser.GetRoot();
	if (!root.IsValid()) {
		throw content_error("root table invalid");
	}

	std::set<std::string>* myOptionsSet = NULL;
	if (optionsSet == NULL) {
		myOptionsSet = new std::set<std::string>();
	} else {
		myOptionsSet = optionsSet;
	}
	for (int index = 1; root.KeyExists(index); index++) {
		Option opt;
		try {
			option_parseOption(root, index, opt, *myOptionsSet);
			options.push_back(opt);
		} catch (const content_error& err) {
			LOG_L(L_WARNING, "Failed parsing option %d from %s: %s",
					index, luaSourceDesc.c_str(), err.what());
		}
	}
	if (optionsSet == NULL) {
		delete myOptionsSet;
		myOptionsSet = NULL;
	}
}
Exemple #10
0
void info_parseInfo(
		std::vector<InfoItem>& info,
		const std::string& fileName,
		const std::string& fileModes,
		const std::string& accessModes,
		std::set<std::string>* infoSet)
{
	LuaParser luaParser(fileName, fileModes, accessModes);

	if (!luaParser.Execute()) {
		throw content_error("luaParser.Execute() failed: "
				+ luaParser.GetErrorLog());
	}

	const LuaTable root = luaParser.GetRoot();
	if (!root.IsValid()) {
		throw content_error("root table invalid");
	}

	std::set<std::string>* myInfoSet = NULL;
	if (infoSet == NULL) {
		myInfoSet = new std::set<std::string>();
	} else {
		myInfoSet = infoSet;
	}
	for (int index = 1; root.KeyExists(index); index++) {
		InfoItem inf;
		if (info_parseInfoItem(root, index, inf, *myInfoSet)) {
			info.push_back(inf);
		}
	}
	if (infoSet == NULL) {
		delete myInfoSet;
		myInfoSet = NULL;
	}
}
Exemple #11
0
/** Load the messages from gamedata/messages.lua into memory. */
void CMessages::Load()
{
    LuaParser luaParser("gamedata/messages.lua",
                        SPRING_VFS_MOD_BASE, SPRING_VFS_MOD_BASE);
    if (!luaParser.Execute()) {
        // Show parse errors in the infolog.
        logOutput.Print(string("ERROR: messages.lua: ") + luaParser.GetErrorLog());
        return;
    }

    const LuaTable root = luaParser.GetRoot();

    vector<string> labels;
    root.GetKeys(labels);

    for (size_t l = 0; l < labels.size(); l++) {
        const string label = StringToLower(labels[l]);
        const LuaTable msgTable = root.SubTable(label);
        if (!msgTable.IsValid()) {
            continue;
        }
        vector<string> msgs;
        for (int s = 1; true; s++) {
            const string msg = msgTable.GetString(s, "");
            if (msg.empty()) {
                break;
            }
            msgs.push_back(msg);
        }
        if (!msgs.empty()) {
            tr[label] = msgs;
        }
    }

    loaded = true;
}
CFeatureHandler::CFeatureHandler() : nextFreeID(0)
{
	PrintLoadMsg("Loading feature definitions");

	drawQuadsX = gs->mapx/DRAW_QUAD_SIZE;
	drawQuadsY = gs->mapy/DRAW_QUAD_SIZE;
	drawQuads.resize(drawQuadsX * drawQuadsY);

	treeDrawer = CBaseTreeDrawer::GetTreeDrawer();

	const LuaTable rootTable = game->defsParser->GetRoot().SubTable("FeatureDefs");
	if (!rootTable.IsValid()) {
		throw content_error("Error loading FeatureDefs");
	}

	// get most of the feature defs (missing trees and geovent from the map)
	vector<string> keys;
	rootTable.GetKeys(keys);
	for (int i = 0; i < (int)keys.size(); i++) {
		const string& name = keys[i];
		const LuaTable fdTable = rootTable.SubTable(name);
		CreateFeatureDef(fdTable, name);
	}
}
void CWeaponDefHandler::ParseTAWeapon(const LuaTable& wdTable, WeaponDef& wd)
{
	bool lineofsight;
	bool ballistic;
	//bool twophase;
	bool beamweapon;
	bool manualBombSettings; //Allow the user to manually specify the burst and burstrate for his AircraftBomb
	//bool guided;
	//bool vlaunch;
	int rendertype;
	int color;
	int beamlaser;
	//bool tracking;
	//bool selfprop;
	//bool turret;
	//bool smokeTrail;
	//string modelName;

	wd.tdfId = wdTable.GetInt("id", 0);

	wd.filename = wdTable.GetString("filename", "unknown");
	wd.description = wdTable.GetString("name", "Weapon");
	wd.cegTag = wdTable.GetString("cegTag", "");

	wd.avoidFriendly = wdTable.GetBool("avoidFriendly", true);
	wd.avoidFeature  = wdTable.GetBool("avoidFeature",  true);

	wd.collisionFlags = 0;
	const bool collideFriendly = wdTable.GetBool("collideFriendly", true);
	const bool collideFeature  = wdTable.GetBool("collideFeature",  true);
	if (!collideFriendly) { wd.collisionFlags += COLLISION_NOFRIENDLY; }
	if (!collideFeature)  { wd.collisionFlags += COLLISION_NOFEATURE;  }

	wd.minIntensity = wdTable.GetFloat("minIntensity", 0.0f);

	wd.dropped  = wdTable.GetBool("dropped", false);
	manualBombSettings = wdTable.GetBool("manualBombSettings", false);
	lineofsight = wdTable.GetBool("lineOfSight", false);
	ballistic   = wdTable.GetBool("ballistic",  false);
	wd.twophase = wdTable.GetBool("twoPhase",   false);
	beamweapon  = wdTable.GetBool("beamWeapon", false);
	wd.guided   = wdTable.GetBool("guidance",   false);
	rendertype  = wdTable.GetInt("renderType",  0);
	color       = wdTable.GetInt("color",       0);
	beamlaser   = wdTable.GetInt("beamlaser",   0);
	wd.vlaunch  = wdTable.GetBool("vlaunch",    false);
	wd.selfprop = wdTable.GetBool("selfprop",   false);
	wd.turret   = wdTable.GetBool("turret",     false);
	wd.noSelfDamage = wdTable.GetBool("noSelfDamage", false);
	wd.visuals.modelName = wdTable.GetString("model", "");
	wd.visuals.smokeTrail = wdTable.GetBool("smokeTrail", false);
	wd.visuals.alwaysVisible = wdTable.GetBool("alwaysVisible", false);

	wd.waterweapon   = wdTable.GetBool("waterWeapon",     false);
	wd.fireSubmersed = wdTable.GetBool("fireSubmersed",   wd.waterweapon);
	wd.submissile    = wdTable.GetBool("submissile",      false);
	wd.tracks        = wdTable.GetBool("tracks",          false);
	wd.fixedLauncher = wdTable.GetBool("fixedLauncher",   false);
	wd.noExplode     = wdTable.GetBool("noExplode",       false);
	wd.isShield      = wdTable.GetBool("isShield",        false);
	wd.maxvelocity   = wdTable.GetFloat("weaponVelocity", 0.0f);
	wd.beamtime      = wdTable.GetFloat("beamTime",       1.0f);
	wd.beamburst     = wdTable.GetBool("beamburst",       false);
		
	wd.waterBounce = wdTable.GetBool("waterbounce", false);
	wd.groundBounce = wdTable.GetBool("groundbounce", false);
	wd.bounceSlip = wdTable.GetFloat("bounceslip", 1);
	wd.bounceRebound = wdTable.GetFloat("bouncerebound", 1);
	wd.numBounce = wdTable.GetInt("numbounce", -1);

	wd.thickness      = wdTable.GetFloat("thickness",       2.0f);
	wd.corethickness  = wdTable.GetFloat("coreThickness",   0.25f);
	wd.laserflaresize = wdTable.GetFloat("laserFlareSize", 15.0f);
	wd.intensity      = wdTable.GetFloat("intensity",       0.9f);
	wd.duration       = wdTable.GetFloat("duration",        0.05f);
	wd.falloffRate    = wdTable.GetFloat("fallOffRate",     0.5f);
	wd.lodDistance    = wdTable.GetInt("lodDistance", 1000);

	wd.visuals.sizeDecay  = wdTable.GetFloat("sizeDecay",  0.0f);
	wd.visuals.alphaDecay = wdTable.GetFloat("alphaDecay", 1.0f);
	wd.visuals.separation = wdTable.GetFloat("separation", 1.0f);
	wd.visuals.noGap  = wdTable.GetBool("noGap", true);
	wd.visuals.stages = wdTable.GetInt("stages", 5);

	if (wd.name.find("disintegrator") != string::npos) {	//fulhack
		wd.visuals.renderType = WEAPON_RENDERTYPE_FIREBALL;
	} else if (wd.visuals.modelName.compare("") != 0) {
		wd.visuals.renderType = WEAPON_RENDERTYPE_MODEL;
	} else if (beamweapon) {
		wd.visuals.renderType = WEAPON_RENDERTYPE_LASER;
	} else {
		wd.visuals.renderType = WEAPON_RENDERTYPE_PLASMA;
	}

	wd.gravityAffected = false;
	if (wd.dropped || ballistic) {
		wd.gravityAffected = true;
	}

	if (wd.dropped) {
		wd.type = "AircraftBomb";

	}	else if (wd.vlaunch) {
		wd.type = "StarburstLauncher";

	}	else if (beamlaser) {
		wd.type = "BeamLaser";

	}	else if (wd.isShield) {
		wd.type = "Shield";

	} else if (wd.waterweapon) {
		wd.type = "TorpedoLauncher";

	} else if (wd.name.find("disintegrator") != string::npos) {
		wd.type = "DGun";

	} else if (lineofsight) {
		if (rendertype==7) {
			wd.type = "LightingCannon";
		} else if (beamweapon) {
			wd.type = "LaserCannon";
		} else if (wd.visuals.modelName.find("laser") != string::npos) {
			wd.type = "LaserCannon";		//swta fix
		} else if (/*selfprop && */wd.visuals.smokeTrail) {
			wd.type = "MissileLauncher";
		} else if (rendertype == 4 && color == 2) {
			wd.type = "EmgCannon";
		} else if (rendertype == 5) {
			wd.type = "Flame";
		//	} else if(rendertype == 1) {
		//		wd.type = "MissileLauncher";
		} else {
			wd.type = "Cannon";
		}
	} else {
		wd.type = "Cannon";
	}

	string ttype = wdTable.GetString("weaponType", "");
	if (ttype != "") {
		wd.type = ttype;
	}

//	logOutput.Print("%s as %s",weaponname.c_str(),wd.type.c_str());

	const bool melee = (wd.type == "Melee");
	wd.targetBorder = wdTable.GetFloat("targetBorder", melee ? 1.0f : 0.0f);
	if (wd.targetBorder > 1.0f) {
		logOutput.Print("warning: targetBorder truncated to 1 (was %f)", wd.targetBorder);
		wd.targetBorder = 1.0f;
	} else if (wd.targetBorder < -1.0f) {
		logOutput.Print("warning: targetBorder truncated to -1 (was %f)", wd.targetBorder);
		wd.targetBorder = -1.0f;
	}
	wd.cylinderTargetting = wdTable.GetFloat("cylinderTargetting", melee ? 1.0f : 0.0f);

	wd.range = wdTable.GetFloat("range", 10.0f);
	const float accuracy       = wdTable.GetFloat("accuracy",   0.0f);
	const float sprayangle     = wdTable.GetFloat("sprayAngle", 0.0f);
	const float movingAccuracy = wdTable.GetFloat("movingAccuracy", accuracy);
	// should really be tan but TA seem to cap it somehow
	// should also be 7fff or ffff theoretically but neither seems good
	wd.accuracy       = sin((accuracy)       * PI / 0xafff);
	wd.sprayangle     = sin((sprayangle)     * PI / 0xafff);
	wd.movingAccuracy = sin((movingAccuracy) * PI / 0xafff);

	wd.targetMoveError = wdTable.GetFloat("targetMoveError", 0.0f);
	wd.leadLimit = wdTable.GetFloat("leadLimit", -1.0f);
	wd.leadBonus = wdTable.GetFloat("leadBonus", 0.0f);

	// setup the default damages
	const LuaTable dmgTable = wdTable.SubTable("damage");
	float defDamage = dmgTable.GetFloat("default", 0.0f);
	if (defDamage == 0.0f) {
		defDamage = 1.0f; //avoid division by zeroes
	}
	for (int a = 0; a < damageArrayHandler->GetNumTypes(); ++a) {
		wd.damages[a] = defDamage;
	}

	map<string, float> damages;
	dmgTable.GetMap(damages);
	
	map<string, float>::const_iterator di;
	for (di = damages.begin(); di != damages.end(); ++di) {
		const int type = damageArrayHandler->GetTypeFromName(di->first);
		if (type != 0) {
			float dmg = di->second;
			if (dmg != 0.0f) {
				wd.damages[type] = dmg;
			} else {
				wd.damages[type] = 1.0f;
			}
		}
	}
	
	wd.damages.impulseFactor = wdTable.GetFloat("impulseFactor", 1.0f);
	wd.damages.impulseBoost  = wdTable.GetFloat("impulseBoost",  0.0f);
	wd.damages.craterMult    = wdTable.GetFloat("craterMult",  wd.damages.impulseFactor);
	wd.damages.craterBoost   = wdTable.GetFloat("craterBoost", 0.0f);

	wd.areaOfEffect = wdTable.GetFloat("areaOfEffect", 8.0f) * 0.5f;
	wd.edgeEffectiveness = wdTable.GetFloat("edgeEffectiveness", 0.0f);
	// prevent 0/0 division in CGameHelper::Explosion
	if (wd.edgeEffectiveness > 0.999f) {
		wd.edgeEffectiveness = 0.999f;
	}

	wd.projectilespeed = wdTable.GetFloat("weaponVelocity", 0.0f) / GAME_SPEED;
	wd.startvelocity = max(0.01f, wdTable.GetFloat("startVelocity", 0.0f) / GAME_SPEED);
	wd.weaponacceleration = wdTable.GetFloat("weaponAcceleration", 0.0f) / GAME_SPEED / GAME_SPEED;
	wd.reload = wdTable.GetFloat("reloadtime", 1.0f);
	wd.salvodelay = wdTable.GetFloat("burstrate", 0.1f);
	wd.salvosize = wdTable.GetInt("burst", 1);
	wd.projectilespershot = wdTable.GetInt("projectiles", 1);
	wd.maxAngle = wdTable.GetFloat("tolerance", 3000.0f) * 180.0f / 0x7fff;
	wd.restTime = 0.0f;
	wd.metalcost = wdTable.GetFloat("metalpershot", 0.0f);
	wd.energycost = wdTable.GetFloat("energypershot", 0.0f);
	wd.selfExplode = wdTable.GetBool("burnblow", false);
	wd.predictBoost = wdTable.GetFloat("predictBoost", wd.selfExplode ? 0.5f : 0.0f);
	wd.sweepFire = wdTable.GetBool("sweepfire", false);
	wd.canAttackGround = wdTable.GetBool("canattackground", true);
	wd.myGravity = wdTable.GetFloat("myGravity", 0.0f);

	wd.fireStarter = wdTable.GetFloat("fireStarter", 0.0f) * 0.01f;
	wd.paralyzer = wdTable.GetBool("paralyzer", false);
	if (wd.paralyzer) {
		wd.damages.paralyzeDamageTime = max(0, wdTable.GetInt("paralyzeTime", 10));
	} else {
		wd.damages.paralyzeDamageTime = 0;
	}

	const float defShake = wd.paralyzer ? 0.0f : wd.damages.GetDefaultDamage();
	wd.cameraShake = wdTable.GetFloat("cameraShake", defShake);
	wd.cameraShake = max(0.0f, wd.cameraShake);

	wd.soundTrigger = wdTable.GetBool("soundTrigger", false);

	//sunparser->GetDef(wd.highTrajectory, "0", weaponname + "minbarrelangle");
	wd.stockpile     = wdTable.GetBool("stockpile", false);
	wd.interceptor   = wdTable.GetInt("interceptor", 0);
	wd.targetable    = wdTable.GetInt("targetable",  0);
	wd.manualfire    = wdTable.GetBool("commandfire", false);
	wd.coverageRange = wdTable.GetFloat("coverage", 0.0f);

	// FIXME -- remove the old style ?
	LuaTable shTable = wdTable.SubTable("shield");
	const float3 shieldBadColor (1.0f, 0.5f, 0.5f);
	const float3 shieldGoodColor(0.5f, 0.5f, 1.0f);
	if (shTable.IsValid()) {
		wd.shieldRepulser         = shTable.GetBool("repulser",       false);
		wd.smartShield            = shTable.GetBool("smart",          false);
		wd.exteriorShield         = shTable.GetBool("exterior",       false);
		wd.visibleShield          = shTable.GetBool("visible",        false);
		wd.visibleShieldRepulse   = shTable.GetBool("visibleRepulse", false);
		wd.visibleShieldHitFrames = shTable.GetInt("visibleHitFrames", 0);
		wd.shieldEnergyUse        = shTable.GetFloat("energyUse",        0.0f);
		wd.shieldForce            = shTable.GetFloat("force",            0.0f);
		wd.shieldRadius           = shTable.GetFloat("radius",           0.0f);
		wd.shieldMaxSpeed         = shTable.GetFloat("maxSpeed",         0.0f);
		wd.shieldPower            = shTable.GetFloat("power",            0.0f);
		wd.shieldPowerRegen       = shTable.GetFloat("powerRegen",       0.0f);
		wd.shieldPowerRegenEnergy = shTable.GetFloat("powerRegenEnergy", 0.0f);
		wd.shieldStartingPower    = shTable.GetFloat("startingPower",    0.0f);
		wd.shieldInterceptType    = shTable.GetInt("interceptType", 0);
		wd.shieldBadColor         = shTable.GetFloat3("badColor",  shieldBadColor);
		wd.shieldGoodColor        = shTable.GetFloat3("goodColor", shieldGoodColor);
		wd.shieldAlpha            = shTable.GetFloat("alpha", 0.2f);
	}
	else {
		wd.shieldRepulser         = wdTable.GetBool("shieldRepulser",       false);
		wd.smartShield            = wdTable.GetBool("smartShield",          false);
		wd.exteriorShield         = wdTable.GetBool("exteriorShield",       false);
		wd.visibleShield          = wdTable.GetBool("visibleShield",        false);
		wd.visibleShieldRepulse   = wdTable.GetBool("visibleShieldRepulse", false);
		wd.visibleShieldHitFrames = wdTable.GetInt("visibleShieldHitFrames", 0);
		wd.shieldEnergyUse        = wdTable.GetFloat("shieldEnergyUse",        0.0f);
		wd.shieldForce            = wdTable.GetFloat("shieldForce",            0.0f);
		wd.shieldRadius           = wdTable.GetFloat("shieldRadius",           0.0f);
		wd.shieldMaxSpeed         = wdTable.GetFloat("shieldMaxSpeed",         0.0f);
		wd.shieldPower            = wdTable.GetFloat("shieldPower",            0.0f);
		wd.shieldPowerRegen       = wdTable.GetFloat("shieldPowerRegen",       0.0f);
		wd.shieldPowerRegenEnergy = wdTable.GetFloat("shieldPowerRegenEnergy", 0.0f);
		wd.shieldStartingPower    = wdTable.GetFloat("shieldStartingPower",    0.0f);
		wd.shieldInterceptType    = wdTable.GetInt("shieldInterceptType", 0);
		wd.shieldBadColor  = wdTable.GetFloat3("shieldBadColor",  shieldBadColor);
		wd.shieldGoodColor = wdTable.GetFloat3("shieldGoodColor", shieldGoodColor);
		wd.shieldAlpha = wdTable.GetFloat("shieldAlpha", 0.2f);
	}


	int defInterceptType = 0;
	if (wd.type == "Cannon") {
		defInterceptType = 1;
	} else if ((wd.type == "LaserCannon") || (wd.type == "BeamLaser")) {
		defInterceptType = 2;
	} else if ((wd.type == "StarburstLauncher") || (wd.type == "MissileLauncher")) {
		defInterceptType = 4;
	}
	wd.interceptedByShieldType = wdTable.GetInt("interceptedByShieldType", defInterceptType);

	wd.wobble = wdTable.GetFloat("wobble", 0.0f) * PI / 0x7fff / 30.0f;
	wd.dance = wdTable.GetFloat("dance", 0.0f) / GAME_SPEED;
	wd.trajectoryHeight = wdTable.GetFloat("trajectoryHeight", 0.0f);

	wd.noAutoTarget = (wd.manualfire || wd.interceptor || wd.isShield);

	wd.onlyTargetCategory = 0xffffffff;
	if (wdTable.GetBool("toAirWeapon", false)) {
		// fix if we sometime call aircrafts otherwise
		wd.onlyTargetCategory = CCategoryHandler::Instance()->GetCategories("VTOL");
		//logOutput.Print("air only weapon %s %i",weaponname.c_str(),wd.onlyTargetCategory);
	}

	wd.largeBeamLaser = wdTable.GetBool("largeBeamLaser", false);
	wd.visuals.tilelength  = wdTable.GetFloat("tileLength", 200.0f);
	wd.visuals.scrollspeed = wdTable.GetFloat("scrollSpeed",  5.0f);
	wd.visuals.pulseSpeed  = wdTable.GetFloat("pulseSpeed",   1.0f);
	wd.visuals.beamdecay   = wdTable.GetFloat("beamDecay",    1.0f);
	wd.visuals.beamttl     = wdTable.GetInt("beamTTL", 0);

	if (wd.type == "Cannon") {
		wd.heightmod = wdTable.GetFloat("heightMod", 0.8f);
	} else if (wd.type == "BeamLaser") {
		wd.heightmod = wdTable.GetFloat("heightMod", 1.0f);
	} else {
		wd.heightmod = wdTable.GetFloat("heightMod", 0.2f);
	}

	wd.supplycost = 0.0f;

	wd.onlyForward = !wd.turret && (wd.type != "StarburstLauncher");

	const int color2 = wdTable.GetInt("color2", 0);

	const float3 rgbcol = hs2rgb(color / float(255), color2 / float(255));
	wd.visuals.color  = wdTable.GetFloat3("rgbColor",  rgbcol);
	wd.visuals.color2 = wdTable.GetFloat3("rgbColor2", float3(1.0f, 1.0f, 1.0f));

	wd.uptime = wdTable.GetFloat("weaponTimer", 0.0f);
	wd.flighttime = wdTable.GetInt("flightTime", 0) * 32;

	wd.turnrate = wdTable.GetFloat("turnRate", 0.0f) * PI / 0x7fff / 30.0f;

	if ((wd.type == "AircraftBomb") && !manualBombSettings) {
		if (wd.reload < 0.5f) {
			wd.salvodelay = min(0.2f, wd.reload);
			wd.salvosize = (int)(1 / wd.salvodelay) + 1;
			wd.reload = 5;
		} else {
			wd.salvodelay = min(0.4f, wd.reload);
			wd.salvosize = 2;
		}
	}
	//if(!wd.turret && (wd.type != "TorpedoLauncher")) {
	//	wd.maxAngle*=0.4f;
	//}

	//2+min(damages[0]*0.0025f,weaponDef->areaOfEffect*0.1f)
	const float tempsize = 2.0f + min(wd.damages[0] * 0.0025f, wd.areaOfEffect * 0.1f);
	wd.size = wdTable.GetFloat("size", tempsize);
	wd.sizeGrowth = wdTable.GetFloat("sizeGrowth", 0.2f);
	wd.collisionSize = wdTable.GetFloat("collisionSize", 0.05f);

	wd.visuals.colorMap = 0;
	const string colormap = wdTable.GetString("colormap", "");
	if (colormap != "") {
		wd.visuals.colorMap = CColorMap::LoadFromDefString(colormap);
	}

	wd.heightBoostFactor = wdTable.GetFloat("heightBoostFactor", -1.0f);
	wd.proximityPriority = wdTable.GetFloat("proximityPriority", 1.0f);

	// get some weapon specific defaults
	if (wd.type == "Cannon") {
		// CExplosiveProjectile
		wd.visuals.texture1 = &ph->plasmatex;
		wd.visuals.color = wdTable.GetFloat3("rgbColor", float3(1.0f,0.5f,0.0f));
		wd.intensity = wdTable.GetFloat("intensity", 0.2f);
	} else if (wd.type == "Rifle") {
		// ...
	} else if (wd.type == "Melee") {
		// ...
	} else if (wd.type == "AircraftBomb") {
		// CExplosiveProjectile or CTorpedoProjectile
		wd.visuals.texture1 = &ph->plasmatex;
	} else if (wd.type == "Shield") {
		wd.visuals.texture1 = &ph->perlintex;
	} else if (wd.type == "Flame") {
		// CFlameProjectile
		wd.visuals.texture1 = &ph->flametex;
		wd.size          = wdTable.GetFloat("size",      tempsize);
		wd.sizeGrowth    = wdTable.GetFloat("sizeGrowth",    0.5f);
		wd.collisionSize = wdTable.GetFloat("collisionSize", 0.5f);
		wd.duration      = wdTable.GetFloat("flameGfxTime",  1.2f);

		if (wd.visuals.colorMap == 0) {
			wd.visuals.colorMap = CColorMap::Load12f(1.000f, 1.000f, 1.000f, 0.100f,
			                                         0.025f, 0.025f, 0.025f, 0.100f,
			                                         0.000f, 0.000f, 0.000f, 0.000f);
		}

	} else if (wd.type == "MissileLauncher") {
		// CMissileProjectile
		wd.visuals.texture1 = &ph->missileflaretex;
		wd.visuals.texture2 = &ph->missiletrailtex;
	} else if (wd.type == "TorpedoLauncher") {
		// CExplosiveProjectile or CTorpedoProjectile
		wd.visuals.texture1 = &ph->plasmatex;
	} else if (wd.type == "LaserCannon") {
		// CLaserProjectile
		wd.visuals.texture1 = &ph->laserfallofftex;
		wd.visuals.texture2 = &ph->laserendtex;
		wd.visuals.hardStop = wdTable.GetBool("hardstop", false);
		wd.collisionSize = wdTable.GetFloat("collisionSize", 0.5f);
	} else if (wd.type == "BeamLaser") {
		if (wd.largeBeamLaser) {
			wd.visuals.texture1 = ph->textureAtlas->GetTexturePtr("largebeam");
			wd.visuals.texture2 = &ph->laserendtex;
			wd.visuals.texture3 = ph->textureAtlas->GetTexturePtr("muzzleside");
			wd.visuals.texture4 = &ph->beamlaserflaretex;
		} else {
			wd.visuals.texture1 = &ph->laserfallofftex;
			wd.visuals.texture2 = &ph->laserendtex;
			wd.visuals.texture3 = &ph->beamlaserflaretex;
		}
	} else if (wd.type == "LightingCannon") {
		wd.visuals.texture1 = &ph->laserfallofftex;
		wd.thickness = wdTable.GetFloat("thickness", 0.8f);
	} else if (wd.type == "EmgCannon") {
		// CEmgProjectile
		wd.visuals.texture1 = &ph->plasmatex;
		wd.visuals.color = wdTable.GetFloat3("rgbColor", float3(0.9f,0.9f,0.2f)); 
		wd.size = wdTable.GetFloat("size", 3.0f);
	} else if (wd.type == "DGun") {
		// CFireBallProjectile
		wd.collisionSize = wdTable.GetFloat("collisionSize", 10.0f);
	} else if (wd.type == "StarburstLauncher") {
		// CStarburstProjectile
		wd.visuals.texture1 = &ph->sbflaretex;
		wd.visuals.texture2 = &ph->sbtrailtex;
		wd.visuals.texture3 = &ph->explotex;
	} else {
		wd.visuals.texture1 = &ph->plasmatex;
		wd.visuals.texture2 = &ph->plasmatex;
	}

	// FIXME -- remove the 'textureN' format?
	LuaTable texTable = wdTable.SubTable("textures");
	string texName;
	texName = wdTable.GetString("texture1", "");
	texName = texTable.GetString(1, texName);
	if (texName != "") {
		wd.visuals.texture1 = ph->textureAtlas->GetTexturePtr(texName);
	}
	texName = wdTable.GetString("texture2", "");
	texName = texTable.GetString(2, texName);
	if (texName != "") {
		wd.visuals.texture2 = ph->textureAtlas->GetTexturePtr(texName);
	}
	texName = wdTable.GetString("texture3", "");
	texName = texTable.GetString(3, texName);
	if (texName != "") {
		wd.visuals.texture3 = ph->textureAtlas->GetTexturePtr(texName);
	}
	texName = wdTable.GetString("texture4", "");
	texName = texTable.GetString(4, texName);
	if (texName != "") {
		wd.visuals.texture4 = ph->textureAtlas->GetTexturePtr(texName);
	}

	const string expGenTag = wdTable.GetString("explosionGenerator", "");
	if (expGenTag.empty()) {
		wd.explosionGenerator = NULL;
	} else {
		wd.explosionGenerator = explGenHandler->LoadGenerator(expGenTag);
	}
	const string bounceExpGenTag = wdTable.GetString("bounceExplosionGenerator", "");
	if (bounceExpGenTag.empty()) {
		wd.bounceExplosionGenerator = NULL;
	} else {
		wd.bounceExplosionGenerator = explGenHandler->LoadGenerator(bounceExpGenTag);
	}

	const float gd = max(30.0f, wd.damages[0] / 20.0f);
	const float defExpSpeed = (8.0f + (gd * 2.5f)) / (9.0f + (sqrtf(gd) * 0.7f)) * 0.5f;
	wd.explosionSpeed = wdTable.GetFloat("explosionSpeed", defExpSpeed);

	// Dynamic Damage
	wd.dynDamageInverted = wdTable.GetBool("dynDamageInverted", false);
	wd.dynDamageExp      = wdTable.GetFloat("dynDamageExp",   0.0f);
	wd.dynDamageMin      = wdTable.GetFloat("dynDamageMin",   0.0f);
	wd.dynDamageRange    = wdTable.GetFloat("dynDamageRange", 0.0f);

	LoadSound(wdTable, wd.firesound, "firesound");
	LoadSound(wdTable, wd.soundhit,  "soundhit");

	if ((wd.firesound.getVolume(0) == -1.0f) ||
	    (wd.soundhit.getVolume(0)  == -1.0f)) {
		// no volume (-1.0f) read from weapon definition, set it dynamically here
		if (wd.damages[0] <= 50.0f) {
			wd.soundhit.setVolume(0, 5.0f);
			wd.firesound.setVolume(0, 5.0f);
		}
		else {
			float soundVolume = sqrt(wd.damages[0] * 0.5f);

			if (wd.type == "LaserCannon") {
				soundVolume *= 0.5f;
			}

			float hitSoundVolume = soundVolume;

			if ((soundVolume > 100.0f) &&
			    ((wd.type == "MissileLauncher") ||
			     (wd.type == "StarburstLauncher"))) {
				soundVolume = 10.0f * sqrt(soundVolume);
			}

			if (wd.firesound.getVolume(0) == -1.0f) {
				wd.firesound.setVolume(0, soundVolume);
			}

			soundVolume = hitSoundVolume;

			if (wd.areaOfEffect > 8.0f) {
				soundVolume *= 2.0f;
			}
			if (wd.type == "DGun") {
				soundVolume *= 0.15f;
			}
			if (wd.soundhit.getVolume(0) == -1.0f) {
				wd.soundhit.setVolume(0, soundVolume);
			}
		}
	}
}
/*
 * CArchiveScanner::ArchiveData
 */
CArchiveScanner::ArchiveData::ArchiveData(const LuaTable& archiveTable)
{
	if (!archiveTable.IsValid()) {
		return;
	}

	std::vector<std::string> keys;
	if (!archiveTable.GetKeys(keys)) {
		return;
	}

	std::vector<std::string>::const_iterator key;
	for (key = keys.begin(); key != keys.end(); ++key) {
		const std::string& keyLower = StringToLower(*key);
		if (!ArchiveData::IsReservedKey(keyLower)) {
			if (keyLower == "modtype") {
				SetInfoItemValueInteger(*key, archiveTable.GetInt(*key, 0));
				continue;
			}
			
			const int luaType = archiveTable.GetType(*key);
			switch (luaType) {
				case LuaTable::STRING: {
					SetInfoItemValueString(*key, archiveTable.GetString(*key, ""));
				} break;
				case LuaTable::NUMBER: {
					SetInfoItemValueFloat(*key, archiveTable.GetFloat(*key, 0.0f));
				} break;
				case LuaTable::BOOLEAN: {
					SetInfoItemValueBool(*key, archiveTable.GetBool(*key, false));
				} break;
				default: {
					// just ignore unsupported types (most likely to be lua-tables)
					//throw content_error("Lua-type " + IntToString(luaType) + " not supported in archive-info, but it is used on key \"" + *key + "\"");
				} break;
			}
		}
	}

	const LuaTable _dependencies = archiveTable.SubTable("depend");
	for (int dep = 1; _dependencies.KeyExists(dep); ++dep) {
		dependencies.push_back(_dependencies.GetString(dep, ""));
	}

	const LuaTable _replaces = archiveTable.SubTable("replace");
	for (int rep = 1; _replaces.KeyExists(rep); ++rep) {
		replaces.push_back(_replaces.GetString(rep, ""));
	}

	//! FIXME
	//! XXX HACK needed until lobbies, lobbyserver and unitsync are sorted out
	//! so they can uniquely identify different versions of the same mod.
	//! (at time of this writing they use name only)

	//! NOTE when changing this, this function is used both by the code that
	//! reads ArchiveCache.lua and the code that reads modinfo.lua from the mod.
	//! so make sure it doesn't keep adding stuff to the name everytime
	//! Spring/unitsync is loaded.

	const std::string& name = GetName();
	const std::string& version = GetVersion();
	if ((name.find(version) == std::string::npos) && !version.empty()) {
		SetInfoItemValueString("name", name + " " + version);
	}
}
Exemple #15
0
CProjectileDrawer::CProjectileDrawer(): CEventClient("[CProjectileDrawer]", 123456, false) {
	eventHandler.AddClient(this);

	loadscreen->SetLoadMessage("Creating Projectile Textures");

	textureAtlas = new CTextureAtlas(2048, 2048);

	// used to block resources_map.tdf from loading textures
	std::set<std::string> blockMapTexNames;

	LuaParser resourcesParser("gamedata/resources.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP);
	resourcesParser.Execute();

	const LuaTable rootTable = resourcesParser.GetRoot();
	const LuaTable gfxTable = rootTable.SubTable("graphics");
	const LuaTable ptTable = gfxTable.SubTable("projectileTextures");

	// add all textures in projectiletextures section
	std::map<std::string, std::string> ptex;
	ptTable.GetMap(ptex);

	for (std::map<std::string, std::string>::iterator pi = ptex.begin(); pi != ptex.end(); ++pi) {
		textureAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
		blockMapTexNames.insert(StringToLower(pi->first));
	}
	ptex.clear();

	// add all texture from sections within projectiletextures section
	std::vector<std::string> seclist;
	ptTable.GetKeys(seclist);

	for (size_t i = 0; i < seclist.size(); i++) {
		const LuaTable ptSubTable = ptTable.SubTable(seclist[i]);

		if (ptSubTable.IsValid()) {
			ptSubTable.GetMap(ptex);

			for (std::map<std::string, std::string>::iterator pi = ptex.begin(); pi != ptex.end(); ++pi) {
				textureAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
				blockMapTexNames.insert(StringToLower(pi->first));
			}
			ptex.clear();
		}
	}

	// get the smoke textures, hold the count in 'smokeCount'
	const LuaTable smokeTable = gfxTable.SubTable("smoke");
	int smokeCount;

	if (smokeTable.IsValid()) {
		for (smokeCount = 0; true; smokeCount++) {
			const std::string tex = smokeTable.GetString(smokeCount + 1, "");
			if (tex.empty()) {
				break;
			}
			const std::string texName = "bitmaps/" + tex;
			const std::string smokeName = "ismoke" + IntToString(smokeCount, "%02i");

			textureAtlas->AddTexFromFile(smokeName, texName);
			blockMapTexNames.insert(StringToLower(smokeName));
		}
	} else {
		// setup the defaults
		for (smokeCount = 0; smokeCount < 12; smokeCount++) {
			const std::string smokeNum = IntToString(smokeCount, "%02i");
			const std::string smokeName = "ismoke" + smokeNum;
			const std::string texName = "bitmaps/smoke/smoke" + smokeNum + ".tga";

			textureAtlas->AddTexFromFile(smokeName, texName);
			blockMapTexNames.insert(StringToLower(smokeName));
		}
	}

	if (smokeCount <= 0) {
		throw content_error("missing smoke textures");
	}

	char tex[128][128][4];
	for (int y = 0; y < 128; y++) { // shield
		for (int x = 0; x < 128; x++) {
			tex[y][x][0] = 70;
			tex[y][x][1] = 70;
			tex[y][x][2] = 70;
			tex[y][x][3] = 70;
		}
	}

	textureAtlas->AddTexFromMem("perlintex", 128, 128, CTextureAtlas::RGBA32, tex);
	blockMapTexNames.insert("perlintex");

	blockMapTexNames.insert("flare");
	blockMapTexNames.insert("explo");
	blockMapTexNames.insert("explofade");
	blockMapTexNames.insert("heatcloud");
	blockMapTexNames.insert("laserend");
	blockMapTexNames.insert("laserfalloff");
	blockMapTexNames.insert("randdots");
	blockMapTexNames.insert("smoketrail");
	blockMapTexNames.insert("wake");
	blockMapTexNames.insert("perlintex");
	blockMapTexNames.insert("flame");

	blockMapTexNames.insert("sbtrailtexture");
	blockMapTexNames.insert("missiletrailtexture");
	blockMapTexNames.insert("muzzleflametexture");
	blockMapTexNames.insert("repulsetexture");
	blockMapTexNames.insert("dguntexture");
	blockMapTexNames.insert("flareprojectiletexture");
	blockMapTexNames.insert("sbflaretexture");
	blockMapTexNames.insert("missileflaretexture");
	blockMapTexNames.insert("beamlaserflaretexture");
	blockMapTexNames.insert("bubbletexture");
	blockMapTexNames.insert("geosquaretexture");
	blockMapTexNames.insert("gfxtexture");
	blockMapTexNames.insert("projectiletexture");
	blockMapTexNames.insert("repulsegfxtexture");
	blockMapTexNames.insert("sphereparttexture");
	blockMapTexNames.insert("torpedotexture");
	blockMapTexNames.insert("wrecktexture");
	blockMapTexNames.insert("plasmatexture");


	// allow map specified atlas textures for gaia unit projectiles
	LuaParser mapResParser("gamedata/resources_map.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP);
	
	if (mapResParser.Execute()) {
		const LuaTable mapRoot = mapResParser.GetRoot();
		const LuaTable mapTable = mapRoot.SubTable("projectileTextures");

		// add all textures in projectiletextures section
		std::map<std::string, std::string>::iterator pi;

		mapTable.GetMap(ptex);

		for (pi = ptex.begin(); pi != ptex.end(); ++pi) {
			if (blockMapTexNames.find(StringToLower(pi->first)) == blockMapTexNames.end()) {
				textureAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
			}
		}
		ptex.clear();

		// add all texture from sections within projectiletextures section
		mapTable.GetKeys(seclist);
		for (size_t i = 0; i < seclist.size(); i++) {
			const LuaTable mapSubTable = mapTable.SubTable(seclist[i]);
			if (mapSubTable.IsValid()) {
				mapSubTable.GetMap(ptex);
				for (pi = ptex.begin(); pi != ptex.end(); ++pi) {
					if (blockMapTexNames.find(StringToLower(pi->first)) == blockMapTexNames.end()) {
						textureAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
					}
				}
				ptex.clear();
			}
		}
	}

	if (!textureAtlas->Finalize()) {
		LOG_L(L_ERROR, "Could not finalize projectile texture atlas. Use less/smaller textures.");
	}

	flaretex        = textureAtlas->GetTexturePtr("flare");
	explotex        = textureAtlas->GetTexturePtr("explo");
	explofadetex    = textureAtlas->GetTexturePtr("explofade");
	heatcloudtex    = textureAtlas->GetTexturePtr("heatcloud");
	laserendtex     = textureAtlas->GetTexturePtr("laserend");
	laserfallofftex = textureAtlas->GetTexturePtr("laserfalloff");
	randdotstex     = textureAtlas->GetTexturePtr("randdots");
	smoketrailtex   = textureAtlas->GetTexturePtr("smoketrail");
	waketex         = textureAtlas->GetTexturePtr("wake");
	perlintex       = textureAtlas->GetTexturePtr("perlintex");
	flametex        = textureAtlas->GetTexturePtr("flame");

	for (int i = 0; i < smokeCount; i++) {
		const std::string smokeName = "ismoke" + IntToString(i, "%02i");
		smoketex.push_back(textureAtlas->GetTexturePtr(smokeName));
	}

#define GETTEX(t, b) (textureAtlas->GetTexturePtrWithBackup((t), (b)))
	sbtrailtex         = GETTEX("sbtrailtexture",         "smoketrail"    );
	missiletrailtex    = GETTEX("missiletrailtexture",    "smoketrail"    );
	muzzleflametex     = GETTEX("muzzleflametexture",     "explo"         );
	repulsetex         = GETTEX("repulsetexture",         "explo"         );
	dguntex            = GETTEX("dguntexture",            "flare"         );
	flareprojectiletex = GETTEX("flareprojectiletexture", "flare"         );
	sbflaretex         = GETTEX("sbflaretexture",         "flare"         );
	missileflaretex    = GETTEX("missileflaretexture",    "flare"         );
	beamlaserflaretex  = GETTEX("beamlaserflaretexture",  "flare"         );
	bubbletex          = GETTEX("bubbletexture",          "circularthingy");
	geosquaretex       = GETTEX("geosquaretexture",       "circularthingy");
	gfxtex             = GETTEX("gfxtexture",             "circularthingy");
	projectiletex      = GETTEX("projectiletexture",      "circularthingy");
	repulsegfxtex      = GETTEX("repulsegfxtexture",      "circularthingy");
	sphereparttex      = GETTEX("sphereparttexture",      "circularthingy");
	torpedotex         = GETTEX("torpedotexture",         "circularthingy");
	wrecktex           = GETTEX("wrecktexture",           "circularthingy");
	plasmatex          = GETTEX("plasmatexture",          "circularthingy");
#undef GETTEX


	groundFXAtlas = new CTextureAtlas(2048, 2048);
	// add all textures in groundfx section
	const LuaTable groundfxTable = gfxTable.SubTable("groundfx");
	groundfxTable.GetMap(ptex);

	for (std::map<std::string, std::string>::iterator pi = ptex.begin(); pi != ptex.end(); ++pi) {
		groundFXAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
	}
	ptex.clear();

	// add all textures from sections within groundfx section
	groundfxTable.GetKeys(seclist);

	for (size_t i = 0; i < seclist.size(); i++) {
		const LuaTable gfxSubTable = groundfxTable.SubTable(seclist[i]);

		if (gfxSubTable.IsValid()) {
			gfxSubTable.GetMap(ptex);

			for (std::map<std::string, std::string>::iterator pi = ptex.begin(); pi != ptex.end(); ++pi) {
				groundFXAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
			}
			ptex.clear();
		}
	}

	if (!groundFXAtlas->Finalize()) {
		LOG_L(L_ERROR, "Could not finalize groundFX texture atlas. Use less/smaller textures.");
	}

	groundflashtex = groundFXAtlas->GetTexturePtr("groundflash");
	groundringtex = groundFXAtlas->GetTexturePtr("groundring");
	seismictex = groundFXAtlas->GetTexturePtr("seismic");

	for (int a = 0; a < 4; ++a) {
		perlinBlend[a]=0;
	}

	unsigned char tempmem[4 * 16 * 16];
	for (int a = 0; a < 4 * 16 * 16; ++a) {
		tempmem[a] = 0;
	}
	for (int a = 0; a < 8; ++a) {
		glGenTextures(1, &perlinTex[a]);
		glBindTexture(GL_TEXTURE_2D, perlinTex[a]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16,16, 0, GL_RGBA, GL_UNSIGNED_BYTE, tempmem);
	}

	drawPerlinTex = false;

	if (perlinFB.IsValid()) {
		// we never refresh the full texture (just the perlin part). So we need to reload it then.
		perlinFB.reloadOnAltTab = true;

		perlinFB.Bind();
		perlinFB.AttachTexture(textureAtlas->gltex);
		drawPerlinTex = perlinFB.CheckStatus("PERLIN");
		perlinFB.Unbind();
	}


	modelRenderers.resize(MODELTYPE_OTHER, NULL);

	for (int modelType = MODELTYPE_3DO; modelType < MODELTYPE_OTHER; modelType++) {
		modelRenderers[modelType] = IWorldObjectModelRenderer::GetInstance(modelType);
	}
}
void CMapInfo::ReadWater()
{
	const LuaTable wt = mapRoot->SubTable("water");

	water.repeatX = wt.GetFloat("repeatX", 0.0f);
	water.repeatY = wt.GetFloat("repeatY", 0.0f);
	water.damage  = wt.GetFloat("damage",  0.0f) * (16.0f / 30.0f);

	water.absorb    = wt.GetFloat3("absorb",    float3(0.0f, 0.0f, 0.0f));
	water.baseColor = wt.GetFloat3("baseColor", float3(0.0f, 0.0f, 0.0f));
	water.minColor  = wt.GetFloat3("minColor",  float3(0.0f, 0.0f, 0.0f));

	water.surfaceColor = wt.GetFloat3("surfaceColor", float3(0.75f, 0.8f, 0.85f));
	water.surfaceAlpha = wt.GetFloat("surfaceAlpha",  0.55f);

	water.planeColor = wt.GetFloat3("planeColor", float3(0.0f, 0.4f, 0.0f));
	hasWaterPlane    = wt.KeyExists("planeColor");

	water.specularColor  = wt.GetFloat3("specularColor", light.groundSunColor);
	water.specularFactor = wt.GetFloat("specularFactor", 20.0f);

	water.fresnelMin   = wt.GetFloat("fresnelMin",   0.2f);
	water.fresnelMax   = wt.GetFloat("fresnelMax",   0.3f);
	water.fresnelPower = wt.GetFloat("fresnelPower", 4.0f);

	water.texture       = wt.GetString("texture",       "");
	water.foamTexture   = wt.GetString("foamTexture",   "");
	water.normalTexture = wt.GetString("normalTexture", "");

	// use 'resources.lua' for missing fields  (our the engine defaults)
	const LuaTable resGfxMaps = resRoot->SubTable("graphics").SubTable("maps");

	if (!water.texture.empty()) {
		water.texture = "maps/" + water.texture;
	} else {
		water.texture = "bitmaps/" + resGfxMaps.GetString("watertex", "ocean.jpg");
	}

	if (!water.foamTexture.empty()) {
		water.foamTexture = "maps/" + water.foamTexture;
	} else {
		water.foamTexture = "bitmaps/" + resGfxMaps.GetString("waterfoamtex", "foam.jpg");
	}

	if (!water.normalTexture.empty()) {
		water.normalTexture = "maps/" + water.normalTexture;
	} else {
		water.normalTexture = "bitmaps/" + resGfxMaps.GetString("waternormaltex", "waterbump.png");
	}

	// water caustic textures
	LuaTable caustics = wt.SubTable("caustics");
	string causticPrefix = "maps/";
	if (!caustics.IsValid()) {
		caustics = resRoot->SubTable("graphics").SubTable("caustics");
		causticPrefix = "bitmaps/";
	}
	if (caustics.IsValid()) {
		for (int i = 1; true; i++) {
			const string texName = caustics.GetString(i, "");
			if (texName.empty()) {
				break;
			}
			water.causticTextures.push_back(causticPrefix + texName);
		}
	} else {
		// load the default 32 textures
		for (int i = 0; i < 32; i++) {
			char defTex[256];
			sprintf(defTex, "bitmaps/caustics/caustic%02i.jpg", i);
			water.causticTextures.push_back(defTex);
		}
	}
}
Exemple #17
0
void parseMapOptions(
		std::vector<Option>& options,
		const std::string& fileName,
		const std::string& mapName,
		const std::string& fileModes,
		const std::string& accessModes,
		std::set<std::string>* optionsSet,
		CLogSubsystem* logSubsystem) {

	if (!logSubsystem) {
		assert(logSubsystem);
	}

	LuaParser luaParser(fileName, fileModes, accessModes);

	const string mapFile    = archiveScanner->MapNameToMapFile(mapName);
	const string configName = MapParser::GetMapConfigName(mapFile);

	if (mapName.empty())
		throw "Missing map name!";

	if (configName.empty())
		throw "Could not determine config-file name from the map name '" + mapName + "'!";

	luaParser.GetTable("Map");
	luaParser.AddString("name",     mapName);	
	luaParser.AddString("fileName", filesystem.GetFilename(mapFile));
	luaParser.AddString("fullName", mapFile);
	luaParser.AddString("configFile", configName);
	luaParser.EndTable();

	if (!luaParser.Execute()) {
		throw content_error("luaParser.Execute() failed: "
				+ luaParser.GetErrorLog());
	}

	const LuaTable root = luaParser.GetRoot();
	if (!root.IsValid()) {
		throw content_error("root table invalid");
	}

	std::set<std::string>* myOptionsSet = NULL;
	if (optionsSet == NULL) {
		myOptionsSet = new std::set<std::string>();
	} else {
		myOptionsSet = optionsSet;
	}
	for (int index = 1; root.KeyExists(index); index++) {
		Option opt;
		try {
			parseOption(root, index, opt, *myOptionsSet);
			options.push_back(opt);
		} catch (content_error& err) {
			logOutput.Print(*logSubsystem,
					"Failed parsing map-option %d from %s for map %s: %s",
					index, fileName.c_str(), mapName.c_str(), err.what());
		}
	}
	if (optionsSet == NULL) {
		delete myOptionsSet;
		myOptionsSet = NULL;
	}
}
Exemple #18
0
bool CSound::LoadSoundDefsImpl(const std::string& fileName)
{
	//! can be called from LuaUnsyncedCtrl too
	boost::recursive_mutex::scoped_lock lck(soundMutex);

	LuaParser parser(fileName, SPRING_VFS_MOD, SPRING_VFS_ZIP);
	parser.Execute();
	if (!parser.IsValid())
	{
		LOG_L(L_WARNING, "Could not load %s: %s",
				fileName.c_str(), parser.GetErrorLog().c_str());
		return false;
	}
	else
	{
		const LuaTable soundRoot = parser.GetRoot();
		const LuaTable soundItemTable = soundRoot.SubTable("SoundItems");
		if (!soundItemTable.IsValid())
		{
			LOG_L(L_WARNING, "CSound(): could not parse SoundItems table in %s", fileName.c_str());
			return false;
		}
		else
		{
			std::vector<std::string> keys;
			soundItemTable.GetKeys(keys);
			for (std::vector<std::string>::const_iterator it = keys.begin(); it != keys.end(); ++it)
			{
				std::string name(*it);

				soundItemDef bufmap;
				const LuaTable buf(soundItemTable.SubTable(name));
				buf.GetMap(bufmap);
				bufmap["name"] = name;
				soundItemDefMap::const_iterator sit = soundItemDefs.find(name);

				if (name == "default") {
					defaultItem = bufmap;
					defaultItem.erase("name"); //must be empty for default item
					defaultItem.erase("file");
					continue;
				}

				if (sit != soundItemDefs.end())
					LOG_L(L_WARNING, "Sound %s gets overwritten by %s", name.c_str(), fileName.c_str());

				if (!buf.KeyExists("file")) {
					// no file, drop
					LOG_L(L_WARNING, "Sound %s is missing file tag (ignoring)", name.c_str());
					continue;
				} else {
					soundItemDefs[name] = bufmap;
				}

				if (buf.KeyExists("preload")) {
					MakeItemFromDef(bufmap);
				}
			}
			LOG(" parsed %i sounds from %s", (int)keys.size(), fileName.c_str());
		}
	}

	//FIXME why do sounds w/o an own soundItemDef create (!=pointer) a new one from the defaultItem?
	for (soundItemDefMap::iterator it = soundItemDefs.begin(); it != soundItemDefs.end(); ++it) {
		soundItemDef& snddef = it->second;
		if (snddef.find("name") == snddef.end()) {
			// uses defaultItem! update it!
			const std::string file = snddef["file"];
			snddef = defaultItem;
			snddef["file"] = file;
		}
	}

	return true;
}
unsigned int CCustomExplosionGenerator::Load(CExplosionGeneratorHandler* h, const string& tag)
{
	unsigned int explosionID = -1U;

	if (tag.empty()) {
		return explosionID;
	}

	const std::map<std::string, unsigned int>::const_iterator it = explosionIDs.find(tag);

	if (it == explosionIDs.end()) {
		CEGData cegData;

		const LuaTable* root = h->GetExplosionTableRoot();
		const LuaTable& expTable = (root != NULL)? root->SubTable(tag): LuaTable();

		if (!expTable.IsValid()) {
			// not a fatal error: any calls to ::Explosion will just return early
			logOutput.Print("[CCEG::Load] WARNING: table for CEG \"" + tag + "\" invalid (parse errors?)");
			return explosionID;
		}

		vector<string> spawns;
		expTable.GetKeys(spawns);

		for (vector<string>::iterator si = spawns.begin(); si != spawns.end(); ++si) {
			ProjectileSpawnInfo psi;

			const string& spawnName = *si;
			const LuaTable spawnTable = expTable.SubTable(spawnName);

			if (!spawnTable.IsValid() || spawnName == "groundflash") {
				continue;
			}

			const string className = spawnTable.GetString("class", spawnName);

			psi.projectileClass = h->projectileClasses.GetClass(className);
			psi.flags = GetFlagsFromTable(spawnTable);
			psi.count = spawnTable.GetInt("count", 1);

			if (psi.projectileClass->binder->flags & creg::CF_Synced) {
				psi.flags |= SPW_SYNCED;
			}

			string code;
			map<string, string> props;
			map<string, string>::const_iterator propIt;
			spawnTable.SubTable("properties").GetMap(props);

			for (propIt = props.begin(); propIt != props.end(); ++propIt) {
				creg::Class::Member* m = psi.projectileClass->FindMember(propIt->first.c_str());
				if (m && (m->flags & creg::CM_Config)) {
					ParseExplosionCode(&psi, m->offset, m->type, propIt->second, code);
				}
			}

			code += (char)OP_END;
			psi.code.resize(code.size());
			copy(code.begin(), code.end(), psi.code.begin());

			cegData.projectileSpawn.push_back(psi);
		}

		const LuaTable gndTable = expTable.SubTable("groundflash");
		const int ttl = gndTable.GetInt("ttl", 0);
		if (ttl > 0) {
			cegData.groundFlash.circleAlpha  = gndTable.GetFloat("circleAlpha",  0.0f);
			cegData.groundFlash.flashSize    = gndTable.GetFloat("flashSize",    0.0f);
			cegData.groundFlash.flashAlpha   = gndTable.GetFloat("flashAlpha",   0.0f);
			cegData.groundFlash.circleGrowth = gndTable.GetFloat("circleGrowth", 0.0f);
			cegData.groundFlash.color        = gndTable.GetFloat3("color", float3(1.0f, 1.0f, 0.8f));

			cegData.groundFlash.flags = SPW_GROUND | GetFlagsFromTable(gndTable);
			cegData.groundFlash.ttl = ttl;
		}

		cegData.useDefaultExplosions = expTable.GetBool("useDefaultExplosions", false);

		explosionID = explosionData.size();
		explosionData.push_back(cegData);
		explosionIDs[tag] = explosionID;
	} else {
		explosionID = it->second;
	}

	return explosionID;
}
void CCustomExplosionGenerator::Load(CExplosionGeneratorHandler* h, const string& tag)
{
    static std::map<string, CEGData> cachedCEGs;
    std::map<string, CEGData>::iterator it = cachedCEGs.find(tag);

    if (it == cachedCEGs.end()) {
        CEGData cegData;

        const LuaTable& root = h->GetTable();
        const LuaTable expTable = root.SubTable(tag);
        if (!expTable.IsValid()) {
            throw content_error("Explosion info for " + tag + " not found.");
        }

        vector<string> spawns;
        expTable.GetKeys(spawns);

        for (vector<string>::iterator si = spawns.begin(); si != spawns.end(); ++si) {
            ProjectileSpawnInfo psi;

            const string& spawnName = *si;
            const LuaTable spawnTable = expTable.SubTable(spawnName);

            if (!spawnTable.IsValid() || spawnName == "groundflash") {
                continue;
            }

            const string className = spawnTable.GetString("class", spawnName);
            unsigned int flags = 0;

            if (spawnTable.GetBool("ground",     false)) {
                flags |= SPW_GROUND;
            }
            if (spawnTable.GetBool("water",      false)) {
                flags |= SPW_WATER;
            }
            if (spawnTable.GetBool("air",        false)) {
                flags |= SPW_AIR;
            }
            if (spawnTable.GetBool("underwater", false)) {
                flags |= SPW_UNDERWATER;
            }
            if (spawnTable.GetBool("unit",       false)) {
                flags |= SPW_UNIT;
            }
            if (spawnTable.GetBool("nounit",     false)) {
                flags |= SPW_NO_UNIT;
            }

            psi.projectileClass = h->projectileClasses.GetClass(className);
            psi.flags = flags;
            psi.count = spawnTable.GetInt("count", 1);

            string code;
            map<string, string> props;
            map<string, string>::const_iterator propIt;
            spawnTable.SubTable("properties").GetMap(props);

            for (propIt = props.begin(); propIt != props.end(); ++propIt) {
                creg::Class::Member* m = psi.projectileClass->FindMember(propIt->first.c_str());
                if (m && (m->flags & creg::CM_Config)) {
                    ParseExplosionCode(&psi, m->offset, m->type, propIt->second, code);
                }
            }

            code += (char)OP_END;
            psi.code.resize(code.size());
            copy(code.begin(), code.end(), psi.code.begin());

            cegData.projectileSpawn.push_back(psi);
        }

        const LuaTable gndTable = expTable.SubTable("groundflash");
        const int ttl = gndTable.GetInt("ttl", 0);
        if (ttl > 0) {
            cegData.groundFlash.circleAlpha  = gndTable.GetFloat("circleAlpha",  0.0f);
            cegData.groundFlash.flashSize    = gndTable.GetFloat("flashSize",    0.0f);
            cegData.groundFlash.flashAlpha   = gndTable.GetFloat("flashAlpha",   0.0f);
            cegData.groundFlash.circleGrowth = gndTable.GetFloat("circleGrowth", 0.0f);
            cegData.groundFlash.color        = gndTable.GetFloat3("color", float3(1.0f, 1.0f, 0.8f));

            unsigned int flags = SPW_GROUND;
            if (gndTable.GetBool("ground",     false)) {
                flags |= SPW_GROUND;
            }
            if (gndTable.GetBool("water",      false)) {
                flags |= SPW_WATER;
            }
            if (gndTable.GetBool("air",        false)) {
                flags |= SPW_AIR;
            }
            if (gndTable.GetBool("underwater", false)) {
                flags |= SPW_UNDERWATER;
            }
            if (gndTable.GetBool("unit",       false)) {
                flags |= SPW_UNIT;
            }
            if (gndTable.GetBool("nounit",     false)) {
                flags |= SPW_NO_UNIT;
            }

            cegData.groundFlash.flags = flags;
            cegData.groundFlash.ttl = ttl;
        }

        cegData.useDefaultExplosions = expTable.GetBool("useDefaultExplosions", false);

        cachedCEGs[tag] = cegData;
        currentCEG = &cachedCEGs[tag];
    } else {
        currentCEG = &(it->second);
    }
}
void CWeaponDefHandler::ParseWeapon(const LuaTable& wdTable, WeaponDef& wd)
{
	bool manualBombSettings; //Allow the user to manually specify the burst and burstrate for his AircraftBomb
	int color;
	int color2;

	wd.tdfId = wdTable.GetInt("id", 0);

	wd.description = wdTable.GetString("name",     "Weapon");
	wd.cegTag      = wdTable.GetString("cegTag",   "");

	wd.avoidFriendly = wdTable.GetBool("avoidFriendly", true);
	wd.avoidFeature  = wdTable.GetBool("avoidFeature",  true);
	wd.avoidNeutral  = wdTable.GetBool("avoidNeutral",  false);

	//FIXME may be smarter to merge the collideXYZ tags with avoidXYZ and removing the collisionFlags tag (and move the code into CWeapon)?
	wd.collisionFlags = 0;

	if (!wdTable.GetBool("collideEnemy",    true)) { wd.collisionFlags |= Collision::NOENEMIES;    }
	if (!wdTable.GetBool("collideFriendly", true)) { wd.collisionFlags |= Collision::NOFRIENDLIES; }
	if (!wdTable.GetBool("collideFeature",  true)) { wd.collisionFlags |= Collision::NOFEATURES;   }
	if (!wdTable.GetBool("collideNeutral",  true)) { wd.collisionFlags |= Collision::NONEUTRALS;   }
	if (!wdTable.GetBool("collideGround",   true)) { wd.collisionFlags |= Collision::NOGROUND;     }

	wd.minIntensity = wdTable.GetFloat("minIntensity", 0.0f);

	manualBombSettings = wdTable.GetBool("manualBombSettings", false);
	wd.turret   = wdTable.GetBool("turret",      false);
	wd.highTrajectory = wdTable.GetInt("highTrajectory", 2);
	wd.noSelfDamage   = wdTable.GetBool("noSelfDamage", false);
	wd.impactOnly     = wdTable.GetBool("impactOnly",   false);

	wd.waterweapon   = wdTable.GetBool("waterWeapon",     false);
	wd.fireSubmersed = wdTable.GetBool("fireSubmersed",   wd.waterweapon);
	wd.submissile    = wdTable.GetBool("submissile",      false);
	wd.tracks        = wdTable.GetBool("tracks",          false);
	wd.fixedLauncher = wdTable.GetBool("fixedLauncher",   false);
	wd.noExplode     = wdTable.GetBool("noExplode",       false);
	wd.isShield      = wdTable.GetBool("isShield",        false);
	wd.beamtime      = wdTable.GetFloat("beamTime",       1.0f);
	wd.beamburst     = wdTable.GetBool("beamburst",       false);

	wd.waterBounce   = wdTable.GetBool("waterBounce",    false);
	wd.groundBounce  = wdTable.GetBool("groundBounce",   false);
	wd.bounceSlip    = wdTable.GetFloat("bounceSlip",    1.0f);
	wd.bounceRebound = wdTable.GetFloat("bounceRebound", 1.0f);
	wd.numBounce     = wdTable.GetInt("numBounce",       -1);

	wd.thickness      = wdTable.GetFloat("thickness",      2.0f);
	wd.corethickness  = wdTable.GetFloat("coreThickness",  0.25f);
	wd.laserflaresize = wdTable.GetFloat("laserFlareSize", 15.0f);
	wd.intensity      = wdTable.GetFloat("intensity",      0.9f);
	wd.duration       = wdTable.GetFloat("duration",       0.05f);
	wd.falloffRate    = wdTable.GetFloat("fallOffRate",    0.5f);
	wd.lodDistance    = wdTable.GetInt("lodDistance",      1000);

	wd.visuals.modelName     = wdTable.GetString("model",       "");
	wd.visuals.explosionScar = wdTable.GetBool("explosionScar", true);
	wd.visuals.smokeTrail    = wdTable.GetBool("smokeTrail",    false);
	wd.visuals.alwaysVisible = wdTable.GetBool("alwaysVisible", false);
	wd.visuals.sizeDecay     = wdTable.GetFloat("sizeDecay",    0.0f);
	wd.visuals.alphaDecay    = wdTable.GetFloat("alphaDecay",   1.0f);
	wd.visuals.separation    = wdTable.GetFloat("separation",   1.0f);
	wd.visuals.noGap         = wdTable.GetBool("noGap",         true);
	wd.visuals.stages        = wdTable.GetInt("stages",         5);

	wd.gravityAffected = wdTable.GetBool("gravityAffected", false);

	wd.type = wdTable.GetString("weaponType", "Cannon");

	wd.targetBorder = Clamp(wdTable.GetFloat("targetBorder", (wd.type == "Melee")? 1.0f : 0.0f), -1.0f, 1.0f);
	wd.cylinderTargetting = Clamp(wdTable.GetFloat("cylinderTargetting", (wd.type == "Melee")? 1.0f : 0.0f), 0.0f, 128.0f);

	wd.range = wdTable.GetFloat("range", 10.0f);
	const float accuracy       = wdTable.GetFloat("accuracy",   0.0f);
	const float sprayAngle     = wdTable.GetFloat("sprayAngle", 0.0f);
	const float movingAccuracy = wdTable.GetFloat("movingAccuracy", accuracy);
	// should really be tan but TA seem to cap it somehow
	// should also be 7fff or ffff theoretically but neither seems good
	wd.accuracy       = sin((accuracy)       * PI / 0xafff);
	wd.sprayAngle     = sin((sprayAngle)     * PI / 0xafff);
	wd.movingAccuracy = sin((movingAccuracy) * PI / 0xafff);

	wd.targetMoveError = wdTable.GetFloat("targetMoveError", 0.0f);
	wd.leadLimit = wdTable.GetFloat("leadLimit", -1.0f);
	wd.leadBonus = wdTable.GetFloat("leadBonus", 0.0f);

	// setup the default damages
	const LuaTable dmgTable = wdTable.SubTable("damage");
	float defDamage = dmgTable.GetFloat("default", 0.0f);
	if (defDamage == 0.0f) {
		defDamage = 1.0f; //avoid division by zeroes
	}
	for (int a = 0; a < damageArrayHandler->GetNumTypes(); ++a) {
		wd.damages[a] = defDamage;
	}

	map<string, float> damages;
	dmgTable.GetMap(damages);

	map<string, float>::const_iterator di;
	for (di = damages.begin(); di != damages.end(); ++di) {
		const int type = damageArrayHandler->GetTypeFromName(di->first);
		if (type != 0) {
			float dmg = di->second;
			if (dmg != 0.0f) {
				wd.damages[type] = dmg;
			} else {
				wd.damages[type] = 1.0f;
			}
		}
	}

	wd.damages.impulseFactor = wdTable.GetFloat("impulseFactor", 1.0f);
	wd.damages.impulseBoost  = wdTable.GetFloat("impulseBoost",  0.0f);
	wd.damages.craterMult    = wdTable.GetFloat("craterMult",    wd.damages.impulseFactor);
	wd.damages.craterBoost   = wdTable.GetFloat("craterBoost",   0.0f);

	wd.areaOfEffect = wdTable.GetFloat("areaOfEffect", 8.0f) * 0.5f;
	wd.edgeEffectiveness = wdTable.GetFloat("edgeEffectiveness", 0.0f);
	// prevent 0/0 division in CGameHelper::Explosion
	if (wd.edgeEffectiveness > 0.999f) {
		wd.edgeEffectiveness = 0.999f;
	}

	wd.projectilespeed = std::max(0.01f, wdTable.GetFloat("weaponVelocity", 0.0f) / GAME_SPEED);
	wd.startvelocity = max(0.01f, wdTable.GetFloat("startVelocity", 0.0f) / GAME_SPEED);
	wd.weaponacceleration = wdTable.GetFloat("weaponAcceleration", 0.0f) / GAME_SPEED / GAME_SPEED;
	wd.reload = wdTable.GetFloat("reloadTime", 1.0f);
	wd.salvodelay = wdTable.GetFloat("burstRate", 0.1f);
	wd.salvosize = wdTable.GetInt("burst", 1);
	wd.projectilespershot = wdTable.GetInt("projectiles", 1);
	wd.maxAngle = wdTable.GetFloat("tolerance", 3000.0f) * 180.0f / COBSCALEHALF;
	wd.restTime = 0.0f;
	wd.metalcost = wdTable.GetFloat("metalPerShot", 0.0f);
	wd.energycost = wdTable.GetFloat("energyPerShot", 0.0f);
	wd.selfExplode = wdTable.GetBool("burnblow", false);
	wd.predictBoost = wdTable.GetFloat("predictBoost", wd.selfExplode ? 0.5f : 0.0f);
	wd.sweepFire = wdTable.GetBool("sweepfire", false);
	wd.canAttackGround = wdTable.GetBool("canAttackGround", true);
	wd.myGravity = wdTable.GetFloat("myGravity", 0.0f);

	wd.fireStarter = wdTable.GetFloat("fireStarter", 0.0f) * 0.01f;
	wd.paralyzer = wdTable.GetBool("paralyzer", false);
	if (wd.paralyzer) {
		wd.damages.paralyzeDamageTime = max(0, wdTable.GetInt("paralyzeTime", 10));
	} else {
		wd.damages.paralyzeDamageTime = 0;
	}

	const float defShake = wd.paralyzer ? 0.0f : wd.damages.GetDefaultDamage();
	wd.cameraShake = wdTable.GetFloat("cameraShake", defShake);
	wd.cameraShake = max(0.0f, wd.cameraShake);

	// 0.78.2.1 backwards compatibility
	bool defaultSoundTrigger = (wd.type == "BeamLaser" && !wd.beamburst) || 
								wd.type == "Melee"  || wd.type == "Rifle";
	wd.soundTrigger = wdTable.GetBool("soundTrigger", defaultSoundTrigger);

	//sunparser->GetDef(wd.highTrajectory, "0", weaponname + "minbarrelangle");
	wd.stockpile     = wdTable.GetBool("stockpile", false);
	wd.stockpileTime = wdTable.GetFloat("stockpileTime", wd.reload);
	wd.interceptor   = wdTable.GetInt("interceptor", 0);
	wd.targetable    = wdTable.GetInt("targetable",  0);
	wd.manualfire    = wdTable.GetBool("commandfire", false);
	wd.coverageRange = wdTable.GetFloat("coverage", 0.0f);

	// FIXME -- remove the old style ?
	LuaTable shTable = wdTable.SubTable("shield");
	const float3 shieldBadColor (1.0f, 0.5f, 0.5f);
	const float3 shieldGoodColor(0.5f, 0.5f, 1.0f);
	if (shTable.IsValid()) {
		wd.shieldRepulser         = shTable.GetBool("repulser",       false);
		wd.smartShield            = shTable.GetBool("smart",          false);
		wd.exteriorShield         = shTable.GetBool("exterior",       false);
		wd.visibleShield          = shTable.GetBool("visible",        false);
		wd.visibleShieldRepulse   = shTable.GetBool("visibleRepulse", false);
		wd.visibleShieldHitFrames = shTable.GetInt("visibleHitFrames", 0);
		wd.shieldEnergyUse        = shTable.GetFloat("energyUse",        0.0f);
		wd.shieldForce            = shTable.GetFloat("force",            0.0f);
		wd.shieldRadius           = shTable.GetFloat("radius",           0.0f);
		wd.shieldMaxSpeed         = shTable.GetFloat("maxSpeed",         0.0f);
		wd.shieldPower            = shTable.GetFloat("power",            0.0f);
		wd.shieldPowerRegen       = shTable.GetFloat("powerRegen",       0.0f);
		wd.shieldPowerRegenEnergy = shTable.GetFloat("powerRegenEnergy", 0.0f);
		wd.shieldRechargeDelay    = (int)(shTable.GetFloat("rechargeDelay", 0) * GAME_SPEED);
		wd.shieldStartingPower    = shTable.GetFloat("startingPower",    0.0f);
		wd.shieldInterceptType    = shTable.GetInt("interceptType", 0);
		wd.shieldBadColor         = shTable.GetFloat3("badColor",  shieldBadColor);
		wd.shieldGoodColor        = shTable.GetFloat3("goodColor", shieldGoodColor);
		wd.shieldAlpha            = shTable.GetFloat("alpha", 0.2f);
	}
	else {
		wd.shieldRepulser         = wdTable.GetBool("shieldRepulser",       false);
		wd.smartShield            = wdTable.GetBool("smartShield",          false);
		wd.exteriorShield         = wdTable.GetBool("exteriorShield",       false);
		wd.visibleShield          = wdTable.GetBool("visibleShield",        false);
		wd.visibleShieldRepulse   = wdTable.GetBool("visibleShieldRepulse", false);
		wd.visibleShieldHitFrames = wdTable.GetInt("visibleShieldHitFrames", 0);
		wd.shieldEnergyUse        = wdTable.GetFloat("shieldEnergyUse",        0.0f);
		wd.shieldForce            = wdTable.GetFloat("shieldForce",            0.0f);
		wd.shieldRadius           = wdTable.GetFloat("shieldRadius",           0.0f);
		wd.shieldMaxSpeed         = wdTable.GetFloat("shieldMaxSpeed",         0.0f);
		wd.shieldPower            = wdTable.GetFloat("shieldPower",            0.0f);
		wd.shieldPowerRegen       = wdTable.GetFloat("shieldPowerRegen",       0.0f);
		wd.shieldPowerRegenEnergy = wdTable.GetFloat("shieldPowerRegenEnergy", 0.0f);
		wd.shieldRechargeDelay    = (int)(wdTable.GetFloat("shieldRechargeDelay", 0) * GAME_SPEED);
		wd.shieldStartingPower    = wdTable.GetFloat("shieldStartingPower",    0.0f);
		wd.shieldInterceptType    = wdTable.GetInt("shieldInterceptType", 0);
		wd.shieldBadColor         = wdTable.GetFloat3("shieldBadColor",  shieldBadColor);
		wd.shieldGoodColor        = wdTable.GetFloat3("shieldGoodColor", shieldGoodColor);
		wd.shieldAlpha            = wdTable.GetFloat("shieldAlpha", 0.2f);
	}


	int defInterceptType = 0;
	if ((wd.type == "Cannon") || (wd.type == "EmgCannon")) {
		defInterceptType = 1;
	} else if ((wd.type == "LaserCannon") || (wd.type == "BeamLaser")) {
		defInterceptType = 2;
	} else if ((wd.type == "StarburstLauncher") || (wd.type == "MissileLauncher")) {
		defInterceptType = 4;
	} else if (wd.type == "AircraftBomb") {
		defInterceptType = 8;
	} else if (wd.type == "Flame") {
		defInterceptType = 16;
	} else if (wd.type == "TorpedoLauncher") {
		defInterceptType = 32;
	} else if (wd.type == "LightningCannon") {
		defInterceptType = 64;
	} else if (wd.type == "Rifle") {
		defInterceptType = 128;
	} else if (wd.type == "Melee") {
		defInterceptType = 256;
	}
	wd.interceptedByShieldType = wdTable.GetInt("interceptedByShieldType", defInterceptType);

	wd.wobble = wdTable.GetFloat("wobble", 0.0f) * TAANG2RAD / 30.0f;
	wd.dance = wdTable.GetFloat("dance", 0.0f) / GAME_SPEED;
	wd.trajectoryHeight = wdTable.GetFloat("trajectoryHeight", 0.0f);

	wd.noAutoTarget = (wd.manualfire || wd.interceptor || wd.isShield);

	wd.onlyTargetCategory = 0xffffffff;
	if (wdTable.GetBool("toAirWeapon", false)) {
		// fix if we sometime call aircrafts otherwise
		wd.onlyTargetCategory = CCategoryHandler::Instance()->GetCategories("VTOL");
		//LOG("air only weapon %s %i", weaponname.c_str(), wd.onlyTargetCategory);
	}

	wd.largeBeamLaser = wdTable.GetBool("largeBeamLaser", false);
	wd.visuals.tilelength  = wdTable.GetFloat("tileLength", 200.0f);
	wd.visuals.scrollspeed = wdTable.GetFloat("scrollSpeed",  5.0f);
	wd.visuals.pulseSpeed  = wdTable.GetFloat("pulseSpeed",   1.0f);
	wd.visuals.beamdecay   = wdTable.GetFloat("beamDecay",    1.0f);
	wd.visuals.beamttl     = wdTable.GetInt("beamTTL", 0);

	if (wd.type == "Cannon") {
		wd.heightmod = wdTable.GetFloat("heightMod", 0.8f);
	} else if (wd.type == "BeamLaser" || wd.type == "LightningCannon") {
		wd.heightmod = wdTable.GetFloat("heightMod", 1.0f);
	} else {
		wd.heightmod = wdTable.GetFloat("heightMod", 0.2f);
	}

	wd.onlyForward = !wd.turret && (wd.type != "StarburstLauncher");

	color  = wdTable.GetInt("color",  0);
	color2 = wdTable.GetInt("color2", 0);

	const float3 rgbcol = hs2rgb(color / float(255), color2 / float(255));
	wd.visuals.color  = wdTable.GetFloat3("rgbColor",  rgbcol);
	wd.visuals.color2 = wdTable.GetFloat3("rgbColor2", float3(1.0f, 1.0f, 1.0f));

	wd.uptime = wdTable.GetFloat("weaponTimer", 0.0f);
	wd.flighttime = wdTable.GetFloat("flightTime", 0) * 32;

	wd.turnrate = wdTable.GetFloat("turnRate", 0.0f) * TAANG2RAD / 30.0f;

	if ((wd.type == "AircraftBomb") && !manualBombSettings) {
		if (wd.reload < 0.5f) {
			wd.salvodelay = min(0.2f, wd.reload);
			wd.salvosize = (int)(1 / wd.salvodelay) + 1;
			wd.reload = 5;
		} else {
			wd.salvodelay = min(0.4f, wd.reload);
			wd.salvosize = 2;
		}
	}
	//if(!wd.turret && (wd.type != "TorpedoLauncher")) {
	//	wd.maxAngle*=0.4f;
	//}

	//2+min(damages[0]*0.0025f,weaponDef->areaOfEffect*0.1f)
	const float tempsize = 2.0f + min(wd.damages[0] * 0.0025f, wd.areaOfEffect * 0.1f);
	wd.size = wdTable.GetFloat("size", tempsize);
	wd.sizeGrowth = wdTable.GetFloat("sizeGrowth", 0.2f);
	wd.collisionSize = wdTable.GetFloat("collisionSize", 0.05f);

	wd.visuals.colorMap = 0;
	const string colormap = wdTable.GetString("colormap", "");
	if (colormap != "") {
		wd.visuals.colorMap = CColorMap::LoadFromDefString(colormap);
	}

	wd.heightBoostFactor = wdTable.GetFloat("heightBoostFactor", -1.0f);
	wd.proximityPriority = wdTable.GetFloat("proximityPriority", 1.0f);

	// get some weapon specific defaults
	if (wd.type == "Cannon") {
		// CExplosiveProjectile
		wd.ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.9f);

		wd.visuals.color = wdTable.GetFloat3("rgbColor", float3(1.0f, 0.5f, 0.0f));
		wd.intensity = wdTable.GetFloat("intensity", 0.2f);
	} else if (wd.type == "Rifle") {
		wd.ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.9f);
	} else if (wd.type == "Melee") {
		// ...
	} else if (wd.type == "Flame") {
		// CFlameProjectile
		wd.ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.2f);
		wd.size              = wdTable.GetFloat("size",      tempsize);
		wd.sizeGrowth        = wdTable.GetFloat("sizeGrowth",    0.5f);
		wd.collisionSize     = wdTable.GetFloat("collisionSize", 0.5f);
		wd.duration          = wdTable.GetFloat("flameGfxTime",  1.2f);
	} else if (wd.type == "MissileLauncher") {
		// CMissileProjectile
		wd.ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.5f);
	} else if (wd.type == "LaserCannon") {
		// CLaserProjectile
		wd.ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.7f);
		wd.collisionSize = wdTable.GetFloat("collisionSize", 0.5f);

		wd.visuals.hardStop = wdTable.GetBool("hardstop", false);
	} else if (wd.type == "BeamLaser") {
		wd.ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.7f);
	} else if (wd.type == "LightningCannon") {
		wd.ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.5f);

		wd.thickness = wdTable.GetFloat("thickness", 0.8f);
	} else if (wd.type == "EmgCannon") {
		// CEmgProjectile
		wd.ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.5f);

		wd.size = wdTable.GetFloat("size", 3.0f);
		wd.visuals.color = wdTable.GetFloat3("rgbColor", float3(0.9f, 0.9f, 0.2f));
	} else if (wd.type == "DGun") {
		// CFireBallProjectile
		wd.ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.5f);
		wd.collisionSize = wdTable.GetFloat("collisionSize", 10.0f);
	} else if (wd.type == "StarburstLauncher") {
		// CStarburstProjectile
		wd.ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.7f);
	} else {
		wd.ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.0f);
	}


	const LuaTable texTable = wdTable.SubTable("textures");

	wd.visuals.texNames[0] = texTable.GetString(1, wdTable.GetString("texture1", ""));
	wd.visuals.texNames[1] = texTable.GetString(2, wdTable.GetString("texture2", ""));
	wd.visuals.texNames[2] = texTable.GetString(3, wdTable.GetString("texture3", ""));
	wd.visuals.texNames[3] = texTable.GetString(4, wdTable.GetString("texture4", ""));

	wd.visuals.expGenTag = wdTable.GetString("explosionGenerator", "");
	wd.visuals.bounceExpGenTag = wdTable.GetString("bounceExplosionGenerator", "");

	const float gd = max(30.0f, wd.damages[0] / 20.0f);
	const float defExpSpeed = (8.0f + (gd * 2.5f)) / (9.0f + (sqrt(gd) * 0.7f)) * 0.5f;
	wd.explosionSpeed = wdTable.GetFloat("explosionSpeed", defExpSpeed);

	// Dynamic Damage
	wd.dynDamageInverted = wdTable.GetBool("dynDamageInverted", false);
	wd.dynDamageExp      = wdTable.GetFloat("dynDamageExp",   0.0f);
	wd.dynDamageMin      = wdTable.GetFloat("dynDamageMin",   0.0f);
	wd.dynDamageRange    = wdTable.GetFloat("dynDamageRange", 0.0f);

	LoadSound(wdTable, wd.firesound, "start");
	LoadSound(wdTable, wd.soundhit,  "hit");

	if ((wd.firesound.getVolume(0) == -1.0f) ||
	    (wd.soundhit.getVolume(0)  == -1.0f)) {
		// no volume (-1.0f) read from weapon definition, set it dynamically here
		if (wd.damages[0] <= 50.0f) {
			wd.soundhit.setVolume(0, 5.0f);
			wd.firesound.setVolume(0, 5.0f);
		}
		else {
			float soundVolume = sqrt(wd.damages[0] * 0.5f);

			if (wd.type == "LaserCannon") {
				soundVolume *= 0.5f;
			}

			float hitSoundVolume = soundVolume;

			if ((soundVolume > 100.0f) &&
			    ((wd.type == "MissileLauncher") ||
			     (wd.type == "StarburstLauncher"))) {
				soundVolume = 10.0f * sqrt(soundVolume);
			}

			if (wd.firesound.getVolume(0) == -1.0f) {
				wd.firesound.setVolume(0, soundVolume);
			}

			soundVolume = hitSoundVolume;

			if (wd.areaOfEffect > 8.0f) {
				soundVolume *= 2.0f;
			}
			if (wd.type == "DGun") {
				soundVolume *= 0.15f;
			}
			if (wd.soundhit.getVolume(0) == -1.0f) {
				wd.soundhit.setVolume(0, soundVolume);
			}
		}
	}

	// custom parameters table
	wdTable.SubTable("customParams").GetMap(wd.customParams);
}
Exemple #22
0
CMoveInfo::CMoveInfo()
{
	const LuaTable rootTable = game->defsParser->GetRoot().SubTable("MoveDefs");
	if (!rootTable.IsValid()) {
		throw content_error("Error loading movement definitions");
	}

	groundMoveMath = new CGroundMoveMath();
	hoverMoveMath = new CHoverMoveMath();
	seaMoveMath = new CShipMoveMath();

	CRC crc;

	for (int tt = 0; tt < CMapInfo::NUM_TERRAIN_TYPES; ++tt) {
		const CMapInfo::TerrainType& terrType = mapInfo->terrainTypes[tt];

		crc << terrType.tankSpeed << terrType.kbotSpeed;
		crc << terrType.hoverSpeed << terrType.shipSpeed;
	}

	for (size_t num = 1; /* no test */; num++) {
		const LuaTable moveTable = rootTable.SubTable(num);
		if (!moveTable.IsValid()) {
			break;
		}

		MoveData* md = new MoveData(NULL);

		md->name          = StringToLower(moveTable.GetString("name", ""));
		md->pathType      = (num - 1);
		md->crushStrength = moveTable.GetFloat("crushStrength", 10.0f);

		const float minWaterDepth = moveTable.GetFloat("minWaterDepth", 10.0f);
		const float maxWaterDepth = moveTable.GetFloat("maxWaterDepth", 0.0f);

		if ((md->name.find("boat") != string::npos) ||
		    (md->name.find("ship") != string::npos)) {
			md->moveType   = MoveData::Ship_Move;
			md->depth      = minWaterDepth;
			md->moveFamily = MoveData::Ship;
			md->moveMath   = seaMoveMath;
			md->subMarine  = moveTable.GetBool("subMarine", 0);
		} else if (md->name.find("hover") != string::npos) {
			md->moveType   = MoveData::Hover_Move;
			md->maxSlope   = DegreesToMaxSlope(moveTable.GetFloat("maxSlope", 15.0f));
			md->moveFamily = MoveData::Hover;
			md->moveMath   = hoverMoveMath;
		} else {
			md->moveType = MoveData::Ground_Move;
			md->depthMod = moveTable.GetFloat("depthMod", 0.1f);
			md->depth    = maxWaterDepth;
			md->maxSlope = DegreesToMaxSlope(moveTable.GetFloat("maxSlope", 60.0f));
			md->moveMath = groundMoveMath;

			if (md->name.find("tank") != string::npos) {
				md->moveFamily = MoveData::Tank;
			} else {
				md->moveFamily = MoveData::KBot;
			}
		}

		md->heatMapping = moveTable.GetBool("heatMapping", false);
		md->heatMod = moveTable.GetFloat("heatMod", 50.0f);
		md->heatProduced = moveTable.GetInt("heatProduced", 60);

		// ground units hug the ocean floor when in water,
		// ships stay at a "fixed" level (their waterline)
		md->followGround =
			(md->moveFamily == MoveData::Tank ||
			md->moveFamily == MoveData::KBot);

		// tank or bot that cannot get its threads / feet
		// wet, or hovercraft (which doesn't touch ground
		// or water)
		const bool b0 =
			((md->followGround && maxWaterDepth <= 0.0) ||
			md->moveFamily == MoveData::Hover);

		// ship (or sub) that cannot crawl onto shore, OR tank or
		// kbot restricted to snorkling (strange but possible)
		const bool b1 =
			((md->moveFamily == MoveData::Ship && minWaterDepth > 0.0) ||
			((md->followGround) && minWaterDepth > 0.0));

		// tank or kbot that CAN go skinny-dipping (amph.),
		// or ship that CAN sprout legs when at the beach
		const bool b2 =
			((md->followGround) && maxWaterDepth > 0.0) ||
			(md->moveFamily == MoveData::Ship && minWaterDepth < 0.0);

		if (b0) { md->terrainClass = MoveData::Land; }
		if (b1) { md->terrainClass = MoveData::Water; }
		if (b2) { md->terrainClass = MoveData::Mixed; }


		const int xsize = std::max(1, moveTable.GetInt("footprintX",     1));
		const int zsize = std::max(1, moveTable.GetInt("footprintZ", xsize));
		const int scale = 2;

		// make all mobile footprints point-symmetric in heightmap space
		// (meaning that only non-even dimensions are possible and each
		// footprint always has a unique center square)
		md->xsize = xsize * scale;
		md->zsize = zsize * scale;
		md->xsize -= ((md->xsize & 1)? 0: 1);
		md->zsize -= ((md->zsize & 1)? 0: 1);
		md->slopeMod = moveTable.GetFloat("slopeMod", 4.0f / (md->maxSlope + 0.001f));

		const unsigned int checksum =
			(md->xsize        << 16) +
			(md->zsize        <<  8) +
			(md->followGround <<  4) +
			(md->subMarine    <<  3) +
			(b2               <<  2) +
			(b1               <<  1) +
			(b0               <<  0);

		crc << checksum
			<< md->maxSlope << md->slopeMod
			<< md->depth << md->depthMod
			<< md->crushStrength;

		moveData.push_back(md);
		name2moveData[md->name] = md->pathType;
	}


	const float waterDamage = mapInfo->water.damage;
	if (waterDamage >= 1000.0f) {
		CGroundMoveMath::waterDamageCost = 0.0f; //! block water
	} else {
		CGroundMoveMath::waterDamageCost = 1.0f / (1.0f + waterDamage * 0.1f);
	}

	CHoverMoveMath::noWaterMove = (waterDamage >= 10000.0f);

	crc << CGroundMoveMath::waterDamageCost;
	crc << CHoverMoveMath::noWaterMove;

	moveInfoChecksum = crc.GetDigest();
}
CProjectileHandler::CProjectileHandler()
{
	PrintLoadMsg("Creating projectile texture");

	maxParticles     = configHandler->Get("MaxParticles",      4000);
	maxNanoParticles = configHandler->Get("MaxNanoParticles", 10000);

	currentParticles       = 0;
	currentNanoParticles   = 0;
	particleSaturation     = 0.0f;
	nanoParticleSaturation = 0.0f;
	numPerlinProjectiles   = 0;

	// preload some IDs
	// (note that 0 is reserved for unsynced projectiles)
	for (int i = 1; i <= 12345; i++) {
		freeIDs.push_back(i);
	}
	maxUsedID = freeIDs.size();

	textureAtlas = new CTextureAtlas(2048, 2048);

	// used to block resources_map.tdf from loading textures
	set<string> blockMapTexNames;

	LuaParser resourcesParser("gamedata/resources.lua",
	                          SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP);
	if (!resourcesParser.Execute()) {
		logOutput.Print(resourcesParser.GetErrorLog());
	}
	const LuaTable rootTable = resourcesParser.GetRoot();
	const LuaTable gfxTable = rootTable.SubTable("graphics");

	const LuaTable ptTable = gfxTable.SubTable("projectileTextures");
	// add all textures in projectiletextures section
	map<string, string> ptex;
	ptTable.GetMap(ptex);

	for (map<string, string>::iterator pi=ptex.begin(); pi!=ptex.end(); ++pi) {
		textureAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
		blockMapTexNames.insert(StringToLower(pi->first));
	}

	// add all texture from sections within projectiletextures section
	vector<string> seclist;
	ptTable.GetKeys(seclist);
	for (size_t i = 0; i < seclist.size(); i++) {
		const LuaTable ptSubTable = ptTable.SubTable(seclist[i]);
		if (ptSubTable.IsValid()) {
			map<string, string> ptex2;
			ptSubTable.GetMap(ptex2);
			for (map<string, string>::iterator pi = ptex2.begin(); pi != ptex2.end(); ++pi) {
				textureAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
				blockMapTexNames.insert(StringToLower(pi->first));
			}
		}
	}

	// get the smoke textures, hold the count in 'smokeCount'
	const LuaTable smokeTable = gfxTable.SubTable("smoke");
	int smokeCount;
	if (smokeTable.IsValid()) {
		for (smokeCount = 0; true; smokeCount++) {
			const string tex = smokeTable.GetString(smokeCount + 1, "");
			if (tex.empty()) {
				break;
			}
			const string texName = "bitmaps/" + tex;
			const string smokeName = "ismoke" + IntToString(smokeCount, "%02i");
			textureAtlas->AddTexFromFile(smokeName, texName);
			blockMapTexNames.insert(StringToLower(smokeName));
		}
	}
	else {
		// setup the defaults
		for (smokeCount = 0; smokeCount < 12; smokeCount++) {
			const string smokeNum = IntToString(smokeCount, "%02i");
			const string smokeName = "ismoke" + smokeNum;
			const string texName = "bitmaps/smoke/smoke" + smokeNum + ".tga";
			textureAtlas->AddTexFromFile(smokeName, texName);
			blockMapTexNames.insert(StringToLower(smokeName));
		}
	}
	if (smokeCount <= 0) {
		throw content_error("missing smoke textures");
	}

	char tex[128][128][4];
	for (int y = 0; y < 128; y++) { // shield
		for (int x = 0; x < 128; x++) {
			tex[y][x][0] = 70;
			tex[y][x][1] = 70;
			tex[y][x][2] = 70;
			tex[y][x][3] = 70;
		}
	}
	textureAtlas->AddTexFromMem("perlintex", 128, 128, CTextureAtlas::RGBA32, tex);
	blockMapTexNames.insert("perlintex");

	blockMapTexNames.insert("flare");
	blockMapTexNames.insert("explo");
	blockMapTexNames.insert("explofade");
	blockMapTexNames.insert("heatcloud");
	blockMapTexNames.insert("laserend");
	blockMapTexNames.insert("laserfalloff");
	blockMapTexNames.insert("randdots");
	blockMapTexNames.insert("smoketrail");
	blockMapTexNames.insert("wake");
	blockMapTexNames.insert("perlintex");
	blockMapTexNames.insert("flame");

	blockMapTexNames.insert("sbtrailtexture");
	blockMapTexNames.insert("missiletrailtexture");
	blockMapTexNames.insert("muzzleflametexture");
	blockMapTexNames.insert("repulsetexture");
	blockMapTexNames.insert("dguntexture");
	blockMapTexNames.insert("flareprojectiletexture");
	blockMapTexNames.insert("sbflaretexture");
	blockMapTexNames.insert("missileflaretexture");
	blockMapTexNames.insert("beamlaserflaretexture");
	blockMapTexNames.insert("bubbletexture");
	blockMapTexNames.insert("geosquaretexture");
	blockMapTexNames.insert("gfxtexture");
	blockMapTexNames.insert("projectiletexture");
	blockMapTexNames.insert("repulsegfxtexture");
	blockMapTexNames.insert("sphereparttexture");
	blockMapTexNames.insert("torpedotexture");
	blockMapTexNames.insert("wrecktexture");
	blockMapTexNames.insert("plasmatexture");

	// allow map specified atlas textures for gaia unit projectiles
	LuaParser mapResParser("gamedata/resources_map.lua",
	                              SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP);
	if (mapResParser.IsValid()) {
		const LuaTable mapRoot = mapResParser.GetRoot();
		const LuaTable mapTable = mapRoot.SubTable("projectileTextures");
		//add all textures in projectiletextures section
		map<string, string> mptex;
		mapTable.GetMap(mptex);
		map<string, string>::iterator pi;
		for (pi = mptex.begin(); pi != mptex.end(); ++pi) {
			if (blockMapTexNames.find(StringToLower(pi->first)) == blockMapTexNames.end()) {
				textureAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
			}
		}
		//add all texture from sections within projectiletextures section
		mapTable.GetKeys(seclist);
		for (size_t i = 0; i < seclist.size(); i++) {
			const LuaTable mapSubTable = mapTable.SubTable(seclist[i]);
			if (mapSubTable.IsValid()) {
				map<string, string> ptex2;
				mapSubTable.GetMap(ptex2);
				for (map<string, string>::iterator pi = ptex2.begin(); pi != ptex2.end(); ++pi) {
					if (blockMapTexNames.find(StringToLower(pi->first)) == blockMapTexNames.end()) {
						textureAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
					}
				}
			}
		}
	}

	if (!textureAtlas->Finalize()) {
		logOutput.Print("Could not finalize projectile texture atlas. Use less/smaller textures.");
	}

	flaretex        = textureAtlas->GetTexture("flare");
	explotex        = textureAtlas->GetTexture("explo");
	explofadetex    = textureAtlas->GetTexture("explofade");
	heatcloudtex    = textureAtlas->GetTexture("heatcloud");
	laserendtex     = textureAtlas->GetTexture("laserend");
	laserfallofftex = textureAtlas->GetTexture("laserfalloff");
	randdotstex     = textureAtlas->GetTexture("randdots");
	smoketrailtex   = textureAtlas->GetTexture("smoketrail");
	waketex         = textureAtlas->GetTexture("wake");
	perlintex       = textureAtlas->GetTexture("perlintex");
	flametex        = textureAtlas->GetTexture("flame");

	for (int i = 0; i < smokeCount; i++) {
		const string smokeName = "ismoke" + IntToString(i, "%02i");
		smoketex.push_back(textureAtlas->GetTexture(smokeName));
	}

#define GETTEX(t, b) textureAtlas->GetTextureWithBackup((t), (b))
	sbtrailtex         = GETTEX("sbtrailtexture",         "smoketrail"    );
	missiletrailtex    = GETTEX("missiletrailtexture",    "smoketrail"    );
	muzzleflametex     = GETTEX("muzzleflametexture",     "explo"         );
	repulsetex         = GETTEX("repulsetexture",         "explo"         );
	dguntex            = GETTEX("dguntexture",            "flare"         );
	flareprojectiletex = GETTEX("flareprojectiletexture", "flare"         );
	sbflaretex         = GETTEX("sbflaretexture",         "flare"         );
	missileflaretex    = GETTEX("missileflaretexture",    "flare"         );
	beamlaserflaretex  = GETTEX("beamlaserflaretexture",  "flare"         );
	bubbletex          = GETTEX("bubbletexture",          "circularthingy");
	geosquaretex       = GETTEX("geosquaretexture",       "circularthingy");
	gfxtex             = GETTEX("gfxtexture",             "circularthingy");
	projectiletex      = GETTEX("projectiletexture",      "circularthingy");
	repulsegfxtex      = GETTEX("repulsegfxtexture",      "circularthingy");
	sphereparttex      = GETTEX("sphereparttexture",      "circularthingy");
	torpedotex         = GETTEX("torpedotexture",         "circularthingy");
	wrecktex           = GETTEX("wrecktexture",           "circularthingy");
	plasmatex          = GETTEX("plasmatexture",          "circularthingy");
#undef GETTEX

	groundFXAtlas = new CTextureAtlas(2048, 2048);
	//add all textures in groundfx section
	const LuaTable groundfxTable = gfxTable.SubTable("groundfx");
	groundfxTable.GetMap(ptex);
	for (map<string, string>::iterator pi = ptex.begin(); pi != ptex.end(); ++pi) {
		groundFXAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
	}
	//add all texture from sections within groundfx section
	groundfxTable.GetKeys(seclist);
	for (size_t i = 0; i < seclist.size(); i++) {
		const LuaTable gfxSubTable = groundfxTable.SubTable(seclist[i]);
		if (gfxSubTable.IsValid()) {
			map<string, string> ptex2;
			gfxSubTable.GetMap(ptex2);
			for (map<string, string>::iterator pi = ptex2.begin(); pi != ptex2.end(); ++pi) {
				groundFXAtlas->AddTexFromFile(pi->first, "bitmaps/" + pi->second);
			}
		}
	}

	if (!groundFXAtlas->Finalize()) {
		logOutput.Print("Could not finalize groundFX texture atlas. Use less/smaller textures.");
	}

	groundflashtex = groundFXAtlas->GetTexture("groundflash");
	groundringtex = groundFXAtlas->GetTexture("groundring");
	seismictex = groundFXAtlas->GetTexture("seismic");

	if (shadowHandler->canUseShadows) {
		projectileShadowVP = LoadVertexProgram("projectileshadow.vp");
	}

	for (int a = 0; a < 4; ++a) {
		perlinBlend[a]=0;
	}

	unsigned char tempmem[4*16*16];
	for (int a = 0; a < 4 * 16 * 16; ++a) {
		tempmem[a] = 0;
	}
	for (int a = 0; a < 8; ++a) {
		glGenTextures(1, &perlinTex[a]);
		glBindTexture(GL_TEXTURE_2D, perlinTex[a]);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16,16, 0, GL_RGBA, GL_UNSIGNED_BYTE, tempmem);
	}

	drawPerlinTex=false;

	if (perlinFB.IsValid()) {
		//we never refresh the full texture (just the perlin part). So we need to reload it then.
		perlinFB.reloadOnAltTab = true;

		perlinFB.Bind();
		perlinFB.AttachTexture(textureAtlas->gltex);
		drawPerlinTex=perlinFB.CheckStatus("PERLIN");
		perlinFB.Unbind();
	}
}
Exemple #24
0
CMoveInfo::CMoveInfo()
{
	const LuaTable rootTable = game->defsParser->GetRoot().SubTable("MoveDefs");
	if (!rootTable.IsValid()) {
		throw content_error("Error loading movement definitions");
	}

	groundMoveMath = new CGroundMoveMath();
	hoverMoveMath = new CHoverMoveMath();
	seaMoveMath = new CShipMoveMath();

	moveInfoChecksum = 0;

	for (size_t num = 1; /* no test */; num++) {
		const LuaTable moveTable = rootTable.SubTable(num);
		if (!moveTable.IsValid()) {
			break;
		}

		MoveData* md = new MoveData(0x0, 0);

		md->name     = moveTable.GetString("name", "");
		md->pathType = (num - 1);
		md->maxSlope = 1.0f;
		md->depth    = 0.0f;
		md->depthMod = 0.0f;
		md->crushStrength = moveTable.GetFloat("crushStrength", 10.0f);

		const float minWaterDepth = moveTable.GetFloat("minWaterDepth", 10.0f);
		const float maxWaterDepth = moveTable.GetFloat("maxWaterDepth", 0.0f);

		if ((md->name.find("BOAT") != string::npos) ||
		    (md->name.find("SHIP") != string::npos)) {
			md->moveType   = MoveData::Ship_Move;
			md->depth      = minWaterDepth;
			md->moveFamily = MoveData::Ship;
			md->moveMath   = seaMoveMath;
			md->subMarine  = moveTable.GetBool("subMarine", 0);
		}
		else if (md->name.find("HOVER") != string::npos) {
			md->moveType   = MoveData::Hover_Move;
			md->maxSlope   = DegreesToMaxSlope(moveTable.GetFloat("maxSlope", 15.0f));
			md->moveFamily = MoveData::Hover;
			md->moveMath   = hoverMoveMath;
		}
		else {
			md->moveType = MoveData::Ground_Move;
			md->depthMod = moveTable.GetFloat("depthMod", 0.1f);
			md->depth    = maxWaterDepth;
			md->maxSlope = DegreesToMaxSlope(moveTable.GetFloat("maxSlope", 60.0f));
			md->moveMath = groundMoveMath;

			if (md->name.find("TANK") != string::npos) {
				md->moveFamily = MoveData::Tank;
			} else {
				md->moveFamily = MoveData::KBot;
			}
		}

		// ground units hug the ocean floor when in water,
		// ships stay at a "fixed" level (their waterline)
		md->followGround =
			(md->moveFamily == MoveData::Tank ||
			md->moveFamily == MoveData::KBot);

		// tank or bot that cannot get its threads / feet
		// wet, or hovercraft (which doesn't touch ground
		// or water)
		const bool b0 =
			((md->followGround && maxWaterDepth <= 0.0) ||
			md->moveFamily == MoveData::Hover);

		// ship (or sub) that cannot crawl onto shore, OR tank or
		// kbot restricted to snorkling (strange but possible)
		const bool b1 =
			((md->moveFamily == MoveData::Ship && minWaterDepth > 0.0) ||
			((md->followGround) && minWaterDepth > 0.0));

		// tank or kbot that CAN go skinny-dipping (amph.),
		// or ship that CAN sprout legs when at the beach
		const bool b2 =
			((md->followGround) && maxWaterDepth > 0.0) ||
			(md->moveFamily == MoveData::Ship && minWaterDepth < 0.0);

		if (b0) { md->terrainClass = MoveData::Land; }
		if (b1) { md->terrainClass = MoveData::Water; }
		if (b2) { md->terrainClass = MoveData::Mixed; }


		md->slopeMod = moveTable.GetFloat("slopeMod", 4.0f / (md->maxSlope + 0.001f));
		// TA has only half our resolution, multiply size by 2
		md->size = max(2, min(8, moveTable.GetInt("footprintX", 1) * 2));

		moveInfoChecksum +=
			(md->size         << 5) +
			(md->followGround << 4) +
			(md->subMarine    << 3) +
			(b2               << 2) +
			(b1               << 1) +
			(b0               << 0);
		moveInfoChecksum = moveInfoChecksum * 3 + *(unsigned int*) &md->maxSlope;
		moveInfoChecksum = moveInfoChecksum * 3 + *(unsigned int*) &md->slopeMod;
		moveInfoChecksum = moveInfoChecksum * 3 + *(unsigned int*) &md->depth;
		moveInfoChecksum = moveInfoChecksum * 3 + *(unsigned int*) &md->depthMod;
		moveInfoChecksum = moveInfoChecksum * 5 + *(unsigned int*) &md->crushStrength;

		moveData.push_back(md);
		name2moveData[md->name] = md->pathType;
	}

	for (int a = 0; a < 256; ++a) {
		terrainType2MoveFamilySpeed[a][0] = mapInfo->terrainTypes[a].tankSpeed;
		terrainType2MoveFamilySpeed[a][1] = mapInfo->terrainTypes[a].kbotSpeed;
		terrainType2MoveFamilySpeed[a][2] = mapInfo->terrainTypes[a].hoverSpeed;
		terrainType2MoveFamilySpeed[a][3] = mapInfo->terrainTypes[a].shipSpeed;
	}


	const float waterDamage = mapInfo->water.damage;
	if (waterDamage >= 1000.0f) {
		CGroundMoveMath::waterCost = 0.0f;
	} else {
		CGroundMoveMath::waterCost = 1.0f / (1.0f + waterDamage * 0.1f);
	}

	CHoverMoveMath::noWaterMove = (waterDamage >= 10000.0f);
}
void CCustomExplosionGenerator::Load(CExplosionGeneratorHandler* h, const string& tag)
{
	typedef std::map<string, CEGData> CEGMap;
	typedef std::map<string, CEGData>::iterator CEGMapIt;

	CEGMapIt it = cachedCEGs.find(tag);

	if (it == cachedCEGs.end()) {
		CEGData cegData;

		const LuaTable& root = h->GetTable();
		const LuaTable expTable = root.SubTable(tag);
		if (!expTable.IsValid()) {
			throw content_error("Explosion info for " + tag + " not found.");
		}

		vector<string> spawns;
		expTable.GetKeys(spawns);

		for (vector<string>::iterator si = spawns.begin(); si != spawns.end(); ++si) {
			ProjectileSpawnInfo psi;

			const string& spawnName = *si;
			const LuaTable spawnTable = expTable.SubTable(spawnName);

			if (!spawnTable.IsValid() || spawnName == "groundflash") {
				continue;
			}

			const string className = spawnTable.GetString("class", spawnName);

			psi.projectileClass = h->projectileClasses.GetClass(className);
			psi.flags = GetFlagsFromTable(spawnTable);
			psi.count = spawnTable.GetInt("count", 1);

			if (psi.projectileClass->binder->flags & creg::CF_Synced) {
				psi.flags |= SPW_SYNCED;
			}

			string code;
			map<string, string> props;
			map<string, string>::const_iterator propIt;
			spawnTable.SubTable("properties").GetMap(props);

			for (propIt = props.begin(); propIt != props.end(); ++propIt) {
				creg::Class::Member* m = psi.projectileClass->FindMember(propIt->first.c_str());
				if (m && (m->flags & creg::CM_Config)) {
					ParseExplosionCode(&psi, m->offset, m->type, propIt->second, code);
				}
			}

			code += (char)OP_END;
			psi.code.resize(code.size());
			copy(code.begin(), code.end(), psi.code.begin());

			cegData.projectileSpawn.push_back(psi);
		}

		const LuaTable gndTable = expTable.SubTable("groundflash");
		const int ttl = gndTable.GetInt("ttl", 0);
		if (ttl > 0) {
			cegData.groundFlash.circleAlpha  = gndTable.GetFloat("circleAlpha",  0.0f);
			cegData.groundFlash.flashSize    = gndTable.GetFloat("flashSize",    0.0f);
			cegData.groundFlash.flashAlpha   = gndTable.GetFloat("flashAlpha",   0.0f);
			cegData.groundFlash.circleGrowth = gndTable.GetFloat("circleGrowth", 0.0f);
			cegData.groundFlash.color        = gndTable.GetFloat3("color", float3(1.0f, 1.0f, 0.8f));

			cegData.groundFlash.flags = SPW_GROUND | GetFlagsFromTable(gndTable);
			cegData.groundFlash.ttl = ttl;
		}

		cegData.useDefaultExplosions = expTable.GetBool("useDefaultExplosions", false);
		it = cachedCEGs.insert(std::make_pair(tag, cegData)).first;
	}

	currentCEG = it;
}
Exemple #26
0
void CUnitDefHandler::ParseUnitDefTable(const LuaTable& udTable, const string& unitName, int id)
{
	UnitDef& ud = unitDefs[id];

	// allocate and fill ud->unitImage
	ud.buildPicName = udTable.GetString("buildPic", "");

	ud.humanName = udTable.GetString("name", "");

	if (ud.humanName.empty()) {
		const string errmsg = "missing 'name' parameter for the " + unitName + " unitdef";
		throw content_error(errmsg);
	}
	ud.filename  = udTable.GetString("filename", "");
	if (ud.filename.empty()) {
		const string errmsg = "missing 'filename' parameter for the" + unitName + " unitdef";
		throw content_error(errmsg);
	}
	ud.tooltip = udTable.GetString("description", ud.name);

	const string decoy = udTable.GetString("decoyFor", "");
	if (!decoy.empty()) {
		decoyNameMap[ud.name] = StringToLower(decoy);
	}

	ud.gaia = udTable.GetString("gaia", "");

	ud.isCommander = udTable.GetBool("commander", false);

	if (ud.isCommander && gameSetup) {
		ud.metalStorage  = udTable.GetFloat("metalStorage",  gameSetup->startMetal);
		ud.energyStorage = udTable.GetFloat("energyStorage", gameSetup->startEnergy);
	} else {
		ud.metalStorage  = udTable.GetFloat("metalStorage",  0.0f);
		ud.energyStorage = udTable.GetFloat("energyStorage", 0.0f);
	}

	ud.extractsMetal  = udTable.GetFloat("extractsMetal",  0.0f);
	ud.windGenerator  = udTable.GetFloat("windGenerator",  0.0f);
	ud.tidalGenerator = udTable.GetFloat("tidalGenerator", 0.0f);

	ud.metalUpkeep  = udTable.GetFloat("metalUse",   0.0f);
	ud.energyUpkeep = udTable.GetFloat("energyUse",  0.0f);
	ud.metalMake    = udTable.GetFloat("metalMake",  0.0f);
	ud.makesMetal   = udTable.GetFloat("makesMetal", 0.0f);
	ud.energyMake   = udTable.GetFloat("energyMake", 0.0f);

	ud.health       = udTable.GetFloat("maxDamage",  0.0f);
	ud.autoHeal     = udTable.GetFloat("autoHeal",      0.0f) * (16.0f / GAME_SPEED);
	ud.idleAutoHeal = udTable.GetFloat("idleAutoHeal", 10.0f) * (16.0f / GAME_SPEED);
	ud.idleTime     = udTable.GetInt("idleTime", 600);

	ud.buildangle = udTable.GetInt("buildAngle", 0);

	ud.isMetalMaker = (ud.makesMetal >= 1 && ud.energyUpkeep > ud.makesMetal * 40);

	ud.controlRadius = 32;
	ud.losHeight = 20;
	ud.metalCost = udTable.GetFloat("buildCostMetal", 0.0f);
	if (ud.metalCost < 1.0f) {
		ud.metalCost = 1.0f; //avoid some nasty divide by 0 etc
	}
	ud.mass = udTable.GetFloat("mass", 0.0f);
	if (ud.mass <= 0.0f) {
		ud.mass=ud.metalCost;
	}
	ud.energyCost = udTable.GetFloat("buildCostEnergy", 0.0f);
	ud.buildTime = udTable.GetFloat("buildTime", 0.0f);
	if (ud.buildTime < 1.0f) {
		ud.buildTime = 1.0f; //avoid some nasty divide by 0 etc
	}

	ud.aihint = id; // FIXME? (as noted in SelectedUnits.cpp, aihint is ignored)
	ud.cobID = udTable.GetInt("cobID", -1);

	ud.losRadius = udTable.GetFloat("sightDistance", 0.0f) * modInfo.losMul / (SQUARE_SIZE * (1 << modInfo.losMipLevel));
	ud.airLosRadius = udTable.GetFloat("airSightDistance", -1.0f);
	if (ud.airLosRadius == -1.0f) {
		ud.airLosRadius=udTable.GetFloat("sightDistance", 0.0f) * modInfo.airLosMul * 1.5f / (SQUARE_SIZE * (1 << modInfo.airMipLevel));
	} else {
		ud.airLosRadius = ud.airLosRadius * modInfo.airLosMul / (SQUARE_SIZE * (1 << modInfo.airMipLevel));
	}

	ud.canSubmerge = udTable.GetBool("canSubmerge", false);
	ud.canfly      = udTable.GetBool("canFly",      false);
	ud.canmove     = udTable.GetBool("canMove",     false);
	ud.reclaimable = udTable.GetBool("reclaimable", true);
	ud.capturable  = udTable.GetBool("capturable",  true);
	ud.repairable  = udTable.GetBool("repairable",  true);
	ud.canAttack   = udTable.GetBool("canAttack",   true);
	ud.canFight    = udTable.GetBool("canFight",    true);
	ud.canPatrol   = udTable.GetBool("canPatrol",   true);
	ud.canGuard    = udTable.GetBool("canGuard",    true);
	ud.canRepeat   = udTable.GetBool("canRepeat",   true);

	ud.builder = udTable.GetBool("builder", true);

	ud.canRestore = udTable.GetBool("canRestore", ud.builder);
	ud.canRepair  = udTable.GetBool("canRepair",  ud.builder);
	ud.canReclaim = udTable.GetBool("canReclaim", ud.builder);
	ud.canAssist  = udTable.GetBool("canAssist",  ud.builder);

	ud.canBeAssisted = udTable.GetBool("canBeAssisted", true);
	ud.canSelfRepair = udTable.GetBool("canSelfRepair", false);
	ud.fullHealthFactory = udTable.GetBool("fullHealthFactory", false);
	ud.factoryHeadingTakeoff = udTable.GetBool("factoryHeadingTakeoff", true);

	ud.upright = udTable.GetBool("upright", false);
	ud.collide = udTable.GetBool("collide", true);
	ud.onoffable = udTable.GetBool("onoffable", false);

	ud.maxSlope = udTable.GetFloat("maxSlope", 0.0f);
	ud.maxHeightDif = 40 * tan(ud.maxSlope * (PI / 180));
	ud.maxSlope = cos(ud.maxSlope * (PI / 180));
	ud.minWaterDepth = udTable.GetFloat("minWaterDepth", -10e6f);
	ud.maxWaterDepth = udTable.GetFloat("maxWaterDepth", +10e6f);
	ud.minCollisionSpeed = udTable.GetFloat("minCollisionSpeed", 1.0f);
	ud.slideTolerance = udTable.GetFloat("slideTolerance", 0.0f); // disabled
	ud.pushResistant = udTable.GetBool("pushResistant", false);

	ud.waterline = udTable.GetFloat("waterline", 0.0f);
	if ((ud.waterline >= 5.0f) && ud.canmove) {
		// make subs travel at somewhat larger depths
		// to reduce vulnerability to surface weapons
		ud.waterline += 10.0f;
	}

	ud.canSelfD = udTable.GetBool("canSelfDestruct", true);
	ud.selfDCountdown = udTable.GetInt("selfDestructCountdown", 5);

	ud.speed  = udTable.GetFloat("maxVelocity",  0.0f) * GAME_SPEED;
	ud.rSpeed = udTable.GetFloat("maxReverseVelocity", 0.0f) * GAME_SPEED;
	ud.speed  = fabs(ud.speed);
	ud.rSpeed = fabs(ud.rSpeed);

	ud.maxAcc = fabs(udTable.GetFloat("acceleration", 0.5f)); // no negative values
	ud.maxDec = fabs(udTable.GetFloat("brakeRate",    3.0f * ud.maxAcc)) * (ud.canfly? 0.1f: 1.0f); // no negative values

	ud.turnRate    = udTable.GetFloat("turnRate",     0.0f);
	ud.turnInPlace = udTable.GetBool( "turnInPlace",  true);
	ud.turnInPlaceDistance = udTable.GetFloat("turnInPlaceDistance", 350.f);
	ud.turnInPlaceSpeedLimit = udTable.GetFloat("turnInPlaceSpeedLimit", 15.f);

	const bool noAutoFire  = udTable.GetBool("noAutoFire",  false);
	ud.canFireControl = udTable.GetBool("canFireControl", !noAutoFire);
	ud.fireState = udTable.GetInt("fireState", ud.canFireControl ? -1 : 2);
	ud.fireState = std::min(ud.fireState,2);
	ud.moveState = udTable.GetInt("moveState", (ud.canmove && ud.speed>0.0f)  ? -1 : 1);
	ud.moveState = std::min(ud.moveState,2);

	ud.buildRange3D = udTable.GetBool("buildRange3D", false);
	ud.buildDistance = udTable.GetFloat("buildDistance", 128.0f);
	ud.buildDistance = std::max(128.0f, ud.buildDistance);
	ud.buildSpeed = udTable.GetFloat("workerTime", 0.0f);

	ud.repairSpeed    = udTable.GetFloat("repairSpeed",    ud.buildSpeed);
	ud.maxRepairSpeed = udTable.GetFloat("maxRepairSpeed", 1e20f);
	ud.reclaimSpeed   = udTable.GetFloat("reclaimSpeed",   ud.buildSpeed);
	ud.resurrectSpeed = udTable.GetFloat("resurrectSpeed", ud.buildSpeed);
	ud.captureSpeed   = udTable.GetFloat("captureSpeed",   ud.buildSpeed);
	ud.terraformSpeed = udTable.GetFloat("terraformSpeed", ud.buildSpeed);

	ud.flankingBonusMode = udTable.GetInt("flankingBonusMode", modInfo.flankingBonusModeDefault);
	ud.flankingBonusMax  = udTable.GetFloat("flankingBonusMax", 1.9f);
	ud.flankingBonusMin  = udTable.GetFloat("flankingBonusMin", 0.9);
	ud.flankingBonusDir  = udTable.GetFloat3("flankingBonusDir", float3(0.0f, 0.0f, 1.0f));
	ud.flankingBonusMobilityAdd = udTable.GetFloat("flankingBonusMobilityAdd", 0.01f);

	ud.armoredMultiple = udTable.GetFloat("damageModifier", 1.0f);
	ud.armorType = damageArrayHandler->GetTypeFromName(ud.name);

	ud.radarRadius    = udTable.GetInt("radarDistance",    0);
	ud.sonarRadius    = udTable.GetInt("sonarDistance",    0);
	ud.jammerRadius   = udTable.GetInt("radarDistanceJam", 0);
	ud.sonarJamRadius = udTable.GetInt("sonarDistanceJam", 0);

	ud.stealth        = udTable.GetBool("stealth",            false);
	ud.sonarStealth   = udTable.GetBool("sonarStealth",       false);
	ud.targfac        = udTable.GetBool("isTargetingUpgrade", false);
	ud.isFeature      = udTable.GetBool("isFeature",          false);
	ud.canResurrect   = udTable.GetBool("canResurrect",       false);
	ud.canCapture     = udTable.GetBool("canCapture",         false);
	ud.hideDamage     = udTable.GetBool("hideDamage",         false);
	ud.showPlayerName = udTable.GetBool("showPlayerName",     false);

	ud.cloakCost = udTable.GetFloat("cloakCost", -1.0f);
	ud.cloakCostMoving = udTable.GetFloat("cloakCostMoving", -1.0f);
	if (ud.cloakCostMoving < 0) {
		ud.cloakCostMoving = ud.cloakCost;
	}
	ud.canCloak = (ud.cloakCost >= 0);

	ud.startCloaked     = udTable.GetBool("initCloaked", false);
	ud.decloakDistance  = udTable.GetFloat("minCloakDistance", 0.0f);
	ud.decloakSpherical = udTable.GetBool("decloakSpherical", true);
	ud.decloakOnFire    = udTable.GetBool("decloakOnFire",    true);

	ud.highTrajectoryType = udTable.GetInt("highTrajectory", 0);

	ud.canKamikaze = udTable.GetBool("kamikaze", false);
	ud.kamikazeDist = udTable.GetFloat("kamikazeDistance", -25.0f) + 25.0f; //we count 3d distance while ta count 2d distance so increase slightly

	ud.showNanoFrame = udTable.GetBool("showNanoFrame", true);
	ud.showNanoSpray = udTable.GetBool("showNanoSpray", true);
	ud.nanoColor = udTable.GetFloat3("nanoColor", float3(0.2f,0.7f,0.2f));

	ud.canhover = udTable.GetBool("canHover", false);

	ud.floater = udTable.GetBool("floater", udTable.KeyExists("WaterLine"));

	ud.builder = udTable.GetBool("builder", false);
	if (ud.builder && !ud.buildSpeed) { // core anti is flagged as builder for some reason
		ud.builder = false;
	}

	ud.airStrafe     = udTable.GetBool("airStrafe", true);
	ud.hoverAttack   = udTable.GetBool("hoverAttack", false);
	ud.wantedHeight  = udTable.GetFloat("cruiseAlt", 0.0f);
	ud.dlHoverFactor = udTable.GetFloat("airHoverFactor", -1.0f);
	ud.bankingAllowed = udTable.GetBool("bankingAllowed", true);

	ud.transportSize     = udTable.GetInt("transportSize",      0);
	ud.minTransportSize  = udTable.GetInt("minTransportSize",   0);
	ud.transportCapacity = udTable.GetInt("transportCapacity",  0);
	ud.isFirePlatform    = udTable.GetBool("isFirePlatform",    false);
	ud.isAirBase         = udTable.GetBool("isAirBase",         false);
	ud.loadingRadius     = udTable.GetFloat("loadingRadius",    220.0f);
	ud.unloadSpread      = udTable.GetFloat("unloadSpread",     1.0f);
	ud.transportMass     = udTable.GetFloat("transportMass",    100000.0f);
	ud.minTransportMass  = udTable.GetFloat("minTransportMass", 0.0f);
	ud.holdSteady        = udTable.GetBool("holdSteady",        true);
	ud.releaseHeld       = udTable.GetBool("releaseHeld",       false);
	ud.cantBeTransported = udTable.GetBool("cantBeTransported", false);
	ud.transportByEnemy  = udTable.GetBool("transportByEnemy",  true);
	ud.fallSpeed         = udTable.GetFloat("fallSpeed",    0.2);
	ud.unitFallSpeed     = udTable.GetFloat("unitFallSpeed",  0);
	ud.transportUnloadMethod	= udTable.GetInt("transportUnloadMethod" , 0);

	// modrules transport settings
	if ((!modInfo.transportAir    && ud.canfly)   ||
	    (!modInfo.transportShip   && ud.floater)  ||
	    (!modInfo.transportHover  && ud.canhover) ||
	    (!modInfo.transportGround && !ud.canhover && !ud.floater && !ud.canfly)) {
 		ud.cantBeTransported = true;
	}

	ud.wingDrag     = udTable.GetFloat("wingDrag",     0.07f);  // drag caused by wings
	ud.wingDrag = std::min(1.0f, std::max(0.0f, ud.wingDrag));
	ud.wingAngle    = udTable.GetFloat("wingAngle",    0.08f);  // angle between front and the wing plane
	ud.frontToSpeed = udTable.GetFloat("frontToSpeed", 0.1f);   // fudge factor for lining up speed and front of plane
	ud.speedToFront = udTable.GetFloat("speedToFront", 0.07f);  // fudge factor for lining up speed and front of plane
	ud.myGravity    = udTable.GetFloat("myGravity",    0.4f);   // planes are slower than real airplanes so lower gravity to compensate
	ud.crashDrag    = udTable.GetFloat("crashDrag",0.005f);     // drag used when crashing
	ud.crashDrag = std::min(1.0f, std::max(0.0f, ud.crashDrag));

	ud.maxBank = udTable.GetFloat("maxBank", 0.8f);         // max roll
	ud.maxPitch = udTable.GetFloat("maxPitch", 0.45f);      // max pitch this plane tries to keep
	ud.turnRadius = udTable.GetFloat("turnRadius", 500.0f); // hint to the ai about how large turn radius this plane needs
	ud.verticalSpeed = udTable.GetFloat("verticalSpeed", 3.0f); // speed of takeoff and landing, at least for gunships

	ud.maxAileron  = udTable.GetFloat("maxAileron",  0.015f); // turn speed around roll axis
	ud.maxElevator = udTable.GetFloat("maxElevator", 0.01f);  // turn speed around pitch axis
	ud.maxRudder   = udTable.GetFloat("maxRudder",   0.004f); // turn speed around yaw axis

	ud.maxFuel = udTable.GetFloat("maxFuel", 0.0f); //max flight time in seconds before aircraft must return to base
	ud.refuelTime = udTable.GetFloat("refuelTime", 5.0f);
	ud.minAirBasePower = udTable.GetFloat("minAirBasePower", 0.0f);
	ud.maxThisUnit = udTable.GetInt("unitRestricted", MAX_UNITS);

	string lname = StringToLower(ud.name);

	if (gameSetup->restrictedUnits.find(lname) != gameSetup->restrictedUnits.end()) {
		ud.maxThisUnit = std::min(ud.maxThisUnit, gameSetup->restrictedUnits.find(lname)->second);
	}

	ud.categoryString = udTable.GetString("category", "");
	ud.category = CCategoryHandler::Instance()->GetCategories(udTable.GetString("category", ""));
	ud.noChaseCategory = CCategoryHandler::Instance()->GetCategories(udTable.GetString("noChaseCategory", ""));
//	logOutput.Print("Unit %s has cat %i",ud.humanName.c_str(),ud.category);

	const string iconName = udTable.GetString("iconType", "default");
	ud.iconType = iconHandler->GetIcon(iconName);

	ud.shieldWeaponDef    = NULL;
	ud.stockpileWeaponDef = NULL;

	ud.maxWeaponRange = 0.0f;
	ud.maxCoverage = 0.0f;

	const WeaponDef* noWeaponDef = weaponDefHandler->GetWeapon("NOWEAPON");

	LuaTable weaponsTable = udTable.SubTable("weapons");
	for (int w = 0; w < COB_MaxWeapons; w++) {
		LuaTable wTable;
		string name = weaponsTable.GetString(w + 1, "");
		if (name.empty()) {
			wTable = weaponsTable.SubTable(w + 1);
			name = wTable.GetString("name", "");
		}
		const WeaponDef* wd = NULL;
		if (!name.empty()) {
			wd = weaponDefHandler->GetWeapon(name);
		}
		if (wd == NULL) {
			if (w <= 3) {
				continue; // allow empty weapons among the first 3
			} else {
				break;
			}
		}

		while (ud.weapons.size() < w) {
			if (!noWeaponDef) {
				logOutput.Print("Error: Spring requires a NOWEAPON weapon type "
				                "to be present as a placeholder for missing weapons");
				break;
			} else {
				ud.weapons.push_back(UnitDef::UnitDefWeapon());
				ud.weapons.back().def = noWeaponDef;
			}
		}

		const string badTarget = wTable.GetString("badTargetCategory", "");
		unsigned int btc = CCategoryHandler::Instance()->GetCategories(badTarget);

		const string onlyTarget = wTable.GetString("onlyTargetCategory", "");
		unsigned int otc;
		if (onlyTarget.empty()) {
			otc = 0xffffffff;
		} else {
			otc = CCategoryHandler::Instance()->GetCategories(onlyTarget);
		}

		const unsigned int slaveTo = wTable.GetInt("slaveTo", 0);

		float3 mainDir = wTable.GetFloat3("mainDir", float3(1.0f, 0.0f, 0.0f));
		mainDir.SafeNormalize();

		const float angleDif = cos(wTable.GetFloat("maxAngleDif", 360.0f) * (PI / 360.0f));

		const float fuelUse = wTable.GetFloat("fuelUsage", 0.0f);

		ud.weapons.push_back(UnitDef::UnitDefWeapon(name, wd, slaveTo, mainDir,
		                                            angleDif, btc, otc, fuelUse));

		if (wd->range > ud.maxWeaponRange) {
			ud.maxWeaponRange = wd->range;
		}
		if (wd->interceptor && wd->coverageRange > ud.maxCoverage) {
			ud.maxCoverage = wd->coverageRange;
		}
		if (wd->isShield) {
			if (!ud.shieldWeaponDef || // use the biggest shield
			    (ud.shieldWeaponDef->shieldRadius < wd->shieldRadius)) {
				ud.shieldWeaponDef = wd;
			}
		}
		if (wd->stockpile) {
			// interceptors have priority
			if (wd->interceptor        ||
			    !ud.stockpileWeaponDef ||
			    !ud.stockpileWeaponDef->interceptor) {
				ud.stockpileWeaponDef = wd;
			}
		}
	}

	ud.canDGun = udTable.GetBool("canDGun", false);

	string TEDClass = udTable.GetString("TEDClass", "0");
	ud.TEDClassString = TEDClass;

	ud.extractRange = 0.0f;
	ud.extractSquare = udTable.GetBool("extractSquare", false);

	if (ud.extractsMetal) {
		ud.extractRange = mapInfo->map.extractorRadius;
		ud.type = "MetalExtractor";
	}
	else if (ud.transportCapacity) {
		ud.type = "Transport";
	}
	else if (ud.builder) {
		if (TEDClass != "PLANT") {
			ud.type = "Builder";
		} else {
			ud.type = "Factory";
		}
	}
	else if (ud.canfly && !ud.hoverAttack) {
		if (!ud.weapons.empty() && (ud.weapons[0].def != 0) &&
		   (ud.weapons[0].def->type=="AircraftBomb" || ud.weapons[0].def->type=="TorpedoLauncher")) {
			ud.type = "Bomber";
			if (ud.turnRadius == 500) { // only reset it if user hasnt set it explicitly
				ud.turnRadius = 1000;     // hint to the ai about how large turn radius this plane needs
			}
		} else {
			ud.type = "Fighter";
		}
		ud.maxAcc = udTable.GetFloat("maxAcc", 0.065f); // engine power
	}
	else if (ud.canmove) {
		ud.type = "GroundUnit";
	}
	else {
		ud.type = "Building";
	}

	ud.movedata = 0;
	if (ud.canmove && !ud.canfly && (ud.type != "Factory")) {
		string moveclass = StringToLower(udTable.GetString("movementClass", ""));
		ud.movedata = moveinfo->GetMoveDataFromName(moveclass);

		if (!ud.movedata) {
			const string errmsg = "WARNING: Couldn't find a MoveClass named " + moveclass + " (used in UnitDef: " + unitName + ")";
			logOutput.Print(errmsg);
			// remove the UnitDef
			throw content_error(errmsg);
		}

		if ((ud.movedata->moveType == MoveData::Hover_Move) ||
		    (ud.movedata->moveType == MoveData::Ship_Move)) {
			ud.upright = true;
		}
		if (ud.canhover) {
			if (ud.movedata->moveType != MoveData::Hover_Move) {
				logOutput.Print("Inconsistent movedata %i for %s (moveclass %s): canhover, but not a hovercraft movetype",
				     ud.movedata->pathType, ud.name.c_str(), moveclass.c_str());
			}
		} else if (ud.floater) {
			if (ud.movedata->moveType != MoveData::Ship_Move) {
				logOutput.Print("Inconsistent movedata %i for %s (moveclass %s): floater, but not a ship movetype",
				     ud.movedata->pathType, ud.name.c_str(), moveclass.c_str());
			}
		} else {
			if (ud.movedata->moveType != MoveData::Ground_Move) {
				logOutput.Print("Inconsistent movedata %i for %s (moveclass %s): neither canhover nor floater, but not a ground movetype",
				     ud.movedata->pathType, ud.name.c_str(), moveclass.c_str());
			}
		}
	}

	if ((ud.maxAcc != 0) && (ud.speed != 0)) {
		//meant to set the drag such that the maxspeed becomes what it should be
		ud.drag = 1.0f / (ud.speed/GAME_SPEED * 1.1f / ud.maxAcc)
		          - (ud.wingAngle * ud.wingAngle * ud.wingDrag);
		ud.drag = std::min(1.0f, std::max(0.0f, ud.drag));
	} else {
		//shouldn't be needed since drag is only used in CAirMoveType anyway,
		//and aircraft without acceleration or speed aren't common :)
		//initializing it anyway just for safety
		ud.drag = 0.005f;
	}

	std::string objectname = udTable.GetString("objectName", "");
	if (objectname.find(".") == std::string::npos) {
		objectname += ".3do";
	}
	ud.modelDef.modelpath = "objects3d/" + objectname;
	ud.modelDef.modelname = objectname;

	ud.scriptName = udTable.GetString("script", unitName + ".cob");
	ud.scriptPath = "scripts/" + ud.scriptName;

	ud.wreckName = udTable.GetString("corpse", "");
	ud.deathExplosion = udTable.GetString("explodeAs", "");
	ud.selfDExplosion = udTable.GetString("selfDestructAs", "");

	ud.power = udTable.GetFloat("power", (ud.metalCost + (ud.energyCost / 60.0f)));

	// Prevent a division by zero in experience calculations.
	if (ud.power < 1.0e-3f) {
		logOutput.Print("Unit %s is really cheap? %f", ud.humanName.c_str(), ud.power);
		logOutput.Print("This can cause a division by zero in experience calculations.");
		ud.power = 1.0e-3f;
	}

	ud.activateWhenBuilt = udTable.GetBool("activateWhenBuilt", false);

	// TA has only half our res so multiply size with 2
	ud.xsize = udTable.GetInt("footprintX", 1) * 2;
	ud.zsize = udTable.GetInt("footprintZ", 1) * 2;

	ud.needGeo = false;
	if ((ud.type == "Building") || (ud.type == "Factory")) {
		CreateYardMap(&ud, udTable.GetString("yardMap", "c"));
	} else {
		for (int u = 0; u < 4; u++) {
			ud.yardmaps[u] = 0;
		}
	}

	ud.leaveTracks   = udTable.GetBool("leaveTracks", false);
	ud.trackWidth    = udTable.GetFloat("trackWidth",   32.0f);
	ud.trackOffset   = udTable.GetFloat("trackOffset",   0.0f);
	ud.trackStrength = udTable.GetFloat("trackStrength", 0.0f);
	ud.trackStretch  = udTable.GetFloat("trackStretch",  1.0f);
	if (ud.leaveTracks && groundDecals) {
		ud.trackType = groundDecals->GetTrackType(udTable.GetString("trackType", "StdTank"));
	}

	ud.useBuildingGroundDecal = udTable.GetBool("useBuildingGroundDecal", false);
	ud.buildingDecalSizeX = udTable.GetInt("buildingGroundDecalSizeX", 4);
	ud.buildingDecalSizeY = udTable.GetInt("buildingGroundDecalSizeY", 4);
	ud.buildingDecalDecaySpeed = udTable.GetFloat("buildingGroundDecalDecaySpeed", 0.1f);
	if (ud.useBuildingGroundDecal && groundDecals) {
		ud.buildingDecalType = groundDecals->GetBuildingDecalType(udTable.GetString("buildingGroundDecalType", ""));
	}

	ud.canDropFlare    = udTable.GetBool("canDropFlare", false);
	ud.flareReloadTime = udTable.GetFloat("flareReload",     5.0f);
	ud.flareDelay      = udTable.GetFloat("flareDelay",      0.3f);
	ud.flareEfficiency = udTable.GetFloat("flareEfficiency", 0.5f);
	ud.flareDropVector = udTable.GetFloat3("flareDropVector", ZeroVector);
	ud.flareTime       = udTable.GetInt("flareTime", 3) * GAME_SPEED;
	ud.flareSalvoSize  = udTable.GetInt("flareSalvoSize",  4);
	ud.flareSalvoDelay = udTable.GetInt("flareSalvoDelay", 0) * GAME_SPEED;

	ud.smoothAnim = udTable.GetBool("smoothAnim", false);
	ud.canLoopbackAttack = udTable.GetBool("canLoopbackAttack", false);
	ud.canCrash = udTable.GetBool("canCrash", true);
	ud.levelGround = udTable.GetBool("levelGround", true);
	ud.strafeToAttack = udTable.GetBool("strafeToAttack", false);


	ud.modelCenterOffset = udTable.GetFloat3("modelCenterOffset", ZeroVector);

	ud.collisionVolumeTypeStr   = udTable.GetString("collisionVolumeType", "");
	ud.collisionVolumeScales    = udTable.GetFloat3("collisionVolumeScales", ZeroVector);
	ud.collisionVolumeOffsets   = udTable.GetFloat3("collisionVolumeOffsets", ZeroVector);
	ud.collisionVolumeTest      = udTable.GetInt("collisionVolumeTest", COLVOL_TEST_DISC);
	ud.usePieceCollisionVolumes = udTable.GetBool("usePieceCollisionVolumes", false);

	// initialize the (per-unitdef) collision-volume
	// all CUnit instances hold a copy of this object
	ud.collisionVolume = new CollisionVolume(
		ud.collisionVolumeTypeStr,
		ud.collisionVolumeScales,
		ud.collisionVolumeOffsets,
		ud.collisionVolumeTest
	);

	if (ud.usePieceCollisionVolumes) {
		ud.collisionVolume->Disable();
	}


	ud.seismicRadius    = udTable.GetInt("seismicDistance", 0);
	ud.seismicSignature = udTable.GetFloat("seismicSignature", -1.0f);
	if (ud.seismicSignature == -1.0f) {
		if (!ud.floater && !ud.canhover && !ud.canfly) {
			ud.seismicSignature = sqrt(ud.mass / 100.0f);
		} else {
			ud.seismicSignature = 0.0f;
		}
	}

	LuaTable buildsTable = udTable.SubTable("buildOptions");
	if (buildsTable.IsValid()) {
		for (int bo = 1; true; bo++) {
			const string order = buildsTable.GetString(bo, "");
			if (order.empty()) {
				break;
			}
			ud.buildOptions[bo] = order;
		}
	}

	LuaTable sfxTable = udTable.SubTable("SFXTypes");
	LuaTable expTable = sfxTable.SubTable("explosionGenerators");
	for (int expNum = 1; expNum <= 1024; expNum++) {
		string expsfx = expTable.GetString(expNum, "");
		if (expsfx == "") {
			break;
		} else {
			ud.sfxExplGens.push_back(explGenHandler->LoadGenerator(expsfx));
		}
	}

	// we use range in a modulo operation, so it needs to be >= 1
	ud.pieceTrailCEGTag = udTable.GetString("pieceTrailCEGTag", "");
	ud.pieceTrailCEGRange = udTable.GetInt("pieceTrailCEGRange", 1);
	ud.pieceTrailCEGRange = std::max(ud.pieceTrailCEGRange, 1);

	LuaTable soundsTable = udTable.SubTable("sounds");

	LoadSounds(soundsTable, ud.sounds.ok,          "ok");      // eg. "ok1", "ok2", ...
	LoadSounds(soundsTable, ud.sounds.select,      "select");  // eg. "select1", "select2", ...
	LoadSounds(soundsTable, ud.sounds.arrived,     "arrived"); // eg. "arrived1", "arrived2", ...
	LoadSounds(soundsTable, ud.sounds.build,       "build");
	LoadSounds(soundsTable, ud.sounds.activate,    "activate");
	LoadSounds(soundsTable, ud.sounds.deactivate,  "deactivate");
	LoadSounds(soundsTable, ud.sounds.cant,        "cant");
	LoadSounds(soundsTable, ud.sounds.underattack, "underattack");

	// custom parameters table
	udTable.SubTable("customParams").GetMap(ud.customParams);
}
Exemple #27
0
CUnitDefHandler::CUnitDefHandler(void) : noCost(false)
{
	weaponDefHandler = new CWeaponDefHandler();

	PrintLoadMsg("Loading unit definitions");

	const LuaTable rootTable = game->defsParser->GetRoot().SubTable("UnitDefs");
	if (!rootTable.IsValid()) {
		throw content_error("Error loading UnitDefs");
	}

	vector<string> unitDefNames;
	rootTable.GetKeys(unitDefNames);

	numUnitDefs = unitDefNames.size();

	/*
	// ?? "restricted" does not automatically mean "cannot be built
	// at all, so we don't need the unitdef for this unit" -- Kloot
	numUnitDefs -= gameSetup->restrictedUnits.size();
	*/

	// This could be wasteful if there is a lot of restricted units, but that is not that likely
	unitDefs = new UnitDef[numUnitDefs + 1];

	// start at unitdef id 1
	unsigned int id = 1;

	for (unsigned int a = 0; a < unitDefNames.size(); ++a) {
		const string unitName = unitDefNames[a];

		/*
		// Restrictions may tell us not to use this unit at all
		// FIXME: causes mod errors when a unit is restricted to
		// 0, since GetUnitByName() will return NULL if its UnitDef
		// has not been loaded -- Kloot
		const std::map<std::string, int>& resUnits = gameSetup->restrictedUnits;

		if ((resUnits.find(unitName) != resUnits.end()) &&
			(resUnits.find(unitName)->second == 0)) {
			continue;
		}
		*/

		// Seems ok, load it
		unitDefs[id].valid = false;
		unitDefs[id].name = unitName;
		unitDefs[id].id = id;
		unitDefs[id].buildangle = 0;
		unitDefs[id].buildPic   = NULL;
		unitDefs[id].decoyDef   = NULL;
		unitDefs[id].techLevel  = -1;
		unitDefs[id].collisionVolume = NULL;
		unitID[unitName] = id;
		for (int ym = 0; ym < 4; ym++) {
			unitDefs[id].yardmaps[ym] = 0;
		}

		// parse the unitdef data (but don't load buildpics, etc...)
		LuaTable udTable = rootTable.SubTable(unitName);
		ParseUnitDef(udTable, unitName, id);

		// Increase index for next unit
		id++;
	}

	// set the real number of unitdefs
	numUnitDefs = (id - 1);

	CleanBuildOptions();
	FindStartUnits();
	ProcessDecoys();
	AssignTechLevels();
}
Exemple #28
0
void CMapInfo::ReadWater()
{
	const LuaTable& wt = parser->GetRoot().SubTable("water");

	water.repeatX = wt.GetFloat("repeatX", 0.0f);
	water.repeatY = wt.GetFloat("repeatY", 0.0f);
	water.damage  = wt.GetFloat("damage",  0.0f) * (16.0f / GAME_SPEED);

	water.absorb    = wt.GetFloat3("absorb",    float3(0.0f, 0.0f, 0.0f));
	water.baseColor = wt.GetFloat3("baseColor", float3(0.0f, 0.0f, 0.0f));
	water.minColor  = wt.GetFloat3("minColor",  float3(0.0f, 0.0f, 0.0f));

	water.ambientFactor = wt.GetFloat("ambientFactor", 1.0f);
	water.diffuseFactor = wt.GetFloat("diffuseFactor", 1.0f);
	water.specularFactor= wt.GetFloat("specularFactor",1.0f);
	water.specularPower = wt.GetFloat("specularPower", 20.0f);

	water.planeColor    = wt.GetFloat3("planeColor", float3(0.0f, 0.4f, 0.0f));
	water.hasWaterPlane = wt.KeyExists("planeColor");

	water.surfaceColor  = wt.GetFloat3("surfaceColor", float3(0.75f, 0.8f, 0.85f));
	water.surfaceAlpha  = wt.GetFloat("surfaceAlpha",  0.55f);
	water.diffuseColor  = wt.GetFloat3("diffuseColor",  float3(1.0f, 1.0f, 1.0f));
	water.specularColor = wt.GetFloat3("specularColor", light.groundSunColor);

	water.fresnelMin   = wt.GetFloat("fresnelMin",   0.2f);
	water.fresnelMax   = wt.GetFloat("fresnelMax",   0.8f);
	water.fresnelPower = wt.GetFloat("fresnelPower", 4.0f);

	water.reflDistortion = wt.GetFloat("reflectionDistortion", 1.0f);

	water.blurBase     = wt.GetFloat("blurBase", 2.0f);
	water.blurExponent = wt.GetFloat("blurExponent", 1.5f);

	water.perlinStartFreq  = wt.GetFloat("perlinStartFreq",  8.0f);
	water.perlinLacunarity = wt.GetFloat("perlinLacunarity", 3.0f);
	water.perlinAmplitude  = wt.GetFloat("perlinAmplitude",  0.9f);
	water.windSpeed        = wt.GetFloat("windSpeed", 1.0f);

	water.texture       = wt.GetString("texture",       "");
	water.foamTexture   = wt.GetString("foamTexture",   "");
	water.normalTexture = wt.GetString("normalTexture", "");

	water.shoreWaves = wt.GetBool("shoreWaves", true);

	water.forceRendering = wt.GetBool("forceRendering", false);

	// use 'resources.lua' for missing fields  (our the engine defaults)
	const LuaTable& resGfxMaps = resRoot->SubTable("graphics").SubTable("maps");

	if (!water.texture.empty()) {
		water.texture = "maps/" + water.texture;
	} else {
		water.texture = "bitmaps/" + resGfxMaps.GetString("watertex", "ocean.jpg");
	}

	if (!water.foamTexture.empty()) {
		water.foamTexture = "maps/" + water.foamTexture;
	} else {
		water.foamTexture = "bitmaps/" + resGfxMaps.GetString("waterfoamtex", "foam.jpg");
	}

	if (!water.normalTexture.empty()) {
		water.normalTexture = "maps/" + water.normalTexture;
		water.numTiles    = std::min(16,std::max(1,wt.GetInt("numTiles",1)));
	} else {
		water.normalTexture = "bitmaps/" + resGfxMaps.GetString("waternormaltex", "waterbump.png");
		if (resGfxMaps.KeyExists("waternormaltex")) {
			water.numTiles = std::min(16,std::max(1,resGfxMaps.GetInt("numTiles",1)));
		}else{
			// default texture is a TileSet of 3x3
			// user-defined textures are expected to be 1x1 (no DynWaves possible)
			water.numTiles = 3;
		}
	}

	// water caustic textures
	LuaTable caustics = wt.SubTable("caustics");
	string causticPrefix = "maps/";
	if (!caustics.IsValid()) {
		caustics = resRoot->SubTable("graphics").SubTable("caustics");
		causticPrefix = "bitmaps/";
	}
	if (caustics.IsValid()) {
		for (int i = 1; true; i++) {
			const string texName = caustics.GetString(i, "");
			if (texName.empty()) {
				break;
			}
			water.causticTextures.push_back(causticPrefix + texName);
		}
	} else {
		// load the default 32 textures
		for (int i = 0; i < 32; i++) {
			char defTex[256];
			sprintf(defTex, "bitmaps/caustics/caustic%02i.jpg", i);
			water.causticTextures.push_back(defTex);
		}
	}
}
Exemple #29
0
UnitDef::UnitDef(const LuaTable& udTable, const std::string& unitName, int id)
: name(unitName)
, id(id)
, collisionVolume(NULL)
, decoyDef(NULL)
, techLevel(-1)
, buildPic(NULL)
, buildangle(0)
{
	humanName = udTable.GetString("name", "");
	if (humanName.empty()) {
		const string errmsg = "missing 'name' parameter for the " + unitName + " unitdef";
		throw content_error(errmsg);
	}
	filename  = udTable.GetString("filename", "");
	if (filename.empty()) {
		const string errmsg = "missing 'filename' parameter for the" + unitName + " unitdef";
		throw content_error(errmsg);
	}
	tooltip = udTable.GetString("description", name);
	buildPicName = udTable.GetString("buildPic", "");

	decoyName = udTable.GetString("decoyFor", "");
	gaia = udTable.GetString("gaia", "");

	isCommander = udTable.GetBool("commander", false);

	metalStorage  = udTable.GetFloat("metalStorage",  0.0f);
	energyStorage = udTable.GetFloat("energyStorage", 0.0f);

	extractsMetal  = udTable.GetFloat("extractsMetal",  0.0f);
	windGenerator  = udTable.GetFloat("windGenerator",  0.0f);
	tidalGenerator = udTable.GetFloat("tidalGenerator", 0.0f);

	metalUpkeep  = udTable.GetFloat("metalUse",   0.0f);
	energyUpkeep = udTable.GetFloat("energyUse",  0.0f);
	metalMake    = udTable.GetFloat("metalMake",  0.0f);
	makesMetal   = udTable.GetFloat("makesMetal", 0.0f);
	energyMake   = udTable.GetFloat("energyMake", 0.0f);

	health       = udTable.GetFloat("maxDamage",  0.0f);
	autoHeal     = udTable.GetFloat("autoHeal",      0.0f) * (16.0f / GAME_SPEED);
	idleAutoHeal = udTable.GetFloat("idleAutoHeal", 10.0f) * (16.0f / GAME_SPEED);
	idleTime     = udTable.GetInt("idleTime", 600);

	buildangle = udTable.GetInt("buildAngle", 0);

	losHeight = 20;
	metalCost = udTable.GetFloat("buildCostMetal", 0.0f);
	if (metalCost < 1.0f) {
		metalCost = 1.0f; //avoid some nasty divide by 0 etc
	}
	mass = udTable.GetFloat("mass", 0.0f);
	if (mass <= 0.0f) {
		mass = metalCost;
	}
	energyCost = udTable.GetFloat("buildCostEnergy", 0.0f);
	buildTime = udTable.GetFloat("buildTime", 0.0f);
	if (buildTime < 1.0f) {
		buildTime = 1.0f; //avoid some nasty divide by 0 etc
	}

	aihint = id; // FIXME? (as noted in SelectedUnits.cpp, aihint is ignored)
	cobID = udTable.GetInt("cobID", -1);

	losRadius = udTable.GetFloat("sightDistance", 0.0f) * modInfo.losMul / (SQUARE_SIZE * (1 << modInfo.losMipLevel));
	airLosRadius = udTable.GetFloat("airSightDistance", -1.0f);
	if (airLosRadius == -1.0f) {
		airLosRadius = udTable.GetFloat("sightDistance", 0.0f) * modInfo.airLosMul * 1.5f / (SQUARE_SIZE * (1 << modInfo.airMipLevel));
	} else {
		airLosRadius = airLosRadius * modInfo.airLosMul / (SQUARE_SIZE * (1 << modInfo.airMipLevel));
	}

	canSubmerge = udTable.GetBool("canSubmerge", false);
	canfly      = udTable.GetBool("canFly",      false);
	canmove     = udTable.GetBool("canMove",     false);
	reclaimable = udTable.GetBool("reclaimable", true);
	capturable  = udTable.GetBool("capturable",  true);
	repairable  = udTable.GetBool("repairable",  true);
	canAttack   = udTable.GetBool("canAttack",   true);
	canFight    = udTable.GetBool("canFight",    true);
	canPatrol   = udTable.GetBool("canPatrol",   true);
	canGuard    = udTable.GetBool("canGuard",    true);
	canRepeat   = udTable.GetBool("canRepeat",   true);

	builder = udTable.GetBool("builder", false);

	canRestore = udTable.GetBool("canRestore", builder);
	canRepair  = udTable.GetBool("canRepair",  builder);
	canReclaim = udTable.GetBool("canReclaim", builder);
	canAssist  = udTable.GetBool("canAssist",  builder);

	canBeAssisted = udTable.GetBool("canBeAssisted", true);
	canSelfRepair = udTable.GetBool("canSelfRepair", false);
	fullHealthFactory = udTable.GetBool("fullHealthFactory", false);
	factoryHeadingTakeoff = udTable.GetBool("factoryHeadingTakeoff", true);

	upright = udTable.GetBool("upright", false);
	collide = udTable.GetBool("collide", true);
	onoffable = udTable.GetBool("onoffable", false);

	maxSlope = Clamp(udTable.GetFloat("maxSlope", 0.0f), 0.0f, 89.0f);
	maxHeightDif = 40 * tan(maxSlope * (PI / 180));
	maxSlope = cos(maxSlope * (PI / 180));
	minWaterDepth = udTable.GetFloat("minWaterDepth", -10e6f);
	maxWaterDepth = udTable.GetFloat("maxWaterDepth", +10e6f);
	minCollisionSpeed = udTable.GetFloat("minCollisionSpeed", 1.0f);
	slideTolerance = udTable.GetFloat("slideTolerance", 0.0f); // disabled
	pushResistant = udTable.GetBool("pushResistant", false);

	waterline = udTable.GetFloat("waterline", 0.0f);
	if ((waterline >= 5.0f) && canmove) {
		// make subs travel at somewhat larger depths
		// to reduce vulnerability to surface weapons
		waterline += 10.0f;
	}

	canSelfD = udTable.GetBool("canSelfDestruct", true);
	selfDCountdown = udTable.GetInt("selfDestructCountdown", 5);

	speed  = udTable.GetFloat("maxVelocity",  0.0f) * GAME_SPEED;
	rSpeed = udTable.GetFloat("maxReverseVelocity", 0.0f) * GAME_SPEED;
	speed  = fabs(speed);
	rSpeed = fabs(rSpeed);

	maxAcc = fabs(udTable.GetFloat("acceleration", 0.5f)); // no negative values
	maxDec = fabs(udTable.GetFloat("brakeRate",    3.0f * maxAcc)) * (canfly? 0.1f: 1.0f); // no negative values

	turnRate    = udTable.GetFloat("turnRate",     0.0f);
	turnInPlace = udTable.GetBool( "turnInPlace",  true);
	turnInPlaceDistance = udTable.GetFloat("turnInPlaceDistance", 350.f);
	turnInPlaceSpeedLimit = udTable.GetFloat("turnInPlaceSpeedLimit", (speed / GAME_SPEED) * 0.2f);

	const bool noAutoFire  = udTable.GetBool("noAutoFire",  false);
	canFireControl = udTable.GetBool("canFireControl", !noAutoFire);
	fireState = udTable.GetInt("fireState", canFireControl ? -1 : 2);
	fireState = std::min(fireState,2);
	moveState = udTable.GetInt("moveState", (canmove && speed>0.0f)  ? -1 : 1);
	moveState = std::min(moveState,2);

	buildRange3D = udTable.GetBool("buildRange3D", false);
	buildDistance = udTable.GetFloat("buildDistance", 128.0f);
	buildDistance = std::max(128.0f, buildDistance);
	buildSpeed = udTable.GetFloat("workerTime", 0.0f);

	repairSpeed    = udTable.GetFloat("repairSpeed",    buildSpeed);
	maxRepairSpeed = udTable.GetFloat("maxRepairSpeed", 1e20f);
	reclaimSpeed   = udTable.GetFloat("reclaimSpeed",   buildSpeed);
	resurrectSpeed = udTable.GetFloat("resurrectSpeed", buildSpeed);
	captureSpeed   = udTable.GetFloat("captureSpeed",   buildSpeed);
	terraformSpeed = udTable.GetFloat("terraformSpeed", buildSpeed);

	flankingBonusMode = udTable.GetInt("flankingBonusMode", modInfo.flankingBonusModeDefault);
	flankingBonusMax  = udTable.GetFloat("flankingBonusMax", 1.9f);
	flankingBonusMin  = udTable.GetFloat("flankingBonusMin", 0.9);
	flankingBonusDir  = udTable.GetFloat3("flankingBonusDir", float3(0.0f, 0.0f, 1.0f));
	flankingBonusMobilityAdd = udTable.GetFloat("flankingBonusMobilityAdd", 0.01f);

	armoredMultiple = udTable.GetFloat("damageModifier", 1.0f);
	armorType = damageArrayHandler->GetTypeFromName(name);

	radarRadius    = udTable.GetInt("radarDistance",    0);
	sonarRadius    = udTable.GetInt("sonarDistance",    0);
	jammerRadius   = udTable.GetInt("radarDistanceJam", 0);
	sonarJamRadius = udTable.GetInt("sonarDistanceJam", 0);

	stealth        = udTable.GetBool("stealth",            false);
	sonarStealth   = udTable.GetBool("sonarStealth",       false);
	targfac        = udTable.GetBool("isTargetingUpgrade", false);
	isFeature      = udTable.GetBool("isFeature",          false);
	canResurrect   = udTable.GetBool("canResurrect",       false);
	canCapture     = udTable.GetBool("canCapture",         false);
	hideDamage     = udTable.GetBool("hideDamage",         false);
	showPlayerName = udTable.GetBool("showPlayerName",     false);

	cloakCost = udTable.GetFloat("cloakCost", -1.0f);
	cloakCostMoving = udTable.GetFloat("cloakCostMoving", -1.0f);
	if (cloakCostMoving < 0) {
		cloakCostMoving = cloakCost;
	}
	canCloak = (cloakCost >= 0);

	startCloaked     = udTable.GetBool("initCloaked", false);
	decloakDistance  = udTable.GetFloat("minCloakDistance", 0.0f);
	decloakSpherical = udTable.GetBool("decloakSpherical", true);
	decloakOnFire    = udTable.GetBool("decloakOnFire",    true);
	cloakTimeout     = udTable.GetInt("cloakTimeout", 128);

	highTrajectoryType = udTable.GetInt("highTrajectory", 0);

	canKamikaze = udTable.GetBool("kamikaze", false);
	kamikazeDist = udTable.GetFloat("kamikazeDistance", -25.0f) + 25.0f; //we count 3d distance while ta count 2d distance so increase slightly
	kamikazeUseLOS = udTable.GetBool("kamikazeUseLOS", false);

	showNanoFrame = udTable.GetBool("showNanoFrame", true);
	showNanoSpray = udTable.GetBool("showNanoSpray", true);
	nanoColor = udTable.GetFloat3("nanoColor", float3(0.2f,0.7f,0.2f));

	canhover = udTable.GetBool("canHover", false);

	floater = udTable.GetBool("floater", udTable.KeyExists("WaterLine"));

	if (builder && !buildSpeed) { // core anti is flagged as builder for some reason
		builder = false;
	}

	airStrafe      = udTable.GetBool("airStrafe", true);
	hoverAttack    = udTable.GetBool("hoverAttack", false);
	wantedHeight   = udTable.GetFloat("cruiseAlt", 0.0f);
	dlHoverFactor  = udTable.GetFloat("airHoverFactor", -1.0f);
	bankingAllowed = udTable.GetBool("bankingAllowed", true);
	useSmoothMesh  = udTable.GetBool("useSmoothMesh", true);

	transportSize     = udTable.GetInt("transportSize",      0);
	minTransportSize  = udTable.GetInt("minTransportSize",   0);
	transportCapacity = udTable.GetInt("transportCapacity",  0);
	isFirePlatform    = udTable.GetBool("isFirePlatform",    false);
	isAirBase         = udTable.GetBool("isAirBase",         false);
	loadingRadius     = udTable.GetFloat("loadingRadius",    220.0f);
	unloadSpread      = udTable.GetFloat("unloadSpread",     1.0f);
	transportMass     = udTable.GetFloat("transportMass",    100000.0f);
	minTransportMass  = udTable.GetFloat("minTransportMass", 0.0f);
	holdSteady        = udTable.GetBool("holdSteady",        false);
	releaseHeld       = udTable.GetBool("releaseHeld",       false);
	cantBeTransported = udTable.GetBool("cantBeTransported", false);
	transportByEnemy  = udTable.GetBool("transportByEnemy",  true);
	fallSpeed         = udTable.GetFloat("fallSpeed",    0.2);
	unitFallSpeed     = udTable.GetFloat("unitFallSpeed",  0);
	transportUnloadMethod	= udTable.GetInt("transportUnloadMethod" , 0);

	// modrules transport settings
	if ((!modInfo.transportAir    && canfly)   ||
	    (!modInfo.transportShip   && floater)  ||
	    (!modInfo.transportHover  && canhover) ||
	    (!modInfo.transportGround && !canhover && !floater && !canfly)) {
 		cantBeTransported = true;
	}

	wingDrag     = udTable.GetFloat("wingDrag",     0.07f);  // drag caused by wings
	wingDrag     = Clamp(wingDrag, 0.0f, 1.0f);
	wingAngle    = udTable.GetFloat("wingAngle",    0.08f);  // angle between front and the wing plane
	frontToSpeed = udTable.GetFloat("frontToSpeed", 0.1f);   // fudge factor for lining up speed and front of plane
	speedToFront = udTable.GetFloat("speedToFront", 0.07f);  // fudge factor for lining up speed and front of plane
	myGravity    = udTable.GetFloat("myGravity",    0.4f);   // planes are slower than real airplanes so lower gravity to compensate
	crashDrag    = udTable.GetFloat("crashDrag",    0.005f); // drag used when crashing
	crashDrag    = Clamp(crashDrag, 0.0f, 1.0f);

	maxBank = udTable.GetFloat("maxBank", 0.8f);         // max roll
	maxPitch = udTable.GetFloat("maxPitch", 0.45f);      // max pitch this plane tries to keep
	turnRadius = udTable.GetFloat("turnRadius", 500.0f); // hint to the ai about how large turn radius this plane needs
	verticalSpeed = udTable.GetFloat("verticalSpeed", 3.0f); // speed of takeoff and landing, at least for gunships

	maxAileron  = udTable.GetFloat("maxAileron",  0.015f); // turn speed around roll axis
	maxElevator = udTable.GetFloat("maxElevator", 0.01f);  // turn speed around pitch axis
	maxRudder   = udTable.GetFloat("maxRudder",   0.004f); // turn speed around yaw axis

	maxFuel = udTable.GetFloat("maxFuel", 0.0f); //max flight time in seconds before aircraft must return to base
	refuelTime = udTable.GetFloat("refuelTime", 5.0f);
	minAirBasePower = udTable.GetFloat("minAirBasePower", 0.0f);
	maxThisUnit = udTable.GetInt("unitRestricted", MAX_UNITS);
	transportableBuilding = udTable.GetBool("transportableBuilding", false);

	const string lname = StringToLower(name);

	if (gameSetup->restrictedUnits.find(lname) != gameSetup->restrictedUnits.end()) {
		maxThisUnit = std::min(maxThisUnit, gameSetup->restrictedUnits.find(lname)->second);
	}

	categoryString = udTable.GetString("category", "");

	category = CCategoryHandler::Instance()->GetCategories(udTable.GetString("category", ""));
	noChaseCategory = CCategoryHandler::Instance()->GetCategories(udTable.GetString("noChaseCategory", ""));

	const string iconName = udTable.GetString("iconType", "default");
	iconType = iconHandler->GetIcon(iconName);

	shieldWeaponDef    = NULL;
	stockpileWeaponDef = NULL;

	maxWeaponRange = 0.0f;
	maxCoverage = 0.0f;

	LuaTable weaponsTable = udTable.SubTable("weapons");
	ParseWeaponsTable(weaponsTable);

	canDGun = udTable.GetBool("canDGun", false);

	extractRange = 0.0f;
	extractSquare = udTable.GetBool("extractSquare", false);

	if (extractsMetal) {
		extractRange = mapInfo->map.extractorRadius;
		type = "MetalExtractor";
	}
	else if (transportCapacity) {
		type = "Transport";
	}
	else if (builder) {
		if ((speed > 0.0f) || canfly || udTable.GetString("yardMap", "").empty()) {
			// hubs and nano-towers need to be builders (for now)
			type = "Builder";
		} else {
			type = "Factory";
		}
	}
	else if (canfly && !hoverAttack) {
		if (!weapons.empty() && (weapons[0].def != 0) &&
		   (weapons[0].def->type == "AircraftBomb" || weapons[0].def->type == "TorpedoLauncher")) {
			type = "Bomber";

			if (turnRadius == 500) { // only reset it if user hasnt set it explicitly
				turnRadius *= 2;   // hint to the ai about how large turn radius this plane needs
			}
		} else {
			type = "Fighter";
		}
		maxAcc = udTable.GetFloat("maxAcc", 0.065f); // engine power
	}
	else if (canmove) {
		type = "GroundUnit";
	}
	else {
		type = "Building";
	}

	movedata = NULL;
	if (canmove && !canfly && (type != "Factory")) {
		string moveclass = StringToLower(udTable.GetString("movementClass", ""));
		movedata = moveinfo->GetMoveDataFromName(moveclass);

		if (!movedata) {
			const string errmsg = "WARNING: Couldn't find a MoveClass named " + moveclass + " (used in UnitDef: " + unitName + ")";
			throw content_error(errmsg); //! invalidate unitDef (this gets catched in ParseUnitDef!)
		}

		if ((movedata->moveType == MoveData::Hover_Move) ||
		    (movedata->moveType == MoveData::Ship_Move)) {
			upright = true;
		}
		if (canhover) {
			if (movedata->moveType != MoveData::Hover_Move) {
				logOutput.Print("Inconsistent movedata %i for %s (moveclass %s): canhover, but not a hovercraft movetype",
				     movedata->pathType, name.c_str(), moveclass.c_str());
			}
		} else if (floater) {
			if (movedata->moveType != MoveData::Ship_Move) {
				logOutput.Print("Inconsistent movedata %i for %s (moveclass %s): floater, but not a ship movetype",
				     movedata->pathType, name.c_str(), moveclass.c_str());
			}
		} else {
			if (movedata->moveType != MoveData::Ground_Move) {
				logOutput.Print("Inconsistent movedata %i for %s (moveclass %s): neither canhover nor floater, but not a ground movetype",
				     movedata->pathType, name.c_str(), moveclass.c_str());
			}
		}
	}

	if ((maxAcc != 0) && (speed != 0)) {
		//meant to set the drag such that the maxspeed becomes what it should be
		drag = 1.0f / (speed/GAME_SPEED * 1.1f / maxAcc)
		          - (wingAngle * wingAngle * wingDrag);
		drag = Clamp(drag, 0.0f, 1.0f);
	} else {
		//shouldn't be needed since drag is only used in CAirMoveType anyway,
		//and aircraft without acceleration or speed aren't common :)
		//initializing it anyway just for safety
		drag = 0.005f;
	}

	objectName = udTable.GetString("objectName", "");
	if (objectName.find(".") == std::string::npos) {
		objectName += ".3do"; // NOTE: get rid of this?
	}
	modelDef.modelPath = "objects3d/" + objectName;
	modelDef.modelName = objectName;

	scriptName = udTable.GetString("script", unitName + ".cob");
	scriptPath = "scripts/" + scriptName;

	wreckName = udTable.GetString("corpse", "");
	deathExplosion = udTable.GetString("explodeAs", "");
	selfDExplosion = udTable.GetString("selfDestructAs", "");

	power = udTable.GetFloat("power", (metalCost + (energyCost / 60.0f)));

	// Prevent a division by zero in experience calculations.
	if (power < 1.0e-3f) {
		logOutput.Print("Unit %s is really cheap? %f", humanName.c_str(), power);
		logOutput.Print("This can cause a division by zero in experience calculations.");
		power = 1.0e-3f;
	}

	activateWhenBuilt = udTable.GetBool("activateWhenBuilt", false);

	// TA has only half our res so multiply size with 2
	xsize = udTable.GetInt("footprintX", 1) * 2;
	zsize = udTable.GetInt("footprintZ", 1) * 2;

	needGeo = false;

	if (speed <= 0.0f) {
		CreateYardMap(udTable.GetString("yardMap", ""));
	}

	leaveTracks   = udTable.GetBool("leaveTracks", false);
	trackTypeName = udTable.GetString("trackType", "StdTank");
	trackWidth    = udTable.GetFloat("trackWidth",   32.0f);
	trackOffset   = udTable.GetFloat("trackOffset",   0.0f);
	trackStrength = udTable.GetFloat("trackStrength", 0.0f);
	trackStretch  = udTable.GetFloat("trackStretch",  1.0f);

	useBuildingGroundDecal = udTable.GetBool("useBuildingGroundDecal", false);
	buildingDecalTypeName = udTable.GetString("buildingGroundDecalType", "");
	buildingDecalSizeX = udTable.GetInt("buildingGroundDecalSizeX", 4);
	buildingDecalSizeY = udTable.GetInt("buildingGroundDecalSizeY", 4);
	buildingDecalDecaySpeed = udTable.GetFloat("buildingGroundDecalDecaySpeed", 0.1f);

	canDropFlare    = udTable.GetBool("canDropFlare", false);
	flareReloadTime = udTable.GetFloat("flareReload",     5.0f);
	flareDelay      = udTable.GetFloat("flareDelay",      0.3f);
	flareEfficiency = udTable.GetFloat("flareEfficiency", 0.5f);
	flareDropVector = udTable.GetFloat3("flareDropVector", ZeroVector);
	flareTime       = udTable.GetInt("flareTime", 3) * GAME_SPEED;
	flareSalvoSize  = udTable.GetInt("flareSalvoSize",  4);
	flareSalvoDelay = udTable.GetInt("flareSalvoDelay", 0) * GAME_SPEED;

	smoothAnim = udTable.GetBool("smoothAnim", false);
	canLoopbackAttack = udTable.GetBool("canLoopbackAttack", false);
	canCrash = udTable.GetBool("canCrash", true);
	levelGround = udTable.GetBool("levelGround", true);
	strafeToAttack = udTable.GetBool("strafeToAttack", false);


	modelCenterOffset = udTable.GetFloat3("modelCenterOffset", ZeroVector);
	usePieceCollisionVolumes = udTable.GetBool("usePieceCollisionVolumes", false);

	// initialize the (per-unitdef) collision-volume
	// all CUnit instances hold a copy of this object
	collisionVolume = new CollisionVolume(
		udTable.GetString("collisionVolumeType", ""),
		udTable.GetFloat3("collisionVolumeScales", ZeroVector),
		udTable.GetFloat3("collisionVolumeOffsets", ZeroVector),
		udTable.GetInt("collisionVolumeTest", CollisionVolume::COLVOL_HITTEST_DISC)
	);

	if (usePieceCollisionVolumes) {
		collisionVolume->Disable();
	}


	seismicRadius    = udTable.GetInt("seismicDistance", 0);
	seismicSignature = udTable.GetFloat("seismicSignature", -1.0f);
	if (seismicSignature == -1.0f) {
		if (!floater && !canhover && !canfly) {
			seismicSignature = sqrt(mass / 100.0f);
		} else {
			seismicSignature = 0.0f;
		}
	}

	LuaTable buildsTable = udTable.SubTable("buildOptions");
	if (buildsTable.IsValid()) {
		for (int bo = 1; true; bo++) {
			const string order = buildsTable.GetString(bo, "");
			if (order.empty()) {
				break;
			}
			buildOptions[bo] = order;
		}
	}

	LuaTable sfxTable = udTable.SubTable("SFXTypes");
	LuaTable expTable = sfxTable.SubTable("explosionGenerators");

	for (int expNum = 1; expNum <= 1024; expNum++) {
		std::string expsfx = expTable.GetString(expNum, "");

		if (expsfx == "") {
			break;
		} else {
			sfxExplGenNames.push_back(expsfx);
		}
	}

	// we use range in a modulo operation, so it needs to be >= 1
	pieceTrailCEGTag = udTable.GetString("pieceTrailCEGTag", "");
	pieceTrailCEGRange = udTable.GetInt("pieceTrailCEGRange", 1);
	pieceTrailCEGRange = std::max(pieceTrailCEGRange, 1);

	// custom parameters table
	udTable.SubTable("customParams").GetMap(customParams);
}
Exemple #30
0
/*
 * CArchiveScanner::ArchiveData
 */
CArchiveScanner::ArchiveData::ArchiveData(const LuaTable& archiveTable, bool fromCache)
{
	if (!archiveTable.IsValid())
		return;

	std::vector<std::string> keys;
	if (!archiveTable.GetKeys(keys))
		return;

	for (std::string& key: keys) {
		const std::string& keyLower = StringToLower(key);

		if (ArchiveData::IsReservedKey(keyLower))
			continue;

		if (keyLower == "modtype") {
			SetInfoItemValueInteger(key, archiveTable.GetInt(key, 0));
			continue;
		}

		switch (archiveTable.GetType(key)) {
			case LuaTable::STRING: {
				SetInfoItemValueString(key, archiveTable.GetString(key, ""));
			} break;
			case LuaTable::NUMBER: {
				SetInfoItemValueFloat(key, archiveTable.GetFloat(key, 0.0f));
			} break;
			case LuaTable::BOOLEAN: {
				SetInfoItemValueBool(key, archiveTable.GetBool(key, false));
			} break;
			default: {
				// just ignore unsupported types (most likely to be lua-tables)
				//throw content_error("Lua-type " + IntToString(luaType) + " not supported in archive-info, but it is used on key \"" + *key + "\"");
			} break;
		}
	}

	const LuaTable& _dependencies = archiveTable.SubTable("depend");
	const LuaTable& _replaces = archiveTable.SubTable("replace");

	for (int dep = 1; _dependencies.KeyExists(dep); ++dep) {
		dependencies.push_back(_dependencies.GetString(dep, ""));
	}
	for (int rep = 1; _replaces.KeyExists(rep); ++rep) {
		replaces.push_back(_replaces.GetString(rep, ""));
	}

	// FIXME
	// XXX HACK needed until lobbies, lobbyserver and unitsync are sorted out
	// so they can uniquely identify different versions of the same mod.
	// (at time of this writing they use name only)

	// NOTE when changing this, this function is used both by the code that
	// reads ArchiveCache.lua and the code that reads modinfo.lua from the mod.
	// so make sure it doesn't keep adding stuff to the name everytime
	// Spring/unitsync is loaded.

	const std::string& name = GetNameVersioned();
	const std::string& version = GetVersion();
	if (!version.empty()) {
		if (name.find(version) == std::string::npos) {
			SetInfoItemValueString("name", name + " " + version);
		} else if (!fromCache) {
			LOG_L(L_WARNING, "[%s] version \"%s\" included in name \"%s\"", __func__, version.c_str(), name.c_str());
		}
	}

	if (GetName().empty())
		SetInfoItemValueString("name_pure", name);
}