/** * Test if a given TileArea is valid. * @return \c true if the area is non-empty and fits inside the map, \c false otherwise. */ static CommandCost ValParamCopyPasteArea(const GenericTileArea &ta) { if (!IsValidTile(ta.tile) || !IsInsideBS(ta.w, 1, _settings_game.construction.clipboard_capacity) || !IsInsideBS(ta.h, 1, _settings_game.construction.clipboard_capacity)) { return CMD_ERROR; } if (TileX(ta.tile) + ta.w > MapMaxX(MapOf(ta.tile)) || TileY(ta.tile) + ta.h > MapMaxY(MapOf(ta.tile))) { return_cmd_error(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB); } return CommandCost(); }
virtual void OnClick(Point pt, int widget, int click_count) { if (widget >= WID_TT_BEGIN && widget < WID_TT_END) { if (_ctrl_pressed) { /* toggle the bit of the transparencies lock variable */ ToggleTransparencyLock((TransparencyOption)(widget - WID_TT_BEGIN)); this->SetDirty(); } else { /* toggle the bit of the transparencies variable and play a sound */ ToggleTransparency((TransparencyOption)(widget - WID_TT_BEGIN)); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); MarkWholeScreenDirty(); } } else if (widget == WID_TT_BUTTONS) { uint i; for (i = WID_TT_BEGIN; i < WID_TT_END; i++) { const NWidgetBase *nwid = this->GetWidget<NWidgetBase>(i); if (IsInsideBS(pt.x, nwid->pos_x, nwid->current_x)) { break; } } if (i == WID_TT_LOADING || i == WID_TT_END) return; ToggleInvisibility((TransparencyOption)(i - WID_TT_BEGIN)); if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP); /* Redraw whole screen only if transparency is set */ if (IsTransparencySet((TransparencyOption)(i - WID_TT_BEGIN))) { MarkWholeScreenDirty(); } else { this->SetWidgetDirty(WID_TT_BUTTONS); } } }
bool BuildConfirmationWindowProcessViewportClick() { if (!BuildConfirmationWindow::shown) return false; Window *w = FindWindowById(WC_BUILD_CONFIRMATION, 0); if (w != NULL && IsInsideBS(_cursor.pos.x, w->left, w->width) && IsInsideBS(_cursor.pos.y, w->top, w->height)) { Point pt; pt.x = _cursor.pos.x - w->left; pt.y = _cursor.pos.y - w->top; w->OnClick(pt, WID_BC_OK, 1); return true; } HideBuildConfirmationWindow(); return false; }
void Blitter_32bppAnim::PaletteAnimate(uint start, uint count) { assert(!_screen_disable_anim); /* Never repaint the transparency pixel */ if (start == 0) { start++; count--; } const uint8 *anim = this->anim_buf; uint32 *dst = (uint32 *)_screen.dst_ptr; /* Let's walk the anim buffer and try to find the pixels */ for (int y = this->anim_buf_height; y != 0 ; y--) { for (int x = this->anim_buf_width; x != 0 ; x--) { uint colour = *anim; if (IsInsideBS(colour, start, count)) { /* Update this pixel */ *dst = LookupColourInPalette(colour); } dst++; anim++; } dst += _screen.pitch - this->anim_buf_width; } /* Make sure the backend redraws the whole screen */ _video_driver->MakeDirty(0, 0, _screen.width, _screen.height); }
/** * Perform all steps to upgrade from the old station buoys to the new version * that uses waypoints. This includes some old saveload mechanics. */ void MoveBuoysToWaypoints() { /* Buoy orders become waypoint orders */ OrderList *ol; FOR_ALL_ORDER_LISTS(ol) { if (ol->GetFirstSharedVehicle()->type != VEH_SHIP) continue; for (Order *o = ol->GetFirstOrder(); o != NULL; o = o->next) UpdateWaypointOrder(o); } Vehicle *v; FOR_ALL_VEHICLES(v) { if (v->type != VEH_SHIP) continue; UpdateWaypointOrder(&v->current_order); } /* Now make the stations waypoints */ Station *st; FOR_ALL_STATIONS(st) { if ((st->had_vehicle_of_type & HVOT_WAYPOINT) == 0) continue; StationID index = st->index; TileIndex xy = st->xy; Town *town = st->town; StringID string_id = st->string_id; char *name = st->name; Date build_date = st->build_date; /* Delete the station, so we can make it a real waypoint. */ delete st; Waypoint *wp = new (index) Waypoint(xy); wp->town = town; wp->string_id = STR_SV_STNAME_BUOY; wp->name = name; wp->delete_ctr = 0; // Just reset delete counter for once. wp->build_date = build_date; wp->owner = OWNER_NONE; if (IsInsideBS(string_id, STR_SV_STNAME_BUOY, 9)) wp->town_cn = string_id - STR_SV_STNAME_BUOY; if (IsBuoyTile(xy) && GetStationIndex(xy) == index) { wp->facilities |= FACIL_DOCK; } wp->rect.BeforeAddTile(xy, StationRect::ADD_FORCE); } }
void Blitter_32bppAnim::CopyFromBuffer(void *video, const void *src, int width, int height) { assert(!_screen_disable_anim); assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch); uint32 *dst = (uint32 *)video; uint32 *usrc = (uint32 *)src; uint8 *anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf; int count = (_use_palette == PAL_DOS) ? PALETTE_ANIM_SIZE_DOS : PALETTE_ANIM_SIZE_WIN; for (; height > 0; height--) { /* We need to keep those for palette animation. */ uint32 *dst_pal = dst; uint8 *anim_pal = anim_line; memcpy(dst, usrc, width * sizeof(uint32)); usrc += width; dst += _screen.pitch; /* Copy back the anim-buffer */ memcpy(anim_line, usrc, width * sizeof(uint8)); usrc = (uint32 *)((uint8 *)usrc + width); anim_line += this->anim_buf_width; /* Okay, it is *very* likely that the image we stored is using * the wrong palette animated colours. There are two things we * can do to fix this. The first is simply reviewing the whole * screen after we copied the buffer, i.e. run PaletteAnimate, * however that forces a full screen redraw which is expensive * for just the cursor. This just copies the implementation of * palette animation, much cheaper though slightly nastier. */ for (int i = 0; i < width; i++) { uint colour = *anim_pal; if (IsInsideBS(colour, PALETTE_ANIM_SIZE_START, count)) { /* Update this pixel */ *dst_pal = LookupColourInPalette(colour); } dst_pal++; anim_pal++; } } }
virtual void OnClick(Point pt, int widget, int click_count) { if (widget >= WID_NCL_TEXTFILE && widget < WID_NCL_TEXTFILE + TFT_END) { if (this->selected == NULL || this->selected->state != ContentInfo::ALREADY_HERE) return; ShowContentTextfileWindow((TextfileType)(widget - WID_NCL_TEXTFILE), this->selected); return; } switch (widget) { case WID_NCL_MATRIX: { uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NCL_MATRIX); if (id_v >= this->content.Length()) return; // click out of bounds this->selected = *this->content.Get(id_v); this->list_pos = id_v; const NWidgetBase *checkbox = this->GetWidget<NWidgetBase>(WID_NCL_CHECKBOX); if (click_count > 1 || IsInsideBS(pt.x, checkbox->pos_x, checkbox->current_x)) { _network_content_client.ToggleSelectedState(this->selected); this->content.ForceResort(); } this->InvalidateData(); break; } case WID_NCL_CHECKBOX: case WID_NCL_TYPE: case WID_NCL_NAME: if (this->content.SortType() == widget - WID_NCL_CHECKBOX) { this->content.ToggleSortOrder(); this->list_pos = this->content.Length() - this->list_pos - 1; } else { this->content.SetSortType(widget - WID_NCL_CHECKBOX); this->content.ForceResort(); this->SortContentList(); } this->ScrollToSelected(); this->InvalidateData(); break; case WID_NCL_SELECT_ALL: _network_content_client.SelectAll(); this->InvalidateData(); break; case WID_NCL_SELECT_UPDATE: _network_content_client.SelectUpgrade(); this->InvalidateData(); break; case WID_NCL_UNSELECT: _network_content_client.UnselectAll(); this->InvalidateData(); break; case WID_NCL_CANCEL: delete this; break; case WID_NCL_OPEN_URL: if (this->selected != NULL) { extern void OpenBrowser(const char *url); OpenBrowser(this->selected->url); } break; case WID_NCL_DOWNLOAD: if (BringWindowToFrontById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD) == NULL) new NetworkContentDownloadStatusWindow(); break; } }
/** * Perform all steps to upgrade from the old station buoys to the new version * that uses waypoints. This includes some old saveload mechanics. */ void MoveBuoysToWaypoints() { /* Buoy orders become waypoint orders */ OrderList *ol; FOR_ALL_ORDER_LISTS(ol) { VehicleType vt = ol->GetFirstSharedVehicle()->type; if (vt != VEH_SHIP && vt != VEH_TRAIN) continue; for (Order *o = ol->GetFirstOrder(); o != NULL; o = o->next) UpdateWaypointOrder(o); } Vehicle *v; FOR_ALL_VEHICLES(v) { VehicleType vt = v->type; if (vt != VEH_SHIP && vt != VEH_TRAIN) continue; UpdateWaypointOrder(&v->current_order); } /* Now make the stations waypoints */ Station *st; FOR_ALL_STATIONS(st) { if ((st->had_vehicle_of_type & HVOT_WAYPOINT) == 0) continue; StationID index = st->index; TileIndex xy = st->xy; Town *town = st->town; StringID string_id = st->string_id; char *name = st->name; st->name = NULL; Date build_date = st->build_date; /* TTDPatch could use "buoys with rail station" for rail waypoints */ bool train = st->train_station.tile != INVALID_TILE; TileArea train_st = st->train_station; /* Delete the station, so we can make it a real waypoint. */ delete st; /* Stations and waypoints are in the same pool, so if a station * is deleted there must be place for a Waypoint. */ assert(Waypoint::CanAllocateItem()); Waypoint *wp = new (index) Waypoint(xy); wp->town = town; wp->string_id = train ? STR_SV_STNAME_WAYPOINT : STR_SV_STNAME_BUOY; wp->name = name; wp->delete_ctr = 0; // Just reset delete counter for once. wp->build_date = build_date; wp->owner = train ? GetTileOwner(xy) : OWNER_NONE; if (IsInsideBS(string_id, STR_SV_STNAME_BUOY, 9)) wp->town_cn = string_id - STR_SV_STNAME_BUOY; if (train) { /* When we make a rail waypoint of the station, convert the map as well. */ TILE_AREA_LOOP(t, train_st) { if (!IsTileType(t, MP_STATION) || GetStationIndex(t) != index) continue; SB(_me[t].m6, 3, 3, STATION_WAYPOINT); wp->rect.BeforeAddTile(t, StationRect::ADD_FORCE); } wp->train_station = train_st; wp->facilities |= FACIL_TRAIN; } else if (IsBuoyTile(xy) && GetStationIndex(xy) == index) { wp->rect.BeforeAddTile(xy, StationRect::ADD_FORCE); wp->facilities |= FACIL_DOCK; } }
virtual void OnClick(Point pt, int widget, int click_count) { switch (widget) { case NCLWW_MATRIX: { uint32 id_v = (pt.y - this->GetWidget<NWidgetBase>(NCLWW_MATRIX)->pos_y) / this->resize.step_height; if (id_v >= this->vscroll.GetCapacity()) return; // click out of bounds id_v += this->vscroll.GetPosition(); if (id_v >= this->content.Length()) return; // click out of bounds this->selected = *this->content.Get(id_v); this->list_pos = id_v; const NWidgetBase *checkbox = this->GetWidget<NWidgetBase>(NCLWW_CHECKBOX); if (click_count > 1 || IsInsideBS(pt.x, checkbox->pos_x, checkbox->current_x)) { _network_content_client.ToggleSelectedState(this->selected); this->content.ForceResort(); } this->InvalidateData(); } break; case NCLWW_CHECKBOX: case NCLWW_TYPE: case NCLWW_NAME: if (this->content.SortType() == widget - NCLWW_CHECKBOX) { this->content.ToggleSortOrder(); this->list_pos = this->content.Length() - this->list_pos - 1; } else { this->content.SetSortType(widget - NCLWW_CHECKBOX); this->content.ForceResort(); this->SortContentList(); } this->ScrollToSelected(); this->InvalidateData(); break; case NCLWW_SELECT_ALL: _network_content_client.SelectAll(); this->InvalidateData(); break; case NCLWW_SELECT_UPDATE: _network_content_client.SelectUpgrade(); this->InvalidateData(); break; case NCLWW_UNSELECT: _network_content_client.UnselectAll(); this->InvalidateData(); break; case NCLWW_CANCEL: delete this; break; case NCLWW_DOWNLOAD: if (BringWindowToFrontById(WC_NETWORK_STATUS_WINDOW, 0) == NULL) new NetworkContentDownloadStatusWindow(); break; } }
/** * Plant a tree. * @param tile start tile of area-drag of tree plantation * @param flags type of operation * @param p1 tree type, TREE_INVALID means random. * @param p2 end tile of area-drag * @param text unused * @return the cost of this operation or an error */ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { StringID msg = INVALID_STRING_ID; CommandCost cost(EXPENSES_OTHER); const byte tree_to_plant = GB(p1, 0, 8); // We cannot use Extract as min and max are climate specific. if (p2 >= MapSize()) return CMD_ERROR; /* Check the tree type within the current climate */ if (tree_to_plant != TREE_INVALID && !IsInsideBS(tree_to_plant, _tree_base_by_landscape[_settings_game.game_creation.landscape], _tree_count_by_landscape[_settings_game.game_creation.landscape])) return CMD_ERROR; TileArea ta(tile, p2); TILE_AREA_LOOP(tile, ta) { switch (GetTileType(tile)) { case MP_TREES: /* no more space for trees? */ if (_game_mode != GM_EDITOR && GetTreeCount(tile) == 4) { msg = STR_ERROR_TREE_ALREADY_HERE; continue; } if (flags & DC_EXEC) { AddTreeCount(tile, 1); MarkTileDirtyByTile(tile); } /* 2x as expensive to add more trees to an existing tile */ cost.AddCost(_price[PR_BUILD_TREES] * 2); break; case MP_WATER: if (!IsCoast(tile) || IsSlopeWithOneCornerRaised(GetTileSlope(tile, NULL))) { msg = STR_ERROR_CAN_T_BUILD_ON_WATER; continue; } /* FALL THROUGH */ case MP_CLEAR: { if (IsBridgeAbove(tile)) { msg = STR_ERROR_SITE_UNSUITABLE; continue; } TreeType treetype = (TreeType)tree_to_plant; /* Be a bit picky about which trees go where. */ if (_settings_game.game_creation.landscape == LT_TROPIC && treetype != TREE_INVALID && ( /* No cacti outside the desert */ (treetype == TREE_CACTUS && GetTropicZone(tile) != TROPICZONE_DESERT) || /* No rain forest trees outside the rain forest, except in the editor mode where it makes those tiles rain forest tile */ (IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS) && GetTropicZone(tile) != TROPICZONE_RAINFOREST && _game_mode != GM_EDITOR) || /* And no subtropical trees in the desert/rain forest */ (IsInsideMM(treetype, TREE_SUB_TROPICAL, TREE_TOYLAND) && GetTropicZone(tile) != TROPICZONE_NORMAL))) { msg = STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE; continue; } if (IsTileType(tile, MP_CLEAR)) { /* Remove fields or rocks. Note that the ground will get barrened */ switch (GetRawClearGround(tile)) { case CLEAR_FIELDS: case CLEAR_ROCKS: { CommandCost ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; cost.AddCost(ret); break; } default: break; } } if (_game_mode != GM_EDITOR && Company::IsValidID(_current_company)) { Town *t = ClosestTownFromTile(tile, _settings_game.economy.dist_local_authority); if (t != NULL) ChangeTownRating(t, RATING_TREE_UP_STEP, RATING_TREE_MAXIMUM, flags); } if (flags & DC_EXEC) { if (treetype == TREE_INVALID) { treetype = GetRandomTreeType(tile, GB(Random(), 24, 8)); if (treetype == TREE_INVALID) treetype = TREE_CACTUS; } /* Plant full grown trees in scenario editor */ PlantTreesOnTile(tile, treetype, 0, _game_mode == GM_EDITOR ? 3 : 0); MarkTileDirtyByTile(tile); /* When planting rainforest-trees, set tropiczone to rainforest in editor. */ if (_game_mode == GM_EDITOR && IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS)) { SetTropicZone(tile, TROPICZONE_RAINFOREST); } } cost.AddCost(_price[PR_BUILD_TREES]); break; } default: msg = STR_ERROR_SITE_UNSUITABLE; break; } } if (cost.GetCost() == 0) { return_cmd_error(msg); } else { return cost; } }