transportunit.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 295 行

CPP
295
字号
#include "StdAfx.h"
#include "TransportUnit.h"
#include "Lua/LuaCallInHandler.h"
#include "Rendering/UnitModels/3DOParser.h"
#include "Sim/MoveTypes/TAAirMoveType.h"
#include "Sim/MoveTypes/groundmovetype.h"
#include "Sim/Units/CommandAI/CommandAI.h"
#include "Sim/Units/UnitDef.h"
#include "Sim/Misc/DamageArray.h"
#include "Sim/Misc/LosHandler.h"
#include "Game/SelectedUnits.h"
#include "LogOutput.h"
#include "creg/STL_List.h"
#include "mmgr.h"


CR_BIND_DERIVED(CTransportUnit, CUnit, );

CR_REG_METADATA(CTransportUnit, (
				CR_MEMBER(transported),
				CR_MEMBER(transportCapacityUsed),
				CR_MEMBER(transportMassUsed),
				CR_RESERVED(16),
				CR_POSTLOAD(PostLoad)
				));

CR_BIND(CTransportUnit::TransportedUnit,);

CR_REG_METADATA_SUB(CTransportUnit,TransportedUnit,(
					CR_MEMBER(unit),
					CR_MEMBER(piece),
					CR_MEMBER(size),
					CR_MEMBER(mass),
					CR_RESERVED(8)
					));

CTransportUnit::CTransportUnit()
:	transportCapacityUsed(0),
  transportMassUsed(0)
{
}


CTransportUnit::~CTransportUnit()
{
}

void CTransportUnit::PostLoad()
{
}

void CTransportUnit::Update()
{
	CUnit::Update();
	list<TransportedUnit>::iterator ti;
	for (ti = transported.begin(); ti != transported.end(); ++ti) {
		float3 relPos;
		if (ti->piece >= 0) {
			relPos = localmodel->GetPiecePos(max(0, ti->piece));
		} else {
			relPos = float3(0.0f, -1000.0f, 0.0f);
		}
		float3 pos = this->pos + (frontdir * relPos.z) +
		                         (updir    * relPos.y) +
		                         (rightdir * relPos.x);
//		pos.y-=ti->unit->radius;
		ti->unit->pos = pos;
		ti->unit->midPos = ti->unit->pos + (ti->unit->frontdir * ti->unit->relMidPos.z) +
		                                   (ti->unit->updir    * ti->unit->relMidPos.y) +
		                                   (ti->unit->rightdir * ti->unit->relMidPos.x);
		if (unitDef->holdSteady) {
			ti->unit->heading  = heading;
			ti->unit->updir    = updir;
			ti->unit->frontdir = frontdir;
			ti->unit->rightdir = rightdir;
		}
	}
}


void CTransportUnit::DependentDied(CObject* o)
{
	for(list<TransportedUnit>::iterator ti=transported.begin();ti!=transported.end();++ti){
		if(ti->unit==o){
			transportCapacityUsed-=ti->size;
			transportMassUsed-=ti->mass;
			transported.erase(ti);
			break;
		}
	}

	CUnit::DependentDied(o);
}


void CTransportUnit::KillUnit(bool selfDestruct,bool reclaimed, CUnit *attacker)
{
	list<TransportedUnit>::iterator ti;
	for (ti = transported.begin(); ti != transported.end(); ++ti) {
		ti->unit->transporter = 0;
		ti->unit->DeleteDeathDependence(this);
		if (!unitDef->releaseHeld) {
			if (!selfDestruct) {
				ti->unit->DoDamage(DamageArray()*1000000,0,ZeroVector);	//dont want it to leave a corpse
			}
			ti->unit->KillUnit(selfDestruct,reclaimed,attacker);
		}
		else {
			ti->unit->stunned = (ti->unit->paralyzeDamage > ti->unit->health);
			if (CGroundMoveType* mt = dynamic_cast<CGroundMoveType*>(ti->unit->moveType)) {
				mt->StartFlying();
			}
			ti->unit->speed = speed;

			luaCallIns.UnitUnloaded(ti->unit, this);
		}
	}

	CUnit::KillUnit(selfDestruct,reclaimed,attacker);
}


bool CTransportUnit::CanTransport (CUnit *unit)
{
	if (unit->transporter) {
		return false;
	}

	if (!unit->unitDef->transportByEnemy && !gs->AlliedTeams(unit->team, team)) {
		return false;
	}

	CTransportUnit* u=this;
	while (u) {
		if (u == unit) {
			return false;
		}
		u = u->transporter;
	}

	return true;
}


void CTransportUnit::AttachUnit(CUnit* unit, int piece)
{
	DetachUnit(unit);

	if (!CanTransport(unit))
		return;

	AddDeathDependence(unit);
	unit->AddDeathDependence (this);
	unit->transporter = this;
	unit->toBeTransported=false;
	if (!unitDef->isfireplatform) {
		unit->stunned=true;	//make sure unit doesnt fire etc in transport
		selectedUnits.RemoveUnit(unit);
	}
	unit->UnBlock();
	loshandler->FreeInstance(unit->los);
	unit->los=0;
	if (dynamic_cast<CTAAirMoveType*>(moveType)) {
		unit->moveType->useHeading=false;
	}
	TransportedUnit tu;
	tu.unit=unit;
	tu.piece=piece;
	tu.size=unit->xsize/2;
	tu.mass=unit->mass;
	transportCapacityUsed+=tu.size;
	transportMassUsed+=tu.mass;
	transported.push_back(tu);

	unit->CalculateTerrainType();
	unit->UpdateTerrainType();

	luaCallIns.UnitLoaded(unit, this);
}

void CTransportUnit::DetachUnit(CUnit* unit)
{
	if (unit->transporter != this) {
		return;
	}

	list<TransportedUnit>::iterator ti;
	for (ti = transported.begin(); ti != transported.end(); ++ti) {
		if (ti->unit == unit) {
			this->DeleteDeathDependence(unit);
			unit->DeleteDeathDependence(this);
			unit->transporter = 0;
			if (dynamic_cast<CTAAirMoveType*>(moveType)) {
				unit->moveType->useHeading = true;
			}
			unit->stunned = (unit->paralyzeDamage > unit->health);
			unit->Block();
			loshandler->MoveUnit(unit, false);
			unit->moveType->LeaveTransport();
			const CCommandQueue& queue = unit->commandAI->commandQue;
			if (queue.empty() || (queue.front().id != CMD_WAIT)) {
				Command c;
				c.id=CMD_STOP;
				unit->commandAI->GiveCommand(c);
			}
			transportCapacityUsed -= ti->size;
			transportMassUsed -= ti->mass;
			transported.erase(ti);

			unit->CalculateTerrainType();
			unit->UpdateTerrainType();

			luaCallIns.UnitUnloaded(unit, this);

			break;
		}
	}
}

void CTransportUnit::DetachUnitFromAir(CUnit* unit, float3 pos) {

	if(unit->transporter != this)
		return;

	for (list<TransportedUnit>::iterator ti=transported.begin();ti!=transported.end();++ti){
		if (ti->unit==unit) {
			this->DeleteDeathDependence(unit);
			unit->DeleteDeathDependence(this);
			unit->transporter=0;
			if (dynamic_cast<CTAAirMoveType*>(moveType))
				unit->moveType->useHeading=true;

			unit->stunned=false; // de-stun in case it isfireplatform=0
			loshandler->MoveUnit(unit,false);

			//add an additional move command for after we land
			Command c;
			c.id=CMD_MOVE;
			c.params.push_back(pos.x);
			c.params.push_back(pos.y);
			c.params.push_back(pos.z);
			unit->commandAI->GiveCommand(c);

			transportCapacityUsed-=ti->size;
			transportMassUsed-=ti->mass;
			transported.erase(ti);

			unit->Drop(this->pos,this->frontdir,this);
			unit->moveType->LeaveTransport();
			unit->CalculateTerrainType();
			unit->UpdateTerrainType();
			luaCallIns.UnitUnloaded(unit, this);

			break;
		}
	}

}

void CTransportUnit::DetachUnitFromAir(CUnit* unit)
{
	if(unit->transporter != this)
		return;

	for(list<TransportedUnit>::iterator ti=transported.begin();ti!=transported.end();++ti){
		if(ti->unit==unit){
			this->DeleteDeathDependence(unit);
			unit->DeleteDeathDependence(this);
			unit->transporter=0;
			if (dynamic_cast<CTAAirMoveType*>(moveType))
				unit->moveType->useHeading=true;
			unit->stunned=false; // de-stun in case it isfireplatform=0
			unit->Block();

			loshandler->MoveUnit(unit,false);

			Command c;
			c.id=CMD_STOP;
			unit->commandAI->GiveCommand(c);

			transportCapacityUsed-=ti->size;
			transportMassUsed-=ti->mass;
			transported.erase(ti);

			unit->Drop(this->pos,this->frontdir,this);
			unit->moveType->LeaveTransport();
			unit->CalculateTerrainType();
			unit->UpdateTerrainType();
			luaCallIns.UnitUnloaded(unit, this);

			break;
		}
	}
}

⌨️ 快捷键说明

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