/* Create a feature on the map */ FEATURE * buildFeature(FEATURE_STATS *psStats, UDWORD x, UDWORD y,BOOL FromSave) { UDWORD mapX, mapY; UDWORD width,breadth, foundationMin,foundationMax, height; UDWORD startX,startY,max,min; SDWORD i; UBYTE vis; //try and create the Feature FEATURE* psFeature = createFeature(); if (psFeature == NULL) { debug(LOG_WARNING, "Feature couldn't be built."); return NULL; } psFeature->psStats = psStats; // features are not in the cluster system // this will cause an assert when they still end up there psFeature->cluster = ~0; //add the feature to the list - this enables it to be drawn whilst being built addFeature(psFeature); // get the terrain average height startX = map_coord(x); startY = map_coord(y); foundationMin = TILE_MAX_HEIGHT; foundationMax = TILE_MIN_HEIGHT; for (breadth = 0; breadth < psStats->baseBreadth; breadth++) { for (width = 0; width < psStats->baseWidth; width++) { getTileMaxMin(startX + width, startY + breadth, &max, &min); if (foundationMin > min) { foundationMin = min; } if (foundationMax < max) { foundationMax = max; } } } //return the average of max/min height height = (foundationMin + foundationMax) / 2; // snap the coords to a tile if (!FromSave) { x = (x & ~TILE_MASK) + psStats->baseWidth %2 * TILE_UNITS/2; y = (y & ~TILE_MASK) + psStats->baseBreadth%2 * TILE_UNITS/2; } else { if ((x & TILE_MASK) != psStats->baseWidth %2 * TILE_UNITS/2 || (y & TILE_MASK) != psStats->baseBreadth%2 * TILE_UNITS/2) { debug(LOG_WARNING, "Feature not aligned. position (%d,%d), size (%d,%d)", x, y, psStats->baseWidth, psStats->baseBreadth); } } psFeature->pos.x = x; psFeature->pos.y = y; /* Dump down the building wrecks at random angles - still looks shit though */ if(psStats->subType == FEAT_BUILD_WRECK || psStats->subType == FEAT_TREE) { psFeature->rot.direction = gameRand(DEG_360); } else { psFeature->rot.direction = 0; } psFeature->selected = false; psFeature->body = psStats->body; psFeature->player = MAX_PLAYERS+1; //set the player out of range to avoid targeting confusions objSensorCache((BASE_OBJECT *)psFeature, NULL); objEcmCache((BASE_OBJECT *)psFeature, NULL); psFeature->bTargetted = false; psFeature->timeLastHit = 0; psFeature->lastHitWeapon = WSC_NUM_WEAPON_SUBCLASSES; // no such weapon // it has never been drawn psFeature->sDisplay.frameNumber = 0; if(getRevealStatus()) { vis = 0; } else { if(psStats->visibleAtStart) { vis = UBYTE_MAX; } else { vis = 0; } } // note that the advanced armour system current unused for features for (i = 0; i < NUM_HIT_SIDES; i++) { int j; for (j = 0; j < WC_NUM_WEAPON_CLASSES; j++) { psFeature->armour[i][j] = psFeature->psStats->armourValue; } } memset(psFeature->seenThisTick, 0, sizeof(psFeature->seenThisTick)); memset(psFeature->visible, 0, sizeof(psFeature->visible)); //load into the map data mapX = map_coord(x) - psStats->baseWidth/2; mapY = map_coord(y) - psStats->baseBreadth/2; // set up the imd for the feature if(psFeature->psStats->subType==FEAT_BUILD_WRECK) { psFeature->sDisplay.imd = getRandomWreckageImd(); } else { psFeature->sDisplay.imd = psStats->psImd; } ASSERT_OR_RETURN(NULL, psFeature->sDisplay.imd, "No IMD for feature"); // make sure we have an imd. for (width = 0; width < psStats->baseWidth; width++) { for (breadth = 0; breadth < psStats->baseBreadth; breadth++) { MAPTILE *psTile = mapTile(mapX + width, mapY + breadth); //check not outside of map - for load save game ASSERT_OR_RETURN(NULL, mapX + width < mapWidth, "x coord bigger than map width - %s, id = %d", getName(psFeature->psStats->pName), psFeature->id); ASSERT_OR_RETURN(NULL, mapY + breadth < mapHeight, "y coord bigger than map height - %s, id = %d", getName(psFeature->psStats->pName), psFeature->id); if (width != psStats->baseWidth && breadth != psStats->baseBreadth) { if (TileHasFeature(psTile)) { FEATURE *psBlock = (FEATURE *)psTile->psObject; debug(LOG_ERROR, "%s(%d) already placed at (%d+%d, %d+%d) when trying to place %s(%d) at (%d+%d, %d+%d) - removing it", getName(psBlock->psStats->pName), psBlock->id, map_coord(psBlock->pos.x), psBlock->psStats->baseWidth, map_coord(psBlock->pos.y), psBlock->psStats->baseBreadth, getName(psFeature->psStats->pName), psFeature->id, mapX, psStats->baseWidth, mapY, psStats->baseBreadth); removeFeature(psBlock); } psTile->psObject = (BASE_OBJECT*)psFeature; // if it's a tall feature then flag it in the map. if (psFeature->sDisplay.imd->max.y > TALLOBJECT_YMAX) { auxSetBlocking(mapX + width, mapY + breadth, AIR_BLOCKED); } if (psStats->subType != FEAT_GEN_ARTE && psStats->subType != FEAT_OIL_DRUM && psStats->subType != FEAT_BUILD_WRECK) { auxSetBlocking(mapX + width, mapY + breadth, FEATURE_BLOCKED); } } if( (!psStats->tileDraw) && (FromSave == false) ) { psTile->height = height; } } } psFeature->pos.z = map_TileHeight(mapX,mapY);//jps 18july97 // // set up the imd for the feature // if(psFeature->psStats->subType==FEAT_BUILD_WRECK) // { // psFeature->sDisplay.imd = wreckageImds[rand()%MAX_WRECKAGE]; // } // else // { // psFeature->sDisplay.imd = psStats->psImd; // } return psFeature; }
static PIELIGHT appliedRadarColour(RADAR_DRAW_MODE radarDrawMode, MAPTILE *WTile) { PIELIGHT WScr = WZCOL_BLACK; // squelch warning // draw radar on/off feature if (!getRevealStatus() && !TEST_TILE_VISIBLE(selectedPlayer, WTile)) { return WZCOL_RADAR_BACKGROUND; } switch (radarDrawMode) { case RADAR_MODE_TERRAIN: { // draw radar terrain on/off feature PIELIGHT col = tileColours[TileNumber_tile(WTile->texture)]; col.byte.r = sqrtf(col.byte.r * WTile->illumination); col.byte.b = sqrtf(col.byte.b * WTile->illumination); col.byte.g = sqrtf(col.byte.g * WTile->illumination); if (terrainType(WTile) == TER_CLIFFFACE) { col.byte.r /= 2; col.byte.g /= 2; col.byte.b /= 2; } if (!hasSensorOnTile(WTile, selectedPlayer)) { col.byte.r = col.byte.r * 2 / 3; col.byte.g = col.byte.g * 2 / 3; col.byte.b = col.byte.b * 2 / 3; } if (!TEST_TILE_VISIBLE(selectedPlayer, WTile)) { col.byte.r /= 2; col.byte.g /= 2; col.byte.b /= 2; } WScr = col; } break; case RADAR_MODE_COMBINED: { // draw radar terrain on/off feature PIELIGHT col = tileColours[TileNumber_tile(WTile->texture)]; col.byte.r = sqrtf(col.byte.r * (WTile->illumination + WTile->height / ELEVATION_SCALE) / 2); col.byte.b = sqrtf(col.byte.b * (WTile->illumination + WTile->height / ELEVATION_SCALE) / 2); col.byte.g = sqrtf(col.byte.g * (WTile->illumination + WTile->height / ELEVATION_SCALE) / 2); if (terrainType(WTile) == TER_CLIFFFACE) { col.byte.r /= 2; col.byte.g /= 2; col.byte.b /= 2; } if (!hasSensorOnTile(WTile, selectedPlayer)) { col.byte.r = col.byte.r * 2 / 3; col.byte.g = col.byte.g * 2 / 3; col.byte.b = col.byte.b * 2 / 3; } if (!TEST_TILE_VISIBLE(selectedPlayer, WTile)) { col.byte.r /= 2; col.byte.g /= 2; col.byte.b /= 2; } WScr = col; } break; case RADAR_MODE_HEIGHT_MAP: { WScr.byte.r = WScr.byte.g = WScr.byte.b = WTile->height / ELEVATION_SCALE; } break; case RADAR_MODE_NO_TERRAIN: { WScr = WZCOL_RADAR_BACKGROUND; } break; case NUM_RADAR_MODES: { assert(false); } break; } return WScr; }