Exemple #1
0
/// Is this position next to a water tile?
static bool isWater(int x, int y)
{
	bool result = false;
	result = result || (tileOnMap(x  , y) && terrainType(mapTile(x  , y)) == TER_WATER);
	result = result || (tileOnMap(x - 1, y) && terrainType(mapTile(x - 1, y)) == TER_WATER);
	result = result || (tileOnMap(x  , y - 1) && terrainType(mapTile(x  , y - 1)) == TER_WATER);
	result = result || (tileOnMap(x - 1, y - 1) && terrainType(mapTile(x - 1, y - 1)) == TER_WATER);
	return result;
}
Exemple #2
0
//By passing in params - it means that if the scroll limits are changed mid-mission
//we can re-do over the area that hasn't been seen
void initLighting(UDWORD x1, UDWORD y1, UDWORD x2, UDWORD y2)
{
	UDWORD       i, j;

	// quick check not trying to go off the map - don't need to check for < 0 since UWORD's!!
	if (x1 > mapWidth || x2 > mapWidth || y1 > mapHeight || y2 > mapHeight)
	{
		ASSERT( false, "initLighting: coords off edge of map" );
		return;
	}

	for (i = x1; i < x2; i++)
	{
		for(j = y1; j < y2; j++)
		{
			MAPTILE	*psTile = mapTile(i, j);

			// always make the edge tiles dark
			if (i==0 || j==0 || i >= mapWidth-1 || j >= mapHeight-1)
			{
				psTile->illumination = 16;

				// give water tiles at edge of map a border
				if (terrainType(psTile) == TER_WATER)
				{
					psTile->texture = 0;
				}
			}
			else
			{
				calcTileIllum(i,j);
			}
			// Basically darkens down the tiles that are outside the scroll
			// limits - thereby emphasising the cannot-go-there-ness of them
			if ((SDWORD)i < scrollMinX + 4 || (SDWORD)i > scrollMaxX - 4
			    || (SDWORD)j < scrollMinY + 4 || (SDWORD)j > scrollMaxY - 4)
			{
				psTile->illumination/=3;
			}
		}
	}
}
Exemple #3
0
/* Remove a Feature and free it's memory */
bool destroyFeature(FEATURE *psDel)
{
	UDWORD			widthScatter,breadthScatter,heightScatter, i;
	EFFECT_TYPE		explosionSize;
	Vector3i pos;
	UDWORD			width,breadth;
	UDWORD			mapX,mapY;

	ASSERT_OR_RETURN(false, psDel != NULL, "Invalid feature pointer");

 	/* Only add if visible and damageable*/
	if(psDel->visible[selectedPlayer] && psDel->psStats->damageable)
	{
		/* Set off a destruction effect */
		/* First Explosions */
		widthScatter = TILE_UNITS/2;
		breadthScatter = TILE_UNITS/2;
		heightScatter = TILE_UNITS/4;
		//set which explosion to use based on size of feature
		if (psDel->psStats->baseWidth < 2 && psDel->psStats->baseBreadth < 2)
		{
			explosionSize = EXPLOSION_TYPE_SMALL;
		}
		else if (psDel->psStats->baseWidth < 3 && psDel->psStats->baseBreadth < 3)
		{
			explosionSize = EXPLOSION_TYPE_MEDIUM;
		}
		else
		{
			explosionSize = EXPLOSION_TYPE_LARGE;
		}
		for(i=0; i<4; i++)
		{
			pos.x = psDel->pos.x + widthScatter - rand()%(2*widthScatter);
			pos.z = psDel->pos.y + breadthScatter - rand()%(2*breadthScatter);
			pos.y = psDel->pos.z + 32 + rand()%heightScatter;
			addEffect(&pos,EFFECT_EXPLOSION,explosionSize,false,NULL,0);
		}

		if(psDel->psStats->subType == FEAT_SKYSCRAPER)
		{
			pos.x = psDel->pos.x;
			pos.z = psDel->pos.y;
			pos.y = psDel->pos.z;
			addEffect(&pos,EFFECT_DESTRUCTION,DESTRUCTION_TYPE_SKYSCRAPER,true,psDel->sDisplay.imd,0);
			initPerimeterSmoke(psDel->sDisplay.imd, pos);

			shakeStart();
		}

		/* Then a sequence of effects */
		pos.x = psDel->pos.x;
		pos.z = psDel->pos.y;
		pos.y = map_Height(pos.x,pos.z);
		addEffect(&pos,EFFECT_DESTRUCTION,DESTRUCTION_TYPE_FEATURE,false,NULL,0);

		//play sound
		// ffs gj
		if(psDel->psStats->subType == FEAT_SKYSCRAPER)
		{
			audio_PlayStaticTrack( psDel->pos.x, psDel->pos.y, ID_SOUND_BUILDING_FALL );
		}
		else
		{
			audio_PlayStaticTrack( psDel->pos.x, psDel->pos.y, ID_SOUND_EXPLOSION );
		}
	}

	if (psDel->psStats->subType == FEAT_SKYSCRAPER)
	{
		// ----- Flip all the tiles under the skyscraper to a rubble tile
		// smoke effect should disguise this happening
		mapX = map_coord(psDel->pos.x) - psDel->psStats->baseWidth/2;
		mapY = map_coord(psDel->pos.y) - psDel->psStats->baseBreadth/2;
		for (width = 0; width < psDel->psStats->baseWidth; width++)
		{
			for (breadth = 0; breadth < psDel->psStats->baseBreadth; breadth++)
			{
				MAPTILE *psTile = mapTile(mapX+width,mapY+breadth);
				// stops water texture chnaging for underwateer festures
				if (terrainType(psTile) != TER_WATER)
				{
					if (terrainType(psTile) != TER_CLIFFFACE)
					{
						/* Clear feature bits */
						psTile->texture = TileNumber_texture(psTile->texture) | RUBBLE_TILE;
					}
					else
					{
						/* This remains a blocking tile */
						psTile->psObject = NULL;
						psTile->texture = TileNumber_texture(psTile->texture) | BLOCKING_RUBBLE_TILE;
					}
				}
			}
		}
	}

	removeFeature(psDel);
	return true;
}
Exemple #4
0
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;
}
Exemple #5
0
// not a direct script function but a helper for scrSkDefenseLocation and scrSkDefenseLocationB
static bool defenseLocation(bool variantB)
{
	SDWORD		*pX, *pY, statIndex, statIndex2;
	UDWORD		x, y, gX, gY, dist, player, nearestSoFar, count;
	GATEWAY		*psGate, *psChosenGate;
	DROID		*psDroid;
	UDWORD		x1, x2, x3, x4, y1, y2, y3, y4;
	bool		noWater;
	UDWORD      minCount;
	UDWORD      offset;

	if (!stackPopParams(6,
	        VAL_REF | VAL_INT, &pX,
	        VAL_REF | VAL_INT, &pY,
	        ST_STRUCTURESTAT, &statIndex,
	        ST_STRUCTURESTAT, &statIndex2,
	        ST_DROID, &psDroid,
	        VAL_INT, &player))
	{
		debug(LOG_ERROR, "defenseLocation: failed to pop");
		return false;
	}

	if (player >= MAX_PLAYERS)
	{
		ASSERT(false, "defenseLocation:player number is too high");
		return false;
	}

	ASSERT_OR_RETURN(false, statIndex < numStructureStats, "Invalid range referenced for numStructureStats, %d > %d", statIndex, numStructureStats);

	ASSERT_OR_RETURN(false, statIndex2 < numStructureStats, "Invalid range referenced for numStructureStats, %d > %d", statIndex2, numStructureStats);
	STRUCTURE_STATS *psWStats = (asStructureStats + statIndex2);

	// check for wacky coords.
	if (*pX < 0
	    ||	*pX > world_coord(mapWidth)
	    ||	*pY < 0
	    ||	*pY > world_coord(mapHeight)
	   )
	{
		goto failed;
	}

	x = map_coord(*pX);					// change to tile coords.
	y = map_coord(*pY);

	// go down the gateways, find the nearest gateway with >1 empty tiles
	nearestSoFar = UDWORD_MAX;
	psChosenGate = NULL;
	for (psGate = gwGetGateways(); psGate; psGate = psGate->psNext)
	{
		if (auxTile(psGate->x1, psGate->y1, player) & AUXBITS_THREAT)
		{
			continue;	// enemy can shoot there, not safe to build
		}
		count = 0;
		noWater = true;
		// does it have >1 tile unoccupied.
		if (psGate->x1 == psGate->x2)
		{
			// vert
			//skip gates that are too short
			if (variantB && (psGate->y2 - psGate->y1) <= 2)
			{
				continue;
			}
			gX = psGate->x1;
			for (gY = psGate->y1; gY <= psGate->y2; gY++)
			{
				if (! TileIsOccupied(mapTile(gX, gY)))
				{
					count++;
				}
				if (terrainType(mapTile(gX, gY)) == TER_WATER)
				{
					noWater = false;
				}
			}
		}
		else
		{
			// horiz
			//skip gates that are too short
			if (variantB && (psGate->x2 - psGate->x1) <= 2)
			{
				continue;
			}
			gY = psGate->y1;
			for (gX = psGate->x1; gX <= psGate->x2; gX++)
			{
				if (! TileIsOccupied(mapTile(gX, gY)))
				{
					count++;
				}
				if (terrainType(mapTile(gX, gY)) == TER_WATER)
				{
					noWater = false;
				}
			}
		}
		if (variantB)
		{
			minCount = 2;
		}
		else
		{
			minCount = 1;
		}
		if (count > minCount && noWater)	//<NEW> min 2 tiles
		{
			// ok it's free. Is it the nearest one yet?
			/* Get gateway midpoint */
			gX = (psGate->x1 + psGate->x2) / 2;
			gY = (psGate->y1 + psGate->y2) / 2;
			/* Estimate the distance to it */
			dist = iHypot(x - gX, y - gY);
			/* Is it best we've found? */
			if (dist < nearestSoFar && dist < 30)
			{
				/* Yes, then keep a record of it */
				nearestSoFar = dist;
				psChosenGate = psGate;
			}
		}
	}

	if (!psChosenGate)	// we have a gateway.
	{
		goto failed;
	}

	// find an unnocupied tile on that gateway.
	if (psChosenGate->x1 == psChosenGate->x2)
	{
		// vert
		gX = psChosenGate->x1;
		for (gY = psChosenGate->y1; gY <= psChosenGate->y2; gY++)
		{
			if (! TileIsOccupied(mapTile(gX, gY)))
			{
				y = gY;
				x = gX;
				break;
			}
		}
	}
	else
	{
		// horiz
		gY = psChosenGate->y1;
		for (gX = psChosenGate->x1; gX <= psChosenGate->x2; gX++)
		{
			if (! TileIsOccupied(mapTile(gX, gY)))
			{
				y = gY;
				x = gX;
				break;
			}
		}
	}

	// back to world coords and store result.
	*pX = world_coord(x) + (TILE_UNITS / 2);		// return centre of tile.
	*pY = world_coord(y) + (TILE_UNITS / 2);

	scrFunctionResult.v.bval = true;
	if (!stackPushResult(VAL_BOOL, &scrFunctionResult))		// success
	{
		return false;
	}


	// order the droid to build two walls, one either side of the gateway.
	// or one in the case of a 2 size gateway.

	//find center of the gateway
	x = (psChosenGate->x1 + psChosenGate->x2) / 2;
	y = (psChosenGate->y1 + psChosenGate->y2) / 2;

	//find start pos of the gateway
	x1 = world_coord(psChosenGate->x1) + (TILE_UNITS / 2);
	y1 = world_coord(psChosenGate->y1) + (TILE_UNITS / 2);

	if (variantB)
	{
		offset = 2;
	}
	else
	{
		offset = 1;
	}
	if (psChosenGate->x1 == psChosenGate->x2)	//vert
	{
		x2 = x1;	//vert: end x pos of the first section = start x pos
		y2 = world_coord(y - 1) + TILE_UNITS / 2;	//start y loc of the first sec
		x3 = x1;
		y3 = world_coord(y + offset) + TILE_UNITS / 2;
	}
	else		//hor
	{
		x2 = world_coord(x - 1) + TILE_UNITS / 2;
		y2 = y1;
		x3 = world_coord(x + offset) + TILE_UNITS / 2;
		y3 = y1;

	}
	//end coords of the second section
	x4 = world_coord(psChosenGate->x2) + TILE_UNITS / 2;
	y4 = world_coord(psChosenGate->y2) + TILE_UNITS / 2;

	// first section.
	if (x1 == x2 && y1 == y2)	//first sec is 1 tile only: ((2 tile gate) or (3 tile gate and first sec))
	{
		orderDroidStatsLocDir(psDroid, DORDER_BUILD, psWStats, x1, y1, 0, ModeQueue);
	}
	else
	{
		orderDroidStatsTwoLocDir(psDroid, DORDER_LINEBUILD, psWStats,  x1, y1, x2, y2, 0, ModeQueue);
	}

	// second section
	if (x3 == x4 && y3 == y4)
	{
		orderDroidStatsLocDirAdd(psDroid, DORDER_BUILD, psWStats, x3, y3, 0);
	}
	else
	{
		orderDroidStatsTwoLocDirAdd(psDroid, DORDER_LINEBUILD, psWStats,  x3, y3, x4, y4, 0);
	}

	return true;

failed:
	scrFunctionResult.v.bval = false;
	if (!stackPushResult(VAL_BOOL, &scrFunctionResult))		// failed!
	{
		return false;
	}
	return true;
}
Exemple #6
0
/* Moves one of the particles */
static void processParticle(ATPART *psPart)
{
	SDWORD	groundHeight;
	Vector3i pos;
	UDWORD	x, y;
	MAPTILE	*psTile;

	/* Only move if the game isn't paused */
	if (!gamePaused())
	{
		/* Move the particle - frame rate controlled */
		psPart->position.x += graphicsTimeAdjustedIncrement(psPart->velocity.x);
		psPart->position.y += graphicsTimeAdjustedIncrement(psPart->velocity.y);
		psPart->position.z += graphicsTimeAdjustedIncrement(psPart->velocity.z);

		/* Wrap it around if it's gone off grid... */
		testParticleWrap(psPart);

		/* If it's gone off the WORLD... */
		if (psPart->position.x < 0 || psPart->position.z < 0 ||
		    psPart->position.x > ((mapWidth - 1)*TILE_UNITS) ||
		    psPart->position.z > ((mapHeight - 1)*TILE_UNITS))
		{
			/* The kill it */
			psPart->status = APS_INACTIVE;
			return;
		}

		/* What height is the ground under it? Only do if low enough...*/
		if (psPart->position.y < 255 * ELEVATION_SCALE)
		{
			/* Get ground height */
			groundHeight = map_Height(psPart->position.x, psPart->position.z);

			/* Are we below ground? */
			if ((int)psPart->position.y < groundHeight
			    || psPart->position.y < 0.f)
			{
				/* Kill it and return */
				psPart->status = APS_INACTIVE;
				if (psPart->type == AP_RAIN)
				{
					x = map_coord(psPart->position.x);
					y = map_coord(psPart->position.z);
					psTile = mapTile(x, y);
					if (terrainType(psTile) == TER_WATER && TEST_TILE_VISIBLE(selectedPlayer, psTile))
					{
						pos.x = psPart->position.x;
						pos.z = psPart->position.z;
						pos.y = groundHeight;
						effectSetSize(60);
						addEffect(&pos, EFFECT_EXPLOSION, EXPLOSION_TYPE_SPECIFIED, true, getImdFromIndex(MI_SPLASH), 0);
					}
				}
				return;
			}
		}
		if (psPart->type == AP_SNOW)
		{
			if (rand() % 30 == 1)
			{
				psPart->velocity.z = (float)SNOW_SPEED_DRIFT;
			}
			if (rand() % 30 == 1)
			{
				psPart->velocity.x = (float)SNOW_SPEED_DRIFT;
			}
		}
	}
}
Exemple #7
0
int main(int argc, char **argv)
{
	char *filename, *p_filename;
	char *base, tmpFile[PATH_MAX];
	GAMEMAP *map;
	MAPTILE *psTile;

	if (argc != 2)
	{
		printf("Usage: %s <map>\n", argv[0]);
		return -1;
	}

	physfs_init(argv[0]);
	filename = physfs_addmappath(argv[1]);

	p_filename = strrchr(filename, '/');
	if (p_filename)
	{
		p_filename++;
		base = strdup(p_filename);
	}
	else
	{
		base = strdup(filename);
	}
	
	map = mapLoad(filename);
	free(filename);
	
	if (!map)
	{
		return EXIT_FAILURE;
	}

	const PreviewColors* tileColors = NULL;
	switch (map->tileset)
	{
	case TILESET_ARIZONA:
		tileColors = &pArizonaColors;
		break;
	case TILESET_URBAN:
		tileColors = &pUrbanColors;
		break;
	case TILESET_ROCKIES:
		tileColors = &pRockiesColors;
		break;
	default:
		fprintf(stderr, "Unknown tileset: %d\n", (int)map->tileset);
		mapFree(map);
		physfs_shutdown();
		return EXIT_FAILURE;
	}

	const int mapWidth = (int) map->width;
	const int mapHeight = (int) map->height;
	int col;

	// RGB888 pixels
	uint8_t *pixels = (uint8_t*) malloc(sizeof(uint8_t) * mapWidth * mapHeight * 3);

	for (int y = 0; y < mapHeight; y++)
	{
		for (int x = 0; x < mapWidth; x++)
		{
			// We're placing the origin at the top for aesthetic reasons
			psTile = mapTile(map, x, mapHeight-1-y);
			col = psTile->height / 2; // 2 = ELEVATION_SCALE
			uint8_t * const p = &pixels[(y * map->width + x) * 3];
			switch(terrainType(psTile))
			{
				case TER_CLIFFFACE:
					p[0] = tileColors->cliffLow.x + (tileColors->cliffHigh.x - tileColors->cliffLow.x) * col / 256;
					p[1] = tileColors->cliffLow.y + (tileColors->cliffHigh.y - tileColors->cliffLow.y) * col / 256;
					p[2] = tileColors->cliffLow.z + (tileColors->cliffHigh.z - tileColors->cliffLow.z) * col / 256;
				break;
				case TER_WATER:
					p[0] = tileColors->water.x;
					p[1] = tileColors->water.y;
					p[2] = tileColors->water.z;
				break;
				case TER_ROAD:
					p[0] = tileColors->roadLow.x + (tileColors->roadHigh.x - tileColors->roadLow.x) * col / 256;
					p[1] = tileColors->roadLow.y + (tileColors->roadHigh.y - tileColors->roadLow.y) * col / 256;
					p[2] = tileColors->roadLow.z + (tileColors->roadHigh.z - tileColors->roadLow.z) * col / 256;
				break;
				default:
					p[0] = tileColors->groundLow.x + (tileColors->groundHigh.x - tileColors->groundLow.x) * col / 256;
					p[1] = tileColors->groundLow.y + (tileColors->groundHigh.y - tileColors->groundLow.y) * col / 256;
					p[2] = tileColors->groundLow.z + (tileColors->groundHigh.z - tileColors->groundLow.z) * col / 256;
				break;
			}
		}
	}

	paintStructureData(pixels, map);

	strcpy(tmpFile, base);
	strcat(tmpFile, ".png");

	savePng(tmpFile, pixels, mapWidth, mapHeight);

	free(pixels);

	mapFree(map);

	physfs_shutdown();

	return 0;
}
Exemple #8
0
// multiple turrets display removed the pointless mountRotation
void displayComponentObject(DROID *psDroid)
{
	Vector3i	position, rotation;
	int32_t		xShift,zShift;
	SDWORD		frame;
	PROPULSION_STATS	*psPropStats;
	UDWORD	tileX,tileY;
	MAPTILE	*psTile;
	SPACETIME st = interpolateObjectSpacetime((SIMPLE_OBJECT *)psDroid, graphicsTime);

	psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION].nStat;

	leftFirst = angleDelta(player.r.y - st.rot.direction) <= 0;

	/* Push the matrix */
	pie_MatBegin();

	/* Get internal tile units coordinates */
	xShift = map_round(player.p.x);
	zShift = map_round(player.p.z);

	/* Mask out to tile_units resolution */
	pie_TRANSLATE(xShift,0,-zShift);

	/* Get the real position */
	position.x = (st.pos.x - player.p.x) - terrainMidX*TILE_UNITS;
	position.z = terrainMidY*TILE_UNITS - (st.pos.y - player.p.z);
	position.y = st.pos.z;

	if(psDroid->droidType == DROID_TRANSPORTER)
	{
		position.y += bobTransporterHeight();
	}

	/* Get all the pitch,roll,yaw info */
	rotation.y = -st.rot.direction;
	rotation.x = st.rot.pitch;
	rotation.z = st.rot.roll;

	/* Translate origin */
	pie_TRANSLATE(position.x,position.y,position.z);

	/* Rotate for droid */
	pie_MatRotY(rotation.y);
	pie_MatRotX(rotation.x);
	pie_MatRotZ(rotation.z);

	if( (gameTime-psDroid->timeLastHit < GAME_TICKS_PER_SEC) && psDroid->lastHitWeapon == WSC_ELECTRONIC)
	{
		objectShimmy( (BASE_OBJECT*) psDroid );
	}

	if (psDroid->lastHitWeapon == WSC_EMP &&
	    (gameTime - psDroid->timeLastHit < EMP_DISABLE_TIME))
	{
		Vector3i position;

		//add an effect on the droid
		position.x = st.pos.x + DROID_EMP_SPREAD;
		position.y = st.pos.z + rand()%8;
		position.z = st.pos.y + DROID_EMP_SPREAD;
		effectGiveAuxVar(90+rand()%20);
		addEffect(&position,EFFECT_EXPLOSION,EXPLOSION_TYPE_PLASMA,false,NULL,0);
	}

	if ((psDroid->visible[selectedPlayer] == UBYTE_MAX) || demoGetStatus())
	{
		//ingame not button object
		//should render 3 mounted weapons now
		displayCompObj(psDroid, false);
	}
	else
	{

		// make sure it's not over water.
		tileX = st.pos.x/TILE_UNITS;
		tileY = st.pos.y/TILE_UNITS;
		// double check it's on map
		if ( tileX < mapWidth && tileY < mapHeight )
		{
			psTile = mapTile(tileX,tileY);
			if (terrainType(psTile) != TER_WATER)
			{
				frame = gameTime/BLIP_ANIM_DURATION + psDroid->id; //visible[selectedPlayer];
				pie_Draw3DShape(getImdFromIndex(MI_BLIP), frame, 0, WZCOL_WHITE, WZCOL_BLACK, pie_ADDITIVE, psDroid->visible[selectedPlayer] / 2);
				/* set up all the screen coords stuff - need to REMOVE FROM THIS LOOP */
			}
		}
	}
	pie_MatEnd();
}
Exemple #9
0
/* Remove a Feature and free it's memory */
bool destroyFeature(FEATURE *psDel, unsigned impactTime)
{
	UDWORD			widthScatter, breadthScatter, heightScatter, i;
	EFFECT_TYPE		explosionSize;
	Vector3i pos;

	ASSERT_OR_RETURN(false, psDel != NULL, "Invalid feature pointer");
	ASSERT(gameTime - deltaGameTime < impactTime, "Expected %u < %u, gameTime = %u, bad impactTime", gameTime - deltaGameTime, impactTime, gameTime);

	/* Only add if visible and damageable*/
	if (psDel->visible[selectedPlayer] && psDel->psStats->damageable)
	{
		/* Set off a destruction effect */
		/* First Explosions */
		widthScatter = TILE_UNITS / 2;
		breadthScatter = TILE_UNITS / 2;
		heightScatter = TILE_UNITS / 4;
		//set which explosion to use based on size of feature
		if (psDel->psStats->baseWidth < 2 && psDel->psStats->baseBreadth < 2)
		{
			explosionSize = EXPLOSION_TYPE_SMALL;
		}
		else if (psDel->psStats->baseWidth < 3 && psDel->psStats->baseBreadth < 3)
		{
			explosionSize = EXPLOSION_TYPE_MEDIUM;
		}
		else
		{
			explosionSize = EXPLOSION_TYPE_LARGE;
		}
		for (i = 0; i < 4; i++)
		{
			pos.x = psDel->pos.x + widthScatter - rand() % (2 * widthScatter);
			pos.z = psDel->pos.y + breadthScatter - rand() % (2 * breadthScatter);
			pos.y = psDel->pos.z + 32 + rand() % heightScatter;
			addEffect(&pos, EFFECT_EXPLOSION, explosionSize, false, NULL, 0, impactTime);
		}

		if (psDel->psStats->subType == FEAT_SKYSCRAPER)
		{
			pos.x = psDel->pos.x;
			pos.z = psDel->pos.y;
			pos.y = psDel->pos.z;
			addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_SKYSCRAPER, true, psDel->sDisplay.imd, 0, impactTime);
			initPerimeterSmoke(psDel->sDisplay.imd, pos);

			shakeStart(250);	// small shake
		}

		/* Then a sequence of effects */
		pos.x = psDel->pos.x;
		pos.z = psDel->pos.y;
		pos.y = map_Height(pos.x, pos.z);
		addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_FEATURE, false, NULL, 0, impactTime);

		//play sound
		// ffs gj
		if (psDel->psStats->subType == FEAT_SKYSCRAPER)
		{
			audio_PlayStaticTrack(psDel->pos.x, psDel->pos.y, ID_SOUND_BUILDING_FALL);
		}
		else
		{
			audio_PlayStaticTrack(psDel->pos.x, psDel->pos.y, ID_SOUND_EXPLOSION);
		}
	}

	if (psDel->psStats->subType == FEAT_SKYSCRAPER)
	{
		// ----- Flip all the tiles under the skyscraper to a rubble tile
		// smoke effect should disguise this happening
		StructureBounds b = getStructureBounds(psDel);
		for (int breadth = 0; breadth < b.size.y; ++breadth)
		{
			for (int width = 0; width < b.size.x; ++width)
			{
				MAPTILE *psTile = mapTile(b.map.x + width, b.map.y + breadth);
				// stops water texture changing for underwater features
				if (terrainType(psTile) != TER_WATER)
				{
					if (terrainType(psTile) != TER_CLIFFFACE)
					{
						/* Clear feature bits */
						psTile->texture = TileNumber_texture(psTile->texture) | RUBBLE_TILE;
						auxClearBlocking(b.map.x + width, b.map.y + breadth, AUXBITS_ALL);
					}
					else
					{
						/* This remains a blocking tile */
						psTile->psObject = NULL;
						auxClearBlocking(b.map.x + width, b.map.y + breadth, AIR_BLOCKED);  // Shouldn't remain blocking for air units, however.
						psTile->texture = TileNumber_texture(psTile->texture) | BLOCKING_RUBBLE_TILE;
					}
				}
			}
		}
	}

	removeFeature(psDel);
	psDel->died = impactTime;
	return true;
}