cobinstance.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 1,724 行 · 第 1/4 页
CPP
1,724 行
float pieceChance=1-(ph->currentParticles-(ph->maxParticles-2000))/2000;
// logOutput.Print("Shattering %i %f",dl->prims.size(),pieceChance);
S3DO* dl = pieceData->original3do;
if(dl){
/* 3DO */
for(std::vector<S3DOPrimitive>::iterator pi=dl->prims.begin();pi!=dl->prims.end();++pi){
if(gu->usRandFloat()>pieceChance || pi->numVertex!=4)
continue;
ph->AddFlyingPiece(pos,speed+gu->usRandVector()*2,dl,&*pi);
}
}
SS3O* cookedPiece = pieceData->originals3o;
if (cookedPiece){
/* S3O */
if (cookedPiece->primitiveType == 0){
/* GL_TRIANGLES */
for (int i = 0; i < cookedPiece->vertexDrawOrder.size(); i += 3){
if(gu->usRandFloat()>pieceChance)
continue;
SS3OVertex * verts = SAFE_NEW SS3OVertex[4];
verts[0] = cookedPiece->vertices[cookedPiece->vertexDrawOrder[i + 0]];
verts[1] = cookedPiece->vertices[cookedPiece->vertexDrawOrder[i + 1]];
verts[2] = cookedPiece->vertices[cookedPiece->vertexDrawOrder[i + 1]];
verts[3] = cookedPiece->vertices[cookedPiece->vertexDrawOrder[i + 2]];
ph->AddFlyingPiece(unit->model->textureType,
unit->team,
pos, speed+gu->usRandVector()*2, verts);
}
} else if (cookedPiece->primitiveType == 1){
/* GL_TRIANGLE_STRIP */
for (int i = 2; i < cookedPiece->vertexDrawOrder.size(); i++){
if(gu->usRandFloat()>pieceChance)
continue;
SS3OVertex * verts = SAFE_NEW SS3OVertex[4];
verts[0] = cookedPiece->vertices[cookedPiece->vertexDrawOrder[i - 2]];
verts[1] = cookedPiece->vertices[cookedPiece->vertexDrawOrder[i - 1]];
verts[2] = cookedPiece->vertices[cookedPiece->vertexDrawOrder[i - 1]];
verts[3] = cookedPiece->vertices[cookedPiece->vertexDrawOrder[i - 0]];
ph->AddFlyingPiece(unit->model->textureType,
unit->team,
pos, speed+gu->usRandVector()*2, verts);
}
} else if (cookedPiece->primitiveType == 2){
/* GL_QUADS */
for (int i = 0; i < cookedPiece->vertexDrawOrder.size(); i += 4){
if(gu->usRandFloat()>pieceChance)
continue;
SS3OVertex * verts = SAFE_NEW SS3OVertex[4];
verts[0] = cookedPiece->vertices[cookedPiece->vertexDrawOrder[i + 0]];
verts[1] = cookedPiece->vertices[cookedPiece->vertexDrawOrder[i + 1]];
verts[2] = cookedPiece->vertices[cookedPiece->vertexDrawOrder[i + 2]];
verts[3] = cookedPiece->vertices[cookedPiece->vertexDrawOrder[i + 3]];
ph->AddFlyingPiece(unit->model->textureType,
unit->team,
pos, speed+gu->usRandVector()*2, verts);
}
}
}
ENTER_SYNCED;
}
else {
if (pieceData->original3do != NULL || pieceData->originals3o != NULL) {
//logOutput.Print("Exploding %s as %d", script.pieceNames[piece].c_str(), dl);
SAFE_NEW CPieceProjectile(pos, speed, pieceData, newflags,unit,0.5f);
}
}
#endif
}
void CCobInstance::PlayUnitSound(int snr, int attr)
{
int sid = script.sounds[snr];
//logOutput.Print("Playing %d %d %d", snr, attr, sid);
sound->PlaySample(sid, unit->pos, attr);
}
void CCobInstance::ShowFlare(int piece)
{
if (!unit->localmodel->PieceExists(piece)) {
GCobEngine.ShowScriptError("Invalid piecenumber for show(flare)");
return;
}
#ifndef _CONSOLE
float3 relpos = unit->localmodel->GetPiecePos(piece);
float3 pos=unit->pos + unit->frontdir*relpos.z + unit->updir*relpos.y + unit->rightdir*relpos.x;
float3 dir=unit->lastMuzzleFlameDir;
float size=unit->lastMuzzleFlameSize;
SAFE_NEW CMuzzleFlame(pos, unit->speed,dir, size);
#endif
}
int CCobInstance::GetUnitVal(int val, int p1, int p2, int p3, int p4)
{
#ifndef _CONSOLE
switch(val)
{
case ACTIVATION:
if (unit->activated)
return 1;
else
return 0;
break;
case STANDINGMOVEORDERS:
return unit->moveState;
break;
case STANDINGFIREORDERS:
return unit->fireState;
break;
case HEALTH:{
if (p1 <= 0)
return (int) ((unit->health/unit->maxHealth)*100.0f);
CUnit *u = (p1 < MAX_UNITS) ? uh->units[p1] : NULL;
if (u == NULL)
return 0;
else
return (int) ((u->health/u->maxHealth)*100.0f);
}
case INBUILDSTANCE:
if (unit->inBuildStance)
return 1;
else
return 0;
case BUSY:
if (busy)
return 1;
else
return 0;
break;
case PIECE_XZ:{
if (!unit->localmodel->PieceExists(p1))
GCobEngine.ShowScriptError("Invalid piecenumber for get piece_xz");
float3 relPos = unit->localmodel->GetPiecePos(p1);
float3 pos = unit->pos + unit->frontdir * relPos.z + unit->updir * relPos.y + unit->rightdir * relPos.x;
return PACKXZ(pos.x, pos.z);}
case PIECE_Y:{
if (!unit->localmodel->PieceExists(p1))
GCobEngine.ShowScriptError("Invalid piecenumber for get piece_y");
float3 relPos = unit->localmodel->GetPiecePos(p1);
float3 pos = unit->pos + unit->frontdir * relPos.z + unit->updir * relPos.y + unit->rightdir * relPos.x;
return (int)(pos.y * COBSCALE);}
case UNIT_XZ: {
if (p1 <= 0)
return PACKXZ(unit->pos.x, unit->pos.z);
CUnit *u = (p1 < MAX_UNITS) ? uh->units[p1] : NULL;
if (u == NULL)
return PACKXZ(0,0);
else
return PACKXZ(u->pos.x, u->pos.z);}
case UNIT_Y: {
//logOutput.Print("Unit-y %d", p1);
if (p1 <= 0)
return (int)(unit->pos.y * COBSCALE);
CUnit *u = (p1 < MAX_UNITS) ? uh->units[p1] : NULL;
if (u == NULL)
return 0;
else
return (int)(u->pos.y * COBSCALE);}
case UNIT_HEIGHT:{
if (p1 <= 0)
return (int)(unit->radius * COBSCALE);
CUnit *u = (p1 < MAX_UNITS) ? uh->units[p1] : NULL;
if (u == NULL)
return 0;
else
return (int)(u->radius * COBSCALE);}
case XZ_ATAN:
return (int)(TAANG2RAD*atan2((float)UNPACKX(p1), (float)UNPACKZ(p1)) + 32768 - unit->heading);
case XZ_HYPOT:
return (int)(hypot((float)UNPACKX(p1), (float)UNPACKZ(p1)) * COBSCALE);
case ATAN:
return (int)(TAANG2RAD*atan2((float)p1, (float)p2));
case HYPOT:
return (int)hypot((float)p1, (float)p2);
case GROUND_HEIGHT:
return (int)(ground->GetHeight(UNPACKX(p1), UNPACKZ(p1)) * COBSCALE);
case GROUND_WATER_HEIGHT:
return (int)(ground->GetHeight2(UNPACKX(p1), UNPACKZ(p1)) * COBSCALE);
case BUILD_PERCENT_LEFT:
return (int)((1 - unit->buildProgress) * 100);
case YARD_OPEN:
if (yardOpen)
return 1;
else
return 0;
case BUGGER_OFF:
break;
case ARMORED:
if (unit->armoredState)
return 1;
else
return 0;
case VETERAN_LEVEL:
return (int)(100*unit->experience);
case CURRENT_SPEED:
if (unit->moveType)
return (int)(unit->speed.Length()*COBSCALE);
return 0;
case ON_ROAD:
return 0;
case IN_WATER:
return (unit->pos.y < 0.0f) ? 1 : 0;
case MAX_ID:
return MAX_UNITS-1;
case MY_ID:
return unit->id;
case UNIT_TEAM:{
CUnit *u = (p1 >= 0 && p1 < MAX_UNITS) ? uh->units[p1] : NULL;
return u ? unit->team : 0; }
case UNIT_ALLIED:{
CUnit *u = (p1 >= 0 && p1 < MAX_UNITS) ? uh->units[p1] : NULL;
if (u) return gs->Ally (unit->allyteam, u->allyteam) ? 1 : 0;
return 0;}
case UNIT_BUILD_PERCENT_LEFT:{
CUnit *u = (p1 >= 0 && p1 < MAX_UNITS) ? uh->units[p1] : NULL;
if (u) return (int)((1 - u->buildProgress) * 100);
return 0;}
case MAX_SPEED:
if(unit->moveType){
return int(unit->moveType->maxSpeed*COBSCALE);
}
break;
case CLOAKED:
return !!unit->isCloaked;
case WANT_CLOAK:
return !!unit->wantCloak;
case UPRIGHT:
return !!unit->upright;
case POW:
return int(pow(((float)p1)/COBSCALE,((float)p2)/COBSCALE)*COBSCALE);
case PRINT:
logOutput.Print("Value 1: %d, 2: %d, 3: %d, 4: %d", p1, p2, p3, p4);
break;
case HEADING: {
if (p1 <= 0)
return unit->heading;
CUnit *u = (p1 < MAX_UNITS) ? uh->units[p1] : NULL;
if (u == NULL)
return -1;
else
return u->heading;}
case TARGET_ID:
if (unit->weapons[p1-1]) {
CWeapon* weapon = unit->weapons[p1-1];
TargetType tType = weapon->targetType;
if (tType == Target_Unit)
return unit->weapons[p1 - 1]->targetUnit->id;
else if (tType == Target_None)
return -1;
else if (tType == Target_Pos)
return -2;
else // Target_Intercept
return -3;
}
return -4; // weapon does not exist
case LAST_ATTACKER_ID:
return unit->lastAttacker?unit->lastAttacker->id:-1;
case LOS_RADIUS:
return unit->realLosRadius;
case AIR_LOS_RADIUS:
return unit->realAirLosRadius;
case RADAR_RADIUS:
return unit->radarRadius;
case JAMMER_RADIUS:
return unit->jammerRadius;
case SONAR_RADIUS:
return unit->sonarRadius;
case SONAR_JAM_RADIUS:
return unit->sonarJamRadius;
case SEISMIC_RADIUS:
return unit->seismicRadius;
case DO_SEISMIC_PING:
float pingSize;
if (p1 == 0) {
pingSize = unit->seismicSignature;
} else {
pingSize = p1;
}
unit->DoSeismicPing(pingSize);
break;
case CURRENT_FUEL:
return int(unit->currentFuel * float(COBSCALE));
case TRANSPORT_ID:
return unit->transporter?unit->transporter->id:-1;
case SHIELD_POWER: {
if (unit->shieldWeapon == NULL) {
return -1;
}
const CPlasmaRepulser* shield = (CPlasmaRepulser*)unit->shieldWeapon;
return int(shield->curPower * float(COBSCALE));
}
case STEALTH: {
return unit->stealth ? 1 : 0;
}
case CRASHING:
return !!unit->crashing;
case ALPHA_THRESHOLD: {
return int(unit->alphaThreshold * 255);
}
case COB_ID: {
if (p1 <= 0) {
return unit->unitDef->cobID;
} else {
const CUnit *u = (p1 < MAX_UNITS) ? uh->units[p1] : NULL;
return (u == NULL) ? -1 : u->unitDef->cobID;
}
}
case PLAY_SOUND: {
if ((p1 < 0) || (p1 >= script.sounds.size())) {
return 1;
}
switch (p3) { //who hears the sound
case 0: //ALOS
if (!loshandler->InAirLos(unit->pos,gu->myAllyTeam)) { return 0; }
break;
case 1: //LOS
if (!(unit->losStatus[gu->myAllyTeam] & LOS_INLOS)) { return 0; }
break;
case 2: //ALOS or radar
if (!(loshandler->InAirLos(unit->pos,gu->myAllyTeam) || unit->losStatus[gu->myAllyTeam] & (LOS_INRADAR))) { return 0; }
break;
case 3: //LOS or radar
if (!(unit->losStatus[gu->myAllyTeam] & (LOS_INLOS | LOS_INRADAR))) { return 0; }
break;
case 4: //everyone
break;
case 5: //allies
if (unit->allyteam != gu->myAllyTeam) { return 0; }
break;
case 6: //team
if (unit->team != gu->myTeam) { return 0; }
break;
case 7: //enemies
if (unit->allyteam == gu->myAllyTeam) { return 0; }
break;
}
if (p4 == 0) {
sound->PlaySample(script.sounds[p1], unit->pos, float(p2) / COBSCALE);
} else {
sound->PlaySample(script.sounds[p1], float(p2) / COBSCALE);
}
return 0;
}
case SET_WEAPON_UNIT_TARGET: {
const int weaponID = p1 - 1;
const int targetID = p2;
const bool userTarget = !!p3;
//logOutput.Print("SET_WEAPON_UNIT_TARGET: %i %i %i\n", weaponID, targetID, p3); // FIXME
if ((weaponID < 0) || (weaponID >= unit->weapons.size())) {
return 0;
}
CWeapon* weapon = unit->weapons[weaponID];
if (weapon == NULL) { return 0; }
if ((targetID < 0) || (targetID >= MAX_UNITS)) { return 0; }
CUnit* target = (targetID == 0) ? NULL : uh->units[targetID];
//logOutput.Print("SET_WEAPON_UNIT_TARGET2\n"); // FIXME
return weapon->AttackUnit(target, userTarget) ? 1 : 0;
}
case SET_WEAPON_GROUND_TARGET: {
const int weaponID = p1 - 1;
const float3 pos = float3(float(UNPACKX(p2)),
float(p3) / float(COBSCALE),
float(UNPACKZ(p2)));
const bool userTarget = !!p4;
//logOutput.Print("SET_WEAPON_GROUND_TARGET: %i %f %f %f\n", weaponID, pos.x, pos.y, pos.z);//FIXME
if ((weaponID < 0) || (weaponID >= unit->weapons.size())) {
return 0;
}
CWeapon* weapon = unit->weapons[weaponID];
if (weapon == NULL) { return 0; }
return weapon->AttackGround(pos, userTarget) ? 1 : 0;
}
case FLANK_B_MODE:
return unit->flankingBonusMode;
case FLANK_B_DIR:
switch(p1){
case 1: return int(unit->flankingBonusDir.x * COBSCALE);
case 2: return int(unit->flankingBonusDir.y * COBSCALE);
case 3: return int(unit->flankingBonusDir.z * COBSCALE);
case 4: unit->flankingBonusDir.x = (p2/(float)COBSCALE); return 0;
case 5: unit->flankingBonusDir.y = (p2/(float)COBSCALE); return 0;
case 6: unit->flankingBonusDir.z = (p2/(float)COBSCALE); return 0;
case 7: unit->flankingBonusDir = float3(p2/(float)COBSCALE, p3/(float)COBSCALE, p4/(float)COBSCALE).Normalize(); return 0;
default: return(-1);
}
case FLANK_B_MOBILITY_ADD:
return int(unit->flankingBonusMobilityAdd * COBSCALE);
case FLANK_B_MAX_DAMAGE:
return int((unit->flankingBonusAvgDamage + unit->flankingBonusDifDamage) * COBSCALE);
case FLANK_B_MIN_DAMAGE:
return int((unit->flankingBonusAvgDamage - unit->flankingBonusDifDamage) * COBSCALE);
case KILL_UNIT: {
if (p1 >= 0 && p1 < MAX_UNITS) {
CUnit *u = p1 ? uh->units[p1] : unit;
if (!u) {
return 0;
}
if (u->beingBuilt) u->KillUnit(false, true, NULL); // no explosions and no corpse for units under construction
else u->KillUnit(p2!=0, p3!=0, NULL);
return 1;
}
return 0;
}
case WEAPON_RELOADSTATE: {
if (p1 > 0 && p1 <= unit->weapons.size()) {
return unit->weapons[p1-1]->reloadStatus;
}
else if (p1 < 0 && p1 >= 0 - unit->weapons.size()) {
int old = unit->weapons[-p1-1]->reloadStatus;
unit->weapons[-p1-1]->reloadStatus = p2;
return old;
}
else {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?