#include "../server/exe_headers.h" #include "cm_local.h" #include "cm_patch.h" #include "cm_landscape.h" #include "../game/genericparser2.h" //#include "image.h" //#include "../qcommon/q_imath.h" #include "cm_terrainmap.h" #include "cm_draw.h" #include "../png/png.h" static CTerrainMap *TerrainMap = 0; void R_CreateAutomapImage( const char *name, const byte *pic, int width, int height, qboolean mipmap, qboolean allowPicmip, qboolean allowTC, int glWrapClampMode ); // simple function for getting a proper color for a side inline CPixel32 SideColor(int side) { CPixel32 col(255,255,255); switch (side) { default: break; case SIDE_BLUE: col = CPixel32(0,0,192); break; case SIDE_RED: col = CPixel32(192,0,0); break; } return col; } CTerrainMap::CTerrainMap(CCMLandScape *landscape) : mLandscape(landscape) { ApplyBackground(); ApplyHeightmap(); CDraw32 draw; draw.SetBuffer((CPixel32*) mImage); draw.SetBufferSize(TM_WIDTH,TM_HEIGHT,TM_WIDTH); // create version with paths and water shown int x,y; int water; int land; for (y=0; yGetBaseWaterHeight() - cp.a)*4, 0, 255); cp.a = 255; if (x > TM_BORDER && x < (TM_WIDTH-TM_BORDER) && y > TM_BORDER && y < (TM_WIDTH-TM_BORDER)) { cp = ALPHA_PIX (CPixel32(0,0,0), cp, land, 256-land); if (water > 0) cp = ALPHA_PIX (CPixel32(0,0,255), cp, water, 256-water); } draw.PutPix(x, y, cp); } // Load icons for symbols on map GLenum format; #ifdef _XBOX int mipcount; R_LoadImage("gfx/menus/rmg/start", (byte**)&mSymStart, &mSymStartWidth, &mSymStartHeight, &mipcount, &format); R_LoadImage("gfx/menus/rmg/end", (byte**)&mSymEnd, &mSymEndWidth, &mSymEndHeight, &mipcount, &format); R_LoadImage("gfx/menus/rmg/objective", (byte**)&mSymObjective, &mSymObjectiveWidth, &mSymObjectiveHeight, &mipcount, &format); R_LoadImage("gfx/menus/rmg/building", (byte**)&mSymBld, &mSymBldWidth, &mSymBldHeight, &mipcount, &format); #else R_LoadImage("gfx/menus/rmg/start", (byte**)&mSymStart, &mSymStartWidth, &mSymStartHeight, &format); R_LoadImage("gfx/menus/rmg/end", (byte**)&mSymEnd, &mSymEndWidth, &mSymEndHeight, &format); R_LoadImage("gfx/menus/rmg/objective", (byte**)&mSymObjective, &mSymObjectiveWidth, &mSymObjectiveHeight, &format); R_LoadImage("gfx/menus/rmg/building", (byte**)&mSymBld, &mSymBldWidth, &mSymBldHeight, &format); #endif } CTerrainMap::~CTerrainMap() { if (mSymStart) { Z_Free(mSymStart); mSymStart = NULL; } if (mSymEnd) { Z_Free(mSymEnd); mSymEnd = NULL; } if (mSymBld) { Z_Free(mSymBld); mSymBld = NULL; } if (mSymObjective) { Z_Free(mSymObjective); mSymObjective = NULL; } CDraw32::CleanUp(); } void CTerrainMap::ApplyBackground(void) { int x, y; byte *outPos; float xRel, yRel, xInc, yInc; byte *backgroundImage; int backgroundWidth, backgroundHeight, backgroundDepth; int pos; GLenum format; memset(mImage, 255, sizeof(mBufImage)); // R_LoadImage("textures\\kamchatka\\ice", &backgroundImage, &backgroundWidth, &backgroundHeight, &format);0 backgroundDepth = 4; #ifdef _XBOX int mipcount; R_LoadImage("gfx\\menus\\rmg\\01_bg", &backgroundImage, &backgroundWidth, &backgroundHeight, &mipcount, &format); #else R_LoadImage("gfx\\menus\\rmg\\01_bg", &backgroundImage, &backgroundWidth, &backgroundHeight, &format); #endif if (backgroundImage) { outPos = (byte *)mBufImage; xInc = (float)backgroundWidth / (float)TM_WIDTH; yInc = (float)backgroundHeight / (float)TM_HEIGHT; yRel = 0.0; for(y=0;yGetHeightMap(); int width = mLandscape->GetRealWidth(); int height = mLandscape->GetRealHeight(); byte *outPos; unsigned tempColor; float xRel, yRel, xInc, yInc; int count; outPos = (byte *)mBufImage; outPos += (((TM_BORDER * TM_WIDTH) + TM_BORDER) * 4); xInc = (float)width / (float)(TM_REAL_WIDTH); yInc = (float)height / (float)(TM_REAL_HEIGHT); // add in height map as alpha yRel = 0.0; for(y=0;y= 1.0) { tempColor += inPos[(((int)(yRel-0.5))*width) + ((int)xRel)]; count++; } if (yRel <= height-2) { tempColor += inPos[(((int)(yRel+0.5))*width) + ((int)xRel)]; count++; } if (xRel >= 1.0) { tempColor += inPos[(((int)(yRel))*width) + ((int)(xRel-0.5))]; count++; } if (xRel <= width-2) { tempColor += inPos[(((int)(yRel))*width) + ((int)(xRel+0.5))]; count++; } tempColor /= count; outPos[3] = tempColor; outPos += 4; // x is flipped! xRel -= xInc; } outPos += TM_BORDER * 4 * 2; yRel += yInc; } } // Convert position in game coords to automap coords void CTerrainMap::ConvertPos(int& x, int& y) { x = ((x - mLandscape->GetMins()[0]) / mLandscape->GetSize()[0]) * TM_REAL_WIDTH; y = ((y - mLandscape->GetMins()[1]) / mLandscape->GetSize()[1]) * TM_REAL_HEIGHT; // x is flipped! x = TM_REAL_WIDTH - x - 1; // border x += TM_BORDER; y += TM_BORDER; } void CTerrainMap::AddStart(int x, int y, int side) { ConvertPos(x, y); CDraw32 draw; draw.BlitColor(x-mSymStartWidth/2, y-mSymStartHeight/2, mSymStartWidth, mSymStartHeight, (CPixel32*)mSymStart, 0, 0, mSymStartWidth, SideColor(side)); } void CTerrainMap::AddEnd(int x, int y, int side) { ConvertPos(x, y); CDraw32 draw; draw.BlitColor(x-mSymEndWidth/2, y-mSymEndHeight/2, mSymEndWidth, mSymEndHeight, (CPixel32*)mSymEnd, 0, 0, mSymEndWidth, SideColor(side)); } void CTerrainMap::AddObjective(int x, int y, int side) { ConvertPos(x, y); CDraw32 draw; draw.BlitColor(x-mSymObjectiveWidth/2, y-mSymObjectiveHeight/2, mSymObjectiveWidth, mSymObjectiveHeight, (CPixel32*)mSymObjective, 0, 0, mSymObjectiveWidth, SideColor(side)); } void CTerrainMap::AddBuilding(int x, int y, int side) { ConvertPos(x, y); CDraw32 draw; draw.BlitColor(x-mSymBldWidth/2, y-mSymBldHeight/2, mSymBldWidth, mSymBldHeight, (CPixel32*)mSymBld, 0, 0, mSymBldWidth, SideColor(side)); } void CTerrainMap::AddNPC(int x, int y, bool friendly) { ConvertPos(x, y); CDraw32 draw; if (friendly) draw.DrawCircle(x,y,3, CPixel32(0,192,0), CPixel32(0,0,0,0)); else draw.DrawCircle(x,y,3, CPixel32(192,0,0), CPixel32(0,0,0,0)); } void CTerrainMap::AddNode(int x, int y) { ConvertPos(x, y); CDraw32 draw; draw.DrawCircle(x,y,20, CPixel32(255,255,255), CPixel32(0,0,0,0)); } void CTerrainMap::AddWallRect(int x, int y, int side) { ConvertPos(x, y); CDraw32 draw; switch (side) { default: draw.DrawBox(x-1,y-1,3,3,CPixel32(192,192,192,128)); break; case SIDE_BLUE: draw.DrawBox(x-1,y-1,3,3,CPixel32(0,0,192,128)); break; case SIDE_RED: draw.DrawBox(x-1,y-1,3,3,CPixel32(192,0,0,128)); break; } } void CTerrainMap::AddPlayer(vec3_t origin, vec3_t angles) { // draw player start on automap CDraw32 draw; vec3_t up; vec3_t pt[4] = {{0,0,0},{-5,-5,0},{10,0,0},{-5,5,0}}; vec3_t p; int x,y,i; float facing; POINT poly[4]; facing = angles[1]; up[0] = 0; up[1] = 0; up[2] = 1; x = (int)origin[0]; y = (int)origin[1]; ConvertPos(x, y); x++; y++; for (i=0; i<4; i++) { RotatePointAroundVector( p, up, pt[i], facing ); poly[i].x = (int)(-p[0] + x); poly[i].y = (int)(p[1] + y); } // draw arrowhead shadow draw.DrawPolygon(4, poly, CPixel32(0,0,0,128), CPixel32(0,0,0,128)); // draw arrowhead for (i=0; i<4; i++) { poly[i].x--; poly[i].y--; } draw.DrawPolygon(4, poly, CPixel32(255,255,255), CPixel32(255,255,255)); } void CTerrainMap::Upload(vec3_t player_origin, vec3_t player_angles) { CDraw32 draw; // copy completed map to mBufImage draw.SetBuffer((CPixel32*) mBufImage); draw.SetBufferSize(TM_WIDTH,TM_HEIGHT,TM_WIDTH); draw.Blit(0, 0, TM_WIDTH, TM_HEIGHT, (CPixel32*)mImage, 0, 0, TM_WIDTH); // now draw player's location on map if (player_origin) { AddPlayer(player_origin, player_angles); } draw.SetAlphaBuffer(255); R_CreateAutomapImage("*automap", (unsigned char *)draw.buffer, TM_WIDTH, TM_HEIGHT, qfalse, qfalse, qtrue, qfalse); draw.SetBuffer((CPixel32*) mImage); } void CTerrainMap::SaveImageToDisk(const char * terrainName, const char * missionName, const char * seed) { //ri.COM_SavePNG(va("save/%s_%s_%s.png", terrainName, missionName, seed), // (unsigned char *)mImage, TM_WIDTH, TM_HEIGHT, 4); //rww - Use JPG here? This function seems to be only for debugging anyway. // PNG_Save(va("save/%s_%s_%s.png", terrainName, missionName, seed), // (unsigned char *)mImage, TM_WIDTH, TM_HEIGHT, 4); } void CM_TM_Create(CCMLandScape *landscape) { if (TerrainMap) { CM_TM_Free(); } TerrainMap = new CTerrainMap(landscape); } void CM_TM_Free(void) { if (TerrainMap) { delete TerrainMap; TerrainMap = 0; } } void CM_TM_AddStart(int x, int y, int side) { if (TerrainMap) { TerrainMap->AddStart(x, y, side); } } void CM_TM_AddEnd(int x, int y, int side) { if (TerrainMap) { TerrainMap->AddEnd(x, y, side); } } void CM_TM_AddObjective(int x, int y, int side) { if (TerrainMap) { TerrainMap->AddObjective(x, y, side); } } void CM_TM_AddNPC(int x, int y, bool friendly) { if (TerrainMap) { TerrainMap->AddNPC(x, y, friendly); } } void CM_TM_AddNode(int x, int y) { if (TerrainMap) { TerrainMap->AddNode(x, y); } } void CM_TM_AddBuilding(int x, int y, int side) { if (TerrainMap) { TerrainMap->AddBuilding(x, y, side); } } void CM_TM_AddWallRect(int x, int y, int side) { if (TerrainMap) { TerrainMap->AddWallRect(x, y, side); } } void CM_TM_Upload(vec3_t player_origin, vec3_t player_angles) { if (TerrainMap) { TerrainMap->Upload(player_origin, player_angles); } } void CM_TM_SaveImageToDisk(const char * terrainName, const char * missionName, const char * seed) { if (TerrainMap) { // write out automap TerrainMap->SaveImageToDisk(terrainName, missionName, seed); } } void CM_TM_ConvertPosition(int &x, int &y, int Width, int Height) { if (TerrainMap) { TerrainMap->ConvertPos(x, y); x = x * Width / TM_WIDTH; y = y * Height / TM_HEIGHT; } }