unithandler.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 642 行 · 第 1/2 页
CPP
642 行
// UnitHandler.cpp: implementation of the CUnitHandler class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "UnitHandler.h"
#include "Unit.h"
#include "Rendering/GL/myGL.h"
#include "Game/Team.h"
#include "TimeProfiler.h"
#include "myMath.h"
#include "Map/Ground.h"
#include "Map/ReadMap.h"
#include "Platform/ConfigHandler.h"
#include "Rendering/FartextureHandler.h"
#include "UnitDefHandler.h"
#include "Sim/Misc/QuadField.h"
#include "CommandAI/BuilderCAI.h"
#include "Game/SelectedUnits.h"
#include "FileSystem/FileHandler.h"
#include "LogOutput.h"
#include "Game/SelectedUnits.h"
#include "Sim/Misc/Feature.h"
#include "Sim/Misc/FeatureHandler.h"
#include "Sim/Units/Unit.h"
#include "LoadSaveInterface.h"
#include "UnitLoader.h"
#include "Sync/SyncTracer.h"
#include "Game/GameSetup.h"
#include "Sim/Units/CommandAI/Command.h"
#include "Sim/Misc/AirBaseHandler.h"
#include "creg/STL_List.h"
#include "creg/STL_Deque.h"
#include "creg/STL_Set.h"
#include "mmgr.h"
BuildInfo::BuildInfo(const std::string& name, const float3& p, int facing)
{
def = unitDefHandler->GetUnitByName(name);
pos = p;
buildFacing = facing;
}
void BuildInfo::FillCmd(Command& c) const
{
c.id=-def->id;
c.params.resize(4);
c.params[0]=pos.x;
c.params[1]=pos.y;
c.params[2]=pos.z;
c.params[3]=(float)buildFacing;
}
bool BuildInfo::Parse(const Command& c)
{
if (c.params.size() >= 3) {
pos = float3(c.params[0],c.params[1],c.params[2]);
if(c.id < 0) {
def = unitDefHandler->GetUnitByID(-c.id);
buildFacing = 0;
if (c.params.size()==4)
buildFacing = int(c.params[3]);
return true;
}
}
return false;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CUnitHandler* uh;
using namespace std;
CR_BIND(CUnitHandler, (true));
CR_REG_METADATA(CUnitHandler, (
CR_MEMBER(activeUnits),
CR_MEMBER(units),
CR_MEMBER(freeIDs),
CR_MEMBER(waterDamage),
CR_MEMBER(maxUnits),
CR_MEMBER(maxUnitRadius),
CR_MEMBER(lastDamageWarning),
CR_MEMBER(lastCmdDamageWarning),
CR_MEMBER(limitDgun),
CR_MEMBER(dgunRadius),
CR_MEMBER(diminishingMetalMakers),
CR_MEMBER(metalMakerIncome),
CR_MEMBER(metalMakerEfficiency),
CR_MEMBER(toBeRemoved),
CR_MEMBER(morphUnitToFeature),
CR_MEMBER(toBeRemoved),
CR_MEMBER(builderCAIs),
CR_MEMBER(unitsByDefs),
CR_POSTLOAD(PostLoad),
CR_SERIALIZER(Serialize)
));
void CUnitHandler::Serialize(creg::ISerializer& s)
{
}
void CUnitHandler::PostLoad()
{
// reset any synced stuff that is not saved
slowUpdateIterator = activeUnits.end();
}
CUnitHandler::CUnitHandler(bool serializing)
:
maxUnits(500),
maxUnitRadius(0.0f),
lastDamageWarning(0),
lastCmdDamageWarning(0),
metalMakerIncome(0),
metalMakerEfficiency(1),
diminishingMetalMakers(false),
limitDgun(false),
morphUnitToFeature(true)
{
//unitModelLoader=SAFE_NEW CUnit3DLoader;
for (int a = 1; a < MAX_UNITS; a++) {
freeIDs.push_back(a);
units[a] = 0;
}
units[0] = 0;
slowUpdateIterator = activeUnits.end();
waterDamage=atof(readmap->mapDefParser.SGetValueDef("0","MAP\\WATER\\WaterDamage").c_str())*(16.0f/30.0f);
if (gameSetup) {
maxUnits = gameSetup->maxUnits;
}
if (maxUnits > ((MAX_UNITS / gs->activeTeams) - 5)) {
maxUnits = (MAX_UNITS / gs->activeTeams) -5;
}
if (gameSetup) {
if (gameSetup->limitDgun) {
limitDgun = true;
dgunRadius = gs->mapx * 3;
}
if (gameSetup->diminishingMMs) {
diminishingMetalMakers = true;
}
}
if (!serializing) {
airBaseHandler = SAFE_NEW CAirBaseHandler;
for (int i = 0; i < MAX_TEAMS; i++) {
unitsByDefs[i].resize(unitDefHandler->numUnitDefs + 1);
}
}
}
CUnitHandler::~CUnitHandler()
{
list<CUnit*>::iterator usi;
for (usi = activeUnits.begin(); usi != activeUnits.end(); usi++) {
delete (*usi);
}
delete airBaseHandler;
}
int CUnitHandler::AddUnit(CUnit *unit)
{
ASSERT_SYNCED_MODE;
int num=(int)(gs->randFloat())*((int)activeUnits.size()-1);
std::list<CUnit*>::iterator ui=activeUnits.begin();
for(int a=0;a<num;++a){
++ui;
}
activeUnits.insert(ui,unit); //randomize this to make the order in slowupdate random (good if one build say many buildings at once and then many mobile ones etc)
unit->id=freeIDs.front();
freeIDs.pop_front();
units[unit->id]=unit;
gs->Team(unit->team)->AddUnit(unit,CTeam::AddBuilt);
unitsByDefs[unit->team][unit->unitDef->id].insert(unit);
maxUnitRadius = max(unit->radius, maxUnitRadius);
return unit->id;
}
void CUnitHandler::DeleteUnit(CUnit* unit)
{
ASSERT_SYNCED_MODE;
toBeRemoved.push_back(unit);
}
void CUnitHandler::Update()
{
ASSERT_SYNCED_MODE;
SCOPED_TIMER("Unit handler");
while(!toBeRemoved.empty()){
CUnit* delUnit=toBeRemoved.back();
toBeRemoved.pop_back();
int delTeam = 0;
int delType = 0;
list<CUnit*>::iterator usi;
for(usi=activeUnits.begin();usi!=activeUnits.end();++usi){
if(*usi==delUnit){
if (slowUpdateIterator!=activeUnits.end() && *usi==*slowUpdateIterator) {
slowUpdateIterator++;
}
delTeam = delUnit->team;
delType = delUnit->unitDef->id;
activeUnits.erase(usi);
units[delUnit->id] = 0;
freeIDs.push_back(delUnit->id);
gs->Team(delTeam)->RemoveUnit(delUnit, CTeam::RemoveDied);
unitsByDefs[delTeam][delType].erase(delUnit);
delete delUnit;
break;
}
}
//debug
for (usi = activeUnits.begin(); usi != activeUnits.end(); /* no post-op */) {
if (*usi == delUnit){
logOutput.Print("Error: Duplicated unit found in active units on erase");
usi = activeUnits.erase(usi);
} else {
++usi;
}
}
}
list<CUnit*>::iterator usi;
for (usi = activeUnits.begin(); usi != activeUnits.end(); usi++) {
(*usi)->Update();
}
{
SCOPED_TIMER("Unit slow update");
if (!(gs->frameNum & 15)) {
slowUpdateIterator=activeUnits.begin();
}
int numToUpdate=activeUnits.size()/16+1;
for(;slowUpdateIterator!=activeUnits.end() && numToUpdate!=0;++slowUpdateIterator){
(*slowUpdateIterator)->SlowUpdate();
numToUpdate--;
}
} // for timer destruction
if(!(gs->frameNum&15)){
if(diminishingMetalMakers)
metalMakerEfficiency=8.0f/(8.0f+max(0.0f,sqrtf(metalMakerIncome/gs->activeTeams)-4));
metalMakerIncome=0;
}
}
float CUnitHandler::GetBuildHeight(float3 pos, const UnitDef* unitdef)
{
float minh=-5000;
float maxh=5000;
int numBorder=0;
float borderh=0;
float* heightmap=readmap->GetHeightmap();
int xsize=1;
int ysize=1;
float maxDif=unitdef->maxHeightDif;
int x1 = (int)max(0.f,(pos.x-(xsize*0.5f*SQUARE_SIZE))/SQUARE_SIZE);
int x2 = min(gs->mapx,x1+xsize);
int z1 = (int)max(0.f,(pos.z-(ysize*0.5f*SQUARE_SIZE))/SQUARE_SIZE);
int z2 = min(gs->mapy,z1+ysize);
if (x1 > gs->mapx) x1 = gs->mapx;
if (x2 < 0) x2 = 0;
if (z1 > gs->mapy) z1 = gs->mapy;
if (z2 < 0) z2 = 0;
for(int x=x1; x<=x2; x++){
for(int z=z1; z<=z2; z++){
float orgh=readmap->orgheightmap[z*(gs->mapx+1)+x];
float h=heightmap[z*(gs->mapx+1)+x];
if(x==x1 || x==x2 || z==z1 || z==z2){
numBorder++;
borderh+=h;
}
if(minh<min(h,orgh)-maxDif)
minh=min(h,orgh)-maxDif;
if(maxh>max(h,orgh)+maxDif)
maxh=max(h,orgh)+maxDif;
}
}
float h=borderh/numBorder;
if(h<minh && minh<maxh)
h=minh+0.01f;
if(h>maxh && maxh>minh)
h=maxh-0.01f;
return h;
}
int CUnitHandler::TestUnitBuildSquare(const BuildInfo& buildInfo, CFeature *&feature, int allyteam)
{
feature=0;
int xsize=buildInfo.GetXSize();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?