diff --git a/Makefile.bundle.in b/Makefile.bundle.in index 63edb62d97..a04a0a31e7 100644 --- a/Makefile.bundle.in +++ b/Makefile.bundle.in @@ -45,6 +45,7 @@ bundle: all $(Q)mkdir -p "$(BUNDLE_DIR)/docs" $(Q)mkdir -p "$(BUNDLE_DIR)/media" $(Q)mkdir -p "$(BUNDLE_DIR)/scripts" + $(Q)mkdir -p "$(BUNDLE_DIR)/data" $(Q)mkdir -p "$(TTD_DIR)" $(Q)mkdir -p "$(AI_DIR)" $(Q)mkdir -p "$(GAME_DIR)" @@ -82,6 +83,7 @@ endif $(Q)cp "$(ROOT_DIR)/media/openttd.32.xpm" "$(BUNDLE_DIR)/media/" $(Q)cp "$(ROOT_DIR)/media/openttd."*.png "$(BUNDLE_DIR)/media/" $(Q)cp "$(BIN_DIR)/scripts/"* "$(BUNDLE_DIR)/scripts/" + $(Q)cp "$(BIN_DIR)/data/"*.grf "$(BUNDLE_DIR)/data/" ifdef MENU_DIR $(Q)cp "$(ROOT_DIR)/media/openttd.desktop" "$(BUNDLE_DIR)/media/" $(Q)$(AWK) -f "$(ROOT_DIR)/media/openttd.desktop.translation.awk" "$(SRC_DIR)/lang/"*.txt | $(SORT) | $(AWK) -f "$(ROOT_DIR)/media/openttd.desktop.filter.awk" >> "$(BUNDLE_DIR)/media/openttd.desktop" diff --git a/bin/data/tracerestrict.grf b/bin/data/tracerestrict.grf new file mode 100644 index 0000000000..b71ee80c17 Binary files /dev/null and b/bin/data/tracerestrict.grf differ diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 10bc0afa17..440cf5bb1a 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -170,6 +170,9 @@ static void LoadSpriteTables() _palette_remap_grf[i] = (PAL_DOS != used_set->palette); LoadGrfFile(used_set->files[GFT_BASE].filename, 0, i++); + /* Tracerestrict sprites. */ + LoadGrfFile("tracerestrict.grf", SPR_TRACERESTRICT_BASE, i++); + /* * The second basic file always starts at the given location and does * contain a different amount of sprites depending on the "type"; DOS diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index e1b956bad9..3b706c69ea 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1862,6 +1862,7 @@ static void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track trac SignalVariant variant = GetSignalVariant(tile, track); SpriteID sprite = GetCustomSignalSprite(rti, tile, type, variant, condition); + bool is_custom_sprite = (sprite != 0); if (sprite != 0) { sprite += image; } else { @@ -1870,7 +1871,19 @@ static void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track trac sprite += type * 16 + variant * 64 + image * 2 + condition + (type > SIGTYPE_LAST_NOPBS ? 64 : 0); } - AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track)); + if (!is_custom_sprite && variant == SIG_ELECTRIC && IsRestrictedSignal(tile) && GetExistingTraceRestrictProgram(tile, track) != NULL) { + if (type == SIGTYPE_PBS || type == SIGTYPE_PBS_ONEWAY) { + static const SubSprite lower_part { -50, -10, 50, 50 }; + static const SubSprite upper_part { -50, -50, 50, -11 }; + + AddSortableSpriteToDraw(sprite, SPR_TRACERESTRICT_BASE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track), false, 0, 0, 0, &lower_part); + AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track), false, 0, 0, 0, &upper_part); + } else { + AddSortableSpriteToDraw(sprite, SPR_TRACERESTRICT_BASE + 1, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track)); + } + } else { + AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track)); + } } static uint32 _drawtile_track_palette; diff --git a/src/table/sprites.h b/src/table/sprites.h index 81d5388f99..3bd7fdffeb 100644 --- a/src/table/sprites.h +++ b/src/table/sprites.h @@ -296,8 +296,12 @@ static const uint16 EMPTY_BOUNDING_BOX_SPRITE_COUNT = 1; static const SpriteID SPR_PALETTE_BASE = SPR_EMPTY_BOUNDING_BOX + EMPTY_BOUNDING_BOX_SPRITE_COUNT; static const uint16 PALETTE_SPRITE_COUNT = 1; +/* Tracerestrict sprites */ +static const SpriteID SPR_TRACERESTRICT_BASE = SPR_PALETTE_BASE + PALETTE_SPRITE_COUNT; +static const uint16 TRACERESTRICT_SPRITE_COUNT = 2; + /* From where can we start putting NewGRFs? */ -static const SpriteID SPR_NEWGRFS_BASE = SPR_PALETTE_BASE + PALETTE_SPRITE_COUNT; +static const SpriteID SPR_NEWGRFS_BASE = SPR_TRACERESTRICT_BASE + TRACERESTRICT_SPRITE_COUNT; /* Manager face sprites */ static const SpriteID SPR_GRADIENT = 874; // background gradient behind manager face diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 5b9ee86c3a..968a22c8ea 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -49,11 +49,10 @@ * This is not done for shared programs as this would delete the shared aspect whenever * the program became empty. * - * Empty programs with a refcount of 1 may still exist due to the edge case where: - * 1: There is an empty program with refcount 2 - * 2: One of the two mappings is deleted - * Finding the other mapping would entail a linear search of the mappings, and there is little - * to be gained by doing so. + * Special case: In the case where an empty program with refcount 2 has one of its + * mappings removed, the other mapping is left pointing to an empty unshared program. + * This other mapping is then removed by performing a linear search of the mappings, + * and removing the reference to that program ID. */ TraceRestrictProgramPool _tracerestrictprogram_pool("TraceRestrictProgram"); @@ -604,7 +603,13 @@ void TraceRestrictRemoveProgramMapping(TraceRestrictRefId ref) TraceRestrictMapping::iterator iter = _tracerestrictprogram_mapping.find(ref); if (iter != _tracerestrictprogram_mapping.end()) { // Found - _tracerestrictprogram_pool.Get(iter->second.program_id)->DecrementRefCount(); + TraceRestrictProgram *prog = _tracerestrictprogram_pool.Get(iter->second.program_id); + + // check to see if another mapping needs to be removed as well + // do this before decrementing the refcount + bool remove_other_mapping = prog->refcount == 2 && prog->items.empty(); + + prog->DecrementRefCount(); _tracerestrictprogram_mapping.erase(iter); TileIndex tile = GetTraceRestrictRefIdTileIndex(ref); @@ -612,6 +617,17 @@ void TraceRestrictRemoveProgramMapping(TraceRestrictRefId ref) SetIsSignalRestrictedBit(tile); MarkTileDirtyByTile(tile); YapfNotifyTrackLayoutChange(tile, track); + + if (remove_other_mapping) { + TraceRestrictProgramID id = prog->index; + for (TraceRestrictMapping::iterator rm_iter = _tracerestrictprogram_mapping.begin(); + rm_iter != _tracerestrictprogram_mapping.end(); ++rm_iter) { + if (rm_iter->second.program_id == id) { + TraceRestrictRemoveProgramMapping(rm_iter->first); + break; + } + } + } } }