316 lines
8.9 KiB
C
316 lines
8.9 KiB
C
/*
|
|
This file is part of Warzone 2100.
|
|
Copyright (C) 1999-2004 Eidos Interactive
|
|
Copyright (C) 2005-2007 Warzone Resurrection Project
|
|
|
|
Warzone 2100 is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Warzone 2100 is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Warzone 2100; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
#include "lib/framework/frame.h"
|
|
#include "map.h"
|
|
#include "hci.h"
|
|
#include "mapdisplay.h"
|
|
#include "display3d.h"
|
|
#include "lib/ivis_common/ivisdef.h" //ivis matrix code
|
|
#include "lib/ivis_common/piedef.h" //pie render
|
|
#include "lib/ivis_opengl/piematrix.h"
|
|
#include "lib/ivis_common/piepalette.h"
|
|
#include "miscimd.h"
|
|
#include "effects.h"
|
|
#include "bridge.h"
|
|
|
|
/**
|
|
* @file bridge.c
|
|
* Bridges - currently unused.
|
|
*
|
|
* Handles rendering and placement of bridging sections for
|
|
* traversing water and ravines?! My guess is this won't make it into
|
|
* the final game, but we'll see...
|
|
* Alex McLean, Pumpkin Studios EIDOS Interactive, 1998.
|
|
*
|
|
* He was right. It did not make the final game. The code below
|
|
* is unused. Can it be reused? - Per, 2007
|
|
*/
|
|
|
|
/*
|
|
Returns true or false as to whether a bridge is valid.
|
|
For it to be true - all intervening points must be lower than the start
|
|
and end points. We can also check other stuff here like what it's going
|
|
over. Also, it has to be between a minimum and maximum length and
|
|
one of the axes must share the same values.
|
|
*/
|
|
BOOL bridgeValid(UDWORD startX,UDWORD startY, UDWORD endX, UDWORD endY)
|
|
{
|
|
BOOL xBridge, yBridge;
|
|
UDWORD bridgeLength;
|
|
UDWORD startHeight,endHeight,sectionHeight;
|
|
UDWORD i;
|
|
|
|
/* Establish axes allignment */
|
|
xBridge = ( (startX == endX) ? true : false );
|
|
yBridge = ( (startY == endY) ? true : false );
|
|
|
|
/* At least one axis must be constant */
|
|
if (!xBridge && !yBridge)
|
|
{
|
|
/* Bridge isn't straight - this shouldn't have been passed
|
|
in, but better safe than sorry! */
|
|
return(false);
|
|
}
|
|
|
|
/* Get the bridge length */
|
|
bridgeLength = ( xBridge ? abs(startY-endY) : abs(startX-endX) );
|
|
|
|
/* check it's not too long or short */
|
|
if(bridgeLength<MINIMUM_BRIDGE_SPAN || bridgeLength>MAXIMUM_BRIDGE_SPAN)
|
|
{
|
|
/* Cry out */
|
|
return(false);
|
|
}
|
|
|
|
/* Check intervening tiles to see if they're lower
|
|
so first get the start and end heights */
|
|
startHeight = mapTile(startX,startY)->height;
|
|
endHeight = mapTile(endX,endY)->height;
|
|
|
|
/*
|
|
Don't whinge about this piece of code please! It's nice and short
|
|
and is called very infrequently. Could be made slightly faster.
|
|
*/
|
|
for(i = ( xBridge ? MIN(startY, endY) : MIN(startX, endX) );
|
|
i < ( xBridge ? MAX(startY, endY) : MAX(startX, endX) ); i++)
|
|
{
|
|
/* Get the height of a bridge section */
|
|
sectionHeight = mapTile((xBridge ? startX : startY),i)->height;
|
|
/* Is it higher than BOTH end points? */
|
|
if( sectionHeight > MAX(startHeight,endHeight) )
|
|
{
|
|
/* Cry out */
|
|
return(false);
|
|
}
|
|
}
|
|
/* Everything's just fine */
|
|
return(true);
|
|
}
|
|
|
|
|
|
/*
|
|
This function will actually draw a wall section
|
|
Slightly different from yer basic structure draw in that
|
|
it's not alligned to the terrain as bridge sections sit
|
|
at a height stored in their structure - as they're above the ground
|
|
and wouldn't be much use if they weren't, bridge wise.
|
|
*/
|
|
BOOL renderBridgeSection(STRUCTURE *psStructure)
|
|
{
|
|
SDWORD structX,structY,structZ;
|
|
SDWORD rx,rz;
|
|
//iIMDShape *imd;
|
|
Vector3i dv;
|
|
|
|
/* Bomb out if it's not visible and there's no active god mode */
|
|
if(!psStructure->visible[selectedPlayer] && !godMode)
|
|
{
|
|
return(false);
|
|
}
|
|
|
|
/* Get it's x and y coordinates so we don't have to deref. struct later */
|
|
structX = psStructure->pos.x;
|
|
structY = psStructure->pos.y;
|
|
structZ = psStructure->pos.z;
|
|
|
|
/* Establish where it is in the world */
|
|
dv.x = (structX - player.p.x) - terrainMidX*TILE_UNITS;
|
|
dv.z = terrainMidY*TILE_UNITS - (structY - player.p.z);
|
|
dv.y = structZ;
|
|
|
|
/* Push the indentity matrix */
|
|
pie_MatBegin();
|
|
|
|
/* Translate */
|
|
pie_TRANSLATE(dv.x,dv.y,dv.z);
|
|
|
|
/* Get the x,z translation components */
|
|
rx = map_round(player.p.x);
|
|
rz = map_round(player.p.z);
|
|
|
|
/* Translate */
|
|
pie_TRANSLATE(rx,0,-rz);
|
|
|
|
pie_Draw3DShape(psStructure->sDisplay.imd, 0, 0, WZCOL_WHITE, WZCOL_BLACK, 0, 0);
|
|
|
|
pie_MatEnd();
|
|
return(true);
|
|
}
|
|
|
|
/*
|
|
This will work out all the info you need about the bridge including
|
|
length - height to set sections at in order to allign to terrain and
|
|
what you need to alter start and end terrain heights by to establish to
|
|
connection.
|
|
*/
|
|
void getBridgeInfo(UDWORD startX,UDWORD startY,UDWORD endX, UDWORD endY, BRIDGE_INFO *info)
|
|
{
|
|
BOOL xBridge,yBridge;
|
|
UDWORD startHeight,endHeight;
|
|
BOOL startHigher;
|
|
|
|
/* Copy over the location coordinates */
|
|
info->startX = startX;
|
|
info->startY = startY;
|
|
info->endX = endX;
|
|
info->endY = endY;
|
|
|
|
/* Get the heights of the start and end positions */
|
|
startHeight = map_TileHeight(startX,startY);
|
|
endHeight = map_TileHeight(endX,endY);
|
|
|
|
/* Find out which is higher */
|
|
startHigher = (startHeight>=endHeight ? true : false);
|
|
|
|
/* If the start position is higher */
|
|
if(startHigher)
|
|
{
|
|
/* Inform structure */
|
|
info->startHighest = true;
|
|
|
|
/* And the end position needs raising */
|
|
info->heightChange = startHeight - endHeight;
|
|
}
|
|
/* Otherwise, the end position is lower */
|
|
else
|
|
{
|
|
/* Inform structure */
|
|
info->startHighest = false;
|
|
/* So we need to raise the start position */
|
|
info->heightChange = endHeight - startHeight;
|
|
}
|
|
|
|
/* Establish axes allignment */
|
|
/* Only one of these can occur otherwise
|
|
bridge is one square big */
|
|
xBridge = ( (startX == endX) ? true : false );
|
|
yBridge = ( (startY == endY) ? true : false );
|
|
|
|
/*
|
|
Set the bridge's height.
|
|
Note that when the bridge is built BOTH tile heights need
|
|
to be set to the agreed value on their bridge trailing edge
|
|
(x,y) and (x,y+1) is constant X and (x,y) and (x+1,y) if constant
|
|
Y
|
|
*/
|
|
if(startHigher)
|
|
{
|
|
info->bridgeHeight = map_TileHeight(startX,startY);
|
|
}
|
|
else
|
|
{
|
|
info->bridgeHeight = map_TileHeight(endX,endY);
|
|
}
|
|
|
|
/* We've got a bridge of constant X */
|
|
if(xBridge)
|
|
{
|
|
info->bConstantX = true;
|
|
info->bridgeLength = abs(startY-endY);
|
|
}
|
|
/* We've got a bridge of constant Y */
|
|
else if(yBridge)
|
|
{
|
|
info->bConstantX = false;
|
|
info->bridgeLength = abs(startX-endX);
|
|
}
|
|
else
|
|
{
|
|
debug( LOG_ERROR, "Weirdy Bridge requested - no axes allignment" );
|
|
abort();
|
|
}
|
|
}
|
|
|
|
void testBuildBridge(UDWORD startX, UDWORD startY, UDWORD endX, UDWORD endY)
|
|
{
|
|
BRIDGE_INFO bridge;
|
|
UDWORD i;
|
|
Vector3i dv;
|
|
|
|
if(bridgeValid(startX,startY,endX,endY))
|
|
{
|
|
getBridgeInfo(startX,startY,endX,endY,&bridge);
|
|
if(bridge.bConstantX)
|
|
{
|
|
|
|
for(i = MIN(bridge.startY, bridge.endY); i < (MAX(bridge.startY, bridge.endY) + 1); i++)
|
|
{
|
|
dv.x = ((bridge.startX*128)+64);
|
|
dv.z = ((i*128)+64);
|
|
dv.y = bridge.bridgeHeight;
|
|
addEffect(&dv,EFFECT_SMOKE,SMOKE_TYPE_DRIFTING,false,NULL,0);
|
|
// addExplosion(&dv,TYPE_EXPLOSION_SMOKE_CLOUD,NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i = MIN(bridge.startX, bridge.endX); i < (MAX(bridge.startX,bridge.endX) + 1); i++)
|
|
{
|
|
dv.x = ((i*128)+64);
|
|
dv.z = ((bridge.startY*128)+64);
|
|
dv.y = bridge.bridgeHeight;
|
|
addEffect(&dv,EFFECT_SMOKE,SMOKE_TYPE_DRIFTING,false,NULL,0);
|
|
// addExplosion(&dv,TYPE_EXPLOSION_SMOKE_CLOUD,NULL);
|
|
}
|
|
}
|
|
/* Flatten the start tile */
|
|
setTileHeight(bridge.startX,bridge.startY,bridge.bridgeHeight);
|
|
setTileHeight(bridge.startX,bridge.startY+1,bridge.bridgeHeight);
|
|
setTileHeight(bridge.startX+1,bridge.startY,bridge.bridgeHeight);
|
|
setTileHeight(bridge.startX+1,bridge.startY+1,bridge.bridgeHeight);
|
|
|
|
/* Flatten the end tile */
|
|
setTileHeight(bridge.endX,bridge.endY,bridge.bridgeHeight);
|
|
setTileHeight(bridge.endX,bridge.endY+1,bridge.bridgeHeight);
|
|
setTileHeight(bridge.endX+1,bridge.endY,bridge.bridgeHeight);
|
|
setTileHeight(bridge.endX+1,bridge.endY+1,bridge.bridgeHeight);
|
|
}
|
|
else
|
|
{
|
|
getBridgeInfo(startX,startY,endX,endY,&bridge);
|
|
if(bridge.bConstantX)
|
|
{
|
|
for(i = MIN(bridge.startY, bridge.endY); i < (MAX(bridge.startY, bridge.endY) + 1); i++)
|
|
{
|
|
dv.x = ((bridge.startX*128)+64);
|
|
dv.z = ((i*128)+64);
|
|
dv.y = bridge.bridgeHeight;
|
|
addEffect(&dv,EFFECT_EXPLOSION,EXPLOSION_TYPE_SMALL,false,NULL,0);
|
|
// addExplosion(&dv,TYPE_EXPLOSION_MED,NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i = MIN(bridge.startX,bridge.endX); i < (MAX(bridge.startX, bridge.endX) + 1); i++)
|
|
{
|
|
dv.x = ((i*128)+64);
|
|
dv.z = ((bridge.startY*128)+64);
|
|
dv.y = bridge.bridgeHeight;
|
|
addEffect(&dv,EFFECT_EXPLOSION,EXPLOSION_TYPE_SMALL,false,NULL,0);
|
|
// addExplosion(&dv,TYPE_EXPLOSION_MED,NULL);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|