unitdefhandler.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 1,005 行 · 第 1/3 页
CPP
1,005 行
#include "StdAfx.h"
#include "UnitDefHandler.h"
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <locale>
#include <cctype>
#include "UnitDef.h"
#include "FileSystem/FileHandler.h"
#include "Game/Game.h"
#include "Game/GameSetup.h"
#include "Game/Team.h"
#include "Lua/LuaParser.h"
#include "Map/ReadMap.h"
#include "Platform/ConfigHandler.h"
#include "Rendering/GroundDecalHandler.h"
#include "Rendering/GL/myGL.h"
#include "Rendering/Textures/Bitmap.h"
#include "Rendering/UnitModels/3DModelParser.h"
#include "Sim/Misc/CategoryHandler.h"
#include "Sim/Misc/DamageArrayHandler.h"
#include "Sim/Misc/SensorHandler.h"
#include "Sim/ModInfo.h"
#include "Sim/Projectiles/ExplosionGenerator.h"
#include "Sim/Weapons/WeaponDefHandler.h"
#include "System/LogOutput.h"
#include "System/Sound.h"
#include "System/TdfParser.h"
#include "mmgr.h"
CR_BIND(UnitDef, );
const char YARDMAP_CHAR = 'c'; //Need to be low case.
CUnitDefHandler* unitDefHandler;
CUnitDefHandler::CUnitDefHandler(void) : noCost(false)
{
weaponDefHandler = SAFE_NEW CWeaponDefHandler();
PrintLoadMsg("Loading unit definitions");
const LuaTable rootTable = game->defsParser->GetRoot().SubTable("UnitDefs");
if (!rootTable.IsValid()) {
throw content_error("Error loading UnitDefs");
}
vector<string> unitDefNames;
rootTable.GetKeys(unitDefNames);
numUnitDefs = unitDefNames.size();
/*
if (gameSetup) {
// ?? "restricted" does not automatically mean "cannot be built
// at all, so we don't need the unitdef for this unit" -- Kloot
numUnitDefs -= gameSetup->restrictedUnits.size();
}
*/
// This could be wasteful if there is a lot of restricted units, but that is not that likely
unitDefs = SAFE_NEW UnitDef[numUnitDefs + 1];
unsigned int id = 1; // Start at unitdef id 1
for (unsigned int a = 0; a < unitDefNames.size(); ++a) {
const string unitName = unitDefNames[a];
/*
if (gameSetup) {
// Restrictions may tell us not to use this unit at all
// FIXME: causes mod errors when a unit is restricted to
// 0, since GetUnitByName() will return NULL if its UnitDef
// has not been loaded -- Kloot
const std::map<std::string, int>& resUnits = gameSetup->restrictedUnits;
if ((resUnits.find(unitName) != resUnits.end()) &&
(resUnits.find(unitName)->second == 0)) {
continue;
}
}
*/
// Seems ok, load it
unitDefs[id].valid = false;
unitDefs[id].name = unitName;
unitDefs[id].id = id;
unitDefs[id].buildangle = 0;
unitDefs[id].unitimage = 0;
unitDefs[id].imageSizeX = -1;
unitDefs[id].imageSizeY = -1;
unitDefs[id].techLevel = -1;
unitDefs[id].decoyDef = NULL;
unitID[unitName] = id;
for (int ym = 0; ym < 4; ym++) {
unitDefs[id].yardmaps[ym] = 0;
}
// parse the TDF data (but don't load buildpics, etc...)
LuaTable udTable = rootTable.SubTable(unitName);
ParseUnit(udTable, unitName, id);
// Increase index for next unit
id++;
}
// set the real number of unitdefs
numUnitDefs = (id - 1);
FindCommanders();
ProcessDecoys();
AssignTechLevels();
}
CUnitDefHandler::~CUnitDefHandler(void)
{
//Deleting eventual yeardmaps.
for(int i = 1; i <= numUnitDefs; i++){
for (int u = 0; u < 4; u++)
delete[] unitDefs[i].yardmaps[u];
if (unitDefs[i].unitimage) {
glDeleteTextures(1,&unitDefs[i].unitimage);
unitDefs[i].unitimage = 0;
}
}
delete[] unitDefs;
delete weaponDefHandler;
}
void CUnitDefHandler::ProcessDecoys()
{
// assign the decoy pointers, and build the decoy map
map<string, string>::const_iterator mit;
for (mit = decoyNameMap.begin(); mit != decoyNameMap.end(); ++mit) {
map<string, int>::iterator fakeIt, realIt;
fakeIt = unitID.find(mit->first);
realIt = unitID.find(mit->second);
if ((fakeIt != unitID.end()) && (realIt != unitID.end())) {
UnitDef* fake = &unitDefs[fakeIt->second];
UnitDef* real = &unitDefs[realIt->second];
fake->decoyDef = real;
decoyMap[real->id].insert(fake->id);
}
}
decoyNameMap.clear();
}
void CUnitDefHandler::FindCommanders()
{
TdfParser tdfparser;
tdfparser.LoadFile("gamedata/SIDEDATA.TDF");
// get the commander UnitDef IDs
commanderIDs.clear();
std::vector<std::string> sides = tdfparser.GetSectionList("");
for (unsigned int i=0; i<sides.size(); i++){
const std::string& section = sides[i];
if ((section.find("side") == 0) &&
(section.find_first_not_of("0123456789", 4) == std::string::npos)) {
string commUnit = tdfparser.SGetValueDef("", section + "\\COMMANDER");
StringToLowerInPlace(commUnit);
if (!commUnit.empty()) {
std::map<std::string, int>::iterator it = unitID.find(commUnit);
if (it != unitID.end()) {
commanderIDs.insert(it->second);
}
}
}
}
}
void CUnitDefHandler::ParseTAUnit(const LuaTable& udTable, const string& unitName, int id)
{
UnitDef& ud = unitDefs[id];
ud.humanName = udTable.GetString("name", "");
if (ud.humanName.empty()) {
const string errmsg = "missing 'name' parameter for the" + unitName + " unitdef";
throw content_error(errmsg);
}
ud.filename = udTable.GetString("filename", "");
if (ud.filename.empty()) {
const string errmsg = "missing 'filename' parameter for the" + unitName + " unitdef";
throw content_error(errmsg);
}
ud.tooltip = udTable.GetString("description", ud.name);
const string decoy = udTable.GetString("decoyFor", "");
if (!decoy.empty()) {
decoyNameMap[ud.name] = StringToLower(decoy);
}
ud.gaia = udTable.GetString("gaia", "");
ud.isCommander = udTable.GetBool("commander", false);
if (ud.isCommander && gameSetup) {
ud.metalStorage = udTable.GetFloat("metalStorage", gameSetup->startMetal);
ud.energyStorage = udTable.GetFloat("energyStorage", gameSetup->startEnergy);
} else {
ud.metalStorage = udTable.GetFloat("metalStorage", 0.0f);
ud.energyStorage = udTable.GetFloat("energyStorage", 0.0f);
}
ud.extractsMetal = udTable.GetFloat("extractsMetal", 0.0f);
ud.windGenerator = udTable.GetFloat("windGenerator", 0.0f);
ud.tidalGenerator = udTable.GetFloat("tidalGenerator", 0.0f);
ud.metalUpkeep = udTable.GetFloat("metalUse", 0.0f);
ud.energyUpkeep = udTable.GetFloat("energyUse", 0.0f);
ud.metalMake = udTable.GetFloat("metalMake", 0.0f);
ud.makesMetal = udTable.GetFloat("makesMetal", 0.0f);
ud.energyMake = udTable.GetFloat("energyMake", 0.0f);
ud.health = udTable.GetFloat("maxDamage", 0.0f);
ud.autoHeal = udTable.GetFloat("autoHeal", 0.0f) * (16.0f / 30.0f);
ud.idleAutoHeal = udTable.GetFloat("idleAutoHeal", 10.0f) * (16.0f / 30.0f);
ud.idleTime = udTable.GetInt("idleTime", 600);
ud.buildangle = udTable.GetInt("buildAngle", 0);
ud.isMetalMaker = (ud.makesMetal >= 1 && ud.energyUpkeep > ud.makesMetal * 40);
ud.controlRadius = 32;
ud.losHeight = 20;
ud.metalCost = udTable.GetFloat("buildCostMetal", 0.0f);
if (ud.metalCost < 1.0f) {
ud.metalCost = 1.0f; //avoid some nasty divide by 0 etc
}
ud.mass = udTable.GetFloat("mass", 0.0f);
if (ud.mass <= 0.0f) {
ud.mass=ud.metalCost;
}
ud.energyCost = udTable.GetFloat("buildCostEnergy", 0.0f);
ud.buildTime = udTable.GetFloat("buildTime", 0.0f);
if (ud.buildTime < 1.0f) {
ud.buildTime = 1.0f; //avoid some nasty divide by 0 etc
}
ud.aihint = id; // FIXME? (as noted in SelectedUnits.cpp, aihint is ignored)
ud.cobID = udTable.GetInt("cobID", -1);
ud.losRadius = udTable.GetFloat("sightDistance", 0.0f) * sensorHandler->losMul / (SQUARE_SIZE * (1 << sensorHandler->losMipLevel));
ud.airLosRadius = udTable.GetFloat("airSightDistance", -1.0f);
if (ud.airLosRadius == -1.0f) {
ud.airLosRadius=udTable.GetFloat("sightDistance", 0.0f) * sensorHandler->airLosMul * 1.5f / (SQUARE_SIZE * (1 << sensorHandler->airMipLevel));
} else {
ud.airLosRadius = ud.airLosRadius * sensorHandler->airLosMul / (SQUARE_SIZE * (1 << sensorHandler->airMipLevel));
}
ud.moveType = 0;
ud.canSubmerge = udTable.GetBool("canSubmerge", false);
ud.canfly = udTable.GetBool("canFly", false);
ud.canmove = udTable.GetBool("canMove", false);
ud.noAutoFire = udTable.GetBool("noAutoFire", false);
ud.reclaimable = udTable.GetBool("reclaimable", true);
ud.canAttack = udTable.GetBool("canAttack", true);
ud.canFight = udTable.GetBool("canFight", true);
ud.canPatrol = udTable.GetBool("canPatrol", true);
ud.canGuard = udTable.GetBool("canGuard", true);
ud.canRepeat = udTable.GetBool("canRepeat", true);
ud.builder = udTable.GetBool("builder", true);
ud.canRestore = udTable.GetBool("canRestore", ud.builder);
ud.canRepair = udTable.GetBool("canRepair", ud.builder);
ud.canReclaim = udTable.GetBool("canReclaim", ud.builder);
ud.canBuild = udTable.GetBool("canBuild", ud.builder);
ud.canAssist = udTable.GetBool("canAssist", ud.builder);
ud.canBeAssisted = udTable.GetBool("canBeAssisted", true);
ud.canSelfRepair = udTable.GetBool("canSelfRepair", false);
ud.fullHealthFactory = udTable.GetBool("fullHealthFactory", false);
ud.factoryHeadingTakeoff = udTable.GetBool("factoryHeadingTakeoff", true);
ud.upright = udTable.GetBool("upright", false);
ud.collide = udTable.GetBool("collide", true);
ud.onoffable = udTable.GetBool("onoffable", false);
ud.maxSlope = udTable.GetFloat("maxSlope", 0.0f);
ud.maxHeightDif = 40 * tan(ud.maxSlope * (PI / 180));
ud.maxSlope = cos(ud.maxSlope * (PI / 180));
ud.minWaterDepth = udTable.GetFloat("minWaterDepth", -10e6f);
ud.maxWaterDepth = udTable.GetFloat("maxWaterDepth", +10e6f);
ud.minCollisionSpeed = udTable.GetFloat("minCollisionSpeed", 1.0f);
ud.slideTolerance = udTable.GetFloat("slideTolerance", 0.0f); // disabled
ud.pushResistant = udTable.GetBool("pushResistant", false);
ud.waterline = udTable.GetFloat("waterline", 0.0f);
if ((ud.waterline > 8.0f) && ud.canmove) {
// make subs travel at somewhat larger depths
// to reduce vulnerability to surface weapons
ud.waterline += 5.0f;
}
ud.canSelfD = udTable.GetBool("canSelfDestruct", true);
ud.selfDCountdown = udTable.GetInt("selfDestructCountdown", 5);
ud.speed = udTable.GetFloat("maxVelocity", 0.0f) * 30.0f;
ud.maxAcc = udTable.GetFloat("acceleration", 0.5f);
ud.maxDec = udTable.GetFloat("brakeRate", 0.5f) * 0.1f;
ud.turnRate = udTable.GetFloat("turnRate", 0.0f);
ud.buildRange3D = udTable.GetBool("buildRange3D", false);
ud.buildDistance = udTable.GetFloat("buildDistance", 128.0f);
ud.buildDistance = std::max(128.0f, ud.buildDistance);
ud.buildSpeed = udTable.GetFloat("workerTime", 0.0f);
ud.repairSpeed = udTable.GetFloat("repairSpeed", ud.buildSpeed);
ud.reclaimSpeed = udTable.GetFloat("reclaimSpeed", ud.buildSpeed);
ud.resurrectSpeed = udTable.GetFloat("resurrectSpeed", ud.buildSpeed);
ud.captureSpeed = udTable.GetFloat("captureSpeed", ud.buildSpeed);
ud.terraformSpeed = udTable.GetFloat("terraformSpeed", ud.buildSpeed);
ud.flankingBonusMode = udTable.GetInt("flankingBonusMode", modInfo.flankingBonusModeDefault);
ud.flankingBonusMax = udTable.GetFloat("flankingBonusMax", 1.9f);
ud.flankingBonusMin = udTable.GetFloat("flankingBonusMin", 0.9);
ud.flankingBonusDir = udTable.GetFloat3("flankingBonusDir", float3(0.0f, 0.0f, 1.0f));
ud.flankingBonusMobilityAdd = udTable.GetFloat("flankingBonusMobilityAdd", 0.01f);
ud.armoredMultiple = udTable.GetFloat("damageModifier", 1.0f);
ud.armorType = damageArrayHandler->GetTypeFromName(ud.name);
ud.radarRadius = udTable.GetInt("radarDistance", 0);
ud.sonarRadius = udTable.GetInt("sonarDistance", 0);
ud.jammerRadius = udTable.GetInt("radarDistanceJam", 0);
ud.sonarJamRadius = udTable.GetInt("sonarDistanceJam", 0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?