Ejemplo n.º 1
0
/** Move to the next news item */
static void MoveToNextItem()
{
	InvalidateWindowData(WC_STATUS_BAR, 0, SBI_NEWS_DELETED); // invalidate the statusbar
	DeleteWindowById(WC_NEWS_WINDOW, 0); // close the newspapers window if shown
	_forced_news = NULL;
	_statusbar_news_item = NULL;

	/* if we're not at the last item, then move on */
	if (_current_news != _latest_news) {
		_current_news = (_current_news == NULL) ? _oldest_news : _current_news->next;
		const NewsItem *ni = _current_news;
		const NewsType type = ni->type;

		/* check the date, don't show too old items */
		if (_date - _news_type_data[type].age > ni->date) return;

		switch (_news_type_data[type].GetDisplay()) {
			default: NOT_REACHED();
			case ND_OFF: // Off - show nothing only a small reminder in the status bar
				InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SHOW_REMINDER);
				break;

			case ND_SUMMARY: // Summary - show ticker
				ShowTicker(ni);
				break;

			case ND_FULL: // Full - show newspaper
				ShowNewspaper(ni);
				break;
		}
	}
}
Ejemplo n.º 2
0
/**
 * Change the configured music set and reset playback
 * @param index Index of music set to switch to
 */
void ChangeMusicSet(int index)
{
	if (BaseMusic::GetIndexOfUsedSet() == index) return;

	/* Resume playback after switching?
	 * Always if music is already playing, and also if the user is switching
	 * away from an empty music set.
	 * If the user switches away from an empty set, assume it's because they
	 * want to hear music now. */
	bool shouldplay = _song_is_active || (BaseMusic::GetUsedSet()->num_available == 0);
	StopMusic();

	const char *name = BaseMusic::GetSet(index)->name;
	BaseMusic::SetSet(name);
	free(BaseMusic::ini_set);
	BaseMusic::ini_set = stredup(name);

	InitializeMusic();
	ResetPlaylist();
	_settings_client.music.playing = shouldplay;

	InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
	InvalidateWindowData(WC_MUSIC_WINDOW, 0);
	InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_GAME_OPTIONS, 0, true);
}
Ejemplo n.º 3
0
	/**
	 * Some data on this window has become invalid.
	 * @param data Information about the changed data.
	 * @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
	 */
	virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
	{
		if (!gui_scope) return;
		/* Forward the message to the appropriate toolbar (ingame or scenario editor) */
		InvalidateWindowData(WC_MAIN_TOOLBAR, 0, data, true);
		InvalidateWindowData(WC_MAIN_TOOLBAR_RIGHT, 0, data, true);
	}
Ejemplo n.º 4
0
/**
 * Rename a sign. If the new name of the sign is empty, we assume
 * the user wanted to delete it. So delete it. Ownership of signs
 * has no meaning/effect whatsoever except for eyecandy
 * @param tile unused
 * @param flags type of operation
 * @param p1 index of the sign to be renamed/removed
 * @param p2 unused
 * @param text the new name or an empty string when resetting to the default
 * @return the cost of this operation or an error
 */
CommandCost CmdRenameSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	Sign *si = Sign::GetIfValid(p1);
	if (si == NULL) return CMD_ERROR;

	/* Rename the signs when empty, otherwise remove it */
	if (!StrEmpty(text)) {
		if (Utf8StringLength(text) >= MAX_LENGTH_SIGN_NAME_CHARS) return CMD_ERROR;

		if (flags & DC_EXEC) {
			/* Delete the old name */
			free(si->name);
			/* Assign the new one */
			si->name = strdup(text);
			si->owner = _current_company;

			si->UpdateVirtCoord();
			InvalidateWindowData(WC_SIGN_LIST, 0, 1);
		}
	} else { // Delete sign
		if (flags & DC_EXEC) {
			si->sign.MarkDirty();
			delete si;

			InvalidateWindowData(WC_SIGN_LIST, 0, 0);
		}
	}

	return CommandCost();
}
Ejemplo n.º 5
0
/**
 * Invalidating some stuff after removing item from the pool.
 * @param index index of deleted item
 */
void Company::PostDestructor(size_t index)
{
	InvalidateWindowData(WC_GRAPH_LEGEND, 0, (int)index);
	InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, (int)index);
	InvalidateWindowData(WC_COMPANY_LEAGUE, 0, 0);
	/* If the currently shown error message has this company in it, then close it. */
	InvalidateWindowData(WC_ERRMSG, 0);
}
Ejemplo n.º 6
0
/**
 * Build a buoy.
 * @param tile tile where to place the buoy
 * @param flags operation to perform
 * @param p1 unused
 * @param p2 unused
 * @param text unused
 * @return the cost of this operation or an error
 */
CommandCost CmdBuildBuoy(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	if (tile == 0) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);

	WaterClass wc;
	if ((flags & DC_PASTE) && !(flags & DC_EXEC)) {
		/* When pasting a buoy, there may be no water yet (a canal will be placed when DC_EXE'ing).
		 * Ignore that there is no water so we can calculate the cost more precisely. */
		wc = WATER_CLASS_INVALID;
	} else {
		if (!HasTileWaterGround(tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
		wc = GetWaterClass(tile);
	}

	if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);

	if (!IsTileFlat(tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);

	/* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
	Waypoint *wp = FindDeletedWaypointCloseTo(tile, STR_SV_STNAME_BUOY, OWNER_NONE);
	if (wp == NULL && !Waypoint::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_STATIONS_LOADING);

	CommandCost cost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_WAYPOINT_BUOY]);
	if (!IsWaterTile(tile)) {
		CommandCost ret = DoCommand(tile, 0, 0, flags | DC_AUTO, CMD_LANDSCAPE_CLEAR);
		if (ret.Failed()) return ret;
		cost.AddCost(ret);
	}

	if (flags & DC_EXEC) {
		if (wp == NULL) {
			wp = new Waypoint(tile);
		} else {
			/* Move existing (recently deleted) buoy to the new location */
			wp->xy = tile;
			InvalidateWindowData(WC_WAYPOINT_VIEW, wp->index);
		}
		wp->rect.BeforeAddTile(tile, StationRect::ADD_TRY);

		wp->string_id = STR_SV_STNAME_BUOY;

		wp->facilities |= FACIL_DOCK;
		wp->owner = OWNER_NONE;

		wp->build_date = _date;

		if (wp->town == NULL) MakeDefaultName(wp);

		assert(wc != WATER_CLASS_INVALID);
		MakeBuoy(tile, wp->index, wc);

		wp->UpdateVirtCoord();
		InvalidateWindowData(WC_WAYPOINT_VIEW, wp->index);
	}

	return cost;
}
Ejemplo n.º 7
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();
					SetWindowClassesDirty(WC_AI_DEBUG);
					break;

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

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

				case CONTENT_TYPE_BASE_MUSIC:
					BaseMusic::FindSets();
					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);
					break;

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

				default:
					break;
			}
		}

		/* Always invalidate the download window; tell it we are going to be gone */
		InvalidateWindowData(WC_NETWORK_WINDOW, 1, 2);
		_network_content_client.RemoveCallback(this);
	}
Ejemplo n.º 8
0
/** Show news item in the ticker */
static void ShowTicker(const NewsItem *ni)
{
	if (_settings_client.sound.news_ticker) SndPlayFx(SND_16_MORSE);

	_statusbar_news_item = ni;
	InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SHOW_TICKER);
}
Ejemplo n.º 9
0
static void CheckShipLeaveDepot(Ship *v)
{
	if (!v->IsInDepot()) return;

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

	/* Check first (north) side */
	if (DiagdirReachesTracks((DiagDirection)axis) & GetTileShipTrackStatus(TILE_ADD(tile, ToTileIndexDiff(_ship_leave_depot_offs[axis])))) {
		v->direction = ReverseDir(AxisToDirection(axis));
	/* Check second (south) side */
	} else if (DiagdirReachesTracks((DiagDirection)(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);
	SetWindowClassesDirty(WC_SHIPS_LIST);
}
Ejemplo n.º 10
0
/**
 * Create a new story page.
 * @param tile unused.
 * @param flags type of operation
 * @param p1 various bitstuffed elements
 * - p1 = (bit  0 -  7) - Company for which this story page belongs to.
 * @param p2 unused.
 * @param text Title of the story page. Null is allowed in wich case a generic page title is provided by OpenTTD.
 * @return the cost of this operation or an error
 */
CommandCost CmdCreateStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	if (!StoryPage::CanAllocateItem()) return CMD_ERROR;

	CompanyID company = (CompanyID)GB(p1, 0, 8);

	if (_current_company != OWNER_DEITY) return CMD_ERROR;
	if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;

	if (flags & DC_EXEC) {
		if (_story_page_pool.items == 0) {
			/* Initialize the next sort value variable. */
			_story_page_next_sort_value = 0;
		}

		StoryPage *s = new StoryPage();
		s->sort_value = _story_page_next_sort_value;
		s->date = _date;
		s->company = company;
		if (StrEmpty(text)) {
			s->title = NULL;
		} else {
			s->title = strdup(text);
		}

		InvalidateWindowClassesData(WC_STORY_BOOK, -1);
		if (StoryPage::GetNumItems() == 1) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);

		_new_story_page_id = s->index;
		_story_page_next_sort_value++;
	}

	return CommandCost();
}
Ejemplo n.º 11
0
/**
 * Marks subsidy as awarded, creates news and AI event
 * @param company awarded company
 */
void Subsidy::AwardTo(CompanyID company)
{
	assert(!this->IsAwarded());

	this->awarded = company;
	this->remaining = SUBSIDY_CONTRACT_MONTHS;

	char company_name[MAX_LENGTH_COMPANY_NAME_CHARS * MAX_CHAR_LENGTH];
	SetDParam(0, company);
	GetString(company_name, STR_COMPANY_NAME, lastof(company_name));

	char *cn = strdup(company_name);

	/* Add a news item */
	Pair reftype = SetupSubsidyDecodeParam(this, false);
	InjectDParam(1);

	SetDParamStr(0, cn);
	AddNewsItem(
		STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF + _settings_game.difficulty.subsidy_multiplier,
		NT_SUBSIDIES, NF_NORMAL,
		(NewsReferenceType)reftype.a, this->src, (NewsReferenceType)reftype.b, this->dst,
		cn
	);
	AI::BroadcastNewEvent(new ScriptEventSubsidyAwarded(this->index));
	Game::NewEvent(new ScriptEventSubsidyAwarded(this->index));

	InvalidateWindowData(WC_SUBSIDIES_LIST, 0);
}
Ejemplo n.º 12
0
/**
 * Remove a song from a custom playlist.
 * @param song_index Index in the custom playlist to remove.
 */
void MusicSystem::PlaylistRemove(size_t song_index)
{
	if (!this->IsCustomPlaylist()) return;

	Playlist &pl = this->standard_playlists[this->selected_playlist];
	if (song_index >= pl.size()) return;

	/* Remove from "simple" playlists */
	PlaylistEntry song = pl[song_index];
	pl.erase(pl.begin() + song_index);
	this->displayed_playlist.erase(this->displayed_playlist.begin() + song_index);

	/* Find in actual active playlist (may be shuffled) and remove,
	 * if it's the current song restart playback */
	for (size_t i = 0; i < this->active_playlist.size(); i++) {
		Playlist::iterator s2 = this->active_playlist.begin() + i;
		if (s2->filename == song.filename && s2->cat_index == song.cat_index) {
			this->active_playlist.erase(s2);
			if ((int)i == this->playlist_position && this->IsPlaying()) this->Play();
			break;
		}
	}

	this->SaveCustomPlaylist(this->selected_playlist);

	InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
}
Ejemplo n.º 13
0
/** Perform the monthly update of open subsidies, and try to create a new one. */
void SubsidyMonthlyLoop()
{
	bool modified = false;

	Subsidy *s;
	FOR_ALL_SUBSIDIES(s) {
		if (--s->remaining == 0) {
			if (!s->IsAwarded()) {
				Pair reftype = SetupSubsidyDecodeParam(s, true);
				AddNewsItem(STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED, NT_SUBSIDIES, NF_NORMAL, (NewsReferenceType)reftype.a, s->src, (NewsReferenceType)reftype.b, s->dst);
				AI::BroadcastNewEvent(new ScriptEventSubsidyOfferExpired(s->index));
				Game::NewEvent(new ScriptEventSubsidyOfferExpired(s->index));
			} else {
				if (s->awarded == _local_company) {
					Pair reftype = SetupSubsidyDecodeParam(s, true);
					AddNewsItem(STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE, NT_SUBSIDIES, NF_NORMAL, (NewsReferenceType)reftype.a, s->src, (NewsReferenceType)reftype.b, s->dst);
				}
				AI::BroadcastNewEvent(new ScriptEventSubsidyExpired(s->index));
				Game::NewEvent(new ScriptEventSubsidyExpired(s->index));
			}
			delete s;
			modified = true;
		}
	}

	if (modified) RebuildSubsidisedSourceAndDestinationCache();

	bool passenger_subsidy = false;
	bool town_subsidy = false;
	bool industry_subsidy = false;

	int random_chance = RandomRange(16);

	if (random_chance < 2) {
		/* There is a 1/8 chance each month of generating a passenger subsidy. */
		int n = 1000;

		do {
			passenger_subsidy = FindSubsidyPassengerRoute();
		} while (!passenger_subsidy && n--);
	} else if (random_chance == 2) {
		/* Cargo subsidies with a town as a source have a 1/16 chance. */
		int n = 1000;

		do {
			town_subsidy = FindSubsidyTownCargoRoute();
		} while (!town_subsidy && n--);
	} else if (random_chance == 3) {
		/* Cargo subsidies with an industry as a source have a 1/16 chance. */
		int n = 1000;

		do {
			industry_subsidy = FindSubsidyIndustryCargoRoute();
		} while (!industry_subsidy && n--);
	}

	modified |= passenger_subsidy || town_subsidy || industry_subsidy;

	if (modified) InvalidateWindowData(WC_SUBSIDIES_LIST, 0);
}
Ejemplo n.º 14
0
/**
 * Remove a buoy
 * @param tile TileIndex been queried
 * @param flags operation to perform
 * @pre IsBuoyTile(tile)
 * @return cost or failure of operation
 */
CommandCost RemoveBuoy(TileIndex tile, DoCommandFlag flags)
{
	/* XXX: strange stuff, allow clearing as invalid company when clearing landscape */
	if (!Company::IsValidID(_current_company) && !(flags & DC_BANKRUPT)) return_cmd_error(INVALID_STRING_ID);

	Waypoint *wp = Waypoint::GetByTile(tile);

	if (HasStationInUse(wp->index, false, _current_company)) return_cmd_error(STR_ERROR_BUOY_IS_IN_USE);
	/* remove the buoy if there is a ship on tile when company goes bankrupt... */
	if (!(flags & DC_BANKRUPT)) {
		CommandCost ret = EnsureNoVehicleOnGround(tile);
		if (ret.Failed()) return ret;
	}

	if (flags & DC_EXEC) {
		wp->facilities &= ~FACIL_DOCK;

		InvalidateWindowData(WC_WAYPOINT_VIEW, wp->index);

		/* We have to set the water tile's state to the same state as before the
		 * buoy was placed. Otherwise one could plant a buoy on a canal edge,
		 * remove it and flood the land (if the canal edge is at level 0) */
		MakeWaterKeepingClass(tile, GetTileOwner(tile));

		wp->rect.AfterRemoveTile(wp, tile);

		wp->UpdateVirtCoord();
		wp->delete_ctr = 0;
	}

	return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_WAYPOINT_BUOY]);
}
Ejemplo n.º 15
0
/**
 * Marks subsidy as awarded, creates news and AI event
 * @param company awarded company
 */
void Subsidy::AwardTo(CompanyID company)
{
	assert(!this->IsAwarded());

	this->awarded = company;
	this->remaining = SUBSIDY_CONTRACT_MONTHS;

	char *company_name = MallocT<char>(MAX_LENGTH_COMPANY_NAME_BYTES);
	SetDParam(0, company);
	GetString(company_name, STR_COMPANY_NAME, company_name + MAX_LENGTH_COMPANY_NAME_BYTES - 1);

	/* Add a news item */
	Pair reftype = SetupSubsidyDecodeParam(this, 0);
	InjectDParam(1);

	SetDParamStr(0, company_name);
	AddNewsItem(
		STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF + _settings_game.difficulty.subsidy_multiplier,
		NS_SUBSIDIES,
		(NewsReferenceType)reftype.a, this->src, (NewsReferenceType)reftype.b, this->dst,
		company_name
	);
	AI::BroadcastNewEvent(new AIEventSubsidyAwarded(this->index));

	InvalidateWindowData(WC_SUBSIDIES_LIST, 0);
}
Ejemplo n.º 16
0
/** Skip to previous track */
void MusicSystem::Prev()
{
	this->ChangePlaylistPosition(-1);
	if (_settings_client.music.playing) this->Play();

	InvalidateWindowData(WC_MUSIC_WINDOW, 0);
}
Ejemplo n.º 17
0
/**
 * Append a song to a custom playlist.
 * Always adds to the currently active playlist.
 * @param song_index Index of song in the current music set to add
 */
void MusicSystem::PlaylistAdd(size_t song_index)
{
	if (!this->IsCustomPlaylist()) return;

	/* Pick out song from the music set */
	if (song_index >= this->music_set.size()) return;
	PlaylistEntry entry = this->music_set[song_index];

	/* Check for maximum length */
	if (this->standard_playlists[this->selected_playlist].size() >= NUM_SONGS_PLAYLIST) return;

	/* Add it to the appropriate playlist, and the display */
	this->standard_playlists[this->selected_playlist].push_back(entry);
	this->displayed_playlist.push_back(entry);

	/* Add it to the active playlist, if playback is shuffled select a random position to add at */
	if (this->active_playlist.empty()) {
		this->active_playlist.push_back(entry);
		if (this->IsPlaying()) this->Play();
	} else if (this->IsShuffle()) {
		/* Generate a random position between 0 and n (inclusive, new length) to insert at */
		size_t maxpos = this->displayed_playlist.size();
		size_t newpos = InteractiveRandom() % maxpos;
		this->active_playlist.insert(this->active_playlist.begin() + newpos, entry);
		/* Make sure to shift up the current playback position if the song was inserted before it */
		if ((int)newpos <= this->playlist_position) this->playlist_position++;
	} else {
		this->active_playlist.push_back(entry);
	}

	this->SaveCustomPlaylist(this->selected_playlist);

	InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
}
Ejemplo n.º 18
0
/** Stop playback and set flag that we don't intend to play music */
void MusicSystem::Stop()
{
	MusicDriver::GetInstance()->StopSong();
	_settings_client.music.playing = false;

	InvalidateWindowData(WC_MUSIC_WINDOW, 0);
}
Ejemplo n.º 19
0
/**
 * Place a sign at the given coordinates. Ownership of sign has
 * no effect whatsoever except for the colour the sign gets for easy recognition,
 * but everybody is able to rename/remove it.
 * @param tile tile to place sign at
 * @param flags type of operation
 * @param p1 unused
 * @param p2 unused
 * @param text unused
 * @return the cost of this operation or an error
 */
CommandCost CmdPlaceSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	/* Try to locate a new sign */
	if (!Sign::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_SIGNS);

	/* Check sign text length if any */
	if (!StrEmpty(text) && Utf8StringLength(text) >= MAX_LENGTH_SIGN_NAME_CHARS) return CMD_ERROR;

	/* When we execute, really make the sign */
	if (flags & DC_EXEC) {
		Sign *si = new Sign(_current_company);
		int x = TileX(tile) * TILE_SIZE;
		int y = TileY(tile) * TILE_SIZE;

		si->x = x;
		si->y = y;
		si->z = GetSlopeZ(x, y);
		if (!StrEmpty(text)) {
			si->name = strdup(text);
		}
		si->UpdateVirtCoord();
		InvalidateWindowData(WC_SIGN_LIST, 0, 0);
		_new_sign_id = si->index;
	}

	return CommandCost();
}
Ejemplo n.º 20
0
/* static */ void AI::StartNew(CompanyID company, bool rerandomise_ai)
{
	assert(Company::IsValidID(company));

	/* Clients shouldn't start AIs */
	if (_networking && !_network_server) return;

	AIConfig *config = AIConfig::GetConfig(company, AIConfig::SSS_FORCE_GAME);
	AIInfo *info = config->GetInfo();
	if (info == NULL || (rerandomise_ai && config->IsRandom())) {
		info = AI::scanner_info->SelectRandomAI();
		assert(info != NULL);
		/* Load default data and store the name in the settings */
		config->Change(info->GetName(), -1, false, true);
	}

	Backup<CompanyByte> cur_company(_current_company, company, FILE_LINE);
	Company *c = Company::Get(company);

	c->ai_info = info;
	assert(c->ai_instance == NULL);
	c->ai_instance = new AIInstance();
	c->ai_instance->Initialize(info);

	cur_company.Restore();

	InvalidateWindowData(WC_AI_DEBUG, 0, -1);
	return;
}
Ejemplo n.º 21
0
/**
 * Create a new company and sets all company variables default values
 *
 * @param is_ai is an AI company?
 * @param company CompanyID to use for the new company
 * @return the company struct
 */
Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY)
{
	if (!Company::CanAllocateItem()) return NULL;

	/* we have to generate colour before this company is valid */
	Colours colour = GenerateCompanyColour();

	Company *c;
	if (company == INVALID_COMPANY) {
		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 = (100000ll * _economy.inflation_prices >> 16) / 50000 * 50000;

	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, false); // create a random company manager face

	SetDefaultCompanySettings(c->index);

	GeneratePresidentName(c);

	SetWindowDirty(WC_GRAPH_LEGEND, 0);
	SetWindowClassesDirty(WC_CLIENT_LIST_POPUP);
	SetWindowDirty(WC_CLIENT_LIST, 0);
	InvalidateWindowData(WC_LINKGRAPH_LEGEND, 0);
	BuildOwnerLegend();
	InvalidateWindowData(WC_SMALLMAP, 0, 1);

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

	AI::BroadcastNewEvent(new ScriptEventCompanyNew(c->index), c->index);
	Game::NewEvent(new ScriptEventCompanyNew(c->index));

	return c;
}
Ejemplo n.º 22
0
static bool CheckShipLeaveDepot(Ship *v)
{
	if (!v->IsChainInDepot()) return false;

	/* We are leaving a depot, but have to go to the exact same one; re-enter */
	if (v->current_order.IsType(OT_GOTO_DEPOT) &&
			IsShipDepotTile(v->tile) && GetDepotIndex(v->tile) == v->current_order.GetDestination()) {
		VehicleEnterDepot(v);
		return true;
	}

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

	DiagDirection north_dir = ReverseDiagDir(AxisToDiagDir(axis));
	TileIndex north_neighbour = TILE_ADD(tile, TileOffsByDiagDir(north_dir));
	DiagDirection south_dir = AxisToDiagDir(axis);
	TileIndex south_neighbour = TILE_ADD(tile, 2 * TileOffsByDiagDir(south_dir));

	TrackBits north_tracks = DiagdirReachesTracks(north_dir) & GetTileShipTrackStatus(north_neighbour);
	TrackBits south_tracks = DiagdirReachesTracks(south_dir) & GetTileShipTrackStatus(south_neighbour);
	if (north_tracks && south_tracks) {
		/* Ask pathfinder for best direction */
		bool reverse = false;
		bool path_found;
		switch (_settings_game.pf.pathfinder_for_ships) {
			case VPF_OPF: reverse = OPFShipChooseTrack(v, north_neighbour, north_dir, north_tracks, path_found) == INVALID_TRACK; break; // OPF always allows reversing
			case VPF_NPF: reverse = NPFShipCheckReverse(v); break;
			case VPF_YAPF: reverse = YapfShipCheckReverse(v); break;
			default: NOT_REACHED();
		}
		if (reverse) north_tracks = TRACK_BIT_NONE;
	}

	if (north_tracks) {
		/* Leave towards north */
		v->direction = DiagDirToDir(north_dir);
	} else if (south_tracks) {
		/* Leave towards south */
		v->direction = DiagDirToDir(south_dir);
	} else {
		/* Both ways blocked */
		return false;
	}

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

	v->cur_speed = 0;
	v->UpdateViewport(true, true);
	SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);

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

	return false;
}
Ejemplo n.º 23
0
Company::Company(uint16 name_1, bool is_ai)
{
	this->name_1 = name_1;
	this->location_of_HQ = INVALID_TILE;
	this->is_ai = is_ai;
	for (uint j = 0; j < 4; j++) this->share_owners[j] = COMPANY_SPECTATOR;
	InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, INVALID_COMPANY);
}
Ejemplo n.º 24
0
/**
 * Update the virtual coords needed to draw the waypoint sign.
 */
void Waypoint::UpdateVirtCoord()
{
	Point pt = RemapCoords2(TileX(this->xy) * TILE_SIZE, TileY(this->xy) * TILE_SIZE);
	SetDParam(0, this->index);
	this->sign.UpdatePosition(pt.x, pt.y - 32 * ZOOM_LVL_BASE, STR_VIEWPORT_WAYPOINT);
	/* Recenter viewport */
	InvalidateWindowData(WC_WAYPOINT_VIEW, this->index);
}
Ejemplo n.º 25
0
	virtual void DrawWidget(const Rect &r, int widget) const
	{
		StringID str = INVALID_STRING_ID;

		switch (widget) {
			case WID_S_LEFT:
				/* Draw the date */
				SetDParam(0, _date);
				str = STR_WHITE_DATE_LONG;
				break;

			case WID_S_RIGHT: {
				/* Draw company money, if any */
				const Company *c = Company::GetIfValid(_local_company);
				if (c != NULL) {
					SetDParam(0, c->money);
					str = STR_COMPANY_MONEY;
				}
				break;
			}

			case WID_S_MIDDLE:
				/* Draw status bar */
				if (this->saving) { // true when saving is active
					str = STR_STATUSBAR_SAVING_GAME;
				} else if (_do_autosave) {
					str = STR_STATUSBAR_AUTOSAVE;
				} else if (_pause_mode != PM_UNPAUSED) {
					str = STR_STATUSBAR_PAUSED;
				} else if (this->ticker_scroll < TICKER_STOP && FindWindowById(WC_NEWS_WINDOW, 0) == NULL && _statusbar_news_item != NULL && _statusbar_news_item->string_id != 0) {
					/* Draw the scrolling news text */
					if (!DrawScrollingStatusText(_statusbar_news_item, this->ticker_scroll, r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, r.bottom)) {
						InvalidateWindowData(WC_STATUS_BAR, 0, SBI_NEWS_DELETED);
						if (Company::IsValidID(_local_company)) {
							/* This is the default text */
							SetDParam(0, _local_company);
							str = STR_STATUSBAR_COMPANY_NAME;
						}
					}
				} else {
					if (Company::IsValidID(_local_company)) {
						/* This is the default text */
						SetDParam(0, _local_company);
						str = STR_STATUSBAR_COMPANY_NAME;
					}
				}
				break;
		}

		int center_top = Center(r.top + WD_FRAMERECT_TOP, r.bottom - r.top);
		if (str != INVALID_STRING_ID) DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, center_top, str, TC_FROMSTRING, SA_HOR_CENTER);

		if (widget == WID_S_MIDDLE && this->reminder_timeout > 0) {
			Dimension icon_size = GetSpriteSize(SPR_UNREAD_NEWS);
			center_top = Center(r.top + WD_FRAMERECT_TOP, r.bottom - r.top,  icon_size.height);
			DrawSprite(SPR_UNREAD_NEWS, PAL_NONE, r.right - WD_FRAMERECT_RIGHT - icon_size.width, center_top);
		}
	}
Ejemplo n.º 26
0
/* static */ void AILog::Log(AILog::AILogType level, const char *message)
{
    if (AIObject::GetLogPointer() == NULL) {
        AIObject::GetLogPointer() = new LogData();
        LogData *log = (LogData *)AIObject::GetLogPointer();

        log->lines = CallocT<char *>(80);
        log->type = CallocT<AILog::AILogType>(80);
        log->count = 80;
        log->pos = log->count - 1;
        log->used = 0;
    }
    LogData *log = (LogData *)AIObject::GetLogPointer();

    /* Go to the next log-line */
    log->pos = (log->pos + 1) % log->count;

    if (log->used != log->count) log->used++;

    /* Free last message, and write new message */
    free(log->lines[log->pos]);
    log->lines[log->pos] = strdup(message);
    log->type[log->pos] = level;

    /* Cut string after first \n */
    char *p;
    while ((p = strchr(log->lines[log->pos], '\n')) != NULL) {
        *p = '\0';
        break;
    }

    char logc;

    switch (level) {
    case LOG_SQ_ERROR:
        logc = 'S';
        break;
    case LOG_ERROR:
        logc = 'E';
        break;
    case LOG_SQ_INFO:
        logc = 'P';
        break;
    case LOG_WARNING:
        logc = 'W';
        break;
    case LOG_INFO:
        logc = 'I';
        break;
    default:
        logc = '?';
        break;
    }

    /* Also still print to debug window */
    DEBUG(ai, level, "[%d] [%c] %s", (uint)_current_company, logc, log->lines[log->pos]);
    InvalidateWindowData(WC_AI_DEBUG, 0, _current_company);
}
Ejemplo n.º 27
0
/**
 * Build a buoy.
 * @param tile tile where to place the buoy
 * @param flags operation to perform
 * @param p1 unused
 * @param p2 unused
 * @param text unused
 * @return the cost of this operation or an error
 */
CommandCost CmdBuildBuoy(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	if (tile == 0 || !HasTileWaterGround(tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);

	if (GetTileSlope(tile) != SLOPE_FLAT) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);

	/* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
	Waypoint *wp = FindDeletedWaypointCloseTo(tile, STR_SV_STNAME_BUOY, OWNER_NONE);
	if (wp == NULL && !Waypoint::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_STATIONS_LOADING);

	CommandCost cost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_WAYPOINT_BUOY]);
	if (!IsWaterTile(tile)) {
		CommandCost ret = DoCommand(tile, 0, 0, flags | DC_AUTO, CMD_LANDSCAPE_CLEAR);
		if (ret.Failed()) return ret;
		cost.AddCost(ret);
	}

	if (flags & DC_EXEC) {
		if (wp == NULL) {
			wp = new Waypoint(tile);
		} else {
			/* Move existing (recently deleted) buoy to the new location */
			wp->xy = tile;
			InvalidateWindowData(WC_WAYPOINT_VIEW, wp->index);
		}
		wp->rect.BeforeAddTile(tile, StationRect::ADD_TRY);

		wp->string_id = STR_SV_STNAME_BUOY;

		wp->facilities |= FACIL_DOCK;
		wp->owner = OWNER_NONE;

		wp->build_date = _date;

		if (wp->town == NULL) MakeDefaultName(wp);

		MakeBuoy(tile, wp->index, GetWaterClass(tile));

		wp->UpdateVirtCoord();
		InvalidateWindowData(WC_WAYPOINT_VIEW, wp->index);
	}

	return cost;
}
Ejemplo n.º 28
0
/**
 * Rebuild the left autoreplace list if an engine is removed or added
 * @param e Engine to check if it is removed or added
 * @param id_g The group the engine belongs to
 *  Note: this function only works if it is called either
 *   - when a new vehicle is build, but before it's counted in num_engines
 *   - when a vehicle is deleted and after it's subtracted from num_engines
 *   - when not changing the count (used when changing replace orders)
 */
void InvalidateAutoreplaceWindow(EngineID e, GroupID id_g)
{
	if (GetGroupNumEngines(_local_company, id_g, e) == 0 || GetGroupNumEngines(_local_company, ALL_GROUP, e) == 0) {
		/* We don't have any of this engine type.
		 * Either we just sold the last one, we build a new one or we stopped replacing it.
		 * In all cases, we need to update the left list */
		InvalidateWindowData(WC_REPLACE_VEHICLE, Engine::Get(e)->type, 1);
	}
}
Ejemplo n.º 29
0
/** Disable shuffle and restart playback */
void MusicSystem::Unshuffle()
{
	_settings_client.music.shuffle = false;
	this->active_playlist = this->displayed_playlist;

	if (_settings_client.music.playing) this->Play();

	InvalidateWindowData(WC_MUSIC_WINDOW, 0);
}
Ejemplo n.º 30
0
/**
 * Constructor.
 * @param name_1 Name of the company.
 * @param is_ai  A computer program is running for this company.
 */
Company::Company(uint16 name_1, bool is_ai)
{
	this->name_1 = name_1;
	this->location_of_HQ = INVALID_TILE;
	this->is_ai = is_ai;
	this->terraform_limit = _settings_game.construction.terraform_frame_burst << 16;
	this->clear_limit     = _settings_game.construction.clear_frame_burst << 16;

	for (uint j = 0; j < 4; j++) this->share_owners[j] = COMPANY_SPECTATOR;
	InvalidateWindowData(WC_PERFORMANCE_DETAIL, 0, INVALID_COMPANY);
}