void CUnitDrawProxy::Draw(const CViewport *vp) const { int x = this->IX + vp->Map2ViewportX(this->X); int y = this->IY + vp->Map2ViewportY(this->Y); /* FIXME: check if we have to push real type here?*/ if (state == 1 && cframe) { DrawConstructionShadow(*Type, cframe, frame, x, y); } else { if (IsAlive) { DrawShadow(*Type, frame, x, y); } } // // Show that the unit is selected // DrawSelectionAt(x, y); // // Adjust sprite for Harvesters. // CPlayerColorGraphic *sprite = Type->Sprite; if (Type->Harvester && this->CurrentResource) { ResourceInfo *resinfo = Type->ResInfo[this->CurrentResource]; if (this->ResourcesHeld) { if (resinfo->SpriteWhenLoaded) { sprite = resinfo->SpriteWhenLoaded; } } else { if (resinfo->SpriteWhenEmpty) { sprite = resinfo->SpriteWhenEmpty; } } } // // Now draw! // Buildings under construction/upgrade/ready. // if (state == 1) { if (cframe) { DrawConstruction(Player->Index, cframe, *Type, frame, x + (Type->TileWidth * TileSizeX) / 2, y + (Type->TileHeight * TileSizeY) / 2); } // // Draw the future unit type, if upgrading to it. // } else if (state == 2) { // FIXME: this frame is hardcoded!!! DrawUnitType(*Type, sprite, Player->Index, frame < 0 ? /*-1*/ - 1 : 1, x, y); } else { DrawUnitType(*Type, sprite, Player->Index, frame, x, y); } // Unit's extras not fully supported.. need to be decorations themselves. // FIXME: johns: ugly check here, should be removed! if (IsAlive /*unit->IsVisible(ThisPlayer)*/) { DrawDecorationAt(x, y); } //DrawInformations(this, type, x, y); }
/** ** Draw unit on map. ** ** @param unit Pointer to the unit. */ local void DrawUnit(Unit* unit) { int x; int y; int r; UnitType* type; UnitStats* stats; type=unit->Type; x=Map2ScreenX(unit->X)+unit->IX; y=Map2ScreenY(unit->Y)+unit->IY; if( type->UnitType==UnitTypeFly ) { DrawShadow(unit,type,x,y); } DrawSelectionRectangle(unit,type,x,y); PlayerPixels(unit->Player); DrawUnitType(type,unit->Frame,x,y); stats=unit->Stats; // // For debug draw sight, react and attack range! // if( NumSelected==1 && unit->Selected ) { if( ShowSightRange ) { DrawRectangle(ColorGreen ,x+TileSizeX/2-stats->SightRange*TileSizeX ,y+TileSizeY/2-stats->SightRange*TileSizeY ,stats->SightRange*TileSizeX*2 ,stats->SightRange*TileSizeY*2); } if( type->CanAttack ) { if( ShowReactRange ) { r= (unit->Player->Type==PlayerHuman) ? type->ReactRangeHuman : type->ReactRangeComputer; if( r ) { DrawRectangle(ColorBlue ,x+TileSizeX/2-r*TileSizeX ,y+TileSizeY/2-r*TileSizeY ,r*TileSizeX*2 ,r*TileSizeY*2); } } if( ShowAttackRange && stats->AttackRange ) { DrawRectangle(ColorRed ,x+TileSizeX/2-stats->AttackRange*TileSizeX ,y+TileSizeY/2-stats->AttackRange*TileSizeY ,stats->AttackRange*TileSizeX*2 ,stats->AttackRange*TileSizeY*2); } } } // // For debug draw destination. FIXME: should become orders // if( ShowOrders && unit->Selected && (KeyModifiers&ModifierShift)) { DrawPath(unit); } // FIXME: johns: ugly check here should be removed! if( unit->Command.Action!=UnitActionDie ) { DrawDecoration(unit,type,x,y); } }
/** ** Draw unit on map. */ void CUnit::Draw(const CViewport *vp) const { int x; int y; int frame; int state; int constructed; CPlayerColorGraphic *sprite; ResourceInfo *resinfo; CConstructionFrame *cframe; CUnitType *type; /* * Since we can draw in parallel to game logic units may be already destroyed * or removed (this->Container != NULL) most dangerus is destroyed state * but due existence of UnitCashe, unit memory is always valid only we need check * Destroyed flag... the hack is that this->Type == NULL but 'or' logic * should secure this scenario and retir before this->Type->Revealer check */ if (this->Destroyed || this->Container || this->Type->Revealer) { // Revealers are not drawn return; } bool IsVisible = this->IsVisible(ThisPlayer); // Those should have been filtered. Check doesn't make sense with ReplayRevealMap Assert(ReplayRevealMap || this->Type->VisibleUnderFog || IsVisible); int player = this->RescuedFrom ? this->RescuedFrom->Index : this->Player->Index; int action = this->CurrentAction(); if (ReplayRevealMap || IsVisible) { type = this->Type; frame = this->Frame; y = this->IY; x = this->IX; x += vp->Map2ViewportX(this->tilePos.x); y += vp->Map2ViewportY(this->tilePos.y); state = (action == UnitActionBuilt) | ((action == UnitActionUpgradeTo) << 1); constructed = this->Constructed; // Reset Type to the type being upgraded to if (state == 2) { type = this->CurrentOrder()->Arg1.Type; } // This is trash unless the unit is being built, and that's when we use it. cframe = this->Data.Built.Frame; } else { y = this->Seen.IY; x = this->Seen.IX; x += vp->Map2ViewportX(this->Seen.X); y += vp->Map2ViewportY(this->Seen.Y); frame = this->Seen.Frame; type = this->Seen.Type; constructed = this->Seen.Constructed; state = this->Seen.State; cframe = this->Seen.CFrame; } #ifdef DYNAMIC_LOAD if (!type->Sprite) { LoadUnitTypeSprite(*type); } #endif if (!IsVisible && frame == UnitNotSeen) { DebugPrint("FIXME: Something is wrong, unit %d not seen but drawn time %lu?.\n" _C_ this->Slot _C_ GameCycle); return; } if (state == 1 && constructed) { DrawConstructionShadow(*type, cframe, frame, x, y); } else { if (action != UnitActionDie) { DrawShadow(*type, frame, x, y); } } // // Show that the unit is selected // DrawUnitSelection(vp, *this); // // Adjust sprite for Harvesters. // sprite = type->Sprite; if (type->Harvester && this->CurrentResource) { resinfo = type->ResInfo[this->CurrentResource]; if (this->ResourcesHeld) { if (resinfo->SpriteWhenLoaded) { sprite = resinfo->SpriteWhenLoaded; } } else { if (resinfo->SpriteWhenEmpty) { sprite = resinfo->SpriteWhenEmpty; } } } // // Now draw! // Buildings under construction/upgrade/ready. // if (state == 1) { if (constructed) { DrawConstruction(player, cframe, *type, frame, x + (type->TileWidth * TileSizeX) / 2, y + (type->TileHeight * TileSizeY) / 2); } // // Draw the future unit type, if upgrading to it. // } else if (state == 2) { // FIXME: this frame is hardcoded!!! DrawUnitType(*type, sprite, player, frame < 0 ? /*-1*/ - 1 : 1, x, y); } else { DrawUnitType(*type, sprite, player, frame, x, y); } // Unit's extras not fully supported.. need to be decorations themselves. DrawInformations(*this, type, x, y); }
/** ** Draw building on map. ** ** @param unit Pointer to the building */ local void DrawBuilding(Unit* unit) { int x; int y; UnitType* type; int frame; int n_frame; // FIXME: This should I rewrite, without checks here!! type=unit->Type; x = unit->X; y = unit->Y; // FIXME: johns: this isn't 100% correct, building which are partly // FIXME: johns: under the fog are shown partly. // FIXME: There is already a check in the main loop UnitVisibile! if ( !MAPEXPLORED( x, y ) ) { return; } if ( !TheMap.NoFogOfWar && !MAPVISIBLE( x, y ) ) { frame = unit->SeenFrame; if (frame == 255) { return; } } else { frame = unit->SeenFrame = unit->Frame; } #if 0 if( type->Type==UnitOilPlatformHuman || type->Type==UnitOilPlatformOrc ) { DebugLevel0("%d -> %d\n",unit->Frame,frame); } #endif n_frame = 0; if ((frame & 128) == 0 && unit->Rs > 50) { n_frame = 128; // fancy buildings } PlayerPixels(unit->Player); x=Map2ScreenX(unit->X)+unit->IX; y=Map2ScreenY(unit->Y)+unit->IY; // // Buildings under construction/upgrade/ready. // if( unit->Command.Action==UnitActionBuilded ) { if( unit->Constructed || type->RleSprite->NumFrames<=1 ) { DrawConstruction(type->OverlapFrame ,frame ,x+(type->TileWidth*TileSizeX)/2 ,y+(type->TileHeight*TileSizeY)/2); } else { #if 0 DebugLevel0("Remove this %d\n",n_frame); if ( strcmp(type->Ident,"dark-portal") == 0 || strcmp(type->Ident,"runestone") == 0 ) //FIXME: dark-portal and runestone haven't reqiured frames, so we draw construction instead DrawConstruction(type->OverlapFrame ,frame ,x+(type->TileWidth*TileSizeX)/2 ,y+(type->TileHeight*TileSizeY)/2); else #endif DrawUnitType(type,frame+n_frame,x,y); } } else if( unit->Command.Action==UnitActionUpgradeTo ) { DrawUnitType(unit->Command.Data.UpgradeTo.What,1+n_frame,x,y); } else { DrawUnitType(type,frame+n_frame,x,y); } // FIXME: johns: ugly check here should be removed! if( unit->Command.Action!=UnitActionDie ) { DrawDecoration(unit,type,x,y); DrawSelectionRectangle(unit,type,x,y); } }
/** ** 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; } } } }
/** ** Draw unit on map. */ void CUnit::Draw(const CViewport &vp) const { int frame; int state; int constructed; const CConstructionFrame *cframe; const CUnitType *type; if (this->Destroyed || this->Container || this->Type->Revealer) { // Revealers are not drawn return; } bool IsVisible = this->IsVisible(*ThisPlayer); // Those should have been filtered. Check doesn't make sense with ReplayRevealMap Assert(ReplayRevealMap || this->Type->VisibleUnderFog || IsVisible); int player = this->RescuedFrom ? this->RescuedFrom->Index : this->Player->Index; int action = this->CurrentAction(); PixelPos screenPos; if (ReplayRevealMap || IsVisible) { screenPos = vp.MapToScreenPixelPos(this->GetMapPixelPosTopLeft()); type = this->Type; frame = this->Frame; state = (action == UnitActionBuilt) | ((action == UnitActionUpgradeTo) << 1); constructed = this->Constructed; // Reset Type to the type being upgraded to if (action == UnitActionUpgradeTo) { const COrder_UpgradeTo &order = *static_cast<COrder_UpgradeTo *>(this->CurrentOrder()); type = &order.GetUnitType(); } if (this->CurrentAction() == UnitActionBuilt) { COrder_Built &order = *static_cast<COrder_Built *>(this->CurrentOrder()); cframe = &order.GetFrame(); } else { cframe = NULL; } } else { screenPos = vp.TilePosToScreen_TopLeft(this->Seen.tilePos); screenPos.x += this->Seen.IX; screenPos.y += this->Seen.IY; frame = this->Seen.Frame; type = this->Seen.Type; constructed = this->Seen.Constructed; state = this->Seen.State; cframe = this->Seen.CFrame; } #ifdef DYNAMIC_LOAD if (!type->Sprite) { LoadUnitTypeSprite(type); } #endif if (!IsVisible && frame == UnitNotSeen) { DebugPrint("FIXME: Something is wrong, unit %d not seen but drawn time %lu?.\n" _C_ UnitNumber(*this) _C_ GameCycle); return; } if (state == 1 && constructed && cframe) { DrawConstructionShadow(*type, cframe, frame, screenPos); } else { if (action != UnitActionDie) { DrawShadow(*type, frame, screenPos); } } // // Show that the unit is selected // DrawUnitSelection(vp, *this); // // Adjust sprite for Harvesters. // CPlayerColorGraphic *sprite = type->Sprite; if (type->Harvester && this->CurrentResource) { ResourceInfo *resinfo = type->ResInfo[this->CurrentResource]; if (this->ResourcesHeld) { if (resinfo->SpriteWhenLoaded) { sprite = resinfo->SpriteWhenLoaded; } } else { if (resinfo->SpriteWhenEmpty) { sprite = resinfo->SpriteWhenEmpty; } } } // // Now draw! // Buildings under construction/upgrade/ready. // if (state == 1) { if (constructed && cframe) { const PixelPos pos(screenPos + (type->GetPixelSize()) / 2); DrawConstruction(GameSettings.Presets[player].PlayerColor, cframe, *type, frame, pos); } else { DrawUnitType(*type, sprite, GameSettings.Presets[player].PlayerColor, frame, screenPos); } // // Draw the future unit type, if upgrading to it. // } else { DrawUnitType(*type, sprite, GameSettings.Presets[player].PlayerColor, frame, screenPos); } // Unit's extras not fully supported.. need to be decorations themselves. DrawInformations(*this, *type, screenPos); }
/** ** Draw unit on map. */ void CUnit::Draw() const { int x; int y; int frame; int state; int constructed; CPlayerColorGraphic *sprite; ResourceInfo *resinfo; CConstructionFrame *cframe; CUnitType *type; if (this->Type->Revealer) { // Revealers are not drawn return; } // Those should have been filtered. Check doesn't make sense with ReplayRevealMap Assert(ReplayRevealMap || this->Type->VisibleUnderFog || this->IsVisible(ThisPlayer)); if (ReplayRevealMap || this->IsVisible(ThisPlayer)) { type = this->Type; frame = this->Frame; y = this->IY; x = this->IX; x += CurrentViewport->Map2ViewportX(this->X); y += CurrentViewport->Map2ViewportY(this->Y); state = (this->Orders[0]->Action == UnitActionBuilt) | ((this->Orders[0]->Action == UnitActionUpgradeTo) << 1); constructed = this->Constructed; // Reset Type to the type being upgraded to if (state == 2) { type = this->Orders[0]->Type; } // This is trash unless the unit is being built, and that's when we use it. cframe = this->Data.Built.Frame; } else { y = this->Seen.IY; x = this->Seen.IX; x += CurrentViewport->Map2ViewportX(this->Seen.X); y += CurrentViewport->Map2ViewportY(this->Seen.Y); frame = this->Seen.Frame; type = this->Seen.Type; constructed = this->Seen.Constructed; state = this->Seen.State; cframe = this->Seen.CFrame; } #ifdef DYNAMIC_LOAD if (!type->Sprite) { LoadUnitTypeSprite(type); } #endif if (!this->IsVisible(ThisPlayer) && frame == UnitNotSeen) { DebugPrint("FIXME: Something is wrong, unit %d not seen but drawn time %lu?.\n" _C_ this->Slot _C_ GameCycle); return; } if (state == 1 && constructed) { DrawConstructionShadow(this, cframe, frame, x, y); } else { DrawShadow(this, NULL, frame, x, y); } // // Show that the unit is selected // DrawUnitSelection(this); // // Adjust sprite for Harvesters. // sprite = type->Sprite; if (type->Harvester && this->CurrentResource) { resinfo = type->ResInfo[this->CurrentResource]; if (this->ResourcesHeld) { if (resinfo->SpriteWhenLoaded) { sprite = resinfo->SpriteWhenLoaded; } } else { if (resinfo->SpriteWhenEmpty) { sprite = resinfo->SpriteWhenEmpty; } } } // // Now draw! // Buildings under construction/upgrade/ready. // if (state == 1) { if (constructed) { DrawConstruction(this, cframe, type, frame, x + (type->TileWidth * TileSizeX) / 2, y + (type->TileHeight * TileSizeY) / 2); } // // Draw the future unit type, if upgrading to it. // } else if (state == 2) { // FIXME: this frame is hardcoded!!! DrawUnitType(type, sprite, this->RescuedFrom ? this->RescuedFrom->Index : this->Player->Index, frame < 0 ? -1 - 1 : 1, x, y); } else { DrawUnitType(type, sprite, this->RescuedFrom ? this->RescuedFrom->Index : this->Player->Index, frame, x, y); } // Unit's extras not fully supported.. need to be decorations themselves. DrawInformations(this, type, x, y); }