// Free around structure, return the first cell that is free. int cAbstractStructure::iFreeAround() { int iStartX = iCellGiveX(iCell); int iStartY = iCellGiveY(iCell); int iEndX = (iStartX + iWidth) + 1; int iEndY = (iStartY + iHeight) + 1; iStartX--; iStartY--; int iCx=0; int iCy=0; for (int x = iStartX; x < iEndX; x++) for (int y = iStartY; y < iEndY; y++) { iCx=x; iCy=y; FIX_BORDER_POS(iCx, iCy); int cll = iCellMake(iCx, iCy); if (map.occupied(cll) == false) { return cll; } } return -1; // fail }
void cRocketTurret::think() { int iMyIndex = -1; for (int i = 0; i < MAX_STRUCTURES; i++) { if (structure[i] == this) { iMyIndex = i; break; } } // this should not happen, but just in case if (iMyIndex < 0) { return; } if (player[getOwner()].bEnoughPower() == false) { return; // do not fire a thing now } // turning & shooting if (iTargetID > -1) { if (unit[iTargetID].isValid()) { // first make sure we face okay! int iCellX = iCellGiveX(getCell()); int iCellY = iCellGiveY(getCell()); int iTargetX = iCellGiveX(unit[iTargetID].iCell); int iTargetY = iCellGiveY(unit[iTargetID].iCell); int d = fDegrees(iCellX, iCellY, iTargetX, iTargetY); int f = face_angle(d); // get the angle // set facing iShouldHeadFacing = f; if (iShouldHeadFacing == iHeadFacing || (unit[iTargetID].iType == ORNITHOPTER)) { TIMER_fire++; int iDistance = 9999; int iSlowDown = 250; if (getType() == RTURRET) iSlowDown = 450; if (unit[iTargetID].isValid()) { // calculate distance iDistance = ABS_length(iCellX, iCellY, iTargetX, iTargetY); if (iDistance > structures[getType()].sight) iTargetID = -1; } else iTargetID = -1; if (iTargetID < 0) return; if (TIMER_fire > iSlowDown) { int iTargetCell = unit[iTargetID].iCell; int iBullet = BULLET_TURRET; if (getType() == RTURRET && iDistance > 3) iBullet = ROCKET_RTURRET; else { int iShootX = (iDrawX() + 16) + (mapCamera->getX() * 32); int iShootY = (iDrawY() + 16) + (mapCamera->getY() * 32); int bmp_head = convert_angle(iHeadFacing); PARTICLE_CREATE(iShootX, iShootY, OBJECT_TANKSHOOT, -1, bmp_head); } int iBull = create_bullet(iBullet, getCell(), iTargetCell, -1, iMyIndex); if (unit[iTargetID].iType == ORNITHOPTER) { // it is a homing missile! bullet[iBull].iHoming = iTargetID; bullet[iBull].TIMER_homing = 200; } TIMER_fire = 0; } } else { TIMER_turn++; int iSlowDown = 200; if (TIMER_turn > iSlowDown) { TIMER_turn = 0; int d = 1; int toleft = (iHeadFacing + 8) - iShouldHeadFacing; if (toleft > 7) toleft -= 8; int toright = abs(toleft - 8); if (toright == toleft) d = -1 + (rnd(2)); if (toleft > toright) d = 1; if (toright > toleft) d = -1; iHeadFacing += d; if (iHeadFacing < 0) iHeadFacing = 7; if (iHeadFacing > 7) iHeadFacing = 0; } // turning } } else iTargetID = -1; } // think like base class cAbstractStructure::think(); }
void cRocketTurret::think_guard() { // no power = no defense if (player[getOwner()].bEnoughPower() == false) { return; } TIMER_guard++; if (TIMER_guard > 10) { int iCellX = iCellGiveX(getCell()); int iCellY = iCellGiveY(getCell()); int iDistance = 9999; // closest distance int iAir = -1; // aircraft (prioritized!) int iWorm = -1; // worm lowest priority int iDanger = -1; // danger id (unit to attack) iTargetID = -1; // no target // scan area for units for (int i = 0; i < MAX_UNITS; i++) { // is valid if (unit[i].isValid()) { bool bAlly = player[getOwner()].iTeam == player[unit[i].iPlayer].iTeam; // not ours and its visible if (unit[i].iPlayer != getOwner() && mapUtils->isCellVisibleForPlayerId(getOwner(), unit[i].iCell) && bAlly == false) { int distance = ABS_length(iCellX, iCellY, iCellGiveX(unit[i].iCell), iCellGiveY(unit[i].iCell)); // when worm or ornithopter is in range, they are not limited to the iDistance (closest // unit) range. if (distance <= structures[getType()].sight) { if (unit[i].iType == ORNITHOPTER) { iAir = i; } else if (unit[i].iType == SANDWORM) { iWorm = i; } } // when distance < closest range so far, this one is the most dangerous. if (distance <= structures[getType()].sight && distance < iDistance) { // ATTACK iDistance = distance; iDanger = i; } } } } // set target if (iAir > -1) { iTargetID = iAir; } else if (iDanger > -1) { iTargetID = iDanger; } else if (iWorm > -1) { iTargetID = iWorm; // else pick worm } TIMER_guard = 0 - rnd(20); // redo } }
// X drawing position int cAbstractStructure::iDrawX() { return ( (( iCellGiveX(iCell) * 32 ) - (mapCamera->getX()*32))); }
// this structure dies void cAbstractStructure::die() { // find myself and set to zero int iIndex=-1; for (int i=0; i < MAX_STRUCTURES; i++) { if (structure[i] == this) { iIndex=i; break; } } if (iIndex < 0) { logbook("cAbstractStructure(): Could not die"); return; } // selected structure if (game.selected_structure == iIndex) { game.selected_structure = -1; } // remove from array structure[iIndex]=NULL; // Destroy structure, take stuff in effect for the player player[iPlayer].iStructures[getType()]--; // remove from player building indexes // fix up power usage player[iPlayer].use_power -= structures[getType()].power_drain; // less power player[iPlayer].has_power -= structures[getType()].power_give; if (getType() == SILO) { player[iPlayer].max_credits -= 1000; } if (getType() == REFINERY) { player[iPlayer].max_credits -= 1500; } // UnitID > -1, means the unit inside will die too if (iUnitID > -1) { unit[iUnitID].init(iUnitID); // die here... softly } int iCll=iCell; int iCX=iCellGiveX(iCll); int iCY=iCellGiveY(iCll); // create destroy particles for (int w=0; w < iWidth; w++) { for (int h=0; h < iHeight; h++) { iCll=iCellMake(iCX+w, iCY+h); map.cell[iCll].type = TERRAIN_ROCK; mapEditor.smoothAroundCell(iCll); PARTICLE_CREATE(iDrawX() + (mapCamera->getX()*32) + (w*32) + 16, iDrawY() + (mapCamera->getY()*32) + (h*32) + 16, OBJECT_BOOM01, -1, -1); for (int i=0; i < 3; i++) { map.smudge_increase(SMUDGE_ROCK, iCll); // create particle PARTICLE_CREATE(iDrawX() + (mapCamera->getX()*32) + (w*32) + 16 + (-8 + rnd(16)), iDrawY() + (mapCamera->getY()*32) + (h*32) + 16 + (-8 + rnd(16)), EXPLOSION_STRUCTURE01 + rnd(2), -1, -1); // create smoke if (rnd(100) < 7) PARTICLE_CREATE(iDrawX() + (mapCamera->getX()*32) + (w*32) + 16 + (-8 + rnd(16)), iDrawY() + (mapCamera->getY()*32) + (h*32) + 16 + (-8 + rnd(16)), OBJECT_SMOKE, -1, -1); // create fire if (rnd(100) < 5) PARTICLE_CREATE(iDrawX() + (mapCamera->getX()*32) + (w*32) + 16 + (-8 + rnd(16)), iDrawY() + (mapCamera->getY()*32) + (h*32) + 16 + (-8 + rnd(16)), EXPLOSION_FIRE, -1, -1); } } } // play sound play_sound_id(SOUND_CRUMBLE01 + rnd(2), iCellOnScreen(iCell)); // remove from the playground map.remove_id(iIndex, MAPID_STRUCTURES); // screen shaking game.TIMER_shake = (iWidth * iHeight) * 20; // eventually die cStructureFactory::getInstance()->deleteStructureInstance(this); }