📄 builder.cpp
字号:
// Builder.cpp: implementation of the CBuilder class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include <assert.h>
#include <algorithm>
#include "Builder.h"
#include "Building.h"
#include "Game/GameHelper.h"
#include "Game/Team.h"
#include "LogOutput.h"
#include "Lua/LuaCallInHandler.h"
#include "Map/Ground.h"
#include "Map/MapDamage.h"
#include "myMath.h"
#include "Rendering/UnitModels/3DOParser.h"
#include "Sim/Misc/Feature.h"
#include "Sim/Misc/FeatureHandler.h"
#include "Sim/ModInfo.h"
#include "Sim/Projectiles/ProjectileHandler.h"
#include "Sim/Projectiles/Unsynced/GfxProjectile.h"
#include "Sim/Units/COB/CobInstance.h"
#include "Sim/Units/UnitDefHandler.h"
#include "Sim/Units/UnitHandler.h"
#include "Sim/Units/UnitLoader.h"
#include "Sound.h"
#include "mmgr.h"
using namespace std;
CR_BIND_DERIVED(CBuilder, CUnit, );
CR_REG_METADATA(CBuilder, (
CR_MEMBER(range3D),
CR_MEMBER(buildDistance),
CR_MEMBER(buildSpeed),
CR_MEMBER(repairSpeed),
CR_MEMBER(reclaimSpeed),
CR_MEMBER(resurrectSpeed),
CR_MEMBER(captureSpeed),
CR_MEMBER(terraformSpeed),
CR_MEMBER(curResurrect),
CR_MEMBER(lastResurrected),
CR_MEMBER(curBuild),
CR_MEMBER(curCapture),
CR_MEMBER(curReclaim),
CR_MEMBER(helpTerraform),
CR_MEMBER(terraforming),
CR_MEMBER(myTerraformLeft),
CR_MEMBER(terraformHelp),
CR_MEMBER(tx1), CR_MEMBER(tx2), CR_MEMBER(tz1), CR_MEMBER(tz2),
CR_MEMBER(terraformCenter),
CR_MEMBER(terraformRadius),
CR_MEMBER(nextBuildType),
CR_MEMBER(nextBuildPos),
CR_ENUM_MEMBER(terraformType),
CR_RESERVED(12),
CR_POSTLOAD(PostLoad)
));
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBuilder::CBuilder()
: range3D(true),
buildDistance(16),
buildSpeed(100),
repairSpeed(100),
reclaimSpeed(100),
resurrectSpeed(100),
captureSpeed(100),
terraformSpeed(100),
curBuild(0),
curReclaim(0),
terraforming(false),
myTerraformLeft(0),
terraformType(Terraform_Building),
tx1(0),
tx2(0),
tz1(0),
tz2(0),
terraformCenter(0,0,0),
terraformRadius(0),
nextBuildPos(0,0,0),
terraformHelp(0),
helpTerraform(0),
curResurrect(0),
lastResurrected(0),
curCapture(0)
{
}
CBuilder::~CBuilder()
{
}
void CBuilder::PostLoad()
{
if (curResurrect) SetBuildStanceToward(curResurrect->pos);
if (curBuild) SetBuildStanceToward(curBuild->pos);
if (curCapture) SetBuildStanceToward(curCapture->pos);
if (curReclaim) SetBuildStanceToward(curReclaim->pos);
if (terraforming) SetBuildStanceToward(terraformCenter);
if (helpTerraform) SetBuildStanceToward(helpTerraform->terraformCenter);
}
void CBuilder::UnitInit(const UnitDef* def, int team, const float3& position)
{
range3D = def->buildRange3D;
buildDistance = def->buildDistance;
const float scale = (1.0f / 32.0f);
buildSpeed = scale * def->buildSpeed;
repairSpeed = scale * def->repairSpeed;
reclaimSpeed = scale * def->reclaimSpeed;
resurrectSpeed = scale * def->resurrectSpeed;
captureSpeed = scale * def->captureSpeed;
terraformSpeed = scale * def->terraformSpeed;
CUnit::UnitInit (def, team, position);
}
void CBuilder::Update()
{
if (beingBuilt) {
return;
}
if(terraforming && inBuildStance){
float* heightmap = readmap->GetHeightmap();
assert(!mapDamage->disabled); // The map should not be deformed in the first place.
float terraformScale = 0.1;
switch(terraformType) {
case Terraform_Building:
if(curBuild) {
terraformScale = (terraformSpeed + terraformHelp) / curBuild->terraformLeft;
curBuild->terraformLeft -= (terraformSpeed + terraformHelp);
terraformHelp = 0;
if (terraformScale > 1.0f) {
terraformScale = 1.0f;
}
curBuild->AddBuildPower(0.0f,this); //prevent building from timing out while terraforming for it
for(int z=tz1; z<=tz2; z++){
for(int x=tx1; x<=tx2; x++){
float ch=heightmap[z*(gs->mapx+1)+x];
heightmap[z*(gs->mapx+1)+x] += (curBuild->pos.y - ch) * terraformScale;
}
}
if(curBuild->terraformLeft<=0){
terraforming=false;
mapDamage->RecalcArea(tx1,tx2,tz1,tz2);
curBuild->groundLevelled = true;
}
}
break;
case Terraform_Restore:
terraformScale = (terraformSpeed + terraformHelp) / myTerraformLeft;
myTerraformLeft -= (terraformSpeed + terraformHelp);
terraformHelp = 0;
if (terraformScale > 1.0f) {
terraformScale = 1.0f;
}
for(int z=tz1; z<=tz2; z++){
for(int x=tx1; x<=tx2; x++){
float ch=heightmap[z*(gs->mapx+1)+x];
float oh=readmap->orgheightmap[z*(gs->mapx+1)+x];
heightmap[z*(gs->mapx+1)+x] += (oh-ch) * terraformScale;
}
}
if(myTerraformLeft<=0){
terraforming=false;
mapDamage->RecalcArea(tx1,tx2,tz1,tz2);
StopBuild();
}
break;
}
CreateNanoParticle(terraformCenter,terraformRadius*0.5f,false);
for(int z=tz1; z<=tz2; z++){ //smooth the borders x
for(int x=1; x<=3; x++){
if(tx1-3>=0){
float ch3=heightmap[z*(gs->mapx+1)+tx1];
float ch=heightmap[z*(gs->mapx+1)+tx1-x];
float ch2=heightmap[z*(gs->mapx+1)+tx1-3];
heightmap[z*(gs->mapx+1)+tx1-x] += ((ch3*(3-x)+ch2*x)/3-ch) * terraformScale;
}
if(tx2+3<gs->mapx){
float ch3=heightmap[z*(gs->mapx+1)+tx2];
float ch=heightmap[z*(gs->mapx+1)+tx2+x];
float ch2=heightmap[z*(gs->mapx+1)+tx2+3];
heightmap[z*(gs->mapx+1)+tx2+x] += ((ch3*(3-x)+ch2*x)/3-ch) * terraformScale;
}
}
}
for(int z=1; z<=3; z++){ //smooth the borders z
for(int x=tx1; x<=tx2; x++){
if(tz1-3>=0){
float ch3=heightmap[(tz1)*(gs->mapx+1)+x];
float ch=heightmap[(tz1-z)*(gs->mapx+1)+x];
float ch2=heightmap[(tz1-3)*(gs->mapx+1)+x];
heightmap[(tz1-z)*(gs->mapx+1)+x] += ((ch3*(3-z)+ch2*z)/3-ch) * terraformScale;
}
if(tz2+3<gs->mapy){
float ch3=heightmap[(tz2)*(gs->mapx+1)+x];
float ch=heightmap[(tz2+z)*(gs->mapx+1)+x];
float ch2=heightmap[(tz2+3)*(gs->mapx+1)+x];
heightmap[(tz2+z)*(gs->mapx+1)+x] += ((ch3*(3-z)+ch2*z)/3-ch) * terraformScale;
}
}
}
}
else if (helpTerraform && inBuildStance) {
if (helpTerraform->terraforming) {
helpTerraform->terraformHelp += terraformSpeed;
CreateNanoParticle(helpTerraform->terraformCenter,helpTerraform->terraformRadius*0.5f,false);
} else {
DeleteDeathDependence(helpTerraform);
helpTerraform=0;
StopBuild(true);
}
}
else if (curBuild && f3Dist(curBuild->pos, pos) < buildDistance + curBuild->radius) {
if (curBuild->soloBuilder && (curBuild->soloBuilder != this)) {
StopBuild();
} else {
if (!inBuildStance) {
curBuild->AddBuildPower(0.0f, this); //prevent building timing out
} else {
if (scriptCloak <= 2) {
if (isCloaked) {
isCloaked = false;
luaCallIns.UnitDecloaked(this);
}
curCloakTimeout = gs->frameNum + cloakTimeout;
}
float adjBuildSpeed; // adjusted build speed
if (curBuild->buildProgress < 1.0f) {
adjBuildSpeed = buildSpeed; // new build
} else {
adjBuildSpeed = repairSpeed; // repair
}
if (curBuild->AddBuildPower(adjBuildSpeed, this)) {
CreateNanoParticle(curBuild->midPos, curBuild->radius * 0.5f, false);
} else {
if(!curBuild->beingBuilt && curBuild->health >= curBuild->maxHealth) {
StopBuild();
}
}
}
}
}
else if(curReclaim && f3Dist(curReclaim->pos, pos)<buildDistance+curReclaim->radius && inBuildStance){
if (scriptCloak <= 2) {
if (isCloaked) {
isCloaked = false;
luaCallIns.UnitDecloaked(this);
}
curCloakTimeout = gs->frameNum + cloakTimeout;
}
if (curReclaim->AddBuildPower(-reclaimSpeed, this)) {
CreateNanoParticle(curReclaim->midPos, curReclaim->radius * 0.7f, true);
}
}
else if(curResurrect && f3Dist(curResurrect->pos, pos)<buildDistance+curResurrect->radius && inBuildStance){
const UnitDef* ud=unitDefHandler->GetUnitByName(curResurrect->createdFromUnit);
if(ud){
if ((modInfo.reclaimMethod != 1) && (curResurrect->reclaimLeft < 1)) {
// This corpse has been reclaimed a little, need to restore the resources
// before we can let the player resurrect it.
curResurrect->AddBuildPower(repairSpeed, this);
}
else {
// Corpse has been restored, begin resurrection
if (UseEnergy(ud->energyCost * resurrectSpeed / ud->buildTime * 0.5f)) {
curResurrect->resurrectProgress+=resurrectSpeed/ud->buildTime;
CreateNanoParticle(curResurrect->midPos,curResurrect->radius*0.7f,gs->randInt()&1);
}
if(curResurrect->resurrectProgress>1){ //resurrect finished
curResurrect->UnBlock();
CUnit* u = unitLoader.LoadUnit(curResurrect->createdFromUnit, curResurrect->pos,
team, false, curResurrect->buildFacing, this);
if (!this->unitDef->canBeAssisted) {
u->soloBuilder = this;
u->AddDeathDependence(this);
}
u->health*=0.05f;
u->lineage = this->lineage;
lastResurrected=u->id;
curResurrect->resurrectProgress=0;
featureHandler->DeleteFeature(curResurrect);
StopBuild(true);
}
}
} else {
StopBuild(true);
}
}
else if(curCapture && f3Dist(curCapture->pos, pos)<buildDistance+curCapture->radius && inBuildStance){
if(curCapture->team!=team){
curCapture->captureProgress+=1.0f/(150+curCapture->buildTime/captureSpeed*(curCapture->health+curCapture->maxHealth)/curCapture->maxHealth*0.4f);
CreateNanoParticle(curCapture->midPos,curCapture->radius*0.7f,false);
if(curCapture->captureProgress > 1.0f){
if (!curCapture->ChangeTeam(team, CUnit::ChangeCaptured)) {
// capture failed
ENTER_MIXED;
if (team == gu->myTeam) {
logOutput.Print("%s: Capture failed, unit type limit reached", unitDef->humanName.c_str());
logOutput.SetLastMsgPos(pos);
}
ENTER_SYNCED;
} else {
// capture succesful
int oldLineage = curCapture->lineage;
curCapture->lineage = this->lineage;
gs->Team(oldLineage)->LeftLineage(curCapture);
}
curCapture->captureProgress=0.5f; //make units somewhat easier to capture back after first capture
StopBuild(true);
}
} else {
StopBuild(true);
}
}
CUnit::Update();
}
void CBuilder::SlowUpdate(void)
{
if(terraforming){
mapDamage->RecalcArea(tx1,tx2,tz1,tz2);
}
CUnit::SlowUpdate();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -