Changeset - r2092:297c1ed07fe8
[Not reviewed]
master
0 3 0
truelight - 19 years ago 2005-07-17 13:34:19
truelight@openttd.org
(svn r2602) -Codechange: removed unused variable (disable_computer)
-Fix: Changed some stuff to make server-side AIs possible in the far future
3 files changed with 5 insertions and 6 deletions:
0 comments (0 inline, 0 general)
main_gui.c
Show inline comments
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "spritecache.h"
 
#include "strings.h"
 
#include "table/sprites.h"
 
#include "table/strings.h"
 
#include "map.h"
 
#include "tile.h"
 
#include "window.h"
 
#include "gui.h"
 
#include "viewport.h"
 
#include "gfx.h"
 
#include "player.h"
 
#include "command.h"
 
#include "news.h"
 
#include "town.h"
 
#include "vehicle.h"
 
#include "console.h"
 
#include "sound.h"
 
#include "network.h"
 
#include "signs.h"
 
#include "waypoint.h"
 

	
 
#include "network_data.h"
 
#include "network_client.h"
 
#include "network_server.h"
 

	
 
#include "table/animcursors.h"
 

	
 

	
 
/* Min/Max date for scenario editor */
 
static const uint MinDate = 0;     // 1920-01-01 (MAX_YEAR_BEGIN_REAL)
 
static const uint MaxDate = 29220; // 2000-01-01
 

	
 
extern void DoTestSave(void);
 
extern void DoTestLoad(void);
 

	
 
extern bool disable_computer;
 

	
 
static int _rename_id;
 
static int _rename_what;
 

	
 
static byte _terraform_size = 1;
 
static byte _last_built_railtype;
 
extern void GenerateWorld(int mode, uint size_x, uint size_y);
 

	
 
extern void GenerateIndustries(void);
 
extern void GenerateTowns(void);
 

	
 
void HandleOnEditTextCancel(void)
 
{
 
	switch(_rename_what) {
 
#ifdef ENABLE_NETWORK
 
	case 4:
 
		NetworkDisconnect();
 
		ShowNetworkGameWindow();
 
		break;
 
#endif /* ENABLE_NETWORK */
 
	}
 
}
 

	
 
void HandleOnEditText(WindowEvent *e)
 
{
 
	const char *b = e->edittext.str;
 
	int id;
 

	
 
	_cmd_text = b;
 

	
 
	id = _rename_id;
 

	
 
	switch (_rename_what) {
 
	case 0: /* Rename a s sign, if string is empty, delete sign */
 
		DoCommandP(0, id, 0, NULL, CMD_RENAME_SIGN | CMD_MSG(STR_280C_CAN_T_CHANGE_SIGN_NAME));
 
		break;
 
	case 1: /* Rename a waypoint */
 
		if (*b == 0) return;
 
		DoCommandP(0, id, 0, NULL, CMD_RENAME_WAYPOINT | CMD_MSG(STR_CANT_CHANGE_WAYPOINT_NAME));
 
		break;
 
#ifdef ENABLE_NETWORK
 
	case 2: /* Speak to.. */
 
		if (!_network_server)
 
			SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT + (id & 0xFF), id & 0xFF, (id >> 8) & 0xFF, e->edittext.str);
 
		else
 
			NetworkServer_HandleChat(NETWORK_ACTION_CHAT + (id & 0xFF), id & 0xFF, (id >> 8) & 0xFF, e->edittext.str, NETWORK_SERVER_INDEX);
 
		break;
 
	case 3: { /* Give money, you can only give money in excess of loan */
 
		const Player *p = GetPlayer(_current_player);
 
		int32 money = min(p->money64 - p->current_loan, atoi(e->edittext.str) / GetCurrentCurrencyRate());
 
		char msg[20];
 

	
 
		money = clamp(money, 0, 20000000); // Clamp between 20 million and 0
 

	
 
		// Give 'id' the money, and substract it from ourself
 
		if (!DoCommandP(0, money, id, NULL, CMD_GIVE_MONEY | CMD_MSG(STR_INSUFFICIENT_FUNDS))) break;
 

	
 
		// Inform the player of this action
 
		snprintf(msg, sizeof(msg), "%d", money);
 

	
 
		if (!_network_server)
 
			SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_PLAYER, id + 1, msg);
 
		else
 
			NetworkServer_HandleChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_PLAYER, id + 1, msg, NETWORK_SERVER_INDEX);
 
		break;
 
	}
 
	case 4: /* Game-Password and Company-Password */
 
		SEND_COMMAND(PACKET_CLIENT_PASSWORD)(id, e->edittext.str);
 
		break;
 
#endif /* ENABLE_NETWORK */
 
	}
 
}
 

	
 
/**
 
 * This code is shared for the majority of the pushbuttons.
 
 * Handles e.g. the pressing of a button (to build things), playing of click sound and sets certain parameters
 
 *
 
 * @param w Window which called the function
 
 * @param widget ID of the widget (=button) that called this function
 
 * @param cursor How should the cursor image change? E.g. cursor with depot image in it
 
 * @param mode Tile highlighting mode, e.g. drawing a rectangle or a dot on the ground
 
 * @param placeproc Procedure which will be called when someone clicks on the map
 

	
 
 * @return true if the button is clicked, false if it's unclicked
 
 */
 

	
 
bool HandlePlacePushButton(Window *w, int widget, CursorID cursor, int mode, PlaceProc *placeproc)
 
{
 
	uint32 mask = 1 << widget;
 

	
 
	if (w->disabled_state & mask)
 
		return false;
 

	
 
	if (!_no_button_sound) SndPlayFx(SND_15_BEEP);
 
	SetWindowDirty(w);
 

	
 
	if (w->click_state & mask) {
openttd.c
Show inline comments
 
#include "stdafx.h"
 
#include "string.h"
 
#include "table/strings.h"
 
#include "debug.h"
 
#include "strings.h"
 
#include "map.h"
 
#include "tile.h"
 

	
 
#define VARDEF
 
#include "openttd.h"
 
#include "mixer.h"
 
#include "spritecache.h"
 
#include "gfx.h"
 
#include "gui.h"
 
#include "station.h"
 
#include "vehicle.h"
 
#include "viewport.h"
 
#include "window.h"
 
#include "player.h"
 
#include "command.h"
 
#include "town.h"
 
#include "industry.h"
 
#include "news.h"
 
#include "engine.h"
 
#include "sound.h"
 
#include "economy.h"
 
#include "fileio.h"
 
#include "hal.h"
 
#include "airport.h"
 
#include "ai.h"
 
#include "console.h"
 
#include "screenshot.h"
 
#include "network.h"
 
#include "signs.h"
 
#include "depot.h"
 
#include "waypoint.h"
 

	
 
#include <stdarg.h>
 

	
 
#ifdef GPMI
 
#include <gpmi.h>
 
#include <gpmi/packages/paths.h>
 
#endif /* GPMI */
 

	
 
void GenerateWorld(int mode, uint size_x, uint size_y);
 
void CallLandscapeTick(void);
 
void IncreaseDate(void);
 
void RunOtherPlayersLoop(void);
 
void DoPaletteAnimations(void);
 
void MusicLoop(void);
 
void ResetMusic(void);
 
void InitializeStations(void);
 
void DeleteAllPlayerStations(void);
 

	
 
extern void SetDifficultyLevel(int mode, GameOptions *gm_opt);
 
extern void DoStartupNewPlayer(bool is_ai);
 
extern void ShowOSErrorBox(const char *buf);
 

	
 
bool LoadSavegame(const char *filename);
 

	
 
extern void HalGameLoop(void);
 

	
 
uint32 _pixels_redrawn;
 
bool _dbg_screen_rect;
 
bool disable_computer; // We should get ride of this thing.. is only used for a debug-cheat
 
static byte _os_version = 0;
 

	
 
/* TODO: usrerror() for errors which are not of an internal nature but
 
 * caused by the user, i.e. missing files or fatal configuration errors.
 
 * Post-0.4.0 since Celestar doesn't want this in SVN before. --pasky */
 

	
 
void CDECL error(const char *s, ...) {
 
	va_list va;
 
	char buf[512];
 
	va_start(va, s);
 
	vsprintf(buf, s, va);
 
	va_end(va);
 

	
 
	ShowOSErrorBox(buf);
 
	if (_video_driver)
 
		_video_driver->stop();
 

	
 
	assert(0);
 
	exit(1);
 
}
 

	
 
void CDECL ShowInfoF(const char *str, ...)
 
{
 
	va_list va;
 
	char buf[1024];
 
	va_start(va, str);
 
	vsprintf(buf, str, va);
 
	va_end(va);
 
	ShowInfo(buf);
 
}
 

	
 
char * CDECL str_fmt(const char *str, ...)
 
{
 
	char buf[4096];
 
	va_list va;
 
	int len;
 
	char *p;
 

	
 
	va_start(va, str);
 
	len = vsprintf(buf, str, va);
 
	va_end(va);
 
	p = malloc(len + 1);
 
	if (p)
 
		memcpy(p, buf, len + 1);
 
	return p;
 
}
 

	
 

	
 
// NULL midi driver
 
static const char *NullMidiStart(const char * const *parm) { return NULL; }
 
static void NullMidiStop(void) {}
 
static void NullMidiPlaySong(const char *filename) {}
 
static void NullMidiStopSong(void) {}
 
static bool NullMidiIsSongPlaying(void) { return true; }
 
static void NullMidiSetVolume(byte vol) {}
 

	
 
const HalMusicDriver _null_music_driver = {
 
	NullMidiStart,
 
	NullMidiStop,
 
	NullMidiPlaySong,
 
	NullMidiStopSong,
 
	NullMidiIsSongPlaying,
 
	NullMidiSetVolume,
 
};
 

	
 
// NULL video driver
 
static void *_null_video_mem;
 
static const char *NullVideoStart(const char * const *parm)
 
{
 
	_screen.width = _screen.pitch = _cur_resolution[0];
 
	_screen.height = _cur_resolution[1];
 
	_null_video_mem = malloc(_cur_resolution[0]*_cur_resolution[1]);
 
	return NULL;
 
}
 
static void NullVideoStop(void) { free(_null_video_mem); }
 
static void NullVideoMakeDirty(int left, int top, int width, int height) {}
 
static int NullVideoMainLoop(void)
 
{
 
	int i = 1000;
 
	do {
 
		GameLoop();
 
		_screen.dst_ptr = _null_video_mem;
 
		UpdateWindows();
 
	} while (--i);
 
	return ML_QUIT;
 
}
 

	
 
static bool NullVideoChangeRes(int w, int h) { return false; }
 
static void NullVideoFullScreen(bool fs) {}
 

	
 
const HalVideoDriver _null_video_driver = {
 
	NullVideoStart,
 
	NullVideoStop,
 
	NullVideoMakeDirty,
 
	NullVideoMainLoop,
 
	NullVideoChangeRes,
 
@@ -939,193 +938,193 @@ void SwitchMode(int new_mode)
 
		int i;
 

	
 
		if (SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_EDITOR)) {
 
			_opt_ptr = &_opt;
 

	
 
			_local_player = OWNER_NONE;
 
			_generating_world = true;
 
			// delete all players.
 
			for (i = 0; i != MAX_PLAYERS; i++) {
 
				ChangeOwnershipOfPlayerItems(i, 0xff);
 
				_players[i].is_active = false;
 
			}
 
			_generating_world = false;
 
			// delete all stations owned by a player
 
			DeleteAllPlayerStations();
 

	
 
#ifdef ENABLE_NETWORK
 
			if (_network_server)
 
				snprintf(_network_game_info.map_name, 40, "Loaded scenario");
 
#endif /* ENABLE_NETWORK */
 
		} else
 
			ShowErrorMessage(INVALID_STRING_ID, STR_4009_GAME_LOAD_FAILED, 0, 0);
 

	
 
		break;
 
	}
 

	
 

	
 
	case SM_MENU: /* Switch to game intro menu */
 
		LoadIntroGame();
 
		break;
 

	
 
	case SM_SAVE: /* Save game */
 
		if (SaveOrLoad(_file_to_saveload.name, SL_SAVE) != SL_OK)
 
			ShowErrorMessage(INVALID_STRING_ID, STR_4007_GAME_SAVE_FAILED, 0, 0);
 
		else
 
			DeleteWindowById(WC_SAVELOAD, 0);
 
		break;
 

	
 
	case SM_GENRANDLAND: /* Generate random land within scenario editor */
 
		GenerateWorld(2, 1<<_patches.map_x, 1<<_patches.map_y);
 
		// XXX: set date
 
		_local_player = OWNER_NONE;
 
		MarkWholeScreenDirty();
 
		break;
 
	}
 

	
 
	if (_switch_mode_errorstr != INVALID_STRING_ID)
 
		ShowErrorMessage(INVALID_STRING_ID,_switch_mode_errorstr,0,0);
 

	
 
	_in_state_game_loop = false;
 
}
 

	
 

	
 
// State controlling game loop.
 
// The state must not be changed from anywhere
 
// but here.
 
// That check is enforced in DoCommand.
 
void StateGameLoop(void)
 
{
 
	// dont execute the state loop during pause
 
	if (_pause) return;
 

	
 
	_in_state_game_loop = true;
 
	// _frame_counter is increased somewhere else when in network-mode
 
	//  Sidenote: _frame_counter is ONLY used for _savedump in non-MP-games
 
	//    Should that not be deleted? If so, the next 2 lines can also be deleted
 
	if (!_networking)
 
		_frame_counter++;
 

	
 
	if (_savedump_path[0] && (uint)_frame_counter >= _savedump_first && (uint)(_frame_counter -_savedump_first) % _savedump_freq == 0 ) {
 
		char buf[100];
 
		sprintf(buf, "%s%.5d.sav", _savedump_path, _frame_counter);
 
		SaveOrLoad(buf, SL_SAVE);
 
		if ((uint)_frame_counter >= _savedump_last) exit(1);
 
	}
 

	
 
	if (_game_mode == GM_EDITOR) {
 
		RunTileLoop();
 
		CallVehicleTicks();
 
		CallLandscapeTick();
 
		CallWindowTickEvent();
 
		NewsLoop();
 
	} else {
 
		// All these actions has to be done from OWNER_NONE
 
		//  for multiplayer compatibility
 
		uint p = _current_player;
 
		_current_player = OWNER_NONE;
 

	
 
		AnimateAnimatedTiles();
 
		IncreaseDate();
 
		RunTileLoop();
 
		CallVehicleTicks();
 
		CallLandscapeTick();
 

	
 
		// To bad the AI does not work in multiplayer, because states are not saved
 
		//  perfectly
 
		if (!disable_computer && !_networking)
 
		if (!_networking)
 
			RunOtherPlayersLoop();
 

	
 
		CallWindowTickEvent();
 
		NewsLoop();
 
		_current_player = p;
 
	}
 

	
 
	_in_state_game_loop = false;
 
}
 

	
 
static void DoAutosave(void)
 
{
 
	char buf[200];
 

	
 
	if (_patches.keep_all_autosave && _local_player != OWNER_SPECTATOR) {
 
		const Player *p = GetPlayer(_local_player);
 
		char *s;
 
		sprintf(buf, "%s%s", _path.autosave_dir, PATHSEP);
 

	
 
		SetDParam(0, p->name_1);
 
		SetDParam(1, p->name_2);
 
		SetDParam(2, _date);
 
		s = (char*)GetString(buf + strlen(_path.autosave_dir) + strlen(PATHSEP), STR_4004);
 
		strcpy(s, ".sav");
 
	} else { /* Save a maximum of 15 autosaves */
 
		int n = _autosave_ctr;
 
		_autosave_ctr = (_autosave_ctr + 1) & 15;
 
		sprintf(buf, "%s%sautosave%d.sav", _path.autosave_dir, PATHSEP, n);
 
	}
 

	
 
	DEBUG(misc, 2) ("Autosaving to %s", buf);
 
	if (SaveOrLoad(buf, SL_SAVE) != SL_OK)
 
		ShowErrorMessage(INVALID_STRING_ID, STR_AUTOSAVE_FAILED, 0, 0);
 
}
 

	
 
static void ScrollMainViewport(int x, int y)
 
{
 
	if (_game_mode != GM_MENU) {
 
		Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
 
		assert(w);
 

	
 
		WP(w,vp_d).scrollpos_x += x << w->viewport->zoom;
 
		WP(w,vp_d).scrollpos_y += y << w->viewport->zoom;
 
	}
 
}
 

	
 
static const int8 scrollamt[16][2] = {
 
	{ 0, 0},
 
	{-2, 0}, // 1:left
 
	{ 0,-2}, // 2:up
 
	{-2,-1}, // 3:left + up
 
	{ 2, 0}, // 4:right
 
	{ 0, 0}, // 5:left + right
 
	{ 2,-1}, // 6:right + up
 
	{ 0,-2}, // 7:left + right + up = up
 
	{ 0 ,2}, // 8:down
 
	{-2 ,1}, // 9:down+left
 
	{ 0, 0}, // 10:impossible
 
	{-2, 0}, // 11:left + up + down = left
 
	{ 2, 1}, // 12:down+right
 
	{ 0, 2}, // 13:left + right + down = down
 
	{ 0,-2}, // 14:left + right + up = up
 
	{ 0, 0}, // 15:impossible
 
};
 

	
 
static void HandleKeyScrolling(void)
 
{
 
	if (_dirkeys && !_no_scroll) {
 
		int factor = _shift_pressed ? 50 : 10;
 
		ScrollMainViewport(scrollamt[_dirkeys][0] * factor, scrollamt[_dirkeys][1] * factor);
 
	}
 
}
 

	
 
void GameLoop(void)
 
{
 
	int m;
 

	
 
	// autosave game?
 
	if (_do_autosave) {
 
		_do_autosave = false;
 
		DoAutosave();
 
		RedrawAutosave();
 
	}
 

	
 
	// handle scrolling of the main window
 
	if (_dirkeys) HandleKeyScrolling();
 

	
 
	// make a screenshot?
 
	if ((m=_make_screenshot) != 0) {
 
		_make_screenshot = 0;
 
		switch(m) {
 
		case 1: // make small screenshot
 
			UndrawMouseCursor();
 
			ShowScreenshotResult(MakeScreenshot());
 
			break;
 
		case 2: // make large screenshot
players.c
Show inline comments
 
@@ -428,197 +428,199 @@ static void GeneratePresidentName(Player
 
	Player *pp;
 
	char buffer[100], buffer2[40];
 

	
 
	for(;;) {
 
restart:;
 

	
 
		p->president_name_2 = Random();
 
		p->president_name_1 = SPECSTR_PRESIDENT_NAME;
 

	
 
		SetDParam(0, p->president_name_2);
 
		GetString(buffer, p->president_name_1);
 
		if (strlen(buffer) >= 32 || GetStringWidth(buffer) >= 94)
 
			continue;
 

	
 
		FOR_ALL_PLAYERS(pp) {
 
			if (pp->is_active && p != pp) {
 
				SetDParam(0, pp->president_name_2);
 
				GetString(buffer2, pp->president_name_1);
 
				if (strcmp(buffer2, buffer) == 0)
 
					goto restart;
 
			}
 
		}
 
		return;
 
	}
 
}
 

	
 
extern int GetPlayerMaxRailtype(int p);
 

	
 
static Player *AllocatePlayer(void)
 
{
 
	Player *p;
 
	// Find a free slot
 
	FOR_ALL_PLAYERS(p) {
 
		if (!p->is_active) {
 
			int i = p->index;
 
			memset(p, 0, sizeof(Player));
 
			p->index = i;
 
			return p;
 
		}
 
	}
 
	return NULL;
 
}
 

	
 
Player *DoStartupNewPlayer(bool is_ai)
 
{
 
	Player *p;
 
	int index;
 

	
 
	p = AllocatePlayer();
 
	if (p == NULL) return NULL;
 

	
 
	index = p->index;
 

	
 
	// Make a color
 
	p->player_color = GeneratePlayerColor();
 
	_player_colors[index] = p->player_color;
 
	p->name_1 = STR_SV_UNNAMED;
 
	p->is_active = true;
 

	
 
	p->money64 = p->player_money = p->current_loan = 100000;
 

	
 
	p->is_ai = is_ai;
 
	p->ai.state = 5; /* AIS_WANT_NEW_ROUTE */
 
	p->share_owners[0] = p->share_owners[1] = p->share_owners[2] = p->share_owners[3] = 0xFF;
 

	
 
	p->max_railtype = GetPlayerMaxRailtype(index);
 
	p->inaugurated_year = _cur_year;
 
	p->face = Random();
 

	
 
	GeneratePresidentName(p);
 

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

	
 
	return p;
 
}
 

	
 
void StartupPlayers(void)
 
{
 
	// The AI starts like in the setting with +2 month max
 
	_next_competitor_start = _opt.diff.competitor_start_time * 90 * DAY_TICKS + RandomRange(60 * DAY_TICKS) + 1;
 
}
 

	
 
static void MaybeStartNewPlayer(void)
 
{
 
	uint n;
 
	Player *p;
 

	
 
	// count number of competitors
 
	n = 0;
 
	for(p=_players; p!=endof(_players); p++)
 
		if (p->is_active && p->is_ai)
 
			n++;
 

	
 
	// when there's a lot of computers in game, the probability that a new one starts is lower
 
	if (n < (uint)_opt.diff.max_no_competitors && n < RandomRange(_opt.diff.max_no_competitors + 2))
 
	if (n < (uint)_opt.diff.max_no_competitors)
 
		if (n < (!_network_server) ? RandomRange(_opt.diff.max_no_competitors + 2) : InteractiveRandomRange(_opt.diff.max_no_competitors + 2))
 
		DoStartupNewPlayer(true);
 

	
 
	// The next AI starts like the difficulty setting said, with +2 month max
 
	_next_competitor_start = _opt.diff.competitor_start_time * 90 * DAY_TICKS + RandomRange(60 * DAY_TICKS) + 1;
 
	_next_competitor_start = _opt.diff.competitor_start_time * 90 * DAY_TICKS + 1;
 
	_next_competitor_start += (!_network_server) ? RandomRange(60 * DAY_TICKS) : InteractiveRandomRange(60 * DAY_TICKS);
 
}
 

	
 
void InitializePlayers(void)
 
{
 
	int i;
 
	memset(_players, 0, sizeof(_players));
 
	for(i = 0; i != MAX_PLAYERS; i++)
 
		_players[i].index=i;
 
	_cur_player_tick_index = 0;
 
}
 

	
 
void OnTick_Players(void)
 
{
 
	Player *p;
 

	
 
	if (_game_mode == GM_EDITOR)
 
		return;
 

	
 
	p = GetPlayer(_cur_player_tick_index);
 
	_cur_player_tick_index = (_cur_player_tick_index + 1) % MAX_PLAYERS;
 
	if (p->name_1 != 0) GenerateCompanyName(p);
 

	
 
	if (!_networking && _game_mode != GM_MENU && !--_next_competitor_start) {
 
		MaybeStartNewPlayer();
 
	}
 
}
 

	
 
void RunOtherPlayersLoop(void)
 
{
 
	Player *p;
 

	
 
	_is_ai_player = true;
 

	
 
	FOR_ALL_PLAYERS(p) {
 
		if (p->is_active && p->is_ai) {
 
			_current_player = p->index;
 
			if (_patches.ainew_active)
 
				AiNewDoGameLoop(p);
 
			else
 
				AiDoGameLoop(p);
 
		}
 
	}
 

	
 
	_is_ai_player = false;
 
	_current_player = OWNER_NONE;
 
}
 

	
 
// index is the next parameter in _decode_parameters to set up
 
StringID GetPlayerNameString(byte player, byte index)
 
{
 
	if (IS_HUMAN_PLAYER(player) && player < MAX_PLAYERS) {
 
		SetDParam(index, player+1);
 
		return STR_7002_PLAYER;
 
	}
 
	return STR_EMPTY;
 
}
 

	
 
extern void ShowPlayerFinances(int player);
 

	
 
void PlayersYearlyLoop(void)
 
{
 
	Player *p;
 

	
 
	// Copy statistics
 
	FOR_ALL_PLAYERS(p) {
 
		if (p->is_active) {
 
			memmove(&p->yearly_expenses[1], &p->yearly_expenses[0], sizeof(p->yearly_expenses) - sizeof(p->yearly_expenses[0]));
 
			memset(&p->yearly_expenses[0], 0, sizeof(p->yearly_expenses[0]));
 
			InvalidateWindow(WC_FINANCES, p->index);
 
		}
 
	}
 

	
 
	if (_patches.show_finances && _local_player != OWNER_SPECTATOR) {
 
		ShowPlayerFinances(_local_player);
 
		p = GetPlayer(_local_player);
 
		if (p->num_valid_stat_ent > 5 && p->old_economy[0].performance_history < p->old_economy[4].performance_history) {
 
			SndPlayFx(SND_01_BAD_YEAR);
 
		} else {
 
			SndPlayFx(SND_00_GOOD_YEAR);
 
		}
 
	}
 
}
 

	
 
void DeletePlayerWindows(int pi)
 
{
 
	DeleteWindowById(WC_COMPANY, pi);
 
	DeleteWindowById(WC_FINANCES, pi);
 
	DeleteWindowById(WC_STATION_LIST, pi);
 
	/* The vehicle list windows also have station in the window_number
 
	 * A stationindex of -1 means the global vehicle list */
 
	DeleteWindowById(WC_TRAINS_LIST, (-1 << 16) | pi);
 
	DeleteWindowById(WC_ROADVEH_LIST, (-1 << 16) | pi);
 
	DeleteWindowById(WC_SHIPS_LIST, (-1 << 16) | pi);
 
	DeleteWindowById(WC_AIRCRAFT_LIST, (-1 << 16) | pi);
 
	DeleteWindowById(WC_BUY_COMPANY, pi);
 
}
0 comments (0 inline, 0 general)