(svn r12806) [NewGRF_ports] -Sync: with trunk r12773:12805.
--- a/projects/openttd_vs80.vcproj Fri Apr 18 21:20:03 2008 +0000
+++ b/projects/openttd_vs80.vcproj Sun Apr 20 15:27:28 2008 +0000
@@ -460,6 +460,10 @@
>
</File>
<File
+ RelativePath=".\..\src\animated_tile.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\articulated_vehicles.cpp"
>
</File>
@@ -544,6 +548,10 @@
>
</File>
<File
+ RelativePath=".\..\src\effectvehicle.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\elrail.cpp"
>
</File>
@@ -816,6 +824,10 @@
>
</File>
<File
+ RelativePath=".\..\src\animated_tile_func.h"
+ >
+ </File>
+ <File
RelativePath=".\..\src\articulated_vehicles.h"
>
</File>
@@ -968,6 +980,14 @@
>
</File>
<File
+ RelativePath=".\..\src\effectvehicle_func.h"
+ >
+ </File>
+ <File
+ RelativePath=".\..\src\effectvehicle_base.h"
+ >
+ </File>
+ <File
RelativePath=".\..\src\core\endian_func.hpp"
>
</File>
--- a/projects/openttd_vs90.vcproj Fri Apr 18 21:20:03 2008 +0000
+++ b/projects/openttd_vs90.vcproj Sun Apr 20 15:27:28 2008 +0000
@@ -457,6 +457,10 @@
>
</File>
<File
+ RelativePath=".\..\src\animated_tile.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\articulated_vehicles.cpp"
>
</File>
@@ -541,6 +545,10 @@
>
</File>
<File
+ RelativePath=".\..\src\effectvehicle.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\elrail.cpp"
>
</File>
@@ -809,6 +817,10 @@
>
</File>
<File
+ RelativePath=".\..\src\animated_tile_func.h"
+ >
+ </File>
+ <File
RelativePath=".\..\src\articulated_vehicles.h"
>
</File>
@@ -961,6 +973,14 @@
>
</File>
<File
+ RelativePath=".\..\src\effectvehicle_func.h"
+ >
+ </File>
+ <File
+ RelativePath=".\..\src\effectvehicle_base.h"
+ >
+ </File>
+ <File
RelativePath=".\..\src\core\endian_func.hpp"
>
</File>
--- a/source.list Fri Apr 18 21:20:03 2008 +0000
+++ b/source.list Sun Apr 20 15:27:28 2008 +0000
@@ -1,6 +1,7 @@
# Source Files
airport.cpp
core/alloc_func.cpp
+animated_tile.cpp
articulated_vehicles.cpp
autoreplace_cmd.cpp
aystar.cpp
@@ -22,6 +23,7 @@
driver.cpp
widgets/dropdown.cpp
economy.cpp
+effectvehicle.cpp
elrail.cpp
engine.cpp
fileio.cpp
@@ -125,6 +127,7 @@
airport.h
core/alloc_func.hpp
core/alloc_type.hpp
+animated_tile_func.h
articulated_vehicles.h
autoreplace_base.h
autoreplace_func.h
@@ -163,6 +166,8 @@
widgets/dropdown_type.h
economy_func.h
economy_type.h
+effectvehicle_func.h
+effectvehicle_base.h
core/endian_func.hpp
engine_func.h
engine_type.h
--- a/src/aircraft_cmd.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/aircraft_cmd.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -36,6 +36,7 @@
#include "player_func.h"
#include "settings_type.h"
#include "order_func.h"
+#include "effectvehicle_func.h"
#include "table/strings.h"
#include "table/sprites.h"
@@ -2211,7 +2212,7 @@
if (v->breakdown_ctr <= 2) {
HandleBrokenAircraft(v);
} else {
- v->breakdown_ctr--;
+ if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--;
}
}
--- a/src/autoreplace_cmd.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/autoreplace_cmd.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -1,5 +1,7 @@
/* $Id$ */
+/** @file autoreplace_cmd.cpp Deals with autoreplace execution but not the setup */
+
#include "stdafx.h"
#include "openttd.h"
#include "roadveh.h"
@@ -117,31 +119,26 @@
return CT_NO_REFIT; // We failed to find a cargo type on the old vehicle and we will not refit the new one
}
-/* Replaces a vehicle (used to be called autorenew)
+/** Replaces a vehicle (used to be called autorenew)
* This function is only called from MaybeReplaceVehicle()
* Must be called with _current_player set to the owner of the vehicle
* @param w Vehicle to replace
* @param flags is the flags to use when calling DoCommand(). Mainly DC_EXEC counts
+ * @param p The vehicle owner (faster than refinding the pointer)
+ * @param new_engine_type The EngineID to replace to
* @return value is cost of the replacement or CMD_ERROR
*/
-static CommandCost ReplaceVehicle(Vehicle **w, byte flags, Money total_cost)
+static CommandCost ReplaceVehicle(Vehicle **w, byte flags, Money total_cost, const Player *p, EngineID new_engine_type)
{
CommandCost cost;
CommandCost sell_value;
Vehicle *old_v = *w;
- const Player *p = GetPlayer(old_v->owner);
- EngineID new_engine_type;
const UnitID cached_unitnumber = old_v->unitnumber;
bool new_front = false;
Vehicle *new_v = NULL;
char *vehicle_name = NULL;
CargoID replacement_cargo_type;
- /* Check if there is a autoreplacement set for the vehicle */
- new_engine_type = EngineReplacementForPlayer(p, old_v->engine_type, old_v->group_id);
- /* if not, just renew to the same type */
- if (new_engine_type == INVALID_ENGINE) new_engine_type = old_v->engine_type;
-
replacement_cargo_type = GetNewCargoTypeForReplace(old_v, new_engine_type);
/* check if we can't refit to the needed type, so no replace takes place to prevent the vehicle from altering cargo type */
@@ -292,21 +289,103 @@
return cost;
}
+/** Removes wagons from a train until it get a certain length
+ * @param v The vehicle
+ * @param old_total_length The wanted max length
+ * @return The profit from selling the wagons
+ */
+static CommandCost WagonRemoval(Vehicle *v, uint16 old_total_length)
+{
+ if (v->type != VEH_TRAIN) return CommandCost();
+ Vehicle *front = v;
+
+ CommandCost cost = CommandCost();
+
+ while (front->u.rail.cached_total_length > old_total_length) {
+ /* the train is too long. We will remove cars one by one from the start of the train until it's short enough */
+ while (v != NULL && RailVehInfo(v->engine_type)->railveh_type != RAILVEH_WAGON) {
+ /* We move backwards in the train until we find a wagon */
+ v = GetNextVehicle(v);
+ }
+
+ if (v == NULL) {
+ /* We sold all the wagons and the train is still not short enough */
+ SetDParam(0, front->unitnumber);
+ AddNewsItem(STR_TRAIN_TOO_LONG_AFTER_REPLACEMENT, NM_SMALL, NF_VIEWPORT | NF_VEHICLE, NT_ADVICE, DNC_NONE, front->index, 0);
+ return cost;
+ }
+
+ /* We found a wagon we can sell */
+ Vehicle *temp = v;
+ v = GetNextVehicle(v);
+ DoCommand(0, (INVALID_VEHICLE << 16) | temp->index, 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE); // remove the wagon from the train
+ MoveVehicleCargo(front, temp); // move the cargo back on the train
+ cost.AddCost(DoCommand(0, temp->index, 0, DC_EXEC, CMD_SELL_RAIL_WAGON)); // sell the wagon
+ }
+ return cost;
+}
+
+/** Get the EngineID of the replacement for a vehicle
+ * @param v The vehicle to find a replacement for
+ * @param p The vehicle's owner (it's faster to forward the pointer than refinding it)
+ * @return the EngineID of the replacement. INVALID_ENGINE if no buildable replacement is found
+ */
+static EngineID GetNewEngineType(const Vehicle *v, const Player *p)
+{
+ if (v->type == VEH_TRAIN && IsRearDualheaded(v)) {
+ /* we build the rear ends of multiheaded trains with the front ones */
+ return INVALID_ENGINE;
+ }
+
+ EngineID e = EngineReplacementForPlayer(p, v->engine_type, v->group_id);
+
+ if (e != INVALID_ENGINE && IsEngineBuildable(e, v->type, _current_player)) {
+ return e;
+ }
+
+ if (v->NeedsAutorenewing(p) && // replace if engine is too old
+ IsEngineBuildable(v->engine_type, v->type, _current_player)) { // engine can still be build
+ return v->engine_type;
+ }
+
+ return INVALID_ENGINE;
+}
+
/** replaces a vehicle if it's set for autoreplace or is too old
* (used to be called autorenew)
* @param v The vehicle to replace
* if the vehicle is a train, v needs to be the front engine
- * @param check Checks if the replace is valid. No action is done at all
- * @param display_costs If set, a cost animation is shown (only if check is false)
- * @return CMD_ERROR if something went wrong. Otherwise the price of the replace
+ * @param flags
+ * @param display_costs If set, a cost animation is shown (only if DC_EXEC is set)
+ * This bool also takes autorenew money into consideration
+ * @return the costs, the success bool and sometimes an error message
*/
-CommandCost MaybeReplaceVehicle(Vehicle *v, bool check, bool display_costs)
+CommandCost MaybeReplaceVehicle(Vehicle *v, uint32 flags, bool display_costs)
{
Vehicle *w;
const Player *p = GetPlayer(v->owner);
- byte flags = 0;
- CommandCost cost, temp_cost;
- bool stopped;
+ CommandCost cost;
+ bool stopped = false;
+
+ /* We only want "real" vehicle types. */
+ assert(IsPlayerBuildableVehicleType(v));
+
+ /* Ensure that this bool is cleared. */
+ assert(!v->leave_depot_instantly);
+
+ /* We can't sell if the current player don't own the vehicle. */
+ assert(v->owner == _current_player);
+
+ if (!v->IsInDepot()) {
+ /* The vehicle should be inside the depot */
+ switch (v->type) {
+ default: NOT_REACHED();
+ case VEH_TRAIN: return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED); break;
+ case VEH_ROAD: return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE); break;
+ case VEH_SHIP: return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN); break;
+ case VEH_AIRCRAFT: return_cmd_error(STR_A01B_AIRCRAFT_MUST_BE_STOPPED); break;
+ }
+ }
/* Remember the length in case we need to trim train later on
* If it's not a train, the value is unused
@@ -317,38 +396,22 @@
-1
);
-
- _current_player = v->owner;
-
- assert(IsPlayerBuildableVehicleType(v));
-
- assert(v->vehstatus & VS_STOPPED); // the vehicle should have been stopped in VehicleEnteredDepotThisTick() if needed
+ if (!(v->vehstatus & VS_STOPPED)) {
+ /* The vehicle is moving so we better stop it before we might alter consist or sell it */
+ v->vehstatus |= VS_STOPPED;
+ /* Remember that we stopped the vehicle */
+ stopped = true;
+ }
- /* Remember the flag v->leave_depot_instantly because if we replace the vehicle, the vehicle holding this flag will be sold
- * If it is set, then we only stopped the vehicle to replace it (if needed) and we will need to start it again.
- * We also need to reset the flag since it should remain false except from when the vehicle enters a depot until autoreplace is handled in the same tick */
- stopped = v->leave_depot_instantly;
- v->leave_depot_instantly = false;
-
- for (;;) {
+ {
cost = CommandCost(EXPENSES_NEW_VEHICLES);
w = v;
do {
- if (w->type == VEH_TRAIN && IsRearDualheaded(w)) {
- /* we build the rear ends of multiheaded trains with the front ones */
- continue;
- }
-
- // check if the vehicle should be replaced
- if (!w->NeedsAutorenewing(p) || // replace if engine is too old
- w->max_age == 0) { // rail cars got a max age of 0
- if (!EngineHasReplacementForPlayer(p, w->engine_type, w->group_id)) continue;
- }
+ EngineID new_engine = GetNewEngineType(w, p);
+ if (new_engine == INVALID_ENGINE) continue;
/* Now replace the vehicle */
- temp_cost = ReplaceVehicle(&w, flags, cost.GetCost());
-
- if (CmdFailed(temp_cost)) break; // replace failed for some reason. Leave the vehicle alone
+ cost.AddCost(ReplaceVehicle(&w, flags, cost.GetCost(), p, new_engine));
if (flags & DC_EXEC &&
(w->type != VEH_TRAIN || w->u.rail.first_engine == INVALID_ENGINE)) {
@@ -358,11 +421,26 @@
*/
v = w;
}
- cost.AddCost(temp_cost);
} while (w->type == VEH_TRAIN && (w = GetNextVehicle(w)) != NULL);
- if (!(flags & DC_EXEC) && (p->player_money < (cost.GetCost() + p->engine_renew_money) || cost.GetCost() == 0)) {
- if (!check && p->player_money < (cost.GetCost() + p->engine_renew_money) && ( _local_player == v->owner ) && cost.GetCost() != 0) {
+ if (flags & DC_QUERY_COST || cost.GetCost() == 0) {
+ /* We didn't do anything during the replace so we will just exit here */
+ if (stopped) v->vehstatus &= ~VS_STOPPED;
+ return cost;
+ }
+
+ if (display_costs && !(flags & DC_EXEC)) {
+ /* We want to ensure that we will not get below p->engine_renew_money.
+ * We will not actually pay this amount. It's for display and checks only. */
+ cost.AddCost((Money)p->engine_renew_money);
+ if (CmdSucceeded(cost) && GetAvailableMoneyForCommand() < cost.GetCost()) {
+ /* We don't have enough money so we will set cost to failed */
+ cost.AddCost(CMD_ERROR);
+ }
+ }
+
+ if (display_costs && CmdFailed(cost)) {
+ if (GetAvailableMoneyForCommand() < cost.GetCost() && IsLocalPlayer()) {
StringID message;
SetDParam(0, v->unitnumber);
switch (v->type) {
@@ -376,50 +454,22 @@
AddNewsItem(message, NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, DNC_NONE, v->index, 0);
}
- if (stopped) v->vehstatus &= ~VS_STOPPED;
- if (display_costs) _current_player = OWNER_NONE;
- return CMD_ERROR;
- }
-
- if (flags & DC_EXEC) {
- break; // we are done replacing since the loop ran once with DC_EXEC
- } else if (check) {
- /* It's a test only and we know that we can do this
- * NOTE: payment for wagon removal is NOT included in this price */
- return cost;
- }
- // now we redo the loop, but this time we actually do stuff since we know that we can do it
- flags |= DC_EXEC;
- }
-
- /* If setting is on to try not to exceed the old length of the train with the replacement */
- if (v->type == VEH_TRAIN && p->renew_keep_length) {
- Vehicle *temp;
- w = v;
-
- while (v->u.rail.cached_total_length > old_total_length) {
- // the train is too long. We will remove cars one by one from the start of the train until it's short enough
- while (w != NULL && RailVehInfo(w->engine_type)->railveh_type != RAILVEH_WAGON) {
- w = GetNextVehicle(w);
- }
- if (w == NULL) {
- // we failed to make the train short enough
- SetDParam(0, v->unitnumber);
- AddNewsItem(STR_TRAIN_TOO_LONG_AFTER_REPLACEMENT, NM_SMALL, NF_VIEWPORT | NF_VEHICLE, NT_ADVICE, DNC_NONE, v->index, 0);
- break;
- }
- temp = w;
- w = GetNextVehicle(w);
- DoCommand(0, (INVALID_VEHICLE << 16) | temp->index, 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
- MoveVehicleCargo(v, temp);
- cost.AddCost(DoCommand(0, temp->index, 0, DC_EXEC, CMD_SELL_RAIL_WAGON));
}
}
+ if (flags & DC_EXEC && CmdSucceeded(cost)) {
+ if (v->type == VEH_TRAIN && p->renew_keep_length) {
+ /* Remove wagons until the wanted length is reached */
+ cost.AddCost(WagonRemoval(v, old_total_length));
+ }
+
+ if (display_costs && IsLocalPlayer()) {
+ ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
+ }
+ }
+
+ /* Start the vehicle if we stopped it earlier */
if (stopped) v->vehstatus &= ~VS_STOPPED;
- if (display_costs) {
- if (IsLocalPlayer()) ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
- _current_player = OWNER_NONE;
- }
+
return cost;
}
--- a/src/core/alloc_func.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/core/alloc_func.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -9,7 +9,7 @@
* Function to exit with an error message after malloc() or calloc() have failed
* @param size number of bytes we tried to allocate
*/
-void MallocError(size_t size)
+void NORETURN MallocError(size_t size)
{
error("Out of memory. Cannot allocate %i bytes", size);
}
@@ -18,7 +18,7 @@
* Function to exit with an error message after realloc() have failed
* @param size number of bytes we tried to allocate
*/
-void ReallocError(size_t size)
+void NORETURN ReallocError(size_t size)
{
error("Out of memory. Cannot reallocate %i bytes", size);
}
--- a/src/core/alloc_func.hpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/core/alloc_func.hpp Sun Apr 20 15:27:28 2008 +0000
@@ -11,8 +11,8 @@
* duplicated in each object file making the final
* binary needlessly large.
*/
-void MallocError(size_t size);
-void ReallocError(size_t size);
+void NORETURN MallocError(size_t size);
+void NORETURN ReallocError(size_t size);
/**
* Simplified allocation function that allocates the specified number of
--- a/src/disaster_cmd.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/disaster_cmd.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -39,6 +39,7 @@
#include "vehicle_func.h"
#include "vehicle_base.h"
#include "sound_func.h"
+#include "effectvehicle_func.h"
#include "table/strings.h"
#include "table/sprites.h"
--- a/src/economy.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/economy.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -26,6 +26,7 @@
#include "newgrf_callbacks.h"
#include "newgrf_industries.h"
#include "newgrf_industrytiles.h"
+#include "newgrf_station.h"
#include "unmovable.h"
#include "cargotype.h"
#include "player_face.h"
@@ -1691,6 +1692,8 @@
st->time_since_load = 0;
st->last_vehicle_type = v->type;
+ StationAnimationTrigger(st, st->xy, STAT_ANIM_CARGO_TAKEN, v->cargo_type);
+
unloading_time += cap;
result |= 2;
--- a/src/engine_func.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/engine_func.h Sun Apr 20 15:27:28 2008 +0000
@@ -1,6 +1,6 @@
/* $Id$ */
-/** @file engine.h */
+/** @file engine_func.h */
#ifndef ENGINE_H
#define ENGINE_H
--- a/src/functions.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/functions.h Sun Apr 20 15:27:28 2008 +0000
@@ -22,21 +22,11 @@
bool CheckOwnership(Owner owner);
bool CheckTileOwnership(TileIndex tile);
-/* texteff.cpp */
-void AddAnimatedTile(TileIndex tile);
-void DeleteAnimatedTile(TileIndex tile);
-void AnimateAnimatedTiles();
-void InitializeAnimatedTiles();
-
/* misc_cmd.cpp */
void PlaceTreesRandomly();
void InitializeLandscapeVariables(bool only_constants);
-/* misc.cpp */
-bool IsCustomName(StringID id);
-char *CopyFromOldName(StringID id);
-
/* misc functions */
/**
* Mark a tile given by its coordinate dirty for repaint.
@@ -68,14 +58,10 @@
void RedrawAutosave();
-StringID RemapOldStringID(StringID s);
-
void UpdateViewportSignPos(ViewportSign *sign, int left, int top, StringID str);
-
/* callback from drivers that is called if the game size changes dynamically */
void GameSizeChanged();
-const char *GetCurrentLocale(const char *param);
int ttd_main(int argc, char* argv[]);
void HandleExitGameRequest();
--- a/src/gfx.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/gfx.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -17,6 +17,7 @@
#include "strings_func.h"
#include "core/math_func.hpp"
#include "settings_type.h"
+#include "core/alloc_func.hpp"
#include "table/palettes.h"
#include "table/sprites.h"
@@ -64,8 +65,12 @@
static const byte *_color_remap_ptr;
static byte _string_colorremap[3];
-#define DIRTY_BYTES_PER_LINE (MAX_SCREEN_WIDTH / 64)
-static byte _dirty_blocks[DIRTY_BYTES_PER_LINE * MAX_SCREEN_HEIGHT / 8];
+enum {
+ DIRTY_BLOCK_HEIGHT = 8,
+ DIRTY_BLOCK_WIDTH = 64,
+};
+static uint _dirty_bytes_per_line = 0;
+static byte *_dirty_blocks = NULL;
void GfxScroll(int left, int top, int width, int height, int xo, int yo)
{
@@ -930,6 +935,9 @@
void ScreenSizeChanged()
{
+ _dirty_bytes_per_line = (_screen.width + DIRTY_BLOCK_WIDTH - 1) / DIRTY_BLOCK_WIDTH;
+ _dirty_blocks = ReallocT<byte>(_dirty_blocks, _dirty_bytes_per_line * ((_screen.height + DIRTY_BLOCK_HEIGHT - 1) / DIRTY_BLOCK_HEIGHT));
+
/* check the dirty rect */
if (_invalid_rect.right >= _screen.width) _invalid_rect.right = _screen.width;
if (_invalid_rect.bottom >= _screen.height) _invalid_rect.bottom = _screen.height;
@@ -1033,8 +1041,8 @@
void DrawDirtyBlocks()
{
byte *b = _dirty_blocks;
- const int w = Align(_screen.width, 64);
- const int h = Align(_screen.height, 8);
+ const int w = Align(_screen.width, DIRTY_BLOCK_WIDTH);
+ const int h = Align(_screen.height, DIRTY_BLOCK_HEIGHT);
int x;
int y;
@@ -1047,7 +1055,7 @@
if (*b != 0) {
int left;
int top;
- int right = x + 64;
+ int right = x + DIRTY_BLOCK_WIDTH;
int bottom = y;
byte *p = b;
int h2;
@@ -1055,12 +1063,12 @@
/* First try coalescing downwards */
do {
*p = 0;
- p += DIRTY_BYTES_PER_LINE;
- bottom += 8;
+ p += _dirty_bytes_per_line;
+ bottom += DIRTY_BLOCK_HEIGHT;
} while (bottom != h && *p != 0);
/* Try coalescing to the right too. */
- h2 = (bottom - y) >> 3;
+ h2 = (bottom - y) / DIRTY_BLOCK_HEIGHT;
assert(h2 > 0);
p = b;
@@ -1070,18 +1078,18 @@
/* Check if a full line of dirty flags is set. */
do {
if (!*p2) goto no_more_coalesc;
- p2 += DIRTY_BYTES_PER_LINE;
+ p2 += _dirty_bytes_per_line;
} while (--h != 0);
/* Wohoo, can combine it one step to the right!
* Do that, and clear the bits. */
- right += 64;
+ right += DIRTY_BLOCK_WIDTH;
h = h2;
p2 = p;
do {
*p2 = 0;
- p2 += DIRTY_BYTES_PER_LINE;
+ p2 += _dirty_bytes_per_line;
} while (--h != 0);
}
no_more_coalesc:
@@ -1099,8 +1107,8 @@
}
}
- } while (b++, (x += 64) != w);
- } while (b += -(w >> 6) + DIRTY_BYTES_PER_LINE, (y += 8) != h);
+ } while (b++, (x += DIRTY_BLOCK_WIDTH) != w);
+ } while (b += -(w / DIRTY_BLOCK_WIDTH) + _dirty_bytes_per_line, (y += DIRTY_BLOCK_HEIGHT) != h);
_invalid_rect.left = w;
_invalid_rect.top = h;
@@ -1147,13 +1155,13 @@
if (right > _invalid_rect.right ) _invalid_rect.right = right;
if (bottom > _invalid_rect.bottom) _invalid_rect.bottom = bottom;
- left >>= 6;
- top >>= 3;
+ left /= DIRTY_BLOCK_WIDTH;
+ top /= DIRTY_BLOCK_HEIGHT;
- b = _dirty_blocks + top * DIRTY_BYTES_PER_LINE + left;
+ b = _dirty_blocks + top * _dirty_bytes_per_line + left;
- width = ((right - 1) >> 6) - left + 1;
- height = ((bottom - 1) >> 3) - top + 1;
+ width = ((right - 1) / DIRTY_BLOCK_WIDTH) - left + 1;
+ height = ((bottom - 1) / DIRTY_BLOCK_HEIGHT) - top + 1;
assert(width > 0 && height > 0);
@@ -1162,7 +1170,7 @@
do b[--i] = 0xFF; while (i);
- b += DIRTY_BYTES_PER_LINE;
+ b += _dirty_bytes_per_line;
} while (--height != 0);
}
--- a/src/industry_cmd.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/industry_cmd.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -39,6 +39,8 @@
#include "sound_func.h"
#include "station_base.h"
#include "oldpool_func.h"
+#include "animated_tile_func.h"
+#include "effectvehicle_func.h"
#include "table/strings.h"
#include "table/sprites.h"
@@ -620,7 +622,7 @@
}
}
-static void CreateIndustryEffectSmoke(TileIndex tile)
+static void CreateChimneySmoke(TileIndex tile)
{
uint x = TileX(tile) * TILE_SIZE;
uint y = TileY(tile) * TILE_SIZE;
@@ -657,7 +659,7 @@
switch (gfx) {
case GFX_POWERPLANT_CHIMNEY:
- CreateIndustryEffectSmoke(tile);
+ CreateChimneySmoke(tile);
break;
case GFX_OILRIG_1:
@@ -684,10 +686,10 @@
{
int dir;
Vehicle *v;
- static const int8 _tileloop_ind_case_161[12] = {
- 11, 0, -4, -14,
- -4, -10, -4, 1,
- 49, 59, 60, 65,
+ static const int8 _bubble_spawn_location[3][4] = {
+ { 11, 0, -4, -14 },
+ { -4, -10, -4, 1 },
+ { 49, 59, 60, 65 },
};
SndPlayTileFx(SND_2E_EXTRACT_AND_POP, tile);
@@ -695,13 +697,13 @@
dir = Random() & 3;
v = CreateEffectVehicleAbove(
- TileX(tile) * TILE_SIZE + _tileloop_ind_case_161[dir + 0],
- TileY(tile) * TILE_SIZE + _tileloop_ind_case_161[dir + 4],
- _tileloop_ind_case_161[dir + 8],
+ TileX(tile) * TILE_SIZE + _bubble_spawn_location[0][dir],
+ TileY(tile) * TILE_SIZE + _bubble_spawn_location[1][dir],
+ _bubble_spawn_location[2][dir],
EV_BUBBLE
);
- if (v != NULL) v->u.special.animation_substate = dir;
+ if (v != NULL) v->u.effect.animation_substate = dir;
}
static void TileLoop_Industry(TileIndex tile)
--- a/src/industry_gui.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/industry_gui.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -631,7 +631,7 @@
WP(w, indview_d).editbox_line = 0;
WP(w, indview_d).clicked_line = 0;
WP(w, indview_d).clicked_button = 0;
- AssignWindowViewport(w, 3, 17, 0xFE, 0x56, GetIndustry(w->window_number)->xy + TileDiffXY(1, 1), ZOOM_LVL_INDUSTRY);
+ InitializeWindowViewport(w, 3, 17, 254, 86, GetIndustry(w->window_number)->xy + TileDiffXY(1, 1), ZOOM_LVL_INDUSTRY);
}
}
--- a/src/landscape.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/landscape.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -24,6 +24,7 @@
#include "vehicle_func.h"
#include "settings_type.h"
#include "water.h"
+#include "effectvehicle_func.h"
#include "table/sprites.h"
--- a/src/main_gui.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/main_gui.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -412,7 +412,7 @@
int height = _screen.height;
Window *w = AllocateWindow(0, 0, width, height, MainWindowWndProc, WC_MAIN_WINDOW, NULL);
- AssignWindowViewport(w, 0, 0, width, height, TileXY(32, 32), ZOOM_LVL_VIEWPORT);
+ InitializeWindowViewport(w, 0, 0, width, height, TileXY(32, 32), ZOOM_LVL_VIEWPORT);
/* XXX: these are not done */
switch (_game_mode) {
@@ -449,7 +449,7 @@
{
_cur_resolution[0] = _screen.width;
_cur_resolution[1] = _screen.height;
+ ScreenSizeChanged();
RelocateAllWindows(_screen.width, _screen.height);
- ScreenSizeChanged();
MarkWholeScreenDirty();
}
--- a/src/misc.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/misc.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -23,14 +23,13 @@
#include "date_func.h"
#include "vehicle_func.h"
#include "texteff.hpp"
-#include "string_func.h"
#include "gfx_func.h"
#include "core/alloc_type.hpp"
+#include "animated_tile_func.h"
#include "table/strings.h"
#include "table/sprites.h"
-char _name_array[512][32];
extern TileIndex _cur_tileloop_tile;
void InitializeVehicles();
@@ -49,10 +48,10 @@
void InitializeSigns();
void InitializeStations();
void InitializeCargoPackets();
-static void InitializeNameMgr();
void InitializePlayers();
void InitializeCheats();
void InitializeNPF();
+void InitializeOldNames();
void InitializeGame(int mode, uint size_x, uint size_y)
{
@@ -93,7 +92,7 @@
InitializeIndustries();
InitializeBuildingCounts();
- InitializeNameMgr();
+ InitializeOldNames();
InitializeVehiclesGuiList();
InitializeTrains();
InitializeNPF();
@@ -111,60 +110,6 @@
ResetObjectToPlace();
}
-bool IsCustomName(StringID id)
-{
- return GB(id, 11, 5) == 15;
-}
-
-
-static void InitializeNameMgr()
-{
- memset(_name_array, 0, sizeof(_name_array));
-}
-
-/* Copy and convert old custom names to UTF-8 */
-char *CopyFromOldName(StringID id)
-{
- if (!IsCustomName(id)) return NULL;
-
- if (CheckSavegameVersion(37)) {
- /* Old names were 32 characters long, so 128 characters should be
- * plenty to allow for expansion when converted to UTF-8. */
- char tmp[128];
- const char *strfrom = _name_array[GB(id, 0, 9)];
- char *strto = tmp;
-
- for (; *strfrom != '\0'; strfrom++) {
- WChar c = (byte)*strfrom;
-
- /* Map from non-ISO8859-15 characters to UTF-8. */
- switch (c) {
- case 0xA4: c = 0x20AC; break; // Euro
- case 0xA6: c = 0x0160; break; // S with caron
- case 0xA8: c = 0x0161; break; // s with caron
- case 0xB4: c = 0x017D; break; // Z with caron
- case 0xB8: c = 0x017E; break; // z with caron
- case 0xBC: c = 0x0152; break; // OE ligature
- case 0xBD: c = 0x0153; break; // oe ligature
- case 0xBE: c = 0x0178; break; // Y with diaresis
- default: break;
- }
-
- /* Check character will fit into our buffer. */
- if (strto + Utf8CharLen(c) > lastof(tmp)) break;
-
- strto += Utf8Encode(strto, c);
- }
-
- /* Terminate the new string and copy it back to the name array */
- *strto = '\0';
-
- return strdup(tmp);
- } else {
- /* Name will already be in UTF-8. */
- return strdup(_name_array[GB(id, 0, 9)]);
- }
-}
/* Calculate constants that depend on the landscape type. */
void InitializeLandscapeVariables(bool only_constants)
@@ -177,15 +122,6 @@
}
}
-static void Load_NAME()
-{
- int index;
-
- while ((index = SlIterateArray()) != -1) {
- SlArray(_name_array[index], SlGetFieldLength(), SLE_UINT8);
- }
-}
-
static const SaveLoadGlobVarList _date_desc[] = {
SLEG_CONDVAR(_date, SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
SLEG_CONDVAR(_date, SLE_INT32, 31, SL_MAX_VERSION),
@@ -469,7 +405,6 @@
{ 'MAPE', Save_MAP6, Load_MAP6, CH_RIFF },
{ 'MAP7', Save_MAP7, Load_MAP7, CH_RIFF },
- { 'NAME', NULL, Load_NAME, CH_ARRAY},
{ 'DATE', SaveLoad_DATE, SaveLoad_DATE, CH_RIFF},
{ 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, CH_RIFF | CH_LAST},
};
--- a/src/network/core/packet.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/network/core/packet.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -11,10 +11,6 @@
#include "packet.h"
-
-/* Do not want to include functions.h and all required headers */
-extern void NORETURN CDECL error(const char *str, ...);
-
/**
* Create a packet that is used to read from a network socket
* @param cs the socket handler associated with the socket we are reading from
--- a/src/newgrf.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/newgrf.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -1127,19 +1127,17 @@
statspec->blocked = grf_load_byte(&buf);
break;
- case 0x16: // @todo Animation info
- grf_load_word(&buf);
- ret = true;
- break;
-
- case 0x17: // @todo Animation speed
- grf_load_byte(&buf);
- ret = true;
- break;
-
- case 0x18: // @todo Animation triggers
- grf_load_word(&buf);
- ret = true;
+ case 0x16: // Animation info
+ statspec->anim_frames = grf_load_byte(&buf);
+ statspec->anim_status = grf_load_byte(&buf);
+ break;
+
+ case 0x17: // Animation speed
+ statspec->anim_speed = grf_load_byte(&buf);
+ break;
+
+ case 0x18: // Animation triggers
+ statspec->anim_triggers = grf_load_word(&buf);
break;
default:
--- a/src/newgrf_callbacks.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/newgrf_callbacks.h Sun Apr 20 15:27:28 2008 +0000
@@ -173,13 +173,13 @@
/* There are no callbacks 0x3E - 0x13F */
/** Called for periodically starting or stopping the animation. */
- CBID_STATION_ANIM_START_STOP = 0x140, // not implemented
+ CBID_STATION_ANIM_START_STOP = 0x140,
/** Called to determine station tile next animation frame. */
- CBID_STATION_ANIM_NEXT_FRAME = 0x141, // not implemented
+ CBID_STATION_ANIM_NEXT_FRAME = 0x141,
/** Called to indicate how long the current animation frame should last. */
- CBID_STATION_ANIMATION_SPEED = 0x142, // not implemented
+ CBID_STATION_ANIMATION_SPEED = 0x142,
/** Called to determine whether a town building can be destroyed. */
CBID_HOUSE_DENY_DESTRUCTION = 0x143,
--- a/src/newgrf_fsmports.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/newgrf_fsmports.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -21,6 +21,7 @@
#include "cargotype.h"
#include "town_map.h"
#include "newgrf_town.h"
+#include "date_func.h"
#include "player_func.h"
#include "gfx_func.h"
#include "strings_func.h"
--- a/src/newgrf_house.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/newgrf_house.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -21,6 +21,8 @@
#include "transparency.h"
#include "functions.h"
#include "player_func.h"
+#include "animated_tile_func.h"
+#include "date_func.h"
#include "table/strings.h"
#include "table/sprites.h"
--- a/src/newgrf_industrytiles.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/newgrf_industrytiles.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -23,6 +23,7 @@
#include "functions.h"
#include "town.h"
#include "command_func.h"
+#include "animated_tile_func.h"
#include "table/sprites.h"
#include "table/strings.h"
--- a/src/newgrf_station.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/newgrf_station.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -22,6 +22,8 @@
#include "gfx_func.h"
#include "date_func.h"
#include "player_func.h"
+#include "animated_tile_func.h"
+#include "functions.h"
#include "table/sprites.h"
#include "table/strings.h"
@@ -741,8 +743,12 @@
free(st->speclist);
st->num_specs = 0;
st->speclist = NULL;
+ st->cached_anim_triggers = 0;
+ return;
}
}
+
+ StationUpdateAnimTriggers(st);
}
/** Draw representation of a station tile for GUI purposes.
@@ -854,3 +860,178 @@
HasBit(statspec->pylons, GetStationGfx(tile)) ||
!HasBit(statspec->wires, GetStationGfx(tile));
}
+
+void AnimateStationTile(TileIndex tile)
+{
+ const StationSpec *ss = GetStationSpec(tile);
+ if (ss == NULL) return;
+
+ const Station *st = GetStationByTile(tile);
+
+ uint8 animation_speed = ss->anim_speed;
+
+ if (HasBit(ss->callbackmask, CBM_STATION_ANIMATION_SPEED)) {
+ uint16 callback = GetStationCallback(CBID_STATION_ANIMATION_SPEED, 0, 0, ss, st, tile);
+ if (callback != CALLBACK_FAILED) animation_speed = Clamp(callback & 0xFF, 0, 16);
+ }
+
+ if (_tick_counter % (1 << animation_speed) != 0) return;
+
+ uint8 frame = GetStationAnimationFrame(tile);
+ uint8 num_frames = ss->anim_frames;
+
+ bool frame_set_by_callback = false;
+
+ if (HasBit(ss->callbackmask, CBM_STATION_ANIMATION_NEXT_FRAME)) {
+ uint32 param = HasBit(ss->flags, 2) ? Random() : 0;
+ uint16 callback = GetStationCallback(CBID_STATION_ANIM_NEXT_FRAME, param, 0, ss, st, tile);
+
+ if (callback != CALLBACK_FAILED) {
+ frame_set_by_callback = true;
+
+ switch (callback & 0xFF) {
+ case 0xFF:
+ DeleteAnimatedTile(tile);
+ break;
+
+ case 0xFE:
+ frame_set_by_callback = false;
+ break;
+
+ default:
+ frame = callback & 0xFF;
+ break;
+ }
+ }
+ }
+
+ if (!frame_set_by_callback) {
+ if (frame < num_frames) {
+ frame++;
+ } else if (frame == num_frames && HasBit(ss->anim_status, 0)) {
+ /* This animation loops, so start again from the beginning */
+ frame = 0;
+ } else {
+ /* This animation doesn't loop, so stay here */
+ DeleteAnimatedTile(tile);
+ }
+ }
+
+ SetStationAnimationFrame(tile, frame);
+ MarkTileDirtyByTile(tile);
+}
+
+
+static void ChangeStationAnimationFrame(const StationSpec *ss, const Station *st, TileIndex tile, uint16 random_bits, StatAnimTrigger trigger, CargoID cargo_type)
+{
+ uint16 callback = GetStationCallback(CBID_STATION_ANIM_START_STOP, (random_bits << 16) | Random(), (uint8)trigger | (cargo_type << 8), ss, st, tile);
+ if (callback == CALLBACK_FAILED) return;
+
+ switch (callback & 0xFF) {
+ case 0xFD: /* Do nothing. */ break;
+ case 0xFE: AddAnimatedTile(tile); break;
+ case 0xFF: DeleteAnimatedTile(tile); break;
+ default:
+ SetStationAnimationFrame(tile, callback);
+ AddAnimatedTile(tile);
+ break;
+ }
+}
+
+enum TriggerArea {
+ TA_TILE,
+ TA_PLATFORM,
+ TA_WHOLE,
+};
+
+struct TileArea {
+ TileIndex tile;
+ uint8 w;
+ uint8 h;
+
+ TileArea(const Station *st, TileIndex tile, TriggerArea ta)
+ {
+ switch (ta) {
+ default: NOT_REACHED();
+
+ case TA_TILE:
+ this->tile = tile;
+ this->w = 1;
+ this->h = 1;
+ break;
+
+ case TA_PLATFORM: {
+ TileIndex start, end;
+ Axis axis = GetRailStationAxis(tile);
+ TileIndexDiff delta = TileOffsByDiagDir(AxisToDiagDir(axis));
+
+ for (end = tile; IsRailwayStationTile(end + delta) && IsCompatibleTrainStationTile(tile, end + delta); end += delta) { /* Nothing */ }
+ for (start = tile; IsRailwayStationTile(start - delta) && IsCompatibleTrainStationTile(tile, start - delta); start -= delta) { /* Nothing */ }
+
+ this->tile = start;
+ this->w = TileX(end) - TileX(start) + 1;
+ this->h = TileY(end) - TileY(start) + 1;
+ break;
+ }
+
+ case TA_WHOLE:
+ this->tile = st->train_tile;
+ this->w = st->trainst_w + 1;
+ this->h = st->trainst_h + 1;
+ break;
+ }
+ }
+};
+
+void StationAnimationTrigger(const Station *st, TileIndex tile, StatAnimTrigger trigger, CargoID cargo_type)
+{
+ /* List of coverage areas for each animation trigger */
+ static const TriggerArea tas[] = {
+ TA_TILE, TA_WHOLE, TA_WHOLE, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM, TA_WHOLE
+ };
+
+ /* Get Station if it wasn't supplied */
+ if (st == NULL) st = GetStationByTile(tile);
+
+ /* Check the cached animation trigger bitmask to see if we need
+ * to bother with any further processing. */
+ if (!HasBit(st->cached_anim_triggers, trigger)) return;
+
+ uint16 random_bits = Random();
+ TileArea area = TileArea(st, tile, tas[trigger]);
+
+ for (uint y = 0; y < area.h; y++) {
+ for (uint x = 0; x < area.w; x++) {
+ if (st->TileBelongsToRailStation(area.tile)) {
+ const StationSpec *ss = GetStationSpec(area.tile);
+ if (ss != NULL && HasBit(ss->anim_triggers, trigger)) {
+ CargoID cargo;
+ if (cargo_type == CT_INVALID) {
+ cargo = CT_INVALID;
+ } else {
+ cargo = GetReverseCargoTranslation(cargo_type, ss->grffile);
+ }
+ ChangeStationAnimationFrame(ss, st, area.tile, random_bits, trigger, cargo);
+ }
+ }
+ area.tile += TileDiffXY(1, 0);
+ }
+ area.tile += TileDiffXY(-area.w, 1);
+ }
+}
+
+/**
+ * Update the cached animation trigger bitmask for a station.
+ * @param st Station to update.
+ */
+void StationUpdateAnimTriggers(Station *st)
+{
+ st->cached_anim_triggers = 0;
+
+ /* Combine animation trigger bitmask for all station specs
+ * of this station. */
+ for (uint i = 0; i < st->num_specs; i++) {
+ const StationSpec *ss = st->speclist[i].spec;
+ if (ss != NULL) st->cached_anim_triggers |= ss->anim_triggers;
+ }
+}
--- a/src/newgrf_station.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/newgrf_station.h Sun Apr 20 15:27:28 2008 +0000
@@ -83,6 +83,11 @@
StationLayout **layouts;
bool copied_layouts;
+ uint8 anim_frames;
+ uint8 anim_status;
+ uint8 anim_speed;
+ uint16 anim_triggers;
+
/**
* NUM_CARGO real cargo plus three pseudo cargo sprite groups.
* Used for obtaining the sprite offset of custom sprites, and for
@@ -132,4 +137,18 @@
/* Draw representation of a station tile for GUI purposes. */
bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID sclass, uint station);
+enum StatAnimTrigger {
+ STAT_ANIM_BUILT,
+ STAT_ANIM_NEW_CARGO,
+ STAT_ANIM_CARGO_TAKEN,
+ STAT_ANIM_TRAIN_ARRIVES,
+ STAT_ANIM_TRAIN_DEPARTS,
+ STAT_ANIM_TRAIN_LOADS,
+ STAT_ANIM_250_TICKS,
+};
+
+void AnimateStationTile(TileIndex tile);
+void StationAnimationTrigger(const Station *st, TileIndex tile, StatAnimTrigger trigger, CargoID cargo_type = CT_INVALID);
+void StationUpdateAnimTriggers(Station *st);
+
#endif /* NEWGRF_STATION_H */
--- a/src/news_func.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/news_func.h Sun Apr 20 15:27:28 2008 +0000
@@ -14,10 +14,9 @@
void InitNewsItemStructs();
extern NewsItem _statusbar_news_item;
-extern uint32 _news_display_opt;
extern bool _news_ticker_sound;
-extern const char *_news_display_name[NT_END];
+extern NewsTypeData _news_type_data[NT_END];
/**
* Delete a news item type about a vehicle
--- a/src/news_gui.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/news_gui.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -53,7 +53,6 @@
#define INVALID_NEWS 255
NewsItem _statusbar_news_item;
-uint32 _news_display_opt;
bool _news_ticker_sound;
static NewsItem _news_items[MAX_NEWS]; ///< The news FIFO queue
static NewsID _current_news = INVALID_NEWS; ///< points to news item that should be shown next
@@ -335,25 +334,24 @@
/**
- * Maximum age of news items.
- * Don't show item if it's older than x days, corresponds with NewsType in news_type.h
- * @see NewsType
+ * Per-NewsType data
*/
-static const byte _news_items_age[NT_END] = {
- 60, ///< NT_ARRIVAL_PLAYER
- 60, ///< NT_ARRIVAL_OTHER
- 90, ///< NT_ACCIDENT
- 60, ///< NT_COMPANY_INFO
- 90, ///< NT_OPENCLOSE
- 30, ///< NT_ECONOMY
- 30, ///< NT_INDUSTRY_PLAYER
- 30, ///< NT_INDUSTRY_OTHER
- 30, ///< NT_INDUSTRY_NOBODY
- 150, ///< NT_ADVICE
- 30, ///< NT_NEW_VEHICLES
- 90, ///< NT_ACCEPTANCE
- 180, ///< NT_SUBSIDIES
- 60 ///< NT_GENERAL
+NewsTypeData _news_type_data[NT_END] = {
+ /* name, age, sound, display */
+ { "arrival_player", 60, SND_1D_APPLAUSE, ND_FULL }, ///< NT_ARRIVAL_PLAYER
+ { "arrival_other", 60, SND_1D_APPLAUSE, ND_FULL }, ///< NT_ARRIVAL_OTHER
+ { "accident", 90, SND_BEGIN, ND_FULL }, ///< NT_ACCIDENT
+ { "company_info", 60, SND_BEGIN, ND_FULL }, ///< NT_COMPANY_INFO
+ { "openclose", 90, SND_BEGIN, ND_FULL }, ///< NT_OPENCLOSE
+ { "economy", 30, SND_BEGIN, ND_FULL }, ///< NT_ECONOMY
+ { "production_player", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_PLAYER
+ { "production_other", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_OTHER
+ { "production_nobody", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_NOBODY
+ { "advice", 150, SND_BEGIN, ND_FULL }, ///< NT_ADVICE
+ { "new_vehicles", 30, SND_1E_OOOOH, ND_FULL }, ///< NT_NEW_VEHICLES
+ { "acceptance", 90, SND_BEGIN, ND_FULL }, ///< NT_ACCEPTANCE
+ { "subsidies", 180, SND_BEGIN, ND_FULL }, ///< NT_SUBSIDIES
+ { "general", 60, SND_BEGIN, ND_FULL }, ///< NT_GENERAL
};
@@ -401,63 +399,6 @@
NewsWindowProc
};
-static const SoundFx _news_sounds[NT_END] = {
- SND_1D_APPLAUSE, ///< NT_ARRIVAL_PLAYER
- SND_1D_APPLAUSE, ///< NT_ARRIVAL_OTHER
- SND_BEGIN, ///< NT_ACCIDENT
- SND_BEGIN, ///< NT_COMPANY_INFO
- SND_BEGIN, ///< NT_OPENCLOSE
- SND_BEGIN, ///< NT_ECONOMY
- SND_BEGIN, ///< NT_INDUSTRY_PLAYER
- SND_BEGIN, ///< NT_INDUSTRY_OTHER
- SND_BEGIN, ///< NT_INDUSTRY_NOBODY
- SND_BEGIN, ///< NT_ADVICE
- SND_1E_OOOOH, ///< NT_NEW_VEHICLES
- SND_BEGIN, ///< NT_ACCEPTANCE
- SND_BEGIN, ///< NT_SUBSIDIES
- SND_BEGIN, ///< NT_GENERAL
-};
-
-const char *_news_display_name[NT_END] = {
- "arrival_player",
- "arrival_other",
- "accident",
- "company_info",
- "openclose",
- "economy",
- "production_player",
- "production_other",
- "production_nobody",
- "advice",
- "new_vehicles",
- "acceptance",
- "subsidies",
- "general",
-};
-
-/**
- * Get the value of an item of the news-display settings. This is
- * a little tricky since on/off/summary must use 2 bits to store the value
- * @param item the item whose value is requested
- * @return return the found value which is between 0-2
- */
-static inline byte GetNewsDisplayValue(byte item)
-{
- assert(item < NT_END && GB(_news_display_opt, item * 2, 2) <= 2);
- return GB(_news_display_opt, item * 2, 2);
-}
-
-/**
- * Set the value of an item in the news-display settings. This is
- * a little tricky since on/off/summary must use 2 bits to store the value
- * @param item the item whose value is being set
- * @param val new value
- */
-static inline void SetNewsDisplayValue(byte item, byte val)
-{
- assert(item < NT_END && val <= 2);
- SB(_news_display_opt, item * 2, 2, val);
-}
/** Open up an own newspaper window for the news item */
static void ShowNewspaper(NewsItem *ni)
@@ -465,7 +406,7 @@
ni->flags &= ~NF_FORCE_BIG;
ni->duration = 555;
- SoundFx sound = _news_sounds[ni->type];
+ SoundFx sound = _news_type_data[ni->type].sound;
if (sound != 0) SndPlayFx(sound);
int top = _screen.height;
@@ -476,7 +417,7 @@
_news_type13_desc.top = top;
w = AllocateWindowDesc(&_news_type13_desc);
if (ni->flags & NF_VIEWPORT) {
- AssignWindowViewport(w, 2, 58, 0x1AA, 0x6E,
+ InitializeWindowViewport(w, 2, 58, 426, 110,
ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS);
}
break;
@@ -485,7 +426,7 @@
_news_type2_desc.top = top;
w = AllocateWindowDesc(&_news_type2_desc);
if (ni->flags & NF_VIEWPORT) {
- AssignWindowViewport(w, 2, 58, 0x1AA, 0x46,
+ InitializeWindowViewport(w, 2, 58, 426, 70,
ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS);
}
break;
@@ -494,7 +435,7 @@
_news_type0_desc.top = top;
w = AllocateWindowDesc(&_news_type0_desc);
if (ni->flags & NF_VIEWPORT) {
- AssignWindowViewport(w, 3, 17, 0x112, 0x2F,
+ InitializeWindowViewport(w, 3, 17, 274, 47,
ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS);
}
break;
@@ -553,11 +494,11 @@
NewsItem *ni = &_news_items[_current_news];
/* check the date, don't show too old items */
- if (_date - _news_items_age[ni->type] > ni->date) return;
+ if (_date - _news_type_data[ni->type].age > ni->date) return;
- switch (GetNewsDisplayValue(ni->type)) {
+ switch (_news_type_data[ni->type].display) {
default: NOT_REACHED();
- case 0: { // Off - show nothing only a small reminder in the status bar
+ case ND_OFF: { // Off - show nothing only a small reminder in the status bar
Window *w = FindWindowById(WC_STATUS_BAR, 0);
if (w != NULL) {
@@ -567,14 +508,14 @@
break;
}
- case 1: // Summary - show ticker, but if forced big, cascade to full
+ case ND_SUMMARY: // Summary - show ticker, but if forced big, cascade to full
if (!(ni->flags & NF_FORCE_BIG)) {
ShowTicker(ni);
break;
}
/* Fallthrough */
- case 2: // Full - show newspaper
+ case ND_FULL: // Full - show newspaper
ShowNewspaper(ni);
break;
}
@@ -803,33 +744,30 @@
/* WP(w, def_d).data_1 stores state of the ALL on/off/summary button */
switch (e->event) {
case WE_CREATE: {
- uint32 val = _news_display_opt;
- uint32 all_val;
+ NewsDisplay all_val;
/* Set up the initial disabled buttons in the case of 'off' or 'full' */
- all_val = val & 0x3;
- for (int i = 0; i < NT_END; i++, val >>= 2) {
- SetMessageButtonStates(w, val & 0x3, i);
+ all_val = _news_type_data[0].display;
+ for (int i = 0; i < NT_END; i++) {
+ SetMessageButtonStates(w, _news_type_data[i].display, i);
/* If the value doesn't match the ALL-button value, set the ALL-button value to 'off' */
- if ((val & 0x3) != all_val) all_val = 0;
+ if (_news_type_data[i].display != all_val) all_val = ND_OFF;
}
/* If all values are the same value, the ALL-button will take over this value */
WP(w, def_d).data_1 = all_val;
} break;
case WE_PAINT: {
- uint32 val = _news_display_opt;
-
if (_news_ticker_sound) w->LowerWidget(WIDGET_NEWSOPT_SOUNDTICKER);
w->widget[WIDGET_NEWSOPT_DROP_SUMMARY].data = message_opt[WP(w, def_d).data_1];
DrawWindowWidgets(w);
/* Draw the string of each setting on each button. */
- for (int i = 0, y = 26; i < NT_END; i++, y += 12, val >>= 2) {
+ for (int i = 0, y = 26; i < NT_END; i++, y += 12) {
/* 51 comes from 13 + 89 (left and right of the button)+1, shiefted by one as to get division,
* which will give centered position */
- DrawStringCentered(51, y + 1, message_opt[val & 0x3], TC_BLACK);
+ DrawStringCentered(51, y + 1, message_opt[_news_type_data[i].display], TC_BLACK);
}
} break;
@@ -849,10 +787,10 @@
int wid = e->we.click.widget - WIDGET_NEWSOPT_START_OPTION;
if (wid >= 0 && wid < (NB_WIDG_PER_SETTING * NT_END)) {
int element = wid / NB_WIDG_PER_SETTING;
- byte val = (GetNewsDisplayValue(element) + ((wid % NB_WIDG_PER_SETTING) ? 1 : -1)) % 3;
+ byte val = (_news_type_data[element].display + ((wid % NB_WIDG_PER_SETTING) ? 1 : -1)) % 3;
SetMessageButtonStates(w, val, element);
- SetNewsDisplayValue(element, val);
+ _news_type_data[element].display = (NewsDisplay)val;
SetWindowDirty(w);
}
} break;
@@ -864,7 +802,7 @@
for (int i = 0; i < NT_END; i++) {
SetMessageButtonStates(w, e->we.dropdown.index, i);
- SetNewsDisplayValue(i, e->we.dropdown.index);
+ _news_type_data[i].display = (NewsDisplay)e->we.dropdown.index;
}
SetWindowDirty(w);
break;
--- a/src/news_type.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/news_type.h Sun Apr 20 15:27:28 2008 +0000
@@ -8,6 +8,7 @@
#include "window_type.h"
#include "date_type.h"
#include "strings_type.h"
+#include "sound_type.h"
/**
* Type of news.
@@ -75,6 +76,25 @@
NB_BNEWCOMPANY = (4 << 4), ///< A new company has been started
};
+/**
+ * News display options
+ */
+enum NewsDisplay {
+ ND_OFF, ///< Only show a reminder in the status bar
+ ND_SUMMARY, ///< Show ticker
+ ND_FULL, ///< Show newspaper
+};
+
+/**
+ * Per-NewsType data
+ */
+struct NewsTypeData {
+ const char *const name; ///< Name
+ const byte age; ///< Maximum age of news items (in days)
+ const SoundFx sound; ///< Sound
+ NewsDisplay display; ///< Display mode (off, summary, full)
+};
+
struct NewsItem {
StringID string_id; ///< Message text (sometimes also used for storing other info)
uint16 duration; ///< Remaining time for showing this news message
--- a/src/oldloader.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/oldloader.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -24,6 +24,8 @@
#include "date_func.h"
#include "vehicle_func.h"
#include "variables.h"
+#include "strings_func.h"
+#include "effectvehicle_base.h"
#include "table/strings.h"
@@ -84,6 +86,12 @@
OC_TILE = OC_VAR_U32 | OC_FILE_U16,
+ /**
+ * Dereference the pointer once before writing to it,
+ * so we do not have to use big static arrays.
+ */
+ OC_DEREFERENCE_POINTER = 1 << 31,
+
OC_END = 0 ///< End of the whole chunk, all 32bits set to zero
};
@@ -201,10 +209,10 @@
byte *base_ptr = (byte*)base;
while (chunk->type != OC_END) {
- byte* ptr = (byte*)chunk->ptr;
- uint i;
+ byte *ptr = (byte*)chunk->ptr;
+ if ((chunk->type & OC_DEREFERENCE_POINTER) != 0) ptr = *(byte**)ptr;
- for (i = 0; i < chunk->amount; i++) {
+ for (uint i = 0; i < chunk->amount; i++) {
if (ls->failed) return false;
/* Handle simple types */
@@ -391,10 +399,10 @@
extern TileIndex *_animated_tile_list;
extern uint _animated_tile_count;
-extern char _name_array[512][32];
+extern char *_old_name_array;
static byte _old_vehicle_multiplier;
-static uint8 _old_map3[OLD_MAP_SIZE * 2];
+static uint8 *_old_map3;
static bool _new_ttdpatch_format;
static uint32 _old_town_index;
static uint16 _old_string_id;
@@ -1079,9 +1087,9 @@
OCL_END()
};
-static const OldChunks vehicle_special_chunk[] = {
- OCL_SVAR( OC_UINT16, VehicleSpecial, animation_state ),
- OCL_SVAR( OC_UINT8, VehicleSpecial, animation_substate ),
+static const OldChunks vehicle_effect_chunk[] = {
+ OCL_SVAR( OC_UINT16, VehicleEffect, animation_state ),
+ OCL_SVAR( OC_UINT8, VehicleEffect, animation_substate ),
OCL_NULL( 7 ), // Junk
@@ -1116,7 +1124,7 @@
case VEH_ROAD : res = LoadChunk(ls, &v->u.road, vehicle_road_chunk); break;
case VEH_SHIP : res = LoadChunk(ls, &v->u.ship, vehicle_ship_chunk); break;
case VEH_AIRCRAFT: res = LoadChunk(ls, &v->u.air, vehicle_air_chunk); break;
- case VEH_SPECIAL : res = LoadChunk(ls, &v->u.special, vehicle_special_chunk); break;
+ case VEH_EFFECT : res = LoadChunk(ls, &v->u.effect, vehicle_effect_chunk); break;
case VEH_DISASTER: res = LoadChunk(ls, &v->u.disaster, vehicle_disaster_chunk); break;
}
@@ -1229,7 +1237,7 @@
case 0x11 /*VEH_ROAD */: v = new (_current_vehicle_id) RoadVehicle(); break;
case 0x12 /*VEH_SHIP */: v = new (_current_vehicle_id) Ship(); break;
case 0x13 /*VEH_AIRCRAFT*/: v = new (_current_vehicle_id) Aircraft(); break;
- case 0x14 /*VEH_SPECIAL */: v = new (_current_vehicle_id) SpecialVehicle(); break;
+ case 0x14 /*VEH_EFFECT */: v = new (_current_vehicle_id) EffectVehicle(); break;
case 0x15 /*VEH_DISASTER*/: v = new (_current_vehicle_id) DisasterVehicle(); break;
}
if (!LoadChunk(ls, v, vehicle_chunk)) return false;
@@ -1263,7 +1271,7 @@
v->name = CopyFromOldName(_old_string_id);
/* Vehicle-subtype is different in TTD(Patch) */
- if (v->type == VEH_SPECIAL) v->subtype = v->subtype >> 1;
+ if (v->type == VEH_EFFECT) v->subtype = v->subtype >> 1;
if (_cargo_count != 0) {
CargoPacket *cp = new CargoPacket((_cargo_source == 0xFF) ? INVALID_STATION : _cargo_source, _cargo_count);
@@ -1521,7 +1529,7 @@
OCL_ASSERT( 0x6F0F2 ),
- OCL_VAR ( OC_UINT8, 32 * 500, &_name_array[0] ),
+ OCL_VAR ( OC_UINT8 | OC_DEREFERENCE_POINTER, 32 * 500, &_old_name_array ),
OCL_NULL( 0x2000 ), ///< Old hash-table, no longer in use
@@ -1601,8 +1609,10 @@
DEBUG(oldloader, 3, "Reading main chunk...");
/* Load the biggest chunk */
+ _old_map3 = MallocT<byte>(OLD_MAP_SIZE * 2);
if (!LoadChunk(ls, NULL, main_chunk)) {
DEBUG(oldloader, 0, "Loading failed");
+ free(_old_map3);
return false;
}
DEBUG(oldloader, 3, "Done, converting game data...");
@@ -1669,6 +1679,8 @@
DEBUG(oldloader, 3, "Finished converting game data");
DEBUG(oldloader, 1, "TTD(Patch) savegame successfully converted");
+ free(_old_map3);
+
return true;
}
--- a/src/openttd.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/openttd.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -59,6 +59,8 @@
#include "date_func.h"
#include "vehicle_func.h"
#include "cheat_func.h"
+#include "animated_tile_func.h"
+#include "functions.h"
#include "newgrf.h"
#include "newgrf_config.h"
@@ -92,6 +94,8 @@
void DoPaletteAnimations();
void MusicLoop();
void ResetMusic();
+void ResetOldNames();
+void ProcessAsyncSaveFinish();
extern void SetDifficultyLevel(int mode, GameOptions *gm_opt);
extern Player* DoStartupNewPlayer(bool is_ai);
@@ -259,8 +263,8 @@
return;
}
- res[0] = Clamp(strtoul(s, NULL, 0), 64, MAX_SCREEN_WIDTH);
- res[1] = Clamp(strtoul(t + 1, NULL, 0), 64, MAX_SCREEN_HEIGHT);
+ res[0] = max(strtoul(s, NULL, 0), 64UL);
+ res[1] = max(strtoul(t + 1, NULL, 0), 64UL);
}
static void InitializeDynamicVariables()
@@ -639,39 +643,6 @@
}
}
-
-/** Mutex so that only one thread can communicate with the main program
- * at any given time */
-static ThreadMsg _message = MSG_OTTD_NO_MESSAGE;
-
-static inline void OTTD_ReleaseMutex() {_message = MSG_OTTD_NO_MESSAGE;}
-static inline ThreadMsg OTTD_PollThreadEvent() {return _message;}
-
-/** Called by running thread to execute some action in the main game.
- * It will stall as long as the mutex is not freed (handled) by the game */
-void OTTD_SendThreadMessage(ThreadMsg msg)
-{
- if (_exit_game) return;
- while (_message != MSG_OTTD_NO_MESSAGE) CSleep(10);
-
- _message = msg;
-}
-
-
-/** Handle the user-messages sent to us
- * @param message message sent
- */
-static void ProcessSentMessage(ThreadMsg message)
-{
- switch (message) {
- case MSG_OTTD_SAVETHREAD_DONE: SaveFileDone(); break;
- case MSG_OTTD_SAVETHREAD_ERROR: SaveFileError(); break;
- default: NOT_REACHED();
- }
-
- OTTD_ReleaseMutex(); // release mutex so that other threads, messages can be handled
-}
-
static void ShowScreenshotResult(bool b)
{
if (b) {
@@ -1089,9 +1060,7 @@
void GameLoop()
{
- ThreadMsg message;
-
- if ((message = OTTD_PollThreadEvent()) != 0) ProcessSentMessage(message);
+ ProcessAsyncSaveFinish();
/* autosave game? */
if (_do_autosave) {
@@ -1413,6 +1382,9 @@
}
}
+ /* From this point the old names array is cleared. */
+ ResetOldNames();
+
/* convert road side to my format. */
if (_opt.road_side) _opt.road_side = 1;
--- a/src/openttd.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/openttd.h Sun Apr 20 15:27:28 2008 +0000
@@ -1,4 +1,5 @@
/* $Id$ */
+
/** @file openttd.h */
#ifndef OPENTTD_H
@@ -97,11 +98,6 @@
extern byte _savegame_sort_order;
-enum {
- MAX_SCREEN_WIDTH = 2048,
- MAX_SCREEN_HEIGHT = 1200,
-};
-
/* In certain windows you navigate with the arrow keys. Do not scroll the
* gameview when here. Bitencoded variable that only allows scrolling if all
* elements are zero */
@@ -113,17 +109,6 @@
};
extern byte _no_scroll;
-/** To have a concurrently running thread interface with the main program, use
- * the OTTD_SendThreadMessage() function. Actions to perform upon the message are handled
- * in the ProcessSentMessage() function */
-enum ThreadMsg {
- MSG_OTTD_NO_MESSAGE,
- MSG_OTTD_SAVETHREAD_DONE,
- MSG_OTTD_SAVETHREAD_ERROR,
-};
-
-void OTTD_SendThreadMessage(ThreadMsg msg);
-
extern byte _game_mode;
extern bool _exit_game;
extern int8 _pause_game;
--- a/src/rail_cmd.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/rail_cmd.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -43,6 +43,7 @@
#include "tunnelbridge.h"
#include "station_map.h"
#include "water_map.h"
+#include "functions.h"
#include "table/sprites.h"
#include "table/strings.h"
--- a/src/road_cmd.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/road_cmd.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -36,6 +36,8 @@
#include "road_func.h"
#include "tunnelbridge.h"
#include "cheat_func.h"
+#include "functions.h"
+#include "effectvehicle_func.h"
#include "table/sprites.h"
#include "table/strings.h"
--- a/src/roadveh_cmd.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/roadveh_cmd.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -42,6 +42,7 @@
#include "order_func.h"
#include "depot_base.h"
#include "depot_func.h"
+#include "effectvehicle_func.h"
#include "table/strings.h"
@@ -704,7 +705,7 @@
if (!(v->vehstatus & VS_HIDDEN)) {
Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE);
- if (u != NULL) u->u.special.animation_state = v->breakdown_delay * 2;
+ if (u != NULL) u->u.effect.animation_state = v->breakdown_delay * 2;
}
}
@@ -1844,7 +1845,7 @@
HandleBrokenRoadVeh(v);
return;
}
- v->breakdown_ctr--;
+ if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--;
}
if (v->vehstatus & VS_STOPPED) return;
--- a/src/saveload.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/saveload.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -87,6 +87,32 @@
throw std::exception();
}
+typedef void (*AsyncSaveFinishProc)();
+static AsyncSaveFinishProc _async_save_finish = NULL;
+
+/**
+ * Called by save thread to tell we finished saving.
+ */
+static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
+{
+ if (_exit_game) return;
+ while (_async_save_finish != NULL) CSleep(10);
+
+ _async_save_finish = proc;
+}
+
+/**
+ * Handle async save finishes.
+ */
+void ProcessAsyncSaveFinish()
+{
+ if (_async_save_finish == NULL) return;
+
+ _async_save_finish();
+
+ _async_save_finish = NULL;
+}
+
/**
* Fill the input buffer by reading from the file with the given reader
*/
@@ -1248,6 +1274,7 @@
/* these define the chunks */
extern const ChunkHandler _misc_chunk_handlers[];
+extern const ChunkHandler _name_chunk_handlers[];
extern const ChunkHandler _cheat_chunk_handlers[] ;
extern const ChunkHandler _setting_chunk_handlers[];
extern const ChunkHandler _player_chunk_handlers[];
@@ -1268,6 +1295,7 @@
static const ChunkHandler * const _chunk_handlers[] = {
_misc_chunk_handlers,
+ _name_chunk_handlers,
_cheat_chunk_handlers,
_setting_chunk_handlers,
_veh_chunk_handlers,
@@ -1455,7 +1483,7 @@
/** Update the gui accordingly when starting saving
* and set locks on saveload. Also turn off fast-forward cause with that
* saving takes Aaaaages */
-void SaveFileStart()
+static void SaveFileStart()
{
_ts.ff_state = _fast_forward;
_fast_forward = 0;
@@ -1467,7 +1495,7 @@
/** Update the gui accordingly when saving is done and release locks
* on saveload */
-void SaveFileDone()
+static void SaveFileDone()
{
_fast_forward = _ts.ff_state;
if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE);
@@ -1494,7 +1522,7 @@
}
/** Show a gui message when saving has failed */
-void SaveFileError()
+static void SaveFileError()
{
SetDParamStr(0, GetSaveLoadErrorString());
ShowErrorMessage(STR_012D, STR_NULL, 0, 0);
@@ -1543,7 +1571,7 @@
GetSavegameFormat("memory")->uninit_write(); // clean the memorypool
fclose(_sl.fh);
- if (threaded) OTTD_SendThreadMessage(MSG_OTTD_SAVETHREAD_DONE);
+ if (threaded) SetAsyncSaveFinish(SaveFileDone);
return SL_OK;
}
@@ -1555,7 +1583,7 @@
fprintf(stderr, GetSaveLoadErrorString());
if (threaded) {
- OTTD_SendThreadMessage(MSG_OTTD_SAVETHREAD_ERROR);
+ SetAsyncSaveFinish(SaveFileError);
} else {
SaveFileError();
}
--- a/src/saveload.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/saveload.h Sun Apr 20 15:27:28 2008 +0000
@@ -321,7 +321,4 @@
void SlObject(void *object, const SaveLoad *sld);
bool SlObjectMember(void *object, const SaveLoad *sld);
-void SaveFileStart();
-void SaveFileDone();
-void SaveFileError();
#endif /* SAVELOAD_H */
--- a/src/settings.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/settings.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -1654,20 +1654,18 @@
#undef NO
#undef CR
-static uint NewsDisplayLoadConfig(IniFile *ini, const char *grpname)
+static void NewsDisplayLoadConfig(IniFile *ini, const char *grpname)
{
IniGroup *group = ini_getgroup(ini, grpname, -1);
IniItem *item;
- /* By default, set everything to full (0xAAAAAAAA = 1010101010101010) */
- uint res = 0xAAAAAAAA;
- /* If no group exists, return everything full */
- if (group == NULL) return res;
+ /* If no group exists, return */
+ if (group == NULL) return;
for (item = group->item; item != NULL; item = item->next) {
int news_item = -1;
for (int i = 0; i < NT_END; i++) {
- if (strcasecmp(item->name, _news_display_name[i]) == 0) {
+ if (strcasecmp(item->name, _news_type_data[i].name) == 0) {
news_item = i;
break;
}
@@ -1678,18 +1676,16 @@
}
if (strcasecmp(item->value, "full") == 0) {
- SB(res, news_item * 2, 2, 2);
+ _news_type_data[news_item].display = ND_FULL;
} else if (strcasecmp(item->value, "off") == 0) {
- SB(res, news_item * 2, 2, 0);
+ _news_type_data[news_item].display = ND_OFF;
} else if (strcasecmp(item->value, "summarized") == 0) {
- SB(res, news_item * 2, 2, 1);
+ _news_type_data[news_item].display = ND_SUMMARY;
} else {
DEBUG(misc, 0, "Invalid display value: %s", item->value);
continue;
}
}
-
- return res;
}
/* Load a GRF configuration from the given group name */
@@ -1745,7 +1741,7 @@
return first;
}
-static void NewsDisplaySaveConfig(IniFile *ini, const char *grpname, uint news_display)
+static void NewsDisplaySaveConfig(IniFile *ini, const char *grpname)
{
IniGroup *group = ini_getgroup(ini, grpname, -1);
IniItem **item;
@@ -1756,11 +1752,11 @@
for (int i = 0; i < NT_END; i++) {
const char *value;
- int v = GB(news_display, i * 2, 2);
+ int v = _news_type_data[i].display;
- value = (v == 0 ? "off" : (v == 1 ? "summarized" : "full"));
+ value = (v == ND_OFF ? "off" : (v == ND_SUMMARY ? "summarized" : "full"));
- *item = ini_item_alloc(group, _news_display_name[i], strlen(_news_display_name[i]));
+ *item = ini_item_alloc(group, _news_type_data[i].name, strlen(_news_type_data[i].name));
(*item)->value = (char*)pool_strdup(&ini->pool, value, strlen(value));
item = &(*item)->next;
}
@@ -1847,7 +1843,7 @@
HandleSettingDescs(ini, ini_load_settings, ini_load_setting_list);
_grfconfig_newgame = GRFLoadConfig(ini, "newgrf", false);
_grfconfig_static = GRFLoadConfig(ini, "newgrf-static", true);
- _news_display_opt = NewsDisplayLoadConfig(ini, "news_display");
+ NewsDisplayLoadConfig(ini, "news_display");
CheckDifficultyLevels();
ini_free(ini);
}
@@ -1859,7 +1855,7 @@
HandleSettingDescs(ini, ini_save_settings, ini_save_setting_list);
GRFSaveConfig(ini, "newgrf", _grfconfig_newgame);
GRFSaveConfig(ini, "newgrf-static", _grfconfig_static);
- NewsDisplaySaveConfig(ini, "news_display", _news_display_opt);
+ NewsDisplaySaveConfig(ini, "news_display");
SaveVersionInConfig(ini);
ini_save(_config_file, ini);
ini_free(ini);
--- a/src/ship_cmd.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/ship_cmd.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -40,6 +40,7 @@
#include "gfx_func.h"
#include "settings_type.h"
#include "order_func.h"
+#include "effectvehicle_func.h"
#include "table/strings.h"
@@ -210,7 +211,7 @@
if (!(v->vehstatus & VS_HIDDEN)) {
Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE);
- if (u != NULL) u->u.special.animation_state = v->breakdown_delay * 2;
+ if (u != NULL) u->u.effect.animation_state = v->breakdown_delay * 2;
}
}
@@ -594,7 +595,7 @@
HandleBrokenShip(v);
return;
}
- v->breakdown_ctr--;
+ if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--;
}
if (v->vehstatus & VS_STOPPED) return;
--- a/src/smallmap_gui.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/smallmap_gui.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -682,7 +682,7 @@
byte color;
FOR_ALL_VEHICLES(v) {
- if (v->type != VEH_SPECIAL &&
+ if (v->type != VEH_EFFECT &&
(v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0) {
/* Remap into flat coordinates. */
Point pt = RemapCoords(
@@ -1108,15 +1108,15 @@
static void ExtraViewPortWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
- case WE_CREATE: /* Disable zoom in button */
+ case WE_CREATE: // Disable zoom in button
/* New viewport start at (zero,zero) */
- AssignWindowViewport(w, 3, 17, w->widget[4].right - w->widget[4].left - 1, w->widget[4].bottom - w->widget[4].top - 1, 0, ZOOM_LVL_VIEWPORT);
+ InitializeWindowViewport(w, 3, 17, w->widget[4].right - w->widget[4].left - 1, w->widget[4].bottom - w->widget[4].top - 1, 0, ZOOM_LVL_VIEWPORT);
w->DisableWidget(5);
break;
case WE_PAINT:
- // set the number in the title bar
+ /* set the number in the title bar */
SetDParam(0, w->window_number + 1);
DrawWindowWidgets(w);
@@ -1128,7 +1128,7 @@
case 5: DoZoomInOutWindow(ZOOM_IN, w); break;
case 6: DoZoomInOutWindow(ZOOM_OUT, w); break;
- case 7: { /* location button (move main view to same spot as this view) 'Paste Location' */
+ case 7: { // location button (move main view to same spot as this view) 'Paste Location'
Window *w2 = FindWindowById(WC_MAIN_WINDOW, 0);
int x = WP(w, vp_d).scrollpos_x; // Where is the main looking at
int y = WP(w, vp_d).scrollpos_y;
@@ -1138,7 +1138,7 @@
WP(w2, vp_d).dest_scrollpos_y = y - (w2->viewport->virtual_height - w->viewport->virtual_height) / 2;
} break;
- case 8: { /* inverse location button (move this view to same spot as main view) 'Copy Location' */
+ case 8: { // inverse location button (move this view to same spot as main view) 'Copy Location'
const Window *w2 = FindWindowById(WC_MAIN_WINDOW, 0);
int x = WP(w2, const vp_d).scrollpos_x;
int y = WP(w2, const vp_d).scrollpos_y;
--- a/src/sound.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/sound.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -207,6 +207,14 @@
}
}
+/**
+ * Decide 'where' (between left and right speaker) to play the sound effect.
+ * @param sound Sound effect to play
+ * @param left Left edge of virtual coordinates where the sound is produced
+ * @param right Right edge of virtual coordinates where the sound is produced
+ * @param top Top edge of virtual coordinates where the sound is produced
+ * @param bottom Bottom edge of virtual coordinates where the sound is produced
+ */
static void SndPlayScreenCoordFx(SoundFx sound, int left, int right, int top, int bottom)
{
Window* const *wz;
@@ -231,7 +239,6 @@
return;
}
}
-
}
void SndPlayTileFx(SoundFx sound, TileIndex tile)
--- a/src/station_base.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/station_base.h Sun Apr 20 15:27:28 2008 +0000
@@ -171,6 +171,7 @@
uint16 random_bits;
byte waiting_triggers;
+ uint8 cached_anim_triggers; ///< Combined animation trigger bitmask, used to determine if trigger processing should happen.
StationRect rect; ///< Station spread out rectangle (not saved) maintained by StationRect_xxx() functions
--- a/src/station_cmd.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/station_cmd.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -43,6 +43,7 @@
#include "string_func.h"
#include "signal_func.h"
#include "oldpool_func.h"
+#include "animated_tile_func.h"
#include "table/sprites.h"
#include "table/strings.h"
@@ -1127,6 +1128,12 @@
st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TRY);
+ if (statspec != NULL) {
+ /* Include this station spec's animation trigger bitmask
+ * in the station's cached copy. */
+ st->cached_anim_triggers |= statspec->anim_triggers;
+ }
+
tile_delta = (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
track = AxisToTrack(axis);
@@ -1143,6 +1150,7 @@
MakeRailStation(tile, st->owner, st->index, axis, layout & ~1, (RailType)GB(p2, 0, 4));
SetCustomStationSpecIndex(tile, specindex);
SetStationTileRandomBits(tile, GB(Random(), 0, 4));
+ SetStationAnimationFrame(tile, 0);
if (statspec != NULL) {
/* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */
@@ -1151,6 +1159,9 @@
/* As the station is not yet completely finished, the station does not yet exist. */
uint16 callback = GetStationCallback(CBID_STATION_TILE_LAYOUT, platinfo, 0, statspec, NULL, tile);
if (callback != CALLBACK_FAILED && callback < 8) SetStationGfx(tile, (callback & ~1) + axis);
+
+ /* Trigger station animation -- after building? */
+ StationAnimationTrigger(st, tile, STAT_ANIM_BUILT);
}
tile += tile_delta;
@@ -1372,6 +1383,7 @@
free(st->speclist);
st->num_specs = 0;
st->speclist = NULL;
+ st->cached_anim_triggers = 0;
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
UpdateStationVirtCoordDirty(st);
@@ -2482,6 +2494,11 @@
{ GFX_WINDSACK_INTERCON_FIRST, GFX_WINDSACK_INTERCON_LAST, 1 }
};
+ if (IsRailwayStation(tile)) {
+ AnimateStationTile(tile);
+ return;
+ }
+
StationGfx gfx = GetStationGfx(tile);
for (const AnimData *i = data; i != endof(data); i++) {
@@ -2729,7 +2746,16 @@
if (IsValidStationID(i)) StationHandleBigTick(GetStation(i));
Station *st;
- FOR_ALL_STATIONS(st) StationHandleSmallTick(st);
+ FOR_ALL_STATIONS(st) {
+ StationHandleSmallTick(st);
+
+ /* Run 250 tick interval trigger for station animation.
+ * Station index is included so that triggers are not all done
+ * at the same time. */
+ if ((_tick_counter + st->index) % 250 == 0) {
+ StationAnimationTrigger(st, st->xy, STAT_ANIM_250_TICKS);
+ }
+ }
}
void StationMonthlyLoop()
@@ -2761,6 +2787,8 @@
st->goods[type].cargo.Append(new CargoPacket(st->index, amount));
SetBit(st->goods[type].acceptance_pickup, GoodsEntry::PICKUP);
+ StationAnimationTrigger(st, st->xy, STAT_ANIM_NEW_CARGO, type);
+
InvalidateWindow(WC_STATION_VIEW, st->index);
st->MarkTilesDirty(true);
}
@@ -3135,6 +3163,8 @@
}
for (CargoID c = 0; c < NUM_CARGO; c++) st->goods[c].cargo.InvalidateCache();
+
+ StationUpdateAnimTriggers(st);
}
}
--- a/src/station_gui.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/station_gui.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -184,35 +184,36 @@
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(plstations_d));
/**
- * Set the 'SL_REBUILD' flag for all station lists
+ * Set the station sort flag for all station-list windows.
+ * @param sl_flag Sort list flag to set for all station-list windows
*/
-void RebuildStationLists()
+static void SetStationListsFlag(StationListFlags sl_flag)
{
Window *const *wz;
FOR_ALL_WINDOWS(wz) {
Window *w = *wz;
if (w->window_class == WC_STATION_LIST) {
- WP(w, plstations_d).flags |= SL_REBUILD;
+ WP(w, plstations_d).flags |= sl_flag;
SetWindowDirty(w);
}
}
}
/**
+ * Set the 'SL_REBUILD' flag for all station lists
+ */
+void RebuildStationLists()
+{
+ SetStationListsFlag(SL_REBUILD);
+}
+
+/**
* Set the 'SL_RESORT' flag for all station lists
*/
void ResortStationLists()
{
- Window *const *wz;
-
- FOR_ALL_WINDOWS(wz) {
- Window *w = *wz;
- if (w->window_class == WC_STATION_LIST) {
- WP(w, plstations_d).flags |= SL_RESORT;
- SetWindowDirty(w);
- }
- }
+ SetStationListsFlag(SL_RESORT);
}
/**
--- a/src/stdafx.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/stdafx.h Sun Apr 20 15:27:28 2008 +0000
@@ -309,13 +309,7 @@
#define CloseConnection OTTD_CloseConnection
#endif /* __APPLE__ */
-#if !defined(STRGEN)
- /* In strgen error is not fatal and returns */
- void NORETURN CDECL error(const char *str, ...);
-#else
- void CDECL error(const char *str, ...);
-#endif
-
+void NORETURN CDECL error(const char *str, ...);
#define NOT_REACHED() error("NOT_REACHED triggered at line %i of %s", __LINE__, __FILE__)
#if defined(MORPHOS) || defined(__NDS__)
--- a/src/strgen/strgen.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/strgen/strgen.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -155,7 +155,7 @@
# define LINE_NUM_FMT ":%d"
#endif
-static void CDECL warning(const char *s, ...)
+static void CDECL strgen_warning(const char *s, ...)
{
char buf[1024];
va_list va;
@@ -166,7 +166,7 @@
_warnings++;
}
-void CDECL error(const char *s, ...)
+static void CDECL strgen_error(const char *s, ...)
{
char buf[1024];
va_list va;
@@ -177,8 +177,7 @@
_errors++;
}
-
-static void NORETURN CDECL fatal(const char *s, ...)
+void NORETURN CDECL error(const char *s, ...)
{
char buf[1024];
va_list va;
@@ -191,7 +190,7 @@
static void PutByte(byte c)
{
- if (_put_pos == lengthof(_put_buf)) fatal("Put buffer too small");
+ if (_put_pos == lengthof(_put_buf)) error("Put buffer too small");
_put_buf[_put_pos++] = c;
}
@@ -213,7 +212,7 @@
PutByte(0x80 + GB(value, 6, 6));
PutByte(0x80 + GB(value, 0, 6));
} else {
- warning("Invalid unicode value U+0x%X", value);
+ strgen_warning("Invalid unicode value U+0x%X", value);
}
}
@@ -245,7 +244,7 @@
static void EmitSingleChar(char *buf, int value)
{
- if (*buf != '\0') warning("Ignoring trailing letters in command");
+ if (*buf != '\0') strgen_warning("Ignoring trailing letters in command");
PutUtf8(value);
}
@@ -254,7 +253,7 @@
{
char *err;
int x = strtol(buf, &err, 0);
- if (*err != 0) fatal("SetX param invalid");
+ if (*err != 0) error("SetX param invalid");
PutUtf8(SCC_SETX);
PutByte((byte)x);
}
@@ -267,9 +266,9 @@
int y;
x = strtol(buf, &err, 0);
- if (*err != ' ') fatal("SetXY param invalid");
+ if (*err != ' ') error("SetXY param invalid");
y = strtol(err + 1, &err, 0);
- if (*err != 0) fatal("SetXY param invalid");
+ if (*err != 0) error("SetXY param invalid");
PutUtf8(SCC_SETXY);
PutByte((byte)x);
@@ -371,14 +370,14 @@
}
if (nw == 0)
- fatal("%s: No plural words", _cur_ident);
+ error("%s: No plural words", _cur_ident);
if (_plural_form_counts[_lang_pluralform] != nw) {
if (_translated) {
- fatal("%s: Invalid number of plural forms. Expecting %d, found %d.", _cur_ident,
+ error("%s: Invalid number of plural forms. Expecting %d, found %d.", _cur_ident,
_plural_form_counts[_lang_pluralform], nw);
} else {
- if ((_show_todo & 2) != 0) warning("'%s' is untranslated. Tweaking english string to allow compilation for plural forms", _cur_ident);
+ if ((_show_todo & 2) != 0) strgen_warning("'%s' is untranslated. Tweaking english string to allow compilation for plural forms", _cur_ident);
if (nw > _plural_form_counts[_lang_pluralform]) {
nw = _plural_form_counts[_lang_pluralform];
} else {
@@ -405,7 +404,7 @@
// This is a {G=DER} command
for (nw = 0; ; nw++) {
- if (nw >= 8) fatal("G argument '%s' invalid", buf);
+ if (nw >= 8) error("G argument '%s' invalid", buf);
if (strcmp(buf, _genders[nw]) == 0) break;
}
// now nw contains the gender index
@@ -422,7 +421,7 @@
words[nw] = ParseWord(&buf);
if (words[nw] == NULL) break;
}
- if (nw != _numgenders) fatal("Bad # of arguments for gender command");
+ if (nw != _numgenders) error("Bad # of arguments for gender command");
PutUtf8(SCC_GENDER_LIST);
PutByte(TranslateArgumentIdx(argidx));
EmitWordList(words, nw);
@@ -553,7 +552,7 @@
for (i = 0; i < MAX_NUM_CASES; i++) {
if (memcmp(_cases[i], str, len) == 0 && _cases[i][len] == 0) return i + 1;
}
- fatal("Invalid case-name '%s'", str);
+ error("Invalid case-name '%s'", str);
}
@@ -578,7 +577,7 @@
char *end;
*argno = strtoul(s, &end, 0);
- if (*end != ':') fatal("missing arg #");
+ if (*end != ':') error("missing arg #");
s = end + 1;
}
@@ -590,7 +589,7 @@
cmd = FindCmd(start, s - start - 1);
if (cmd == NULL) {
- error("Undefined command '%.*s'", s - start - 1, start);
+ strgen_error("Undefined command '%.*s'", s - start - 1, start);
return NULL;
}
@@ -598,14 +597,14 @@
const char *casep = s;
if (!(cmd->flags & C_CASE))
- fatal("Command '%s' can't have a case", cmd->cmd);
+ error("Command '%s' can't have a case", cmd->cmd);
do c = *s++; while (c != '}' && c != ' ' && c != '\0');
*casei = ResolveCaseName(casep, s - casep - 1);
}
if (c == '\0') {
- error("Missing } from command '%s'", start);
+ strgen_error("Missing } from command '%s'", start);
return NULL;
}
@@ -618,10 +617,10 @@
c = *s++;
if (c == '}') break;
if (c == '\0') {
- error("Missing } from command '%s'", start);
+ strgen_error("Missing } from command '%s'", start);
return NULL;
}
- if (s - start == 250) fatal("param command too long");
+ if (s - start == 250) error("param command too long");
*param++ = c;
}
}
@@ -646,7 +645,7 @@
} else if (!memcmp(str, "plural ", 7)) {
_lang_pluralform = atoi(str + 7);
if (_lang_pluralform >= lengthof(_plural_form_counts))
- fatal("Invalid pluralform %d", _lang_pluralform);
+ error("Invalid pluralform %d", _lang_pluralform);
} else if (!memcmp(str, "gender ", 7)) {
char* buf = str + 7;
@@ -654,7 +653,7 @@
const char* s = ParseWord(&buf);
if (s == NULL) break;
- if (_numgenders >= MAX_NUM_GENDER) fatal("Too many genders, max %d", MAX_NUM_GENDER);
+ if (_numgenders >= MAX_NUM_GENDER) error("Too many genders, max %d", MAX_NUM_GENDER);
ttd_strlcpy(_genders[_numgenders], s, sizeof(_genders[_numgenders]));
_numgenders++;
}
@@ -665,12 +664,12 @@
const char* s = ParseWord(&buf);
if (s == NULL) break;
- if (_numcases >= MAX_NUM_CASES) fatal("Too many cases, max %d", MAX_NUM_CASES);
+ if (_numcases >= MAX_NUM_CASES) error("Too many cases, max %d", MAX_NUM_CASES);
ttd_strlcpy(_cases[_numcases], s, sizeof(_cases[_numcases]));
_numcases++;
}
} else {
- fatal("unknown pragma '%s'", str);
+ error("unknown pragma '%s'", str);
}
}
@@ -690,16 +689,16 @@
if (ar == NULL) break;
// Sanity checking
- if (argno != -1 && ar->consumes == 0) fatal("Non consumer param can't have a paramindex");
+ if (argno != -1 && ar->consumes == 0) error("Non consumer param can't have a paramindex");
if (ar->consumes) {
if (argno != -1) argidx = argno;
- if (argidx < 0 || argidx >= lengthof(p->cmd)) fatal("invalid param idx %d", argidx);
- if (p->cmd[argidx] != NULL && p->cmd[argidx] != ar) fatal("duplicate param idx %d", argidx);
+ if (argidx < 0 || argidx >= lengthof(p->cmd)) error("invalid param idx %d", argidx);
+ if (p->cmd[argidx] != NULL && p->cmd[argidx] != ar) error("duplicate param idx %d", argidx);
p->cmd[argidx++] = ar;
} else if (!(ar->flags & C_DONTCOUNT)) { // Ignore some of them
- if (p->np >= lengthof(p->pairs)) fatal("too many commands in string, max %d", lengthof(p->pairs));
+ if (p->np >= lengthof(p->pairs)) error("too many commands in string, max %d", lengthof(p->pairs));
p->pairs[p->np].a = ar;
p->pairs[p->np].v = param[0] != '\0' ? strdup(param) : "";
p->np++;
@@ -738,7 +737,7 @@
// For each string in templ, see if we find it in lang
if (templ.np != lang.np) {
- warning("%s: template string and language string have a different # of commands", name);
+ strgen_warning("%s: template string and language string have a different # of commands", name);
result = false;
}
@@ -756,7 +755,7 @@
}
if (!found) {
- warning("%s: command '%s' exists in template file but not in language file", name, templ.pairs[i].a->cmd);
+ strgen_warning("%s: command '%s' exists in template file but not in language file", name, templ.pairs[i].a->cmd);
result = false;
}
}
@@ -765,7 +764,7 @@
// Check if the non consumer commands match up also.
for (i = 0; i < lengthof(templ.cmd); i++) {
if (TranslateCmdForCompare(templ.cmd[i]) != TranslateCmdForCompare(lang.cmd[i])) {
- warning("%s: Param idx #%d '%s' doesn't match with template command '%s'", name, i,
+ strgen_warning("%s: Param idx #%d '%s' doesn't match with template command '%s'", name, i,
lang.cmd[i] == NULL ? "<empty>" : lang.cmd[i]->cmd,
templ.cmd[i] == NULL ? "<empty>" : templ.cmd[i]->cmd);
result = false;
@@ -791,7 +790,7 @@
s = strchr(str, ':');
if (s == NULL) {
- error("Line has no ':' delimiter");
+ strgen_error("Line has no ':' delimiter");
return;
}
@@ -806,7 +805,7 @@
const char *tmp;
for (tmp = s; *tmp != '\0';) {
size_t len = Utf8Validate(tmp);
- if (len == 0) fatal("Invalid UTF-8 sequence in '%s'", s);
+ if (len == 0) error("Invalid UTF-8 sequence in '%s'", s);
tmp += len;
}
}
@@ -821,18 +820,18 @@
if (master) {
if (ent != NULL && casep == NULL) {
- error("String name '%s' is used multiple times", str);
+ strgen_error("String name '%s' is used multiple times", str);
return;
}
if (ent == NULL && casep != NULL) {
- error("Base string name '%s' doesn't exist yet. Define it before defining a case.", str);
+ strgen_error("Base string name '%s' doesn't exist yet. Define it before defining a case.", str);
return;
}
if (ent == NULL) {
if (_strings[_next_string_id]) {
- error("String ID 0x%X for '%s' already in use by '%s'", ent, str, _strings[_next_string_id]->name);
+ strgen_error("String ID 0x%X for '%s' already in use by '%s'", ent, str, _strings[_next_string_id]->name);
return;
}
@@ -859,12 +858,12 @@
} else {
if (ent == NULL) {
- warning("String name '%s' does not exist in master file", str);
+ strgen_warning("String name '%s' does not exist in master file", str);
return;
}
if (ent->translated && casep == NULL) {
- error("String name '%s' is used multiple times", str);
+ strgen_error("String name '%s' is used multiple times", str);
return;
}
@@ -912,7 +911,7 @@
// derive some strings from english....
in = fopen(file, "r");
- if (in == NULL) fatal("Cannot open file");
+ if (in == NULL) error("Cannot open file");
_cur_line = 1;
while (fgets(buf, sizeof(buf), in) != NULL) {
rstrip(buf);
@@ -922,7 +921,7 @@
fclose(in);
if (StrEmpty(_lang_name) || StrEmpty(_lang_ownname) || StrEmpty(_lang_isocode)) {
- fatal("Language must include ##name, ##ownname and ##isocode");
+ error("Language must include ##name, ##ownname and ##isocode");
}
}
@@ -991,7 +990,7 @@
if (f2 == NULL) return false;
f1 = fopen(n1, "rb");
- if (f1 == NULL) fatal("can't open %s", n1);
+ if (f1 == NULL) error("can't open %s", n1);
do {
l1 = fread(b1, 1, sizeof(b1), f1);
@@ -1017,7 +1016,7 @@
int next = -1;
out = fopen("tmp.xxx", "w");
- if (out == NULL) fatal("can't open tmp.xxx");
+ if (out == NULL) error("can't open tmp.xxx");
fprintf(out, "/* This file is automatically generated. Do not modify */\n\n");
fprintf(out, "#ifndef TABLE_STRINGS_H\n");
@@ -1052,7 +1051,7 @@
#if defined(WIN32) || defined(WIN64)
unlink(filename);
#endif
- if (rename("tmp.xxx", filename) == -1) fatal("rename() failed");
+ if (rename("tmp.xxx", filename) == -1) error("rename() failed");
}
}
@@ -1061,7 +1060,7 @@
int i, sum;
if (argidx < 0 || argidx >= lengthof(_cur_pcs.cmd))
- fatal("invalid argidx %d", argidx);
+ error("invalid argidx %d", argidx);
for (i = sum = 0; i < argidx; i++) {
const CmdStruct *cs = _cur_pcs.cmd[i];
@@ -1112,7 +1111,7 @@
// Output the one from the master string... it's always accurate.
cs = _cur_pcs.cmd[_cur_argidx++];
if (cs == NULL) {
- fatal("%s: No argument exists at position %d", _cur_ident, _cur_argidx - 1);
+ error("%s: No argument exists at position %d", _cur_ident, _cur_argidx - 1);
}
}
@@ -1128,7 +1127,7 @@
fputc((length >> 8) | 0xC0, f);
fputc(length & 0xFF, f);
} else {
- fatal("string too long");
+ error("string too long");
}
}
@@ -1142,7 +1141,7 @@
uint j;
f = fopen(filename, "wb");
- if (f == NULL) fatal("can't open %s", filename);
+ if (f == NULL) error("can't open %s", filename);
memset(&hdr, 0, sizeof(hdr));
for (i = 0; i != 32; i++) {
@@ -1180,7 +1179,7 @@
// Produce a message if a string doesn't have a translation.
if (_show_todo > 0 && ls->translated == NULL) {
if ((_show_todo & 2) != 0) {
- warning("'%s' is untranslated", ls->name);
+ strgen_warning("'%s' is untranslated", ls->name);
}
if ((_show_todo & 1) != 0) {
const char *s = "<TODO> ";
--- a/src/strings.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/strings.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -37,6 +37,7 @@
#include "settings_type.h"
#include "video/video_driver.hpp"
#include "engine_func.h"
+#include "saveload.h"
#include "table/strings.h"
#include "table/control_codes.h"
@@ -1045,11 +1046,11 @@
static char *StationGetSpecialString(char *buff, int x, const char* last)
{
- if ((x & 0x01) && (buff + Utf8CharLen(SCC_TRAIN) < last)) buff += Utf8Encode(buff, SCC_TRAIN);
- if ((x & 0x02) && (buff + Utf8CharLen(SCC_LORRY) < last)) buff += Utf8Encode(buff, SCC_LORRY);
- if ((x & 0x04) && (buff + Utf8CharLen(SCC_BUS) < last)) buff += Utf8Encode(buff, SCC_BUS);
- if ((x & 0x08) && (buff + Utf8CharLen(SCC_PLANE) < last)) buff += Utf8Encode(buff, SCC_PLANE);
- if ((x & 0x10) && (buff + Utf8CharLen(SCC_SHIP) < last)) buff += Utf8Encode(buff, SCC_SHIP);
+ if ((x & FACIL_TRAIN) && (buff + Utf8CharLen(SCC_TRAIN) < last)) buff += Utf8Encode(buff, SCC_TRAIN);
+ if ((x & FACIL_TRUCK_STOP) && (buff + Utf8CharLen(SCC_LORRY) < last)) buff += Utf8Encode(buff, SCC_LORRY);
+ if ((x & FACIL_BUS_STOP) && (buff + Utf8CharLen(SCC_BUS) < last)) buff += Utf8Encode(buff, SCC_BUS);
+ if ((x & FACIL_AIRPORT) && (buff + Utf8CharLen(SCC_PLANE) < last)) buff += Utf8Encode(buff, SCC_PLANE);
+ if ((x & FACIL_DOCK) && (buff + Utf8CharLen(SCC_SHIP) < last)) buff += Utf8Encode(buff, SCC_SHIP);
*buff = '\0';
return buff;
}
@@ -1226,31 +1227,6 @@
return NULL;
}
-/**
- * remap a string ID from the old format to the new format
- * @param s StringID that requires remapping
- * @return translated ID*/
-StringID RemapOldStringID(StringID s)
-{
- switch (s) {
- case 0x0006: return STR_SV_EMPTY;
- case 0x7000: return STR_SV_UNNAMED;
- case 0x70E4: return SPECSTR_PLAYERNAME_ENGLISH;
- case 0x70E9: return SPECSTR_PLAYERNAME_ENGLISH;
- case 0x8864: return STR_SV_TRAIN_NAME;
- case 0x902B: return STR_SV_ROADVEH_NAME;
- case 0x9830: return STR_SV_SHIP_NAME;
- case 0xA02F: return STR_SV_AIRCRAFT_NAME;
-
- default:
- if (IsInsideMM(s, 0x300F, 0x3030)) {
- return s - 0x300F + STR_SV_STNAME;
- } else {
- return s;
- }
- }
-}
-
#ifdef ENABLE_NETWORK
extern void SortNetworkLanguages();
#else /* ENABLE_NETWORK */
@@ -1342,6 +1318,8 @@
return getenv("LANG");
}
+#else
+const char *GetCurrentLocale(const char *param);
#endif /* !(defined(WIN32) || defined(__APPLE__)) */
int CDECL StringIDSorter(const void *a, const void *b)
@@ -1548,3 +1526,118 @@
}
}
}
+
+
+/* --- Handling of saving/loading string IDs from old savegames --- */
+
+/**
+ * Remap a string ID from the old format to the new format
+ * @param s StringID that requires remapping
+ * @return translated ID
+ */
+StringID RemapOldStringID(StringID s)
+{
+ switch (s) {
+ case 0x0006: return STR_SV_EMPTY;
+ case 0x7000: return STR_SV_UNNAMED;
+ case 0x70E4: return SPECSTR_PLAYERNAME_ENGLISH;
+ case 0x70E9: return SPECSTR_PLAYERNAME_ENGLISH;
+ case 0x8864: return STR_SV_TRAIN_NAME;
+ case 0x902B: return STR_SV_ROADVEH_NAME;
+ case 0x9830: return STR_SV_SHIP_NAME;
+ case 0xA02F: return STR_SV_AIRCRAFT_NAME;
+
+ default:
+ if (IsInsideMM(s, 0x300F, 0x3030)) {
+ return s - 0x300F + STR_SV_STNAME;
+ } else {
+ return s;
+ }
+ }
+}
+
+/** Location to load the old names to. */
+char *_old_name_array = NULL;
+
+/**
+ * Copy and convert old custom names to UTF-8.
+ * They were all stored in a 512 by 32 long string array and are
+ * now stored with stations, waypoints and other places with names.
+ * @param id the StringID of the custom name to clone.
+ * @return the clones custom name.
+ */
+char *CopyFromOldName(StringID id)
+{
+ /* Is this name an (old) custom name? */
+ if (GB(id, 11, 5) != 15) return NULL;
+
+ if (CheckSavegameVersion(37)) {
+ /* Old names were 32 characters long, so 128 characters should be
+ * plenty to allow for expansion when converted to UTF-8. */
+ char tmp[128];
+ const char *strfrom = &_old_name_array[32 * GB(id, 0, 9)];
+ char *strto = tmp;
+
+ for (; *strfrom != '\0'; strfrom++) {
+ WChar c = (byte)*strfrom;
+
+ /* Map from non-ISO8859-15 characters to UTF-8. */
+ switch (c) {
+ case 0xA4: c = 0x20AC; break; // Euro
+ case 0xA6: c = 0x0160; break; // S with caron
+ case 0xA8: c = 0x0161; break; // s with caron
+ case 0xB4: c = 0x017D; break; // Z with caron
+ case 0xB8: c = 0x017E; break; // z with caron
+ case 0xBC: c = 0x0152; break; // OE ligature
+ case 0xBD: c = 0x0153; break; // oe ligature
+ case 0xBE: c = 0x0178; break; // Y with diaresis
+ default: break;
+ }
+
+ /* Check character will fit into our buffer. */
+ if (strto + Utf8CharLen(c) > lastof(tmp)) break;
+
+ strto += Utf8Encode(strto, c);
+ }
+
+ /* Terminate the new string and copy it back to the name array */
+ *strto = '\0';
+
+ return strdup(tmp);
+ } else {
+ /* Name will already be in UTF-8. */
+ return strdup(&_old_name_array[32 * GB(id, 0, 9)]);
+ }
+}
+
+/**
+ * Free the memory of the old names array.
+ * Should be called once the old names have all been converted.
+ */
+void ResetOldNames()
+{
+ free(_old_name_array);
+ _old_name_array = NULL;
+}
+
+/**
+ * Initialize the old names table memory.
+ */
+void InitializeOldNames()
+{
+ free(_old_name_array);
+ _old_name_array = CallocT<char>(512 * 32);
+}
+
+static void Load_NAME()
+{
+ int index;
+
+ while ((index = SlIterateArray()) != -1) {
+ SlArray(&_old_name_array[32 * index], SlGetFieldLength(), SLE_UINT8);
+ }
+}
+
+extern const ChunkHandler _name_chunk_handlers[] = {
+ { 'NAME', NULL, Load_NAME, CH_ARRAY | CH_LAST},
+};
--- a/src/strings_func.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/strings_func.h Sun Apr 20 15:27:28 2008 +0000
@@ -78,4 +78,7 @@
void CheckForMissingGlyphsInLoadedLanguagePack();
+StringID RemapOldStringID(StringID s);
+char *CopyFromOldName(StringID id);
+
#endif /* STRINGS_TYPE_H */
--- a/src/texteff.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/texteff.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -4,10 +4,8 @@
#include "stdafx.h"
#include "openttd.h"
-#include "tile_cmd.h"
#include "landscape.h"
#include "gfx_func.h"
-#include "saveload.h"
#include "console.h"
#include "variables.h"
#include "blitter/factory.hpp"
@@ -423,128 +421,3 @@
default: NOT_REACHED();
}
}
-
-/** The table/list with animated tiles. */
-TileIndex *_animated_tile_list = NULL;
-/** The number of animated tiles in the current state. */
-uint _animated_tile_count = 0;
-/** The number of slots for animated tiles allocated currently. */
-static uint _animated_tile_allocated = 0;
-
-/**
- * Removes the given tile from the animated tile table.
- * @param tile the tile to remove
- */
-void DeleteAnimatedTile(TileIndex tile)
-{
- for (TileIndex *ti = _animated_tile_list; ti < _animated_tile_list + _animated_tile_count; ti++) {
- if (tile == *ti) {
- /* Remove the hole
- * The order of the remaining elements must stay the same, otherwise the animation loop
- * may miss a tile; that's why we must use memmove instead of just moving the last element.
- */
- memmove(ti, ti + 1, (_animated_tile_list + _animated_tile_count - (ti + 1)) * sizeof(*ti));
- _animated_tile_count--;
- MarkTileDirtyByTile(tile);
- return;
- }
- }
-}
-
-/**
- * Add the given tile to the animated tile table (if it does not exist
- * on that table yet). Also increases the size of the table if necessary.
- * @param tile the tile to make animated
- */
-void AddAnimatedTile(TileIndex tile)
-{
- MarkTileDirtyByTile(tile);
-
- for (const TileIndex *ti = _animated_tile_list; ti < _animated_tile_list + _animated_tile_count; ti++) {
- if (tile == *ti) return;
- }
-
- /* Table not large enough, so make it larger */
- if (_animated_tile_count == _animated_tile_allocated) {
- _animated_tile_allocated *= 2;
- _animated_tile_list = ReallocT<TileIndex>(_animated_tile_list, _animated_tile_allocated);
- }
-
- _animated_tile_list[_animated_tile_count] = tile;
- _animated_tile_count++;
-}
-
-/**
- * Animate all tiles in the animated tile list, i.e.\ call AnimateTile on them.
- */
-void AnimateAnimatedTiles()
-{
- const TileIndex *ti = _animated_tile_list;
- while (ti < _animated_tile_list + _animated_tile_count) {
- const TileIndex curr = *ti;
- AnimateTile(curr);
- /* During the AnimateTile call, DeleteAnimatedTile could have been called,
- * deleting an element we've already processed and pushing the rest one
- * slot to the left. We can detect this by checking whether the index
- * in the current slot has changed - if it has, an element has been deleted,
- * and we should process the current slot again instead of going forward.
- * NOTE: this will still break if more than one animated tile is being
- * deleted during the same AnimateTile call, but no code seems to
- * be doing this anyway.
- */
- if (*ti == curr) ++ti;
- }
-}
-
-/**
- * Initialize all animated tile variables to some known begin point
- */
-void InitializeAnimatedTiles()
-{
- _animated_tile_list = ReallocT<TileIndex>(_animated_tile_list, 256);
- _animated_tile_count = 0;
- _animated_tile_allocated = 256;
-}
-
-/**
- * Save the ANIT chunk.
- */
-static void Save_ANIT()
-{
- SlSetLength(_animated_tile_count * sizeof(*_animated_tile_list));
- SlArray(_animated_tile_list, _animated_tile_count, SLE_UINT32);
-}
-
-/**
- * Load the ANIT chunk; the chunk containing the animated tiles.
- */
-static void Load_ANIT()
-{
- /* Before version 80 we did NOT have a variable length animated tile table */
- if (CheckSavegameVersion(80)) {
- /* In pre version 6, we has 16bit per tile, now we have 32bit per tile, convert it ;) */
- SlArray(_animated_tile_list, 256, CheckSavegameVersion(6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32);
-
- for (_animated_tile_count = 0; _animated_tile_count < 256; _animated_tile_count++) {
- if (_animated_tile_list[_animated_tile_count] == 0) break;
- }
- return;
- }
-
- _animated_tile_count = SlGetFieldLength() / sizeof(*_animated_tile_list);
-
- /* Determine a nice rounded size for the amount of allocated tiles */
- _animated_tile_allocated = 256;
- while (_animated_tile_allocated < _animated_tile_count) _animated_tile_allocated *= 2;
-
- _animated_tile_list = ReallocT<TileIndex>(_animated_tile_list, _animated_tile_allocated);
- SlArray(_animated_tile_list, _animated_tile_count, SLE_UINT32);
-}
-
-/**
- * "Definition" imported by the saveload code to be able to load and save
- * the animated tile table.
- */
-extern const ChunkHandler _animated_tile_chunk_handlers[] = {
- { 'ANIT', Save_ANIT, Load_ANIT, CH_RIFF | CH_LAST},
-};
--- a/src/town_cmd.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/town_cmd.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -45,6 +45,9 @@
#include "economy_func.h"
#include "station_func.h"
#include "cheat_func.h"
+#include "functions.h"
+#include "animated_tile_func.h"
+#include "date_func.h"
#include "table/strings.h"
#include "table/sprites.h"
@@ -268,7 +271,10 @@
pos += (pos < dest) ? 1 : -1;
SetLiftPosition(tile, pos);
- if (pos == dest) HaltLift(tile);
+ if (pos == dest) {
+ HaltLift(tile);
+ DeleteAnimatedTile(tile);
+ }
MarkTileDirtyByTile(tile);
}
@@ -385,6 +391,7 @@
/* Now that construction is complete, we can add the population of the
* building to the town. */
ChangePopulation(GetTownByTile(tile), GetHouseSpecs(GetHouseType(tile))->population);
+ SetHouseConstructionYear(tile, _cur_year);
}
MarkTileDirtyByTile(tile);
}
@@ -1644,6 +1651,9 @@
assert(CmdSucceeded(cc));
MakeHouseTile(tile, tid, counter, stage, type, random_bits);
+ if (GetHouseSpecs(type)->building_flags & BUILDING_IS_ANIMATED) AddAnimatedTile(tile);
+
+ MarkTileDirtyByTile(tile);
}
--- a/src/town_gui.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/town_gui.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -396,7 +396,7 @@
if (w != NULL) {
w->flags4 |= WF_DISABLE_VP_SCROLL;
- AssignWindowViewport(w, 3, 17, 0xFE, 0x56, GetTown(town)->xy, ZOOM_LVL_TOWN);
+ InitializeWindowViewport(w, 3, 17, 254, 86, GetTown(town)->xy, ZOOM_LVL_TOWN);
}
}
--- a/src/town_map.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/town_map.h Sun Apr 20 15:27:28 2008 +0000
@@ -6,9 +6,8 @@
#define TOWN_MAP_H
#include "town.h"
-#include "date_func.h"
+#include "date_type.h"
#include "tile_map.h"
-#include "functions.h"
/**
* Get the index of which town this house/street is attached to.
@@ -113,7 +112,6 @@
static inline void HaltLift(TileIndex t)
{
SB(_me[t].m7, 0, 4, 0);
- DeleteAnimatedTile(t);
}
/**
@@ -206,9 +204,6 @@
_m[t].m5 = IsHouseCompleted(t) ? 0 : (stage << 3 | counter);
SetHouseAnimationFrame(t, 0);
_me[t].m7 = GetHouseSpecs(type)->processing_time;
-
- if (GetHouseSpecs(type)->building_flags & BUILDING_IS_ANIMATED) AddAnimatedTile(t);
- MarkTileDirtyByTile(t);
}
/**
@@ -266,11 +261,22 @@
/* House is now completed.
* Store the year of construction as well, for newgrf house purpose */
SetHouseCompleted(t, true);
- _m[t].m5 = Clamp(_cur_year - ORIGINAL_BASE_YEAR, 0, 0xFF);
}
}
/**
+ * Set the year that this house was constructed (between 1920 and 2175).
+ * @param t the tile of this house
+ * @param year the year to set
+ * @pre IsTileType(t, MP_HOUSE) && IsHouseCompleted(t)
+ */
+static inline void SetHouseConstructionYear(TileIndex t, Year year)
+{
+ assert(IsTileType(t, MP_HOUSE) && IsHouseCompleted(t));
+ _m[t].m5 = Clamp(year - ORIGINAL_BASE_YEAR, 0, 0xFF);
+}
+
+/**
* Get the year that this house was constructed (between 1920 and 2175).
* @param t the tile of this house
* @pre IsTileType(t, MP_HOUSE)
--- a/src/train_cmd.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/train_cmd.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -48,6 +48,8 @@
#include "gfx_func.h"
#include "settings_type.h"
#include "order_func.h"
+#include "newgrf_station.h"
+#include "effectvehicle_func.h"
#include "table/strings.h"
#include "table/train_cmd.h"
@@ -2218,6 +2220,8 @@
SND_41_MAGLEV
};
+ if (IsTileType(this->tile, MP_STATION)) StationAnimationTrigger(NULL, this->tile, STAT_ANIM_TRAIN_DEPARTS);
+
if (PlayVehicleSound(this, VSE_START)) return;
EngineID engtype = this->engine_type;
@@ -2638,6 +2642,8 @@
}
v->BeginLoading();
+
+ StationAnimationTrigger(st, v->tile, STAT_ANIM_TRAIN_ARRIVES);
}
static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
@@ -3232,7 +3238,7 @@
if (!(v->vehstatus & VS_HIDDEN)) {
Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE);
- if (u != NULL) u->u.special.animation_state = v->breakdown_delay * 2;
+ if (u != NULL) u->u.effect.animation_state = v->breakdown_delay * 2;
}
}
@@ -3421,7 +3427,7 @@
HandleBrokenTrain(v);
return;
}
- v->breakdown_ctr--;
+ if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--;
}
if (HasBit(v->u.rail.flags, VRF_REVERSING) && v->cur_speed == 0) {
--- a/src/vehicle.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/vehicle.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -47,6 +47,8 @@
#include "settings_type.h"
#include "oldpool_func.h"
#include "depot_map.h"
+#include "animated_tile_func.h"
+#include "effectvehicle_base.h"
#include "table/sprites.h"
#include "table/strings.h"
@@ -106,6 +108,7 @@
if (!p->engine_renew) return false;
if (this->age - this->max_age < (p->engine_renew_months * 30)) return false;
+ if (this->age == 0) return false; // rail cars don't age and lacks a max age
return true;
}
@@ -691,11 +694,32 @@
/* now we handle all the vehicles that entered a depot this tick */
v = _first_veh_in_depot_list;
- while (v != NULL) {
- Vehicle *w = v->depot_list;
- v->depot_list = NULL; // it should always be NULL at the end of each tick
- MaybeReplaceVehicle(v, false, true);
- v = w;
+ if (v != NULL) {
+ while (v != NULL) {
+ /* Autoreplace needs the current player set as the vehicle owner */
+ _current_player = v->owner;
+
+ /* Buffer v->depot_list and clear it.
+ * Autoreplace might clear this so it has to be buffered. */
+ Vehicle *w = v->depot_list;
+ v->depot_list = NULL; // it should always be NULL at the end of each tick
+
+ /* Start vehicle if we stopped them in VehicleEnteredDepotThisTick()
+ * We need to stop them between VehicleEnteredDepotThisTick() and here or we risk that
+ * they are already leaving the depot again before being replaced. */
+ if (v->leave_depot_instantly) {
+ v->leave_depot_instantly = false;
+ v->vehstatus &= ~VS_STOPPED;
+ }
+
+ CommandCost cost = MaybeReplaceVehicle(v, 0, true);
+ if (CmdSucceeded(cost) && cost.GetCost() != 0) {
+ /* Looks like we can replace this vehicle so we go ahead and do so */
+ MaybeReplaceVehicle(v, DC_EXEC, true);
+ }
+ v = w;
+ }
+ _current_player = OWNER_NONE;
}
}
@@ -823,605 +847,6 @@
}
}
-static void ChimneySmokeInit(Vehicle *v)
-{
- uint32 r = Random();
- v->cur_image = SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3);
- v->progress = GB(r, 16, 3);
-}
-
-static void ChimneySmokeTick(Vehicle *v)
-{
- if (v->progress > 0) {
- v->progress--;
- } else {
- BeginVehicleMove(v);
-
- TileIndex tile = TileVirtXY(v->x_pos, v->y_pos);
- if (!IsTileType(tile, MP_INDUSTRY)) {
- EndVehicleMove(v);
- delete v;
- return;
- }
-
- if (v->cur_image != SPR_CHIMNEY_SMOKE_7) {
- v->cur_image++;
- } else {
- v->cur_image = SPR_CHIMNEY_SMOKE_0;
- }
- v->progress = 7;
- VehiclePositionChanged(v);
- EndVehicleMove(v);
- }
-}
-
-static void SteamSmokeInit(Vehicle *v)
-{
- v->cur_image = SPR_STEAM_SMOKE_0;
- v->progress = 12;
-}
-
-static void SteamSmokeTick(Vehicle *v)
-{
- bool moved = false;
-
- BeginVehicleMove(v);
-
- v->progress++;
-
- if ((v->progress & 7) == 0) {
- v->z_pos++;
- moved = true;
- }
-
- if ((v->progress & 0xF) == 4) {
- if (v->cur_image != SPR_STEAM_SMOKE_4) {
- v->cur_image++;
- } else {
- EndVehicleMove(v);
- delete v;
- return;
- }
- moved = true;
- }
-
- if (moved) {
- VehiclePositionChanged(v);
- EndVehicleMove(v);
- }
-}
-
-static void DieselSmokeInit(Vehicle *v)
-{
- v->cur_image = SPR_DIESEL_SMOKE_0;
- v->progress = 0;
-}
-
-static void DieselSmokeTick(Vehicle *v)
-{
- v->progress++;
-
- if ((v->progress & 3) == 0) {
- BeginVehicleMove(v);
- v->z_pos++;
- VehiclePositionChanged(v);
- EndVehicleMove(v);
- } else if ((v->progress & 7) == 1) {
- BeginVehicleMove(v);
- if (v->cur_image != SPR_DIESEL_SMOKE_5) {
- v->cur_image++;
- VehiclePositionChanged(v);
- EndVehicleMove(v);
- } else {
- EndVehicleMove(v);
- delete v;
- }
- }
-}
-
-static void ElectricSparkInit(Vehicle *v)
-{
- v->cur_image = SPR_ELECTRIC_SPARK_0;
- v->progress = 1;
-}
-
-static void ElectricSparkTick(Vehicle *v)
-{
- if (v->progress < 2) {
- v->progress++;
- } else {
- v->progress = 0;
- BeginVehicleMove(v);
- if (v->cur_image != SPR_ELECTRIC_SPARK_5) {
- v->cur_image++;
- VehiclePositionChanged(v);
- EndVehicleMove(v);
- } else {
- EndVehicleMove(v);
- delete v;
- }
- }
-}
-
-static void SmokeInit(Vehicle *v)
-{
- v->cur_image = SPR_SMOKE_0;
- v->progress = 12;
-}
-
-static void SmokeTick(Vehicle *v)
-{
- bool moved = false;
-
- BeginVehicleMove(v);
-
- v->progress++;
-
- if ((v->progress & 3) == 0) {
- v->z_pos++;
- moved = true;
- }
-
- if ((v->progress & 0xF) == 4) {
- if (v->cur_image != SPR_SMOKE_4) {
- v->cur_image++;
- } else {
- EndVehicleMove(v);
- delete v;
- return;
- }
- moved = true;
- }
-
- if (moved) {
- VehiclePositionChanged(v);
- EndVehicleMove(v);
- }
-}
-
-static void ExplosionLargeInit(Vehicle *v)
-{
- v->cur_image = SPR_EXPLOSION_LARGE_0;
- v->progress = 0;
-}
-
-static void ExplosionLargeTick(Vehicle *v)
-{
- v->progress++;
- if ((v->progress & 3) == 0) {
- BeginVehicleMove(v);
- if (v->cur_image != SPR_EXPLOSION_LARGE_F) {
- v->cur_image++;
- VehiclePositionChanged(v);
- EndVehicleMove(v);
- } else {
- EndVehicleMove(v);
- delete v;
- }
- }
-}
-
-static void BreakdownSmokeInit(Vehicle *v)
-{
- v->cur_image = SPR_BREAKDOWN_SMOKE_0;
- v->progress = 0;
-}
-
-static void BreakdownSmokeTick(Vehicle *v)
-{
- v->progress++;
- if ((v->progress & 7) == 0) {
- BeginVehicleMove(v);
- if (v->cur_image != SPR_BREAKDOWN_SMOKE_3) {
- v->cur_image++;
- } else {
- v->cur_image = SPR_BREAKDOWN_SMOKE_0;
- }
- VehiclePositionChanged(v);
- EndVehicleMove(v);
- }
-
- v->u.special.animation_state--;
- if (v->u.special.animation_state == 0) {
- BeginVehicleMove(v);
- EndVehicleMove(v);
- delete v;
- }
-}
-
-static void ExplosionSmallInit(Vehicle *v)
-{
- v->cur_image = SPR_EXPLOSION_SMALL_0;
- v->progress = 0;
-}
-
-static void ExplosionSmallTick(Vehicle *v)
-{
- v->progress++;
- if ((v->progress & 3) == 0) {
- BeginVehicleMove(v);
- if (v->cur_image != SPR_EXPLOSION_SMALL_B) {
- v->cur_image++;
- VehiclePositionChanged(v);
- EndVehicleMove(v);
- } else {
- EndVehicleMove(v);
- delete v;
- }
- }
-}
-
-static void BulldozerInit(Vehicle *v)
-{
- v->cur_image = SPR_BULLDOZER_NE;
- v->progress = 0;
- v->u.special.animation_state = 0;
- v->u.special.animation_substate = 0;
-}
-
-struct BulldozerMovement {
- byte direction:2;
- byte image:2;
- byte duration:3;
-};
-
-static const BulldozerMovement _bulldozer_movement[] = {
- { 0, 0, 4 },
- { 3, 3, 4 },
- { 2, 2, 7 },
- { 0, 2, 7 },
- { 1, 1, 3 },
- { 2, 2, 7 },
- { 0, 2, 7 },
- { 1, 1, 3 },
- { 2, 2, 7 },
- { 0, 2, 7 },
- { 3, 3, 6 },
- { 2, 2, 6 },
- { 1, 1, 7 },
- { 3, 1, 7 },
- { 0, 0, 3 },
- { 1, 1, 7 },
- { 3, 1, 7 },
- { 0, 0, 3 },
- { 1, 1, 7 },
- { 3, 1, 7 }
-};
-
-static const struct {
- int8 x;
- int8 y;
-} _inc_by_dir[] = {
- { -1, 0 },
- { 0, 1 },
- { 1, 0 },
- { 0, -1 }
-};
-
-static void BulldozerTick(Vehicle *v)
-{
- v->progress++;
- if ((v->progress & 7) == 0) {
- const BulldozerMovement* b = &_bulldozer_movement[v->u.special.animation_state];
-
- BeginVehicleMove(v);
-
- v->cur_image = SPR_BULLDOZER_NE + b->image;
-
- v->x_pos += _inc_by_dir[b->direction].x;
- v->y_pos += _inc_by_dir[b->direction].y;
-
- v->u.special.animation_substate++;
- if (v->u.special.animation_substate >= b->duration) {
- v->u.special.animation_substate = 0;
- v->u.special.animation_state++;
- if (v->u.special.animation_state == lengthof(_bulldozer_movement)) {
- EndVehicleMove(v);
- delete v;
- return;
- }
- }
- VehiclePositionChanged(v);
- EndVehicleMove(v);
- }
-}
-
-static void BubbleInit(Vehicle *v)
-{
- v->cur_image = SPR_BUBBLE_GENERATE_0;
- v->spritenum = 0;
- v->progress = 0;
-}
-
-struct BubbleMovement {
- int8 x:4;
- int8 y:4;
- int8 z:4;
- byte image:4;
-};
-
-#define MK(x, y, z, i) { x, y, z, i }
-#define ME(i) { i, 4, 0, 0 }
-
-static const BubbleMovement _bubble_float_sw[] = {
- MK(0, 0, 1, 0),
- MK(1, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(1, 0, 1, 2),
- ME(1)
-};
-
-
-static const BubbleMovement _bubble_float_ne[] = {
- MK( 0, 0, 1, 0),
- MK(-1, 0, 1, 1),
- MK( 0, 0, 1, 0),
- MK(-1, 0, 1, 2),
- ME(1)
-};
-
-static const BubbleMovement _bubble_float_se[] = {
- MK(0, 0, 1, 0),
- MK(0, 1, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 1, 1, 2),
- ME(1)
-};
-
-static const BubbleMovement _bubble_float_nw[] = {
- MK(0, 0, 1, 0),
- MK(0, -1, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, -1, 1, 2),
- ME(1)
-};
-
-static const BubbleMovement _bubble_burst[] = {
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 7),
- MK(0, 0, 1, 8),
- MK(0, 0, 1, 9),
- ME(0)
-};
-
-static const BubbleMovement _bubble_absorb[] = {
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(0, 0, 1, 1),
- MK(2, 1, 3, 0),
- MK(1, 1, 3, 1),
- MK(2, 1, 3, 0),
- MK(1, 1, 3, 2),
- MK(2, 1, 3, 0),
- MK(1, 1, 3, 1),
- MK(2, 1, 3, 0),
- MK(1, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(1, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(1, 0, 1, 2),
- MK(0, 0, 1, 0),
- MK(1, 0, 1, 1),
- MK(0, 0, 1, 0),
- MK(1, 0, 1, 2),
- ME(2),
- MK(0, 0, 0, 0xA),
- MK(0, 0, 0, 0xB),
- MK(0, 0, 0, 0xC),
- MK(0, 0, 0, 0xD),
- MK(0, 0, 0, 0xE),
- ME(0)
-};
-#undef ME
-#undef MK
-
-static const BubbleMovement * const _bubble_movement[] = {
- _bubble_float_sw,
- _bubble_float_ne,
- _bubble_float_se,
- _bubble_float_nw,
- _bubble_burst,
- _bubble_absorb,
-};
-
-static void BubbleTick(Vehicle *v)
-{
- /*
- * Warning: those effects can NOT use Random(), and have to use
- * InteractiveRandom(), because somehow someone forgot to save
- * spritenum to the savegame, and so it will cause desyncs in
- * multiplayer!! (that is: in ToyLand)
- */
- uint et;
-
- v->progress++;
- if ((v->progress & 3) != 0) return;
-
- BeginVehicleMove(v);
-
- if (v->spritenum == 0) {
- v->cur_image++;
- if (v->cur_image < SPR_BUBBLE_GENERATE_3) {
- VehiclePositionChanged(v);
- EndVehicleMove(v);
- return;
- }
- if (v->u.special.animation_substate != 0) {
- v->spritenum = GB(InteractiveRandom(), 0, 2) + 1;
- } else {
- v->spritenum = 6;
- }
- et = 0;
- } else {
- et = v->engine_type + 1;
- }
-
- const BubbleMovement *b = &_bubble_movement[v->spritenum - 1][et];
-
- if (b->y == 4 && b->x == 0) {
- EndVehicleMove(v);
- delete v;
- return;
- }
-
- if (b->y == 4 && b->x == 1) {
- if (v->z_pos > 180 || Chance16I(1, 96, InteractiveRandom())) {
- v->spritenum = 5;
- SndPlayVehicleFx(SND_2F_POP, v);
- }
- et = 0;
- }
-
- if (b->y == 4 && b->x == 2) {
- TileIndex tile;
-
- et++;
- SndPlayVehicleFx(SND_31_EXTRACT, v);
-
- tile = TileVirtXY(v->x_pos, v->y_pos);
- if (IsTileType(tile, MP_INDUSTRY) && GetIndustryGfx(tile) == GFX_BUBBLE_CATCHER) AddAnimatedTile(tile);
- }
-
- v->engine_type = et;
- b = &_bubble_movement[v->spritenum - 1][et];
-
- v->x_pos += b->x;
- v->y_pos += b->y;
- v->z_pos += b->z;
- v->cur_image = SPR_BUBBLE_0 + b->image;
-
- VehiclePositionChanged(v);
- EndVehicleMove(v);
-}
-
-
-typedef void EffectInitProc(Vehicle *v);
-typedef void EffectTickProc(Vehicle *v);
-
-static EffectInitProc * const _effect_init_procs[] = {
- ChimneySmokeInit,
- SteamSmokeInit,
- DieselSmokeInit,
- ElectricSparkInit,
- SmokeInit,
- ExplosionLargeInit,
- BreakdownSmokeInit,
- ExplosionSmallInit,
- BulldozerInit,
- BubbleInit,
-};
-
-static EffectTickProc * const _effect_tick_procs[] = {
- ChimneySmokeTick,
- SteamSmokeTick,
- DieselSmokeTick,
- ElectricSparkTick,
- SmokeTick,
- ExplosionLargeTick,
- BreakdownSmokeTick,
- ExplosionSmallTick,
- BulldozerTick,
- BubbleTick,
-};
-
-
-Vehicle *CreateEffectVehicle(int x, int y, int z, EffectVehicle type)
-{
- Vehicle *v = new SpecialVehicle();
- if (v != NULL) {
- v->subtype = type;
- v->x_pos = x;
- v->y_pos = y;
- v->z_pos = z;
- v->tile = 0;
- v->UpdateDeltaXY(INVALID_DIR);
- v->vehstatus = VS_UNCLICKABLE;
-
- _effect_init_procs[type](v);
-
- VehiclePositionChanged(v);
- BeginVehicleMove(v);
- EndVehicleMove(v);
- }
- return v;
-}
-
-Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicle type)
-{
- int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE);
- int safe_y = Clamp(y, 0, MapMaxY() * TILE_SIZE);
- return CreateEffectVehicle(x, y, GetSlopeZ(safe_x, safe_y) + z, type);
-}
-
-Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicle type)
-{
- return CreateEffectVehicle(v->x_pos + x, v->y_pos + y, v->z_pos + z, type);
-}
-
-void SpecialVehicle::Tick()
-{
- _effect_tick_procs[this->subtype](this);
-}
-
Vehicle *CheckClickOnVehicle(const ViewPort *vp, int x, int y)
{
Vehicle *found = NULL, *v;
@@ -1695,16 +1120,11 @@
for (uint i = 0; i < engine_count; i++) {
Vehicle *v = vl[i];
- bool stopped = !(v->vehstatus & VS_STOPPED);
/* Ensure that the vehicle completely in the depot */
if (!v->IsInDepot()) continue;
- if (stopped) {
- v->vehstatus |= VS_STOPPED; // Stop the vehicle
- v->leave_depot_instantly = true;
- }
- CommandCost ret = MaybeReplaceVehicle(v, !(flags & DC_EXEC), false);
+ CommandCost ret = MaybeReplaceVehicle(v, flags, false);
if (CmdSucceeded(ret)) {
cost.AddCost(ret);
@@ -2480,7 +1900,7 @@
/* Vehicle is turning around, get the direction from vehicle's direction */
return DiagdirToDiagTrackdir(DirToDiagDir(v->direction));
- /* case VEH_AIRCRAFT: case VEH_SPECIAL: case VEH_DISASTER: */
+ /* case VEH_AIRCRAFT: case VEH_EFFECT: case VEH_DISASTER: */
default: return INVALID_TRACKDIR;
}
}
@@ -2939,7 +2359,7 @@
};
static const SaveLoad _special_desc[] = {
- SLE_WRITEBYTE(Vehicle, type, VEH_SPECIAL),
+ SLE_WRITEBYTE(Vehicle, type, VEH_EFFECT),
SLE_VAR(Vehicle, subtype, SLE_UINT8),
@@ -2957,8 +2377,8 @@
SLE_VAR(Vehicle, progress, SLE_UINT8),
SLE_VAR(Vehicle, vehstatus, SLE_UINT8),
- SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleSpecial, animation_state), SLE_UINT16),
- SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleSpecial, animation_substate), SLE_UINT8),
+ SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleEffect, animation_state), SLE_UINT16),
+ SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleEffect, animation_substate), SLE_UINT8),
/* reserve extra space in savegame here. (currently 16 bytes) */
SLE_CONDNULL(16, 2, SL_MAX_VERSION),
@@ -3046,7 +2466,7 @@
case VEH_ROAD: v = new (index) RoadVehicle(); break;
case VEH_SHIP: v = new (index) Ship(); break;
case VEH_AIRCRAFT: v = new (index) Aircraft(); break;
- case VEH_SPECIAL: v = new (index) SpecialVehicle(); break;
+ case VEH_EFFECT: v = new (index) EffectVehicle(); break;
case VEH_DISASTER: v = new (index) DisasterVehicle(); break;
case VEH_INVALID: v = new (index) InvalidVehicle(); break;
default: NOT_REACHED();
@@ -3266,15 +2686,6 @@
}
}
-void SpecialVehicle::UpdateDeltaXY(Direction direction)
-{
- this->x_offs = 0;
- this->y_offs = 0;
- this->x_extent = 1;
- this->y_extent = 1;
- this->z_extent = 1;
-}
-
void StopAllVehicles()
{
Vehicle *v;
--- a/src/vehicle_base.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/vehicle_base.h Sun Apr 20 15:27:28 2008 +0000
@@ -171,7 +171,7 @@
RoadTypes compatible_roadtypes;
};
-struct VehicleSpecial {
+struct VehicleEffect {
uint16 animation_state;
byte animation_substate;
};
@@ -315,7 +315,7 @@
VehicleRail rail;
VehicleAir air;
VehicleRoad road;
- VehicleSpecial special;
+ VehicleEffect effect;
VehicleDisaster disaster;
VehicleShip ship;
} u;
@@ -541,33 +541,6 @@
* v = new (v) Train();
*
* As side-effect the vehicle type is set correctly.
- *
- * A special vehicle is one of the following:
- * - smoke
- * - electric sparks for trains
- * - explosions
- * - bulldozer (road works)
- * - bubbles (industry)
- */
-struct SpecialVehicle : public Vehicle {
- /** Initializes the Vehicle to a special vehicle */
- SpecialVehicle() { this->type = VEH_SPECIAL; }
-
- /** We want to 'destruct' the right class. */
- virtual ~SpecialVehicle() {}
-
- const char *GetTypeString() const { return "special vehicle"; }
- void UpdateDeltaXY(Direction direction);
- void Tick();
-};
-
-/**
- * This class 'wraps' Vehicle; you do not actually instantiate this class.
- * You create a Vehicle using AllocateVehicle, so it is added to the pool
- * and you reinitialize that to a Train using:
- * v = new (v) Train();
- *
- * As side-effect the vehicle type is set correctly.
*/
struct DisasterVehicle : public Vehicle {
/** Initializes the Vehicle to a disaster vehicle */
--- a/src/vehicle_func.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/vehicle_func.h Sun Apr 20 15:27:28 2008 +0000
@@ -1,6 +1,6 @@
/* $Id$ */
-/** @vehicle.h Functions related to vehicles. */
+/** @file vehicle.h Functions related to vehicles. */
#ifndef VEHICLE_FUNC_H
#define VEHICLE_FUNC_H
@@ -71,7 +71,7 @@
CommandCost SendAllVehiclesToDepot(VehicleType type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id);
void VehicleEnterDepot(Vehicle *v);
-CommandCost MaybeReplaceVehicle(Vehicle *v, bool check, bool display_costs);
+CommandCost MaybeReplaceVehicle(Vehicle *v, uint32 flags, bool display_costs);
bool CanBuildVehicleInfrastructure(VehicleType type);
void CcCloneVehicle(bool success, TileIndex tile, uint32 p1, uint32 p2);
@@ -171,13 +171,9 @@
bool EnsureNoVehicleOnGround(TileIndex tile);
void StopAllVehicles();
-Vehicle *CreateEffectVehicle(int x, int y, int z, EffectVehicle type);
-Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicle type);
-Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicle type);
-
extern VehicleID _vehicle_id_ctr_day;
extern Vehicle *_place_clicked_vehicle;
extern VehicleID _new_vehicle_id;
extern uint16 _returned_refit_capacity;
-#endif /* VEHICLE_H */
+#endif /* VEHICLE_FUNC_H */
--- a/src/vehicle_gui.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/vehicle_gui.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -35,7 +35,6 @@
#include "settings_type.h"
#include "widgets/dropdown_func.h"
#include "order_func.h"
-#include "depot_base.h"
#include "table/sprites.h"
#include "table/strings.h"
@@ -103,7 +102,11 @@
INVALID_STRING_ID
};
-void RebuildVehicleLists()
+/**
+ * Set sort list flag for all vehicle list windows
+ * @param sl_flag Sort list flag to set
+ */
+static void SetVehicleListsFlag(SortListFlags sl_flag)
{
Window* const *wz;
@@ -115,7 +118,7 @@
case WC_ROADVEH_LIST:
case WC_SHIPS_LIST:
case WC_AIRCRAFT_LIST:
- WP(w, vehiclelist_d).l.flags |= VL_REBUILD;
+ WP(w, vehiclelist_d).l.flags |= sl_flag;
SetWindowDirty(w);
break;
@@ -124,25 +127,20 @@
}
}
+/**
+ * Rebuild all vehicle list windows
+ */
+void RebuildVehicleLists()
+{
+ SetVehicleListsFlag(VL_REBUILD);
+}
+
+/**
+ * Resort all vehicle list windows
+ */
void ResortVehicleLists()
{
- Window* const *wz;
-
- FOR_ALL_WINDOWS(wz) {
- Window *w = *wz;
-
- switch (w->window_class) {
- case WC_TRAINS_LIST:
- case WC_ROADVEH_LIST:
- case WC_SHIPS_LIST:
- case WC_AIRCRAFT_LIST:
- WP(w, vehiclelist_d).l.flags |= VL_RESORT;
- SetWindowDirty(w);
- break;
-
- default: break;
- }
- }
+ SetVehicleListsFlag(VL_RESORT);
}
void BuildVehicleList(vehiclelist_d *vl, PlayerID owner, uint16 index, uint16 window_type)
@@ -1753,7 +1751,7 @@
if (w != NULL) {
w->caption_color = v->owner;
- AssignWindowViewport(w, VV_VIEWPORT_X, VV_VIEWPORT_Y, VV_INITIAL_VIEWPORT_WIDTH,
+ InitializeWindowViewport(w, VV_VIEWPORT_X, VV_VIEWPORT_Y, VV_INITIAL_VIEWPORT_WIDTH,
(v->type == VEH_TRAIN) ? VV_INITIAL_VIEWPORT_HEIGHT_TRAIN : VV_INITIAL_VIEWPORT_HEIGHT,
w->window_number | (1 << 31), _vehicle_view_zoom_levels[v->type]);
}
--- a/src/vehicle_type.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/vehicle_type.h Sun Apr 20 15:27:28 2008 +0000
@@ -14,7 +14,7 @@
VEH_ROAD,
VEH_SHIP,
VEH_AIRCRAFT,
- VEH_SPECIAL,
+ VEH_EFFECT,
VEH_DISASTER,
VEH_END,
VEH_INVALID = 0xFF,
@@ -38,20 +38,6 @@
static const VehicleID INVALID_VEHICLE = 0xFFFF;
-/* Effect vehicle types */
-enum EffectVehicle {
- EV_CHIMNEY_SMOKE = 0,
- EV_STEAM_SMOKE = 1,
- EV_DIESEL_SMOKE = 2,
- EV_ELECTRIC_SPARK = 3,
- EV_SMOKE = 4,
- EV_EXPLOSION_LARGE = 5,
- EV_BREAKDOWN_SMOKE = 6,
- EV_EXPLOSION_SMALL = 7,
- EV_BULLDOZER = 8,
- EV_BUBBLE = 9
-};
-
/** Pathfinding option states */
enum {
VPF_OPF = 0, ///< The Original PathFinder
--- a/src/video/cocoa/wnd_quartz.mm Fri Apr 18 21:20:03 2008 +0000
+++ b/src/video/cocoa/wnd_quartz.mm Sun Apr 20 15:27:28 2008 +0000
@@ -175,7 +175,8 @@
CMCloseProfile(sysProfile);
}
- assert(colorSpace != NULL);
+ if (colorSpace == NULL)
+ error("Could not get system colour space. You might need to recalibrate your monitor.");
}
return colorSpace;
--- a/src/video/dedicated_v.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/video/dedicated_v.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -140,6 +140,7 @@
_screen.width = _screen.pitch = _cur_resolution[0];
_screen.height = _cur_resolution[1];
+ ScreenSizeChanged();
SetDebugString("net=6");
--- a/src/video/null_v.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/video/null_v.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -15,6 +15,8 @@
this->ticks = GetDriverParamInt(parm, "ticks", 1000);
_screen.width = _screen.pitch = _cur_resolution[0];
_screen.height = _cur_resolution[1];
+ ScreenSizeChanged();
+
/* Do not render, nor blit */
DEBUG(misc, 1, "Forcing blitter 'null'...");
BlitterFactoryBase::SelectBlitter("null");
--- a/src/video/sdl_v.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/video/sdl_v.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -127,8 +127,7 @@
for (i = 0; modes[i]; i++) {
int w = modes[i]->w;
int h = modes[i]->h;
- if (IsInsideMM(w, 640, MAX_SCREEN_WIDTH + 1) &&
- IsInsideMM(h, 480, MAX_SCREEN_HEIGHT + 1)) {
+ if (w >= 640 && h >= 480) {
int j;
for (j = 0; j < n; j++) {
if (_resolutions[j][0] == w && _resolutions[j][1] == h) break;
@@ -419,8 +418,8 @@
break;
case SDL_VIDEORESIZE: {
- int w = Clamp(ev.resize.w, 64, MAX_SCREEN_WIDTH);
- int h = Clamp(ev.resize.h, 64, MAX_SCREEN_HEIGHT);
+ int w = max(ev.resize.w, 64);
+ int h = max(ev.resize.h, 64);
ChangeResInGame(w, h);
break;
}
--- a/src/video/win32_v.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/video/win32_v.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -545,8 +545,8 @@
w = r->right - r->left - (r2.right - r2.left);
h = r->bottom - r->top - (r2.bottom - r2.top);
- w = Clamp(w, 64, MAX_SCREEN_WIDTH);
- h = Clamp(h, 64, MAX_SCREEN_HEIGHT);
+ w = max(w, 64);
+ h = max(h, 64);
SetRect(&r2, 0, 0, w, h);
AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
@@ -677,8 +677,8 @@
HDC dc;
int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
- w = Clamp(w, 64, MAX_SCREEN_WIDTH);
- h = Clamp(h, 64, MAX_SCREEN_HEIGHT);
+ w = max(w, 64);
+ h = max(h, 64);
if (bpp == 0) error("Can't use a blitter that blits 0 bpp for normal visuals");
@@ -737,8 +737,8 @@
* Doesn't really matter since we don't pass a string anyways, but still
* a letdown */
for (i = 0; EnumDisplaySettingsA(NULL, i, &dm) != 0; i++) {
- if (dm.dmBitsPerPel == BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() && IsInsideMM(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH + 1) &&
- IsInsideMM(dm.dmPelsHeight, 480, MAX_SCREEN_HEIGHT + 1)) {
+ if (dm.dmBitsPerPel == BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() &&
+ dm.dmPelsWidth >= 640 && dm.dmPelsHeight >= 480) {
uint j;
for (j = 0; j < n; j++) {
@@ -787,10 +787,10 @@
_wnd.height_org = _cur_resolution[1];
AllocateDibSection(_cur_resolution[0], _cur_resolution[1]);
+ MakeWindow(_fullscreen);
+
MarkWholeScreenDirty();
- MakeWindow(_fullscreen);
-
return NULL;
}
--- a/src/viewport.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/viewport.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -159,7 +159,19 @@
w->viewport = NULL;
}
-void AssignWindowViewport(Window *w, int x, int y,
+/**
+ * Initialize viewport of the window for use.
+ * @param w Window to use/display the viewport in
+ * @param x Offset of left edge of viewport with respect to left edge window \a w
+ * @param y Offset of top edge of viewport with respect to top edge window \a w
+ * @param width Width of the viewport
+ * @param height Height of the viewport
+ * @param follow_flags Flags controlling the viewport.
+ * - If bit 31 is set, the lower 16 bits are the vehicle that the viewport should follow.
+ * - If bit 31 is clear, it is a tile position.
+ * @param zoom Zoomlevel to display
+ */
+void InitializeWindowViewport(Window *w, int x, int y,
int width, int height, uint32 follow_flags, ZoomLevel zoom)
{
assert(w->viewport == NULL);
@@ -325,7 +337,14 @@
}
}
-
+/**
+ * Is a xy position inside the viewport of the window?
+ * @param w Window to examine its viewport
+ * @param x X coordinate of the xy position
+ * @param y Y coordinate of the xy position
+ * @return Pointer to the viewport if the xy position is in the viewport of the window,
+ * otherwise \c NULL is returned.
+ */
ViewPort *IsPtInWindowViewport(const Window *w, int x, int y)
{
ViewPort *vp = w->viewport;
@@ -1617,11 +1636,12 @@
}
/**
- * Marks a viewport as dirty for repaint.
- *
- * @param vp The viewport to mark as dirty
- * @todo documents the missing parameters @c left, @c top, @c right and @c bottom
- * @todo detailed description missing
+ * Marks a viewport as dirty for repaint if it displays (a part of) the area the needs to be repainted.
+ * @param vp The viewport to mark as dirty
+ * @param left Left edge of area to repaint
+ * @param top Top edge of area to repaint
+ * @param right Right edge of area to repaint
+ * @param bottom Bottom edge of area to repaint
* @ingroup dirty
*/
static void MarkViewportDirty(const ViewPort *vp, int left, int top, int right, int bottom)
@@ -1648,6 +1668,14 @@
);
}
+/**
+ * Mark all viewports that display an area as dirty (in need of repaint).
+ * @param left Left edge of area to repaint
+ * @param top Top edge of area to repaint
+ * @param right Right edge of area to repaint
+ * @param bottom Bottom edge of area to repaint
+ * @ingroup dirty
+ */
void MarkAllViewportsDirty(int left, int top, int right, int bottom)
{
Window **wz;
--- a/src/viewport_func.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/viewport_func.h Sun Apr 20 15:27:28 2008 +0000
@@ -13,7 +13,7 @@
void SetSelectionRed(bool);
void DeleteWindowViewport(Window *w);
-void AssignWindowViewport(Window *w, int x, int y, int width, int height, uint32 follow_flags, ZoomLevel zoom);
+void InitializeWindowViewport(Window *w, int x, int y, int width, int height, uint32 follow_flags, ZoomLevel zoom);
ViewPort *IsPtInWindowViewport(const Window *w, int x, int y);
Point GetTileBelowCursor();
void UpdateViewportPosition(Window *w);
--- a/src/water_cmd.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/water_cmd.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -39,6 +39,7 @@
#include "station_base.h"
#include "airport.h"
#include "newgrf_cargo.h"
+#include "effectvehicle_func.h"
#include "table/sprites.h"
#include "table/strings.h"
--- a/src/window.cpp Fri Apr 18 21:20:03 2008 +0000
+++ b/src/window.cpp Sun Apr 20 15:27:28 2008 +0000
@@ -303,6 +303,7 @@
}
}
+ /* Setup blitter, and dispatch a repaint event to window *wz */
DrawPixelInfo *dp = _cur_dpi;
dp->width = right - left;
dp->height = bottom - top;
@@ -334,6 +335,7 @@
bottom > w->top &&
left < w->left + w->width &&
top < w->top + w->height) {
+ /* Window w intersects with the rectangle => needs repaint */
DrawOverlappedWindow(wz, left, top, right, bottom);
}
}
@@ -398,7 +400,8 @@
}
/**
- * Remove window and all its child windows from the window stack
+ * Remove window and all its child windows from the window stack.
+ * @param w Window to delete
*/
void DeleteWindow(Window *w)
{
@@ -622,11 +625,11 @@
{
Window* const *wz;
- for (wz = _z_windows;; wz++) {
+ FOR_ALL_WINDOWS(wz) {
Window *w = *wz;
- assert(wz < _last_z_window);
if (w->window_class != WC_MAIN_WINDOW && !IsVitalWindow(w)) return w;
}
+ NOT_REACHED();
}
bool IsWindowOfPrototype(const Window *w, const Widget *widget)
@@ -1018,9 +1021,7 @@
* @return a pointer to the found window if any, NULL otherwise */
Window *FindWindowFromPt(int x, int y)
{
- Window* const *wz;
-
- for (wz = _last_z_window; wz != _z_windows;) {
+ for (Window * const *wz = _last_z_window; wz != _z_windows;) {
Window *w = *--wz;
if (IsInsideBS(x, w->left, w->width) && IsInsideBS(y, w->top, w->height)) {
return w;
@@ -1038,6 +1039,7 @@
IConsoleClose();
_last_z_window = _z_windows;
+ _mouseover_last_w = NULL;
_no_scroll = 0;
}
@@ -1604,8 +1606,7 @@
static bool MaybeBringWindowToFront(const Window *w)
{
bool bring_to_front = false;
- Window* const *wz;
- Window* const *uz;
+ Window * const *wz;
if (w->window_class == WC_MAIN_WINDOW ||
IsVitalWindow(w) ||
@@ -1615,7 +1616,7 @@
}
wz = FindWindowZPosition(w);
- for (uz = wz; ++uz != _last_z_window;) {
+ for (Window * const *uz = wz; ++uz != _last_z_window;) {
Window *u = *uz;
/* A modal child will prevent the activation of the parent window */
@@ -1789,9 +1790,6 @@
}
}
-extern void UpdateTileSelection();
-extern bool VpHandlePlaceSizingDrag();
-
/**
* Local counter that is incremented each time an mouse input event is detected.
* The counter is used to stop auto-scrolling.
@@ -1852,6 +1850,9 @@
TIME_BETWEEN_DOUBLE_CLICK = 500, ///< Time between 2 left clicks before it becoming a double click, in ms
};
+extern void UpdateTileSelection();
+extern bool VpHandlePlaceSizingDrag();
+
void MouseLoop(MouseClick click, int mousewheel)
{
int x,y;
@@ -2064,8 +2065,9 @@
}
/**
- * Mark window data as invalid (in need of re-computing)
- * @param w Window with invalid data
+ * Mark window as dirty (in need of repainting)
+ * @param cls Window class
+ * @param number Window number in that class
*/
void InvalidateWindow(WindowClass cls, WindowNumber number)
{
@@ -2077,7 +2079,7 @@
}
}
-/*
+/**
* Mark a particular widget in a particular window as dirty (in need of repainting)
* @param cls Window class
* @param number Window number in that class
@@ -2095,7 +2097,7 @@
}
}
-/*
+/**
* Mark all windows of a particular class as dirty (in need of repainting)
* @param cls Window class
*/
@@ -2119,7 +2121,7 @@
}
/**
- * Mark window data the window of a given class and specific window number as invalid (in need of re-computing)
+ * Mark window data of the window of a given class and specific window number as invalid (in need of re-computing)
* @param cls Window class
* @param number Window number within the class
*/
@@ -2151,13 +2153,17 @@
*/
void CallWindowTickEvent()
{
- Window* const *wz;
-
- for (wz = _last_z_window; wz != _z_windows;) {
+ for (Window * const *wz = _last_z_window; wz != _z_windows;) {
CallWindowEventNP(*--wz, WE_TICK);
}
}
+/**
+ * Try to delete a non-vital window.
+ * Non-vital windows are windows other than the game selection, main toolbar,
+ * status bar, toolbar menu, and tooltip windows. Stickied windows are also
+ * considered vital.
+ */
void DeleteNonVitalWindows()
{
Window* const *wz;
--- a/src/window_func.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/window_func.h Sun Apr 20 15:27:28 2008 +0000
@@ -32,7 +32,6 @@
void DeleteAllNonVitalWindows();
void HideVitalWindows();
void ShowVitalWindows();
-Window **FindWindowZPosition(const Window *w);
void InvalidateWindow(WindowClass cls, WindowNumber number);
void InvalidateWindowWidget(WindowClass cls, WindowNumber number, byte widget_index);
--- a/src/window_gui.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/window_gui.h Sun Apr 20 15:27:28 2008 +0000
@@ -549,15 +549,9 @@
bool IsWindowOfPrototype(const Window *w, const Widget *widget);
void AssignWidgetToWindow(Window *w, const Widget *widget);
-Window *AllocateWindow(
- int x,
- int y,
- int width,
- int height,
- WindowProc *proc,
- WindowClass cls,
- const Widget *widget,
- void *data = NULL);
+Window *AllocateWindow(int x, int y, int width, int height,
+ WindowProc *proc, WindowClass cls, const Widget *widget,
+ void *data = NULL);
Window *AllocateWindowDesc(const WindowDesc *desc, void *data = NULL);
Window *AllocateWindowDescFront(const WindowDesc *desc, int window_number, void *data = NULL);
@@ -594,12 +588,6 @@
void DrawSortButtonState(const Window *w, int widget, SortButtonState state);
-Window *GetCallbackWnd();
-void DeleteNonVitalWindows();
-void DeleteAllNonVitalWindows();
-void HideVitalWindows();
-void ShowVitalWindows();
-Window **FindWindowZPosition(const Window *w);
/* window.cpp */
extern Window *_z_windows[];
@@ -624,6 +612,13 @@
WSM_PRESIZE = 3,
};
+Window *GetCallbackWnd();
+void DeleteNonVitalWindows();
+void DeleteAllNonVitalWindows();
+void HideVitalWindows();
+void ShowVitalWindows();
+Window **FindWindowZPosition(const Window *w);
+
void ScrollbarClickHandler(Window *w, const Widget *wi, int x, int y);
void ResizeButtons(Window *w, byte left, byte right);
--- a/src/zoom_func.h Fri Apr 18 21:20:03 2008 +0000
+++ b/src/zoom_func.h Sun Apr 20 15:27:28 2008 +0000
@@ -1,6 +1,6 @@
/* $Id$ */
-/** @file zoom_func.hpp */
+/** @file zoom_func.h */
#ifndef ZOOM_FUNC_H
#define ZOOM_FUNC_H