weapondefhandler.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 737 行 · 第 1/2 页

CPP
737
字号
#include "StdAfx.h"
#include <algorithm>
#include <cctype>
#include <iostream>
#include <stdexcept>
#include "WeaponDefHandler.h"
#include "Game/Game.h"
#include "Lua/LuaParser.h"
#include "FileSystem/FileHandler.h"
#include "Rendering/Textures/ColorMap.h"
#include "Rendering/Textures/TAPalette.h"
#include "Rendering/GL/myGL.h"
#include "Sim/Misc/DamageArrayHandler.h"
#include "Sim/Misc/CategoryHandler.h"
#include "Sim/Projectiles/ExplosionGenerator.h"
#include "Sim/Projectiles/ProjectileHandler.h"
#include "Sim/Projectiles/Projectile.h"
#include "System/LogOutput.h"
#include "System/Sound.h"
#include "mmgr.h"

using namespace std;


CR_BIND(WeaponDef, );


CWeaponDefHandler* weaponDefHandler = NULL;


CWeaponDefHandler::CWeaponDefHandler()
{
	PrintLoadMsg("Loading weapon definitions");

	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(); // FIXME: starting at 0, don't need the +1 ?
	weaponDefs = SAFE_NEW WeaponDef[numWeaponDefs + 1];

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

		const LuaTable wdTable = rootTable.SubTable(wd.name);
		ParseTAWeapon(wdTable, wd);
	}
}


CWeaponDefHandler::~CWeaponDefHandler()
{
	delete[] weaponDefs;
}


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

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?