📄 unit.cpp
字号:
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 + -