/** ** Can build unit-type at this point. ** ** @param unit Worker that want to build the building or NULL. ** @param type Building unit-type. ** @param pos tile map position. ** @param real Really build, or just placement ** ** @return OnTop, parent unit, builder on true, NULL false. ** */ CUnit *CanBuildUnitType(const CUnit *unit, const CUnitType &type, const Vec2i &pos, int real) { // Terrain Flags don't matter if building on top of a unit. CUnit *ontop = CanBuildHere(unit, type, pos); if (ontop == NULL) { return NULL; } if (ontop != (CUnit *)1 && ontop != unit) { return ontop; } // Remove unit that is building! if (unit) { UnmarkUnitFieldFlags(*unit); } CPlayer *player = NULL; if (unit && unit->Player->Type == PlayerPerson) { player = unit->Player; } int testmask; unsigned int index = pos.y * Map.Info.MapWidth; for (int h = 0; h < type.TileHeight; ++h) { for (int w = type.TileWidth; w--;) { /* first part of if (!CanBuildOn(x + w, y + h, testmask)) */ if (!Map.Info.IsPointOnMap(pos.x + w, pos.y + h)) { h = type.TileHeight; ontop = NULL; break; } if (player && !real) { //testmask = MapFogFilterFlags(player, x + w, y + h, type.MovementMask); testmask = MapFogFilterFlags(*player, index + pos.x + w, type.MovementMask); } else { testmask = type.MovementMask; } /*secound part of if (!CanBuildOn(x + w, y + h, testmask)) */ const CMapField &mf = *Map.Field(index + pos.x + w); if (mf.CheckMask(testmask)) { h = type.TileHeight; ontop = NULL; break; } if (player && !mf.playerInfo.IsExplored(*player)) { h = type.TileHeight; ontop = NULL; break; } } index += Map.Info.MapWidth; } if (unit) { MarkUnitFieldFlags(*unit); } // We can build here: check distance to gold mine/oil patch! return ontop; }
/** ** Draw cursor for selecting building position. */ local void DrawBuildingCursor(void) { int x; int y; int x1; int y1; int mx; int my; int color; int f; int w; int w0; int h; int mask; x=((CursorX-MAP_X)/TileSizeX)*TileSizeX+MAP_X; // Align to grid y=((CursorY-MAP_Y)/TileSizeY)*TileSizeY+MAP_Y; mx=Screen2MapX(x); my=Screen2MapY(y); // // Draw building // PlayerPixels(ThisPlayer); SetClipping(MAP_X,MAP_Y,MAP_X+MapWidth*TileSizeX,MAP_Y+MapHeight*TileSizeY); DrawUnitType(CursorBuilding,0,x,y); // FIXME: This is dangerous here SetClipping(0,0,VideoWidth,VideoHeight); // // Draw the allow overlay // f=CanBuildHere(CursorBuilding,mx,my); // FIXME: Should be moved into unittype structure, and allow more types. if( CursorBuilding->ShoreBuilding ) { mask=MapFieldLandUnit | MapFieldSeaUnit | MapFieldBuilding // already occuppied | MapFieldWall | MapFieldRocks | MapFieldForest // wall,rock,forest not 100% clear? | MapFieldLandAllowed // can't build on this //| MapFieldUnpassable // FIXME: I think shouldn't be used | MapFieldNoBuilding; } else switch( CursorBuilding->UnitType ) { case UnitTypeLand: mask=MapFieldLandUnit | MapFieldBuilding // already occuppied | MapFieldWall | MapFieldRocks | MapFieldForest // wall,rock,forest not 100% clear? | MapFieldCoastAllowed | MapFieldWaterAllowed // can't build on this | MapFieldUnpassable // FIXME: I think shouldn't be used | MapFieldNoBuilding; break; case UnitTypeNaval: mask=MapFieldSeaUnit | MapFieldBuilding // already occuppied | MapFieldCoastAllowed | MapFieldLandAllowed // can't build on this | MapFieldUnpassable // FIXME: I think shouldn't be used | MapFieldNoBuilding; break; case UnitTypeFly: default: DebugLevel1(__FUNCTION__": Were moves this unit?\n"); return; } h=CursorBuilding->TileHeight; if( my+h>MapY+MapHeight ) { // reduce to view limits h=MapY+MapHeight-my; } w0=CursorBuilding->TileWidth; // reduce to view limits if( mx+w0>MapX+MapWidth ) { w0=MapX+MapWidth-mx; } while( h-- ) { w=w0; while( w-- ) { if( f && (CanBuildOn(mx+w,my+h,mask) || (Selected[0]->X==mx+w && Selected[0]->Y==my+h)) && (TheMap.Fields[mx+w+(my+h)*TheMap.Width].Flags &MapFieldExplored) ) { color=ColorGreen; } else { color=ColorRed; } // FIXME: Could do this faster+better for( y1=0; y1<TileSizeY; ++y1 ) { for( x1=y1&1; x1<TileSizeX; x1+=2 ) { DrawPointUnclipped(color ,x+w*TileSizeX+x1,y+h*TileSizeY+y1); } } } } }
/** ** Draw cursor for selecting building position. */ local void DrawBuildingCursor(void) { int x; int y; int x1; int y1; int mx; int my; int color; int f; int w; int w0; int h; int mask; const Viewport* vp; // Align to grid vp = TheUI.MouseViewport; x=CursorX-(CursorX - vp->X)%TileSizeX; y=CursorY-(CursorY - vp->Y)%TileSizeY; BuildingCursorSX = mx = Viewport2MapX(vp, x); BuildingCursorSY = my = Viewport2MapY(vp, y); // // Draw building // PushClipping(); SetClipping(vp->X, vp->Y, vp->EndX, vp->EndY); GraphicPlayerPixels(ThisPlayer,CursorBuilding->Sprite); if( VideoGraphicFrames(CursorBuilding->Sprite)>5 ) { DrawUnitType(CursorBuilding,4,x,y); } else { DrawUnitType(CursorBuilding,0,x,y); } PopClipping(); // // Draw the allow overlay // f=CanBuildHere(CursorBuilding,mx,my); mask = CursorBuilding->MovementMask; h=CursorBuilding->TileHeight; BuildingCursorEY=my+h-1; if (my+h > vp->MapY + vp->MapHeight) { // reduce to view limits h = vp->MapY + vp->MapHeight - my; } w0 = CursorBuilding->TileWidth; // reduce to view limits BuildingCursorEX=mx+w0-1; if (mx+w0 > vp->MapX + vp->MapWidth) { w0 = vp->MapX + vp->MapWidth - mx; } while( h-- ) { w=w0; while( w-- ) { int basex, basey; // FIXME: The field is covered by fog of war! if( f && CanBuildOn(mx+w,my+h,mask & ((Selected[0] && Selected[0]->X==mx+w && Selected[0]->Y==my+h) ? ~(MapFieldLandUnit|MapFieldSeaUnit) : -1)) && IsMapFieldExplored(ThisPlayer,mx+w,my+h) ) { color=ColorGreen; } else { color=ColorRed; } // FIXME: I could do this faster+better /* latimerius: I'm not sure what you have in mind but I can * at least move invariants out of the loops. */ basex = x + w*TileSizeX; basey = y + h*TileSizeY; for( y1=0; y1<TileSizeY; ++y1 ) { int j = basey+y1; for( x1=y1&1; x1<TileSizeX; x1+=2 ) { int i = basex+x1; if (i > vp->EndX) break; VideoDrawPixel (color, i, j); } if (j > vp->EndY) break; } } } }