bool CSound::LoadSoundDefs(const std::string& filename) { //! can be called from LuaUnsyncedCtrl too boost::mutex::scoped_lock lck(soundMutex); LuaParser parser(filename, SPRING_VFS_MOD, SPRING_VFS_ZIP); parser.SetLowerKeys(false); parser.SetLowerCppKeys(false); parser.Execute(); if (!parser.IsValid()) { LogObject(LOG_SOUND) << "Could not load " << filename << ": " << parser.GetErrorLog(); return false; } else { const LuaTable soundRoot = parser.GetRoot(); const LuaTable soundItemTable = soundRoot.SubTable("SoundItems"); if (!soundItemTable.IsValid()) { LogObject(LOG_SOUND) << "CSound(): could not parse SoundItems table in " << filename; 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) { const std::string name(*it); soundItemDef bufmap; const LuaTable buf(soundItemTable.SubTable(*it)); buf.GetMap(bufmap); bufmap["name"] = name; soundItemDefMap::const_iterator sit = soundItemDefs.find(name); if (sit != soundItemDefs.end()) LogObject(LOG_SOUND) << "CSound(): two SoundItems have the same name: " << name; soundItemDef::const_iterator inspec = bufmap.find("file"); if (inspec == bufmap.end()) // no file, drop LogObject(LOG_SOUND) << "CSound(): SoundItem has no file tag: " << name; else soundItemDefs[name] = bufmap; if (buf.KeyExists("preload")) { LogObject(LOG_SOUND) << "CSound(): preloading " << name; const size_t newid = sounds.size(); sounds.push_back(new SoundItem(GetWaveBuffer(bufmap["file"], true), bufmap)); soundMap[name] = newid; } } LogObject(LOG_SOUND) << "CSound(): Sucessfully parsed " << keys.size() << " SoundItems from " << filename; } } return true; }
bool CSound::LoadSoundDefs(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.SetLowerKeys(false); parser.SetLowerCppKeys(false); 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) { const std::string name(*it); soundItemDef bufmap; const LuaTable buf(soundItemTable.SubTable(*it)); buf.GetMap(bufmap); bufmap["name"] = name; soundItemDefMap::const_iterator sit = soundItemDefs.find(name); if (sit != soundItemDefs.end()) LOG_L(L_WARNING, "Sound %s gets overwritten by %s", name.c_str(), fileName.c_str()); soundItemDef::const_iterator inspec = bufmap.find("file"); if (inspec == bufmap.end()) { // no file, drop LOG_L(L_WARNING, "Sound %s is missing file tag (ignoring)", name.c_str()); } else { soundItemDefs[name] = bufmap; } if (buf.KeyExists("preload")) { MakeItemFromDef(bufmap); } } LOG(" parsed %i sounds from %s", (int)keys.size(), fileName.c_str()); } } return true; }
void CProjectileDrawer::ParseAtlasTextures( const bool blockTextures, const LuaTable& textureTable, std::set<std::string>& blockedTextures, CTextureAtlas* textureAtlas) { std::vector<std::string> subTables; std::map<std::string, std::string> texturesMap; std::map<std::string, std::string>::iterator texturesMapIt; textureTable.GetMap(texturesMap); textureTable.GetKeys(subTables); for (texturesMapIt = texturesMap.begin(); texturesMapIt != texturesMap.end(); ++texturesMapIt) { const std::string textureName = StringToLower(texturesMapIt->first); if (blockTextures) { // no textures added to this atlas are allowed // to be overwritten later by other textures of // the same name blockedTextures.insert(textureName); } if (blockTextures || (blockedTextures.find(textureName) == blockedTextures.end())) { textureAtlas->AddTexFromFile(texturesMapIt->first, "bitmaps/" + texturesMapIt->second); } } texturesMap.clear(); for (size_t i = 0; i < subTables.size(); i++) { const LuaTable& textureSubTable = textureTable.SubTable(subTables[i]); if (textureSubTable.IsValid()) { textureSubTable.GetMap(texturesMap); for (texturesMapIt = texturesMap.begin(); texturesMapIt != texturesMap.end(); ++texturesMapIt) { const std::string textureName = StringToLower(texturesMapIt->first); if (blockTextures) { blockedTextures.insert(textureName); } if (blockTextures || (blockedTextures.find(textureName) == blockedTextures.end())) { textureAtlas->AddTexFromFile(texturesMapIt->first, "bitmaps/" + texturesMapIt->second); } } texturesMap.clear(); } } }
void ClassAliasList::Load(const LuaTable& aliasTable) { map<string, string> aliasList; aliasTable.GetMap(aliasList); aliases.insert(aliasList.begin(), aliasList.end()); }
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; }
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); } } } }
WeaponDef::WeaponDef(const LuaTable& wdTable, const std::string& name_, int id_) : name(name_) , ptrailExplosionGeneratorID(CExplosionGeneratorHandler::EXPGEN_ID_INVALID) , impactExplosionGeneratorID(CExplosionGeneratorHandler::EXPGEN_ID_STANDARD) , bounceExplosionGeneratorID(CExplosionGeneratorHandler::EXPGEN_ID_INVALID) , id(id_) , projectileType(WEAPON_BASE_PROJECTILE) , collisionFlags(0) { WeaponDefs.Load(this, wdTable); if (wdTable.KeyExists("cylinderTargetting")) LOG_L(L_WARNING, "WeaponDef (%s) cylinderTargetting is deprecated and will be removed in the next release (use cylinderTargeting).", name.c_str()); if (wdTable.KeyExists("color1") || wdTable.KeyExists("color2")) LOG_L(L_WARNING, "WeaponDef (%s) color1 & color2 (= hue & sat) are removed. Use rgbColor instead!", name.c_str()); if (wdTable.KeyExists("isShield")) LOG_L(L_WARNING, "WeaponDef (%s) The \"isShield\" tag has been removed. Use the weaponType=\"Shield\" tag instead!", name.c_str()); shieldRechargeDelay = int(wdTable.GetFloat("rechargeDelay", 0) * GAME_SPEED); shieldArmorType = damageArrayHandler->GetTypeFromName(shieldArmorTypeName); flighttime = int(wdTable.GetFloat("flighttime", 0.0f) * 32); maxFireAngle = math::cos(wdTable.GetFloat("firetolerance", 3640.0f) * TAANG2RAD); //FIXME may be smarter to merge the collideXYZ tags with avoidXYZ and removing the collisionFlags tag (and move the code into CWeapon)? collisionFlags = 0; if (!wdTable.GetBool("collideEnemy", true)) { collisionFlags |= Collision::NOENEMIES; } if (!wdTable.GetBool("collideFriendly", true)) { collisionFlags |= Collision::NOFRIENDLIES; } if (!wdTable.GetBool("collideFeature", true)) { collisionFlags |= Collision::NOFEATURES; } if (!wdTable.GetBool("collideNeutral", true)) { collisionFlags |= Collision::NONEUTRALS; } if (!wdTable.GetBool("collideGround", true)) { collisionFlags |= Collision::NOGROUND; } //FIXME defaults depend on other tags { if (paralyzer) cameraShake = wdTable.GetFloat("cameraShake", 0.0f); if (selfExplode) predictBoost = wdTable.GetFloat("predictBoost", 0.5f); if (type == "Melee") { targetBorder = Clamp(wdTable.GetFloat("targetBorder", 1.0f), -1.0f, 1.0f); cylinderTargeting = Clamp(wdTable.GetFloat("cylinderTargeting", wdTable.GetFloat("cylinderTargetting", 1.0f)), 0.0f, 128.0f); } if (type == "Flame") { //FIXME move to lua (for all other weapons this tag is named `duration` and has a different default) duration = wdTable.GetFloat("flameGfxTime", 1.2f); } if (type == "Cannon") { heightmod = wdTable.GetFloat("heightMod", 0.8f); } else if (type == "BeamLaser" || type == "LightningCannon") { heightmod = wdTable.GetFloat("heightMod", 1.0f); } if (type == "LaserCannon") { // for lasers we want this to be true by default: it sets // projectile ttl values to the minimum required to hit a // target which prevents them overshooting (lasers travel // many elmos per frame and ttl's are rounded) at maximum // range selfExplode = wdTable.GetBool("burnblow", true); } } // setup the default damages { const LuaTable dmgTable = wdTable.SubTable("damage"); float defDamage = dmgTable.GetFloat("default", 1.0f); // avoid division by zeros if (defDamage == 0.0f) defDamage = 1.0f; damages.SetDefaultDamage(defDamage); if (!paralyzer) damages.paralyzeDamageTime = 0; std::map<string, float> dmgs; std::map<string, float>::const_iterator di; dmgTable.GetMap(dmgs); for (di = dmgs.begin(); di != dmgs.end(); ++di) { const int type = damageArrayHandler->GetTypeFromName(di->first); if (type != 0) { float dmg = di->second; if (dmg != 0.0f) { damages[type] = dmg; } else { damages[type] = 1.0f; } } } const float tempsize = 2.0f + std::min(defDamage * 0.0025f, damageAreaOfEffect * 0.1f); const float gd = std::max(30.0f, defDamage / 20.0f); const float defExpSpeed = (8.0f + (gd * 2.5f)) / (9.0f + (math::sqrt(gd) * 0.7f)) * 0.5f; size = wdTable.GetFloat("size", tempsize); explosionSpeed = wdTable.GetFloat("explosionSpeed", defExpSpeed); } { // 0.78.2.1 backwards compatibility: non-burst beamlasers play one // sample per shot, not for each individual beam making up the shot const bool singleSampleShot = (type == "BeamLaser" && !beamburst); const bool singleShotWeapon = (type == "Melee" || type == "Rifle"); soundTrigger = wdTable.GetBool("soundTrigger", singleSampleShot || singleShotWeapon); } // get some weapon specific defaults int defInterceptType = 0; if (type == "Cannon") { // CExplosiveProjectile defInterceptType = 1; projectileType = WEAPON_EXPLOSIVE_PROJECTILE; ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.9f); intensity = wdTable.GetFloat("intensity", 0.2f); } else if (type == "Rifle") { // no projectile or intercept type defInterceptType = 128; ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.9f); } else if (type == "Melee") { // no projectile or intercept type defInterceptType = 256; } else if (type == "Flame") { // CFlameProjectile projectileType = WEAPON_FLAME_PROJECTILE; defInterceptType = 16; ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.2f); collisionSize = wdTable.GetFloat("collisionSize", 0.5f); } else if (type == "MissileLauncher") { // CMissileProjectile projectileType = WEAPON_MISSILE_PROJECTILE; defInterceptType = 4; ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.5f); } else if (type == "LaserCannon") { // CLaserProjectile projectileType = WEAPON_LASER_PROJECTILE; defInterceptType = 2; ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.7f); collisionSize = wdTable.GetFloat("collisionSize", 0.5f); } else if (type == "BeamLaser") { projectileType = largeBeamLaser? WEAPON_LARGEBEAMLASER_PROJECTILE: WEAPON_BEAMLASER_PROJECTILE; defInterceptType = 2; ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.7f); } else if (type == "LightningCannon") { projectileType = WEAPON_LIGHTNING_PROJECTILE; defInterceptType = 64; ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.5f); } else if (type == "EmgCannon") { // CEmgProjectile projectileType = WEAPON_EMG_PROJECTILE; defInterceptType = 1; ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.5f); size = wdTable.GetFloat("size", 3.0f); } else if (type == "TorpedoLauncher") { // WeaponLoader will create either BombDropper with dropTorpedoes = true // (owner->unitDef->canfly && !weaponDef->submissile) or TorpedoLauncher // (both types of weapons will spawn TorpedoProjectile's) // projectileType = WEAPON_TORPEDO_PROJECTILE; defInterceptType = 32; waterweapon = true; } else if (type == "DGun") { // CFireBallProjectile projectileType = WEAPON_FIREBALL_PROJECTILE; ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.5f); collisionSize = wdTable.GetFloat("collisionSize", 10.0f); } else if (type == "StarburstLauncher") { // CStarburstProjectile projectileType = WEAPON_STARBURST_PROJECTILE; defInterceptType = 4; ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.7f); } else if (type == "AircraftBomb") { // WeaponLoader will create BombDropper with dropTorpedoes = false // BombDropper with dropTorpedoes=false spawns ExplosiveProjectile's // projectileType = WEAPON_EXPLOSIVE_PROJECTILE; defInterceptType = 8; ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.9f); } else { ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.0f); } interceptedByShieldType = wdTable.GetInt("interceptedByShieldType", defInterceptType); const std::string& colormap = wdTable.GetString("colormap", ""); if (!colormap.empty()) { visuals.colorMap = CColorMap::LoadFromDefString(colormap); } else { visuals.colorMap = NULL; } ParseWeaponSounds(wdTable); // custom parameters table wdTable.SubTable("customParams").GetMap(customParams); // internal only isShield = (type == "Shield"); noAutoTarget = (manualfire || interceptor || isShield); onlyForward = !turret && (type != "StarburstLauncher"); }
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(); } }
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); }
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); } }
WeaponDef::WeaponDef(const LuaTable& wdTable, const std::string& name_, int id_) : name(name_) , id(id_) , isShield(false) , collisionFlags(0) , explosionGenerator(NULL) , bounceExplosionGenerator(NULL) { WeaponDefs.Load(this, wdTable); if (wdTable.KeyExists("cylinderTargetting")) LOG_L(L_WARNING, "WeaponDef (%s) cylinderTargetting is deprecated and will be removed in the next release (use cylinderTargeting).", name.c_str()); if (wdTable.KeyExists("color1") || wdTable.KeyExists("color2")) LOG_L(L_WARNING, "WeaponDef (%s) color1 & color2 (= hue & sat) are removed. Use rgbColor instead!", name.c_str()); if (wdTable.KeyExists("isShield")) LOG_L(L_WARNING, "WeaponDef (%s) isShield is removed. Use weaponType=\"Shield\" instead!", name.c_str()); shieldRechargeDelay = int(wdTable.GetFloat("rechargeDelay", 0) * GAME_SPEED); flighttime = int(wdTable.GetFloat("flighttime", 0.0f) * 32); //FIXME may be smarter to merge the collideXYZ tags with avoidXYZ and removing the collisionFlags tag (and move the code into CWeapon)? collisionFlags = 0; if (!wdTable.GetBool("collideEnemy", true)) { collisionFlags |= Collision::NOENEMIES; } if (!wdTable.GetBool("collideFriendly", true)) { collisionFlags |= Collision::NOFRIENDLIES; } if (!wdTable.GetBool("collideFeature", true)) { collisionFlags |= Collision::NOFEATURES; } if (!wdTable.GetBool("collideNeutral", true)) { collisionFlags |= Collision::NONEUTRALS; } if (!wdTable.GetBool("collideGround", true)) { collisionFlags |= Collision::NOGROUND; } //FIXME defaults depend on other tags { if (paralyzer) cameraShake = wdTable.GetFloat("cameraShake", 0.0f); if (selfExplode) predictBoost = wdTable.GetFloat("predictBoost", 0.5f); if (type == "Melee") { targetBorder = Clamp(wdTable.GetFloat("targetBorder", 1.0f), -1.0f, 1.0f); cylinderTargeting = Clamp(wdTable.GetFloat("cylinderTargeting", wdTable.GetFloat("cylinderTargetting", 1.0f)), 0.0f, 128.0f); } if (type == "Flame") { //FIXME move to lua (for all other weapons this tag is named `duration` and has a different default) duration = wdTable.GetFloat("flameGfxTime", 1.2f); } if (type == "Cannon") { heightmod = wdTable.GetFloat("heightMod", 0.8f); } else if (type == "BeamLaser" || type == "LightningCannon") { heightmod = wdTable.GetFloat("heightMod", 1.0f); } } // setup the default damages { const LuaTable dmgTable = wdTable.SubTable("damage"); float defDamage = dmgTable.GetFloat("default", 1.0f); if (defDamage == 0.0f) { defDamage = 1.0f; //avoid division by zeros } damages.SetDefaultDamage(defDamage); if (!paralyzer) damages.paralyzeDamageTime = 0; std::map<string, float> dmgs; dmgTable.GetMap(dmgs); std::map<string, float>::const_iterator di; for (di = dmgs.begin(); di != dmgs.end(); ++di) { const int type = damageArrayHandler->GetTypeFromName(di->first); if (type != 0) { float dmg = di->second; if (dmg != 0.0f) { damages[type] = dmg; } else { damages[type] = 1.0f; } } } const float tempsize = 2.0f + std::min(defDamage * 0.0025f, damageAreaOfEffect * 0.1f); size = wdTable.GetFloat("size", tempsize); const float gd = std::max(30.0f, defDamage / 20.0f); const float defExpSpeed = (8.0f + (gd * 2.5f)) / (9.0f + (math::sqrt(gd) * 0.7f)) * 0.5f; explosionSpeed = wdTable.GetFloat("explosionSpeed", defExpSpeed); } { // 0.78.2.1 backwards compatibility: non-burst beamlasers play one // sample per shot, not for each individual beam making up the shot const bool singleSampleShot = (type == "BeamLaser" && !beamburst); const bool singleShotWeapon = (type == "Melee" || type == "Rifle"); soundTrigger = wdTable.GetBool("soundTrigger", singleSampleShot || singleShotWeapon); } // get some weapon specific defaults int defInterceptType = 0; if ((type == "Cannon") || (type == "EmgCannon")) { defInterceptType = 1; } else if ((type == "LaserCannon") || (type == "BeamLaser")) { defInterceptType = 2; } else if ((type == "StarburstLauncher") || (type == "MissileLauncher")) { defInterceptType = 4; } else if (type == "AircraftBomb") { defInterceptType = 8; } else if (type == "Flame") { defInterceptType = 16; } else if (type == "TorpedoLauncher") { defInterceptType = 32; } else if (type == "LightningCannon") { defInterceptType = 64; } else if (type == "Rifle") { defInterceptType = 128; } else if (type == "Melee") { defInterceptType = 256; } interceptedByShieldType = wdTable.GetInt("interceptedByShieldType", defInterceptType); if (type == "Cannon") { // CExplosiveProjectile ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.9f); intensity = wdTable.GetFloat("intensity", 0.2f); } else if (type == "Rifle") { ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.9f); } else if (type == "Melee") { // ... } else if (type == "Flame") { // CFlameProjectile ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.2f); collisionSize = wdTable.GetFloat("collisionSize", 0.5f); } else if (type == "MissileLauncher") { // CMissileProjectile ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.5f); } else if (type == "LaserCannon") { // CLaserProjectile ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.7f); collisionSize = wdTable.GetFloat("collisionSize", 0.5f); } else if (type == "BeamLaser") { ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.7f); } else if (type == "LightningCannon") { ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.5f); } else if (type == "EmgCannon") { // CEmgProjectile ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.5f); size = wdTable.GetFloat("size", 3.0f); } else if (type == "TorpedoLauncher") { assert(waterweapon); waterweapon = true; } else if (type == "DGun") { // CFireBallProjectile ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.5f); collisionSize = wdTable.GetFloat("collisionSize", 10.0f); } else if (type == "StarburstLauncher") { // CStarburstProjectile ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.7f); } else { ownerExpAccWeight = wdTable.GetFloat("ownerExpAccWeight", 0.0f); } const std::string& colormap = wdTable.GetString("colormap", ""); visuals.colorMap = NULL; if (!colormap.empty()) { visuals.colorMap = CColorMap::LoadFromDefString(colormap); } ParseWeaponSounds(wdTable); // custom parameters table wdTable.SubTable("customParams").GetMap(customParams); // internal only isShield = (type == "Shield"); noAutoTarget = (manualfire || interceptor || isShield); onlyForward = !turret && (type != "StarburstLauncher"); }