⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unit.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	DoDamage(da * (health / da[armorType]), 0, impulse, -1);
}


/******************************************************************************/
/******************************************************************************/
//
//  Drawing routines
//

inline void CUnit::DrawModel()
{
	if (luaDraw && luaRules && luaRules->DrawUnit(id)) {
		return;
	}

	if (lodCount <= 0) {
		localmodel->Draw();
	} else {
		localmodel->DrawLOD(currentLOD);
	}
}


void CUnit::DrawRawModel()
{
	if (lodCount <= 0) {
		localmodel->Draw();
	} else {
		localmodel->DrawLOD(currentLOD);
	}
}


inline void CUnit::DrawDebug()
{
	// draw the collision sphere
	if (gu->drawdebug) {
		glPushMatrix();
		glTranslatef3((frontdir * relMidPos.z) +
					   (updir    * relMidPos.y) +
					   (rightdir * relMidPos.x));
		GLUquadricObj* q = gluNewQuadric();
		gluQuadricDrawStyle(q, GLU_LINE);
		gluSphere(q, radius, 10, 10);
		gluDeleteQuadric(q);
		glPopMatrix();
	}
}


void CUnit::Draw()
{
	glAlphaFunc(GL_GEQUAL, alphaThreshold);

	glPushMatrix();
	ApplyTransformMatrix();

	if (!beingBuilt || !unitDef->showNanoFrame) {
		DrawModel();
	} else {
		DrawBeingBuilt();
	}

	DrawDebug();
	glPopMatrix();
}


void CUnit::DrawRaw()
{
	glPushMatrix();
	ApplyTransformMatrix();
	DrawModel();
	glPopMatrix();
}


void CUnit::DrawWithLists(unsigned int preList, unsigned int postList)
{
	glPushMatrix();
	ApplyTransformMatrix();

	if (preList != 0) {
		glCallList(preList);
	}

	if (!beingBuilt || !unitDef->showNanoFrame) {
		DrawModel();
	} else {
		DrawBeingBuilt();
	}

	if (postList != 0) {
		glCallList(postList);
	}

	DrawDebug();
	glPopMatrix();
}


void CUnit::DrawRawWithLists(unsigned int preList, unsigned int postList)
{
	glPushMatrix();
	ApplyTransformMatrix();

	if (preList != 0) {
		glCallList(preList);
	}

	DrawModel();

	if (postList != 0) {
		glCallList(postList);
	}

	glPopMatrix();
}


void CUnit::DrawBeingBuilt()
{
	if (shadowHandler->inShadowPass) {
		if (buildProgress > 0.66f) {
			DrawModel();
		}
		return;
	}

	const float start  = model->miny;
	const float height = model->height;

	glEnable(GL_CLIP_PLANE0);
	glEnable(GL_CLIP_PLANE1);

	const float col = fabs(128.0f - ((gs->frameNum * 4) & 255)) / 255.0f + 0.5f;
	float3 fc;// fc frame color
	if (!gu->teamNanospray) {
		fc = unitDef->nanoColor;
	}
	else {
		const unsigned char* tcol = gs->Team(team)->color;
		fc = float3(tcol[0] * (1.0f / 255.0f),
								tcol[1] * (1.0f / 255.0f),
								tcol[2] * (1.0f / 255.0f));
	}
	glColorf3(fc * col);

	unitDrawer->UnitDrawingTexturesOff(model);

	const double plane0[4] = { 0, -1, 0, start + height * buildProgress * 3 };
	glClipPlane(GL_CLIP_PLANE0, plane0);
	const double plane1[4] = { 0, 1, 0, -start - height * (buildProgress * 10 - 9) };
	glClipPlane(GL_CLIP_PLANE1, plane1);

	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	DrawModel();
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	if (buildProgress>0.33f) {
		glColorf3(fc * (1.5f - col));
		const double plane0[4] = { 0, -1, 0, start + height * (buildProgress * 3 - 1) };
		glClipPlane(GL_CLIP_PLANE0, plane0);
		const double plane1[4] = { 0, 1, 0, -start - height * (buildProgress * 3 - 2) };
		glClipPlane(GL_CLIP_PLANE1, plane1);

		DrawModel();
	}
	glDisable(GL_CLIP_PLANE1);

	unitDrawer->UnitDrawingTexturesOn(model);

	if (buildProgress > 0.66f){
		const double plane0[4] = { 0, -1, 0 , start + height * (buildProgress * 3 - 2) };
		glClipPlane(GL_CLIP_PLANE0, plane0);
		if (shadowHandler->drawShadows && !water->drawReflection) {
			glPolygonOffset(1.0f, 1.0f);
			glEnable(GL_POLYGON_OFFSET_FILL);
		}
		DrawModel();
		if (shadowHandler->drawShadows && !water->drawReflection) {
			glDisable(GL_POLYGON_OFFSET_FILL);
		}
	}
	glDisable(GL_CLIP_PLANE0);
}


void CUnit::ApplyTransformMatrix() const
{
	CMatrix44f m;
	GetTransformMatrix(m);
	glMultMatrixf(&m[0]);
}


void CUnit::GetTransformMatrix(CMatrix44f& matrix) const
{
	float3 interPos;
	if (!transporter) {
		interPos = pos + (speed * gu->timeOffset);
	} else {
		interPos = pos + (transporter->speed * gu->timeOffset);
	}

	if (!beingBuilt && (usingScriptMoveType || ((physicalState == Flying) && unitDef->canmove))) {
		// aircraft, skidding ground unit, or active ScriptMoveType
		// note: (CAirMoveType) aircraft under construction should not
		// use this matrix, or their nanoframes won't spin on pad
		CMatrix44f transMatrix(interPos, -rightdir, updir, frontdir);
		matrix = transMatrix;
	}
	else if (transporter && transporter->unitDef->holdSteady) {
		// making local copies of vectors
		float3 frontDir = GetVectorFromHeading(heading);
		float3 upDir    = updir;
		float3 rightDir = frontDir.cross(upDir);
		rightDir.Normalize();
		frontDir = upDir.cross(rightDir);
		CMatrix44f transMatrix(interPos, -rightDir, upDir, frontDir);
		matrix = transMatrix;
	}
	else if (upright || !unitDef->canmove) {
		if (heading == 0) {
			matrix.LoadIdentity();
			matrix.Translate(interPos);
		} else {
			// making local copies of vectors
			float3 frontDir = GetVectorFromHeading(heading);
			float3 upDir    = updir;
			float3 rightDir = frontDir.cross(upDir);
			rightDir.Normalize();
			frontDir = upDir.cross(rightDir);
			CMatrix44f transMatrix(interPos, -rightdir, updir, frontdir);
			matrix = transMatrix;
		}
	}
	else {
		// making local copies of vectors
		float3 frontDir = GetVectorFromHeading(heading);
		float3 upDir    = ground->GetSmoothNormal(pos.x, pos.z);
		float3 rightDir = frontDir.cross(upDir);
		rightDir.Normalize();
		frontDir = upDir.cross(rightDir);
		CMatrix44f transMatrix(interPos, -rightDir, upDir, frontDir);
		matrix = transMatrix;
	}
}


void CUnit::DrawStats()
{
	if ((gu->myAllyTeam != allyteam) &&
	    !gu->spectatingFullView && unitDef->hideDamage) {
		return;
	}

	float3 interPos;
	if (!transporter) {
		interPos = pos + (speed * gu->timeOffset);
	} else {
		interPos = pos + (transporter->speed * gu->timeOffset);
	}
	interPos.y += model->height + 5.0f;

	// setup the billboard transformation
	glPushMatrix();
	glTranslatef(interPos.x, interPos.y, interPos.z);
	//glMultMatrixd(camera->billboard);
	glCallList(CCamera::billboardList);

	// black background for healthbar
	glColor3f(0.0f, 0.0f, 0.0f);
	glRectf(-5.0f, 4.0f, +5.0f, 6.0f);

	// healthbar
	const float hpp = max(0.0f, health / maxHealth);
	const float hEnd = hpp * 10.0f;
	if (stunned) {
		glColor3f(0.0f, 0.0f, 1.0f);
	} else {
		if (hpp > 0.5f) {
			glColor3f(1.0f - ((hpp - 0.5f) * 2.0f), 1.0f, 0.0f);
		} else {
			glColor3f(1.0f, hpp * 2.0f, 0.0f);
		}
	}
	glRectf(-5.0f, 4.0f, hEnd - 5.0f, 6.0f);

	// stun level
	if (!stunned && (paralyzeDamage > 0.0f)) {
		const float pEnd = (paralyzeDamage / maxHealth) * 10.0f;
		glColor3f(0.0f, 0.0f, 1.0f);
		glRectf(-5.0f, 4.0f, pEnd - 5.0f, 6.0f);
	}

	// skip the rest of the indicators if it isn't a local unit
	if ((gu->myTeam != team) && !gu->spectatingFullView) {
		glPopMatrix();
		return;
	}

	// experience bar
	const float eEnd = (limExperience * 0.8f) * 10.0f;
	glColor3f(1.0f, 1.0f, 1.0f);
	glRectf(6.0f, -2.0f, 8.0f, eEnd - 2.0f);

	if (beingBuilt) {
		const float bEnd = (buildProgress * 0.8f) * 10.0f;
		glColor3f(1.0f, 0.0f, 0.0f);
		glRectf(-8.0f, -2.0f, -6.0f, bEnd - 2.0f);
	}
	else if (stockpileWeapon) {
		const float sEnd = (stockpileWeapon->buildPercent * 0.8f) * 10.0f;
		glColor3f(1.0f, 0.0f, 0.0f);
		glRectf(-8.0f, -2.0f, -6.0f, sEnd - 2.0f);
	}

	if (group) {
		const float scale = 10.0f;
		char buf[32];
		sprintf(buf, "%i", group->id);
		const float width = scale * font->CalcTextWidth(buf);

		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glTranslatef(-7.0f - width, 0.0f, 0.0f); // right justified
		glScalef(scale, scale, scale);
		glColor3f(1.0f, 1.0f, 1.0f);
		font->glPrintSuperRaw(buf);
		glDisable(GL_TEXTURE_2D);
		glDisable(GL_BLEND);
	}

	glPopMatrix();
}


/******************************************************************************/
/******************************************************************************/

void CUnit::AddExperience(float exp)
{
	const float oldExp = experience;
	experience += exp;

	const float oldLimExp = limExperience;
	limExperience = experience / (experience + 1.0f);

	if (expGrade != 0.0f) {
		const int oldGrade = (int)(oldLimExp     / expGrade);
		const int newGrade = (int)(limExperience / expGrade);
		if (oldGrade != newGrade) {
			luaCallIns.UnitExperience(this, oldExp);
		}
	}

	if (expPowerScale > 0.0f) {
		power = unitDef->power * (1.0f + (limExperience * expPowerScale));
	}
	if (expReloadScale > 0.0f) {
		reloadSpeed = (1.0f + (limExperience * expReloadScale));
	}
	if (expHealthScale > 0.0f) {
		const float oldMaxHealth = maxHealth;
		maxHealth = unitDef->health * (1.0f + (limExperience * expHealthScale));
		health = health * (maxHealth / oldMaxHealth);
	}
}


void CUnit::DoSeismicPing(float pingSize)
{
	float rx = gs->randFloat();
	float rz = gs->randFloat();

	const float* errorScale = radarhandler->radarErrorSize;
	if (!(losStatus[gu->myAllyTeam] & LOS_INLOS) &&
	    radarhandler->InSeismicDistance(this, gu->myAllyTeam)) {
		const float3 err(errorScale[gu->myAllyTeam] * (0.5f - rx), 0.0f,
		                 errorScale[gu->myAllyTeam] * (0.5f - rz));

		SAFE_NEW CSeismicGroundFlash(pos + err,
		                             ph->seismictex, 30, 15, 0, pingSize, 1,
		                             float3(0.8f,0.0f,0.0f));
	}
	for (int a=0; a<gs->activeAllyTeams; ++a) {
		if (radarhandler->InSeismicDistance(this, a)) {
			const float3 err(errorScale[a] * (0.5f - rx), 0.0f,
							 errorScale[a] * (0.5f - rz));
			const float3 pingPos = (pos + err);
			luaCallIns.UnitSeismicPing(this, a, pingPos, pingSize);
			globalAI->SeismicPing(a, this, pingPos, pingSize);
		}
	}
}

void CUnit::ChangeLos(int l,int airlos)
{
	loshandler->FreeInstance(los);
	los=0;
	losRadius=l;
	airLosRadius=airlos;
	loshandler->MoveUnit(this,false);
}


bool CUnit::ChangeTeam(int newteam, ChangeType type)
{
	// do not allow unit count violations due to team swapping
	// (this includes unit captures)
	if (uh->unitsByDefs[newteam][unitDef->id].size() >= unitDef->maxThisUnit) {
		return false;
	}

	const bool capture = (type == ChangeCaptured);
	if (luaRules && !luaRules->AllowUnitTransfer(this, newteam, capture)) {
		return false;
	}

	const int oldteam = team;

	selectedUnits.RemoveUnit(this);
	SetGroup(0);

	luaCallIns.UnitTaken(this, newteam);
	globalAI->UnitTaken(this, oldteam);

	// reset states and clear the queues
	if (!gs->AlliedTeams(oldteam, newteam)) {
		ChangeTeamReset();
	}

	qf->RemoveUnit(this);
	quads.clear();
	loshandler->FreeInstance(los);
	los = 0;
	losStatus[allyteam] = 0;
	if (hasRadarCapacity) {
		radarhandler->RemoveUnit(this);
	}

	if (unitDef->isAirBase) {
		airBaseHandler->DeregisterAirBase(this);
	}

	// Sharing commander in com ends game kills you.
	// Note that this will kill the com too.
	if (unitDef->isCommander) {
		gs->Team(oldteam)->CommanderDied(this);
	}

	if (type == ChangeGiven) {
		gs->Team(oldteam)->RemoveUnit(this, CTeam::RemoveGiven);
		gs->Team(newteam)->AddUnit(this,    CTeam::AddGiven);
	} else {
		gs->Team(oldteam)->RemoveUnit(this, CTeam::RemoveCaptured);
		gs->Team(newteam)->AddUnit(this,    CTeam::AddCaptured);
	}

	if (!beingBuilt) {
		gs->Team(oldteam)->metalStorage  -= metalStorage;
		gs->Team(oldteam)->energyStorage -= energyStorage;

		gs->Team(newteam)->metalStorage  += metalStorage;
		gs->Team(newteam)->energyStorage += energyStorage;
	}


	team = newteam;
	allyteam = gs->AllyTeam(newteam);

	uh->unitsByDefs[oldteam][unitDef->id].erase(this);
	uh->unitsByDefs[newteam][unitDef->id].insert(this);

	neutral = false;

	loshandler->MoveUnit(this,false);
	losStatus[allyteam] = LOS_INTEAM | LOS_INLOS | LOS_INRADAR | LOS_PREVLOS | LOS_CONTRADAR;
	qf->MovedUnit(this);
	if (hasRadarCapacity) {
		radarhandler->MoveUnit(this);
	}

	model = unitDef->LoadModel(newteam);

⌨️ 快捷键说明

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