Changeset - r28345:d8c125d15395
[Not reviewed]
master
0 6 0
Peter Nelson - 11 months ago 2023-12-27 15:26:33
peter1138@openttd.org
Fix: Changing default livery did not propagate to group liveries.

#11614 attempted to address this but did not handle 2CC properly, and changes to the default livery were not handled.
6 files changed with 59 insertions and 26 deletions:
0 comments (0 inline, 0 general)
src/company_cmd.cpp
Show inline comments
 
@@ -947,12 +947,26 @@ CommandCost CmdSetCompanyManagerFace(DoC
 
		MarkWholeScreenDirty();
 
	}
 
	return CommandCost();
 
}
 

	
 
/**
 
 * Update liveries for a company. This is called when the LS_DEFAULT scheme is changed, to update schemes with colours
 
 * set to default.
 
 * @param c Company to update.
 
 */
 
void UpdateCompanyLiveries(Company *c)
 
{
 
	for (int i = 1; i < LS_END; i++) {
 
		if (!HasBit(c->livery[i].in_use, 0)) c->livery[i].colour1 = c->livery[LS_DEFAULT].colour1;
 
		if (!HasBit(c->livery[i].in_use, 1)) c->livery[i].colour2 = c->livery[LS_DEFAULT].colour2;
 
	}
 
	UpdateCompanyGroupLiveries(c);
 
}
 

	
 
/**
 
 * Change the company's company-colour
 
 * @param flags operation to perform
 
 * @param scheme scheme to set
 
 * @param primary set first/second colour
 
 * @param colour new colour for vehicles, property, etc.
 
 * @return the cost of this operation or an error
 
@@ -979,28 +993,24 @@ CommandCost CmdSetCompanyColour(DoComman
 
			if (colour == INVALID_COLOUR) colour = (Colours)c->livery[LS_DEFAULT].colour1;
 
			c->livery[scheme].colour1 = colour;
 

	
 
			/* If setting the first colour of the default scheme, adjust the
 
			 * original and cached company colours too. */
 
			if (scheme == LS_DEFAULT) {
 
				for (int i = 1; i < LS_END; i++) {
 
					if (!HasBit(c->livery[i].in_use, 0)) c->livery[i].colour1 = colour;
 
				}
 
				UpdateCompanyLiveries(c);
 
				_company_colours[_current_company] = colour;
 
				c->colour = colour;
 
				CompanyAdminUpdate(c);
 
			}
 
		} else {
 
			if (scheme != LS_DEFAULT) SB(c->livery[scheme].in_use, 1, 1, colour != INVALID_COLOUR);
 
			if (colour == INVALID_COLOUR) colour = (Colours)c->livery[LS_DEFAULT].colour2;
 
			c->livery[scheme].colour2 = colour;
 

	
 
			if (scheme == LS_DEFAULT) {
 
				for (int i = 1; i < LS_END; i++) {
 
					if (!HasBit(c->livery[i].in_use, 1)) c->livery[i].colour2 = colour;
 
				}
 
				UpdateCompanyGroupLiveries(c);
 
			}
 
		}
 

	
 
		if (c->livery[scheme].in_use != 0) {
 
			/* If enabling a scheme, set the default scheme to be in use too */
 
			c->livery[LS_DEFAULT].in_use = 1;
src/company_func.h
Show inline comments
 
@@ -21,12 +21,13 @@ static const int OWNED_BY_OWNER_IN_PARAM
 
void SetDParamsForOwnedBy(Owner owner, TileIndex tile);
 
void SetLocalCompany(CompanyID new_company);
 
void ShowBuyCompanyDialog(CompanyID company, bool hostile_takeover);
 
void CompanyAdminUpdate(const Company *company);
 
void CompanyAdminBankrupt(CompanyID company_id);
 
void UpdateLandscapingLimits();
 
void UpdateCompanyLiveries(Company *c);
 

	
 
bool CheckCompanyHasMoney(CommandCost &cost);
 
void SubtractMoneyFromCompany(const CommandCost& cost);
 
void SubtractMoneyFromCompanyFract(CompanyID company, const CommandCost& cost);
 
CommandCost CheckOwnership(Owner owner, TileIndex tile = 0U);
 
CommandCost CheckTileOwnership(TileIndex tile);
src/company_gui.cpp
Show inline comments
 
@@ -904,24 +904,24 @@ public:
 
		int square_offs = (ir.Height() - this->square.height) / 2;
 
		int text_offs   = (ir.Height() - GetCharacterHeight(FS_NORMAL)) / 2;
 

	
 
		int y = ir.top;
 

	
 
		/* Helper function to draw livery info. */
 
		auto draw_livery = [&](StringID str, const Livery &liv, bool sel, bool def, int indent) {
 
		auto draw_livery = [&](StringID str, const Livery &livery, bool is_selected, bool is_default_scheme, int indent) {
 
			/* Livery Label. */
 
			DrawString(sch.left + (rtl ? 0 : indent), sch.right - (rtl ? indent : 0), y + text_offs, str, sel ? TC_WHITE : TC_BLACK);
 
			DrawString(sch.left + (rtl ? 0 : indent), sch.right - (rtl ? indent : 0), y + text_offs, str, is_selected ? TC_WHITE : TC_BLACK);
 

	
 
			/* Text below the first dropdown. */
 
			DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(liv.colour1), pri_squ.left, y + square_offs);
 
			DrawString(pri.left, pri.right, y + text_offs, (def || HasBit(liv.in_use, 0)) ? STR_COLOUR_DARK_BLUE + liv.colour1 : STR_COLOUR_DEFAULT, sel ? TC_WHITE : TC_GOLD);
 
			DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(livery.colour1), pri_squ.left, y + square_offs);
 
			DrawString(pri.left, pri.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 0)) ? STR_COLOUR_DARK_BLUE + livery.colour1 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
 

	
 
			/* Text below the second dropdown. */
 
			if (sec.right > sec.left) { // Second dropdown has non-zero size.
 
				DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(liv.colour2), sec_squ.left, y + square_offs);
 
				DrawString(sec.left, sec.right, y + text_offs, (def || HasBit(liv.in_use, 1)) ? STR_COLOUR_DARK_BLUE + liv.colour2 : STR_COLOUR_DEFAULT, sel ? TC_WHITE : TC_GOLD);
 
				DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(livery.colour2), sec_squ.left, y + square_offs);
 
				DrawString(sec.left, sec.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 1)) ? STR_COLOUR_DARK_BLUE + livery.colour2 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
 
			}
 

	
 
			y += this->line_height;
 
		};
 

	
 
		const Company *c = Company::Get((CompanyID)this->window_number);
 
@@ -935,15 +935,14 @@ public:
 
				}
 
			}
 
		} else {
 
			uint max = static_cast<uint>(std::min<size_t>(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->groups.size()));
 
			for (uint i = this->vscroll->GetPosition(); i < max; ++i) {
 
				const Group *g = this->groups[i];
 
				const bool livery_set = HasBit(g->livery.in_use, 0);
 
				SetDParam(0, g->index);
 
				draw_livery(STR_GROUP_NAME, livery_set ? g->livery : c->livery[LS_DEFAULT], this->sel == g->index, livery_set, this->indents[i] * WidgetDimensions::scaled.hsep_indent);
 
				draw_livery(STR_GROUP_NAME, g->livery, this->sel == g->index, false, this->indents[i] * WidgetDimensions::scaled.hsep_indent);
 
			}
 

	
 
			if (this->vscroll->GetCount() == 0) {
 
				const StringID empty_labels[] = { STR_LIVERY_TRAIN_GROUP_EMPTY, STR_LIVERY_ROAD_VEHICLE_GROUP_EMPTY, STR_LIVERY_SHIP_GROUP_EMPTY, STR_LIVERY_AIRCRAFT_GROUP_EMPTY };
 
				VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);
 
				DrawString(ir.left, ir.right, y + text_offs, empty_labels[vtype], TC_BLACK);
src/group.h
Show inline comments
 
@@ -109,8 +109,9 @@ uint GetGroupNumVehicleMinAge(CompanyID 
 
Money GetGroupProfitLastYearMinAge(CompanyID company, GroupID id_g, VehicleType type);
 

	
 
void SetTrainGroupID(Train *v, GroupID grp);
 
void UpdateTrainGroupID(Train *v);
 
void RemoveAllGroupsForCompany(const CompanyID company);
 
bool GroupIsInGroup(GroupID search, GroupID group);
 
void UpdateCompanyGroupLiveries(const Company *c);
 

	
 
#endif /* GROUP_H */
src/group_cmd.cpp
Show inline comments
 
@@ -272,36 +272,54 @@ const Livery *GetParentLivery(const Grou
 
	const Group *pg = Group::Get(g->parent);
 
	return &pg->livery;
 
}
 

	
 

	
 
/**
 
 * Propagate a livery change to a group's children.
 
 * @param g Group.
 
 * Propagate a livery change to a group's children, and optionally update cached vehicle colourmaps.
 
 * @param g Group to propagate colours to children.
 
 * @param reset_cache Reset colourmap of vehicles in this group.
 
 */
 
void PropagateChildLivery(const Group *g)
 
static void PropagateChildLivery(const Group *g, bool reset_cache)
 
{
 
	/* Company colour data is indirectly cached. */
 
	for (Vehicle *v : Vehicle::Iterate()) {
 
		if (v->group_id == g->index && (!v->IsGroundVehicle() || v->IsFrontEngine())) {
 
			for (Vehicle *u = v; u != nullptr; u = u->Next()) {
 
				u->colourmap = PAL_NONE;
 
				u->InvalidateNewGRFCache();
 
	if (reset_cache) {
 
		/* Company colour data is indirectly cached. */
 
		for (Vehicle *v : Vehicle::Iterate()) {
 
			if (v->group_id == g->index && (!v->IsGroundVehicle() || v->IsFrontEngine())) {
 
				for (Vehicle *u = v; u != nullptr; u = u->Next()) {
 
					u->colourmap = PAL_NONE;
 
					u->InvalidateNewGRFCache();
 
				}
 
			}
 
		}
 
	}
 

	
 
	for (Group *cg : Group::Iterate()) {
 
		if (cg->parent == g->index) {
 
			if (!HasBit(cg->livery.in_use, 0)) cg->livery.colour1 = g->livery.colour1;
 
			if (!HasBit(cg->livery.in_use, 1)) cg->livery.colour2 = g->livery.colour2;
 
			PropagateChildLivery(cg);
 
			PropagateChildLivery(cg, reset_cache);
 
		}
 
	}
 
}
 

	
 
/**
 
 * Update group liveries for a company. This is called when the LS_DEFAULT scheme is changed, to update groups with
 
 * colours set to default.
 
 * @param c Company to update.
 
 */
 
void UpdateCompanyGroupLiveries(const Company *c)
 
{
 
	for (Group *g : Group::Iterate()) {
 
		if (g->owner == c->index && g->parent == INVALID_GROUP) {
 
			if (!HasBit(g->livery.in_use, 0)) g->livery.colour1 = c->livery[LS_DEFAULT].colour1;
 
			if (!HasBit(g->livery.in_use, 1)) g->livery.colour2 = c->livery[LS_DEFAULT].colour2;
 
			PropagateChildLivery(g, false);
 
		}
 
	}
 
}
 

	
 
Group::Group(Owner owner)
 
{
 
	this->owner = owner;
 
	this->folded = false;
 
}
 
@@ -450,13 +468,13 @@ CommandCost CmdAlterGroup(DoCommandFlag 
 

	
 
			if (g->livery.in_use == 0) {
 
				const Livery *livery = GetParentLivery(g);
 
				g->livery.colour1 = livery->colour1;
 
				g->livery.colour2 = livery->colour2;
 

	
 
				PropagateChildLivery(g);
 
				PropagateChildLivery(g, true);
 
				MarkWholeScreenDirty();
 
			}
 
		}
 
	} else {
 
		return CMD_ERROR;
 
	}
 
@@ -658,13 +676,13 @@ CommandCost CmdSetGroupLivery(DoCommandF
 
		} else {
 
			SB(g->livery.in_use, 1, 1, colour != INVALID_COLOUR);
 
			if (colour == INVALID_COLOUR) colour = (Colours)GetParentLivery(g)->colour2;
 
			g->livery.colour2 = colour;
 
		}
 

	
 
		PropagateChildLivery(g);
 
		PropagateChildLivery(g, true);
 
		MarkWholeScreenDirty();
 
	}
 

	
 
	return CommandCost();
 
}
 

	
src/saveload/afterload.cpp
Show inline comments
 
@@ -3259,12 +3259,16 @@ bool AfterLoadGame()
 
		/* Set service date provided to NewGRF. */
 
		for (Vehicle *v : Vehicle::Iterate()) {
 
			v->date_of_last_service_newgrf = v->date_of_last_service;
 
		}
 
	}
 

	
 
	for (Company *c : Company::Iterate()) {
 
		UpdateCompanyLiveries(c);
 
	}
 

	
 
	AfterLoadLabelMaps();
 
	AfterLoadCompanyStats();
 
	AfterLoadStoryBook();
 

	
 
	_gamelog.PrintDebug(1);
 

	
0 comments (0 inline, 0 general)