📄 unit.cpp
字号:
// Unit.cpp: implementation of the CUnit class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "COB/CobFile.h"
#include "COB/CobInstance.h"
#include "CommandAI/CommandAI.h"
#include "CommandAI/FactoryCAI.h"
#include "creg/STL_List.h"
#include "ExternalAI/GlobalAIHandler.h"
#include "ExternalAI/Group.h"
#include "Game/Camera.h"
#include "Game/GameHelper.h"
#include "Game/GameSetup.h"
#include "Game/Player.h"
#include "Game/SelectedUnits.h"
#include "Game/Team.h"
#include "Game/UI/MiniMap.h"
#include "Lua/LuaCallInHandler.h"
#include "Lua/LuaRules.h"
#include "Map/Ground.h"
#include "Map/MetalMap.h"
#include "Map/ReadMap.h"
#include "Rendering/Env/BaseWater.h"
#include "Rendering/glFont.h"
#include "Rendering/GL/myGL.h"
#include "Rendering/GroundDecalHandler.h"
#include "Rendering/GroundFlash.h"
#include "Rendering/ShadowHandler.h"
#include "Rendering/UnitModels/3DModelParser.h"
#include "Rendering/UnitModels/UnitDrawer.h"
#include "Sim/Misc/AirBaseHandler.h"
#include "Sim/Misc/Feature.h"
#include "Sim/Misc/FeatureHandler.h"
#include "Sim/Misc/LosHandler.h"
#include "Sim/Misc/QuadField.h"
#include "Sim/Misc/RadarHandler.h"
#include "Sim/Misc/Wind.h"
#include "Sim/ModInfo.h"
#include "Sim/MoveTypes/AirMoveType.h"
#include "Sim/MoveTypes/MoveType.h"
#include "Sim/MoveTypes/ScriptMoveType.h"
#include "Sim/Projectiles/FlareProjectile.h"
#include "Sim/Projectiles/ProjectileHandler.h"
#include "Sim/Projectiles/WeaponProjectiles/MissileProjectile.h"
#include "Sim/Weapons/BeamLaser.h"
#include "Sim/Weapons/WeaponDefHandler.h"
#include "Sim/Weapons/Weapon.h"
#include "Sync/SyncTracer.h"
#include "System/LoadSaveInterface.h"
#include "System/LogOutput.h"
#include "System/Matrix44f.h"
#include "System/myMath.h"
#include "System/Sound.h"
#include "UnitDef.h"
#include "Unit.h"
#include "UnitHandler.h"
#include "UnitLoader.h"
#include "UnitTypes/Building.h"
#include "UnitTypes/TransportUnit.h"
#include "mmgr.h"
#include "COB/CobEngine.h"
#include "CommandAI/AirCAI.h"
#include "CommandAI/BuilderCAI.h"
#include "CommandAI/CommandAI.h"
#include "CommandAI/FactoryCAI.h"
#include "CommandAI/MobileCAI.h"
#include "CommandAI/TransportCAI.h"
#include "UnitDefHandler.h"
CR_BIND_DERIVED(CUnit, CSolidObject, );
// See end of source for member bindings
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
float CUnit::expMultiplier = 1.0f;
float CUnit::expPowerScale = 1.0f;
float CUnit::expHealthScale = 0.7f;
float CUnit::expReloadScale = 0.4f;
float CUnit::expGrade = 0.0f;
CUnit::CUnit ()
: unitDef(0),
team(0),
maxHealth(100),
health(100),
travel(0.0f),
travelPeriod(0.0f),
power(100),
experience(0),
limExperience(0),
neutral(false),
armorType(0),
soloBuilder(NULL),
beingBuilt(true),
allyteam(0),
restTime(0),
controlRadius(2),
reloadSpeed(1),
commandAI(0),
tempNum(0),
losRadius(0),
airLosRadius(0),
losHeight(0),
metalCost(100),
energyCost(0),
buildTime(100),
frontdir(0,0,1),
rightdir(-1,0,0),
updir(0,1,0),
upright(true),
falling(false),
fallSpeed(0.2),
maxRange(0),
haveTarget(false),
lastAttacker(0),
lastAttack(-200),
userTarget(0),
userAttackGround(false),
commandShotCount(-1),
lastLosUpdate(0),
fireState(2),
moveState(0),
lastSlowUpdate(0),
los(0),
userAttackPos(0,0,0),
crashing(false),
cob(0),
flankingBonusMode(0),
flankingBonusDir(1.0f, 0.0f, 0.0f),
flankingBonusAvgDamage(1.4f),
flankingBonusDifDamage(0.5f),
flankingBonusMobility(10.0f),
flankingBonusMobilityAdd(0.01f),
group(0),
lastDamage(-100),
lastFireWeapon(0),
lastMuzzleFlameSize(0),
lastMuzzleFlameDir(0,1,0),
category(0),
recentDamage(0),
armoredState(false),
armoredMultiple(1),
curArmorMultiple(1),
buildProgress(0),
groundLevelled(true),
terraformLeft(0),
realLosRadius(0),
realAirLosRadius(0),
inBuildStance(false),
isDead(false),
nextPosErrorUpdate(1),
posErrorDelta(0,0,0),
transporter(0),
toBeTransported(false),
hasUWWeapons(false),
lastNanoAdd(gs->frameNum),
cloakTimeout(128),
curCloakTimeout(gs->frameNum),
isCloaked(false),
wantCloak(false),
scriptCloak(0),
decloakDistance(0.0f),
shieldWeapon(0),
stockpileWeapon(0),
haveDGunRequest(false),
jammerRadius(0),
sonarJamRadius(0),
radarRadius(0),
sonarRadius(0),
hasRadarCapacity(false),
stunned(false),
condUseMetal(0.0f),
condUseEnergy(0.0f),
condMakeMetal(0.0f),
condMakeEnergy(0.0f),
uncondUseMetal(0.0f),
uncondUseEnergy(0.0f),
uncondMakeMetal(0.0f),
uncondMakeEnergy(0.0f),
metalUse(0),
energyUse(0),
metalMake(0),
energyMake(0),
metalUseI(0),
energyUseI(0),
metalMakeI(0),
energyMakeI(0),
metalUseold(0),
energyUseold(0),
metalMakeold(0),
energyMakeold(0),
energyTickMake(0),
metalExtract(0),
metalStorage(0),
energyStorage(0),
lastTerrainType(-1),
curTerrainType(0),
relMidPos(0,0,0),
selfDCountdown(0),
useHighTrajectory(false),
deathCountdown(0),
delayedWreckLevel(-1),
paralyzeDamage(0),
captureProgress(0),
myTrack(0),
lastFlareDrop(0),
dontFire(false),
deathScriptFinished(false),
dontUseWeapons(false),
currentFuel(0),
luaDraw(false),
noDraw(false),
noSelect(false),
noMinimap(false),
isIcon(false),
iconRadius(0),
prevMoveType(NULL),
usingScriptMoveType(false),
lodCount(0),
currentLOD(0),
alphaThreshold(0.1f),
cegDamage(1)
{
#ifdef DIRECT_CONTROL_ALLOWED
directControl = 0;
#endif
activated = false;
}
CUnit::~CUnit()
{
if(delayedWreckLevel>=0){
featureHandler->CreateWreckage(pos,wreckName, heading, buildFacing, delayedWreckLevel,team,-1,true,unitDef->name);
}
if(unitDef->isAirBase){
airBaseHandler->DeregisterAirBase(this);
}
#ifdef TRACE_SYNC
tracefile << "Unit died: ";
tracefile << pos.x << " " << pos.y << " " << pos.z << " " << id << "\n";
#endif
#ifdef DIRECT_CONTROL_ALLOWED
if(directControl){
directControl->myController->StopControllingUnit();
directControl=0;
}
#endif
if(activated && unitDef->targfac){
radarhandler->radarErrorSize[allyteam]*=radarhandler->targFacEffect;
}
// if(!beingBuilt){
SetMetalStorage(0);
SetEnergyStorage(0);
// }
delete commandAI; commandAI = 0;
delete moveType; moveType = 0;
delete prevMoveType; prevMoveType = 0;
if(group)
group->RemoveUnit(this);
group=0;
std::vector<CWeapon*>::iterator wi;
for(wi=weapons.begin();wi!=weapons.end();++wi)
delete *wi;
qf->RemoveUnit(this);
loshandler->DelayedFreeInstance(los);
los=0;
if(hasRadarCapacity)
radarhandler->RemoveUnit(this);
delete cob;
delete localmodel;
}
void CUnit::SetMetalStorage(float newStorage)
{
gs->Team(team)->metalStorage-=metalStorage;
metalStorage = newStorage;
gs->Team(team)->metalStorage+=metalStorage;
}
void CUnit::SetEnergyStorage(float newStorage)
{
gs->Team(team)->energyStorage-=energyStorage;
energyStorage = newStorage;
gs->Team(team)->energyStorage+=energyStorage;
}
void CUnit::UnitInit (const UnitDef* def, int Team, const float3& position)
{
pos = position;
team = Team;
allyteam = gs->AllyTeam(Team);
lineage = Team;
unitDef = def;
unitDefName = unitDef->name;
localmodel=NULL;
SetRadius(1.2f);
mapSquare=ground->GetSquare(pos);
uh->AddUnit(this);
qf->MovedUnit(this);
oldRadarPos.x=-1;
for(int a=0;a<MAX_TEAMS;++a)
losStatus[a]=0;
losStatus[allyteam]=LOS_INTEAM | LOS_INLOS | LOS_INRADAR | LOS_PREVLOS | LOS_CONTRADAR;
posErrorVector=gs->randVector();
posErrorVector.y*=0.2f;
#ifdef TRACE_SYNC
tracefile << "New unit: ";
tracefile << pos.x << " " << pos.y << " " << pos.z << " " << id << "\n";
#endif
}
void CUnit::ForcedMove(const float3& newPos)
{
// hack to make mines not block ground
const bool blocking = !unitDef->canKamikaze || (unitDef->type != "Building");
if (blocking) {
UnBlock();
}
CBuilding* building = dynamic_cast<CBuilding*>(this);
if (building && unitDef->useBuildingGroundDecal) {
groundDecals->RemoveBuilding(building, NULL);
}
pos = newPos;
midPos = pos + (frontdir * relMidPos.z) +
(updir * relMidPos.y) +
(rightdir * relMidPos.x);
if (building && unitDef->useBuildingGroundDecal) {
groundDecals->AddBuilding(building);
}
if (blocking) {
Block();
}
qf->MovedUnit(this);
loshandler->MoveUnit(this, false);
if (hasRadarCapacity) {
radarhandler->MoveUnit(this);
}
}
void CUnit::ForcedSpin(const float3& newDir)
{
frontdir = newDir;
heading = GetHeadingFromVector(newDir.x, newDir.z);
ForcedMove(pos); // lazy, don't need to update the quadfield, etc...
}
void CUnit::Drop(float3 parentPos,float3 parentDir, CUnit* parent)
{
//drop unit from position
fallSpeed = unitDef->unitFallSpeed > 0 ? unitDef->unitFallSpeed : parent->unitDef->fallSpeed;
falling = true;
pos.y = parentPos.y - height;
frontdir = parentDir;
frontdir.y = 0;
speed.y = 0;
}
void CUnit::EnableScriptMoveType()
{
if (usingScriptMoveType) {
return;
}
prevMoveType = moveType;
moveType = SAFE_NEW CScriptMoveType(this);
usingScriptMoveType = true;
}
void CUnit::DisableScriptMoveType()
{
if (!usingScriptMoveType) {
return;
}
delete moveType;
moveType = prevMoveType;
prevMoveType = NULL;
usingScriptMoveType = false;
// FIXME: prevent the issuing of extra commands ?
if (moveType) {
moveType->SetGoal(pos);
moveType->StopMoving();
}
CMobileCAI* mobile = dynamic_cast<CMobileCAI*>(moveType);
if (mobile) {
mobile->lastUserGoal = pos;
}
}
void CUnit::Update()
{
posErrorVector += posErrorDelta;
if (deathCountdown) {
--deathCountdown;
if (!deathCountdown) {
if (deathScriptFinished) {
uh->DeleteUnit(this);
} else {
deathCountdown = 1;
}
}
return;
}
if (beingBuilt) {
return;
}
moveType->Update();
if (travelPeriod != 0.0f) {
travel += speed.Length();
travel = fmodf(travel, travelPeriod);
}
recentDamage *= 0.9f;
flankingBonusMobility += flankingBonusMobilityAdd;
if (stunned) {
return;
}
restTime++;
if (!dontUseWeapons) {
std::vector<CWeapon*>::iterator wi;
for (wi = weapons.begin();wi != weapons.end(); ++wi) {
(*wi)->Update();
}
}
}
void CUnit::UpdateResources()
{
metalMake = metalMakeI + metalMakeold;
metalUse = metalUseI + metalUseold;
energyMake = energyMakeI + energyMakeold;
energyUse = energyUseI + energyUseold;
metalMakeold = metalMakeI;
metalUseold = metalUseI;
energyMakeold = energyMakeI;
energyUseold = energyUseI;
metalMakeI = metalUseI = energyMakeI = energyUseI = 0.0f;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -