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"); }
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"); }