Changeset - r13024:48c81d0b078a
[Not reviewed]
src/ai/ai_gui.cpp
Show inline comments
 
@@ -132,49 +132,49 @@ struct AIListWindow : public Window {
 
					DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, STR_AI_LIST_VERSION);
 
					y += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
 
					if (selected_info->GetURL() != NULL) {
 
						SetDParamStr(0, selected_info->GetURL());
 
						DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, STR_AI_LIST_URL);
 
						y += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
 
					}
 
					SetDParamStr(0, selected_info->GetDescription());
 
					DrawStringMultiLine(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, r.bottom - WD_FRAMERECT_BOTTOM, STR_JUST_RAW_STRING, TC_BLACK);
 
				}
 
				break;
 
			}
 
		}
 
	}
 

	
 
	void ChangeAI()
 
	{
 
		if (this->selected == -1) {
 
			AIConfig::GetConfig(slot)->ChangeAI(NULL);
 
		} else {
 
			AIInfoList::const_iterator it = this->ai_info_list->begin();
 
			for (int i = 0; i < this->selected; i++) it++;
 
			AIConfig::GetConfig(slot)->ChangeAI((*it).second->GetName(), (*it).second->GetVersion());
 
		}
 
		InvalidateWindow(WC_GAME_OPTIONS, 0);
 
		SetWindowDirty(WC_GAME_OPTIONS, 0);
 
	}
 

	
 
	virtual void OnClick(Point pt, int widget)
 
	{
 
		switch (widget) {
 
			case AIL_WIDGET_LIST: { // Select one of the AIs
 
				int sel = (pt.y - this->nested_array[AIL_WIDGET_LIST]->pos_y) / this->line_height + this->vscroll.GetPosition() - 1;
 
				if (sel < (int)this->ai_info_list->size()) {
 
					this->selected = sel;
 
					this->SetDirty();
 
				}
 
				break;
 
			}
 

	
 
			case AIL_WIDGET_ACCEPT: {
 
				this->ChangeAI();
 
				delete this;
 
				break;
 
			}
 

	
 
			case AIL_WIDGET_CANCEL:
 
				delete this;
 
				break;
 

	
 
@@ -746,66 +746,66 @@ struct AIDebugWindow : public Window {
 

	
 
			/* Check if we have the company marked as inactive */
 
			if (this->IsWidgetDisabled(i + AID_WIDGET_COMPANY_BUTTON_START)) {
 
				/* New AI! Yippie :p */
 
				this->EnableWidget(i + AID_WIDGET_COMPANY_BUTTON_START);
 

	
 
				/* We need a repaint */
 
				this->SetDirty();
 
			}
 

	
 
			byte offset = (i == ai_debug_company) ? 1 : 0;
 
			DrawCompanyIcon(i, this->nested_array[AID_WIDGET_COMPANY_BUTTON_START + i]->pos_x + 11 + offset, this->nested_array[AID_WIDGET_COMPANY_BUTTON_START + i]->pos_y + 2 + offset);
 
		}
 

	
 
		CompanyID old_company = _current_company;
 
		_current_company = ai_debug_company;
 
		AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
 
		_current_company = old_company;
 

	
 
		int scroll_count = (log == NULL) ? 0 : log->used;
 
		if (this->vscroll.GetCount() != scroll_count) {
 
			this->vscroll.SetCount(scroll_count);
 

	
 
			/* We need a repaint */
 
			this->InvalidateWidget(AID_WIDGET_SCROLLBAR);
 
			this->SetWidgetDirty(AID_WIDGET_SCROLLBAR);
 
		}
 

	
 
		if (log == NULL) return;
 

	
 
		/* Detect when the user scrolls the window. Enable autoscroll when the
 
		 * bottom-most line becomes visible. */
 
		if (this->last_vscroll_pos != this->vscroll.GetPosition()) {
 
			this->autoscroll = this->vscroll.GetPosition() >= log->used - this->vscroll.GetCapacity();
 
		}
 
		if (this->autoscroll) {
 
			int scroll_pos = max(0, log->used - this->vscroll.GetCapacity());
 
			if (scroll_pos != this->vscroll.GetPosition()) {
 
				this->vscroll.SetPosition(scroll_pos);
 

	
 
				/* We need a repaint */
 
				this->InvalidateWidget(AID_WIDGET_SCROLLBAR);
 
				this->InvalidateWidget(AID_WIDGET_LOG_PANEL);
 
				this->SetWidgetDirty(AID_WIDGET_SCROLLBAR);
 
				this->SetWidgetDirty(AID_WIDGET_LOG_PANEL);
 
			}
 
		}
 
		this->last_vscroll_pos = this->vscroll.GetPosition();
 

	
 
	}
 

	
 
	virtual void DrawWidget(const Rect &r, int widget) const
 
	{
 
		if (ai_debug_company == INVALID_COMPANY) return;
 

	
 
		switch (widget) {
 
			case AID_WIDGET_NAME_TEXT: {
 
				/* Draw the AI name */
 
				AIInfo *info = Company::Get(ai_debug_company)->ai_info;
 
				assert(info != NULL);
 
				char name[1024];
 
				snprintf(name, sizeof(name), "%s (v%d)", info->GetName(), info->GetVersion());
 
				DrawString(r.left + 7, r.right - 7, 47, name, TC_BLACK, SA_CENTER);
 
				break;
 
			}
 
			case AID_WIDGET_LOG_PANEL: {
 
				CompanyID old_company = _current_company;
 
				_current_company = ai_debug_company;
 
				AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
src/aircraft_cmd.cpp
Show inline comments
 
@@ -412,49 +412,49 @@ CommandCost CmdBuildAircraft(TileIndex t
 
		/* Aircraft with 3 vehicles (chopper)? */
 
		if (v->subtype == AIR_HELICOPTER) {
 
			Aircraft *w = new Aircraft();
 
			w->engine_type = p1;
 
			w->direction = DIR_N;
 
			w->owner = _current_company;
 
			w->x_pos = v->x_pos;
 
			w->y_pos = v->y_pos;
 
			w->z_pos = v->z_pos + 5;
 
			w->vehstatus = VS_HIDDEN | VS_UNCLICKABLE;
 
			w->spritenum = 0xFF;
 
			w->subtype = AIR_ROTOR;
 
			w->cur_image = SPR_ROTOR_STOPPED;
 
			w->random_bits = VehicleRandomBits();
 
			/* Use rotor's air.state to store the rotor animation frame */
 
			w->state = HRS_ROTOR_STOPPED;
 
			w->UpdateDeltaXY(INVALID_DIR);
 

	
 
			u->SetNext(w);
 
			VehicleMove(w, false);
 
		}
 

	
 
		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 
		InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
 
		InvalidateWindow(WC_COMPANY, v->owner);
 
		SetWindowDirty(WC_COMPANY, v->owner);
 
		if (IsLocalCompany())
 
			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Aircraft window
 

	
 
		Company::Get(_current_company)->num_engines[p1]++;
 
	}
 

	
 
	return value;
 
}
 

	
 

	
 
/** Sell an aircraft.
 
 * @param tile unused
 
 * @param flags for command type
 
 * @param p1 vehicle ID to be sold
 
 * @param p2 unused
 
 * @return result of operation.  Error or sold value
 
 */
 
CommandCost CmdSellAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	Aircraft *v = Aircraft::GetIfValid(p1);
 

	
 
	if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR;
 
	if (!v->IsStoppedInDepot()) return_cmd_error(STR_ERROR_AIRCRAFT_MUST_BE_STOPPED);
 

	
 
@@ -559,109 +559,109 @@ CommandCost CmdRefitAircraft(TileIndex t
 
		 * default cargo capacity */
 
		pass = AircraftDefaultCargoCapacity(new_cid, avi);
 
	} else {
 
		pass = callback;
 
	}
 
	_returned_refit_capacity = pass;
 

	
 
	CommandCost cost;
 
	if (new_cid != v->cargo_type) {
 
		cost = GetRefitCost(v->engine_type);
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		v->cargo_cap = pass;
 

	
 
		Vehicle *u = v->Next();
 
		uint mail = IsCargoInClass(new_cid, CC_PASSENGERS) ? avi->mail_capacity : 0;
 
		u->cargo_cap = mail;
 
		v->cargo.Truncate(v->cargo_type == new_cid ? pass : 0);
 
		u->cargo.Truncate(v->cargo_type == new_cid ? mail : 0);
 
		v->cargo_type = new_cid;
 
		v->cargo_subtype = new_subtype;
 
		v->colourmap = PAL_NONE; // invalidate vehicle colour map
 
		v->InvalidateNewGRFCacheOfChain();
 
		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
		SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
 
		SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);
 
		InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
 
	}
 

	
 
	return cost;
 
}
 

	
 

	
 
static void CheckIfAircraftNeedsService(Aircraft *v)
 
{
 
	if (Company::Get(v->owner)->settings.vehicle.servint_aircraft == 0 || !v->NeedsAutomaticServicing()) return;
 
	if (v->IsInDepot()) {
 
		VehicleServiceInDepot(v);
 
		return;
 
	}
 

	
 
	const Station *st = Station::Get(v->current_order.GetDestination());
 

	
 
	assert(st != NULL);
 

	
 
	/* only goto depot if the target airport has terminals (eg. it is airport) */
 
	if (st->airport_tile != INVALID_TILE && st->Airport()->terminals != NULL) {
 
//		printf("targetairport = %d, st->index = %d\n", v->targetairport, st->index);
 
//		v->targetairport = st->index;
 
		v->current_order.MakeGoToDepot(st->index, ODTFB_SERVICE);
 
		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
		SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	} else if (v->current_order.IsType(OT_GOTO_DEPOT)) {
 
		v->current_order.MakeDummy();
 
		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
		SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	}
 
}
 

	
 
Money Aircraft::GetRunningCost() const
 
{
 
	return GetVehicleProperty(this, 0x0E, AircraftVehInfo(this->engine_type)->running_cost) * _price.aircraft_running;
 
}
 

	
 
void Aircraft::OnNewDay()
 
{
 
	if (!this->IsNormalAircraft()) return;
 

	
 
	if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
 

	
 
	CheckOrders(this);
 

	
 
	CheckVehicleBreakdown(this);
 
	AgeVehicle(this);
 
	CheckIfAircraftNeedsService(this);
 

	
 
	if (this->running_ticks == 0) return;
 

	
 
	CommandCost cost(EXPENSES_AIRCRAFT_RUN, this->GetRunningCost() * this->running_ticks / (DAYS_IN_YEAR * DAY_TICKS));
 

	
 
	this->profit_this_year -= cost.GetCost();
 
	this->running_ticks = 0;
 

	
 
	SubtractMoneyFromCompanyFract(this->owner, cost);
 

	
 
	InvalidateWindow(WC_VEHICLE_DETAILS, this->index);
 
	InvalidateWindowClasses(WC_AIRCRAFT_LIST);
 
	SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
 
	SetWindowClassesDirty(WC_AIRCRAFT_LIST);
 
}
 

	
 
static void HelicopterTickHandler(Aircraft *v)
 
{
 
	Aircraft *u = v->Next()->Next();
 

	
 
	if (u->vehstatus & VS_HIDDEN) return;
 

	
 
	/* if true, helicopter rotors do not rotate. This should only be the case if a helicopter is
 
	 * loading/unloading at a terminal or stopped */
 
	if (v->current_order.IsType(OT_LOADING) || (v->vehstatus & VS_STOPPED)) {
 
		if (u->cur_speed != 0) {
 
			u->cur_speed++;
 
			if (u->cur_speed >= 0x80 && u->state == HRS_ROTOR_MOVING_3) {
 
				u->cur_speed = 0;
 
			}
 
		}
 
	} else {
 
		if (u->cur_speed == 0)
 
			u->cur_speed = 0x70;
 

	
 
		if (u->cur_speed >= 0x50)
 
			u->cur_speed--;
 
	}
 
@@ -795,49 +795,49 @@ static int UpdateAircraftSpeed(Aircraft 
 

	
 
	speed_limit = min(speed_limit, v->max_speed);
 

	
 
	v->subspeed = (t = v->subspeed) + (byte)spd;
 

	
 
	/* Aircraft's current speed is used twice so that very fast planes are
 
	 * forced to slow down rapidly in the short distance needed. The magic
 
	 * value 16384 was determined to give similar results to the old speed/48
 
	 * method at slower speeds. This also results in less reduction at slow
 
	 * speeds to that aircraft do not get to taxi speed straight after
 
	 * touchdown. */
 
	if (!hard_limit && v->cur_speed > speed_limit) {
 
		speed_limit = v->cur_speed - max(1, ((v->cur_speed * v->cur_speed) / 16384) / _settings_game.vehicle.plane_speed);
 
	}
 

	
 
	spd = min(v->cur_speed + (spd >> 8) + (v->subspeed < t), speed_limit);
 

	
 
	/* adjust speed for broken vehicles */
 
	if (v->vehstatus & VS_AIRCRAFT_BROKEN) spd = min(spd, SPEED_LIMIT_BROKEN);
 

	
 
	/* updates statusbar only if speed have changed to save CPU time */
 
	if (spd != v->cur_speed) {
 
		v->cur_speed = spd;
 
		if (_settings_client.gui.vehicle_speed)
 
			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
			SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	}
 

	
 
	/* Adjust distance moved by plane speed setting */
 
	if (_settings_game.vehicle.plane_speed > 1) spd /= _settings_game.vehicle.plane_speed;
 

	
 
	if (!(v->direction & 1)) spd = spd * 3 / 4;
 

	
 
	spd += v->progress;
 
	v->progress = (byte)spd;
 
	return spd >> 8;
 
}
 

	
 
/**
 
 * Gets the cruise altitude of an aircraft.
 
 * The cruise altitude is determined by the velocity of the vehicle
 
 * and the direction it is moving
 
 * @param v The vehicle. Should be an aircraft
 
 * @returns Altitude in pixel units
 
 */
 
byte GetAircraftFlyingAltitude(const Aircraft *v)
 
{
 
	/* Make sure Aircraft fly no lower so that they don't conduct
 
	 * CFITs (controlled flight into terrain)
 
	 */
 
@@ -1198,50 +1198,50 @@ static bool HandleCrashedAircraft(Aircra
 
		 * small airports use AIRPORT_BUSY, city airports use RUNWAY_IN_OUT_block, etc.
 
		 * but they all share the same number */
 
		if (st != NULL) {
 
			CLRBITS(st->airport_flags, RUNWAY_IN_block);
 
			CLRBITS(st->airport_flags, RUNWAY_IN_OUT_block); // commuter airport
 
			CLRBITS(st->airport_flags, RUNWAY_IN2_block);    // intercontinental
 
		}
 

	
 
		delete v;
 

	
 
		return false;
 
	}
 

	
 
	return true;
 
}
 

	
 
static void HandleBrokenAircraft(Aircraft *v)
 
{
 
	if (v->breakdown_ctr != 1) {
 
		v->breakdown_ctr = 1;
 
		v->vehstatus |= VS_AIRCRAFT_BROKEN;
 

	
 
		if (v->breakdowns_since_last_service != 255)
 
			v->breakdowns_since_last_service++;
 
		InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 
		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
		SetWindowDirty(WC_VEHICLE_VIEW, v->index);
 
		SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
 
	}
 
}
 

	
 

	
 
static void HandleAircraftSmoke(Aircraft *v)
 
{
 
	static const struct {
 
		int8 x;
 
		int8 y;
 
	} smoke_pos[] = {
 
		{  5,  5 },
 
		{  6,  0 },
 
		{  5, -5 },
 
		{  0, -6 },
 
		{ -5, -5 },
 
		{ -6,  0 },
 
		{ -5,  5 },
 
		{  0,  6 }
 
	};
 

	
 
	if (!(v->vehstatus & VS_AIRCRAFT_BROKEN)) return;
 

	
 
	if (v->cur_speed < 10) {
 
		v->vehstatus &= ~VS_AIRCRAFT_BROKEN;
 
@@ -1295,49 +1295,49 @@ void HandleMissingAircraftOrders(Aircraf
 
TileIndex Aircraft::GetOrderStationLocation(StationID station)
 
{
 
	/* Orders are changed in flight, ensure going to the right station. */
 
	if (this->state == FLYING) {
 
		AircraftNextAirportPos_and_Order(this);
 
	}
 

	
 
	/* Aircraft do not use dest-tile */
 
	return 0;
 
}
 

	
 
void Aircraft::MarkDirty()
 
{
 
	this->UpdateViewport(false, false);
 
	if (this->subtype == AIR_HELICOPTER) this->Next()->Next()->cur_image = GetRotorImage(this);
 
}
 

	
 
static void CrashAirplane(Aircraft *v)
 
{
 
	v->vehstatus |= VS_CRASHED;
 
	v->crashed_counter = 0;
 

	
 
	CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
 

	
 
	InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 
	SetWindowDirty(WC_VEHICLE_VIEW, v->index);
 

	
 
	uint amt = 2;
 
	if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) amt += v->cargo.Count();
 
	SetDParam(0, amt);
 

	
 
	v->cargo.Truncate(0);
 
	v->Next()->cargo.Truncate(0);
 
	const Station *st = GetTargetAirportIfValid(v);
 
	StringID newsitem;
 
	AIEventVehicleCrashed::CrashReason crash_reason;
 
	if (st == NULL) {
 
		newsitem = STR_NEWS_PLANE_CRASH_OUT_OF_FUEL;
 
		crash_reason = AIEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT;
 
	} else {
 
		SetDParam(1, st->index);
 
		newsitem = STR_NEWS_AIRCRAFT_CRASH;
 
		crash_reason = AIEventVehicleCrashed::CRASH_PLANE_LANDING;
 
	}
 

	
 
	AI::NewEvent(v->owner, new AIEventVehicleCrashed(v->index, v->tile, crash_reason));
 

	
 
	AddVehicleNewsItem(newsitem,
 
		NS_ACCIDENT,
 
		v->index,
 
@@ -1418,49 +1418,49 @@ void AircraftNextAirportPos_and_Order(Ai
 
}
 

	
 
void AircraftLeaveHangar(Aircraft *v)
 
{
 
	v->cur_speed = 0;
 
	v->subspeed = 0;
 
	v->progress = 0;
 
	v->direction = DIR_SE;
 
	v->vehstatus &= ~VS_HIDDEN;
 
	{
 
		Vehicle *u = v->Next();
 
		u->vehstatus &= ~VS_HIDDEN;
 

	
 
		/* Rotor blades */
 
		u = u->Next();
 
		if (u != NULL) {
 
			u->vehstatus &= ~VS_HIDDEN;
 
			u->cur_speed = 80;
 
		}
 
	}
 

	
 
	VehicleServiceInDepot(v);
 
	SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
 
	InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 
	InvalidateWindowClasses(WC_AIRCRAFT_LIST);
 
	SetWindowClassesDirty(WC_AIRCRAFT_LIST);
 
}
 

	
 
/** Checks if an aircraft should head towards a hangar because it needs replacement
 
 * @param *v the vehicle to test
 
 * @return true if the aircraft should head towards a hangar
 
 */
 
static inline bool CheckSendAircraftToHangarForReplacement(const Vehicle *v)
 
{
 
	EngineID new_engine;
 
	Company *c = Company::Get(v->owner);
 

	
 
	if (VehicleHasDepotOrders(v)) return false; // The aircraft will end up in the hangar eventually on it's own
 

	
 
	new_engine = EngineReplacementForCompany(c, v->engine_type, v->group_id);
 

	
 
	if (new_engine == INVALID_ENGINE) {
 
		/* There is no autoreplace assigned to this EngineID so we will set it to renew to the same type if needed */
 
		new_engine = v->engine_type;
 

	
 
		if (!v->NeedsAutorenewing(c)) {
 
			/* No need to replace the aircraft */
 
			return false;
 
		}
 
	}
 
@@ -1529,49 +1529,49 @@ static void AircraftEventHandler_InHanga
 
			if (!AirportFindFreeTerminal(v, apc)) return; // airplane
 
		}
 
	} else { // Else prepare for launch.
 
		/* airplane goto state takeoff, helicopter to helitakeoff */
 
		v->state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF;
 
	}
 
	AircraftLeaveHangar(v);
 
	AirportMove(v, apc);
 
}
 

	
 
/** At one of the Airport's Terminals */
 
static void AircraftEventHandler_AtTerminal(Aircraft *v, const AirportFTAClass *apc)
 
{
 
	/* if we just arrived, execute EnterTerminal first */
 
	if (v->previous_pos != v->pos) {
 
		AircraftEventHandler_EnterTerminal(v, apc);
 
		/* on an airport with helipads, a helicopter will always land there
 
		 * and get serviced at the same time - setting */
 
		if (_settings_game.order.serviceathelipad) {
 
			if (v->subtype == AIR_HELICOPTER && apc->helipads != NULL) {
 
				/* an exerpt of ServiceAircraft, without the invisibility stuff */
 
				v->date_of_last_service = _date;
 
				v->breakdowns_since_last_service = 0;
 
				v->reliability = Engine::Get(v->engine_type)->reliability;
 
				InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
				SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
 
			}
 
		}
 
		return;
 
	}
 

	
 
	if (v->current_order.IsType(OT_NOTHING)) return;
 

	
 
	/* if the block of the next position is busy, stay put */
 
	if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
 

	
 
	/* airport-road is free. We either have to go to another airport, or to the hangar
 
	 * ---> start moving */
 

	
 
	bool go_to_hangar = false;
 
	switch (v->current_order.GetType()) {
 
		case OT_GOTO_STATION: // ready to fly to another airport
 
			break;
 
		case OT_GOTO_DEPOT:   // visit hangar for serivicing, sale, etc.
 
			go_to_hangar = v->current_order.GetDestination() == v->targetairport;
 
			break;
 
		case OT_CONDITIONAL:
 
			/* In case of a conditional order we just have to wait a tick
 
			 * longer, so the conditional order can actually be processed;
 
			 * we should not clear the order as that makes us go nowhere. */
src/bridge_gui.cpp
Show inline comments
 
@@ -100,50 +100,50 @@ private:
 
	{
 
		return a->spec->speed - b->spec->speed;
 
	}
 

	
 
	void BuildBridge(uint8 i)
 
	{
 
		switch ((TransportType)(this->type >> 15)) {
 
			case TRANSPORT_RAIL: _last_railbridge_type = this->bridges->Get(i)->index; break;
 
			case TRANSPORT_ROAD: _last_roadbridge_type = this->bridges->Get(i)->index; break;
 
			default: break;
 
		}
 
		DoCommandP(this->end_tile, this->start_tile, this->type | this->bridges->Get(i)->index,
 
					CMD_BUILD_BRIDGE | CMD_MSG(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE), CcBuildBridge);
 
	}
 

	
 
	/** Sort the builable bridges */
 
	void SortBridgeList()
 
	{
 
		this->bridges->Sort();
 

	
 
		/* Display the current sort variant */
 
		this->nested_array[BBSW_DROPDOWN_CRITERIA]->widget_data = this->sorter_names[this->bridges->SortType()];
 

	
 
		/* Set the modified widgets dirty */
 
		this->InvalidateWidget(BBSW_DROPDOWN_CRITERIA);
 
		this->InvalidateWidget(BBSW_BRIDGE_LIST);
 
		this->SetWidgetDirty(BBSW_DROPDOWN_CRITERIA);
 
		this->SetWidgetDirty(BBSW_BRIDGE_LIST);
 
	}
 

	
 
public:
 
	BuildBridgeWindow(const WindowDesc *desc, TileIndex start, TileIndex end, uint32 br_type, GUIBridgeList *bl) : Window(),
 
		start_tile(start),
 
		end_tile(end),
 
		type(br_type),
 
		bridges(bl)
 
	{
 
		this->CreateNestedTree(desc);
 
		/* Change the data, or the caption of the gui. Set it to road or rail, accordingly. */
 
		this->nested_array[BBSW_CAPTION]->widget_data = (GB(this->type, 15, 2) == TRANSPORT_ROAD) ? STR_SELECT_ROAD_BRIDGE_CAPTION : STR_SELECT_RAIL_BRIDGE_CAPTION;
 
		this->FinishInitNested(desc, GB(br_type, 15, 2)); // Initializes 'this->bridgetext_offset'.
 

	
 
		this->parent = FindWindowById(WC_BUILD_TOOLBAR, GB(this->type, 15, 2));
 
		this->bridges->SetListing(this->last_sorting);
 
		this->bridges->SetSortFuncs(this->sorter_funcs);
 
		this->bridges->NeedResort();
 
		this->SortBridgeList();
 

	
 
		this->vscroll.SetCount(bl->Length());
 
		this->vscroll.SetCapacity(this->nested_array[BBSW_BRIDGE_LIST]->current_y / this->resize.step_height);
 
		if (this->last_size < this->vscroll.GetCapacity()) this->last_size = this->vscroll.GetCapacity();
 
		if (this->last_size > this->vscroll.GetCount()) this->last_size = this->vscroll.GetCount();
src/cheat_gui.cpp
Show inline comments
 
@@ -46,86 +46,86 @@ static int32 ClickMoneyCheat(int32 p1, i
 

	
 
/**
 
 * @param p1 company to set to
 
 * @param p2 is -1 or +1 (down/up)
 
 */
 
static int32 ClickChangeCompanyCheat(int32 p1, int32 p2)
 
{
 
	while ((uint)p1 < Company::GetPoolSize()) {
 
		if (Company::IsValidID((CompanyID)p1)) {
 
			SetLocalCompany((CompanyID)p1);
 
			return _local_company;
 
		}
 
		p1 += p2;
 
	}
 

	
 
	return _local_company;
 
}
 

	
 
/**
 
 * @param p1 new value
 
 * @param p2 unused
 
 */
 
static int32 ClickSetProdCheat(int32 p1, int32 p2)
 
{
 
	InvalidateWindowClasses(WC_INDUSTRY_VIEW);
 
	SetWindowClassesDirty(WC_INDUSTRY_VIEW);
 
	return p1;
 
}
 

	
 
/**
 
 * @param p1 new climate
 
 * @param p2 unused
 
 */
 
static int32 ClickChangeClimateCheat(int32 p1, int32 p2)
 
{
 
	if (p1 == -1) p1 = 3;
 
	if (p1 ==  4) p1 = 0;
 
	_settings_game.game_creation.landscape = p1;
 

	
 
	GamelogStartAction(GLAT_CHEAT);
 
	GamelogTestMode();
 
	ReloadNewGRFData();
 
	GamelogStopAction();
 

	
 
	return _settings_game.game_creation.landscape;
 
}
 

	
 
extern void EnginesMonthlyLoop();
 

	
 
/**
 
 * @param p1 unused
 
 * @param p2 1 (increase) or -1 (decrease)
 
 */
 
static int32 ClickChangeDateCheat(int32 p1, int32 p2)
 
{
 
	YearMonthDay ymd;
 
	ConvertDateToYMD(_date, &ymd);
 

	
 
	if ((ymd.year == MIN_YEAR && p2 == -1) || (ymd.year == MAX_YEAR && p2 == 1)) return _cur_year;
 

	
 
	SetDate(ConvertYMDToDate(_cur_year + p2, ymd.month, ymd.day));
 
	EnginesMonthlyLoop();
 
	InvalidateWindow(WC_STATUS_BAR, 0);
 
	SetWindowDirty(WC_STATUS_BAR, 0);
 
	InvalidateWindowClassesData(WC_BUILD_STATION, 0);
 
	ResetSignalVariant();
 
	return _cur_year;
 
}
 

	
 
typedef int32 CheckButtonClick(int32, int32);
 

	
 
struct CheatEntry {
 
	VarType type;          ///< type of selector
 
	StringID str;          ///< string with descriptive text
 
	void *variable;        ///< pointer to the variable
 
	bool *been_used;       ///< has this cheat been used before?
 
	CheckButtonClick *proc;///< procedure
 
};
 

	
 
static const CheatEntry _cheats_ui[] = {
 
	{SLE_INT32, STR_CHEAT_MONEY,           &_money_cheat_amount,                    &_cheats.money.been_used,            &ClickMoneyCheat         },
 
	{SLE_UINT8, STR_CHEAT_CHANGE_COMPANY,  &_local_company,                         &_cheats.switch_company.been_used,   &ClickChangeCompanyCheat },
 
	{SLE_BOOL,  STR_CHEAT_EXTRA_DYNAMITE,  &_cheats.magic_bulldozer.value,          &_cheats.magic_bulldozer.been_used,  NULL                     },
 
	{SLE_BOOL,  STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value,         &_cheats.crossing_tunnels.been_used, NULL                     },
 
	{SLE_BOOL,  STR_CHEAT_BUILD_IN_PAUSE,  &_cheats.build_in_pause.value,           &_cheats.build_in_pause.been_used,   NULL                     },
 
	{SLE_BOOL,  STR_CHEAT_NO_JETCRASH,     &_cheats.no_jetcrash.value,              &_cheats.no_jetcrash.been_used,      NULL                     },
 
	{SLE_BOOL,  STR_CHEAT_SETUP_PROD,      &_cheats.setup_prod.value,               &_cheats.setup_prod.been_used,       &ClickSetProdCheat       },
 
	{SLE_UINT8, STR_CHEAT_SWITCH_CLIMATE,  &_settings_game.game_creation.landscape, &_cheats.switch_climate.been_used,   &ClickChangeClimateCheat },
src/company_cmd.cpp
Show inline comments
 
@@ -128,50 +128,50 @@ bool IsValidCompanyManagerFace(CompanyMa
 
	bool has_moustache   = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE,   ge) != 0;
 
	bool has_tie_earring = !HasBit(ge, GENDER_FEMALE) || GetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge) != 0;
 
	bool has_glasses     = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
 

	
 
	if (!AreCompanyManagerFaceBitsValid(cmf, CMFV_EYE_COLOUR, ge)) return false;
 
	for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
 
		switch (cmfv) {
 
			case CMFV_MOUSTACHE:   if (!has_moustache)   continue; break;
 
			case CMFV_LIPS:        // FALL THROUGH
 
			case CMFV_NOSE:        if (has_moustache)    continue; break;
 
			case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
 
			case CMFV_GLASSES:     if (!has_glasses)     continue; break;
 
			default: break;
 
		}
 
		if (!AreCompanyManagerFaceBitsValid(cmf, cmfv, ge)) return false;
 
	}
 

	
 
	return true;
 
}
 

	
 
void InvalidateCompanyWindows(const Company *company)
 
{
 
	CompanyID cid = company->index;
 

	
 
	if (cid == _local_company) InvalidateWindow(WC_STATUS_BAR, 0);
 
	InvalidateWindow(WC_FINANCES, cid);
 
	if (cid == _local_company) SetWindowDirty(WC_STATUS_BAR, 0);
 
	SetWindowDirty(WC_FINANCES, cid);
 
}
 

	
 
bool CheckCompanyHasMoney(CommandCost cost)
 
{
 
	if (cost.GetCost() > 0) {
 
		const Company *c = Company::GetIfValid(_current_company);
 
		if (c != NULL && cost.GetCost() > c->money) {
 
			SetDParam(0, cost.GetCost());
 
			_error_message = STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY;
 
			return false;
 
		}
 
	}
 
	return true;
 
}
 

	
 
static void SubtractMoneyFromAnyCompany(Company *c, CommandCost cost)
 
{
 
	if (cost.GetCost() == 0) return;
 
	assert(cost.GetExpensesType() != INVALID_EXPENSES);
 

	
 
	c->money -= cost.GetCost();
 
	c->yearly_expenses[0][cost.GetExpensesType()] += cost.GetCost();
 

	
 
	if (HasBit(1 << EXPENSES_TRAIN_INC    |
 
@@ -438,51 +438,51 @@ Company *DoStartupNewCompany(bool is_ai,
 
		c = new Company(STR_SV_UNNAMED, is_ai);
 
	} else {
 
		if (Company::IsValidID(company)) return NULL;
 
		c = new (company) Company(STR_SV_UNNAMED, is_ai);
 
	}
 

	
 
	c->colour = colour;
 

	
 
	ResetCompanyLivery(c);
 
	_company_colours[c->index] = (Colours)c->colour;
 

	
 
	c->money = c->current_loan = 100000;
 

	
 
	c->share_owners[0] = c->share_owners[1] = c->share_owners[2] = c->share_owners[3] = INVALID_OWNER;
 

	
 
	c->avail_railtypes = GetCompanyRailtypes(c->index);
 
	c->avail_roadtypes = GetCompanyRoadtypes(c->index);
 
	c->inaugurated_year = _cur_year;
 
	RandomCompanyManagerFaceBits(c->face, (GenderEthnicity)Random(), false); // create a random company manager face
 

	
 
	SetDefaultCompanySettings(c->index);
 

	
 
	GeneratePresidentName(c);
 

	
 
	InvalidateWindow(WC_GRAPH_LEGEND, 0);
 
	InvalidateWindow(WC_TOOLBAR_MENU, 0);
 
	InvalidateWindow(WC_CLIENT_LIST, 0);
 
	SetWindowDirty(WC_GRAPH_LEGEND, 0);
 
	SetWindowDirty(WC_TOOLBAR_MENU, 0);
 
	SetWindowDirty(WC_CLIENT_LIST, 0);
 

	
 
	if (is_ai && (!_networking || _network_server)) AI::StartNew(c->index);
 

	
 
	c->num_engines = CallocT<uint16>(Engine::GetPoolSize());
 

	
 
	return c;
 
}
 

	
 
void StartupCompanies()
 
{
 
	_next_competitor_start = 0;
 
}
 

	
 
static void MaybeStartNewCompany()
 
{
 
#ifdef ENABLE_NETWORK
 
	if (_networking && Company::GetNumItems() >= _settings_client.network.max_companies) return;
 
#endif /* ENABLE_NETWORK */
 

	
 
	Company *c;
 

	
 
	/* count number of competitors */
 
	uint n = 0;
 
	FOR_ALL_COMPANIES(c) {
 
@@ -574,49 +574,49 @@ void OnTick_Companies()
 
	if (c != NULL) {
 
		if (c->name_1 != 0) GenerateCompanyName(c);
 
		if (c->bankrupt_asked != 0) HandleBankruptcyTakeover(c);
 
	}
 

	
 
	if (_next_competitor_start == 0) {
 
		_next_competitor_start = AI::GetStartNextTime() * DAY_TICKS;
 
	}
 

	
 
	if (AI::CanStartNew() && _game_mode != GM_MENU && --_next_competitor_start == 0) {
 
		MaybeStartNewCompany();
 
	}
 

	
 
	_cur_company_tick_index = (_cur_company_tick_index + 1) % MAX_COMPANIES;
 
}
 

	
 
void CompaniesYearlyLoop()
 
{
 
	Company *c;
 

	
 
	/* Copy statistics */
 
	FOR_ALL_COMPANIES(c) {
 
		memmove(&c->yearly_expenses[1], &c->yearly_expenses[0], sizeof(c->yearly_expenses) - sizeof(c->yearly_expenses[0]));
 
		memset(&c->yearly_expenses[0], 0, sizeof(c->yearly_expenses[0]));
 
		InvalidateWindow(WC_FINANCES, c->index);
 
		SetWindowDirty(WC_FINANCES, c->index);
 
	}
 

	
 
	if (_settings_client.gui.show_finances && _local_company != COMPANY_SPECTATOR) {
 
		ShowCompanyFinances(_local_company);
 
		c = Company::Get(_local_company);
 
		if (c->num_valid_stat_ent > 5 && c->old_economy[0].performance_history < c->old_economy[4].performance_history) {
 
			SndPlayFx(SND_01_BAD_YEAR);
 
		} else {
 
			SndPlayFx(SND_00_GOOD_YEAR);
 
		}
 
	}
 
}
 

	
 
/** Change engine renewal parameters
 
 * @param tile unused
 
 * @param flags operation to perform
 
 * @param p1 packed data
 
 *   - bits 16-31 = engine group
 
 * @param p2 packed data
 
 *   - bits  0-15 = old engine type
 
 *   - bits 16-31 = new engine type
 
 * @param text unused
 
 */
 
CommandCost CmdSetAutoReplace(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
src/company_gui.cpp
Show inline comments
 
@@ -1644,64 +1644,64 @@ struct CompanyWindow : Window
 
			case CW_WIDGET_COLOUR_SCHEME:
 
				if (BringWindowToFrontById(WC_COMPANY_COLOUR, this->window_number)) break;
 
				new SelectCompanyLiveryWindow(&_select_company_livery_desc, (CompanyID)this->window_number);
 
				break;
 

	
 
			case CW_WIDGET_PRESIDENT_NAME:
 
				this->query_widget = CW_WIDGET_PRESIDENT_NAME;
 
				SetDParam(0, this->window_number);
 
				ShowQueryString(STR_PRESIDENT_NAME, STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION, MAX_LENGTH_PRESIDENT_NAME_BYTES, MAX_LENGTH_PRESIDENT_NAME_PIXELS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT);
 
				break;
 

	
 
			case CW_WIDGET_COMPANY_NAME:
 
				this->query_widget = CW_WIDGET_COMPANY_NAME;
 
				SetDParam(0, this->window_number);
 
				ShowQueryString(STR_COMPANY_NAME, STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION, MAX_LENGTH_COMPANY_NAME_BYTES, MAX_LENGTH_COMPANY_NAME_PIXELS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT);
 
				break;
 

	
 
			case CW_WIDGET_BUILD_VIEW_HQ: {
 
				TileIndex tile = Company::Get((CompanyID)this->window_number)->location_of_HQ;
 
				if (tile == INVALID_TILE) {
 
					if ((byte)this->window_number != _local_company) return;
 
					SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
 
					SetTileSelectSize(2, 2);
 
					this->LowerWidget(CW_WIDGET_BUILD_VIEW_HQ);
 
					this->InvalidateWidget(CW_WIDGET_BUILD_VIEW_HQ);
 
					this->SetWidgetDirty(CW_WIDGET_BUILD_VIEW_HQ);
 
				} else {
 
					if (_ctrl_pressed) {
 
						ShowExtraViewPortWindow(tile);
 
					} else {
 
						ScrollMainWindowToTile(tile);
 
					}
 
				}
 
				break;
 
			}
 

	
 
			case CW_WIDGET_RELOCATE_HQ:
 
				SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
 
				SetTileSelectSize(2, 2);
 
				this->LowerWidget(CW_WIDGET_RELOCATE_HQ);
 
				this->InvalidateWidget(CW_WIDGET_RELOCATE_HQ);
 
				this->SetWidgetDirty(CW_WIDGET_RELOCATE_HQ);
 
				break;
 

	
 
			case CW_WIDGET_BUY_SHARE:
 
				DoCommandP(0, this->window_number, 0, CMD_BUY_SHARE_IN_COMPANY | CMD_MSG(STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS));
 
				break;
 

	
 
			case CW_WIDGET_SELL_SHARE:
 
				DoCommandP(0, this->window_number, 0, CMD_SELL_SHARE_IN_COMPANY | CMD_MSG(STR_ERROR_CAN_T_SELL_25_SHARE_IN));
 
				break;
 

	
 
#ifdef ENABLE_NETWORK
 
			case CW_WIDGET_COMPANY_PASSWORD:
 
				if (this->window_number == _local_company) ShowNetworkCompanyPasswordWindow(this);
 
				break;
 

	
 
			case CW_WIDGET_COMPANY_JOIN: {
 
				this->query_widget = CW_WIDGET_COMPANY_JOIN;
 
				CompanyID company = (CompanyID)this->window_number;
 
				if (_network_server) {
 
					NetworkServerDoMove(CLIENT_ID_SERVER, company);
 
					MarkWholeScreenDirty();
 
				} else if (NetworkCompanyIsPassworded(company)) {
 
					/* ask for the password */
 
					ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION, 20, 180, this, CS_ALPHANUMERAL, QSF_NONE);
src/console_cmds.cpp
Show inline comments
 
@@ -362,49 +362,49 @@ DEF_CONSOLE_CMD(ConPrintWorkingDirectory
 
	const char *path;
 

	
 
	if (argc == 0) {
 
		IConsoleHelp("Print out the current working directory. Usage: 'pwd'");
 
		return true;
 
	}
 

	
 
	/* XXX - Workaround for broken file handling */
 
	FiosGetSavegameList(SLD_LOAD_GAME);
 
	FiosFreeSavegameList();
 

	
 
	FiosGetDescText(&path, NULL);
 
	IConsolePrint(CC_DEFAULT, path);
 
	return true;
 
}
 

	
 
DEF_CONSOLE_CMD(ConClearBuffer)
 
{
 
	if (argc == 0) {
 
		IConsoleHelp("Clear the console buffer. Usage: 'clear'");
 
		return true;
 
	}
 

	
 
	IConsoleClearBuffer();
 
	InvalidateWindow(WC_CONSOLE, 0);
 
	SetWindowDirty(WC_CONSOLE, 0);
 
	return true;
 
}
 

	
 

	
 
/**********************************
 
 * Network Core Console Commands
 
 **********************************/
 
#ifdef ENABLE_NETWORK
 

	
 
DEF_CONSOLE_CMD(ConBan)
 
{
 
	NetworkClientInfo *ci;
 
	const char *banip = NULL;
 
	ClientID client_id;
 

	
 
	if (argc == 0) {
 
		IConsoleHelp("Ban a client from a network game. Usage: 'ban <ip | client-id>'");
 
		IConsoleHelp("For client-id's, see the command 'clients'");
 
		IConsoleHelp("If the client is no longer online, you can still ban his/her IP");
 
		return true;
 
	}
 

	
 
	if (argc != 2) return false;
 

	
src/console_gui.cpp
Show inline comments
 
@@ -120,49 +120,49 @@ struct IConsoleLine {
 
	}
 
};
 

	
 
/* static */ IConsoleLine *IConsoleLine::front = NULL;
 
/* static */ int IConsoleLine::size  = 0;
 

	
 

	
 
/* ** main console cmd buffer ** */
 
static Textbuf _iconsole_cmdline;
 
static char *_iconsole_history[ICON_HISTORY_SIZE];
 
static byte _iconsole_historypos;
 
IConsoleModes _iconsole_mode;
 

	
 
/* *************** *
 
 *  end of header  *
 
 * *************** */
 

	
 
static void IConsoleClearCommand()
 
{
 
	memset(_iconsole_cmdline.buf, 0, ICON_CMDLN_SIZE);
 
	_iconsole_cmdline.size = 1; // only terminating zero
 
	_iconsole_cmdline.width = 0;
 
	_iconsole_cmdline.caretpos = 0;
 
	_iconsole_cmdline.caretxoffs = 0;
 
	InvalidateWindow(WC_CONSOLE, 0);
 
	SetWindowDirty(WC_CONSOLE, 0);
 
}
 

	
 
static inline void IConsoleResetHistoryPos() {_iconsole_historypos = ICON_HISTORY_SIZE - 1;}
 

	
 

	
 
static void IConsoleHistoryAdd(const char *cmd);
 
static void IConsoleHistoryNavigate(int direction);
 

	
 
/** Widgets of the console window. */
 
enum ConsoleWidgets {
 
	CW_BACKGROUND, ///< Background of the console
 
};
 

	
 
static const struct NWidgetPart _nested_console_window_widgets[] = {
 
	NWidget(WWT_EMPTY, INVALID_COLOUR, CW_BACKGROUND), SetResize(1, 1),
 
};
 

	
 
static const WindowDesc _console_window_desc(
 
	0, 0, 0, 0, 0, 0,
 
	WC_CONSOLE, WC_NONE,
 
	0,
 
	NULL, _nested_console_window_widgets, lengthof(_nested_console_window_widgets)
 
);
 

	
 
@@ -449,26 +449,26 @@ static void IConsoleHistoryNavigate(int 
 
	if (direction < 0) {
 
		while (i > 0 && _iconsole_history[i] == NULL) i--;
 
	}
 

	
 
	_iconsole_historypos = i;
 
	IConsoleClearCommand();
 
	/* copy history to 'command prompt / bash' */
 
	assert(_iconsole_history[i] != NULL && IsInsideMM(i, 0, ICON_HISTORY_SIZE));
 
	ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_history[i], _iconsole_cmdline.maxsize);
 
	UpdateTextBufferSize(&_iconsole_cmdline);
 
}
 

	
 
/**
 
 * Handle the printing of text entered into the console or redirected there
 
 * by any other means. Text can be redirected to other clients in a network game
 
 * as well as to a logfile. If the network server is a dedicated server, all activities
 
 * are also logged. All lines to print are added to a temporary buffer which can be
 
 * used as a history to print them onscreen
 
 * @param colour_code the colour of the command. Red in case of errors, etc.
 
 * @param string the message entered or output on the console (notice, error, etc.)
 
 */
 
void IConsoleGUIPrint(ConsoleColour colour_code, char *str)
 
{
 
	new IConsoleLine(str, (TextColour)colour_code);
 
	InvalidateWindow(WC_CONSOLE, 0);
 
	SetWindowDirty(WC_CONSOLE, 0);
 
}
src/date.cpp
Show inline comments
 
@@ -219,73 +219,73 @@ static void OnNewYear()
 
		 *  all of them if the date is set back, else those messages will hang for ever */
 
		NetworkInitChatMessage();
 
#endif /* ENABLE_NETWORK */
 
	}
 

	
 
	if (_settings_client.gui.auto_euro) CheckSwitchToEuro();
 
}
 

	
 
/**
 
 * Runs various procedures that have to be done monthly
 
 */
 
static void OnNewMonth()
 
{
 
	if (_debug_desync_level > 2) {
 
		char name[MAX_PATH];
 
		snprintf(name, lengthof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
 
		SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR);
 
	}
 

	
 
	if (_settings_client.gui.autosave != 0 && (_cur_month % _autosave_months[_settings_client.gui.autosave]) == 0) {
 
		_do_autosave = true;
 
		RedrawAutosave();
 
	}
 

	
 
	InvalidateWindowClasses(WC_CHEATS);
 
	SetWindowClassesDirty(WC_CHEATS);
 
	CompaniesMonthlyLoop();
 
	SubsidyMonthlyLoop();
 
	EnginesMonthlyLoop();
 
	TownsMonthlyLoop();
 
	IndustryMonthlyLoop();
 
	StationMonthlyLoop();
 
#ifdef ENABLE_NETWORK
 
	if (_network_server) NetworkServerMonthlyLoop();
 
#endif /* ENABLE_NETWORK */
 
}
 

	
 
/**
 
 * Runs various procedures that have to be done daily
 
 */
 
static void OnNewDay()
 
{
 
#ifdef ENABLE_NETWORK
 
	NetworkChatMessageDailyLoop();
 
#endif /* ENABLE_NETWORK */
 

	
 
	DisasterDailyLoop();
 
	IndustryDailyLoop();
 

	
 
	InvalidateWindowWidget(WC_STATUS_BAR, 0, 0);
 
	SetWindowWidgetDirty(WC_STATUS_BAR, 0, 0);
 
	EnginesDailyLoop();
 
}
 

	
 
/**
 
 * Increases the tick counter, increases date  and possibly calls
 
 * procedures that have to be called daily, monthly or yearly.
 
 */
 
void IncreaseDate()
 
{
 
	/* increase day, and check if a new day is there? */
 
	_tick_counter++;
 

	
 
	if (_game_mode == GM_MENU) return;
 

	
 
	_date_fract++;
 
	if (_date_fract < DAY_TICKS) return;
 
	_date_fract = 0;
 

	
 
	/* increase day counter and call various daily loops */
 
	_date++;
 
	OnNewDay();
 

	
 
	YearMonthDay ymd;
 

	
src/depot_gui.cpp
Show inline comments
 
@@ -705,49 +705,49 @@ struct DepotWindow : Window {
 
	{
 
		if (this->generate_list) {
 
			/* Generate the vehicle list
 
			 * It's ok to use the wagon pointers for non-trains as they will be ignored */
 
			BuildDepotVehicleList(this->type, this->window_number, &this->vehicle_list, &this->wagon_list);
 
			this->generate_list = false;
 
			DepotSortList(&this->vehicle_list);
 
		}
 
		this->DrawDepotWindow();
 
	}
 

	
 
	virtual void OnClick(Point pt, int widget)
 
	{
 
		switch (widget) {
 
			case DEPOT_WIDGET_MATRIX: // List
 
				this->DepotClick(pt.x, pt.y);
 
				break;
 

	
 
			case DEPOT_WIDGET_BUILD: // Build vehicle
 
				ResetObjectToPlace();
 
				ShowBuildVehicleWindow(this->window_number, this->type);
 
				break;
 

	
 
			case DEPOT_WIDGET_CLONE: // Clone button
 
				this->InvalidateWidget(DEPOT_WIDGET_CLONE);
 
				this->SetWidgetDirty(DEPOT_WIDGET_CLONE);
 
				this->ToggleWidgetLoweredState(DEPOT_WIDGET_CLONE);
 

	
 
				if (this->IsWidgetLowered(DEPOT_WIDGET_CLONE)) {
 
					static const CursorID clone_icons[] = {
 
						SPR_CURSOR_CLONE_TRAIN, SPR_CURSOR_CLONE_ROADVEH,
 
						SPR_CURSOR_CLONE_SHIP, SPR_CURSOR_CLONE_AIRPLANE
 
					};
 

	
 
					_place_clicked_vehicle = NULL;
 
					SetObjectToPlaceWnd(clone_icons[this->type], PAL_NONE, HT_RECT, this);
 
				} else {
 
					ResetObjectToPlace();
 
				}
 
					break;
 

	
 
			case DEPOT_WIDGET_LOCATION:
 
				if (_ctrl_pressed) {
 
					ShowExtraViewPortWindow(this->window_number);
 
				} else {
 
					ScrollMainWindowToTile(this->window_number);
 
				}
 
				break;
 

	
 
			case DEPOT_WIDGET_STOP_ALL:
 
@@ -829,53 +829,53 @@ struct DepotWindow : Window {
 

	
 
			/* Show tooltip window */
 
			uint64 args[2];
 
			args[0] = (whole_chain ? num : v->engine_type);
 
			args[1] = (uint64)(size_t)details;
 
			GuiShowTooltips(whole_chain ? STR_DEPOT_VEHICLE_TOOLTIP_CHAIN : STR_DEPOT_VEHICLE_TOOLTIP, 2, args);
 
		} else {
 
			/* Show tooltip help */
 
			GuiShowTooltips(STR_DEPOT_TRAIN_LIST_TOOLTIP + this->type);
 
		}
 
	}
 

	
 

	
 
	virtual void OnPlaceObject(Point pt, TileIndex tile)
 
	{
 
		const Vehicle *v = CheckMouseOverVehicle();
 

	
 
		if (v != NULL) this->HandleCloneVehClick(v);
 
	}
 

	
 
	virtual void OnPlaceObjectAbort()
 
	{
 
		/* abort clone */
 
		this->RaiseWidget(DEPOT_WIDGET_CLONE);
 
		this->InvalidateWidget(DEPOT_WIDGET_CLONE);
 
		this->SetWidgetDirty(DEPOT_WIDGET_CLONE);
 

	
 
		/* abort drag & drop */
 
		this->sel = INVALID_VEHICLE;
 
		this->InvalidateWidget(DEPOT_WIDGET_MATRIX);
 
		this->SetWidgetDirty(DEPOT_WIDGET_MATRIX);
 
	};
 

	
 
	/* check if a vehicle in a depot was clicked.. */
 
	virtual void OnMouseLoop()
 
	{
 
		const Vehicle *v = _place_clicked_vehicle;
 

	
 
		/* since OTTD checks all open depot windows, we will make sure that it triggers the one with a clicked clone button */
 
		if (v != NULL && this->IsWidgetLowered(DEPOT_WIDGET_CLONE)) {
 
			_place_clicked_vehicle = NULL;
 
			this->HandleCloneVehClick(v);
 
		}
 
	}
 

	
 
	virtual void OnDragDrop(Point pt, int widget)
 
	{
 
		switch (widget) {
 
			case DEPOT_WIDGET_MATRIX: {
 
				const Vehicle *v = NULL;
 
				VehicleID sel = this->sel;
 

	
 
				this->sel = INVALID_VEHICLE;
 
				this->SetDirty();
 

	
 
@@ -914,69 +914,69 @@ struct DepotWindow : Window {
 

	
 
					int sell_cmd = (v->type == VEH_TRAIN && (widget == DEPOT_WIDGET_SELL_CHAIN || _ctrl_pressed)) ? 1 : 0;
 

	
 
					bool is_engine = (v->type != VEH_TRAIN || Train::From(v)->IsFrontEngine());
 

	
 
					if (is_engine) {
 
						_backup_orders_tile = v->tile;
 
						BackupVehicleOrders(v);
 
					}
 

	
 
					if (!DoCommandP(v->tile, v->index, sell_cmd, GetCmdSellVeh(v->type)) && is_engine) _backup_orders_tile = 0;
 
				}
 
				break;
 
			default:
 
				this->sel = INVALID_VEHICLE;
 
				this->SetDirty();
 
		}
 
		_cursor.vehchain = false;
 
	}
 

	
 
	virtual void OnTimeout()
 
	{
 
		if (!this->IsWidgetDisabled(DEPOT_WIDGET_SELL)) {
 
			this->RaiseWidget(DEPOT_WIDGET_SELL);
 
			this->InvalidateWidget(DEPOT_WIDGET_SELL);
 
			this->SetWidgetDirty(DEPOT_WIDGET_SELL);
 
		}
 
		if (!this->IsWidgetDisabled(DEPOT_WIDGET_SELL_CHAIN)) {
 
			this->RaiseWidget(DEPOT_WIDGET_SELL_CHAIN);
 
			this->InvalidateWidget(DEPOT_WIDGET_SELL_CHAIN);
 
			this->SetWidgetDirty(DEPOT_WIDGET_SELL_CHAIN);
 
		}
 
	}
 

	
 
	virtual void OnResize(Point delta)
 
	{
 
		this->vscroll.UpdateCapacity(delta.y / (int)this->resize.step_height);
 
		this->hscroll.UpdateCapacity(delta.x / (int)this->resize.step_width);
 
		this->widget[DEPOT_WIDGET_MATRIX].data = (this->vscroll.GetCapacity() << MAT_ROW_START) + ((this->type == VEH_TRAIN ? 1 : this->hscroll.GetCapacity()) << MAT_COL_START);
 
		this->ResizeDepotButtons();
 
	}
 

	
 
	virtual EventState OnCTRLStateChange()
 
	{
 
		if (this->sel != INVALID_VEHICLE) {
 
			_cursor.vehchain = _ctrl_pressed;
 
			this->InvalidateWidget(DEPOT_WIDGET_MATRIX);
 
			this->SetWidgetDirty(DEPOT_WIDGET_MATRIX);
 
			return ES_HANDLED;
 
		}
 

	
 
		return ES_NOT_HANDLED;
 
	}
 
};
 

	
 
static void DepotSellAllConfirmationCallback(Window *win, bool confirmed)
 
{
 
	if (confirmed) {
 
		DepotWindow *w = (DepotWindow*)win;
 
		TileIndex tile = w->window_number;
 
		byte vehtype = w->type;
 
		DoCommandP(tile, vehtype, 0, CMD_DEPOT_SELL_ALL_VEHICLES);
 
	}
 
}
 

	
 
/** Opens a depot window
 
 * @param tile The tile where the depot/hangar is located
 
 * @param type The type of vehicles in the depot
 
 */
 
void ShowDepotWindow(TileIndex tile, VehicleType type)
 
{
 
	if (BringWindowToFrontById(WC_VEHICLE_DEPOT, tile) != NULL) return;
src/economy.cpp
Show inline comments
 
@@ -260,49 +260,49 @@ int UpdateCompanyRatingAndValue(Company 
 
		int total_score = 0;
 
		int s;
 
		score = 0;
 
		for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) {
 
			/* Skip the total */
 
			if (i == SCORE_TOTAL) continue;
 
			/*  Check the score */
 
			s = Clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].score / _score_info[i].needed;
 
			score += s;
 
			total_score += _score_info[i].score;
 
		}
 

	
 
		_score_part[owner][SCORE_TOTAL] = score;
 

	
 
		/*  We always want the score scaled to SCORE_MAX (1000) */
 
		if (total_score != SCORE_MAX) score = score * SCORE_MAX / total_score;
 
	}
 

	
 
	if (update) {
 
		c->old_economy[0].performance_history = score;
 
		UpdateCompanyHQ(c, score);
 
		c->old_economy[0].company_value = CalculateCompanyValue(c);
 
	}
 

	
 
	InvalidateWindow(WC_PERFORMANCE_DETAIL, 0);
 
	SetWindowDirty(WC_PERFORMANCE_DETAIL, 0);
 
	return score;
 
}
 

	
 
/*  use INVALID_OWNER as new_owner to delete the company. */
 
void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner)
 
{
 
	Town *t;
 
	CompanyID old = _current_company;
 

	
 
	assert(old_owner != new_owner);
 

	
 
	{
 
		Company *c;
 
		uint i;
 

	
 
		/* See if the old_owner had shares in other companies */
 
		_current_company = old_owner;
 
		FOR_ALL_COMPANIES(c) {
 
			for (i = 0; i < 4; i++) {
 
				if (c->share_owners[i] == old_owner) {
 
					/* Sell his shares */
 
					CommandCost res = DoCommand(0, c->index, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
 
					/* Because we are in a DoCommand, we can't just execute an other one and
 
					 *  expect the money to be removed. We need to do it ourself! */
 
@@ -555,54 +555,54 @@ static void CompaniesGenStatistics()
 
	Station *st;
 
	Company *c;
 

	
 
	FOR_ALL_STATIONS(st) {
 
		_current_company = st->owner;
 
		CommandCost cost(EXPENSES_PROPERTY, _price.station_value >> 1);
 
		SubtractMoneyFromCompany(cost);
 
	}
 

	
 
	if (!HasBit(1 << 0 | 1 << 3 | 1 << 6 | 1 << 9, _cur_month))
 
		return;
 

	
 
	FOR_ALL_COMPANIES(c) {
 
		memmove(&c->old_economy[1], &c->old_economy[0], sizeof(c->old_economy) - sizeof(c->old_economy[0]));
 
		c->old_economy[0] = c->cur_economy;
 
		memset(&c->cur_economy, 0, sizeof(c->cur_economy));
 

	
 
		if (c->num_valid_stat_ent != MAX_HISTORY_MONTHS) c->num_valid_stat_ent++;
 

	
 
		UpdateCompanyRatingAndValue(c, true);
 
		if (c->block_preview != 0) c->block_preview--;
 
		CompanyCheckBankrupt(c);
 
	}
 

	
 
	InvalidateWindow(WC_INCOME_GRAPH, 0);
 
	InvalidateWindow(WC_OPERATING_PROFIT, 0);
 
	InvalidateWindow(WC_DELIVERED_CARGO, 0);
 
	InvalidateWindow(WC_PERFORMANCE_HISTORY, 0);
 
	InvalidateWindow(WC_COMPANY_VALUE, 0);
 
	InvalidateWindow(WC_COMPANY_LEAGUE, 0);
 
	SetWindowDirty(WC_INCOME_GRAPH, 0);
 
	SetWindowDirty(WC_OPERATING_PROFIT, 0);
 
	SetWindowDirty(WC_DELIVERED_CARGO, 0);
 
	SetWindowDirty(WC_PERFORMANCE_HISTORY, 0);
 
	SetWindowDirty(WC_COMPANY_VALUE, 0);
 
	SetWindowDirty(WC_COMPANY_LEAGUE, 0);
 
}
 

	
 
/**
 
 * Add monthly inflation
 
 * @param check_year Shall the inflation get stopped after 170 years?
 
 */
 
void AddInflation(bool check_year)
 
{
 
	/* The cargo payment inflation differs from the normal inflation, so the
 
	 * relative amount of money you make with a transport decreases slowly over
 
	 * the 170 years. After a few hundred years we reach a level in which the
 
	 * games will become unplayable as the maximum income will be less than
 
	 * the minimum running cost.
 
	 *
 
	 * Furthermore there are a lot of inflation related overflows all over the
 
	 * place. Solving them is hardly possible because inflation will always
 
	 * reach the overflow threshold some day. So we'll just perform the
 
	 * inflation mechanism during the first 170 years (the amount of years that
 
	 * one had in the original TTD) and stop doing the inflation after that
 
	 * because it only causes problems that can't be solved nicely and the
 
	 * inflation doesn't add anything after that either; it even makes playing
 
	 * it impossible due to the diverging cost and income rates.
 
	 */
 
	if (check_year && (_cur_year - _settings_game.game_creation.starting_year) >= (ORIGINAL_MAX_YEAR - ORIGINAL_BASE_YEAR)) return;
 
@@ -649,52 +649,52 @@ void RecomputePrices()
 
			price = price * 9 >> 3;
 
		}
 

	
 
		/* Apply inflation */
 
		price = (int64)price * _economy.inflation_prices;
 

	
 
		/* Apply newgrf modifiers, and remove fractional part of inflation */
 
		int shift = _price_base_multiplier[i] - 8 - 16;
 
		if (shift >= 0) {
 
			price <<= shift;
 
		} else {
 
			price >>= -shift;
 
		}
 

	
 
		/* Store value */
 
		((Money *)&_price)[i] = price;
 
	}
 

	
 
	/* Setup cargo payment */
 
	CargoSpec *cs;
 
	FOR_ALL_CARGOSPECS(cs) {
 
		cs->current_payment = ((int64)cs->initial_payment * _economy.inflation_payment) >> 16;
 
	}
 

	
 
	InvalidateWindowClasses(WC_BUILD_VEHICLE);
 
	InvalidateWindowClasses(WC_REPLACE_VEHICLE);
 
	InvalidateWindowClasses(WC_VEHICLE_DETAILS);
 
	InvalidateWindow(WC_PAYMENT_RATES, 0);
 
	SetWindowClassesDirty(WC_BUILD_VEHICLE);
 
	SetWindowClassesDirty(WC_REPLACE_VEHICLE);
 
	SetWindowClassesDirty(WC_VEHICLE_DETAILS);
 
	SetWindowDirty(WC_PAYMENT_RATES, 0);
 
}
 

	
 
static void CompaniesPayInterest()
 
{
 
	const Company *c;
 

	
 
	FOR_ALL_COMPANIES(c) {
 
		_current_company = c->index;
 

	
 
		/* Over a year the paid interest should be "loan * interest percentage",
 
		 * but... as that number is likely not dividable by 12 (pay each month),
 
		 * one needs to account for that in the monthly fee calculations.
 
		 * To easily calculate what one should pay "this" month, you calculate
 
		 * what (total) should have been paid up to this month and you substract
 
		 * whatever has been paid in the previous months. This will mean one month
 
		 * it'll be a bit more and the other it'll be a bit less than the average
 
		 * monthly fee, but on average it will be exact. */
 
		Money yearly_fee = c->current_loan * _economy.interest_rate / 100;
 
		Money up_to_previous_month = yearly_fee * _cur_month / 12;
 
		Money up_to_this_month = yearly_fee * (_cur_month + 1) / 12;
 

	
 
		SubtractMoneyFromCompany(CommandCost(EXPENSES_LOAN_INT, up_to_this_month - up_to_previous_month));
 

	
 
		SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, _price.station_value >> 2));
 
@@ -945,49 +945,49 @@ static Money DeliverGoods(int num_pieces
 
			default: profit *= 4; break;
 
		}
 
	}
 

	
 
	return profit;
 
}
 

	
 
/**
 
 * Inform the industry about just delivered cargo
 
 * DeliverGoodsToIndustry() silently incremented incoming_cargo_waiting, now it is time to do something with the new cargo.
 
 * @param i The industry to process
 
 */
 
static void TriggerIndustryProduction(Industry *i)
 
{
 
	const IndustrySpec *indspec = GetIndustrySpec(i->type);
 
	uint16 callback = indspec->callback_flags;
 

	
 
	i->was_cargo_delivered = true;
 
	i->last_cargo_accepted_at = _date;
 

	
 
	if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(callback, CBM_IND_PRODUCTION_256_TICKS)) {
 
		if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) {
 
			IndustryProductionCallback(i, 0);
 
		} else {
 
			InvalidateWindow(WC_INDUSTRY_VIEW, i->index);
 
			SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
 
		}
 
	} else {
 
		for (uint cargo_index = 0; cargo_index < lengthof(i->incoming_cargo_waiting); cargo_index++) {
 
			uint cargo_waiting = i->incoming_cargo_waiting[cargo_index];
 
			if (cargo_waiting == 0) continue;
 

	
 
			i->produced_cargo_waiting[0] = min(i->produced_cargo_waiting[0] + (cargo_waiting * indspec->input_cargo_multiplier[cargo_index][0] / 256), 0xFFFF);
 
			i->produced_cargo_waiting[1] = min(i->produced_cargo_waiting[1] + (cargo_waiting * indspec->input_cargo_multiplier[cargo_index][1] / 256), 0xFFFF);
 

	
 
			i->incoming_cargo_waiting[cargo_index] = 0;
 
		}
 
	}
 

	
 
	TriggerIndustry(i, INDUSTRY_TRIGGER_RECEIVED_CARGO);
 
	StartStopIndustryTileAnimation(i, IAT_INDUSTRY_RECEIVED_CARGO);
 
}
 

	
 
/**
 
 * Makes us a new cargo payment helper.
 
 * @param front The front of the train
 
 * @param destinations List to add the destinations of 'our' cargo to
 
 */
 
CargoPayment::CargoPayment(Vehicle *front) :
 
	front(front),
 
@@ -1333,55 +1333,55 @@ static void LoadUnloadVehicle(Vehicle *v
 
	/* Calculate the loading indicator fill percent and display
 
	 * In the Game Menu do not display indicators
 
	 * If _settings_client.gui.loading_indicators == 2, show indicators (bool can be promoted to int as 0 or 1 - results in 2 > 0,1 )
 
	 * if _settings_client.gui.loading_indicators == 1, _local_company must be the owner or must be a spectator to show ind., so 1 > 0
 
	 * if _settings_client.gui.loading_indicators == 0, do not display indicators ... 0 is never greater than anything
 
	 */
 
	if (_game_mode != GM_MENU && (_settings_client.gui.loading_indicators > (uint)(v->owner != _local_company && _local_company != COMPANY_SPECTATOR))) {
 
		StringID percent_up_down = STR_NULL;
 
		int percent = CalcPercentVehicleFilled(v, &percent_up_down);
 
		if (v->fill_percent_te_id == INVALID_TE_ID) {
 
			v->fill_percent_te_id = ShowFillingPercent(v->x_pos, v->y_pos, v->z_pos + 20, percent, percent_up_down);
 
		} else {
 
			UpdateFillingPercent(v->fill_percent_te_id, percent, percent_up_down);
 
		}
 
	}
 

	
 
	/* Always wait at least 1, otherwise we'll wait 'infinitively' long. */
 
	v->load_unload_time_rem = max(1, unloading_time);
 

	
 
	if (completely_emptied) {
 
		TriggerVehicle(v, VEHICLE_TRIGGER_EMPTY);
 
	}
 

	
 
	if (result != 0) {
 
		InvalidateWindow(GetWindowClassForVehicleType(v->type), v->owner);
 
		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
		SetWindowDirty(GetWindowClassForVehicleType(v->type), v->owner);
 
		SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
 

	
 
		st->MarkTilesDirty(true);
 
		v->MarkDirty();
 

	
 
		if (result & 2) InvalidateWindow(WC_STATION_VIEW, last_visited);
 
		if (result & 2) SetWindowDirty(WC_STATION_VIEW, last_visited);
 
	}
 
}
 

	
 
/**
 
 * Load/unload the vehicles in this station according to the order
 
 * they entered.
 
 * @param st the station to do the loading/unloading for
 
 */
 
void LoadUnloadStation(Station *st)
 
{
 
	/* No vehicle is here... */
 
	if (st->loading_vehicles.empty()) return;
 

	
 
	int cargo_left[NUM_CARGO];
 

	
 
	for (uint i = 0; i < NUM_CARGO; i++) cargo_left[i] = st->goods[i].cargo.Count();
 

	
 
	std::list<Vehicle *>::iterator iter;
 
	for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
 
		Vehicle *v = *iter;
 
		if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) LoadUnloadVehicle(v, cargo_left);
 
	}
 

	
 
	/* Call the production machinery of industries */
 
@@ -1474,79 +1474,79 @@ CommandCost CmdBuyShareInCompany(TileInd
 
	/* Protect new companies from hostile takeovers */
 
	if (_cur_year - c->inaugurated_year < 6) return_cmd_error(STR_ERROR_PROTECTED);
 

	
 
	/* Those lines are here for network-protection (clients can be slow) */
 
	if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 0) return cost;
 

	
 
	/* We can not buy out a real company (temporarily). TODO: well, enable it obviously */
 
	if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 1 && !c->is_ai) return cost;
 

	
 
	cost.AddCost(CalculateCompanyValue(c) >> 2);
 
	if (flags & DC_EXEC) {
 
		OwnerByte *b = c->share_owners;
 
		int i;
 

	
 
		while (*b != COMPANY_SPECTATOR) b++; // share owners is guaranteed to contain at least one COMPANY_SPECTATOR
 
		*b = _current_company;
 

	
 
		for (i = 0; c->share_owners[i] == _current_company;) {
 
			if (++i == 4) {
 
				c->bankrupt_value = 0;
 
				DoAcquireCompany(c);
 
				break;
 
			}
 
		}
 
		InvalidateWindow(WC_COMPANY, p1);
 
		SetWindowDirty(WC_COMPANY, p1);
 
	}
 
	return cost;
 
}
 

	
 
/** Sell shares in an opposing company.
 
 * @param tile unused
 
 * @param flags type of operation
 
 * @param p1 company to sell the shares from
 
 * @param p2 unused
 
 */
 
CommandCost CmdSellShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	Company *c = Company::GetIfValid(p1);
 

	
 
	/* Check if selling shares is allowed (protection against modified clients)
 
	 * Cannot sell own shares */
 
	if (c == NULL || !_settings_game.economy.allow_shares || _current_company == (CompanyID)p1) return CMD_ERROR;
 

	
 
	/* Those lines are here for network-protection (clients can be slow) */
 
	if (GetAmountOwnedBy(c, _current_company) == 0) return CommandCost();
 

	
 
	/* adjust it a little to make it less profitable to sell and buy */
 
	Money cost = CalculateCompanyValue(c) >> 2;
 
	cost = -(cost - (cost >> 7));
 

	
 
	if (flags & DC_EXEC) {
 
		OwnerByte *b = c->share_owners;
 
		while (*b != _current_company) b++; // share owners is guaranteed to contain company
 
		*b = COMPANY_SPECTATOR;
 
		InvalidateWindow(WC_COMPANY, p1);
 
		SetWindowDirty(WC_COMPANY, p1);
 
	}
 
	return CommandCost(EXPENSES_OTHER, cost);
 
}
 

	
 
/** Buy up another company.
 
 * When a competing company is gone bankrupt you get the chance to purchase
 
 * that company.
 
 * @todo currently this only works for AI companies
 
 * @param tile unused
 
 * @param flags type of operation
 
 * @param p1 company to buy up
 
 * @param p2 unused
 
 */
 
CommandCost CmdBuyCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	Company *c = Company::GetIfValid(p1);
 
	if (c == NULL) return CMD_ERROR;
 

	
 
	/* Disable takeovers when not asked */
 
	if (!HasBit(c->bankrupt_asked, _current_company)) return CMD_ERROR;
 

	
 
	/* Disable taking over the local company in single player */
 
	if (!_networking && _local_company == c->index) return CMD_ERROR;
 

	
src/engine.cpp
Show inline comments
 
@@ -415,50 +415,50 @@ static void CalcEngineReliability(Engine
 
			/* Early retirement is enabled and we're past the date... */
 
			e->company_avail = 0;
 
			AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type);
 
		}
 
	}
 

	
 
	if (age < e->duration_phase_1) {
 
		uint start = e->reliability_start;
 
		e->reliability = age * (e->reliability_max - start) / e->duration_phase_1 + start;
 
	} else if ((age -= e->duration_phase_1) < e->duration_phase_2 || _settings_game.vehicle.never_expire_vehicles || e->info.base_life == 0xFF) {
 
		/* We are at the peak of this engines life. It will have max reliability.
 
		 * This is also true if the engines never expire. They will not go bad over time */
 
		e->reliability = e->reliability_max;
 
	} else if ((age -= e->duration_phase_2) < e->duration_phase_3) {
 
		uint max = e->reliability_max;
 
		e->reliability = (int)age * (int)(e->reliability_final - max) / e->duration_phase_3 + max;
 
	} else {
 
		/* time's up for this engine.
 
		 * We will now completely retire this design */
 
		e->company_avail = 0;
 
		e->reliability = e->reliability_final;
 
		/* Kick this engine out of the lists */
 
		AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type);
 
	}
 
	InvalidateWindowClasses(WC_BUILD_VEHICLE); // Update to show the new reliability
 
	InvalidateWindowClasses(WC_REPLACE_VEHICLE);
 
	SetWindowClassesDirty(WC_BUILD_VEHICLE); // Update to show the new reliability
 
	SetWindowClassesDirty(WC_REPLACE_VEHICLE);
 
}
 

	
 
void SetYearEngineAgingStops()
 
{
 
	/* Determine last engine aging year, default to 2050 as previously. */
 
	_year_engine_aging_stops = 2050;
 

	
 
	const Engine *e;
 
	FOR_ALL_ENGINES(e) {
 
		const EngineInfo *ei = &e->info;
 

	
 
		/* Exclude certain engines */
 
		if (!HasBit(ei->climates, _settings_game.game_creation.landscape)) continue;
 
		if (e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON) continue;
 

	
 
		/* Base year ending date on half the model life */
 
		YearMonthDay ymd;
 
		ConvertDateToYMD(ei->base_intro + (ei->lifelength * DAYS_IN_LEAP_YEAR) / 2, &ymd);
 

	
 
		_year_engine_aging_stops = max(_year_engine_aging_stops, ymd.year);
 
	}
 
}
 

	
 
void StartupOneEngine(Engine *e, Date aging_date)
src/genworld_gui.cpp
Show inline comments
 
@@ -33,50 +33,50 @@
 
#include "querystring_gui.h"
 
#include "town.h"
 
#include "thread/thread.h"
 
#include "settings_func.h"
 

	
 
#include "table/strings.h"
 
#include "table/sprites.h"
 

	
 
/**
 
 * In what 'mode' the GenerateLandscapeWindowProc is.
 
 */
 
enum glwp_modes {
 
	GLWP_GENERATE,
 
	GLWP_HEIGHTMAP,
 
	GLWP_SCENARIO,
 
	GLWP_END
 
};
 

	
 
extern void SwitchToMode(SwitchMode new_mode);
 
extern void MakeNewgameSettingsLive();
 

	
 
static inline void SetNewLandscapeType(byte landscape)
 
{
 
	_settings_newgame.game_creation.landscape = landscape;
 
	InvalidateWindowClasses(WC_SELECT_GAME);
 
	InvalidateWindowClasses(WC_GENERATE_LANDSCAPE);
 
	SetWindowClassesDirty(WC_SELECT_GAME);
 
	SetWindowClassesDirty(WC_GENERATE_LANDSCAPE);
 
}
 

	
 
enum GenerateLandscapeWindowWidgets {
 
	GLAND_CLOSEBOX,
 
	GLAND_TITLEBAR,
 
	GLAND_BACKGROUND,
 

	
 
	GLAND_TEMPERATE,
 
	GLAND_ARCTIC,
 
	GLAND_TROPICAL,
 
	GLAND_TOYLAND,
 

	
 
	GLAND_MAPSIZE_X_TEXT,
 
	GLAND_MAPSIZE_X_PULLDOWN,
 
	GLAND_MAPSIZE_Y_TEXT,
 
	GLAND_MAPSIZE_Y_PULLDOWN,
 

	
 
	GLAND_TOWN_TEXT,
 
	GLAND_TOWN_PULLDOWN,
 
	GLAND_INDUSTRY_TEXT,
 
	GLAND_INDUSTRY_PULLDOWN,
 

	
 
	GLAND_RANDOM_TEXT,
 
	GLAND_RANDOM_EDITBOX,
 
@@ -781,49 +781,49 @@ struct GenerateLandscapeWindow : public 
 
				_settings_newgame.game_creation.water_borders = ToggleBit(_settings_newgame.game_creation.water_borders, BORDER_NE);
 
				break;
 

	
 
			case GLAND_WATER_SE:
 
				_settings_newgame.game_creation.water_borders = ToggleBit(_settings_newgame.game_creation.water_borders, BORDER_SE);
 
				break;
 

	
 
			case GLAND_WATER_SW:
 
				_settings_newgame.game_creation.water_borders = ToggleBit(_settings_newgame.game_creation.water_borders, BORDER_SW);
 
				break;
 

	
 
			case GLAND_BORDERS_RANDOM:
 
				_settings_newgame.game_creation.water_borders = (_settings_newgame.game_creation.water_borders == BORDERS_RANDOM) ? 0 : BORDERS_RANDOM;
 
				this->SetDirty();
 
				break;
 
		}
 
	}
 

	
 
	virtual void OnTimeout()
 
	{
 
		static const int raise_widgets[] = {GLAND_START_DATE_DOWN, GLAND_START_DATE_UP, GLAND_SNOW_LEVEL_UP, GLAND_SNOW_LEVEL_DOWN, WIDGET_LIST_END};
 
		for (const int *widget = raise_widgets; *widget != WIDGET_LIST_END; widget++) {
 
			if (this->IsWidgetLowered(*widget)) {
 
				this->RaiseWidget(*widget);
 
				this->InvalidateWidget(*widget);
 
				this->SetWidgetDirty(*widget);
 
			}
 
		}
 
	}
 

	
 
	virtual void OnMouseLoop()
 
	{
 
		this->HandleEditBox(GLAND_RANDOM_EDITBOX);
 
	}
 

	
 
	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 
	{
 
		EventState state;
 
		this->HandleEditBoxKey(GLAND_RANDOM_EDITBOX, key, keycode, state);
 
		/* the seed is unsigned, therefore atoi cannot be used.
 
		 * As UINT32_MAX is a 'magic' value (use random seed) it
 
		 * should not be possible to be entered into the input
 
		 * field; the generate seed button can be used instead. */
 
		_settings_newgame.game_creation.generation_seed = minu(strtoul(this->edit_str_buf, NULL, 10), UINT32_MAX - 1);
 
		return state;
 
	}
 

	
 
	virtual void OnDropdownSelect(int widget, int index)
 
	{
 
		switch (widget) {
 
@@ -859,54 +859,54 @@ struct GenerateLandscapeWindow : public 
 
				_game_mode = GM_MENU;
 
				IConsoleSetSetting("difficulty.terrain_type", index);
 
				_game_mode = old_gm;
 
				break;
 
			}
 

	
 
			case GLAND_WATER_PULLDOWN: {
 
				GameMode old_gm = _game_mode;
 
				_game_mode = GM_MENU;
 
				IConsoleSetSetting("difficulty.quantity_sea_lakes", index);
 
				_game_mode = old_gm;
 
				break;
 
			}
 
		}
 
		this->SetDirty();
 
	}
 

	
 
	virtual void OnQueryTextFinished(char *str)
 
	{
 
		if (!StrEmpty(str)) {
 
			int32 value = atoi(str);
 

	
 
			switch (this->widget_id) {
 
				case GLAND_START_DATE_TEXT:
 
					this->InvalidateWidget(GLAND_START_DATE_TEXT);
 
					this->SetWidgetDirty(GLAND_START_DATE_TEXT);
 
					_settings_newgame.game_creation.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
 
					break;
 

	
 
				case GLAND_SNOW_LEVEL_TEXT:
 
					this->InvalidateWidget(GLAND_SNOW_LEVEL_TEXT);
 
					this->SetWidgetDirty(GLAND_SNOW_LEVEL_TEXT);
 
					_settings_newgame.game_creation.snow_line_height = Clamp(value, 2, MAX_SNOWLINE_HEIGHT);
 
					break;
 

	
 
				case GLAND_TOWN_PULLDOWN:
 
					_settings_newgame.game_creation.custom_town_number = Clamp(value, 1, CUSTOM_TOWN_MAX_NUMBER);
 
					break;
 
			}
 

	
 
			this->SetDirty();
 
		}
 
	}
 
};
 

	
 
static const WindowDesc _generate_landscape_desc(
 
	WDP_CENTER, WDP_CENTER, 338, 313, 338, 313,
 
	WC_GENERATE_LANDSCAPE, WC_NONE,
 
	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 
	_generate_landscape_widgets, _nested_generate_landscape_widgets, lengthof(_nested_generate_landscape_widgets)
 
);
 

	
 
static const WindowDesc _heightmap_load_desc(
 
	WDP_CENTER, WDP_CENTER, 338, 236, 338, 236,
 
	WC_GENERATE_LANDSCAPE, WC_NONE,
 
	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS,
 
@@ -915,49 +915,49 @@ static const WindowDesc _heightmap_load_
 

	
 
static void _ShowGenerateLandscape(glwp_modes mode)
 
{
 
	uint x = 0;
 
	uint y = 0;
 

	
 
	DeleteWindowByClass(WC_GENERATE_LANDSCAPE);
 

	
 
	/* Always give a new seed if not editor */
 
	if (_game_mode != GM_EDITOR) _settings_newgame.game_creation.generation_seed = InteractiveRandom();
 

	
 
	if (mode == GLWP_HEIGHTMAP) {
 
		/* If the function returns negative, it means there was a problem loading the heightmap */
 
		if (!GetHeightmapDimensions(_file_to_saveload.name, &x, &y)) return;
 
	}
 

	
 
	GenerateLandscapeWindow *w = AllocateWindowDescFront<GenerateLandscapeWindow>((mode == GLWP_HEIGHTMAP) ? &_heightmap_load_desc : &_generate_landscape_desc, mode);
 

	
 
	if (mode == GLWP_HEIGHTMAP) {
 
		w->x = x;
 
		w->y = y;
 
		strecpy(w->name, _file_to_saveload.title, lastof(w->name));
 
	}
 

	
 
	InvalidateWindow(WC_GENERATE_LANDSCAPE, mode);
 
	SetWindowDirty(WC_GENERATE_LANDSCAPE, mode);
 
}
 

	
 
void ShowGenerateLandscape()
 
{
 
	_ShowGenerateLandscape(GLWP_GENERATE);
 
}
 

	
 
void ShowHeightmapLoad()
 
{
 
	_ShowGenerateLandscape(GLWP_HEIGHTMAP);
 
}
 

	
 
void StartScenarioEditor()
 
{
 
	StartGeneratingLandscape(GLWP_SCENARIO);
 
}
 

	
 
void StartNewGameWithoutGUI(uint seed)
 
{
 
	/* GenerateWorld takes care of the possible GENERATE_NEW_SEED value in 'seed' */
 
	_settings_newgame.game_creation.generation_seed = seed;
 

	
 
	StartGeneratingLandscape(GLWP_GENERATE);
 
}
 
@@ -1079,54 +1079,54 @@ struct CreateScenarioWindow : public Win
 
			case CSCEN_FLAT_LAND_HEIGHT_TEXT: // Height level text
 
				this->widget_id = CSCEN_FLAT_LAND_HEIGHT_TEXT;
 
				SetDParam(0, _settings_newgame.game_creation.se_flat_world_height);
 
				ShowQueryString(STR_JUST_INT, STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_QUERY_CAPT, 3, 100, this, CS_NUMERAL, QSF_NONE);
 
				break;
 
		}
 
	}
 

	
 
	virtual void OnDropdownSelect(int widget, int index)
 
	{
 
		switch (widget) {
 
			case CSCEN_MAPSIZE_X_PULLDOWN: _settings_newgame.game_creation.map_x = index; break;
 
			case CSCEN_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break;
 
		}
 
		this->SetDirty();
 
	}
 

	
 
	virtual void OnQueryTextFinished(char *str)
 
	{
 
		if (!StrEmpty(str)) {
 
			int32 value = atoi(str);
 

	
 
			switch (this->widget_id) {
 
				case CSCEN_START_DATE_TEXT:
 
					this->InvalidateWidget(CSCEN_START_DATE_TEXT);
 
					this->SetWidgetDirty(CSCEN_START_DATE_TEXT);
 
					_settings_newgame.game_creation.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
 
					break;
 

	
 
				case CSCEN_FLAT_LAND_HEIGHT_TEXT:
 
					this->InvalidateWidget(CSCEN_FLAT_LAND_HEIGHT_TEXT);
 
					this->SetWidgetDirty(CSCEN_FLAT_LAND_HEIGHT_TEXT);
 
					_settings_newgame.game_creation.se_flat_world_height = Clamp(value, 0, MAX_TILE_HEIGHT);
 
					break;
 
			}
 

	
 
			this->SetDirty();
 
		}
 
	}
 
};
 

	
 
static const Widget _create_scenario_widgets[] = {
 
{   WWT_CLOSEBOX, RESIZE_NONE, COLOUR_BROWN,    0,  10,   0,  13, STR_BLACK_CROSS,         STR_TOOLTIP_CLOSE_WINDOW},                 // CSCEN_CLOSEBOX
 
{    WWT_CAPTION, RESIZE_NONE, COLOUR_BROWN,   11, 337,   0,  13, STR_SE_MAPGEN_CAPTION,          STR_NULL},                                 // CSCEN_CAPTION
 
{      WWT_PANEL, RESIZE_NONE, COLOUR_BROWN,    0, 337,  14, 169, 0x0,                     STR_NULL},                                 // CSCEN_BACKGROUND
 

	
 
/* Landscape selection */
 
{   WWT_IMGBTN_2, RESIZE_NONE, COLOUR_ORANGE,  10,  86,  24,  78, SPR_SELECT_TEMPERATE,    STR_INTRO_TOOLTIP_TEMPERATE},              // CSCEN_TEMPERATE
 
{   WWT_IMGBTN_2, RESIZE_NONE, COLOUR_ORANGE,  90, 166,  24,  78, SPR_SELECT_SUB_ARCTIC,   STR_INTRO_TOOLTIP_SUB_ARCTIC_LANDSCAPE},   // CSCEN_ARCTIC
 
{   WWT_IMGBTN_2, RESIZE_NONE, COLOUR_ORANGE, 170, 246,  24,  78, SPR_SELECT_SUB_TROPICAL, STR_INTRO_TOOLTIP_SUB_TROPICAL_LANDSCAPE}, // CSCEN_TROPICAL
 
{   WWT_IMGBTN_2, RESIZE_NONE, COLOUR_ORANGE, 250, 326,  24,  78, SPR_SELECT_TOYLAND,      STR_INTRO_TOOLTIP_TOYLAND_LANDSCAPE},      // CSCEN_TOYLAND
 

	
 
/* Generation type */
 
{    WWT_TEXTBTN, RESIZE_NONE, COLOUR_GREEN,   12, 115,  95, 124, STR_SE_MAPGEN_FLAT_WORLD,       STR_SE_MAPGEN_FLAT_WORLD_TOOLTIP},                    // CSCEN_EMPTY_WORLD
 
{    WWT_TEXTBTN, RESIZE_NONE, COLOUR_GREEN,   12, 115, 131, 160, STR_SE_MAPGEN_RANDOM_LAND,      STR_TERRAFORM_TOOLTIP_GENERATE_RANDOM_LAND},// CSCEN_RANDOM_WORLD
 

	
 
@@ -1375,49 +1375,49 @@ static void _SetGeneratingWorldProgress(
 
	if (!_network_dedicated && _tp.timer != 0 && _realtime_tick - _tp.timer < GENWORLD_REDRAW_TIMEOUT) return;
 

	
 
	/* Percentage is about the number of completed tasks, so 'current - 1' */
 
	_tp.percent = percent_table[cls] + (percent_table[cls + 1] - percent_table[cls]) * (_tp.current == 0 ? 0 : _tp.current - 1) / _tp.total;
 

	
 
	if (_network_dedicated) {
 
		static uint last_percent = 0;
 

	
 
		/* Never display 0% */
 
		if (_tp.percent == 0) return;
 
		/* Reset if percent is lower than the last recorded */
 
		if (_tp.percent < last_percent) last_percent = 0;
 
		/* Display every 5%, but 6% is also very valid.. just not smaller steps than 5% */
 
		if (_tp.percent % 5 != 0 && _tp.percent <= last_percent + 5) return;
 
		/* Never show steps smaller than 2%, even if it is a mod 5% */
 
		if (_tp.percent <= last_percent + 2) return;
 

	
 
		DEBUG(net, 1, "Map generation percentage complete: %d", _tp.percent);
 
		last_percent = _tp.percent;
 

	
 
		/* Don't continue as dedicated never has a thread running */
 
		return;
 
	}
 

	
 
	InvalidateWindow(WC_GENERATE_PROGRESS_WINDOW, 0);
 
	SetWindowDirty(WC_GENERATE_PROGRESS_WINDOW, 0);
 
	MarkWholeScreenDirty();
 

	
 
	/* Release the rights to the map generator, and acquire the rights to the
 
	 * paint thread. The 'other' thread already has the paint thread rights so
 
	 * this ensures us that we are waiting until the paint thread is done
 
	 * before we reacquire the mapgen rights */
 
	_genworld_mapgen_mutex->EndCritical();
 
	_genworld_paint_mutex->BeginCritical();
 
	_genworld_mapgen_mutex->BeginCritical();
 
	_genworld_paint_mutex->EndCritical();
 

	
 
	_tp.timer = _realtime_tick;
 
}
 

	
 
/**
 
 * Set the total of a stage of the world generation.
 
 * @param cls the current class we are in.
 
 * @param total Set the total expected items for this class.
 
 *
 
 * Warning: this function isn't clever. Don't go from class 4 to 3. Go upwards, always.
 
 *  Also, progress works if total is zero, total works if progress is zero.
 
 */
 
void SetGeneratingWorldProgress(gwp_class cls, uint total)
 
{
src/graph_gui.cpp
Show inline comments
 
@@ -66,53 +66,53 @@ struct GraphLegendWindow : Window {
 
	}
 

	
 
	virtual void DrawWidget(const Rect &r, int widget) const
 
	{
 
		if (!IsInsideMM(widget, GLW_FIRST_COMPANY, MAX_COMPANIES + GLW_FIRST_COMPANY)) return;
 

	
 
		CompanyID cid = (CompanyID)(widget - GLW_FIRST_COMPANY);
 

	
 
		if (!Company::IsValidID(cid)) return;
 

	
 
		DrawCompanyIcon(cid, r.left + 2, r.top + 2);
 

	
 
		SetDParam(0, cid);
 
		SetDParam(1, cid);
 
		DrawString(r.left + 19, r.right - 2, r.top + 1, STR_COMPANY_NAME_COMPANY_NUM, HasBit(_legend_excluded_companies, cid) ? TC_BLACK : TC_WHITE);
 
	}
 

	
 
	virtual void OnClick(Point pt, int widget)
 
	{
 
		if (!IsInsideMM(widget, GLW_FIRST_COMPANY, MAX_COMPANIES + GLW_FIRST_COMPANY)) return;
 

	
 
		ToggleBit(_legend_excluded_companies, widget - GLW_FIRST_COMPANY);
 
		this->ToggleWidgetLoweredState(widget);
 
		this->SetDirty();
 
		InvalidateWindow(WC_INCOME_GRAPH, 0);
 
		InvalidateWindow(WC_OPERATING_PROFIT, 0);
 
		InvalidateWindow(WC_DELIVERED_CARGO, 0);
 
		InvalidateWindow(WC_PERFORMANCE_HISTORY, 0);
 
		InvalidateWindow(WC_COMPANY_VALUE, 0);
 
		SetWindowDirty(WC_INCOME_GRAPH, 0);
 
		SetWindowDirty(WC_OPERATING_PROFIT, 0);
 
		SetWindowDirty(WC_DELIVERED_CARGO, 0);
 
		SetWindowDirty(WC_PERFORMANCE_HISTORY, 0);
 
		SetWindowDirty(WC_COMPANY_VALUE, 0);
 
	}
 

	
 
	virtual void OnInvalidateData(int data)
 
	{
 
		if (Company::IsValidID(data)) return;
 

	
 
		SetBit(_legend_excluded_companies, data);
 
		this->RaiseWidget(data + GLW_FIRST_COMPANY);
 
	}
 
};
 

	
 
/**
 
 * Construct a vertical list of buttons, one for each company.
 
 * @param biggest_index Storage for collecting the biggest index used in the returned tree.
 
 * @return Panel with company buttons.
 
 * @postcond \c *biggest_index contains the largest used index in the tree.
 
 */
 
static NWidgetBase *MakeNWidgetCompanyLines(int *biggest_index)
 
{
 
	NWidgetVertical *vert = new NWidgetVertical();
 

	
 
	for (int widnum = GLW_FIRST_COMPANY; widnum <= GLW_LAST_COMPANY; widnum++) {
 
		NWidgetBackground *panel = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, widnum);
 
		panel->SetMinimalSize(246, 12);
 
@@ -382,49 +382,49 @@ protected:
 
						GfxFillRect(x - 1, y - 1, x + 1, y + 1, colour);
 

	
 
						/* Draw the line connected to the previous point. */
 
						if (prev_x != INVALID_DATAPOINT_POS) GfxDrawLine(prev_x, prev_y, x, y, colour);
 

	
 
						prev_x = x;
 
						prev_y = y;
 
					} else {
 
						prev_x = INVALID_DATAPOINT_POS;
 
						prev_y = INVALID_DATAPOINT_POS;
 
					}
 

	
 
					x += GRAPH_X_POSITION_SEPARATION;
 
				}
 
			}
 
		}
 
	}
 

	
 

	
 
	BaseGraphWindow(const WindowDesc *desc, WindowNumber window_number, int left,
 
									int top, int height, bool has_negative_values, StringID format_str_y_axis) :
 
			Window(desc, window_number), has_negative_values(has_negative_values),
 
			format_str_y_axis(format_str_y_axis)
 
	{
 
		InvalidateWindow(WC_GRAPH_LEGEND, 0);
 
		SetWindowDirty(WC_GRAPH_LEGEND, 0);
 
		this->num_vert_lines = 24;
 

	
 
		this->graph_location.left   = left;
 
		this->graph_location.right  = left + GRAPH_X_POSITION_BEGINNING + this->num_vert_lines * GRAPH_X_POSITION_SEPARATION - 1;
 

	
 
		this->graph_location.top    = top;
 
		this->graph_location.bottom = top + height - 1;
 
	}
 

	
 
	void InitializeWindow(const WindowDesc *desc)
 
	{
 
		this->FindWindowPlacementAndResize(desc);
 

	
 
		/* Initialise the dataset */
 
		this->UpdateStatistics(true);
 
	}
 

	
 
public:
 
	virtual void OnPaint()
 
	{
 
		this->DrawWidgets();
 

	
 
		this->DrawGraph(this->graph_location);
 
	}
src/group_cmd.cpp
Show inline comments
 
@@ -207,49 +207,49 @@ CommandCost CmdAddVehicleGroup(TileIndex
 
		Group *g = Group::Get(new_g);
 
		if (g->owner != _current_company || g->vehicle_type != v->type) return CMD_ERROR;
 
	}
 

	
 
	if (v->owner != _current_company || !v->IsPrimaryVehicle()) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		DecreaseGroupNumVehicle(v->group_id);
 
		IncreaseGroupNumVehicle(new_g);
 

	
 
		switch (v->type) {
 
			default: NOT_REACHED();
 
			case VEH_TRAIN:
 
				SetTrainGroupID(Train::From(v), new_g);
 
				break;
 
			case VEH_ROAD:
 
			case VEH_SHIP:
 
			case VEH_AIRCRAFT:
 
				if (v->IsEngineCountable()) UpdateNumEngineGroup(v->engine_type, v->group_id, new_g);
 
				v->group_id = new_g;
 
				break;
 
		}
 

	
 
		/* Update the Replace Vehicle Windows */
 
		InvalidateWindow(WC_REPLACE_VEHICLE, v->type);
 
		SetWindowDirty(WC_REPLACE_VEHICLE, v->type);
 
		InvalidateWindowData(GetWindowClassForVehicleType(v->type), (v->type << 11) | VLW_GROUP_LIST | _current_company);
 
	}
 

	
 
	return CommandCost();
 
}
 

	
 
/**
 
 * Add all shared vehicles of all vehicles from a group
 
 * @param tile unused
 
 * @param p1   index of group array
 
 *  - p1 bit 0-15 : GroupID
 
 * @param p2   type of vehicles
 
 */
 
CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	VehicleType type = (VehicleType)p2;
 
	if (!Group::IsValidID(p1) || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		Vehicle *v;
 
		VehicleType type = (VehicleType)p2;
 
		GroupID id_g = p1;
 

	
 
		/* Find the first front engine which belong to the group id_g
 
@@ -341,72 +341,72 @@ void RemoveVehicleFromGroup(const Vehicl
 

	
 
	if (!IsDefaultGroupID(v->group_id)) DecreaseGroupNumVehicle(v->group_id);
 
}
 

	
 

	
 
/**
 
 * Affect the groupID of a train to new_g.
 
 * @note called in CmdAddVehicleGroup and CmdMoveRailVehicle
 
 * @param v     First vehicle of the chain.
 
 * @param new_g index of array group
 
 */
 
void SetTrainGroupID(Train *v, GroupID new_g)
 
{
 
	if (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g)) return;
 

	
 
	assert(v->IsFrontEngine());
 

	
 
	for (Vehicle *u = v; u != NULL; u = u->Next()) {
 
		if (u->IsEngineCountable()) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);
 

	
 
		u->group_id = new_g;
 
	}
 

	
 
	/* Update the Replace Vehicle Windows */
 
	InvalidateWindow(WC_REPLACE_VEHICLE, VEH_TRAIN);
 
	SetWindowDirty(WC_REPLACE_VEHICLE, VEH_TRAIN);
 
}
 

	
 

	
 
/**
 
 * Recalculates the groupID of a train. Should be called each time a vehicle is added
 
 * to/removed from the chain,.
 
 * @note this needs to be called too for 'wagon chains' (in the depot, without an engine)
 
 * @note Called in CmdBuildRailVehicle, CmdBuildRailWagon, CmdMoveRailVehicle, CmdSellRailWagon
 
 * @param v First vehicle of the chain.
 
 */
 
void UpdateTrainGroupID(Train *v)
 
{
 
	assert(v->IsFrontEngine() || v->IsFreeWagon());
 

	
 
	GroupID new_g = v->IsFrontEngine() ? v->group_id : (GroupID)DEFAULT_GROUP;
 
	for (Vehicle *u = v; u != NULL; u = u->Next()) {
 
		if (u->IsEngineCountable()) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);
 

	
 
		u->group_id = new_g;
 
	}
 

	
 
	/* Update the Replace Vehicle Windows */
 
	InvalidateWindow(WC_REPLACE_VEHICLE, VEH_TRAIN);
 
	SetWindowDirty(WC_REPLACE_VEHICLE, VEH_TRAIN);
 
}
 

	
 
uint GetGroupNumEngines(CompanyID company, GroupID id_g, EngineID id_e)
 
{
 
	if (Group::IsValidID(id_g)) return Group::Get(id_g)->num_engines[id_e];
 

	
 
	uint num = Company::Get(company)->num_engines[id_e];
 
	if (!IsDefaultGroupID(id_g)) return num;
 

	
 
	const Group *g;
 
	FOR_ALL_GROUPS(g) {
 
		if (g->owner == company) num -= g->num_engines[id_e];
 
	}
 
	return num;
 
}
 

	
 
void RemoveAllGroupsForCompany(const CompanyID company)
 
{
 
	Group *g;
 

	
 
	FOR_ALL_GROUPS(g) {
 
		if (company == g->owner) delete g;
 
	}
 
}
src/group_gui.cpp
Show inline comments
 
@@ -655,49 +655,49 @@ public:
 
						DoCommandP(0, this->group_sel, this->vehicle_type, CMD_REMOVE_ALL_VEHICLES_GROUP | CMD_MSG(STR_ERROR_GROUP_CAN_T_REMOVE_ALL_VEHICLES));
 
						break;
 
					default: NOT_REACHED();
 
				}
 
				break;
 

	
 
			default: NOT_REACHED();
 
		}
 

	
 
		this->SetDirty();
 
	}
 

	
 
	virtual void OnTick()
 
	{
 
		if (_pause_mode != PM_UNPAUSED) return;
 
		if (this->groups.NeedResort() || this->vehicles.NeedResort()) {
 
			this->SetDirty();
 
		}
 
	}
 

	
 
	virtual void OnPlaceObjectAbort()
 
	{
 
		/* abort drag & drop */
 
		this->vehicle_sel = INVALID_VEHICLE;
 
		this->InvalidateWidget(GRP_WIDGET_LIST_VEHICLE);
 
		this->SetWidgetDirty(GRP_WIDGET_LIST_VEHICLE);
 
	}
 

	
 
	void ShowRenameGroupWindow(GroupID group)
 
	{
 
		assert(Group::IsValidID(group));
 
		this->group_rename = group;
 
		SetDParam(0, group);
 
		ShowQueryString(STR_GROUP_NAME, STR_GROUP_RENAME_CAPTION, MAX_LENGTH_GROUP_NAME_BYTES, MAX_LENGTH_GROUP_NAME_PIXELS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT);
 
	}
 

	
 
	/**
 
	 * Tests whether a given vehicle is selected in the window, and unselects it if necessary.
 
	 * Called when the vehicle is deleted.
 
	 * @param vehicle Vehicle that is going to be deleted
 
	 */
 
	void UnselectVehicle(VehicleID vehicle)
 
	{
 
		if (this->vehicle_sel == vehicle) ResetObjectToPlace();
 
	}
 
};
 

	
 

	
 
static WindowDesc _group_desc(
 
	WDP_AUTO, WDP_AUTO, 460, 194, 460, 246,
src/industry_cmd.cpp
Show inline comments
 
@@ -1873,49 +1873,49 @@ void GenerateIndustries()
 

	
 
static void UpdateIndustryStatistics(Industry *i)
 
{
 
	byte pct;
 
	bool refresh = false;
 

	
 
	for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
 
		if (i->produced_cargo[j] != CT_INVALID) {
 
			pct = 0;
 
			if (i->this_month_production[j] != 0) {
 
				i->last_prod_year = _cur_year;
 
				pct = min(i->this_month_transported[j] * 256 / i->this_month_production[j], 255);
 
			}
 
			i->last_month_pct_transported[j] = pct;
 

	
 
			i->last_month_production[j] = i->this_month_production[j];
 
			i->this_month_production[j] = 0;
 

	
 
			i->last_month_transported[j] = i->this_month_transported[j];
 
			i->this_month_transported[j] = 0;
 
			refresh = true;
 
		}
 
	}
 

	
 
	if (refresh) InvalidateWindow(WC_INDUSTRY_VIEW, i->index);
 
	if (refresh) SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
 
}
 

	
 
/** Simple helper that will collect data for the generation of industries */
 
struct ProbabilityHelper {
 
	uint16 prob;      ///< probability
 
	IndustryType ind; ///< industry id correcponding
 
};
 

	
 
/**
 
 * Try to create a random industry, during gameplay
 
 */
 
static void MaybeNewIndustry()
 
{
 
	Industry *ind;               // will receive the industry's creation pointer
 
	IndustryType rndtype, j;     // Loop controlers
 
	const IndustrySpec *ind_spc;
 
	uint num = 0;
 
	ProbabilityHelper cumulative_probs[NUM_INDUSTRYTYPES]; // probability collector
 
	uint16 probability_max = 0;
 

	
 
	/* Generate a list of all possible industries that can be built. */
 
	for (j = 0; j < NUM_INDUSTRYTYPES; j++) {
 
		ind_spc = GetIndustrySpec(j);
 
		byte chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape];
src/industry_gui.cpp
Show inline comments
 
@@ -785,49 +785,49 @@ protected:
 
	/* Constants for sorting stations */
 
	static const StringID sorter_names[];
 
	static GUIIndustryList::SortFunction * const sorter_funcs[];
 

	
 
	GUIIndustryList industries;
 

	
 
	/** (Re)Build industries list */
 
	void BuildSortIndustriesList()
 
	{
 
		if (this->industries.NeedRebuild()) {
 
			this->industries.Clear();
 

	
 
			const Industry *i;
 
			FOR_ALL_INDUSTRIES(i) {
 
				*this->industries.Append() = i;
 
			}
 

	
 
			this->industries.Compact();
 
			this->industries.RebuildDone();
 
			this->vscroll.SetCount(this->industries.Length()); // Update scrollbar as well.
 
		}
 

	
 
		if (!this->industries.Sort()) return;
 
		IndustryDirectoryWindow::last_industry = NULL; // Reset name sorter sort cache
 
		this->InvalidateWidget(IDW_INDUSTRY_LIST); // Set the modified widget dirty
 
		this->SetWidgetDirty(IDW_INDUSTRY_LIST); // Set the modified widget dirty
 
	}
 

	
 
	/**
 
	 * Returns percents of cargo transported if industry produces this cargo, else -1
 
	 *
 
	 * @param i industry to check
 
	 * @param id cargo slot
 
	 * @return percents of cargo transported, or -1 if industry doesn't use this cargo slot
 
	 */
 
	static inline int GetCargoTransportedPercentsIfValid(const Industry *i, uint id)
 
	{
 
		assert(id < lengthof(i->produced_cargo));
 

	
 
		if (i->produced_cargo[id] == CT_INVALID) return 101;
 
		return ToPercent8(i->last_month_pct_transported[id]);
 
	}
 

	
 
	/**
 
	 * Returns value representing industry's transported cargo
 
	 *  percentage for industry sorting
 
	 *
 
	 * @param i industry to check
 
	 * @return value used for sorting
 
	 */
src/intro_gui.cpp
Show inline comments
 
@@ -14,49 +14,49 @@
 
#include "gui.h"
 
#include "window_gui.h"
 
#include "textbuf_gui.h"
 
#include "network/network.h"
 
#include "variables.h"
 
#include "genworld.h"
 
#include "network/network_gui.h"
 
#include "network/network_content.h"
 
#include "landscape_type.h"
 
#include "strings_func.h"
 
#include "window_func.h"
 
#include "fios.h"
 
#include "settings_type.h"
 
#include "functions.h"
 
#include "newgrf_config.h"
 
#include "ai/ai_gui.hpp"
 
#include "gfx_func.h"
 

	
 
#include "table/strings.h"
 
#include "table/sprites.h"
 

	
 
static inline void SetNewLandscapeType(byte landscape)
 
{
 
	_settings_newgame.game_creation.landscape = landscape;
 
	InvalidateWindowClasses(WC_SELECT_GAME);
 
	SetWindowClassesDirty(WC_SELECT_GAME);
 
}
 

	
 
enum SelectGameIntroWidgets {
 
	SGI_CLOSE,
 
	SGI_CAPTION,
 
	SGI_GENERATE_GAME,
 
	SGI_LOAD_GAME,
 
	SGI_PLAY_SCENARIO,
 
	SGI_PLAY_HEIGHTMAP,
 
	SGI_EDIT_SCENARIO,
 
	SGI_PLAY_NETWORK,
 
	SGI_TEMPERATE_LANDSCAPE,
 
	SGI_ARCTIC_LANDSCAPE,
 
	SGI_TROPIC_LANDSCAPE,
 
	SGI_TOYLAND_LANDSCAPE,
 
	SGI_OPTIONS,
 
	SGI_DIFFICULTIES,
 
	SGI_SETTINGS_OPTIONS,
 
	SGI_GRF_SETTINGS,
 
	SGI_CONTENT_DOWNLOAD,
 
	SGI_AI_SETTINGS,
 
	SGI_EXIT,
 
};
 

	
src/misc_cmd.cpp
Show inline comments
 
@@ -333,50 +333,50 @@ CommandCost CmdPause(TileIndex tile, DoC
 
		case PM_PAUSED_SAVELOAD:
 
		case PM_PAUSED_ERROR:
 
		case PM_PAUSED_JOIN:
 
		case PM_PAUSED_NORMAL:
 
			break;
 

	
 
		default: return CMD_ERROR;
 
	}
 
	if (flags & DC_EXEC) {
 
		if (p1 == PM_PAUSED_NORMAL && _pause_mode & PM_PAUSED_ERROR) {
 
			ShowQuery(
 
				STR_NEWGRF_UNPAUSE_WARNING_TITLE,
 
				STR_NEWGRF_UNPAUSE_WARNING,
 
				NULL,
 
				AskUnsafeUnpauseCallback
 
			);
 
		} else {
 
			if (p2 == 0) {
 
				_pause_mode = _pause_mode & ~p1;
 
			} else {
 
				_pause_mode = _pause_mode | p1;
 
			}
 
		}
 

	
 
		InvalidateWindow(WC_STATUS_BAR, 0);
 
		InvalidateWindow(WC_MAIN_TOOLBAR, 0);
 
		SetWindowDirty(WC_STATUS_BAR, 0);
 
		SetWindowDirty(WC_MAIN_TOOLBAR, 0);
 
	}
 
	return CommandCost();
 
}
 

	
 
/** Change the financial flow of your company.
 
 * This is normally only enabled in offline mode, but if there is a debug
 
 * build, you can cheat (to test).
 
 * @param tile unused
 
 * @param flags operation to perform
 
 * @param p1 the amount of money to receive (if negative), or spend (if positive)
 
 * @param p2 unused
 
 */
 
CommandCost CmdMoneyCheat(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
#ifndef _DEBUG
 
	if (_networking) return CMD_ERROR;
 
#endif
 
	return CommandCost(EXPENSES_OTHER, -(int32)p1);
 
}
 

	
 
/** Transfer funds (money) from one company to another.
 
 * To prevent abuse in multiplayer games you can only send money to other
 
 * companies if you have paid off your loan (either explicitely, or implicitely
 
 * given the fact that you have more money than loan).
src/misc_gui.cpp
Show inline comments
 
@@ -1120,79 +1120,79 @@ bool HandleCaret(Textbuf *tb)
 
	}
 
	return false;
 
}
 

	
 
bool QueryString::HasEditBoxFocus(const Window *w, int wid) const
 
{
 
	if (w->IsWidgetGloballyFocused(wid)) return true;
 
	if (w->window_class != WC_OSK || _focused_window != w->parent) return false;
 
	return (w->parent->focused_widget != NULL && w->parent->focused_widget->type == WWT_EDITBOX) ||
 
		(w->parent->nested_focus != NULL && w->parent->nested_focus->type == WWT_EDITBOX);
 
}
 

	
 
HandleEditBoxResult QueryString::HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, Window::EventState &state)
 
{
 
	if (!QueryString::HasEditBoxFocus(w, wid)) return HEBR_NOT_FOCUSED;
 

	
 
	state = Window::ES_HANDLED;
 

	
 
	switch (keycode) {
 
		case WKC_ESC: return HEBR_CANCEL;
 

	
 
		case WKC_RETURN: case WKC_NUM_ENTER: return HEBR_CONFIRM;
 

	
 
		case (WKC_CTRL | 'V'):
 
			if (InsertTextBufferClipboard(&this->text)) w->InvalidateWidget(wid);
 
			if (InsertTextBufferClipboard(&this->text)) w->SetWidgetDirty(wid);
 
			break;
 

	
 
		case (WKC_CTRL | 'U'):
 
			DeleteTextBufferAll(&this->text);
 
			w->InvalidateWidget(wid);
 
			w->SetWidgetDirty(wid);
 
			break;
 

	
 
		case WKC_BACKSPACE: case WKC_DELETE:
 
			if (DeleteTextBufferChar(&this->text, keycode)) w->InvalidateWidget(wid);
 
			if (DeleteTextBufferChar(&this->text, keycode)) w->SetWidgetDirty(wid);
 
			break;
 

	
 
		case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME:
 
			if (MoveTextBufferPos(&this->text, keycode)) w->InvalidateWidget(wid);
 
			if (MoveTextBufferPos(&this->text, keycode)) w->SetWidgetDirty(wid);
 
			break;
 

	
 
		default:
 
			if (IsValidChar(key, this->afilter)) {
 
				if (InsertTextBufferChar(&this->text, key)) w->InvalidateWidget(wid);
 
				if (InsertTextBufferChar(&this->text, key)) w->SetWidgetDirty(wid);
 
			} else {
 
				state = Window::ES_NOT_HANDLED;
 
			}
 
	}
 

	
 
	return HEBR_EDITING;
 
}
 

	
 
void QueryString::HandleEditBox(Window *w, int wid)
 
{
 
	if (HasEditBoxFocus(w, wid) && HandleCaret(&this->text)) {
 
		w->InvalidateWidget(wid);
 
		w->SetWidgetDirty(wid);
 
		/* When we're not the OSK, notify 'our' OSK to redraw the widget,
 
		 * so the caret changes appropriately. */
 
		if (w->window_class != WC_OSK) {
 
			Window *w_osk = FindWindowById(WC_OSK, 0);
 
			if (w_osk != NULL && w_osk->parent == w) w_osk->OnInvalidateData();
 
		}
 
	}
 
}
 

	
 
void QueryString::DrawEditBox(Window *w, int wid)
 
{
 
	int left;
 
	int right;
 
	int top;
 
	int bottom;
 
	if (w->widget == NULL) {
 
		const NWidgetCore *wi = w->nested_array[wid];
 

	
 
		assert((wi->type & WWT_MASK) == WWT_EDITBOX);
 

	
 
		left   = wi->pos_x;
 
		right  = wi->pos_x + wi->current_x - 1;
 
		top    = wi->pos_y;
 
		bottom = wi->pos_y + wi->current_y - 1;
 
@@ -1911,49 +1911,49 @@ public:
 

	
 
				const FiosItem *file = _fios_items.Get(y);
 

	
 
				const char *name = FiosBrowseTo(file);
 
				if (name != NULL) {
 
					if (_saveload_mode == SLD_LOAD_GAME || _saveload_mode == SLD_LOAD_SCENARIO) {
 
						_switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD;
 

	
 
						SetFiosType(file->type);
 
						strecpy(_file_to_saveload.name, name, lastof(_file_to_saveload.name));
 
						strecpy(_file_to_saveload.title, file->title, lastof(_file_to_saveload.title));
 

	
 
						delete this;
 
					} else if (_saveload_mode == SLD_LOAD_HEIGHTMAP) {
 
						SetFiosType(file->type);
 
						strecpy(_file_to_saveload.name, name, lastof(_file_to_saveload.name));
 
						strecpy(_file_to_saveload.title, file->title, lastof(_file_to_saveload.title));
 

	
 
						delete this;
 
						ShowHeightmapLoad();
 
					} else {
 
						/* SLD_SAVE_GAME, SLD_SAVE_SCENARIO copy clicked name to editbox */
 
						ttd_strlcpy(this->text.buf, file->title, this->text.maxsize);
 
						UpdateTextBufferSize(&this->text);
 
						this->InvalidateWidget(SLWW_SAVE_OSK_TITLE);
 
						this->SetWidgetDirty(SLWW_SAVE_OSK_TITLE);
 
					}
 
				} else {
 
					/* Changed directory, need repaint. */
 
					this->SetDirty();
 
					BuildFileList();
 
				}
 
				break;
 
			}
 

	
 
			case SLWW_CONTENT_DOWNLOAD:
 
				if (!_network_available) {
 
					ShowErrorMessage(INVALID_STRING_ID, STR_NETWORK_ERROR_NOTAVAILABLE, 0, 0);
 
				} else {
 
#if defined(ENABLE_NETWORK)
 
					switch (_saveload_mode) {
 
						default: NOT_REACHED();
 
						case SLD_LOAD_SCENARIO:  ShowNetworkContentListWindow(NULL, CONTENT_TYPE_SCENARIO);  break;
 
						case SLD_LOAD_HEIGHTMAP: ShowNetworkContentListWindow(NULL, CONTENT_TYPE_HEIGHTMAP); break;
 
					}
 
#endif
 
				}
 
				break;
 

	
 
			case SLWW_DELETE_SELECTION: case SLWW_SAVE_GAME: // Delete, Save game
 
@@ -2057,49 +2057,49 @@ static const FileType _file_modetotype[]
 
	FT_SAVEGAME,  ///< SLD_NEW_GAME
 
};
 

	
 
void ShowSaveLoadDialog(SaveLoadDialogMode mode)
 
{
 
	DeleteWindowById(WC_SAVELOAD, 0);
 

	
 
	const WindowDesc *sld;
 
	switch (mode) {
 
		case SLD_SAVE_GAME:
 
		case SLD_SAVE_SCENARIO:
 
			sld = &_save_dialog_desc; break;
 
		default:
 
			sld = &_load_dialog_desc; break;
 
	}
 

	
 
	_saveload_mode = mode;
 
	_file_to_saveload.filetype = _file_modetotype[mode];
 

	
 
	new SaveLoadWindow(sld, mode);
 
}
 

	
 
void RedrawAutosave()
 
{
 
	InvalidateWindow(WC_STATUS_BAR, 0);
 
	SetWindowDirty(WC_STATUS_BAR, 0);
 
}
 

	
 
void SetFiosType(const byte fiostype)
 
{
 
	switch (fiostype) {
 
		case FIOS_TYPE_FILE:
 
		case FIOS_TYPE_SCENARIO:
 
			_file_to_saveload.mode = SL_LOAD;
 
			break;
 

	
 
		case FIOS_TYPE_OLDFILE:
 
		case FIOS_TYPE_OLD_SCENARIO:
 
			_file_to_saveload.mode = SL_OLD_LOAD;
 
			break;
 

	
 
#ifdef WITH_PNG
 
		case FIOS_TYPE_PNG:
 
			_file_to_saveload.mode = SL_PNG;
 
			break;
 
#endif /* WITH_PNG */
 

	
 
		case FIOS_TYPE_BMP:
 
			_file_to_saveload.mode = SL_BMP;
 
			break;
src/music_gui.cpp
Show inline comments
 
@@ -127,70 +127,70 @@ static void SelectSongToPlay()
 
	} while (_playlists[msf.playlist][++i] != 0 && j < lengthof(_cur_playlist) - 1);
 

	
 
	/* Do not shuffle when on the intro-start window, as the song to play has to be the original TTD Theme*/
 
	if (msf.shuffle && _game_mode != GM_MENU) {
 
		i = 500;
 
		do {
 
			uint32 r = InteractiveRandom();
 
			byte *a = &_cur_playlist[GB(r, 0, 5)];
 
			byte *b = &_cur_playlist[GB(r, 8, 5)];
 

	
 
			if (*a != 0 && *b != 0) {
 
				byte t = *a;
 
				*a = *b;
 
				*b = t;
 
			}
 
		} while (--i);
 
	}
 
}
 

	
 
static void StopMusic()
 
{
 
	_music_wnd_cursong = 0;
 
	DoStopMusic();
 
	_song_is_active = false;
 
	InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 9);
 
	SetWindowWidgetDirty(WC_MUSIC_WINDOW, 0, 9);
 
}
 

	
 
static void PlayPlaylistSong()
 
{
 
	if (_cur_playlist[0] == 0) {
 
		SelectSongToPlay();
 
		/* if there is not songs in the playlist, it may indicate
 
		 * no file on the gm folder, or even no gm folder.
 
		 * Stop the playback, then */
 
		if (_cur_playlist[0] == 0) {
 
			_song_is_active = false;
 
			_music_wnd_cursong = 0;
 
			msf.playing = false;
 
			return;
 
		}
 
	}
 
	_music_wnd_cursong = _cur_playlist[0];
 
	DoPlaySong();
 
	_song_is_active = true;
 

	
 
	InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 9);
 
	SetWindowWidgetDirty(WC_MUSIC_WINDOW, 0, 9);
 
}
 

	
 
void ResetMusic()
 
{
 
	_music_wnd_cursong = 1;
 
	DoPlaySong();
 
}
 

	
 
void MusicLoop()
 
{
 
	if (!msf.playing && _song_is_active) {
 
		StopMusic();
 
	} else if (msf.playing && !_song_is_active) {
 
		PlayPlaylistSong();
 
	}
 

	
 
	if (!_song_is_active) return;
 

	
 
	if (!_music_driver->IsSongPlaying()) {
 
		if (_game_mode != GM_MENU) {
 
			StopMusic();
 
			SkipToNextSong();
 
			PlayPlaylistSong();
 
		} else {
 
@@ -579,72 +579,72 @@ struct MusicWindow : public Window {
 
				break;
 

	
 
			case MW_PLAY: // start playing
 
				msf.playing = true;
 
				break;
 

	
 
			case MW_MUSIC_VOL: case MW_EFFECT_VOL: { // volume sliders
 
				int x = pt.x - this->nested_array[widget]->pos_x;
 

	
 
				byte *vol = (widget == MW_MUSIC_VOL) ? &msf.music_vol : &msf.effect_vol;
 

	
 
				byte new_vol = x * 127 / this->nested_array[widget]->current_x;
 
				if (new_vol != *vol) {
 
					*vol = new_vol;
 
					if (widget == MW_MUSIC_VOL) MusicVolumeChanged(new_vol);
 
					this->SetDirty();
 
				}
 

	
 
				_left_button_clicked = false;
 
			} break;
 

	
 
			case MW_SHUFFLE: // toggle shuffle
 
				msf.shuffle ^= 1;
 
				this->SetWidgetLoweredState(MW_SHUFFLE, msf.shuffle);
 
				this->InvalidateWidget(MW_SHUFFLE);
 
				this->SetWidgetDirty(MW_SHUFFLE);
 
				StopMusic();
 
				SelectSongToPlay();
 
				this->SetDirty();
 
				break;
 

	
 
			case MW_PROGRAMME: // show track selection
 
				ShowMusicTrackSelection();
 
				break;
 

	
 
			case MW_ALL: case MW_OLD: case MW_NEW:
 
			case MW_EZY: case MW_CUSTOM1: case MW_CUSTOM2: // playlist
 
				SelectPlaylist(widget - MW_ALL);
 
				StopMusic();
 
				SelectSongToPlay();
 
				this->SetDirty();
 
				break;
 
		}
 
	}
 

	
 
#if 0
 
	virtual void OnTick()
 
	{
 
		this->InvalidateWidget(MW_GAUGE);
 
		this->SetWidgetDirty(MW_GAUGE);
 
	}
 
#endif
 
};
 

	
 
static const NWidgetPart _nested_music_window_widgets[] = {
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_CLOSEBOX, COLOUR_GREY, MW_CLOSE),
 
		NWidget(WWT_CAPTION, COLOUR_GREY, MW_CAPTION), SetDataTip(STR_MUSIC_JAZZ_JUKEBOX_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
 
	EndContainer(),
 

	
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, MW_PREV), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_SKIP_TO_PREV, STR_MUSIC_TOOLTIP_SKIP_TO_PREVIOUS_TRACK),
 
		NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, MW_NEXT), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_SKIP_TO_NEXT, STR_MUSIC_TOOLTIP_SKIP_TO_NEXT_TRACK_IN_SELECTION),
 
		NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, MW_STOP), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_STOP_MUSIC, STR_MUSIC_TOOLTIP_STOP_PLAYING_MUSIC),
 
		NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, MW_PLAY), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_PLAY_MUSIC, STR_MUSIC_TOOLTIP_START_PLAYING_MUSIC),
 
		NWidget(WWT_PANEL, COLOUR_GREY, MW_SLIDERS),
 
			NWidget(NWID_HORIZONTAL), SetPIP(20, 0, 20),
 
				NWidget(WWT_EMPTY, COLOUR_GREY, MW_MUSIC_VOL), SetMinimalSize(67, 22), SetFill(false, false), SetDataTip(0x0, STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
 
				NWidget(WWT_PANEL, COLOUR_GREY, MW_GAUGE), SetMinimalSize(16, 20), SetPadding(1, 11, 1, 11), SetFill(false, false), EndContainer(),
 
				NWidget(WWT_EMPTY, COLOUR_GREY, MW_EFFECT_VOL), SetMinimalSize(67, 22), SetFill(false, false), SetDataTip(0x0, STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
 
				NWidget(NWID_SPACER), SetFill(true, false),
 
			EndContainer(),
 
		EndContainer(),
 
	EndContainer(),
src/network/network.cpp
Show inline comments
 
@@ -420,97 +420,97 @@ void ParseConnectionString(const char **
 
 *   Used both by the server and the client */
 
static NetworkClientSocket *NetworkAllocClient(SOCKET s)
 
{
 
	if (_network_server) {
 
		/* Can we handle a new client? */
 
		if (_network_clients_connected >= MAX_CLIENTS) return NULL;
 
		if (_network_game_info.clients_on >= _settings_client.network.max_clients) return NULL;
 

	
 
		/* Register the login */
 
		_network_clients_connected++;
 
	}
 

	
 
	NetworkClientSocket *cs = new NetworkClientSocket(INVALID_CLIENT_ID);
 
	cs->sock = s;
 
	cs->last_frame = _frame_counter;
 
	cs->last_frame_server = _frame_counter;
 

	
 
	if (_network_server) {
 
		cs->client_id = _network_client_id++;
 
		NetworkClientInfo *ci = new NetworkClientInfo(cs->client_id);
 
		cs->SetInfo(ci);
 
		ci->client_playas = COMPANY_INACTIVE_CLIENT;
 
		ci->join_date = _date;
 

	
 
		InvalidateWindow(WC_CLIENT_LIST, 0);
 
		SetWindowDirty(WC_CLIENT_LIST, 0);
 
	}
 

	
 
	return cs;
 
}
 

	
 
/* Close a connection */
 
void NetworkCloseClient(NetworkClientSocket *cs, bool error)
 
{
 
	/*
 
	 * Sending a message just before leaving the game calls cs->Send_Packets.
 
	 * This might invoke this function, which means that when we close the
 
	 * connection after cs->Send_Packets we will close an already closed
 
	 * connection. This handles that case gracefully without having to make
 
	 * that code any more complex or more aware of the validity of the socket.
 
	 */
 
	if (cs->sock == INVALID_SOCKET) return;
 

	
 
	if (error && !cs->HasClientQuit() && _network_server && cs->status > STATUS_INACTIVE) {
 
		/* We did not receive a leave message from this client... */
 
		char client_name[NETWORK_CLIENT_NAME_LENGTH];
 
		NetworkClientSocket *new_cs;
 

	
 
		NetworkGetClientName(client_name, sizeof(client_name), cs);
 

	
 
		NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_ERROR_CLIENT_CONNECTION_LOST);
 

	
 
		/* Inform other clients of this... strange leaving ;) */
 
		FOR_ALL_CLIENT_SOCKETS(new_cs) {
 
			if (new_cs->status > STATUS_AUTH && cs != new_cs) {
 
				SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->client_id, NETWORK_ERROR_CONNECTION_LOST);
 
			}
 
		}
 
	}
 

	
 
	DEBUG(net, 1, "Closed client connection %d", cs->client_id);
 

	
 
	/* When the client was PRE_ACTIVE, the server was in pause mode, so unpause */
 
	if (cs->status == STATUS_PRE_ACTIVE && (_pause_mode & PM_PAUSED_JOIN)) {
 
		DoCommandP(0, PM_PAUSED_JOIN, 0, CMD_PAUSE);
 
		NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "", CLIENT_ID_SERVER, NETWORK_SERVER_MESSAGE_GAME_UNPAUSED_CONNECT_FAIL);
 
	}
 

	
 
	if (_network_server) {
 
		/* We just lost one client :( */
 
		if (cs->status >= STATUS_AUTH) _network_game_info.clients_on--;
 
		_network_clients_connected--;
 

	
 
		InvalidateWindow(WC_CLIENT_LIST, 0);
 
		SetWindowDirty(WC_CLIENT_LIST, 0);
 
	}
 

	
 
	delete cs->GetInfo();
 
	delete cs;
 
}
 

	
 
/* For the server, to accept new clients */
 
static void NetworkAcceptClients(SOCKET ls)
 
{
 
	for (;;) {
 
		struct sockaddr_storage sin;
 
		memset(&sin, 0, sizeof(sin));
 
		socklen_t sin_len = sizeof(sin);
 
		SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
 
		if (s == INVALID_SOCKET) return;
 

	
 
		SetNonBlocking(s); // XXX error handling?
 

	
 
		NetworkAddress address(sin, sin_len);
 
		DEBUG(net, 1, "Client connected from %s on frame %d", address.GetHostname(), _frame_counter);
 

	
 
		SetNoDelay(s); // XXX error handling?
 

	
 
		/* Check if the client is banned */
src/network/network_client.cpp
Show inline comments
 
@@ -103,70 +103,70 @@ void HashCurrentCompanyPassword(const ch
 
	const char *new_pw = GenerateCompanyPasswordHash(password);
 
	strecpy(_network_company_states[_local_company].password, new_pw, lastof(_network_company_states[_local_company].password));
 

	
 
	if (_network_server) {
 
		NetworkServerUpdateCompanyPassworded(_local_company, !StrEmpty(_network_company_states[_local_company].password));
 
	}
 
}
 

	
 

	
 
/***********
 
 * Sending functions
 
 *   DEF_CLIENT_SEND_COMMAND has no parameters
 
 ************/
 

	
 
DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_COMPANY_INFO)
 
{
 
	/*
 
	 * Packet: CLIENT_COMPANY_INFO
 
	 * Function: Request company-info (in detail)
 
	 * Data:
 
	 *    <none>
 
	 */
 
	Packet *p;
 
	_network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
 
	InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
 
	SetWindowDirty(WC_NETWORK_STATUS_WINDOW, 0);
 

	
 
	p = NetworkSend_Init(PACKET_CLIENT_COMPANY_INFO);
 
	MY_CLIENT->Send_Packet(p);
 
}
 

	
 
DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_JOIN)
 
{
 
	/*
 
	 * Packet: CLIENT_JOIN
 
	 * Function: Try to join the server
 
	 * Data:
 
	 *    String: OpenTTD Revision (norev000 if no revision)
 
	 *    String: Client Name (max NETWORK_NAME_LENGTH)
 
	 *    uint8:  Play as Company id (1..MAX_COMPANIES)
 
	 *    uint8:  Language ID
 
	 *    String: Unique id to find the client back in server-listing
 
	 */
 

	
 
	Packet *p;
 
	_network_join_status = NETWORK_JOIN_STATUS_AUTHORIZING;
 
	InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
 
	SetWindowDirty(WC_NETWORK_STATUS_WINDOW, 0);
 

	
 
	p = NetworkSend_Init(PACKET_CLIENT_JOIN);
 
	p->Send_string(_openttd_revision);
 
	p->Send_string(_settings_client.network.client_name); // Client name
 
	p->Send_uint8 (_network_join_as);     // PlayAs
 
	p->Send_uint8 (NETLANG_ANY);          // Language
 
	p->Send_string(_settings_client.network.network_id);
 
	MY_CLIENT->Send_Packet(p);
 
}
 

	
 
DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)
 
{
 
	/*
 
	 * Packet: CLIENT_NEWGRFS_CHECKED
 
	 * Function: Tell the server that we have the required GRFs
 
	 * Data:
 
	 */
 

	
 
	Packet *p = NetworkSend_Init(PACKET_CLIENT_NEWGRFS_CHECKED);
 
	MY_CLIENT->Send_Packet(p);
 
}
 

	
 
DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_PASSWORD)(NetworkPasswordType type, const char *password)
 
{
 
@@ -378,96 +378,96 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
		/* We have received all data... (there are no more packets coming) */
 
		if (!p->Recv_bool()) return NETWORK_RECV_STATUS_CLOSE_QUERY;
 

	
 
		CompanyID current = (Owner)p->Recv_uint8();
 
		if (current >= MAX_COMPANIES) return NETWORK_RECV_STATUS_CLOSE_QUERY;
 

	
 
		NetworkCompanyInfo *company_info = GetLobbyCompanyInfo(current);
 
		if (company_info == NULL) return NETWORK_RECV_STATUS_CLOSE_QUERY;
 

	
 
		p->Recv_string(company_info->company_name, sizeof(company_info->company_name));
 
		company_info->inaugurated_year = p->Recv_uint32();
 
		company_info->company_value    = p->Recv_uint64();
 
		company_info->money            = p->Recv_uint64();
 
		company_info->income           = p->Recv_uint64();
 
		company_info->performance      = p->Recv_uint16();
 
		company_info->use_password     = p->Recv_bool();
 
		for (int i = 0; i < NETWORK_VEHICLE_TYPES; i++)
 
			company_info->num_vehicle[i] = p->Recv_uint16();
 
		for (int i = 0; i < NETWORK_STATION_TYPES; i++)
 
			company_info->num_station[i] = p->Recv_uint16();
 
		company_info->ai               = p->Recv_bool();
 

	
 
		p->Recv_string(company_info->clients, sizeof(company_info->clients));
 

	
 
		InvalidateWindow(WC_NETWORK_WINDOW, 0);
 
		SetWindowDirty(WC_NETWORK_WINDOW, 0);
 

	
 
		return NETWORK_RECV_STATUS_OKAY;
 
	}
 

	
 
	return NETWORK_RECV_STATUS_CLOSE_QUERY;
 
}
 

	
 
/* This packet contains info about the client (playas and name)
 
 *  as client we save this in NetworkClientInfo, linked via 'client_id'
 
 *  which is always an unique number on a server. */
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO)
 
{
 
	NetworkClientInfo *ci;
 
	ClientID client_id = (ClientID)p->Recv_uint32();
 
	CompanyID playas = (CompanyID)p->Recv_uint8();
 
	char name[NETWORK_NAME_LENGTH];
 

	
 
	p->Recv_string(name, sizeof(name));
 

	
 
	if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 

	
 
	ci = NetworkFindClientInfoFromClientID(client_id);
 
	if (ci != NULL) {
 
		if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) {
 
			/* Client name changed, display the change */
 
			NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, name);
 
		} else if (playas != ci->client_playas) {
 
			/* The client changed from client-player..
 
			 * Do not display that for now */
 
		}
 

	
 
		ci->client_playas = playas;
 
		strecpy(ci->client_name, name, lastof(ci->client_name));
 

	
 
		InvalidateWindow(WC_CLIENT_LIST, 0);
 
		SetWindowDirty(WC_CLIENT_LIST, 0);
 

	
 
		return NETWORK_RECV_STATUS_OKAY;
 
	}
 

	
 
	/* We don't have this client_id yet, find an empty client_id, and put the data there */
 
	ci = new NetworkClientInfo(client_id);
 
	ci->client_playas = playas;
 
	if (client_id == _network_own_client_id) MY_CLIENT->SetInfo(ci);
 

	
 
	strecpy(ci->client_name, name, lastof(ci->client_name));
 

	
 
	InvalidateWindow(WC_CLIENT_LIST, 0);
 
	SetWindowDirty(WC_CLIENT_LIST, 0);
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR)
 
{
 
	NetworkErrorCode error = (NetworkErrorCode)p->Recv_uint8();
 

	
 
	switch (error) {
 
		/* We made an error in the protocol, and our connection is closed.... */
 
		case NETWORK_ERROR_NOT_AUTHORIZED:
 
		case NETWORK_ERROR_NOT_EXPECTED:
 
		case NETWORK_ERROR_COMPANY_MISMATCH:
 
			_switch_mode_errorstr = STR_NETWORK_ERROR_SERVER_ERROR;
 
			break;
 
		case NETWORK_ERROR_FULL:
 
			_switch_mode_errorstr = STR_NETWORK_ERROR_SERVER_FULL;
 
			break;
 
		case NETWORK_ERROR_WRONG_REVISION:
 
			_switch_mode_errorstr = STR_NETWORK_ERROR_WRONG_REVISION;
 
			break;
 
		case NETWORK_ERROR_WRONG_PASSWORD:
 
			_switch_mode_errorstr = STR_NETWORK_ERROR_WRONG_PASSWORD;
 
			break;
 
@@ -539,112 +539,112 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
			}
 
			return NETWORK_RECV_STATUS_OKAY;
 

	
 
		default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 
	}
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WELCOME)
 
{
 
	_network_own_client_id = (ClientID)p->Recv_uint32();
 

	
 
	/* Initialize the password hash salting variables, even if they were previously. */
 
	_password_game_seed = p->Recv_uint32();
 
	p->Recv_string(_password_server_unique_id, sizeof(_password_server_unique_id));
 

	
 
	/* Start receiving the map */
 
	SEND_COMMAND(PACKET_CLIENT_GETMAP)();
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WAIT)
 
{
 
	_network_join_status = NETWORK_JOIN_STATUS_WAITING;
 
	_network_join_waiting = p->Recv_uint8();
 
	InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
 
	SetWindowDirty(WC_NETWORK_STATUS_WINDOW, 0);
 

	
 
	/* We are put on hold for receiving the map.. we need GUI for this ;) */
 
	DEBUG(net, 1, "The server is currently busy sending the map to someone else, please wait..." );
 
	DEBUG(net, 1, "There are %d clients in front of you", _network_join_waiting);
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP)
 
{
 
	static FILE *file_pointer;
 

	
 
	byte maptype;
 

	
 
	maptype = p->Recv_uint8();
 

	
 
	if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 

	
 
	/* First packet, init some stuff */
 
	if (maptype == MAP_PACKET_START) {
 
		file_pointer = FioFOpenFile("network_client.tmp", "wb", AUTOSAVE_DIR);;
 
		if (file_pointer == NULL) {
 
			_switch_mode_errorstr = STR_NETWORK_ERROR_SAVEGAMEERROR;
 
			return NETWORK_RECV_STATUS_SAVEGAME;
 
		}
 

	
 
		_frame_counter = _frame_counter_server = _frame_counter_max = p->Recv_uint32();
 

	
 
		_network_join_bytes = 0;
 
		_network_join_bytes_total = p->Recv_uint32();
 

	
 
		/* If the network connection has been closed due to loss of connection
 
		 * or when _network_join_kbytes_total is 0, the join status window will
 
		 * do a division by zero. When the connection is lost, we just return
 
		 * that. If kbytes_total is 0, the packet must be malformed as a
 
		 * savegame less than 1 kilobyte is practically impossible. */
 
		if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 
		if (_network_join_bytes_total == 0) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 

	
 
		_network_join_status = NETWORK_JOIN_STATUS_DOWNLOADING;
 
		InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
 
		SetWindowDirty(WC_NETWORK_STATUS_WINDOW, 0);
 

	
 
		/* The first packet does not contain any more data */
 
		return NETWORK_RECV_STATUS_OKAY;
 
	}
 

	
 
	if (maptype == MAP_PACKET_NORMAL) {
 
		/* We are still receiving data, put it to the file */
 
		if (fwrite(p->buffer + p->pos, 1, p->size - p->pos, file_pointer) != (size_t)(p->size - p->pos)) {
 
			_switch_mode_errorstr = STR_NETWORK_ERROR_SAVEGAMEERROR;
 
			return NETWORK_RECV_STATUS_SAVEGAME;
 
		}
 

	
 
		_network_join_bytes = ftell(file_pointer);
 
		InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
 
		SetWindowDirty(WC_NETWORK_STATUS_WINDOW, 0);
 
	}
 

	
 
	/* Check if this was the last packet */
 
	if (maptype == MAP_PACKET_END) {
 
		fclose(file_pointer);
 

	
 
		_network_join_status = NETWORK_JOIN_STATUS_PROCESSING;
 
		InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
 
		SetWindowDirty(WC_NETWORK_STATUS_WINDOW, 0);
 

	
 
		/* The map is done downloading, load it */
 
		if (!SafeSaveOrLoad("network_client.tmp", SL_LOAD, GM_NORMAL, AUTOSAVE_DIR)) {
 
			DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
 
			_switch_mode_errorstr = STR_NETWORK_ERROR_SAVEGAMEERROR;
 
			return NETWORK_RECV_STATUS_SAVEGAME;
 
		}
 
		/* If the savegame has successfully loaded, ALL windows have been removed,
 
		 * only toolbar/statusbar and gamefield are visible */
 

	
 
		/* Say we received the map and loaded it correctly! */
 
		SEND_COMMAND(PACKET_CLIENT_MAP_OK)();
 

	
 
		/* New company/spectator (invalid company) or company we want to join is not active
 
		 * Switch local company to spectator and await the server's judgement */
 
		if (_network_join_as == COMPANY_NEW_COMPANY || !Company::IsValidID(_network_join_as)) {
 
			SetLocalCompany(COMPANY_SPECTATOR);
 

	
 
			if (_network_join_as != COMPANY_SPECTATOR) {
 
				/* We have arrived and ready to start playing; send a command to make a new company;
 
				 * the server will give us a client-id and let us in */
 
				_network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
 
				ShowJoinStatusWindow();
 
				NetworkSend_Command(0, 0, 0, CMD_COMPANY_CTRL, NULL, NULL);
 
@@ -754,82 +754,82 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 

	
 
			default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 
		}
 
	} else {
 
		/* Display message from somebody else */
 
		snprintf(name, sizeof(name), "%s", ci_to->client_name);
 
		ci = ci_to;
 
	}
 

	
 
	if (ci != NULL)
 
		NetworkTextMessage(action, (ConsoleColour)GetDrawStringCompanyColour(ci->client_playas), self_send, name, msg, data);
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT)
 
{
 
	ClientID client_id = (ClientID)p->Recv_uint32();
 

	
 
	NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id);
 
	if (ci != NULL) {
 
		NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, NULL, GetNetworkErrorMsg((NetworkErrorCode)p->Recv_uint8()));
 
		delete ci;
 
	}
 

	
 
	InvalidateWindow(WC_CLIENT_LIST, 0);
 
	SetWindowDirty(WC_CLIENT_LIST, 0);
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_QUIT)
 
{
 
	NetworkClientInfo *ci;
 

	
 
	ClientID client_id = (ClientID)p->Recv_uint32();
 

	
 
	ci = NetworkFindClientInfoFromClientID(client_id);
 
	if (ci != NULL) {
 
		NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
 
		delete ci;
 
	} else {
 
		DEBUG(net, 0, "Unknown client (%d) is leaving the game", client_id);
 
	}
 

	
 
	InvalidateWindow(WC_CLIENT_LIST, 0);
 
	SetWindowDirty(WC_CLIENT_LIST, 0);
 

	
 
	/* If we come here it means we could not locate the client.. strange :s */
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_JOIN)
 
{
 
	ClientID client_id = (ClientID)p->Recv_uint32();
 

	
 
	NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id);
 
	if (ci != NULL)
 
		NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, ci->client_name);
 

	
 
	InvalidateWindow(WC_CLIENT_LIST, 0);
 
	SetWindowDirty(WC_CLIENT_LIST, 0);
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN)
 
{
 
	_switch_mode_errorstr = STR_NETWORK_MESSAGE_SERVER_SHUTDOWN;
 

	
 
	return NETWORK_RECV_STATUS_SERVER_ERROR;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME)
 
{
 
	/* To trottle the reconnects a bit, every clients waits
 
	 *  his _local_company value before reconnecting
 
	 * COMPANY_SPECTATOR is currently 255, so to avoid long wait periods
 
	 *  set the max to 10. */
 
	_network_reconnect = min(_local_company + 1, 10);
 
	_switch_mode_errorstr = STR_NETWORK_MESSAGE_SERVER_REBOOT;
 

	
 
	return NETWORK_RECV_STATUS_SERVER_ERROR;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_RCON)
 
@@ -860,49 +860,49 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER
 
	/* Just make sure we do not try to use a client_index that does not exist */
 
	if (ci == NULL) return NETWORK_RECV_STATUS_OKAY;
 

	
 
	/* if not valid player, force spectator, else check player exists */
 
	if (!Company::IsValidID(company_id)) company_id = COMPANY_SPECTATOR;
 

	
 
	if (client_id == _network_own_client_id) {
 
		SetLocalCompany(company_id);
 
	}
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CONFIG_UPDATE)
 
{
 
	_network_server_max_companies = p->Recv_uint8();
 
	_network_server_max_spectators = p->Recv_uint8();
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 
DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_UPDATE)
 
{
 
	_network_company_passworded = p->Recv_uint16();
 
	InvalidateWindowClasses(WC_COMPANY);
 
	SetWindowClassesDirty(WC_COMPANY);
 

	
 
	return NETWORK_RECV_STATUS_OKAY;
 
}
 

	
 

	
 
/* The layout for the receive-functions by the client */
 
typedef NetworkRecvStatus NetworkClientPacket(Packet *p);
 

	
 
/* This array matches PacketType. At an incoming
 
 *  packet it is matches against this array
 
 *  and that way the right function to handle that
 
 *  packet is found. */
 
static NetworkClientPacket * const _network_client_packet[] = {
 
	RECEIVE_COMMAND(PACKET_SERVER_FULL),
 
	RECEIVE_COMMAND(PACKET_SERVER_BANNED),
 
	NULL, // PACKET_CLIENT_JOIN,
 
	RECEIVE_COMMAND(PACKET_SERVER_ERROR),
 
	NULL, // PACKET_CLIENT_COMPANY_INFO,
 
	RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO),
 
	RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO),
 
	RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD),
 
	NULL, // PACKET_CLIENT_PASSWORD,
 
	RECEIVE_COMMAND(PACKET_SERVER_WELCOME),
 
	NULL, // PACKET_CLIENT_GETMAP,
src/network/network_content_gui.cpp
Show inline comments
 
@@ -74,59 +74,59 @@ public:
 
	 * Create a new download window based on a list of content information
 
	 * with flags whether to download them or not.
 
	 * @param infos the list to search in
 
	 */
 
	NetworkContentDownloadStatusWindow() :
 
		cur_id(UINT32_MAX)
 
	{
 
		this->parent = FindWindowById(WC_NETWORK_WINDOW, 1);
 

	
 
		_network_content_client.AddCallback(this);
 
		_network_content_client.DownloadSelectedContent(this->total_files, this->total_bytes);
 

	
 
		this->InitNested(&_network_content_download_status_window_desc, 0);
 
	}
 

	
 
	/** Free whatever we've allocated */
 
	~NetworkContentDownloadStatusWindow()
 
	{
 
		/* Tell all the backends about what we've downloaded */
 
		for (ContentType *iter = this->receivedTypes.Begin(); iter != this->receivedTypes.End(); iter++) {
 
			switch (*iter) {
 
				case CONTENT_TYPE_AI:
 
				case CONTENT_TYPE_AI_LIBRARY:
 
					AI::Rescan();
 
					InvalidateWindowClasses(WC_AI_DEBUG);
 
					SetWindowClassesDirty(WC_AI_DEBUG);
 
					break;
 

	
 
				case CONTENT_TYPE_BASE_GRAPHICS:
 
					BaseGraphics::FindSets();
 
					InvalidateWindow(WC_GAME_OPTIONS, 0);
 
					SetWindowDirty(WC_GAME_OPTIONS, 0);
 
					break;
 

	
 
				case CONTENT_TYPE_BASE_SOUNDS:
 
					BaseSounds::FindSets();
 
					InvalidateWindow(WC_GAME_OPTIONS, 0);
 
					SetWindowDirty(WC_GAME_OPTIONS, 0);
 
					break;
 

	
 
				case CONTENT_TYPE_NEWGRF:
 
					ScanNewGRFFiles();
 
					/* Yes... these are the NewGRF windows */
 
					InvalidateWindowClassesData(WC_SAVELOAD);
 
					InvalidateWindowData(WC_GAME_OPTIONS, 0, 1);
 
					InvalidateWindowData(WC_NETWORK_WINDOW, 1, 2);
 
					break;
 

	
 
				case CONTENT_TYPE_SCENARIO:
 
				case CONTENT_TYPE_HEIGHTMAP:
 
					extern void ScanScenarios();
 
					ScanScenarios();
 
					InvalidateWindowData(WC_SAVELOAD, 0, 0);
 
					break;
 

	
 
				default:
 
					break;
 
			}
 
		}
 

	
 
		_network_content_client.RemoveCallback(this);
 
	}
src/network/network_gui.cpp
Show inline comments
 
@@ -1182,49 +1182,49 @@ struct NetworkStartServerWindow : public
 
	{
 
		if (this->field == NSSW_GAMENAME) this->HandleEditBox(NSSW_GAMENAME);
 
	}
 

	
 
	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 
	{
 
		EventState state = ES_NOT_HANDLED;
 
		if (this->field == NSSW_GAMENAME) {
 
			if (this->HandleEditBoxKey(NSSW_GAMENAME, key, keycode, state) == HEBR_CONFIRM) return state;
 

	
 
			strecpy(_settings_client.network.server_name, this->text.buf, lastof(_settings_client.network.server_name));
 
		}
 

	
 
		return state;
 
	}
 

	
 
	virtual void OnQueryTextFinished(char *str)
 
	{
 
		if (str == NULL) return;
 

	
 
		if (this->widget_id == NSSW_SETPWD) {
 
			strecpy(_settings_client.network.server_password, str, lastof(_settings_client.network.server_password));
 
		} else {
 
			int32 value = atoi(str);
 
			this->InvalidateWidget(this->widget_id);
 
			this->SetWidgetDirty(this->widget_id);
 
			switch (this->widget_id) {
 
				default: NOT_REACHED();
 
				case NSSW_CLIENTS_TXT:    _settings_client.network.max_clients    = Clamp(value, 2, MAX_CLIENTS); break;
 
				case NSSW_COMPANIES_TXT:  _settings_client.network.max_companies  = Clamp(value, 1, MAX_COMPANIES); break;
 
				case NSSW_SPECTATORS_TXT: _settings_client.network.max_spectators = Clamp(value, 0, MAX_CLIENTS); break;
 
			}
 
		}
 

	
 
		this->SetDirty();
 
	}
 
};
 

	
 
static const Widget _network_start_server_window_widgets[] = {
 
/* Window decoration and background panel */
 
{   WWT_CLOSEBOX,   RESIZE_NONE,   COLOUR_LIGHT_BLUE,     0,    10,     0,    13, STR_BLACK_CROSS,                    STR_TOOLTIP_CLOSE_WINDOW },            // NSSW_CLOSE
 
{    WWT_CAPTION,   RESIZE_NONE,   COLOUR_LIGHT_BLUE,    11,   419,     0,    13, STR_NETWORK_START_SERVER_CAPTION,      STR_NULL},                             // NSSW_CAPTION
 
{      WWT_PANEL,   RESIZE_NONE,   COLOUR_LIGHT_BLUE,     0,   419,    14,   243, 0x0,                                STR_NULL},                             // NSSW_BACKGROUND
 

	
 
/* Set game name and password widgets */
 
{       WWT_TEXT,   RESIZE_NONE,   COLOUR_LIGHT_BLUE,    10,    90,    22,    34, STR_NETWORK_START_SERVER_NEW_GAME_NAME,          STR_NULL},                             // NSSW_GAMENAME_LABEL
 
{    WWT_EDITBOX,   RESIZE_NONE,   COLOUR_LIGHT_BLUE,   100,   272,    22,    33, STR_NETWORK_START_SERVER_NEW_GAME_NAME_OSKTITLE, STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP},        // NSSW_GAMENAME
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   COLOUR_WHITE,        285,   405,    22,    33, STR_NETWORK_START_SERVER_SET_PASSWORD,           STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP},             // NSSW_SETPWD
 

	
 
/* List of playable scenarios */
src/network/network_server.cpp
Show inline comments
 
@@ -1712,49 +1712,49 @@ void NetworkServerShowStatusToConsole()
 
		IConsolePrintF(CC_INFO, "Client #%1d  name: '%s'  status: '%s'  frame-lag: %3d  company: %1d  IP: %s  unique-id: '%s'",
 
			cs->client_id, ci->client_name, status, lag,
 
			ci->client_playas + (Company::IsValidID(ci->client_playas) ? 1 : 0),
 
			GetClientIP(ci), ci->unique_id);
 
	}
 
}
 

	
 
/**
 
 * Send Config Update
 
 */
 
void NetworkServerSendConfigUpdate()
 
{
 
	NetworkClientSocket *cs;
 

	
 
	FOR_ALL_CLIENT_SOCKETS(cs) {
 
		SEND_COMMAND(PACKET_SERVER_CONFIG_UPDATE)(cs);
 
	}
 
}
 

	
 
void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded)
 
{
 
	if (NetworkCompanyIsPassworded(company_id) == passworded) return;
 

	
 
	SB(_network_company_passworded, company_id, 1, !!passworded);
 
	InvalidateWindowClasses(WC_COMPANY);
 
	SetWindowClassesDirty(WC_COMPANY);
 

	
 
	NetworkClientSocket *cs;
 
	FOR_ALL_CLIENT_SOCKETS(cs) {
 
		SEND_COMMAND(PACKET_SERVER_COMPANY_UPDATE)(cs);
 
	}
 
}
 

	
 
/**
 
 * Handle the tid-bits of moving a client from one company to another.
 
 * @param client_id id of the client we want to move.
 
 * @param company_id id of the company we want to move the client to.
 
 * @return void
 
 **/
 
void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
 
{
 
	/* Only allow non-dedicated servers and normal clients to be moved */
 
	if (client_id == CLIENT_ID_SERVER && _network_dedicated) return;
 

	
 
	NetworkClientInfo *ci = NetworkFindClientInfoFromClientID(client_id);
 

	
 
	/* No need to waste network resources if the client is in the company already! */
 
	if (ci->client_playas == company_id) return;
 

	
 
	ci->client_playas = company_id;
src/newgrf_industries.cpp
Show inline comments
 
@@ -536,26 +536,26 @@ void IndustryProductionCallback(Industry
 
			/* abort the function early, this error isn't critical and will allow the game to continue to run */
 
			break;
 
		}
 

	
 
		SB(object.callback_param2, 8, 16, loop);
 
		const SpriteGroup *tgroup = SpriteGroup::Resolve(spec->grf_prop.spritegroup, &object);
 
		if (tgroup == NULL || tgroup->type != SGT_INDUSTRY_PRODUCTION) break;
 
		const IndustryProductionSpriteGroup *group = (const IndustryProductionSpriteGroup *)tgroup;
 

	
 
		bool deref = (group->version == 1);
 

	
 
		for (uint i = 0; i < 3; i++) {
 
			ind->incoming_cargo_waiting[i] = Clamp(ind->incoming_cargo_waiting[i] - DerefIndProd(group->substract_input[i], deref) * multiplier, 0, 0xFFFF);
 
		}
 
		for (uint i = 0; i < 2; i++) {
 
			ind->produced_cargo_waiting[i] = Clamp(ind->produced_cargo_waiting[i] + max(DerefIndProd(group->add_output[i], deref), 0) * multiplier, 0, 0xFFFF);
 
		}
 

	
 
		int32 again = DerefIndProd(group->again, deref);
 
		if (again == 0) break;
 

	
 
		SB(object.callback_param2, 24, 8, again);
 
	}
 

	
 
	InvalidateWindow(WC_INDUSTRY_VIEW, ind->index);
 
	SetWindowDirty(WC_INDUSTRY_VIEW, ind->index);
 
}
src/news_gui.cpp
Show inline comments
 
@@ -669,83 +669,83 @@ void AddNewsItem(StringID string, NewsSu
 
	/* show this news message in colour? */
 
	if (_cur_year >= _settings_client.gui.coloured_news_year) ni->flags |= NF_INCOLOUR;
 

	
 
	ni->reftype1 = reftype1;
 
	ni->reftype2 = reftype2;
 
	ni->ref1 = ref1;
 
	ni->ref2 = ref2;
 
	ni->free_data = free_data;
 
	ni->date = _date;
 
	CopyOutDParam(ni->params, 0, lengthof(ni->params));
 

	
 
	if (_total_news++ == 0) {
 
		assert(_oldest_news == NULL);
 
		_oldest_news = ni;
 
		ni->prev = NULL;
 
	} else {
 
		assert(_latest_news->next == NULL);
 
		_latest_news->next = ni;
 
		ni->prev = _latest_news;
 
	}
 

	
 
	ni->next = NULL;
 
	_latest_news = ni;
 

	
 
	InvalidateWindow(WC_MESSAGE_HISTORY, 0);
 
	SetWindowDirty(WC_MESSAGE_HISTORY, 0);
 
}
 

	
 
/** Delete a news item from the queue */
 
static void DeleteNewsItem(NewsItem *ni)
 
{
 
	if (_forced_news == ni || _current_news == ni) {
 
		/* about to remove the currently forced item (shown as newspapers) ||
 
		 * about to remove the currently displayed item (newspapers, ticker, or just a reminder) */
 
		MoveToNextItem();
 
	}
 

	
 
	/* delete item */
 

	
 
	if (ni->prev != NULL) {
 
		ni->prev->next = ni->next;
 
	} else {
 
		assert(_oldest_news == ni);
 
		_oldest_news = ni->next;
 
	}
 

	
 
	if (ni->next != NULL) {
 
		ni->next->prev = ni->prev;
 
	} else {
 
		assert(_latest_news == ni);
 
		_latest_news = ni->prev;
 
	}
 

	
 
	free(ni->free_data);
 

	
 
	if (_current_news == ni) _current_news = ni->prev;
 
	_total_news--;
 
	delete ni;
 

	
 
	InvalidateWindow(WC_MESSAGE_HISTORY, 0);
 
	SetWindowDirty(WC_MESSAGE_HISTORY, 0);
 
}
 

	
 
void DeleteVehicleNews(VehicleID vid, StringID news)
 
{
 
	NewsItem *ni = _oldest_news;
 

	
 
	while (ni != NULL) {
 
		NewsItem *next = ni->next;
 
		if (((ni->reftype1 == NR_VEHICLE && ni->ref1 == vid) || (ni->reftype2 == NR_VEHICLE && ni->ref2 == vid)) &&
 
				(news == INVALID_STRING_ID || ni->string_id == news)) {
 
			DeleteNewsItem(ni);
 
		}
 
		ni = next;
 
	}
 
}
 

	
 
/** Remove news regarding given station so there are no 'unknown station now accepts Mail'
 
 * or 'First train arrived at unknown station' news items.
 
 * @param sid station to remove news about
 
 */
 
void DeleteStationNews(StationID sid)
 
{
 
	NewsItem *ni = _oldest_news;
 

	
 
@@ -1139,49 +1139,49 @@ struct MessageOptionsWindow : Window {
 
			}
 
			return;
 
		}
 
	}
 

	
 
	virtual void OnInvalidateData(int data)
 
	{
 
		/* Update the dropdown value for 'set all categories'. */
 
		this->nested_array[WIDGET_NEWSOPT_DROP_SUMMARY]->widget_data = this->message_opt[this->state];
 

	
 
		/* Update widget to reflect the value of the #_news_ticker_sound variable. */
 
		this->SetWidgetLoweredState(WIDGET_NEWSOPT_SOUNDTICKER, _news_ticker_sound);
 
	}
 

	
 
	virtual void OnClick(Point pt, int widget)
 
	{
 
		switch (widget) {
 
			case WIDGET_NEWSOPT_DROP_SUMMARY: // Dropdown menu for all settings
 
				ShowDropDownMenu(this, this->message_opt, this->state, WIDGET_NEWSOPT_DROP_SUMMARY, 0, 0);
 
				break;
 

	
 
			case WIDGET_NEWSOPT_SOUNDTICKER: // Change ticker sound on/off
 
				_news_ticker_sound ^= 1;
 
				this->OnInvalidateData(0);
 
				this->InvalidateWidget(widget);
 
				this->SetWidgetDirty(widget);
 
				break;
 

	
 
			default: { // Clicked on the [<] .. [>] widgets
 
				if (widget >= WIDGET_NEWSOPT_START_OPTION && widget < WIDGET_NEWSOPT_END_OPTION) {
 
					int wid = widget - WIDGET_NEWSOPT_START_OPTION;
 
					int element = wid / MOS_WIDG_PER_SETTING;
 
					byte val = (_news_type_data[element].display + ((wid % MOS_WIDG_PER_SETTING) ? 1 : -1)) % 3;
 

	
 
					this->SetMessageButtonStates(val, element);
 
					_news_type_data[element].display = (NewsDisplay)val;
 
					this->SetDirty();
 
				}
 
				break;
 
			}
 
		}
 
	}
 

	
 
	virtual void OnDropdownSelect(int widget, int index)
 
	{
 
		this->state = index;
 

	
 
		for (int i = 0; i < NT_END; i++) {
 
			this->SetMessageButtonStates(index, i);
 
			_news_type_data[i].display = (NewsDisplay)index;
src/openttd.cpp
Show inline comments
 
@@ -581,49 +581,49 @@ int ttd_main(int argc, char *argv[])
 
#if defined(ENABLE_NETWORK)
 
	if (dedicated_host) {
 
		_network_bind_list.Clear();
 
		*_network_bind_list.Append() = strdup(dedicated_host);
 
	}
 
	if (dedicated_port) _settings_client.network.server_port = dedicated_port;
 
	if (_dedicated_forks && !dedicated) _dedicated_forks = false;
 
#endif /* ENABLE_NETWORK */
 

	
 
	/* enumerate language files */
 
	InitializeLanguagePacks();
 

	
 
	/* initialize screenshot formats */
 
	InitializeScreenshotFormats();
 

	
 
	/* initialize airport state machines */
 
	InitializeAirports();
 

	
 
	/* initialize all variables that are allocated dynamically */
 
	InitializeDynamicVariables();
 

	
 
	/* Initialize FreeType */
 
	InitFreeType();
 

	
 
	/* This must be done early, since functions use the InvalidateWindow* calls */
 
	/* This must be done early, since functions use the SetWindowDirty* calls */
 
	InitWindowSystem();
 

	
 
	/* Look for the sounds before the graphics. Otherwise none would be set and
 
	 * the first initialisation of the video happens on the wrong data. Now it
 
	 * can do the first initialisation right. */
 
	if (sounds_set == NULL && BaseSounds::ini_set != NULL) sounds_set = strdup(BaseSounds::ini_set);
 
	if (!BaseSounds::SetSet(sounds_set)) {
 
		StrEmpty(sounds_set) ?
 
			usererror("Failed to find a sounds set. Please acquire a sounds set for OpenTTD.") :
 
			usererror("Failed to select requested sounds set '%s'", sounds_set);
 
	}
 
	free(sounds_set);
 

	
 
	if (graphics_set == NULL && BaseGraphics::ini_set != NULL) graphics_set = strdup(BaseGraphics::ini_set);
 
	if (!BaseGraphics::SetSet(graphics_set)) {
 
		StrEmpty(graphics_set) ?
 
			usererror("Failed to find a graphics set. Please acquire a graphics set for OpenTTD.") :
 
			usererror("Failed to select requested graphics set '%s'", graphics_set);
 
	}
 
	free(graphics_set);
 

	
 
	/* Initialize game palette */
 
	GfxInitPalettes();
 

	
src/order_cmd.cpp
Show inline comments
 
@@ -158,59 +158,59 @@ uint16 Order::MapOldOrder() const
 
			break;
 
	}
 
	return order;
 
}
 

	
 
Order::Order(uint32 packed)
 
{
 
	this->type    = (OrderType)GB(packed,  0,  8);
 
	this->flags   = GB(packed,  8,  8);
 
	this->dest    = GB(packed, 16, 16);
 
	this->next    = NULL;
 
	this->refit_cargo   = CT_NO_REFIT;
 
	this->refit_subtype = 0;
 
	this->wait_time     = 0;
 
	this->travel_time   = 0;
 
}
 

	
 
/**
 
 *
 
 * Updates the widgets of a vehicle which contains the order-data
 
 *
 
 */
 
void InvalidateVehicleOrder(const Vehicle *v, int data)
 
{
 
	InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 
	SetWindowDirty(WC_VEHICLE_VIEW, v->index);
 

	
 
	if (data != 0) {
 
		/* Calls SetDirty() too */
 
		InvalidateWindowData(WC_VEHICLE_ORDERS,    v->index, data);
 
		InvalidateWindowData(WC_VEHICLE_TIMETABLE, v->index, data);
 
		return;
 
	}
 

	
 
	InvalidateWindow(WC_VEHICLE_ORDERS,    v->index);
 
	InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index);
 
	SetWindowDirty(WC_VEHICLE_ORDERS,    v->index);
 
	SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
 
}
 

	
 
/**
 
 *
 
 * Assign data to an order (from an other order)
 
 *   This function makes sure that the index is maintained correctly
 
 *
 
 */
 
void Order::AssignOrder(const Order &other)
 
{
 
	this->type  = other.type;
 
	this->flags = other.flags;
 
	this->dest  = other.dest;
 

	
 
	this->refit_cargo   = other.refit_cargo;
 
	this->refit_subtype = other.refit_subtype;
 

	
 
	this->wait_time   = other.wait_time;
 
	this->travel_time = other.travel_time;
 
}
 

	
 
void OrderList::Initialize(Order *chain, Vehicle *v)
 
{
 
	this->first = chain;
 
@@ -774,50 +774,50 @@ CommandCost CmdDeleteOrder(TileIndex til
 
 */
 
CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	VehicleID veh_id = p1;
 
	VehicleOrderID sel_ord = p2;
 

	
 
	Vehicle *v = Vehicle::GetIfValid(veh_id);
 

	
 
	if (v == NULL || !CheckOwnership(v->owner) || sel_ord == v->cur_order_index ||
 
			sel_ord >= v->GetNumOrders() || v->GetNumOrders() < 2) {
 
		return CMD_ERROR;
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		v->cur_order_index = sel_ord;
 

	
 
		if (v->type == VEH_ROAD) ClearSlot(RoadVehicle::From(v));
 

	
 
		if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
 

	
 
		InvalidateVehicleOrder(v, -2);
 
	}
 

	
 
	/* We have an aircraft/ship, they have a mini-schedule, so update them all */
 
	if (v->type == VEH_AIRCRAFT) InvalidateWindowClasses(WC_AIRCRAFT_LIST);
 
	if (v->type == VEH_SHIP) InvalidateWindowClasses(WC_SHIPS_LIST);
 
	if (v->type == VEH_AIRCRAFT) SetWindowClassesDirty(WC_AIRCRAFT_LIST);
 
	if (v->type == VEH_SHIP) SetWindowClassesDirty(WC_SHIPS_LIST);
 

	
 
	return CommandCost();
 
}
 

	
 
/**
 
 * Move an order inside the orderlist
 
 * @param tile unused
 
 * @param p1 the ID of the vehicle
 
 * @param p2 order to move and target
 
 *           bit 0-15  : the order to move
 
 *           bit 16-31 : the target order
 
 * @note The target order will move one place down in the orderlist
 
 *  if you move the order upwards else it'll move it one place down
 
 */
 
CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	VehicleID veh = p1;
 
	VehicleOrderID moving_order = GB(p2,  0, 16);
 
	VehicleOrderID target_order = GB(p2, 16, 16);
 

	
 
	Vehicle *v = Vehicle::GetIfValid(veh);
 
	if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR;
 

	
 
	/* Don't make senseless movements */
 
@@ -1494,49 +1494,49 @@ void CheckOrders(const Vehicle *v)
 
	}
 
}
 

	
 
/**
 
 * Removes an order from all vehicles. Triggers when, say, a station is removed.
 
 * @param type The type of the order (OT_GOTO_[STATION|DEPOT|WAYPOINT]).
 
 * @param destination The destination. Can be a StationID, DepotID or WaypointID.
 
 */
 
void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination)
 
{
 
	Vehicle *v;
 

	
 
	/* Aircraft have StationIDs for depot orders and never use DepotIDs
 
	 * This fact is handled specially below
 
	 */
 

	
 
	/* Go through all vehicles */
 
	FOR_ALL_VEHICLES(v) {
 
		Order *order;
 

	
 
		order = &v->current_order;
 
		if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) ? OT_GOTO_STATION : order->GetType()) == type &&
 
				v->current_order.GetDestination() == destination) {
 
			order->MakeDummy();
 
			InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 
			SetWindowDirty(WC_VEHICLE_VIEW, v->index);
 
		}
 

	
 
		/* Clear the order from the order-list */
 
		int id = -1;
 
		FOR_VEHICLE_ORDERS(v, order) {
 
			id++;
 
			if (order->IsType(OT_GOTO_DEPOT) && (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) continue;
 
			if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) ? OT_GOTO_STATION : order->GetType()) == type &&
 
					order->GetDestination() == destination) {
 
				order->MakeDummy();
 
				for (const Vehicle *w = v->FirstShared(); w != NULL; w = w->NextShared()) {
 
					/* In GUI, simulate by removing the order and adding it back */
 
					InvalidateVehicleOrder(w, id | (INVALID_VEH_ORDER_ID << 8));
 
					InvalidateVehicleOrder(w, (INVALID_VEH_ORDER_ID << 8) | id);
 
				}
 
			}
 
		}
 
	}
 
}
 

	
 
/**
 
 *
 
 * Checks if a vehicle has a GOTO_DEPOT in his order list
 
 *
 
@@ -1785,49 +1785,49 @@ bool ProcessOrders(Vehicle *v)
 
		if (v->type == VEH_ROAD) ClearSlot(RoadVehicle::From(v));
 
		return false;
 
	}
 

	
 
	/* If it is unchanged, keep it. */
 
	if (order->Equals(v->current_order) && (v->type == VEH_AIRCRAFT || v->dest_tile != 0) &&
 
			(v->type != VEH_SHIP || !order->IsType(OT_GOTO_STATION) || Station::Get(order->GetDestination())->dock_tile != INVALID_TILE)) {
 
		return false;
 
	}
 

	
 
	/* Otherwise set it, and determine the destination tile. */
 
	v->current_order = *order;
 

	
 
	InvalidateVehicleOrder(v, -2);
 
	switch (v->type) {
 
		default:
 
			NOT_REACHED();
 

	
 
		case VEH_ROAD:
 
		case VEH_TRAIN:
 
			break;
 

	
 
		case VEH_AIRCRAFT:
 
		case VEH_SHIP:
 
			InvalidateWindowClasses(GetWindowClassForVehicleType(v->type));
 
			SetWindowClassesDirty(GetWindowClassForVehicleType(v->type));
 
			break;
 
	}
 

	
 
	return UpdateOrderDest(v, order) && may_reverse;
 
}
 

	
 
/**
 
 * Check whether the given vehicle should stop at the given station
 
 * based on this order and the non-stop settings.
 
 * @param v       the vehicle that might be stopping.
 
 * @param station the station to stop at.
 
 * @return true if the vehicle should stop.
 
 */
 
bool Order::ShouldStopAtStation(const Vehicle *v, StationID station) const
 
{
 
	bool is_dest_station = this->IsType(OT_GOTO_STATION) && this->dest == station;
 
	return
 
			(!this->IsType(OT_GOTO_DEPOT) || (this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0) &&
 
			v->last_station_visited != station && // Do stop only when we've not just been there
 
			/* Finally do stop when there is no non-stop flag set for this type of station. */
 
			!(this->GetNonStopType() & (is_dest_station ? ONSF_NO_STOP_AT_DESTINATION_STATION : ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS));
 
}
 

	
 
void InitializeOrders()
src/order_gui.cpp
Show inline comments
 
@@ -435,49 +435,49 @@ private:
 
		if (!u->IsPrimaryVehicle()) {
 
			u = u->First();
 
			if (!u->IsPrimaryVehicle()) return false;
 
		}
 

	
 
		/* v is vehicle getting orders. Only copy/clone orders if vehicle doesn't have any orders yet
 
		 * obviously if you press CTRL on a non-empty orders vehicle you know what you are doing */
 
		if (this->vehicle->GetNumOrders() != 0 && _ctrl_pressed == 0) return false;
 

	
 
		if (DoCommandP(this->vehicle->tile, this->vehicle->index | (u->index << 16), _ctrl_pressed ? CO_SHARE : CO_COPY,
 
			_ctrl_pressed ? CMD_CLONE_ORDER | CMD_MSG(STR_ERROR_CAN_T_SHARE_ORDER_LIST) : CMD_CLONE_ORDER | CMD_MSG(STR_ERROR_CAN_T_COPY_ORDER_LIST))) {
 
			this->selected_order = -1;
 
			ResetObjectToPlace();
 
		}
 

	
 
		return true;
 
	}
 

	
 
	/**
 
	 * Handle the click on the goto button.
 
	 * @param i Dummy parameter.
 
	 */
 
	void OrderClick_Goto(int i)
 
	{
 
		this->InvalidateWidget(ORDER_WIDGET_GOTO);
 
		this->SetWidgetDirty(ORDER_WIDGET_GOTO);
 
		this->ToggleWidgetLoweredState(ORDER_WIDGET_GOTO);
 
		if (this->IsWidgetLowered(ORDER_WIDGET_GOTO)) {
 
			_place_clicked_vehicle = NULL;
 
			SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, HT_RECT, this);
 
			this->goto_type = OPOS_GOTO;
 
		} else {
 
			ResetObjectToPlace();
 
		}
 
	}
 

	
 
	/**
 
	 * Handle the click on the full load button.
 
	 * @param load_type the way to load.
 
	 */
 
	void OrderClick_FullLoad(int load_type)
 
	{
 
		VehicleOrderID sel_ord = this->OrderGetSel();
 
		const Order *order = this->vehicle->GetOrder(sel_ord);
 

	
 
		if (order == NULL || order->GetLoadType() == load_type) return;
 

	
 
		if (load_type < 0) {
 
			load_type = order->GetLoadType() == OLF_LOAD_IF_POSSIBLE ? OLF_FULL_LOAD_ANY : OLF_LOAD_IF_POSSIBLE;
 
		}
 
@@ -500,88 +500,88 @@ private:
 
	}
 

	
 
	/**
 
	 * Handle the click on the service in nearest depot button.
 
	 * @param i Dummy parameter.
 
	 */
 
	void OrderClick_NearestDepot(int i)
 
	{
 
		Order order;
 
		order.next = NULL;
 
		order.index = 0;
 
		order.MakeGoToDepot(0, ODTFB_PART_OF_ORDERS,
 
				_settings_client.gui.new_nonstop && (this->vehicle->type == VEH_TRAIN || this->vehicle->type == VEH_ROAD) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
 
		order.SetDepotActionType(ODATFB_NEAREST_DEPOT);
 

	
 
		DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 16), order.Pack(), CMD_INSERT_ORDER | CMD_MSG(STR_ERROR_CAN_T_INSERT_NEW_ORDER));
 
	}
 

	
 
	/**
 
	 * Handle the click on the conditional order button.
 
	 * @param i Dummy parameter.
 
	 */
 
	void OrderClick_Conditional(int i)
 
	{
 
		this->InvalidateWidget(ORDER_WIDGET_GOTO);
 
		this->SetWidgetDirty(ORDER_WIDGET_GOTO);
 
		this->LowerWidget(ORDER_WIDGET_GOTO);
 
		SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, HT_RECT, this);
 
		this->goto_type = OPOS_CONDITIONAL;
 
	}
 

	
 
	/**
 
	 * Handle the click on the unload button.
 
	 */
 
	void OrderClick_Unload(int unload_type)
 
	{
 
		VehicleOrderID sel_ord = this->OrderGetSel();
 
		const Order *order = this->vehicle->GetOrder(sel_ord);
 

	
 
		if (order == NULL || order->GetUnloadType() == unload_type) return;
 

	
 
		if (unload_type < 0) {
 
			unload_type = order->GetUnloadType() == OUF_UNLOAD_IF_POSSIBLE ? OUFB_UNLOAD : OUF_UNLOAD_IF_POSSIBLE;
 
		}
 

	
 
		DoCommandP(this->vehicle->tile, this->vehicle->index + (sel_ord << 16), MOF_UNLOAD | (unload_type << 4), CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
 
	}
 

	
 
	/**
 
	 * Handle the click on the nonstop button.
 
	 * @param non_stop what non-stop type to use; -1 to use the 'next' one.
 
	 */
 
	void OrderClick_Nonstop(int non_stop)
 
	{
 
		VehicleOrderID sel_ord = this->OrderGetSel();
 
		const Order *order = this->vehicle->GetOrder(sel_ord);
 

	
 
		if (order == NULL || order->GetNonStopType() == non_stop) return;
 

	
 
		/* Keypress if negative, so 'toggle' to the next */
 
		if (non_stop < 0) {
 
			non_stop = order->GetNonStopType() ^ ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS;
 
		}
 

	
 
		this->InvalidateWidget(ORDER_WIDGET_NON_STOP);
 
		this->SetWidgetDirty(ORDER_WIDGET_NON_STOP);
 
		DoCommandP(this->vehicle->tile, this->vehicle->index + (sel_ord << 16), MOF_NON_STOP | non_stop << 4,  CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
 
	}
 

	
 
	/**
 
	 * Handle the click on the skip button.
 
	 * If ctrl is pressed, skip to selected order, else skip to current order + 1
 
	 * @param i Dummy parameter.
 
	 */
 
	void OrderClick_Skip(int i)
 
	{
 
		/* Don't skip when there's nothing to skip */
 
		if (_ctrl_pressed && this->vehicle->cur_order_index == this->OrderGetSel()) return;
 
		if (this->vehicle->GetNumOrders() <= 1) return;
 

	
 
		DoCommandP(this->vehicle->tile, this->vehicle->index, _ctrl_pressed ? this->OrderGetSel() : ((this->vehicle->cur_order_index + 1) % this->vehicle->GetNumOrders()),
 
				CMD_SKIP_TO_ORDER | CMD_MSG(_ctrl_pressed ? STR_ERROR_CAN_T_SKIP_TO_ORDER : STR_ERROR_CAN_T_SKIP_ORDER));
 
	}
 

	
 
	/**
 
	 * Handle the click on the delete button.
 
	 * @param i Dummy parameter.
 
	 */
 
	void OrderClick_Delete(int i)
 
	{
 
@@ -1117,49 +1117,49 @@ public:
 
			}
 
		}
 
	}
 

	
 
	virtual void OnPlaceObjectAbort()
 
	{
 
		if (this->goto_type == OPOS_CONDITIONAL) {
 
			this->goto_type = OPOS_GOTO;
 
			if (_cursor.pos.x >= (this->left + this->widget[ORDER_WIDGET_ORDER_LIST].left) &&
 
					_cursor.pos.y >= (this->top  + this->widget[ORDER_WIDGET_ORDER_LIST].top) &&
 
					_cursor.pos.x <= (this->left + this->widget[ORDER_WIDGET_ORDER_LIST].right) &&
 
					_cursor.pos.y <= (this->top  + this->widget[ORDER_WIDGET_ORDER_LIST].bottom)) {
 
				int order_id = this->GetOrderFromPt(_cursor.pos.y - this->top);
 
				if (order_id != INVALID_ORDER) {
 
					Order order;
 
					order.next = NULL;
 
					order.index = 0;
 
					order.MakeConditional(order_id);
 

	
 
					DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 16), order.Pack(), CMD_INSERT_ORDER | CMD_MSG(STR_ERROR_CAN_T_INSERT_NEW_ORDER));
 
				}
 
			}
 
		}
 
		this->RaiseWidget(ORDER_WIDGET_GOTO);
 
		this->InvalidateWidget(ORDER_WIDGET_GOTO);
 
		this->SetWidgetDirty(ORDER_WIDGET_GOTO);
 
	}
 

	
 
	virtual void OnMouseLoop()
 
	{
 
		const Vehicle *v = _place_clicked_vehicle;
 
		/*
 
		 * Check if we clicked on a vehicle
 
		 * and if the GOTO button of this window is pressed
 
		 * This is because of all open order windows WE_MOUSELOOP is called
 
		 * and if you have 3 windows open, and this check is not done
 
		 * the order is copied to the last open window instead of the
 
		 * one where GOTO is enabled
 
		 */
 
		if (v != NULL && this->IsWidgetLowered(ORDER_WIDGET_GOTO)) {
 
			_place_clicked_vehicle = NULL;
 
			this->HandleOrderVehClick(v);
 
		}
 
	}
 

	
 
	/**
 
	 * Set the left and right edge of a widget in the window.
 
	 * @param widnum Number of the widget to modify.
 
	 * @param left   New offset of the left edge of the widget.
 
	 * @param right  New offset of the right edge of the widget.
 
@@ -1212,49 +1212,49 @@ public:
 
				SetWidgetLeftRight(ORDER_WIDGET_SERVICE_DROPDOWN, two_third, rightmost - 1);
 
				SetWidgetLeftRight(ORDER_WIDGET_SERVICE, two_third, rightmost - 1 - arrow_width);
 
			} else {
 
				/* Window displays orders of your ship/plane vehicle. */
 
				const int middle = (rightmost - leftmost) / 2; // Start of second half.
 
				/* Left 1/2 buttons. */
 
				SetWidgetLeftRight(ORDER_WIDGET_FULL_LOAD_DROPDOWN, leftmost, middle - 1);
 
				SetWidgetLeftRight(ORDER_WIDGET_FULL_LOAD, leftmost, middle - 1 - arrow_width);
 
				SetWidgetLeftRight(ORDER_WIDGET_REFIT, leftmost, middle - 1);
 
				/* Right 1/2 buttons. */
 
				SetWidgetLeftRight(ORDER_WIDGET_UNLOAD_DROPDOWN, middle, rightmost - 1);
 
				SetWidgetLeftRight(ORDER_WIDGET_UNLOAD, middle, rightmost - 1 - arrow_width);
 
				SetWidgetLeftRight(ORDER_WIDGET_SERVICE_DROPDOWN, middle, rightmost - 1);
 
				SetWidgetLeftRight(ORDER_WIDGET_SERVICE, middle, rightmost - 1 - arrow_width);
 
			}
 
		}
 
	}
 

	
 
	virtual void OnTimeout()
 
	{
 
		/* unclick all buttons except for the 'goto' button (ORDER_WIDGET_GOTO), which is 'persistent' */
 
		for (uint i = 0; i < this->widget_count; i++) {
 
			if (this->IsWidgetLowered(i) && i != ORDER_WIDGET_GOTO) {
 
				this->RaiseWidget(i);
 
				this->InvalidateWidget(i);
 
				this->SetWidgetDirty(i);
 
			}
 
		}
 
	}
 
};
 

	
 
/**
 
 * Widget definition for "your" train orders
 
 */
 
static const Widget _orders_train_widgets[] = {
 
	{   WWT_CLOSEBOX,   RESIZE_NONE,   COLOUR_GREY,     0,    10,     0,    13, STR_BLACK_CROSS,            STR_TOOLTIP_CLOSE_WINDOW},                 // ORDER_WIDGET_CLOSEBOX
 
	{    WWT_CAPTION,   RESIZE_RIGHT,  COLOUR_GREY,    11,   371,     0,    13, STR_ORDERS_CAPTION,         STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS},       // ORDER_WIDGET_CAPTION
 
	{ WWT_PUSHTXTBTN,   RESIZE_LR,     COLOUR_GREY,   311,   371,     0,    13, STR_ORDERS_TIMETABLE_VIEW,  STR_ORDERS_TIMETABLE_VIEW_TOOLTIP},               // ORDER_WIDGET_TIMETABLE_VIEW
 
	{  WWT_STICKYBOX,   RESIZE_LR,     COLOUR_GREY,   372,   383,     0,    13, STR_NULL,                   STR_TOOLTIP_STICKY},                        // ORDER_WIDGET_STICKY
 

	
 
	{      WWT_PANEL,   RESIZE_RB,     COLOUR_GREY,     0,   371,    14,    75, 0x0,                        STR_ORDERS_LIST_TOOLTIP},                  // ORDER_WIDGET_ORDER_LIST
 

	
 
	{  WWT_SCROLLBAR,   RESIZE_LRB,    COLOUR_GREY,   372,   383,    14,    75, 0x0,                        STR_TOOLTIP_VSCROLL_BAR_SCROLLS_LIST},     // ORDER_WIDGET_SCROLLBAR
 

	
 
	{ WWT_PUSHTXTBTN,   RESIZE_TB,     COLOUR_GREY,     0,   123,    88,    99, STR_ORDERS_SKIP_BUTTON,     STR_ORDERS_SKIP_TOOLTIP},                  // ORDER_WIDGET_SKIP
 
	{ WWT_PUSHTXTBTN,   RESIZE_TB,     COLOUR_GREY,   124,   247,    88,    99, STR_ORDERS_DELETE_BUTTON,   STR_ORDERS_DELETE_TOOLTIP},                // ORDER_WIDGET_DELETE
 
	{   WWT_DROPDOWN,   RESIZE_TB,     COLOUR_GREY,     0,   123,    76,    87, STR_NULL,                   STR_ORDER_TOOLTIP_NON_STOP},               // ORDER_WIDGET_NON_STOP_DROPDOWN
 
	{    WWT_TEXTBTN,   RESIZE_TB,     COLOUR_GREY,     0,   111,    76,    87, STR_ORDER_NON_STOP,         STR_ORDER_TOOLTIP_NON_STOP},               // ORDER_WIDGET_NON_STOP
 
	{   WWT_DROPDOWN,   RESIZE_RTB,    COLOUR_GREY,   248,   371,    88,    99, STR_EMPTY,                  STR_ORDERS_GO_TO_DROPDOWN_TOOLTIP},         // ORDER_WIDGET_GOTO_DROPDOWN
 
	{    WWT_TEXTBTN,   RESIZE_RTB,    COLOUR_GREY,   248,   359,    88,    99, STR_ORDERS_GO_TO_BUTTON,    STR_ORDERS_GO_TO_TOOLTIP},                 // ORDER_WIDGET_GOTO
src/osk_gui.cpp
Show inline comments
 
@@ -224,62 +224,62 @@ struct OskWindow : public Window {
 
				delete this;
 
				break;
 

	
 
			case OSK_WIDGET_CANCEL:
 
				if (this->cancel_btn != 0) { // pass a cancel event to the parent window
 
					this->parent->OnClick(pt, this->cancel_btn);
 
					/* Window gets deleted when the parent window removes itself. */
 
					return;
 
				} else { // or reset to original string
 
					strcpy(qs->text.buf, this->orig_str_buf);
 
					UpdateTextBufferSize(&qs->text);
 
					MoveTextBufferPos(&qs->text, WKC_END);
 
					this->InvalidateParent();
 
					delete this;
 
				}
 
				break;
 
		}
 
	}
 

	
 
	void InvalidateParent()
 
	{
 
		QueryStringBaseWindow *w = dynamic_cast<QueryStringBaseWindow*>(this->parent);
 
		if (w != NULL) w->OnOSKInput(this->text_btn);
 

	
 
		this->InvalidateWidget(OSK_WIDGET_TEXT);
 
		if (this->parent != NULL) this->parent->InvalidateWidget(this->text_btn);
 
		this->SetWidgetDirty(OSK_WIDGET_TEXT);
 
		if (this->parent != NULL) this->parent->SetWidgetDirty(this->text_btn);
 
	}
 

	
 
	virtual void OnMouseLoop()
 
	{
 
		this->qs->HandleEditBox(this, OSK_WIDGET_TEXT);
 
		/* make the caret of the parent window also blink */
 
		this->parent->InvalidateWidget(this->text_btn);
 
		this->parent->SetWidgetDirty(this->text_btn);
 
	}
 

	
 
	virtual void OnInvalidateData(int)
 
	{
 
		this->InvalidateWidget(OSK_WIDGET_TEXT);
 
		this->SetWidgetDirty(OSK_WIDGET_TEXT);
 
	}
 
};
 

	
 
static const Widget _osk_widgets[] = {
 
{    WWT_CAPTION, RESIZE_NONE,  COLOUR_GREY,     0,   255,     0,    13, STR_WHITE_STRING,  STR_NULL}, // OSK_WIDGET_CAPTION
 
{      WWT_PANEL, RESIZE_NONE,  COLOUR_GREY,     0,   255,    14,    29, 0x0,               STR_NULL}, // OSK_WIDGET_TEXT_BACKGROUND
 
{    WWT_EDITBOX, RESIZE_NONE,  COLOUR_GREY,     2,   253,    16,    27, 0x0,               STR_NULL}, // OSK_WIDGET_TEXT
 

	
 
{      WWT_PANEL, RESIZE_NONE,  COLOUR_GREY,     0,   255,    30,   139, 0x0,               STR_NULL}, // OSK_WIDGET_KEYS_BACKGROUND
 

	
 
{    WWT_TEXTBTN, RESIZE_NONE,  COLOUR_GREY,     3,   108,    35,    46, STR_BUTTON_CANCEL, STR_NULL}, // OSK_WIDGET_CANCEL
 
{    WWT_TEXTBTN, RESIZE_NONE,  COLOUR_GREY,   111,   216,    35,    46, STR_BUTTON_OK,     STR_NULL}, // OSK_WIDGET_OK
 
{ WWT_PUSHIMGBTN, RESIZE_NONE,  COLOUR_GREY,   219,   252,    35,    46, SPR_OSK_BACKSPACE, STR_NULL}, // OSK_WIDGET_BACKSPACE
 

	
 
{ WWT_PUSHIMGBTN, RESIZE_NONE,  COLOUR_GREY,     3,    27,    67,    82, SPR_OSK_SPECIAL,   STR_NULL}, // OSK_WIDGET_SPECIAL
 
{     WWT_IMGBTN, RESIZE_NONE,  COLOUR_GREY,     3,    36,    85,   100, SPR_OSK_CAPS,      STR_NULL}, // OSK_WIDGET_CAPS
 
{     WWT_IMGBTN, RESIZE_NONE,  COLOUR_GREY,     3,    27,   103,   118, SPR_OSK_SHIFT,     STR_NULL}, // OSK_WIDGET_SHIFT
 

	
 
{ WWT_PUSHTXTBTN, RESIZE_NONE,  COLOUR_GREY,    75,   189,   121,   136, STR_EMPTY,         STR_NULL}, // OSK_WIDGET_SPACE
 

	
 
{ WWT_PUSHIMGBTN, RESIZE_NONE,  COLOUR_GREY,   219,   234,   121,   136, SPR_OSK_LEFT,      STR_NULL}, // OSK_WIDGET_LEFT
 
{ WWT_PUSHIMGBTN, RESIZE_NONE,  COLOUR_GREY,   237,   252,   121,   136, SPR_OSK_RIGHT,     STR_NULL}, // OSK_WIDGET_RIGHT
 

	
 
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,     3,    18,    49,    64, 0x0,    STR_NULL},            // OSK_WIDGET_NUMBERS_FIRST = OSK_WIDGET_LETTERS
src/rail_gui.cpp
Show inline comments
 
@@ -293,49 +293,49 @@ enum RailToolbarWidgets {
 
	RTW_BUILD_NS,
 
	RTW_BUILD_X,
 
	RTW_BUILD_EW,
 
	RTW_BUILD_Y,
 
	RTW_AUTORAIL,
 
	RTW_DEMOLISH,
 
	RTW_BUILD_DEPOT,
 
	RTW_BUILD_WAYPOINT,
 
	RTW_BUILD_STATION,
 
	RTW_BUILD_SIGNALS,
 
	RTW_BUILD_BRIDGE,
 
	RTW_BUILD_TUNNEL,
 
	RTW_REMOVE,
 
	RTW_CONVERT_RAIL,
 
};
 

	
 

	
 
/** Toggles state of the Remove button of Build rail toolbar
 
 * @param w window the button belongs to
 
 */
 
static void ToggleRailButton_Remove(Window *w)
 
{
 
	DeleteWindowById(WC_SELECT_STATION, 0);
 
	w->ToggleWidgetLoweredState(RTW_REMOVE);
 
	w->InvalidateWidget(RTW_REMOVE);
 
	w->SetWidgetDirty(RTW_REMOVE);
 
	_remove_button_clicked = w->IsWidgetLowered(RTW_REMOVE);
 
	SetSelectionRed(_remove_button_clicked);
 
}
 

	
 
/** Updates the Remove button because of Ctrl state change
 
 * @param w window the button belongs to
 
 * @return true iff the remove buton was changed
 
 */
 
static bool RailToolbar_CtrlChanged(Window *w)
 
{
 
	if (w->IsWidgetDisabled(RTW_REMOVE)) return false;
 

	
 
	/* allow ctrl to switch remove mode only for these widgets */
 
	for (uint i = RTW_BUILD_NS; i <= RTW_BUILD_STATION; i++) {
 
		if ((i <= RTW_AUTORAIL || i >= RTW_BUILD_WAYPOINT) && w->IsWidgetLowered(i)) {
 
			ToggleRailButton_Remove(w);
 
			return true;
 
		}
 
	}
 

	
 
	return false;
 
}
 

	
 

	
 
@@ -774,49 +774,49 @@ struct BuildRailToolbarWindow : Window {
 
							HandleStationPlacement(start_tile, end_tile);
 
						}
 
					} else {
 
						/* Waypoint */
 
						if (_remove_button_clicked) {
 
							DoCommandP(end_tile, start_tile, _ctrl_pressed ? 0 : 1, CMD_REMOVE_FROM_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_REMOVE_TRAIN_WAYPOINT), CcPlaySound1E);
 
						} else {
 
							TileArea ta(start_tile, end_tile);
 
							uint32 p1 = _cur_railtype | (select_method == VPM_FIX_X ? AXIS_X : AXIS_Y) << 4 | ta.w << 8 | ta.h << 16 | _ctrl_pressed << 24;
 
							uint32 p2 = STAT_CLASS_WAYP | _cur_waypoint_type << 8 | INVALID_STATION << 16;
 

	
 
							CommandContainer cmdcont = { ta.tile, p1, p2, CMD_BUILD_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT), CcPlaySound1E, "" };
 
							ShowSelectWaypointIfNeeded(cmdcont, ta);
 
						}
 
					}
 
					break;
 
			}
 
		}
 
	}
 

	
 
	virtual void OnPlaceObjectAbort()
 
	{
 
		this->RaiseButtons();
 
		this->DisableWidget(RTW_REMOVE);
 
		this->InvalidateWidget(RTW_REMOVE);
 
		this->SetWidgetDirty(RTW_REMOVE);
 

	
 
		DeleteWindowById(WC_BUILD_SIGNAL, TRANSPORT_RAIL);
 
		DeleteWindowById(WC_BUILD_STATION, TRANSPORT_RAIL);
 
		DeleteWindowById(WC_BUILD_DEPOT, TRANSPORT_RAIL);
 
		DeleteWindowById(WC_SELECT_STATION, 0);
 
		DeleteWindowByClass(WC_BUILD_BRIDGE);
 
	}
 

	
 
	virtual void OnPlacePresize(Point pt, TileIndex tile)
 
	{
 
		DoCommand(tile, _cur_railtype, 0, DC_AUTO, CMD_BUILD_TUNNEL);
 
		VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
 
	}
 

	
 
	virtual EventState OnCTRLStateChange()
 
	{
 
		/* do not toggle Remove button by Ctrl when placing station */
 
		if (!this->IsWidgetLowered(RTW_BUILD_STATION) && !this->IsWidgetLowered(RTW_BUILD_WAYPOINT) && RailToolbar_CtrlChanged(this)) return ES_HANDLED;
 
		return ES_NOT_HANDLED;
 
	}
 
};
 

	
 
static const NWidgetPart _nested_build_rail_widgets[] = {
 
	NWidget(NWID_HORIZONTAL),
 
@@ -1580,56 +1580,56 @@ public:
 
			case BSW_SEMAPHORE_ENTRY:
 
			case BSW_SEMAPHORE_EXIT:
 
			case BSW_SEMAPHORE_COMBO:
 
			case BSW_SEMAPHORE_PBS:
 
			case BSW_SEMAPHORE_PBS_OWAY:
 
			case BSW_ELECTRIC_NORM:
 
			case BSW_ELECTRIC_ENTRY:
 
			case BSW_ELECTRIC_EXIT:
 
			case BSW_ELECTRIC_COMBO:
 
			case BSW_ELECTRIC_PBS:
 
			case BSW_ELECTRIC_PBS_OWAY:
 
				this->RaiseWidget((_cur_signal_variant == SIG_ELECTRIC ? BSW_ELECTRIC_NORM : BSW_SEMAPHORE_NORM) + _cur_signal_type);
 

	
 
				_cur_signal_type = (SignalType)((uint)((widget - BSW_SEMAPHORE_NORM) % (SIGTYPE_LAST + 1)));
 
				_cur_signal_variant = widget >= BSW_ELECTRIC_NORM ? SIG_ELECTRIC : SIG_SEMAPHORE;
 
				break;
 

	
 
			case BSW_CONVERT:
 
				_convert_signal_button = !_convert_signal_button;
 
				break;
 

	
 
			case BSW_DRAG_SIGNALS_DENSITY_DECREASE:
 
				if (_settings_client.gui.drag_signals_density > 1) {
 
					_settings_client.gui.drag_signals_density--;
 
					InvalidateWindow(WC_GAME_OPTIONS, 0);
 
					SetWindowDirty(WC_GAME_OPTIONS, 0);
 
				}
 
				break;
 

	
 
			case BSW_DRAG_SIGNALS_DENSITY_INCREASE:
 
				if (_settings_client.gui.drag_signals_density < 20) {
 
					_settings_client.gui.drag_signals_density++;
 
					InvalidateWindow(WC_GAME_OPTIONS, 0);
 
					SetWindowDirty(WC_GAME_OPTIONS, 0);
 
				}
 
				break;
 

	
 
			default: break;
 
		}
 

	
 
		this->SetDirty();
 
	}
 
};
 

	
 
/** Nested widget definition of the build signal window */
 
static const NWidgetPart _nested_signal_builder_widgets[] = {
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN, BSW_CLOSEBOX),
 
		NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, BSW_CAPTION), SetDataTip( STR_BUILD_SIGNAL_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
 
	EndContainer(),
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_NORM), SetMinimalSize(22, 27), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_NORM_TOOLTIP), EndContainer(),
 
		NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_ENTRY), SetMinimalSize(22, 27), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_ENTRY_TOOLTIP), EndContainer(),
 
		NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_EXIT), SetMinimalSize(22, 27), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_EXIT_TOOLTIP), EndContainer(),
 
		NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_COMBO), SetMinimalSize(22, 27), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_COMBO_TOOLTIP), EndContainer(),
 
		NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_PBS), SetMinimalSize(22, 27), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_PBS_TOOLTIP), EndContainer(),
 
		NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BSW_SEMAPHORE_PBS_OWAY), SetMinimalSize(22, 27), SetDataTip(STR_NULL, STR_BUILD_SIGNAL_SEMAPHORE_PBS_OWAY_TOOLTIP), EndContainer(),
 
		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, BSW_CONVERT), SetMinimalSize(22, 27), SetDataTip(SPR_IMG_SIGNAL_CONVERT, STR_BUILD_SIGNAL_CONVERT_TOOLTIP),
src/road_gui.cpp
Show inline comments
 
@@ -246,49 +246,49 @@ enum RoadToolbarWidgets {
 
	RTW_CAPTION,
 
	RTW_STICKY,
 
	RTW_ROAD_X,
 
	RTW_ROAD_Y,
 
	RTW_AUTOROAD,
 
	RTW_DEMOLISH,
 
	RTW_DEPOT,
 
	RTW_BUS_STATION,
 
	RTW_TRUCK_STATION,
 
	RTW_ONE_WAY,
 
	RTW_BUILD_BRIDGE,
 
	RTW_BUILD_TUNNEL,
 
	RTW_REMOVE,
 
};
 

	
 
typedef void OnButtonClick(Window *w);
 

	
 

	
 
/** Toogles state of the Remove button of Build road toolbar
 
 * @param w window the button belongs to
 
 */
 
static void ToggleRoadButton_Remove(Window *w)
 
{
 
	w->ToggleWidgetLoweredState(RTW_REMOVE);
 
	w->InvalidateWidget(RTW_REMOVE);
 
	w->SetWidgetDirty(RTW_REMOVE);
 
	_remove_button_clicked = w->IsWidgetLowered(RTW_REMOVE);
 
	SetSelectionRed(_remove_button_clicked);
 
}
 

	
 
/** Updates the Remove button because of Ctrl state change
 
 * @param w window the button belongs to
 
 * @return true iff the remove buton was changed
 
 */
 
static bool RoadToolbar_CtrlChanged(Window *w)
 
{
 
	if (w->IsWidgetDisabled(RTW_REMOVE)) return false;
 

	
 
	/* allow ctrl to switch remove mode only for these widgets */
 
	for (uint i = RTW_ROAD_X; i <= RTW_AUTOROAD; i++) {
 
		if (w->IsWidgetLowered(i)) {
 
			ToggleRoadButton_Remove(w);
 
			return true;
 
		}
 
	}
 

	
 
	return false;
 
}
 

	
 

	
 
@@ -426,54 +426,54 @@ struct BuildRoadToolbarWindow : Window {
 
			RTW_TRUCK_STATION,
 
			WIDGET_LIST_END);
 

	
 
		if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
 
	}
 

	
 
	~BuildRoadToolbarWindow()
 
	{
 
		if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
 
	}
 

	
 
	/**
 
	 * Update the remove button lowered state of the road toolbar
 
	 *
 
	 * @param clicked_widget The widget which the client clicked just now
 
	 */
 
	void UpdateOptionWidgetStatus(RoadToolbarWidgets clicked_widget)
 
	{
 
		/* The remove and the one way button state is driven
 
		 * by the other buttons so they don't act on themselfs.
 
		 * Both are only valid if they are able to apply as options. */
 
		switch (clicked_widget) {
 
			case RTW_REMOVE:
 
				this->RaiseWidget(RTW_ONE_WAY);
 
				this->InvalidateWidget(RTW_ONE_WAY);
 
				this->SetWidgetDirty(RTW_ONE_WAY);
 
				break;
 

	
 
			case RTW_ONE_WAY:
 
				this->RaiseWidget(RTW_REMOVE);
 
				this->InvalidateWidget(RTW_REMOVE);
 
				this->SetWidgetDirty(RTW_REMOVE);
 
				break;
 

	
 
			case RTW_BUS_STATION:
 
			case RTW_TRUCK_STATION:
 
				this->DisableWidget(RTW_ONE_WAY);
 
				this->SetWidgetDisabledState(RTW_REMOVE, !this->IsWidgetLowered(clicked_widget));
 
				break;
 

	
 
			case RTW_ROAD_X:
 
			case RTW_ROAD_Y:
 
			case RTW_AUTOROAD:
 
				this->SetWidgetsDisabledState(!this->IsWidgetLowered(clicked_widget),
 
					RTW_REMOVE,
 
					RTW_ONE_WAY,
 
					WIDGET_LIST_END);
 
				break;
 

	
 
			default:
 
				/* When any other buttons than road/station, raise and
 
				 * disable the removal button */
 
				this->SetWidgetsDisabledState(true,
 
					RTW_REMOVE,
 
					RTW_ONE_WAY,
 
					WIDGET_LIST_END);
 
@@ -512,50 +512,50 @@ struct BuildRoadToolbarWindow : Window {
 
				this->UpdateOptionWidgetStatus((RoadToolbarWidgets)(i + RTW_ROAD_X));
 
				if (_ctrl_pressed) RoadToolbar_CtrlChanged(this);
 
				state = ES_HANDLED;
 
				break;
 
			}
 
		}
 
		MarkTileDirtyByTile(TileVirtXY(_thd.pos.x, _thd.pos.y)); // redraw tile selection
 
		return state;
 
	}
 

	
 
	virtual void OnPlaceObject(Point pt, TileIndex tile)
 
	{
 
		_remove_button_clicked = this->IsWidgetLowered(RTW_REMOVE);
 
		_one_way_button_clicked = this->IsWidgetLowered(RTW_ONE_WAY);
 
		_place_proc(tile);
 
	}
 

	
 
	virtual void OnPlaceObjectAbort()
 
	{
 
		this->RaiseButtons();
 
		this->SetWidgetsDisabledState(true,
 
			RTW_REMOVE,
 
			RTW_ONE_WAY,
 
			WIDGET_LIST_END);
 
		this->InvalidateWidget(RTW_REMOVE);
 
		this->InvalidateWidget(RTW_ONE_WAY);
 
		this->SetWidgetDirty(RTW_REMOVE);
 
		this->SetWidgetDirty(RTW_ONE_WAY);
 

	
 
		DeleteWindowById(WC_BUS_STATION, TRANSPORT_ROAD);
 
		DeleteWindowById(WC_TRUCK_STATION, TRANSPORT_ROAD);
 
		DeleteWindowById(WC_BUILD_DEPOT, TRANSPORT_ROAD);
 
		DeleteWindowById(WC_SELECT_STATION, 0);
 
		DeleteWindowByClass(WC_BUILD_BRIDGE);
 
	}
 

	
 
	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
 
	{
 
		/* Here we update the end tile flags
 
		 * of the road placement actions.
 
		 * At first we reset the end halfroad
 
		 * bits and if needed we set them again. */
 
		switch (select_proc) {
 
			case DDSP_PLACE_ROAD_X_DIR:
 
				_place_road_flag &= ~RF_END_HALFROAD_X;
 
				if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
 
				break;
 

	
 
			case DDSP_PLACE_ROAD_Y_DIR:
 
				_place_road_flag &= ~RF_END_HALFROAD_Y;
 
				if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
 
				break;
src/roadveh_cmd.cpp
Show inline comments
 
@@ -274,49 +274,49 @@ CommandCost CmdBuildRoadVeh(TileIndex ti
 
		v->compatible_roadtypes = RoadTypeToRoadTypes(v->roadtype);
 
		v->rcache.cached_veh_length = 8;
 

	
 
		v->vehicle_flags = 0;
 
		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
 

	
 
		v->cargo_cap = rvi->capacity;
 

	
 
		AddArticulatedParts(v, VEH_ROAD);
 
		v->InvalidateNewGRFCacheOfChain();
 

	
 
		/* Call various callbacks after the whole consist has been constructed */
 
		for (RoadVehicle *u = v; u != NULL; u = u->Next()) {
 
			u->rcache.cached_veh_length = GetRoadVehLength(u);
 
			/* Cargo capacity is zero if and only if the vehicle cannot carry anything */
 
			if (u->cargo_cap != 0) u->cargo_cap = GetVehicleProperty(u, 0x0F, u->cargo_cap);
 
			v->InvalidateNewGRFCache();
 
			u->InvalidateNewGRFCache();
 
		}
 

	
 
		VehicleMove(v, false);
 

	
 
		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 
		InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
 
		InvalidateWindow(WC_COMPANY, v->owner);
 
		SetWindowDirty(WC_COMPANY, v->owner);
 
		if (IsLocalCompany()) {
 
			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Road window
 
		}
 

	
 
		Company::Get(_current_company)->num_engines[p1]++;
 

	
 
		CheckConsistencyOfArticulatedVehicle(v);
 
	}
 

	
 
	return cost;
 
}
 

	
 
void ClearSlot(RoadVehicle *v)
 
{
 
	RoadStop *rs = v->slot;
 
	if (v->slot == NULL) return;
 

	
 
	v->slot = NULL;
 
	v->slot_age = 0;
 

	
 
	assert(rs->num_vehicles != 0);
 
	rs->num_vehicles--;
 

	
 
	DEBUG(ms, 3, "Clearing slot at 0x%X", rs->xy);
 
@@ -599,109 +599,109 @@ static Vehicle *EnumCheckRoadVehCrashTra
 
	return
 
		v->type == VEH_TRAIN &&
 
		abs(v->z_pos - u->z_pos) <= 6 &&
 
		abs(v->x_pos - u->x_pos) <= 4 &&
 
		abs(v->y_pos - u->y_pos) <= 4 ?
 
			v : NULL;
 
}
 

	
 
static void RoadVehCrash(RoadVehicle *v)
 
{
 
	uint16 pass = 1;
 

	
 
	v->crashed_ctr++;
 

	
 
	for (Vehicle *u = v; u != NULL; u = u->Next()) {
 
		if (IsCargoInClass(u->cargo_type, CC_PASSENGERS)) pass += u->cargo.Count();
 

	
 
		u->vehstatus |= VS_CRASHED;
 

	
 
		MarkSingleVehicleDirty(u);
 
	}
 

	
 
	ClearSlot(v);
 

	
 
	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 

	
 
	AI::NewEvent(v->owner, new AIEventVehicleCrashed(v->index, v->tile, AIEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING));
 

	
 
	SetDParam(0, pass);
 
	AddVehicleNewsItem(
 
		(pass == 1) ?
 
			STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER : STR_NEWS_ROAD_VEHICLE_CRASH,
 
		NS_ACCIDENT,
 
		v->index
 
	);
 

	
 
	ModifyStationRatingAround(v->tile, v->owner, -160, 22);
 
	SndPlayVehicleFx(SND_12_EXPLOSION, v);
 
}
 

	
 
static bool RoadVehCheckTrainCrash(RoadVehicle *v)
 
{
 
	for (RoadVehicle *u = v; u != NULL; u = u->Next()) {
 
		if (u->state == RVSB_WORMHOLE) continue;
 

	
 
		TileIndex tile = u->tile;
 

	
 
		if (!IsLevelCrossingTile(tile)) continue;
 

	
 
		if (HasVehicleOnPosXY(v->x_pos, v->y_pos, u, EnumCheckRoadVehCrashTrain)) {
 
			RoadVehCrash(v);
 
			return true;
 
		}
 
	}
 

	
 
	return false;
 
}
 

	
 
static void HandleBrokenRoadVeh(RoadVehicle *v)
 
{
 
	if (v->breakdown_ctr != 1) {
 
		v->breakdown_ctr = 1;
 
		v->cur_speed = 0;
 

	
 
		if (v->breakdowns_since_last_service != 255)
 
			v->breakdowns_since_last_service++;
 

	
 
		InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 
		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
		SetWindowDirty(WC_VEHICLE_VIEW, v->index);
 
		SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
 

	
 
		if (!PlayVehicleSound(v, VSE_BREAKDOWN)) {
 
			SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ?
 
				SND_0F_VEHICLE_BREAKDOWN : SND_35_COMEDY_BREAKDOWN, v);
 
		}
 

	
 
		if (!(v->vehstatus & VS_HIDDEN)) {
 
			EffectVehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE);
 
			if (u != NULL) u->animation_state = v->breakdown_delay * 2;
 
		}
 
	}
 

	
 
	if ((v->tick_counter & 1) == 0) {
 
		if (--v->breakdown_delay == 0) {
 
			v->breakdown_ctr = 0;
 
			InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 
			SetWindowDirty(WC_VEHICLE_VIEW, v->index);
 
		}
 
	}
 
}
 

	
 
TileIndex RoadVehicle::GetOrderStationLocation(StationID station)
 
{
 
	if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
 

	
 
	TileIndex dest;
 
	if (YapfFindNearestRoadVehicleCompatibleStop(this, station, &dest)) {
 
		return dest;
 
	} else {
 
		/* There is no stop left at the station, so don't even TRY to go there */
 
		this->IncrementOrderIndex();
 
		return 0;
 
	}
 
}
 

	
 
static void StartRoadVehSound(const RoadVehicle *v)
 
{
 
	if (!PlayVehicleSound(v, VSE_START)) {
 
		SoundID s = RoadVehInfo(v->engine_type)->sfx;
 
		if (s == SND_19_BUS_START_PULL_AWAY && (v->tick_counter & 3) == 0)
 
			s = SND_1A_BUS_START_PULL_AWAY_WITH_HORN;
 
@@ -815,49 +815,49 @@ static void RoadVehArrivesAt(const RoadV
 

	
 
static int RoadVehAccelerate(RoadVehicle *v)
 
{
 
	uint oldspeed = v->cur_speed;
 
	uint accel = 256 + (v->overtaking != 0 ? 256 : 0);
 
	uint spd = v->subspeed + accel;
 

	
 
	v->subspeed = (uint8)spd;
 

	
 
	int tempmax = v->max_speed;
 
	if (v->cur_speed > v->max_speed) {
 
		tempmax = v->cur_speed - (v->cur_speed / 10) - 1;
 
	}
 

	
 
	v->cur_speed = spd = Clamp(v->cur_speed + ((int)spd >> 8), 0, tempmax);
 

	
 
	/* Apply bridge speed limit */
 
	if (v->state == RVSB_WORMHOLE && !(v->vehstatus & VS_HIDDEN)) {
 
		v->cur_speed = min(v->cur_speed, GetBridgeSpec(GetBridgeType(v->tile))->speed * 2);
 
	}
 

	
 
	/* Update statusbar only if speed has changed to save CPU time */
 
	if (oldspeed != v->cur_speed) {
 
		if (_settings_client.gui.vehicle_speed) {
 
			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
			SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
		}
 
	}
 

	
 
	/* Speed is scaled in the same manner as for trains. @see train_cmd.cpp */
 
	int scaled_spd = spd * 3 >> 2;
 

	
 
	scaled_spd += v->progress;
 
	v->progress = 0;
 
	return scaled_spd;
 
}
 

	
 
static Direction RoadVehGetNewDirection(const RoadVehicle *v, int x, int y)
 
{
 
	static const Direction _roadveh_new_dir[] = {
 
		DIR_N , DIR_NW, DIR_W , INVALID_DIR,
 
		DIR_NE, DIR_N , DIR_SW, INVALID_DIR,
 
		DIR_E , DIR_SE, DIR_S
 
	};
 

	
 
	x = x - v->x_pos + 1;
 
	y = y - v->y_pos + 1;
 

	
 
	if ((uint)x > 2 || (uint)y > 2) return v->direction;
 
	return _roadveh_new_dir[y * 4 + x];
 
@@ -1709,49 +1709,49 @@ again:
 
		} else if (v->slot != NULL) {
 
			/* We are leaving the wrong station
 
			 * XXX The question is .. what to do? Actually we shouldn't be here
 
			 * but I guess we need to clear the slot */
 
			DEBUG(ms, 0, "Vehicle %d (index %d) arrived at wrong stop", v->unitnumber, v->index);
 
			if (v->tile != v->dest_tile) {
 
				DEBUG(ms, 2, " current tile 0x%X is not destination tile 0x%X. Route problem", v->tile, v->dest_tile);
 
			}
 
			if (v->dest_tile != v->slot->xy) {
 
				DEBUG(ms, 2, " stop tile 0x%X is not destination tile 0x%X. Multistop desync", v->slot->xy, v->dest_tile);
 
			}
 
			if (!v->current_order.IsType(OT_GOTO_STATION)) {
 
				DEBUG(ms, 2, " current order type (%d) is not OT_GOTO_STATION", v->current_order.GetType());
 
			} else {
 
				if (v->current_order.GetDestination() != st->index)
 
					DEBUG(ms, 2, " current station %d is not target station in current_order.station (%d)",
 
							st->index, v->current_order.GetDestination());
 
			}
 

	
 
			DEBUG(ms, 2, " force a slot clearing");
 
			ClearSlot(v);
 
		}
 

	
 
		StartRoadVehSound(v);
 
		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
		SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	}
 

	
 
	/* Check tile position conditions - i.e. stop position in depot,
 
	 * entry onto bridge or into tunnel */
 
	uint32 r = VehicleEnterTile(v, v->tile, x, y);
 
	if (HasBit(r, VETS_CANNOT_ENTER)) {
 
		v->cur_speed = 0;
 
		return false;
 
	}
 

	
 
	if (v->current_order.IsType(OT_LEAVESTATION) && IsDriveThroughStopTile(v->tile)) {
 
		v->current_order.Free();
 
		ClearSlot(v);
 
	}
 

	
 
	/* Move to next frame unless vehicle arrived at a stop position
 
	 * in a depot or entered a tunnel/bridge */
 
	if (!HasBit(r, VETS_ENTERED_WORMHOLE)) v->frame++;
 

	
 
	RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true));
 
	return true;
 
}
 

	
 
static bool RoadVehController(RoadVehicle *v)
 
@@ -1824,67 +1824,67 @@ bool RoadVehicle::Tick()
 
	}
 

	
 
	return true;
 
}
 

	
 
static void CheckIfRoadVehNeedsService(RoadVehicle *v)
 
{
 
	static const uint MAX_ACCEPTABLE_DEPOT_DIST = 16;
 

	
 
	/* If we already got a slot at a stop, use that FIRST, and go to a depot later */
 
	if (v->slot != NULL || Company::Get(v->owner)->settings.vehicle.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return;
 
	if (v->IsInDepot()) {
 
		VehicleServiceInDepot(v);
 
		return;
 
	}
 

	
 
	RoadFindDepotData rfdd = FindClosestRoadDepot(v, MAX_ACCEPTABLE_DEPOT_DIST);
 
	/* Only go to the depot if it is not too far out of our way. */
 
	if (rfdd.best_length == UINT_MAX || rfdd.best_length > MAX_ACCEPTABLE_DEPOT_DIST) {
 
		if (v->current_order.IsType(OT_GOTO_DEPOT)) {
 
			/* If we were already heading for a depot but it has
 
			 * suddenly moved farther away, we continue our normal
 
			 * schedule? */
 
			v->current_order.MakeDummy();
 
			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
			SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
		}
 
		return;
 
	}
 

	
 
	DepotID depot = GetDepotIndex(rfdd.tile);
 

	
 
	if (v->current_order.IsType(OT_GOTO_DEPOT) &&
 
			v->current_order.GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS &&
 
			!Chance16(1, 20)) {
 
		return;
 
	}
 

	
 
	if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
 
	ClearSlot(v);
 

	
 
	v->current_order.MakeGoToDepot(depot, ODTFB_SERVICE);
 
	v->dest_tile = rfdd.tile;
 
	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
}
 

	
 
void RoadVehicle::OnNewDay()
 
{
 
	if (!this->IsRoadVehFront()) return;
 

	
 
	if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
 
	if (this->blocked_ctr == 0) CheckVehicleBreakdown(this);
 

	
 
	AgeVehicle(this);
 
	CheckIfRoadVehNeedsService(this);
 

	
 
	CheckOrders(this);
 

	
 
	/* Current slot has expired */
 
	if (this->current_order.IsType(OT_GOTO_STATION) && this->slot != NULL && this->slot_age-- == 0) {
 
		DEBUG(ms, 3, "Slot expired for vehicle %d (index %d) at stop 0x%X",
 
			this->unitnumber, this->index, this->slot->xy);
 
		ClearSlot(this);
 
	}
 

	
 
	/* update destination */
 
	if (!(this->vehstatus & VS_STOPPED) && this->current_order.IsType(OT_GOTO_STATION) && !(this->current_order.GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) && this->slot == NULL && !(this->vehstatus & VS_CRASHED)) {
 
		Station *st = Station::Get(this->current_order.GetDestination());
 
@@ -1936,50 +1936,50 @@ void RoadVehicle::OnNewDay()
 
					this->dest_tile = best->xy;
 
					this->slot_age = 14;
 
				} else {
 
					DEBUG(ms, 3, "Could not find a suitable stop");
 
				}
 
			} else {
 
				DEBUG(ms, 5, "Distance from station too far. Postponing slotting for vehicle %d (index %d) at station %d, (0x%X)",
 
						this->unitnumber, this->index, st->index, st->xy);
 
			}
 
		} else {
 
			DEBUG(ms, 4, "No road stop for vehicle %d (index %d) at station %d (0x%X)",
 
					this->unitnumber, this->index, st->index, st->xy);
 
		}
 
	}
 

	
 
	if (this->running_ticks == 0) return;
 

	
 
	CommandCost cost(EXPENSES_ROADVEH_RUN, this->GetRunningCost() * this->running_ticks / (DAYS_IN_YEAR * DAY_TICKS));
 

	
 
	this->profit_this_year -= cost.GetCost();
 
	this->running_ticks = 0;
 

	
 
	SubtractMoneyFromCompanyFract(this->owner, cost);
 

	
 
	InvalidateWindow(WC_VEHICLE_DETAILS, this->index);
 
	InvalidateWindowClasses(WC_ROADVEH_LIST);
 
	SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
 
	SetWindowClassesDirty(WC_ROADVEH_LIST);
 
}
 

	
 
Trackdir RoadVehicle::GetVehicleTrackdir() const
 
{
 
	if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
 

	
 
	if (this->IsInDepot()) {
 
		/* We'll assume the road vehicle is facing outwards */
 
		return DiagDirToDiagTrackdir(GetRoadDepotDirection(this->tile));
 
	}
 

	
 
	if (IsStandardRoadStopTile(this->tile)) {
 
		/* We'll assume the road vehicle is facing outwards */
 
		return DiagDirToDiagTrackdir(GetRoadStopDir(this->tile)); // Road vehicle in a station
 
	}
 

	
 
	/* Drive through road stops / wormholes (tunnels) */
 
	if (this->state > RVSB_TRACKDIR_MASK) return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
 

	
 
	/* If vehicle's state is a valid track direction (vehicle is not turning around) return it,
 
	 * otherwise transform it into a valid track direction */
 
	return (Trackdir)((IsReversingRoadTrackdir((Trackdir)this->state)) ? (this->state - 6) : this->state);
 
}
 

	
 
@@ -2048,36 +2048,36 @@ CommandCost CmdRefitRoadVeh(TileIndex ti
 
				case CT_PASSENGERS: break;
 
				case CT_MAIL:
 
				case CT_GOODS: capacity *= 2; break;
 
				default:       capacity *= 4; break;
 
			}
 
			switch (new_cid) {
 
				case CT_PASSENGERS: break;
 
				case CT_MAIL:
 
				case CT_GOODS: capacity /= 2; break;
 
				default:       capacity /= 4; break;
 
			}
 
		}
 

	
 
		total_capacity += capacity;
 

	
 
		if (new_cid != v->cargo_type) {
 
			cost.AddCost(GetRefitCost(v->engine_type));
 
		}
 

	
 
		if (flags & DC_EXEC) {
 
			v->cargo_cap = capacity;
 
			v->cargo.Truncate((v->cargo_type == new_cid) ? capacity : 0);
 
			v->cargo_type = new_cid;
 
			v->cargo_subtype = new_subtype;
 
			InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
			InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
			SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
 
			SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);
 
			InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
 
		}
 
	}
 

	
 
	if (flags & DC_EXEC) RoadVehUpdateCache(RoadVehicle::Get(p1)->First());
 

	
 
	_returned_refit_capacity = total_capacity;
 

	
 
	return cost;
 
}
src/settings.cpp
Show inline comments
 
@@ -643,55 +643,55 @@ static void ini_save_setting_list(IniFil
 
}
 

	
 
/* Begin - Callback Functions for the various settings
 
 * virtual PositionMainToolbar function, calls the right one.*/
 
static bool v_PositionMainToolbar(int32 p1)
 
{
 
	if (_game_mode != GM_MENU) PositionMainToolbar(NULL);
 
	return true;
 
}
 

	
 
static bool PopulationInLabelActive(int32 p1)
 
{
 
	UpdateAllTownVirtCoords();
 
	return true;
 
}
 

	
 
static bool RedrawScreen(int32 p1)
 
{
 
	MarkWholeScreenDirty();
 
	return true;
 
}
 

	
 
static bool InvalidateDetailsWindow(int32 p1)
 
{
 
	InvalidateWindowClasses(WC_VEHICLE_DETAILS);
 
	SetWindowClassesDirty(WC_VEHICLE_DETAILS);
 
	return true;
 
}
 

	
 
static bool InvalidateStationBuildWindow(int32 p1)
 
{
 
	InvalidateWindow(WC_BUILD_STATION, 0);
 
	SetWindowDirty(WC_BUILD_STATION, 0);
 
	return true;
 
}
 

	
 
static bool InvalidateBuildIndustryWindow(int32 p1)
 
{
 
	InvalidateWindowData(WC_BUILD_INDUSTRY, 0);
 
	return true;
 
}
 

	
 
static bool CloseSignalGUI(int32 p1)
 
{
 
	if (p1 == 0) {
 
		DeleteWindowByClass(WC_BUILD_SIGNAL);
 
	}
 
	return true;
 
}
 

	
 
static bool InvalidateTownViewWindow(int32 p1)
 
{
 
	InvalidateWindowClassesData(WC_TOWN_VIEW, p1);
 
	return true;
 
}
 

	
 
static bool DeleteSelectStationWindow(int32 p1)
 
@@ -731,49 +731,49 @@ static bool CheckInterval(int32 p1)
 
		vds->servint_aircraft = 360;
 
		vds->servint_ships    = 100;
 
	}
 

	
 
	InvalidateDetailsWindow(0);
 

	
 
	return true;
 
}
 

	
 
static bool TrainAccelerationModelChanged(int32 p1)
 
{
 
	Train *t;
 
	FOR_ALL_TRAINS(t) {
 
		if (t->IsFrontEngine()) {
 
			t->tcache.cached_max_curve_speed = GetTrainCurveSpeedLimit(t);
 
			UpdateTrainAcceleration(t);
 
		}
 
	}
 

	
 
	return true;
 
}
 

	
 
static bool DragSignalsDensityChanged(int32)
 
{
 
	InvalidateWindow(WC_BUILD_SIGNAL, 0);
 
	SetWindowDirty(WC_BUILD_SIGNAL, 0);
 

	
 
	return true;
 
}
 

	
 
/*
 
 * A: competitors
 
 * B: competitor start time. Deprecated since savegame version 110.
 
 * C: town count (3 = high, 0 = very low)
 
 * D: industry count (4 = high, 0 = none)
 
 * E: inital loan (in GBP)
 
 * F: interest rate
 
 * G: running costs (0 = low, 2 = high)
 
 * H: construction speed of competitors (0 = very slow, 4 = very fast)
 
 * I: competitor intelligence. Deprecated since savegame version 110.
 
 * J: breakdowns (0 = off, 2 = normal)
 
 * K: subsidy multiplier (0 = 1.5, 3 = 4.0)
 
 * L: construction cost (0-2)
 
 * M: terrain type (0 = very flat, 3 = mountainous)
 
 * N: amount of water (0 = very low, 3 = high)
 
 * O: economy (0 = steady, 1 = fluctuating)
 
 * P: Train reversing (0 = end of line + stations, 1 = end of line)
 
 * Q: disasters
 
 * R: area restructuring (0 = permissive, 2 = hostile)
 
 * S: the difficulty level
 
@@ -799,49 +799,49 @@ void SetDifficultyLevel(int mode, Diffic
 
/**
 
 * Checks the difficulty levels read from the configuration and
 
 * forces them to be correct when invalid.
 
 */
 
void CheckDifficultyLevels()
 
{
 
	if (_settings_newgame.difficulty.diff_level != 3) {
 
		SetDifficultyLevel(_settings_newgame.difficulty.diff_level, &_settings_newgame.difficulty);
 
	}
 
}
 

	
 
static bool DifficultyReset(int32 level)
 
{
 
	SetDifficultyLevel(level, (_game_mode == GM_MENU) ? &_settings_newgame.difficulty : &_settings_game.difficulty);
 
	return true;
 
}
 

	
 
static bool DifficultyChange(int32)
 
{
 
	if (_game_mode == GM_MENU) {
 
		if (_settings_newgame.difficulty.diff_level != 3) {
 
			ShowErrorMessage(INVALID_STRING_ID, STR_WARNING_DIFFICULTY_TO_CUSTOM, 0, 0);
 
			_settings_newgame.difficulty.diff_level = 3;
 
		}
 
		InvalidateWindowClasses(WC_SELECT_GAME);
 
		SetWindowClassesDirty(WC_SELECT_GAME);
 
	} else {
 
		_settings_game.difficulty.diff_level = 3;
 
	}
 

	
 
	/* If we are a network-client, update the difficult setting (if it is open).
 
	 * Use this instead of just dirtying the window because we need to load in
 
	 * the new difficulty settings */
 
	if (_networking && FindWindowById(WC_GAME_OPTIONS, 0) != NULL) {
 
		ShowGameDifficulty();
 
	}
 

	
 
	return true;
 
}
 

	
 
static bool DifficultyNoiseChange(int32 i)
 
{
 
	if (_game_mode == GM_NORMAL) {
 
		UpdateAirportsNoise();
 
		if (_settings_game.economy.station_noise_level) {
 
			InvalidateWindowClassesData(WC_TOWN_VIEW, 0);
 
		}
 
	}
 

	
 
	return DifficultyChange(i);
 
@@ -1425,112 +1425,112 @@ CommandCost CmdChangeSetting(TileIndex t
 

	
 
	if (flags & DC_EXEC) {
 
		GameSettings *s = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings_game;
 
		void *var = GetVariableAddress(s, &sd->save);
 

	
 
		int32 oldval = (int32)ReadValue(var, sd->save.conv);
 
		int32 newval = (int32)p2;
 

	
 
		Write_ValidateSetting(var, sd, newval);
 
		newval = (int32)ReadValue(var, sd->save.conv);
 

	
 
		if (oldval == newval) return CommandCost();
 

	
 
		if (sd->desc.proc != NULL && !sd->desc.proc(newval)) {
 
			WriteValue(var, sd->save.conv, (int64)oldval);
 
			return CommandCost();
 
		}
 

	
 
		if (sd->desc.flags & SGF_NO_NETWORK) {
 
			GamelogStartAction(GLAT_SETTING);
 
			GamelogSetting(sd->desc.name, oldval, newval);
 
			GamelogStopAction();
 
		}
 

	
 
		InvalidateWindow(WC_GAME_OPTIONS, 0);
 
		SetWindowDirty(WC_GAME_OPTIONS, 0);
 
	}
 

	
 
	return CommandCost();
 
}
 

	
 
/** Change one of the per-company settings.
 
 * @param tile unused
 
 * @param flags operation to perform
 
 * @param p1 the index of the setting in the _company_settings array which identifies it
 
 * @param p2 the new value for the setting
 
 * The new value is properly clamped to its minimum/maximum when setting
 
 */
 
CommandCost CmdChangeCompanySetting(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	if (p1 >= lengthof(_company_settings)) return CMD_ERROR;
 
	const SettingDesc *sd = &_company_settings[p1];
 

	
 
	if (flags & DC_EXEC) {
 
		void *var = GetVariableAddress(&Company::Get(_current_company)->settings, &sd->save);
 

	
 
		int32 oldval = (int32)ReadValue(var, sd->save.conv);
 
		int32 newval = (int32)p2;
 

	
 
		Write_ValidateSetting(var, sd, newval);
 
		newval = (int32)ReadValue(var, sd->save.conv);
 

	
 
		if (oldval == newval) return CommandCost();
 

	
 
		if (sd->desc.proc != NULL && !sd->desc.proc(newval)) {
 
			WriteValue(var, sd->save.conv, (int64)oldval);
 
			return CommandCost();
 
		}
 

	
 
		InvalidateWindow(WC_GAME_OPTIONS, 0);
 
		SetWindowDirty(WC_GAME_OPTIONS, 0);
 
	}
 

	
 
	return CommandCost();
 
}
 

	
 
/** Top function to save the new value of an element of the Settings struct
 
 * @param index offset in the SettingDesc array of the Settings struct which
 
 * identifies the setting member we want to change
 
 * @param object pointer to a valid settings struct that has its settings change.
 
 * This only affects setting-members that are not needed to be the same on all
 
 * clients in a network game.
 
 * @param value new value of the setting */
 
bool SetSettingValue(uint index, int32 value)
 
{
 
	const SettingDesc *sd = &_settings[index];
 
	/* If an item is company-based, we do not send it over the network
 
	 * (if any) to change. Also *hack*hack* we update the _newgame version
 
	 * of settings because changing a company-based setting in a game also
 
	 * changes its defaults. At least that is the convention we have chosen */
 
	if (sd->save.conv & SLF_NETWORK_NO) {
 
		void *var = GetVariableAddress((_game_mode == GM_MENU) ? &_settings_newgame : &_settings_game, &sd->save);
 
		Write_ValidateSetting(var, sd, value);
 

	
 
		if (_game_mode != GM_MENU) {
 
			void *var2 = GetVariableAddress(&_settings_newgame, &sd->save);
 
			Write_ValidateSetting(var2, sd, value);
 
		}
 
		if (sd->desc.proc != NULL) sd->desc.proc((int32)ReadValue(var, sd->save.conv));
 
		InvalidateWindow(WC_GAME_OPTIONS, 0);
 
		SetWindowDirty(WC_GAME_OPTIONS, 0);
 
		return true;
 
	}
 

	
 
	/* send non-company-based settings over the network */
 
	if (!_networking || (_networking && _network_server)) {
 
		return DoCommandP(0, index, value, CMD_CHANGE_SETTING);
 
	}
 
	return false;
 
}
 

	
 
/** Top function to save the new value of an element of the Settings struct
 
 * @param index offset in the SettingDesc array of the CompanySettings struct
 
 * which identifies the setting member we want to change
 
 * @param object pointer to a valid CompanySettings struct that has its settings changed.
 
 * @param value new value of the setting */
 
void SetCompanySetting(uint index, int32 value)
 
{
 
	const SettingDesc *sd = &_company_settings[index];
 
	if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
 
		DoCommandP(0, index, value, CMD_CHANGE_COMPANY_SETTING);
 
	} else {
 
		void *var = GetVariableAddress(&_settings_client.company, &sd->save);
 
		Write_ValidateSetting(var, sd, value);
 
		if (sd->desc.proc != NULL) sd->desc.proc((int32)ReadValue(var, sd->save.conv));
src/settings_gui.cpp
Show inline comments
 
@@ -363,49 +363,49 @@ struct GameOptionsWindow : Window {
 
		switch (widget) {
 
			case GOW_CURRENCY_DROPDOWN: // Currency
 
				if (index == CUSTOM_CURRENCY_ID) ShowCustCurrency();
 
				this->opt->locale.currency = index;
 
				MarkWholeScreenDirty();
 
				break;
 

	
 
			case GOW_DISTANCE_DROPDOWN: // Measuring units
 
				this->opt->locale.units = index;
 
				MarkWholeScreenDirty();
 
				break;
 

	
 
			case GOW_ROADSIDE_DROPDOWN: // Road side
 
				if (this->opt->vehicle.road_side != index) { // only change if setting changed
 
					uint i;
 
					if (GetSettingFromName("vehicle.road_side", &i) == NULL) NOT_REACHED();
 
					SetSettingValue(i, index);
 
					MarkWholeScreenDirty();
 
				}
 
				break;
 

	
 
			case GOW_TOWNNAME_DROPDOWN: // Town names
 
				if (_game_mode == GM_MENU || Town::GetNumItems() == 0) {
 
					this->opt->game_creation.town_name = index;
 
					InvalidateWindow(WC_GAME_OPTIONS, 0);
 
					SetWindowDirty(WC_GAME_OPTIONS, 0);
 
				}
 
				break;
 

	
 
			case GOW_AUTOSAVE_DROPDOWN: // Autosave options
 
				_settings_client.gui.autosave = index;
 
				this->SetDirty();
 
				break;
 

	
 
			case GOW_LANG_DROPDOWN: // Change interface language
 
				ReadLanguagePack(index);
 
				CheckForMissingGlyphsInLoadedLanguagePack();
 
				UpdateAllStationVirtCoords();
 
				ReInitAllWindows();
 
				break;
 

	
 
			case GOW_RESOLUTION_DROPDOWN: // Change resolution
 
				if (index < _num_resolutions && ChangeResInGame(_resolutions[index].width, _resolutions[index].height)) {
 
					this->SetDirty();
 
				}
 
				break;
 

	
 
			case GOW_SCREENSHOT_DROPDOWN: // Change screenshot format
 
				SetScreenshotFormat(index);
 
				this->SetDirty();
src/ship_cmd.cpp
Show inline comments
 
@@ -125,132 +125,132 @@ static const Depot *FindClosestShipDepot
 
			uint dist = DistanceManhattan(tile, v->tile);
 
			if (dist < best_dist) {
 
				best_dist = dist;
 
				best_depot = depot;
 
			}
 
		}
 
	}
 

	
 
	return best_depot;
 
}
 

	
 
static void CheckIfShipNeedsService(Vehicle *v)
 
{
 
	if (Company::Get(v->owner)->settings.vehicle.servint_ships == 0 || !v->NeedsAutomaticServicing()) return;
 
	if (v->IsInDepot()) {
 
		VehicleServiceInDepot(v);
 
		return;
 
	}
 

	
 
	const Depot *depot = FindClosestShipDepot(v);
 

	
 
	if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) {
 
		if (v->current_order.IsType(OT_GOTO_DEPOT)) {
 
			v->current_order.MakeDummy();
 
			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
			SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
		}
 
		return;
 
	}
 

	
 
	v->current_order.MakeGoToDepot(depot->index, ODTFB_SERVICE);
 
	v->dest_tile = depot->xy;
 
	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
}
 

	
 
Money Ship::GetRunningCost() const
 
{
 
	return GetVehicleProperty(this, 0x0F, ShipVehInfo(this->engine_type)->running_cost) * _price.ship_running;
 
}
 

	
 
void Ship::OnNewDay()
 
{
 
	if ((++this->day_counter & 7) == 0)
 
		DecreaseVehicleValue(this);
 

	
 
	CheckVehicleBreakdown(this);
 
	AgeVehicle(this);
 
	CheckIfShipNeedsService(this);
 

	
 
	CheckOrders(this);
 

	
 
	if (this->running_ticks == 0) return;
 

	
 
	CommandCost cost(EXPENSES_SHIP_RUN, this->GetRunningCost() * this->running_ticks / (DAYS_IN_YEAR * DAY_TICKS));
 

	
 
	this->profit_this_year -= cost.GetCost();
 
	this->running_ticks = 0;
 

	
 
	SubtractMoneyFromCompanyFract(this->owner, cost);
 

	
 
	InvalidateWindow(WC_VEHICLE_DETAILS, this->index);
 
	SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
 
	/* we need this for the profit */
 
	InvalidateWindowClasses(WC_SHIPS_LIST);
 
	SetWindowClassesDirty(WC_SHIPS_LIST);
 
}
 

	
 
Trackdir Ship::GetVehicleTrackdir() const
 
{
 
	if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
 

	
 
	if (this->IsInDepot()) {
 
		/* We'll assume the ship is facing outwards */
 
		return DiagDirToDiagTrackdir(GetShipDepotDirection(this->tile));
 
	}
 

	
 
	if (this->state == TRACK_BIT_WORMHOLE) {
 
		/* ship on aqueduct, so just use his direction and assume a diagonal track */
 
		return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
 
	}
 

	
 
	return TrackDirectionToTrackdir(FindFirstTrack(this->state), this->direction);
 
}
 

	
 
static void HandleBrokenShip(Vehicle *v)
 
{
 
	if (v->breakdown_ctr != 1) {
 
		v->breakdown_ctr = 1;
 
		v->cur_speed = 0;
 

	
 
		if (v->breakdowns_since_last_service != 255)
 
			v->breakdowns_since_last_service++;
 

	
 
		InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 
		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
		SetWindowDirty(WC_VEHICLE_VIEW, v->index);
 
		SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
 

	
 
		if (!PlayVehicleSound(v, VSE_BREAKDOWN)) {
 
			SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ?
 
				SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v);
 
		}
 

	
 
		if (!(v->vehstatus & VS_HIDDEN)) {
 
			EffectVehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE);
 
			if (u != NULL) u->animation_state = v->breakdown_delay * 2;
 
		}
 
	}
 

	
 
	if (!(v->tick_counter & 1)) {
 
		if (!--v->breakdown_delay) {
 
			v->breakdown_ctr = 0;
 
			InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 
			SetWindowDirty(WC_VEHICLE_VIEW, v->index);
 
		}
 
	}
 
}
 

	
 
void Ship::MarkDirty()
 
{
 
	this->UpdateViewport(false, false);
 
}
 

	
 
static void PlayShipSound(const Vehicle *v)
 
{
 
	if (!PlayVehicleSound(v, VSE_START)) {
 
		SndPlayVehicleFx(ShipVehInfo(v->engine_type)->sfx, v);
 
	}
 
}
 

	
 
void Ship::PlayLeaveStationSound() const
 
{
 
	PlayShipSound(this);
 
}
 

	
 
TileIndex Ship::GetOrderStationLocation(StationID station)
 
{
 
	if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
 
@@ -269,97 +269,97 @@ void Ship::UpdateDeltaXY(Direction direc
 
#define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0)
 
	static const uint32 _delta_xy_table[8] = {
 
		MKIT( 6,  6,  -3,  -3),
 
		MKIT( 6, 32,  -3, -16),
 
		MKIT( 6,  6,  -3,  -3),
 
		MKIT(32,  6, -16,  -3),
 
		MKIT( 6,  6,  -3,  -3),
 
		MKIT( 6, 32,  -3, -16),
 
		MKIT( 6,  6,  -3,  -3),
 
		MKIT(32,  6, -16,  -3),
 
	};
 
#undef MKIT
 

	
 
	uint32 x = _delta_xy_table[direction];
 
	this->x_offs        = GB(x,  0, 8);
 
	this->y_offs        = GB(x,  8, 8);
 
	this->x_extent      = GB(x, 16, 8);
 
	this->y_extent      = GB(x, 24, 8);
 
	this->z_extent      = 6;
 
}
 

	
 
void RecalcShipStuff(Vehicle *v)
 
{
 
	v->UpdateViewport(false, true);
 
	InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
	SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);
 
}
 

	
 
static const TileIndexDiffC _ship_leave_depot_offs[] = {
 
	{-1,  0},
 
	{ 0, -1}
 
};
 

	
 
static void CheckShipLeaveDepot(Ship *v)
 
{
 
	if (!v->IsInDepot()) return;
 

	
 
	TileIndex tile = v->tile;
 
	Axis axis = GetShipDepotAxis(tile);
 

	
 
	/* Check first (north) side */
 
	if (_ship_sometracks[axis] & GetTileShipTrackStatus(TILE_ADD(tile, ToTileIndexDiff(_ship_leave_depot_offs[axis])))) {
 
		v->direction = ReverseDir(AxisToDirection(axis));
 
	/* Check second (south) side */
 
	} else if (_ship_sometracks[axis + 2] & GetTileShipTrackStatus(TILE_ADD(tile, -2 * ToTileIndexDiff(_ship_leave_depot_offs[axis])))) {
 
		v->direction = AxisToDirection(axis);
 
	} else {
 
		return;
 
	}
 

	
 
	v->state = AxisToTrackBits(axis);
 
	v->vehstatus &= ~VS_HIDDEN;
 

	
 
	v->cur_speed = 0;
 
	RecalcShipStuff(v);
 

	
 
	PlayShipSound(v);
 
	VehicleServiceInDepot(v);
 
	InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 
	InvalidateWindowClasses(WC_SHIPS_LIST);
 
	SetWindowClassesDirty(WC_SHIPS_LIST);
 
}
 

	
 
static bool ShipAccelerate(Vehicle *v)
 
{
 
	uint spd;
 
	byte t;
 

	
 
	spd = min(v->cur_speed + 1, GetVehicleProperty(v, 0x0B, v->max_speed));
 

	
 
	/* updates statusbar only if speed have changed to save CPU time */
 
	if (spd != v->cur_speed) {
 
		v->cur_speed = spd;
 
		if (_settings_client.gui.vehicle_speed)
 
			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
			SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	}
 

	
 
	/* Decrease somewhat when turning */
 
	if (!(v->direction & 1)) spd = spd * 3 / 4;
 

	
 
	if (spd == 0) return false;
 
	if ((byte)++spd == 0) return true;
 

	
 
	v->progress = (t = v->progress) - (byte)spd;
 

	
 
	return (t < v->progress);
 
}
 

	
 
static void ShipArrivesAt(const Vehicle *v, Station *st)
 
{
 
	/* Check if station was ever visited before */
 
	if (!(st->had_vehicle_of_type & HVOT_SHIP)) {
 
		st->had_vehicle_of_type |= HVOT_SHIP;
 

	
 
		SetDParam(0, st->index);
 
		AddVehicleNewsItem(
 
			STR_NEWS_FIRST_SHIP_ARRIVAL,
 
			(v->owner == _local_company) ? NS_ARRIVAL_COMPANY : NS_ARRIVAL_OTHER,
 
			v->index,
 
@@ -606,49 +606,49 @@ static void ShipController(Ship *v)
 

	
 
	if (v->current_order.IsType(OT_LOADING)) return;
 

	
 
	CheckShipLeaveDepot(v);
 

	
 
	if (!ShipAccelerate(v)) return;
 

	
 
	GetNewVehiclePosResult gp = GetNewVehiclePos(v);
 
	if (v->state != TRACK_BIT_WORMHOLE) {
 
		/* Not on a bridge */
 
		if (gp.old_tile == gp.new_tile) {
 
			/* Staying in tile */
 
			if (v->IsInDepot()) {
 
				gp.x = v->x_pos;
 
				gp.y = v->y_pos;
 
			} else {
 
				/* Not inside depot */
 
				r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
 
				if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction;
 

	
 
				/* A leave station order only needs one tick to get processed, so we can
 
				 * always skip ahead. */
 
				if (v->current_order.IsType(OT_LEAVESTATION)) {
 
					v->current_order.Free();
 
					InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
					SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
				} else if (v->dest_tile != 0) {
 
					/* We have a target, let's see if we reached it... */
 
					if (v->current_order.IsType(OT_GOTO_WAYPOINT) &&
 
							DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) {
 
						/* We got within 3 tiles of our target buoy, so let's skip to our
 
						 * next order */
 
						UpdateVehicleTimetable(v, true);
 
						v->IncrementOrderIndex();
 
						v->current_order.MakeDummy();
 
					} else {
 
						/* Non-buoy orders really need to reach the tile */
 
						if (v->dest_tile == gp.new_tile) {
 
							if (v->current_order.IsType(OT_GOTO_DEPOT)) {
 
								if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) {
 
									VehicleEnterDepot(v);
 
									return;
 
								}
 
							} else if (v->current_order.IsType(OT_GOTO_STATION)) {
 
								v->last_station_visited = v->current_order.GetDestination();
 

	
 
								/* Process station in the orderlist. */
 
								Station *st = Station::Get(v->current_order.GetDestination());
 
								if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations
 
									ShipArrivesAt(v, st);
 
@@ -798,49 +798,49 @@ CommandCost CmdBuildShip(TileIndex tile,
 
		_new_vehicle_id = v->index;
 

	
 
		v->name = NULL;
 
		v->state = TRACK_BIT_DEPOT;
 

	
 
		v->service_interval = Company::Get(_current_company)->settings.vehicle.servint_ships;
 
		v->date_of_last_service = _date;
 
		v->build_year = _cur_year;
 
		v->cur_image = SPR_IMG_QUERY;
 
		v->random_bits = VehicleRandomBits();
 

	
 
		v->vehicle_flags = 0;
 
		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
 

	
 
		v->InvalidateNewGRFCacheOfChain();
 

	
 
		v->cargo_cap = GetVehicleProperty(v, 0x0D, svi->capacity);
 

	
 
		v->InvalidateNewGRFCacheOfChain();
 

	
 
		VehicleMove(v, false);
 

	
 
		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 
		InvalidateWindowClassesData(WC_SHIPS_LIST, 0);
 
		InvalidateWindow(WC_COMPANY, v->owner);
 
		SetWindowDirty(WC_COMPANY, v->owner);
 
		if (IsLocalCompany())
 
			InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Ship window
 

	
 
		Company::Get(_current_company)->num_engines[p1]++;
 
	}
 

	
 
	return value;
 
}
 

	
 
/** Sell a ship.
 
 * @param tile unused
 
 * @param flags type of operation
 
 * @param p1 vehicle ID to be sold
 
 * @param p2 unused
 
 */
 
CommandCost CmdSellShip(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	Ship *v = Ship::GetIfValid(p1);
 
	if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR;
 

	
 
	if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_CAN_T_SELL_DESTROYED_VEHICLE);
 

	
 
	if (!v->IsStoppedInDepot()) {
 
		return_cmd_error(STR_ERROR_SHIP_MUST_BE_STOPPED_IN_DEPOT);
 
@@ -927,32 +927,32 @@ CommandCost CmdRefitShip(TileIndex tile,
 

	
 
		capacity = GetVehicleCallback(CBID_VEHICLE_REFIT_CAPACITY, 0, 0, v->engine_type, v);
 

	
 
		/* Restore the cargo type */
 
		v->cargo_type = temp_cid;
 
		v->cargo_subtype = temp_subtype;
 
	}
 

	
 
	if (capacity == CALLBACK_FAILED) {
 
		capacity = GetVehicleProperty(v, 0x0D, ShipVehInfo(v->engine_type)->capacity);
 
	}
 
	_returned_refit_capacity = capacity;
 

	
 
	if (new_cid != v->cargo_type) {
 
		cost = GetRefitCost(v->engine_type);
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		v->cargo_cap = capacity;
 
		v->cargo.Truncate((v->cargo_type == new_cid) ? capacity : 0);
 
		v->cargo_type = new_cid;
 
		v->cargo_subtype = new_subtype;
 
		v->colourmap = PAL_NONE; // invalidate vehicle colour map
 
		v->InvalidateNewGRFCacheOfChain();
 
		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
		SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
 
		SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);
 
		InvalidateWindowClassesData(WC_SHIPS_LIST, 0);
 
	}
 

	
 
	return cost;
 

	
 
}
src/signs_gui.cpp
Show inline comments
 
@@ -155,49 +155,49 @@ struct SignListWindow : Window, SignList
 
		}
 
	}
 

	
 
	virtual void OnResize(Point delta)
 
	{
 
		this->vscroll.UpdateCapacity(delta.y / (int)this->resize.step_height);
 
	}
 

	
 
	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *resize)
 
	{
 
		if (widget == SLW_LIST) {
 
			Dimension spr_dim = GetSpriteSize(SPR_PLAYER_ICON);
 
			this->text_offset = WD_FRAMETEXT_LEFT + spr_dim.width + 2; // 2 pixels space between icon and the sign text.
 
			resize->height = max<uint>(FONT_HEIGHT_NORMAL, GetSpriteSize(SPR_PLAYER_ICON).height);
 
			Dimension d = {this->text_offset + MAX_LENGTH_SIGN_NAME_PIXELS + WD_FRAMETEXT_RIGHT, WD_FRAMERECT_TOP + 5 * resize->height + WD_FRAMERECT_BOTTOM};
 
			*size = maxdim(*size, d);
 
		}
 
	}
 

	
 
	virtual void OnInvalidateData(int data)
 
	{
 
		if (data == 0) { // New or deleted sign.
 
			this->signs.ForceRebuild();
 
			this->BuildSignsList();
 
			this->InvalidateWidget(SLW_CAPTION);
 
			this->SetWidgetDirty(SLW_CAPTION);
 
			this->vscroll.SetCount(this->signs.Length());
 
		} else { // Change of sign contents.
 
			this->signs.ForceResort();
 
		}
 

	
 
		this->SortSignsList();
 
	}
 
};
 

	
 
static const NWidgetPart _nested_sign_list_widgets[] = {
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_CLOSEBOX, COLOUR_GREY, SLW_CLOSEBOX),
 
		NWidget(WWT_CAPTION, COLOUR_GREY, SLW_CAPTION), SetDataTip(STR_SIGN_LIST_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
 
		NWidget(WWT_STICKYBOX, COLOUR_GREY, SLW_STICKY),
 
	EndContainer(),
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_PANEL, COLOUR_GREY, SLW_LIST), SetMinimalSize(WD_FRAMETEXT_LEFT + 16 + MAX_LENGTH_SIGN_NAME_PIXELS + WD_FRAMETEXT_RIGHT, 50),
 
							SetResize(1, 10), SetFill(true, false), EndContainer(),
 
		NWidget(NWID_VERTICAL),
 
			NWidget(WWT_SCROLLBAR, COLOUR_GREY, SLW_SCROLLBAR),
 
			NWidget(WWT_RESIZEBOX, COLOUR_GREY, SLW_RESIZE),
 
		EndContainer(),
 
	EndContainer(),
 
};
 
@@ -251,49 +251,49 @@ struct SignWindow : QueryStringBaseWindo
 
		this->afilter = CS_ALPHANUMERAL;
 
		this->LowerWidget(QUERY_EDIT_SIGN_WIDGET_TEXT);
 

	
 
		UpdateSignEditWindow(si);
 
		this->SetFocusedWidget(QUERY_EDIT_SIGN_WIDGET_TEXT);
 
		this->FindWindowPlacementAndResize(desc);
 
	}
 

	
 
	void UpdateSignEditWindow(const Sign *si)
 
	{
 
		char *last_of = &this->edit_str_buf[this->edit_str_size - 1]; // points to terminating '\0'
 

	
 
		/* Display an empty string when the sign hasnt been edited yet */
 
		if (si->name != NULL) {
 
			SetDParam(0, si->index);
 
			GetString(this->edit_str_buf, STR_SIGN_NAME, last_of);
 
		} else {
 
			GetString(this->edit_str_buf, STR_EMPTY, last_of);
 
		}
 
		*last_of = '\0';
 

	
 
		this->cur_sign = si->index;
 
		InitializeTextBuffer(&this->text, this->edit_str_buf, this->edit_str_size, MAX_LENGTH_SIGN_NAME_PIXELS);
 

	
 
		this->InvalidateWidget(QUERY_EDIT_SIGN_WIDGET_TEXT);
 
		this->SetWidgetDirty(QUERY_EDIT_SIGN_WIDGET_TEXT);
 
		this->SetFocusedWidget(QUERY_EDIT_SIGN_WIDGET_TEXT);
 
	}
 

	
 
	/**
 
	 * Returns a pointer to the (alphabetically) previous or next sign of the current sign.
 
	 * @param next false if the previous sign is wanted, true if the next sign is wanted
 
	 * @return pointer to the previous/next sign
 
	 */
 
	const Sign *PrevNextSign(bool next)
 
	{
 
		/* Rebuild the sign list */
 
		this->signs.ForceRebuild();
 
		this->signs.NeedResort();
 
		this->BuildSignsList();
 
		this->SortSignsList();
 

	
 
		/* Search through the list for the current sign, excluding
 
		 * - the first sign if we want the previous sign or
 
		 * - the last sign if we want the next sign */
 
		uint end = this->signs.Length() - (next ? 1 : 0);
 
		for (uint i = next ? 0 : 1; i < end; i++) {
 
			if (this->cur_sign == this->signs[i]->index) {
 
				/* We've found the current sign, so return the sign before/after it */
 
				return this->signs[i + (next ? 1 : -1)];
src/station_cmd.cpp
Show inline comments
 
@@ -406,49 +406,49 @@ void Station::GetTileArea(TileArea *ta, 
 
			ta->tile = this->dock_tile;
 
			break;
 

	
 
		default: NOT_REACHED();
 
	}
 

	
 
	ta->w = 1;
 
	ta->h = 1;
 
}
 

	
 
/**
 
 * Update the virtual coords needed to draw the station sign.
 
 */
 
void Station::UpdateVirtCoord()
 
{
 
	Point pt = RemapCoords2(TileX(this->xy) * TILE_SIZE, TileY(this->xy) * TILE_SIZE);
 

	
 
	pt.y -= 32;
 
	if ((this->facilities & FACIL_AIRPORT) && this->airport_type == AT_OILRIG) pt.y -= 16;
 

	
 
	SetDParam(0, this->index);
 
	SetDParam(1, this->facilities);
 
	this->sign.UpdatePosition(pt.x, pt.y, STR_VIEWPORT_STATION);
 

	
 
	InvalidateWindow(WC_STATION_VIEW, this->index);
 
	SetWindowDirty(WC_STATION_VIEW, this->index);
 
}
 

	
 
/** Update the virtual coords needed to draw the station sign for all stations. */
 
void UpdateAllStationVirtCoords()
 
{
 
	BaseStation *st;
 

	
 
	FOR_ALL_BASE_STATIONS(st) {
 
		st->UpdateVirtCoord();
 
	}
 
}
 

	
 
/** Get a mask of the cargo types that the station accepts.
 
 * @param st Station to query
 
 * @return the expected mask
 
 */
 
static uint GetAcceptanceMask(const Station *st)
 
{
 
	uint mask = 0;
 

	
 
	for (CargoID i = 0; i < NUM_CARGO; i++) {
 
		if (HasBit(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE)) mask |= 1 << i;
 
	}
 
	return mask;
 
@@ -600,49 +600,49 @@ void UpdateStationAcceptance(Station *st
 
		uint num_acc = 0;
 
		uint num_rej = 0;
 

	
 
		/* Test each cargo type to see if its acceptange has changed */
 
		for (CargoID i = 0; i < NUM_CARGO; i++) {
 
			if (HasBit(new_acc, i)) {
 
				if (!HasBit(old_acc, i) && num_acc < lengthof(accepts)) {
 
					/* New cargo is accepted */
 
					accepts[num_acc++] = i;
 
				}
 
			} else {
 
				if (HasBit(old_acc, i) && num_rej < lengthof(rejects)) {
 
					/* Old cargo is no longer accepted */
 
					rejects[num_rej++] = i;
 
				}
 
			}
 
		}
 

	
 
		/* Show news message if there are any changes */
 
		if (num_acc > 0) ShowRejectOrAcceptNews(st, num_acc, accepts, accept_msg[num_acc - 1]);
 
		if (num_rej > 0) ShowRejectOrAcceptNews(st, num_rej, rejects, reject_msg[num_rej - 1]);
 
	}
 

	
 
	/* redraw the station view since acceptance changed */
 
	InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_ACCEPTLIST);
 
	SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_ACCEPTLIST);
 
}
 

	
 
static void UpdateStationSignCoord(BaseStation *st)
 
{
 
	const StationRect *r = &st->rect;
 

	
 
	if (r->IsEmpty()) return; // no tiles belong to this station
 

	
 
	/* clamp sign coord to be inside the station rect */
 
	st->xy = TileXY(ClampU(TileX(st->xy), r->left, r->right), ClampU(TileY(st->xy), r->top, r->bottom));
 
	st->UpdateVirtCoord();
 
}
 

	
 
/** This is called right after a station was deleted.
 
 * It checks if the whole station is free of substations, and if so, the station will be
 
 * deleted after a little while.
 
 * @param st Station
 
 */
 
static void DeleteStationIfEmpty(BaseStation *st)
 
{
 
	if (!st->IsInUse()) {
 
		st->delete_ctr = 0;
 
		InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
 
	}
 
@@ -1132,49 +1132,49 @@ CommandCost CmdBuildRailStation(TileInde
 
				}
 

	
 
				tile += tile_delta;
 
			} while (--w);
 
			AddTrackToSignalBuffer(tile_org, track, _current_company);
 
			YapfNotifyTrackLayoutChange(tile_org, track);
 
			tile_org += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta
 
		} while (--numtracks);
 

	
 
		for (uint i = 0; i < affected_vehicles.Length(); ++i) {
 
			/* Restore reservations of trains. */
 
			Train *v = affected_vehicles[i];
 
			if (IsRailStationTile(v->tile)) SetRailStationPlatformReservation(v->tile, TrackdirToExitdir(v->GetVehicleTrackdir()), true);
 
			TryPathReserve(v, true, true);
 
			for (; v->Next() != NULL; v = v->Next()) ;
 
			if (IsRailStationTile(v->tile)) SetRailStationPlatformReservation(v->tile, TrackdirToExitdir(ReverseTrackdir(v->GetVehicleTrackdir())), true);
 
		}
 

	
 
		st->MarkTilesDirty(false);
 
		st->UpdateVirtCoord();
 
		UpdateStationAcceptance(st, false);
 
		st->RecomputeIndustriesNear();
 
		InvalidateWindowData(WC_SELECT_STATION, 0, 0);
 
		InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
 
		SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_TRAINS);
 
	}
 

	
 
	return cost;
 
}
 

	
 
static void MakeRailStationAreaSmaller(BaseStation *st)
 
{
 
	TileArea ta = st->train_station;
 

	
 
restart:
 

	
 
	/* too small? */
 
	if (ta.w != 0 && ta.h != 0) {
 
		/* check the left side, x = constant, y changes */
 
		for (uint i = 0; !st->TileBelongsToRailStation(ta.tile + TileDiffXY(0, i));) {
 
			/* the left side is unused? */
 
			if (++i == ta.h) {
 
				ta.tile += TileDiffXY(1, 0);
 
				ta.w--;
 
				goto restart;
 
			}
 
		}
 

	
 
		/* check the right side, x = constant, y changes */
 
@@ -1289,84 +1289,84 @@ CommandCost RemoveFromRailBaseStation(Ti
 
				for (; v->Next() != NULL; v = v->Next()) ;
 
				if (IsRailStationTile(v->tile)) SetRailStationPlatformReservation(v->tile, TrackdirToExitdir(ReverseTrackdir(v->GetVehicleTrackdir())), true);
 
			}
 
		}
 
		if (keep_rail) {
 
			/* Don't refund the 'steel' of the track! */
 
			total_cost.AddCost(-_price.remove_rail);
 
		}
 
	}
 

	
 
	if (quantity == 0) return CMD_ERROR;
 

	
 
	for (T **stp = affected_stations.Begin(); stp != affected_stations.End(); stp++) {
 
		T *st = *stp;
 

	
 
		/* now we need to make the "spanned" area of the railway station smaller
 
		 * if we deleted something at the edges.
 
		 * we also need to adjust train_tile. */
 
		MakeRailStationAreaSmaller(st);
 
		UpdateStationSignCoord(st);
 

	
 
		/* if we deleted the whole station, delete the train facility. */
 
		if (st->train_station.tile == INVALID_TILE) {
 
			st->facilities &= ~FACIL_TRAIN;
 
			InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
 
			SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_TRAINS);
 
			st->UpdateVirtCoord();
 
			DeleteStationIfEmpty(st);
 
		}
 
	}
 

	
 
	total_cost.AddCost(quantity * removal_cost);
 
	return total_cost;
 
}
 

	
 
/** Remove a single tile from a rail station.
 
 * This allows for custom-built station with holes and weird layouts
 
 * @param start tile of station piece to remove
 
 * @param flags operation to perform
 
 * @param p1 start_tile
 
 * @param p2 various bitstuffed elements
 
 * - p2 = bit 0 - if set keep the rail
 
 * @param text unused
 
 * @return cost of operation or error
 
 */
 
CommandCost CmdRemoveFromRailStation(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	TileIndex end = p1 == 0 ? start : p1;
 
	if (start >= MapSize() || end >= MapSize()) return CMD_ERROR;
 

	
 
	TileArea ta(start, end);
 
	SmallVector<Station *, 4> affected_stations;
 

	
 
	CommandCost ret = RemoveFromRailBaseStation(ta, affected_stations, flags, _price.remove_rail_station, HasBit(p2, 0));
 
	if (ret.Failed()) return ret;
 

	
 
	/* Do all station specific functions here. */
 
	for (Station **stp = affected_stations.Begin(); stp != affected_stations.End(); stp++) {
 
		Station *st = *stp;
 

	
 
		if (st->train_station.tile == INVALID_TILE) InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
 
		if (st->train_station.tile == INVALID_TILE) SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_TRAINS);
 
		st->MarkTilesDirty(false);
 
		st->RecomputeIndustriesNear();
 
	}
 

	
 
	/* Now apply the rail cost to the number that we deleted */
 
	return ret;
 
}
 

	
 
/** Remove a single tile from a waypoint.
 
 * This allows for custom-built waypoint with holes and weird layouts
 
 * @param start tile of waypoint piece to remove
 
 * @param flags operation to perform
 
 * @param p1 start_tile
 
 * @param p2 various bitstuffed elements
 
 * - p2 = bit 0 - if set keep the rail
 
 * @param text unused
 
 * @return cost of operation or error
 
 */
 
CommandCost CmdRemoveFromRailWaypoint(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	TileIndex end = p1 == 0 ? start : p1;
 
	if (start >= MapSize() || end >= MapSize()) return CMD_ERROR;
 

	
 
	TileArea ta(start, end);
 
@@ -1412,49 +1412,49 @@ CommandCost RemoveRailStation(T *st, DoC
 
				v = GetTrainForReservation(tile, track);
 
				if (v != NULL) FreeTrainTrackReservation(v);
 
			}
 
			DoClearSquare(tile);
 
			AddTrackToSignalBuffer(tile, track, owner);
 
			YapfNotifyTrackLayoutChange(tile, track);
 
			if (v != NULL) TryPathReserve(v, true);
 
		}
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		st->rect.AfterRemoveRect(st, st->train_station.tile, st->train_station.w, st->train_station.h);
 

	
 
		st->train_station.tile = INVALID_TILE;
 
		st->train_station.w = 0;
 
		st->train_station.h = 0;
 

	
 
		st->facilities &= ~FACIL_TRAIN;
 

	
 
		free(st->speclist);
 
		st->num_specs = 0;
 
		st->speclist  = NULL;
 
		st->cached_anim_triggers = 0;
 

	
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
 
		SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_TRAINS);
 
		st->UpdateVirtCoord();
 
		DeleteStationIfEmpty(st);
 
	}
 

	
 
	return cost;
 
}
 

	
 
/**
 
 * Remove a rail road station
 
 * @param tile TileIndex been queried
 
 * @param flags operation to perform
 
 * @return cost or failure of operation
 
 */
 
static CommandCost RemoveRailStation(TileIndex tile, DoCommandFlag flags)
 
{
 
	/* if there is flooding and non-uniform stations are enabled, remove platforms tile by tile */
 
	if (_current_company == OWNER_WATER && _settings_game.station.nonuniform_stations) {
 
		return DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_FROM_RAIL_STATION);
 
	}
 

	
 
	Station *st = Station::GetByTile(tile);
 
	CommandCost cost = RemoveRailStation(st, flags);
 

	
 
	if (flags & DC_EXEC) st->RecomputeIndustriesNear();
 
@@ -1615,49 +1615,49 @@ CommandCost CmdBuildRoadStop(TileIndex t
 

	
 
	if (flags & DC_EXEC) {
 
		RoadStop *road_stop = new RoadStop(tile);
 
		/* Insert into linked list of RoadStops */
 
		RoadStop **currstop = FindRoadStopSpot(type, st);
 
		*currstop = road_stop;
 

	
 
		/* initialize an empty station */
 
		st->AddFacility((type) ? FACIL_TRUCK_STOP : FACIL_BUS_STOP, tile);
 

	
 
		st->rect.BeforeAddTile(tile, StationRect::ADD_TRY);
 

	
 
		RoadStopType rs_type = type ? ROADSTOP_TRUCK : ROADSTOP_BUS;
 
		if (is_drive_through) {
 
			MakeDriveThroughRoadStop(tile, st->owner, road_owner, tram_owner, st->index, rs_type, rts, (Axis)p1);
 
		} else {
 
			MakeRoadStop(tile, st->owner, st->index, rs_type, rts, (DiagDirection)p1);
 
		}
 

	
 
		st->UpdateVirtCoord();
 
		UpdateStationAcceptance(st, false);
 
		st->RecomputeIndustriesNear();
 
		InvalidateWindowData(WC_SELECT_STATION, 0, 0);
 
		InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
 
		SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
 
	}
 
	return cost;
 
}
 

	
 

	
 
static Vehicle *ClearRoadStopStatusEnum(Vehicle *v, void *)
 
{
 
	if (v->type == VEH_ROAD) RoadVehicle::From(v)->state &= RVSB_ROAD_STOP_TRACKDIR_MASK;
 

	
 
	return NULL;
 
}
 

	
 

	
 
/**
 
 * Remove a bus station/truck stop
 
 * @param tile TileIndex been queried
 
 * @param flags operation to perform
 
 * @return cost or failure of operation
 
 */
 
static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags)
 
{
 
	Station *st = Station::GetByTile(tile);
 

	
 
	if (_current_company != OWNER_WATER && !CheckOwnership(st->owner)) {
 
@@ -1680,49 +1680,49 @@ static CommandCost RemoveRoadStop(TileIn
 

	
 
	/* don't do the check for drive-through road stops when company bankrupts */
 
	if (IsDriveThroughStopTile(tile) && (flags & DC_BANKRUPT)) {
 
		/* remove the 'going through road stop' status from all vehicles on that tile */
 
		if (flags & DC_EXEC) FindVehicleOnPos(tile, NULL, &ClearRoadStopStatusEnum);
 
	} else {
 
		if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		if (*primary_stop == cur_stop) {
 
			/* removed the first stop in the list */
 
			*primary_stop = cur_stop->next;
 
			/* removed the only stop? */
 
			if (*primary_stop == NULL) {
 
				st->facilities &= (is_truck ? ~FACIL_TRUCK_STOP : ~FACIL_BUS_STOP);
 
			}
 
		} else {
 
			/* tell the predecessor in the list to skip this stop */
 
			RoadStop *pred = *primary_stop;
 
			while (pred->next != cur_stop) pred = pred->next;
 
			pred->next = cur_stop->next;
 
		}
 

	
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
 
		SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
 
		delete cur_stop;
 

	
 
		/* Make sure no vehicle is going to the old roadstop */
 
		RoadVehicle *v;
 
		FOR_ALL_ROADVEHICLES(v) {
 
			if (v->First() == v && v->current_order.IsType(OT_GOTO_STATION) &&
 
					v->dest_tile == tile) {
 
				v->dest_tile = v->GetOrderStationLocation(st->index);
 
			}
 
		}
 

	
 
		DoClearSquare(tile);
 
		st->rect.AfterRemoveTile(st, tile);
 

	
 
		st->UpdateVirtCoord();
 
		st->RecomputeIndustriesNear();
 
		DeleteStationIfEmpty(st);
 
	}
 

	
 
	return CommandCost(EXPENSES_CONSTRUCTION, (is_truck) ? _price.remove_truck_station : _price.remove_bus_station);
 
}
 

	
 
/** Remove a bus or truck stop
 
 * @param tile tile to remove the stop from
 
@@ -1980,52 +1980,52 @@ CommandCost CmdBuildAirport(TileIndex ti
 

	
 
		/* if airport was demolished while planes were en-route to it, the
 
		 * positions can no longer be the same (v->u.air.pos), since different
 
		 * airports have different indexes. So update all planes en-route to this
 
		 * airport. Only update if
 
		 * 1. airport is upgraded
 
		 * 2. airport is added to existing station (unfortunately unavoideable)
 
		 */
 
		if (airport_upgrade) UpdateAirplanesOnNewStation(st);
 

	
 
		{
 
			const byte *b = _airport_sections[p1];
 

	
 
			TILE_LOOP(tile_cur, w, h, tile) {
 
				MakeAirport(tile_cur, st->owner, st->index, *b);
 
				b++;
 
			}
 
		}
 

	
 
		st->UpdateVirtCoord();
 
		UpdateStationAcceptance(st, false);
 
		st->RecomputeIndustriesNear();
 
		InvalidateWindowData(WC_SELECT_STATION, 0, 0);
 
		InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES);
 
		SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_PLANES);
 

	
 
		if (_settings_game.economy.station_noise_level) {
 
			InvalidateWindow(WC_TOWN_VIEW, st->town->index);
 
			SetWindowDirty(WC_TOWN_VIEW, st->town->index);
 
		}
 
	}
 

	
 
	return cost;
 
}
 

	
 
/**
 
 * Remove an airport
 
 * @param tile TileIndex been queried
 
 * @param flags operation to perform
 
 * @return cost or failure of operation
 
 */
 
static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags)
 
{
 
	Station *st = Station::GetByTile(tile);
 

	
 
	if (_current_company != OWNER_WATER && !CheckOwnership(st->owner)) {
 
		return CMD_ERROR;
 
	}
 

	
 
	tile = st->airport_tile;
 

	
 
	const AirportFTAClass *afc = st->Airport();
 
	int w = afc->size_x;
 
@@ -2045,52 +2045,52 @@ static CommandCost RemoveAirport(TileInd
 
		if (flags & DC_EXEC) {
 
			DeleteAnimatedTile(tile_cur);
 
			DoClearSquare(tile_cur);
 
		}
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		for (uint i = 0; i < afc->nof_depots; ++i) {
 
			DeleteWindowById(
 
				WC_VEHICLE_DEPOT, tile + ToTileIndexDiff(afc->airport_depots[i])
 
			);
 
		}
 

	
 
		/* Go get the final noise level, that is base noise minus factor from distance to town center.
 
		 * And as for construction, always remove it, even if the setting is not set, in order to avoid the
 
		 * need of recalculation */
 
		Town *nearest = AirportGetNearestTown(afc, tile);
 
		nearest->noise_reached -= GetAirportNoiseLevelForTown(afc, nearest->xy, tile);
 

	
 
		st->rect.AfterRemoveRect(st, tile, w, h);
 

	
 
		st->airport_tile = INVALID_TILE;
 
		st->facilities &= ~FACIL_AIRPORT;
 

	
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES);
 
		SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_PLANES);
 

	
 
		if (_settings_game.economy.station_noise_level) {
 
			InvalidateWindow(WC_TOWN_VIEW, st->town->index);
 
			SetWindowDirty(WC_TOWN_VIEW, st->town->index);
 
		}
 

	
 
		st->UpdateVirtCoord();
 
		st->RecomputeIndustriesNear();
 
		DeleteStationIfEmpty(st);
 
	}
 

	
 
	return cost;
 
}
 

	
 
/**
 
 * Tests whether the company's vehicles have this station in orders
 
 * When company == INVALID_COMPANY, then check all vehicles
 
 * @param station station ID
 
 * @param company company ID, INVALID_COMPANY to disable the check
 
 */
 
bool HasStationInUse(StationID station, CompanyID company)
 
{
 
	const Vehicle *v;
 
	FOR_ALL_VEHICLES(v) {
 
		if (company == INVALID_COMPANY || v->owner == company) {
 
			const Order *order;
 
			FOR_VEHICLE_ORDERS(v, order) {
 
				if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT)) && order->GetDestination() == station) {
 
@@ -2190,84 +2190,84 @@ CommandCost CmdBuildDock(TileIndex tile,
 
			st->town = ClosestTownFromTile(tile, UINT_MAX);
 
			st->string_id = GenerateStationName(st, tile, STATIONNAMING_DOCK);
 

	
 
			if (Company::IsValidID(_current_company)) {
 
				SetBit(st->town->have_ratings, _current_company);
 
			}
 
		}
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		st->dock_tile = tile;
 
		st->AddFacility(FACIL_DOCK, tile);
 

	
 
		st->rect.BeforeAddRect(
 
				tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
 
				_dock_w_chk[direction], _dock_h_chk[direction], StationRect::ADD_TRY);
 

	
 
		MakeDock(tile, st->owner, st->index, direction, wc);
 

	
 
		st->UpdateVirtCoord();
 
		UpdateStationAcceptance(st, false);
 
		st->RecomputeIndustriesNear();
 
		InvalidateWindowData(WC_SELECT_STATION, 0, 0);
 
		InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
 
		SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_SHIPS);
 
	}
 

	
 
	return CommandCost(EXPENSES_CONSTRUCTION, _price.build_dock);
 
}
 

	
 
/**
 
 * Remove a dock
 
 * @param tile TileIndex been queried
 
 * @param flags operation to perform
 
 * @return cost or failure of operation
 
 */
 
static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags)
 
{
 
	Station *st = Station::GetByTile(tile);
 
	if (!CheckOwnership(st->owner)) return CMD_ERROR;
 

	
 
	TileIndex tile1 = st->dock_tile;
 
	TileIndex tile2 = tile1 + TileOffsByDiagDir(GetDockDirection(tile1));
 

	
 
	if (!EnsureNoVehicleOnGround(tile1)) return CMD_ERROR;
 
	if (!EnsureNoVehicleOnGround(tile2)) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		DoClearSquare(tile1);
 
		MakeWaterKeepingClass(tile2, st->owner);
 

	
 
		st->rect.AfterRemoveTile(st, tile1);
 
		st->rect.AfterRemoveTile(st, tile2);
 

	
 
		MarkTileDirtyByTile(tile2);
 

	
 
		st->dock_tile = INVALID_TILE;
 
		st->facilities &= ~FACIL_DOCK;
 

	
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
 
		SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_SHIPS);
 
		st->UpdateVirtCoord();
 
		st->RecomputeIndustriesNear();
 
		DeleteStationIfEmpty(st);
 
	}
 

	
 
	return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_dock);
 
}
 

	
 
#include "table/station_land.h"
 

	
 
const DrawTileSprites *GetStationTileLayout(StationType st, byte gfx)
 
{
 
	return &_station_display_datas[st][gfx];
 
}
 

	
 
static void DrawTile_Station(TileInfo *ti)
 
{
 
	const DrawTileSprites *t = NULL;
 
	RoadTypes roadtypes;
 
	int32 total_offset;
 
	int32 custom_ground_offset;
 

	
 
	if (HasStationRail(ti->tile)) {
 
		const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
 
@@ -2802,51 +2802,51 @@ static void UpdateStationRating(Station 
 
				}
 

	
 
				/* At some point we really must cap the cargo. Previously this
 
				 * was a strict 4095, but now we'll have a less strict, but
 
				 * increasingly agressive truncation of the amount of cargo. */
 
				static const uint WAITING_CARGO_THRESHOLD  = 1 << 12;
 
				static const uint WAITING_CARGO_CUT_FACTOR = 1 <<  6;
 
				static const uint MAX_WAITING_CARGO        = 1 << 15;
 

	
 
				if (waiting > WAITING_CARGO_THRESHOLD) {
 
					uint difference = waiting - WAITING_CARGO_THRESHOLD;
 
					waiting -= (difference / WAITING_CARGO_CUT_FACTOR);
 

	
 
					waiting = min(waiting, MAX_WAITING_CARGO);
 
					waiting_changed = true;
 
				}
 

	
 
				if (waiting_changed) ge->cargo.Truncate(waiting);
 
			}
 
		}
 
	} while (++ge != endof(st->goods));
 

	
 
	StationID index = st->index;
 
	if (waiting_changed) {
 
		InvalidateWindow(WC_STATION_VIEW, index); // update whole window
 
		SetWindowDirty(WC_STATION_VIEW, index); // update whole window
 
	} else {
 
		InvalidateWindowWidget(WC_STATION_VIEW, index, SVW_RATINGLIST); // update only ratings list
 
		SetWindowWidgetDirty(WC_STATION_VIEW, index, SVW_RATINGLIST); // update only ratings list
 
	}
 
}
 

	
 
/* called for every station each tick */
 
static void StationHandleSmallTick(BaseStation *st)
 
{
 
	if ((st->facilities & FACIL_WAYPOINT) != 0 || !st->IsInUse()) return;
 

	
 
	byte b = st->delete_ctr + 1;
 
	if (b >= 185) b = 0;
 
	st->delete_ctr = b;
 

	
 
	if (b == 0) UpdateStationRating(Station::From(st));
 
}
 

	
 
void OnTick_Station()
 
{
 
	if (_game_mode == GM_EDITOR) return;
 

	
 
	BaseStation *st;
 
	FOR_ALL_BASE_STATIONS(st) {
 
		StationHandleSmallTick(st);
 

	
 
		/* Run 250 tick interval trigger for station animation.
 
@@ -2870,49 +2870,49 @@ void ModifyStationRatingAround(TileIndex
 
{
 
	Station *st;
 

	
 
	FOR_ALL_STATIONS(st) {
 
		if (st->owner == owner &&
 
				DistanceManhattan(tile, st->xy) <= radius) {
 
			for (CargoID i = 0; i < NUM_CARGO; i++) {
 
				GoodsEntry *ge = &st->goods[i];
 

	
 
				if (ge->acceptance_pickup != 0) {
 
					ge->rating = Clamp(ge->rating + amount, 0, 255);
 
				}
 
			}
 
		}
 
	}
 
}
 

	
 
static void UpdateStationWaiting(Station *st, CargoID type, uint amount, SourceType source_type, SourceID source_id)
 
{
 
	st->goods[type].cargo.Append(new CargoPacket(st->index, amount, source_type, source_id));
 
	SetBit(st->goods[type].acceptance_pickup, GoodsEntry::PICKUP);
 

	
 
	StationAnimationTrigger(st, st->xy, STAT_ANIM_NEW_CARGO, type);
 

	
 
	InvalidateWindow(WC_STATION_VIEW, st->index);
 
	SetWindowDirty(WC_STATION_VIEW, st->index);
 
	st->MarkTilesDirty(true);
 
}
 

	
 
static bool IsUniqueStationName(const char *name)
 
{
 
	const Station *st;
 

	
 
	FOR_ALL_STATIONS(st) {
 
		if (st->name != NULL && strcmp(st->name, name) == 0) return false;
 
	}
 

	
 
	return true;
 
}
 

	
 
/** Rename a station
 
 * @param tile unused
 
 * @param flags operation to perform
 
 * @param p1 station ID that is to be renamed
 
 * @param p2 unused
 
 */
 
CommandCost CmdRenameStation(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	Station *st = Station::GetIfValid(p1);
 
	if (st == NULL || !CheckOwnership(st->owner)) return CMD_ERROR;
src/station_gui.cpp
Show inline comments
 
@@ -233,49 +233,49 @@ protected:
 
	/** Sort stations by their rating */
 
	static int CDECL StationRatingMinSorter(const Station * const *a, const Station * const *b)
 
	{
 
		byte minr1 = 255;
 
		byte minr2 = 255;
 

	
 
		for (CargoID j = 0; j < NUM_CARGO; j++) {
 
			if (!HasBit(cargo_filter, j)) continue;
 
			if (HasBit((*a)->goods[j].acceptance_pickup, GoodsEntry::PICKUP)) minr1 = min(minr1, (*a)->goods[j].rating);
 
			if (HasBit((*b)->goods[j].acceptance_pickup, GoodsEntry::PICKUP)) minr2 = min(minr2, (*b)->goods[j].rating);
 
		}
 

	
 
		return -(minr1 - minr2);
 
	}
 

	
 
	/** Sort the stations list */
 
	void SortStationsList()
 
	{
 
		if (!this->stations.Sort()) return;
 

	
 
		/* Reset name sorter sort cache */
 
		this->last_station = NULL;
 

	
 
		/* Set the modified widget dirty */
 
		this->InvalidateWidget(SLW_LIST);
 
		this->SetWidgetDirty(SLW_LIST);
 
	}
 

	
 
public:
 
	CompanyStationsWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
 
	{
 
		this->owner = (Owner)this->window_number;
 
		this->vscroll.SetCapacity(12);
 
		this->resize.step_height = 10;
 
		this->resize.height = this->height - 10 * 7; // minimum if 5 in the list
 

	
 
		/* Add cargo filter buttons */
 
		uint num_active = 0;
 
		const CargoSpec *cs;
 
		FOR_ALL_CARGOSPECS(cs) {
 
			num_active++;
 
		}
 

	
 
		this->widget_count += num_active;
 
		this->widget = ReallocT(this->widget, this->widget_count + 1);
 
		this->widget[this->widget_count].type = WWT_LAST;
 

	
 
		uint i = 0;
 
		FOR_ALL_CARGOSPECS(cs) {
 
			Widget *wi = &this->widget[SLW_CARGOSTART + i];
 
@@ -948,49 +948,49 @@ struct StationViewWindow : public Window
 
			DrawString(this->widget[SVW_ACCEPTLIST].left + 2, this->widget[SVW_ACCEPTLIST].right - 2, y, STR_STATION_VIEW_CARGO_RATINGS_TITLE);
 
			y += 10;
 

	
 
			const CargoSpec *cs;
 
			FOR_ALL_CARGOSPECS(cs) {
 
				const GoodsEntry *ge = &st->goods[cs->Index()];
 
				if (!HasBit(ge->acceptance_pickup, GoodsEntry::PICKUP)) continue;
 

	
 
				SetDParam(0, cs->name);
 
				SetDParam(2, ToPercent8(ge->rating));
 
				SetDParam(1, STR_CARGO_RATING_APPALLING + (ge->rating >> 5));
 
				DrawString(this->widget[SVW_ACCEPTLIST].left + 8, this->widget[SVW_ACCEPTLIST].right - 2, y, STR_STATION_VIEW_CARGO_RATING);
 
				y += 10;
 
			}
 
		}
 
	}
 

	
 
	void HandleCargoWaitingClick(int row)
 
	{
 
		if (row == 0) return;
 

	
 
		for (CargoID c = 0; c < NUM_CARGO; c++) {
 
			if (this->cargo_rows[c] == row) {
 
				ToggleBit(this->cargo, c);
 
				this->InvalidateWidget(SVW_WAITING);
 
				this->SetWidgetDirty(SVW_WAITING);
 
				break;
 
			}
 
		}
 
	}
 

	
 
	virtual void OnClick(Point pt, int widget)
 
	{
 
		switch (widget) {
 
			case SVW_WAITING:
 
				this->HandleCargoWaitingClick((pt.y - this->widget[SVW_WAITING].top) / 10 + this->vscroll.GetPosition());
 
				break;
 

	
 
			case SVW_LOCATION:
 
				if (_ctrl_pressed) {
 
					ShowExtraViewPortWindow(Station::Get(this->window_number)->xy);
 
				} else {
 
					ScrollMainWindowToTile(Station::Get(this->window_number)->xy);
 
				}
 
				break;
 

	
 
			case SVW_RATINGS:
 
				this->SetDirty();
 

	
 
				if (this->widget[SVW_RATINGS].data == STR_STATION_VIEW_RATINGS_BUTTON) {
src/statusbar_gui.cpp
Show inline comments
 
@@ -150,56 +150,56 @@ struct StatusBarWindow : Window {
 
			case SBI_SHOW_TICKER:     this->ticker_scroll = 0; break;
 
			case SBI_SHOW_REMINDER:   this->reminder_timeout = REMINDER_START; break;
 
			case SBI_NEWS_DELETED:
 
				this->ticker_scroll    =   TICKER_STOP; // reset ticker ...
 
				this->reminder_timeout = REMINDER_STOP; // ... and reminder
 
				break;
 
		}
 
	}
 

	
 
	virtual void OnClick(Point pt, int widget)
 
	{
 
		switch (widget) {
 
			case SBW_MIDDLE: ShowLastNewsMessage(); break;
 
			case SBW_RIGHT:  if (_local_company != COMPANY_SPECTATOR) ShowCompanyFinances(_local_company); break;
 
			default: ResetObjectToPlace();
 
		}
 
	}
 

	
 
	virtual void OnTick()
 
	{
 
		if (_pause_mode != PM_UNPAUSED) return;
 

	
 
		if (this->ticker_scroll < TICKER_STOP) { // Scrolling text
 
			this->ticker_scroll += COUNTER_STEP;
 
			this->InvalidateWidget(SBW_MIDDLE);
 
			this->SetWidgetDirty(SBW_MIDDLE);
 
		}
 

	
 
		if (this->reminder_timeout > REMINDER_STOP) { // Red blot to show there are new unread newsmessages
 
			this->reminder_timeout -= COUNTER_STEP;
 
		} else if (this->reminder_timeout < REMINDER_STOP) {
 
			this->reminder_timeout = REMINDER_STOP;
 
			this->InvalidateWidget(SBW_MIDDLE);
 
			this->SetWidgetDirty(SBW_MIDDLE);
 
		}
 
	}
 
};
 

	
 
static const Widget _main_status_widgets[] = {
 
{      WWT_PANEL,   RESIZE_NONE,   COLOUR_GREY,     0,   139,     0,    11, 0x0, STR_NULL},
 
{    WWT_PUSHBTN,   RESIZE_RIGHT,  COLOUR_GREY,   140,   179,     0,    11, 0x0, STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS},
 
{    WWT_PUSHBTN,   RESIZE_LR,     COLOUR_GREY,   180,   319,     0,    11, 0x0, STR_NULL},
 
{   WIDGETS_END},
 
};
 

	
 
static const NWidgetPart _nested_main_status_widgets[] = {
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_PANEL, COLOUR_GREY, SBW_LEFT), SetMinimalSize(140, 12), EndContainer(),
 
		NWidget(WWT_PUSHBTN, COLOUR_GREY, SBW_MIDDLE), SetMinimalSize(40, 12), SetDataTip(0x0, STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS), SetResize(1, 0),
 
		NWidget(WWT_PUSHBTN, COLOUR_GREY, SBW_RIGHT), SetMinimalSize(140, 12),
 
	EndContainer(),
 
};
 

	
 
static WindowDesc _main_status_desc(
 
	WDP_CENTER, 0, 320, 12, 640, 12,
 
	WC_STATUS_BAR, WC_NONE,
 
	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_NO_FOCUS,
 
	_main_status_widgets, _nested_main_status_widgets, lengthof(_nested_main_status_widgets)
src/terraform_gui.cpp
Show inline comments
 
@@ -713,49 +713,49 @@ struct ScenarioEditorLandscapeGeneration
 
					SndPlayFx(SND_15_BEEP);
 
					this->SetDirty();
 
				} break;
 
				case ETTW_NEW_SCENARIO: // gen random land
 
					this->HandleButtonClick(widget);
 
					ShowCreateScenario();
 
					break;
 
				case ETTW_RESET_LANDSCAPE: // Reset landscape
 
					ShowQuery(
 
						STR_QUERY_RESET_LANDSCAPE_CAPTION,
 
						STR_RESET_LANDSCAPE_CONFIRMATION_TEXT,
 
						NULL,
 
						ResetLandscapeConfirmationCallback);
 
					break;
 
			}
 
		}
 
	}
 

	
 
	virtual void OnTimeout()
 
	{
 
		for (uint i = ETTW_START; i < this->nested_array_size; i++) {
 
			if (i == ETTW_BUTTONS_START) i = ETTW_BUTTONS_END; // skip the buttons
 
			if (this->IsWidgetLowered(i)) {
 
				this->RaiseWidget(i);
 
				this->InvalidateWidget(i);
 
				this->SetWidgetDirty(i);
 
			}
 
		}
 
	}
 

	
 
	virtual void OnPlaceObject(Point pt, TileIndex tile)
 
	{
 
		_place_proc(tile);
 
	}
 

	
 
	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
 
	{
 
		VpSelectTilesWithMethod(pt.x, pt.y, select_method);
 
	}
 

	
 
	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
 
	{
 
		if (pt.x != -1) {
 
			switch (select_proc) {
 
				default: NOT_REACHED();
 
				case DDSP_CREATE_ROCKS:
 
				case DDSP_CREATE_DESERT:
 
				case DDSP_RAISE_AND_LEVEL_AREA:
 
				case DDSP_LOWER_AND_LEVEL_AREA:
 
				case DDSP_LEVEL_AREA:
src/timetable_cmd.cpp
Show inline comments
 
@@ -19,49 +19,49 @@
 
#include "table/strings.h"
 

	
 
static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 time, bool is_journey)
 
{
 
	Order *order = v->GetOrder(order_number);
 
	int delta;
 

	
 
	if (is_journey) {
 
		delta = time - order->travel_time;
 
		order->travel_time = time;
 
	} else {
 
		delta = time - order->wait_time;
 
		order->wait_time = time;
 
	}
 
	v->orders.list->UpdateOrderTimetable(delta);
 

	
 
	for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
 
		if (v->cur_order_index == order_number && v->current_order.Equals(*order)) {
 
			if (is_journey) {
 
				v->current_order.travel_time = time;
 
			} else {
 
				v->current_order.wait_time = time;
 
			}
 
		}
 
		InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index);
 
		SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
 
	}
 
}
 

	
 
/**
 
 * Add or remove waiting times from an order.
 
 * @param tile Not used.
 
 * @param flags Operation to perform.
 
 * @param p1 Various bitstuffed elements
 
 * - p1 = (bit  0-15) - Vehicle with the orders to change.
 
 * - p1 = (bit 16-23) - Order index to modify.
 
 * - p1 = (bit    24) - Whether to change the waiting time or the travelling
 
 *                      time.
 
 * - p1 = (bit    25) - Whether p2 contains waiting and travelling time.
 
 * @param p2 The amount of time to wait.
 
 * - p2 = (bit  0-15) - Waiting or travelling time as specified by p1 bit 24 if p1 bit 25 is not set,
 
 *                      Travelling time if p1 bit 25 is set.
 
 * - p2 = (bit 16-31) - Waiting time if p1 bit 25 is set
 
 */
 
CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	if (!_settings_game.order.timetabling) return CMD_ERROR;
 

	
 
	VehicleID veh = GB(p1, 0, 16);
 

	
 
@@ -155,49 +155,49 @@ CommandCost CmdAutofillTimetable(TileInd
 
	if (flags & DC_EXEC) {
 
		if (HasBit(p2, 0)) {
 
			/* Start autofilling the timetable, which clears the
 
			 * "timetable has started" bit. Times are not cleared anymore, but are
 
			 * overwritten when the order is reached now. */
 
			SetBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
 
			ClrBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
 

	
 
			/* Overwrite waiting times only if they got longer */
 
			if (HasBit(p2, 1)) SetBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
 

	
 
			v->lateness_counter = 0;
 
		} else {
 
			ClrBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
 
			ClrBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
 
		}
 
	}
 

	
 
	for (Vehicle *v2 = v->FirstShared(); v2 != NULL; v2 = v2->NextShared()) {
 
		if (v2 != v) {
 
			/* Stop autofilling; only one vehicle at a time can perform autofill */
 
			ClrBit(v2->vehicle_flags, VF_AUTOFILL_TIMETABLE);
 
			ClrBit(v2->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
 
		}
 
		InvalidateWindow(WC_VEHICLE_TIMETABLE, v2->index);
 
		SetWindowDirty(WC_VEHICLE_TIMETABLE, v2->index);
 
	}
 

	
 
	return CommandCost();
 
}
 

	
 
void UpdateVehicleTimetable(Vehicle *v, bool travelling)
 
{
 
	uint timetabled = travelling ? v->current_order.travel_time : v->current_order.wait_time;
 
	uint time_taken = v->current_order_time;
 

	
 
	v->current_order_time = 0;
 

	
 
	if (!_settings_game.order.timetabling) return;
 

	
 
	bool just_started = false;
 

	
 
	/* Make sure the timetable only starts when the vehicle reaches the first
 
	 * order, not when travelling from the depot to the first station. */
 
	if (v->cur_order_index == 0 && !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) {
 
		SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
 
		just_started = true;
 
	}
 

	
 
	if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) return;
 
@@ -220,27 +220,27 @@ void UpdateVehicleTimetable(Vehicle *v, 
 

	
 
			ChangeTimetable(v, v->cur_order_index, time_taken, travelling);
 
		}
 

	
 
		if (v->cur_order_index == 0 && travelling) {
 
			/* If we just started we would have returned earlier and have not reached
 
			 * this code. So obviously, we have completed our round: So turn autofill
 
			 * off again. */
 
			ClrBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
 
			ClrBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
 
		}
 
		return;
 
	}
 

	
 
	if (just_started) return;
 

	
 
	/* Vehicles will wait at stations if they arrive early even if they are not
 
	 * timetabled to wait there, so make sure the lateness counter is updated
 
	 * when this happens. */
 
	if (timetabled == 0 && (travelling || v->lateness_counter >= 0)) return;
 

	
 
	v->lateness_counter -= (timetabled - time_taken);
 

	
 
	for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
 
		InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index);
 
		SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
 
	}
 
}
src/toolbar_gui.cpp
Show inline comments
 
@@ -1099,72 +1099,72 @@ struct MainToolbarWindow : Window {
 
			case WKC_SHIFT | WKC_F11: ShowBuildTreesToolbar(); break;
 
			case WKC_SHIFT | WKC_F12: ShowMusicWindow(); break;
 
			case WKC_CTRL  | 'S': MenuClickSmallScreenshot(); break;
 
			case WKC_CTRL  | 'G': MenuClickWorldScreenshot(); break;
 
			case WKC_CTRL | WKC_ALT | 'C': if (!_networking) ShowCheatWindow(); break;
 
			case 'A': if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, 4); break; // Invoke Autorail
 
			case 'L': ShowTerraformToolbar(); break;
 
			case 'Q': case 'W': case 'E': case 'D': ShowTerraformToolbarWithTool(key, keycode); break;
 
			case 'M': ShowSmallMap(); break;
 
			case 'V': ShowExtraViewPortWindow(); break;
 
			default: return ES_NOT_HANDLED;
 
		}
 
		return ES_HANDLED;
 
	}
 

	
 
	virtual void OnPlaceObject(Point pt, TileIndex tile)
 
	{
 
		_place_proc(tile);
 
	}
 

	
 
	virtual void OnTick()
 
	{
 
		if (this->IsWidgetLowered(TBN_PAUSE) != !!_pause_mode) {
 
			this->ToggleWidgetLoweredState(TBN_PAUSE);
 
			this->InvalidateWidget(TBN_PAUSE);
 
			this->SetWidgetDirty(TBN_PAUSE);
 
		}
 

	
 
		if (this->IsWidgetLowered(TBN_FASTFORWARD) != !!_fast_forward) {
 
			this->ToggleWidgetLoweredState(TBN_FASTFORWARD);
 
			this->InvalidateWidget(TBN_FASTFORWARD);
 
			this->SetWidgetDirty(TBN_FASTFORWARD);
 
		}
 
	}
 

	
 
	virtual void OnResize(Point delta)
 
	{
 
		if (this->width <= TBP_NORMAL_MAXBUTTON * TBP_BUTTONWIDTH) {
 
			SplitToolbar(this);
 
		} else {
 
			ResizeToolbar(this);
 
		}
 
	}
 

	
 
	virtual void OnTimeout()
 
	{
 
		for (uint i = TBN_SETTINGS; i < this->widget_count - 1; i++) {
 
			if (this->IsWidgetLowered(i)) {
 
				this->RaiseWidget(i);
 
				this->InvalidateWidget(i);
 
				this->SetWidgetDirty(i);
 
			}
 
		}
 
	}
 

	
 
	virtual void OnInvalidateData(int data)
 
	{
 
		if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, TBN_ZOOMIN, TBN_ZOOMOUT);
 
	}
 
};
 

	
 
static const Widget _toolb_normal_widgets[] = {
 
{     WWT_IMGBTN,   RESIZE_LEFT,  COLOUR_GREY,     0,     0,     0,    21, SPR_IMG_PAUSE,           STR_TOOLBAR_TOOLTIP_PAUSE_GAME},               // TBN_PAUSE
 
{     WWT_IMGBTN,   RESIZE_NONE,  COLOUR_GREY,     0,     0,     0,    21, SPR_IMG_FASTFORWARD,     STR_TOOLBAR_TOOLTIP_FORWARD},                  // TBN_FASTFORWARD
 
{     WWT_IMGBTN,   RESIZE_NONE,  COLOUR_GREY,     0,     0,     0,    21, SPR_IMG_SETTINGS,        STR_TOOLBAR_TOOLTIP_OPTIONS},                  // TBN_SETTINGS
 
{   WWT_IMGBTN_2,   RESIZE_NONE,  COLOUR_GREY,     0,     0,     0,    21, SPR_IMG_SAVE,            STR_TOOLBAR_TOOLTIP_SAVE_GAME_ABANDON_GAME},   // TBN_SAVEGAME
 

	
 
{     WWT_IMGBTN,   RESIZE_NONE,  COLOUR_GREY,     0,     0,     0,    21, SPR_IMG_SMALLMAP,        STR_TOOLBAR_TOOLTIP_DISPLAY_MAP},              // TBN_SMALLMAP
 
{     WWT_IMGBTN,   RESIZE_NONE,  COLOUR_GREY,     0,     0,     0,    21, SPR_IMG_TOWN,            STR_TOOLBAR_TOOLTIP_DISPLAY_TOWN_DIRECTORY},   // TBN_TOWNDIRECTORY
 
{     WWT_IMGBTN,   RESIZE_NONE,  COLOUR_GREY,     0,     0,     0,    21, SPR_IMG_SUBSIDIES,       STR_TOOLBAR_TOOLTIP_DISPLAY_SUBSIDIES},        // TBN_SUBSIDIES
 
{     WWT_IMGBTN,   RESIZE_NONE,  COLOUR_GREY,     0,     0,     0,    21, SPR_IMG_COMPANY_LIST,    STR_TOOLBAR_TOOLTIP_DISPLAY_LIST_OF_COMPANY_STATIONS},  // TBN_STATIONS
 

	
 
{     WWT_IMGBTN,   RESIZE_NONE,  COLOUR_GREY,     0,     0,     0,    21, SPR_IMG_COMPANY_FINANCE, STR_TOOLBAR_TOOLTIP_DISPLAY_COMPANY_FINANCES}, // TBN_FINANCES
 
{     WWT_IMGBTN,   RESIZE_NONE,  COLOUR_GREY,     0,     0,     0,    21, SPR_IMG_COMPANY_GENERAL, STR_TOOLBAR_TOOLTIP_DISPLAY_COMPANY_GENERAL},  // TBN_COMPANIES
 
{     WWT_IMGBTN,   RESIZE_NONE,  COLOUR_GREY,     0,     0,     0,    21, SPR_IMG_GRAPHS,          STR_TOOLBAR_TOOLTIP_DISPLAY_GRAPHS},           // TBN_GRAPHICS
 
@@ -1372,50 +1372,50 @@ public:
 

	
 
				default:
 
					if (this->widget[i].bottom == 0) continue;
 

	
 
					this->widget[i].left = x;
 
					x += buttons_width / (TBP_SCENARIO_MAXBUTTON - b);
 
					this->widget[i].right = x - 1;
 
					buttons_width -= buttons_width / (TBP_SCENARIO_MAXBUTTON - b);
 
					b++;
 
					break;
 
			}
 

	
 
			if (extra_spacing_at[j] == i) {
 
				j++;
 
				uint add = spacing / (lengthof(extra_spacing_at) - j);
 
				spacing -= add;
 
				x += add;
 
			}
 
		}
 
	}
 

	
 
	virtual void OnTimeout()
 
	{
 
		this->SetWidgetsLoweredState(false, TBSE_DATEBACKWARD, TBSE_DATEFORWARD, WIDGET_LIST_END);
 
		this->InvalidateWidget(TBSE_DATEBACKWARD);
 
		this->InvalidateWidget(TBSE_DATEFORWARD);
 
		this->SetWidgetDirty(TBSE_DATEBACKWARD);
 
		this->SetWidgetDirty(TBSE_DATEFORWARD);
 
	}
 

	
 
	virtual void OnTick()
 
	{
 
		if (this->IsWidgetLowered(TBSE_PAUSE) != !!_pause_mode) {
 
			this->ToggleWidgetLoweredState(TBSE_PAUSE);
 
			this->SetDirty();
 
		}
 

	
 
		if (this->IsWidgetLowered(TBSE_FASTFORWARD) != !!_fast_forward) {
 
			this->ToggleWidgetLoweredState(TBSE_FASTFORWARD);
 
			this->SetDirty();
 
		}
 
	}
 

	
 
	virtual void OnInvalidateData(int data)
 
	{
 
		if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, TBSE_ZOOMIN, TBSE_ZOOMOUT);
 
	}
 
};
 

	
 
static const Widget _toolb_scen_widgets[] = {
 
{    WWT_IMGBTN, RESIZE_LEFT,  COLOUR_GREY,   0,   0,  0, 21, SPR_IMG_PAUSE,       STR_TOOLBAR_TOOLTIP_PAUSE_GAME},                  // TBSE_PAUSE
 
{    WWT_IMGBTN, RESIZE_NONE,  COLOUR_GREY,   0,   0,  0, 21, SPR_IMG_FASTFORWARD, STR_TOOLBAR_TOOLTIP_FORWARD},                     // TBSE_FASTFORWARD
src/town_cmd.cpp
Show inline comments
 
@@ -318,70 +318,70 @@ static void AnimateTile_Town(TileIndex t
 
 * @returns true if the tile correspond to the distance criteria
 
 */
 
static bool IsCloseToTown(TileIndex tile, uint dist)
 
{
 
	const Town *t;
 

	
 
	FOR_ALL_TOWNS(t) {
 
		if (DistanceManhattan(tile, t->xy) < dist) return true;
 
	}
 
	return false;
 
}
 

	
 
/**
 
 * Resize the sign(label) of the town after changes in
 
 * population (creation or growth or else)
 
 */
 
void Town::UpdateVirtCoord()
 
{
 
	Point pt = RemapCoords2(TileX(this->xy) * TILE_SIZE, TileY(this->xy) * TILE_SIZE);
 
	SetDParam(0, this->index);
 
	SetDParam(1, this->population);
 
	this->sign.UpdatePosition(pt.x, pt.y - 24,
 
		_settings_client.gui.population_in_label ? STR_VIEWPORT_TOWN_POP : STR_VIEWPORT_TOWN);
 

	
 
	InvalidateWindow(WC_TOWN_VIEW, this->index);
 
	SetWindowDirty(WC_TOWN_VIEW, this->index);
 
}
 

	
 
/** Update the virtual coords needed to draw the town sign for all towns. */
 
void UpdateAllTownVirtCoords()
 
{
 
	Town *t;
 

	
 
	FOR_ALL_TOWNS(t) {
 
		t->UpdateVirtCoord();
 
	}
 
}
 

	
 
/**
 
 * Change the towns population
 
 * @param t Town which polulation has changed
 
 * @param mod polulation change (can be positive or negative)
 
 */
 
static void ChangePopulation(Town *t, int mod)
 
{
 
	t->population += mod;
 
	InvalidateWindow(WC_TOWN_VIEW, t->index);
 
	SetWindowDirty(WC_TOWN_VIEW, t->index);
 
	t->UpdateVirtCoord();
 

	
 
	InvalidateWindowData(WC_TOWN_DIRECTORY, 0, 1);
 
}
 

	
 
/**
 
 * Determines the world population
 
 * Basically, count population of all towns, one by one
 
 * @return uint32 the calculated population of the world
 
 */
 
uint32 GetWorldPopulation()
 
{
 
	uint32 pop = 0;
 
	const Town *t;
 

	
 
	FOR_ALL_TOWNS(t) pop += t->population;
 
	return pop;
 
}
 

	
 
/**
 
 * Helper function for house completion stages progression
 
 * @param tile TileIndex of the house (or parts of it) to "grow"
 
 */
 
static void MakeSingleHouseBigger(TileIndex tile)
 
@@ -2450,49 +2450,49 @@ static void TownActionBuyRights(Town *t)
 
static void TownActionBribe(Town *t)
 
{
 
	if (Chance16(1, 14)) {
 
		/* set as unwanted for 6 months */
 
		t->unwanted[_current_company] = 6;
 

	
 
		/* set all close by station ratings to 0 */
 
		Station *st;
 
		FOR_ALL_STATIONS(st) {
 
			if (st->town == t && st->owner == _current_company) {
 
				for (CargoID i = 0; i < NUM_CARGO; i++) st->goods[i].rating = 0;
 
			}
 
		}
 

	
 
		/* only show errormessage to the executing player. All errors are handled command.c
 
		 * but this is special, because it can only 'fail' on a DC_EXEC */
 
		if (IsLocalCompany()) ShowErrorMessage(STR_ERROR_BRIBE_FAILED_2, STR_ERROR_BRIBE_FAILED, 0, 0);
 

	
 
		/* decrease by a lot!
 
		 * ChangeTownRating is only for stuff in demolishing. Bribe failure should
 
		 * be independent of any cheat settings
 
		 */
 
		if (t->ratings[_current_company] > RATING_BRIBE_DOWN_TO) {
 
			t->ratings[_current_company] = RATING_BRIBE_DOWN_TO;
 
			InvalidateWindow(WC_TOWN_AUTHORITY, t->index);
 
			SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
 
		}
 
	} else {
 
		ChangeTownRating(t, RATING_BRIBE_UP_STEP, RATING_BRIBE_MAXIMUM, DC_EXEC);
 
	}
 
}
 

	
 
typedef void TownActionProc(Town *t);
 
static TownActionProc * const _town_action_proc[] = {
 
	TownActionAdvertiseSmall,
 
	TownActionAdvertiseMedium,
 
	TownActionAdvertiseLarge,
 
	TownActionRoadRebuild,
 
	TownActionBuildStatue,
 
	TownActionFundBuildings,
 
	TownActionBuyRights,
 
	TownActionBribe
 
};
 

	
 
enum TownActions {
 
	TACT_NONE             = 0x00,
 

	
 
	TACT_ADVERTISE_SMALL  = 0x01,
 
	TACT_ADVERTISE_MEDIUM = 0x02,
 
	TACT_ADVERTISE_LARGE  = 0x04,
 
@@ -2554,90 +2554,90 @@ uint GetMaskOfTownActions(int *nump, Com
 

	
 
	if (nump != NULL) *nump = num;
 
	return buttons;
 
}
 

	
 
/** Do a town action.
 
 * This performs an action such as advertising, building a statue, funding buildings,
 
 * but also bribing the town-council
 
 * @param tile unused
 
 * @param flags type of operation
 
 * @param p1 town to do the action at
 
 * @param p2 action to perform, @see _town_action_proc for the list of available actions
 
 */
 
CommandCost CmdDoTownAction(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	Town *t = Town::GetIfValid(p1);
 
	if (t == NULL || p2 >= lengthof(_town_action_proc)) return CMD_ERROR;
 

	
 
	if (!HasBit(GetMaskOfTownActions(NULL, _current_company, t), p2)) return CMD_ERROR;
 

	
 
	CommandCost cost(EXPENSES_OTHER, (_price.build_industry >> 8) * _town_action_costs[p2]);
 

	
 
	if (flags & DC_EXEC) {
 
		_town_action_proc[p2](t);
 
		InvalidateWindow(WC_TOWN_AUTHORITY, p1);
 
		SetWindowDirty(WC_TOWN_AUTHORITY, p1);
 
	}
 

	
 
	return cost;
 
}
 

	
 
static void UpdateTownGrowRate(Town *t)
 
{
 
	/* Increase company ratings if they're low */
 
	const Company *c;
 
	FOR_ALL_COMPANIES(c) {
 
		if (t->ratings[c->index] < RATING_GROWTH_MAXIMUM) {
 
			t->ratings[c->index] = min((int)RATING_GROWTH_MAXIMUM, t->ratings[c->index] + RATING_GROWTH_UP_STEP);
 
		}
 
	}
 

	
 
	int n = 0;
 

	
 
	const Station *st;
 
	FOR_ALL_STATIONS(st) {
 
		if (DistanceSquare(st->xy, t->xy) <= t->squared_town_zone_radius[0]) {
 
			if (st->time_since_load <= 20 || st->time_since_unload <= 20) {
 
				n++;
 
				if (Company::IsValidID(st->owner)) {
 
					int new_rating = t->ratings[st->owner] + RATING_STATION_UP_STEP;
 
					t->ratings[st->owner] = min(new_rating, INT16_MAX); // do not let it overflow
 
				}
 
			} else {
 
				if (Company::IsValidID(st->owner)) {
 
					int new_rating = t->ratings[st->owner] + RATING_STATION_DOWN_STEP;
 
					t->ratings[st->owner] = max(new_rating, INT16_MIN);
 
				}
 
			}
 
		}
 
	}
 

	
 
	/* clamp all ratings to valid values */
 
	for (uint i = 0; i < MAX_COMPANIES; i++) {
 
		t->ratings[i] = Clamp(t->ratings[i], RATING_MINIMUM, RATING_MAXIMUM);
 
	}
 

	
 
	InvalidateWindow(WC_TOWN_AUTHORITY, t->index);
 
	SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
 

	
 
	ClrBit(t->flags, TOWN_IS_FUNDED);
 
	if (_settings_game.economy.town_growth_rate == 0 && t->fund_buildings_months == 0) return;
 

	
 
	/** Towns are processed every TOWN_GROWTH_FREQUENCY ticks, and this is the
 
	 * number of times towns are processed before a new building is built. */
 
	static const uint16 _grow_count_values[2][6] = {
 
		{ 120, 120, 120, 100,  80,  60 }, // Fund new buildings has been activated
 
		{ 320, 420, 300, 220, 160, 100 }  // Normal values
 
	};
 

	
 
	uint16 m;
 

	
 
	if (t->fund_buildings_months != 0) {
 
		m = _grow_count_values[0][min(n, 5)];
 
		t->fund_buildings_months--;
 
	} else {
 
		m = _grow_count_values[1][min(n, 5)];
 
		if (n == 0 && !Chance16(1, 12)) return;
 
	}
 

	
 
	if (_settings_game.game_creation.landscape == LT_ARCTIC) {
 
		if (TilePixelHeight(t->xy) >= GetSnowLine() && t->act_food == 0 && t->population > 90)
 
			return;
 
@@ -2654,49 +2654,49 @@ static void UpdateTownGrowRate(Town *t)
 
	if (t->larger_town) m /= 2;
 

	
 
	t->growth_rate = m / (t->num_houses / 50 + 1);
 
	if (m <= t->grow_counter)
 
		t->grow_counter = m;
 

	
 
	SetBit(t->flags, TOWN_IS_FUNDED);
 
}
 

	
 
static void UpdateTownAmounts(Town *t)
 
{
 
	/* Using +1 here to prevent overflow and division by zero */
 
	t->pct_pass_transported = t->new_act_pass * 256 / (t->new_max_pass + 1);
 

	
 
	t->max_pass = t->new_max_pass; t->new_max_pass = 0;
 
	t->act_pass = t->new_act_pass; t->new_act_pass = 0;
 
	t->act_food = t->new_act_food; t->new_act_food = 0;
 
	t->act_water = t->new_act_water; t->new_act_water = 0;
 

	
 
	/* Using +1 here to prevent overflow and division by zero */
 
	t->pct_mail_transported = t->new_act_mail * 256 / (t->new_max_mail + 1);
 
	t->max_mail = t->new_max_mail; t->new_max_mail = 0;
 
	t->act_mail = t->new_act_mail; t->new_act_mail = 0;
 

	
 
	InvalidateWindow(WC_TOWN_VIEW, t->index);
 
	SetWindowDirty(WC_TOWN_VIEW, t->index);
 
}
 

	
 
static void UpdateTownUnwanted(Town *t)
 
{
 
	const Company *c;
 

	
 
	FOR_ALL_COMPANIES(c) {
 
		if (t->unwanted[c->index] > 0) t->unwanted[c->index]--;
 
	}
 
}
 

	
 
/**
 
 * Checks whether the local authority allows construction of a new station (rail, road, airport, dock) on the given tile
 
 * @param tile The tile where the station shall be constructed.
 
 * @param flags Command flags. DC_NO_TEST_TOWN_RATING is tested.
 
 */
 
bool CheckIfAuthorityAllowsNewStation(TileIndex tile, DoCommandFlag flags)
 
{
 
	if (!Company::IsValidID(_current_company) || (flags & DC_NO_TEST_TOWN_RATING)) return true;
 

	
 
	Town *t = ClosestTownFromTile(tile, _settings_game.economy.dist_local_authority);
 
	if (t == NULL) return true;
 

	
 
	if (t->ratings[_current_company] > RATING_VERYPOOR) return true;
 
@@ -2800,49 +2800,49 @@ void ChangeTownRating(Town *t, int add, 
 
	/* if magic_bulldozer cheat is active, town doesn't penaltize for removing stuff */
 
	if (t == NULL || (flags & DC_NO_MODIFY_TOWN_RATING) ||
 
			!Company::IsValidID(_current_company) ||
 
			(_cheats.magic_bulldozer.value && add < 0)) {
 
		return;
 
	}
 

	
 
	int rating = GetRating(t);
 
	if (add < 0) {
 
		if (rating > max) {
 
			rating += add;
 
			if (rating < max) rating = max;
 
		}
 
	} else {
 
		if (rating < max) {
 
			rating += add;
 
			if (rating > max) rating = max;
 
		}
 
	}
 
	if (_town_rating_test) {
 
		_town_test_ratings[t] = rating;
 
	} else {
 
		SetBit(t->have_ratings, _current_company);
 
		t->ratings[_current_company] = rating;
 
		InvalidateWindow(WC_TOWN_AUTHORITY, t->index);
 
		SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
 
	}
 
}
 

	
 
bool CheckforTownRating(DoCommandFlag flags, Town *t, TownRatingCheckType type)
 
{
 
	/* if magic_bulldozer cheat is active, town doesn't restrict your destructive actions */
 
	if (t == NULL || !Company::IsValidID(_current_company) ||
 
			_cheats.magic_bulldozer.value || (flags & DC_NO_TEST_TOWN_RATING)) {
 
		return true;
 
	}
 

	
 
	/* minimum rating needed to be allowed to remove stuff */
 
	static const int needed_rating[][TOWN_RATING_CHECK_TYPE_COUNT] = {
 
		/*                  ROAD_REMOVE,                    TUNNELBRIDGE_REMOVE */
 
		{ RATING_ROAD_NEEDED_PERMISSIVE, RATING_TUNNEL_BRIDGE_NEEDED_PERMISSIVE}, // Permissive
 
		{    RATING_ROAD_NEEDED_NEUTRAL,    RATING_TUNNEL_BRIDGE_NEEDED_NEUTRAL}, // Neutral
 
		{    RATING_ROAD_NEEDED_HOSTILE,    RATING_TUNNEL_BRIDGE_NEEDED_HOSTILE}, // Hostile
 
	};
 

	
 
	/* check if you're allowed to remove the road/bridge/tunnel
 
	 * owned by a town no removal if rating is lower than ... depends now on
 
	 * difficulty setting. Minimum town rating selected by difficulty level
 
	 */
 
	int needed = needed_rating[_settings_game.difficulty.town_council_tolerance][type];

Changeset was too big and was cut off... Show full diff anyway

0 comments (0 inline, 0 general)