mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r14385) [0.6] -Backport from trunk:
- Fix: Invalid v->u.air.targetairport could cause crashes at several places [FS#2300] (r14383, r14344, r14343) - Fix: Moving the first vehicle of a train elsewhere might require a new unitnumber for the remaining chain which might not be available (r14384) - Fix: Trams jumping when reversing on a single trambit (like caused during road construction reworks) or when (manually) reversing in a corner [FS#1852] (r14371) - Fix: Multiheaded parts in free wagon chains weren't connected (could cause desyncs) (r14366, r14362) - Fix: [Win32] Some keypress combinations could be handled twice [FS#2206] (r14363) - Fix: The ownership of roadtiles was not properly set for very old savegames (including TTD's) making it impossible to remove some pieces of road [FS#2311] (r14359) - Fix: Desync due to randomly ordered vehicle hash by flooding and road vehicle overtake/following (r14356, r14258) - Fix: Signs were not updated on company bankrupcy/sell, and thus could have the colour of invalid player (r14348) - Fix: Delete the RenameSignWindow when 'its' sign is deleted (r14345)
This commit is contained in:
parent
456b479a21
commit
68fe4d71e1
|
@ -91,10 +91,10 @@ elif [ -d "$ROOT_DIR/.hg" ]; then
|
|||
if [ -n "`hg status \"$SRC_DIR\" | grep -v '^?'`" ]; then
|
||||
MODIFIED="2"
|
||||
fi
|
||||
HASH=`LC_ALL=C hg tip 2>/dev/null | head -n 1 | cut -d: -f3 | cut -c1-8`
|
||||
HASH=`LC_ALL=C hg parents 2>/dev/null | head -n 1 | cut -d: -f3 | cut -c1-8`
|
||||
REV="h$HASH"
|
||||
BRANCH=`hg branch | sed 's/^default$//'`
|
||||
REV_NR=`LC_ALL=C hg log -k "svn" -l 1 --template "{desc}\n" "$SRC_DIR" | grep "^(svn r[0-9]*)" | head -n 1 | sed "s/.*(svn r\([0-9]*\)).*/\1/"`
|
||||
REV_NR=`LC_ALL=C hg log -r $HASH:0 -k "svn" -l 1 --template "{desc}\n" "$SRC_DIR" | grep "^(svn r[0-9]*)" | head -n 1 | sed "s/.*(svn r\([0-9]*\)).*/\1/"`
|
||||
else
|
||||
# We don't know
|
||||
MODIFIED="1"
|
||||
|
|
|
@ -41,7 +41,7 @@ Sub UpdateFiles(version)
|
|||
revision = Mid(revision, 1, InStr(revision, "-") - 1)
|
||||
End If
|
||||
Case "h" ' mercurial (hg)
|
||||
Set oExec = WshShell.Exec("hg log -k " & Chr(34) & "svn" & Chr(34) & " -l 1 --template " & Chr(34) & "{desc}\n" & Chr(34) & " ../src")
|
||||
Set oExec = WshShell.Exec("hg log -r " & Mid(version, 2, 8) & ":0 -k " & Chr(34) & "svn" & Chr(34) & " -l 1 --template " & Chr(34) & "{desc}\n" & Chr(34) & " ../src")
|
||||
If Err.Number = 0 Then
|
||||
revision = Mid(OExec.StdOut.ReadLine(), 7)
|
||||
revision = Mid(revision, 1, InStr(revision, ")") - 1)
|
||||
|
@ -207,7 +207,7 @@ Function DetermineSVNVersion()
|
|||
Else
|
||||
' try mercurial (hg)
|
||||
Err.Clear
|
||||
Set oExec = WshShell.Exec("hg tip")
|
||||
Set oExec = WshShell.Exec("hg parents")
|
||||
If Err.Number = 0 Then
|
||||
' Wait till the application is finished ...
|
||||
Do While oExec.Status = 0
|
||||
|
|
|
@ -1059,10 +1059,8 @@ static bool AircraftController(Vehicle *v)
|
|||
{
|
||||
int count;
|
||||
|
||||
StationID target = v->u.air.targetairport;
|
||||
|
||||
/* NULL if station is invalid */
|
||||
const Station *st = IsValidStationID(target) ? GetStation(target) : NULL;
|
||||
const Station *st = IsValidStationID(v->u.air.targetairport) ? GetStation(v->u.air.targetairport) : NULL;
|
||||
/* 0 if there is no station */
|
||||
TileIndex tile = 0;
|
||||
if (st != NULL) {
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "signal_func.h"
|
||||
#include "gfx_func.h"
|
||||
#include "autoreplace_func.h"
|
||||
#include "signs.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/sprites.h"
|
||||
|
@ -469,6 +470,11 @@ void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player)
|
|||
}
|
||||
}
|
||||
|
||||
Sign *si;
|
||||
FOR_ALL_SIGNS(si) {
|
||||
if (si->owner == old_player) si->owner = new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player;
|
||||
}
|
||||
|
||||
/* Change color of existing windows */
|
||||
if (new_player != PLAYER_SPECTATOR) ChangeWindowOwner(old_player, new_player);
|
||||
|
||||
|
|
|
@ -685,9 +685,12 @@ void UpdateFillingPercent(TextEffectID te_id, uint8 percent, StringID string)
|
|||
UpdateTextEffect(te_id, string);
|
||||
}
|
||||
|
||||
void HideFillingPercent(TextEffectID te_id)
|
||||
void HideFillingPercent(TextEffectID *te_id)
|
||||
{
|
||||
if (te_id != INVALID_TE_ID) RemoveTextEffect(te_id);
|
||||
if (*te_id == INVALID_TE_ID) return;
|
||||
|
||||
RemoveTextEffect(*te_id);
|
||||
*te_id = INVALID_TE_ID;
|
||||
}
|
||||
|
||||
static const Widget _tooltips_widgets[] = {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "direction_func.h"
|
||||
#include "rail_map.h"
|
||||
#include "rail.h"
|
||||
#include "aircraft.h"
|
||||
|
||||
|
||||
int _traininfo_vehicle_pitch = 0;
|
||||
|
@ -215,8 +216,8 @@ enum {
|
|||
*/
|
||||
static byte MapAircraftMovementState(const Vehicle *v)
|
||||
{
|
||||
const Station *st = GetStation(v->u.air.targetairport);
|
||||
if (st->airport_tile == 0) return AMS_TTDP_FLIGHT_TO_TOWER;
|
||||
const Station *st = GetTargetAirportIfValid(v);
|
||||
if (st == NULL) return AMS_TTDP_FLIGHT_TO_TOWER;
|
||||
|
||||
const AirportFTAClass *afc = st->Airport();
|
||||
uint16 amdflag = afc->MovingData(v->u.air.pos)->flag;
|
||||
|
@ -552,22 +553,26 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by
|
|||
{
|
||||
const Vehicle *w = v->Next();
|
||||
uint16 altitude = v->z_pos - w->z_pos; // Aircraft height - shadow height
|
||||
byte airporttype;
|
||||
byte airporttype = ATP_TTDP_LARGE;
|
||||
|
||||
switch (GetStation(v->u.air.targetairport)->airport_type) {
|
||||
/* Note, Helidepot and Helistation are treated as small airports
|
||||
* as they are at ground level. */
|
||||
case AT_HELIDEPOT:
|
||||
case AT_HELISTATION:
|
||||
case AT_COMMUTER:
|
||||
case AT_SMALL: airporttype = ATP_TTDP_SMALL; break;
|
||||
case AT_METROPOLITAN:
|
||||
case AT_INTERNATIONAL:
|
||||
case AT_INTERCON:
|
||||
case AT_LARGE: airporttype = ATP_TTDP_LARGE; break;
|
||||
case AT_HELIPORT: airporttype = ATP_TTDP_HELIPORT; break;
|
||||
case AT_OILRIG: airporttype = ATP_TTDP_OILRIG; break;
|
||||
default: airporttype = ATP_TTDP_LARGE; break;
|
||||
const Station *st = GetTargetAirportIfValid(v);
|
||||
|
||||
if (st != NULL) {
|
||||
switch (st->airport_type) {
|
||||
/* Note, Helidepot and Helistation are treated as small airports
|
||||
* as they are at ground level. */
|
||||
case AT_HELIDEPOT:
|
||||
case AT_HELISTATION:
|
||||
case AT_COMMUTER:
|
||||
case AT_SMALL: airporttype = ATP_TTDP_SMALL; break;
|
||||
case AT_METROPOLITAN:
|
||||
case AT_INTERNATIONAL:
|
||||
case AT_INTERCON:
|
||||
case AT_LARGE: airporttype = ATP_TTDP_LARGE; break;
|
||||
case AT_HELIPORT: airporttype = ATP_TTDP_HELIPORT; break;
|
||||
case AT_OILRIG: airporttype = ATP_TTDP_OILRIG; break;
|
||||
default: airporttype = ATP_TTDP_LARGE; break;
|
||||
}
|
||||
}
|
||||
|
||||
return (altitude << 8) | airporttype;
|
||||
|
|
|
@ -1188,8 +1188,8 @@ static void ConvertTownOwner()
|
|||
for (tile = 0; tile != MapSize(); tile++) {
|
||||
switch (GetTileType(tile)) {
|
||||
case MP_ROAD:
|
||||
if (GB(_m[tile].m5, 4, 2) == ROAD_TILE_CROSSING && HasBit(_m[tile].m4, 7)) {
|
||||
_m[tile].m4 = OWNER_TOWN;
|
||||
if (GB(_m[tile].m5, 4, 2) == ROAD_TILE_CROSSING && HasBit(_m[tile].m3, 7)) {
|
||||
_m[tile].m3 = OWNER_TOWN;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
|
@ -1596,7 +1596,7 @@ bool AfterLoadGame()
|
|||
|
||||
case MP_ROAD:
|
||||
_m[t].m4 |= (_m[t].m2 << 4);
|
||||
if (IsTileOwner(t, OWNER_TOWN)) {
|
||||
if ((GB(_m[t].m5, 4, 2) == ROAD_TILE_CROSSING ? (Owner)_m[t].m3 : GetTileOwner(t)) == OWNER_TOWN) {
|
||||
SetTownIndex(t, CalcClosestTownFromTile(t, (uint)-1)->index);
|
||||
} else {
|
||||
SetTownIndex(t, 0);
|
||||
|
@ -2477,6 +2477,15 @@ bool AfterLoadGame()
|
|||
}
|
||||
}
|
||||
|
||||
/* Just always run this for 0.6. Doesn't hurt to fix the owners a second time. */
|
||||
if (CheckSavegameVersion(103)) {
|
||||
/* signs with invalid owner left from older savegames */
|
||||
Sign *si;
|
||||
FOR_ALL_SIGNS(si) {
|
||||
if (si->owner != OWNER_NONE && !IsValidPlayer(si->owner) && GetPlayer(si->owner)->is_active) si->owner = OWNER_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
return InitializeWindowsAndCaches();
|
||||
}
|
||||
|
||||
|
|
|
@ -1282,7 +1282,7 @@ CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|||
|
||||
/* When not coverting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */
|
||||
if (!IsCompatibleRail(GetRailType(tile), totype) &&
|
||||
!HasVehicleOnTunnelBridge(tile, endtile)) continue;
|
||||
HasVehicleOnTunnelBridge(tile, endtile)) continue;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
SetRailType(tile, totype);
|
||||
|
|
|
@ -35,6 +35,10 @@ Sign::Sign(PlayerID owner)
|
|||
Sign::~Sign()
|
||||
{
|
||||
free(this->name);
|
||||
|
||||
if (CleaningPool()) return;
|
||||
|
||||
DeleteRenameSignWindow(this->index);
|
||||
this->owner = INVALID_PLAYER;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ void PlaceProc_Sign(TileIndex tile);
|
|||
|
||||
/* signs_gui.cpp */
|
||||
void ShowRenameSignWindow(const Sign *si);
|
||||
|
||||
void DeleteRenameSignWindow(SignID sign);
|
||||
void ShowSignList();
|
||||
|
||||
#endif /* SIGNS_H */
|
||||
|
|
|
@ -251,8 +251,9 @@ static void QuerySignEditWndProc(Window *w, WindowEvent *e)
|
|||
|
||||
case QUERY_EDIT_SIGN_WIDGET_DELETE:
|
||||
/* Only need to set the buffer to null, the rest is handled as the OK button */
|
||||
DeleteTextBufferAll(&qs->text);
|
||||
/* FALL THROUGH */
|
||||
RenameSign(qs->cur_sign, "");
|
||||
/* don't delete this, we are deleted in Sign::~Sign() -> DeleteRenameSignWindow() */
|
||||
break;
|
||||
|
||||
case QUERY_EDIT_SIGN_WIDGET_OK:
|
||||
RenameSign(qs->cur_sign, qs->text.buf);
|
||||
|
@ -325,5 +326,9 @@ void ShowRenameSignWindow(const Sign *si)
|
|||
UpdateSignEditWindow(w, si);
|
||||
}
|
||||
|
||||
void DeleteRenameSignWindow(SignID sign)
|
||||
{
|
||||
const Window *w = FindWindowById(WC_QUERY_STRING, 0);
|
||||
|
||||
|
||||
if (w != NULL && WP(w, editsign_d).cur_sign == sign) delete w;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,6 @@ void UndrawChatMessage();
|
|||
/* misc_gui.cpp */
|
||||
TextEffectID ShowFillingPercent(int x, int y, int z, uint8 percent, StringID color);
|
||||
void UpdateFillingPercent(TextEffectID te_id, uint8 percent, StringID color);
|
||||
void HideFillingPercent(TextEffectID te_id);
|
||||
void HideFillingPercent(TextEffectID *te_id);
|
||||
|
||||
#endif /* TEXTEFF_HPP */
|
||||
|
|
|
@ -1123,6 +1123,14 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p
|
|||
if (flags & DC_EXEC) src->unitnumber = unit_num;
|
||||
}
|
||||
|
||||
/* When we move the front vehicle, the second vehicle might need a unitnumber */
|
||||
if (!HasBit(p2, 0) && (IsFreeWagon(src) || IsFrontEngine(src)) && (flags & DC_AUTOREPLACE) == 0) {
|
||||
Vehicle *second = GetNextUnit(src);
|
||||
if (second != NULL && IsTrainEngine(second) && GetFreeUnitNumber(VEH_TRAIN) > _patches.max_trains) {
|
||||
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the vehicles in the source chain are in the destination
|
||||
* chain. This can easily be done by checking whether the first vehicle
|
||||
|
@ -1962,6 +1970,7 @@ CommandCost CmdReverseTrainDirection(TileIndex tile, uint32 flags, uint32 p1, ui
|
|||
} else {
|
||||
v->cur_speed = 0;
|
||||
SetLastSpeed(v, 0);
|
||||
HideFillingPercent(&v->fill_percent_te_id);
|
||||
ReverseTrainDirection(v);
|
||||
}
|
||||
}
|
||||
|
@ -3850,9 +3859,23 @@ void ConnectMultiheadedTrains()
|
|||
}
|
||||
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
|
||||
Vehicle *u = v;
|
||||
if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) {
|
||||
/* Two ways to associate multiheaded parts to each other:
|
||||
* sequential-matching: Trains shall be arranged to look like <..>..<..>..<..>..
|
||||
* bracket-matching: Free vehicle chains shall be arranged to look like ..<..<..>..<..>..>..
|
||||
*
|
||||
* Note: Old savegames might contain chains which do not comply with these rules, e.g.
|
||||
* - the front and read parts have invalid orders
|
||||
* - different engine types might be combined
|
||||
* - there might be different amounts of front and rear parts.
|
||||
*
|
||||
* Note: The multiheaded parts need to be matched exactly like they are matched on the server, else desyncs will occur.
|
||||
* This is why two matching strategies are needed.
|
||||
*/
|
||||
|
||||
bool sequential_matching = IsFrontEngine(v);
|
||||
|
||||
Vehicle *u = v;
|
||||
BEGIN_ENUM_WAGONS(u) {
|
||||
if (u->u.rail.other_multiheaded_part != NULL) continue; // we already linked this one
|
||||
|
||||
|
@ -3863,14 +3886,35 @@ void ConnectMultiheadedTrains()
|
|||
u->spritenum--;
|
||||
}
|
||||
|
||||
/* Find a matching back part */
|
||||
EngineID eid = u->engine_type;
|
||||
Vehicle *w;
|
||||
for (w = u->Next(); w != NULL && (w->engine_type != u->engine_type || w->u.rail.other_multiheaded_part != NULL); w = GetNextVehicle(w)) {}
|
||||
if (w != NULL) {
|
||||
/* we found a car to partner with this engine. Now we will make sure it face the right way */
|
||||
if (IsTrainEngine(w)) {
|
||||
ClearTrainEngine(w);
|
||||
w->spritenum++;
|
||||
if (sequential_matching) {
|
||||
for (w = GetNextVehicle(u); w != NULL; w = GetNextVehicle(w)) {
|
||||
if (w->engine_type != eid || w->u.rail.other_multiheaded_part != NULL || !IsMultiheaded(w)) continue;
|
||||
|
||||
/* we found a car to partner with this engine. Now we will make sure it face the right way */
|
||||
if (IsTrainEngine(w)) {
|
||||
ClearTrainEngine(w);
|
||||
w->spritenum++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
uint stack_pos = 0;
|
||||
for (w = GetNextVehicle(u); w != NULL; w = GetNextVehicle(w)) {
|
||||
if (w->engine_type != eid || w->u.rail.other_multiheaded_part != NULL || !IsMultiheaded(w)) continue;
|
||||
|
||||
if (IsTrainEngine(w)) {
|
||||
stack_pos++;
|
||||
} else {
|
||||
if (stack_pos == 0) break;
|
||||
stack_pos--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (w != NULL) {
|
||||
w->u.rail.other_multiheaded_part = u;
|
||||
u->u.rail.other_multiheaded_part = w;
|
||||
} else {
|
||||
|
|
|
@ -616,8 +616,7 @@ void Vehicle::PreDestructor()
|
|||
if (IsValidStationID(this->last_station_visited)) {
|
||||
GetStation(this->last_station_visited)->loading_vehicles.remove(this);
|
||||
|
||||
HideFillingPercent(this->fill_percent_te_id);
|
||||
this->fill_percent_te_id = INVALID_TE_ID;
|
||||
HideFillingPercent(&this->fill_percent_te_id);
|
||||
}
|
||||
|
||||
if (IsEngineCountable(this)) {
|
||||
|
@ -3240,8 +3239,7 @@ void Vehicle::LeaveStation()
|
|||
current_order.flags = 0;
|
||||
GetStation(this->last_station_visited)->loading_vehicles.remove(this);
|
||||
|
||||
HideFillingPercent(this->fill_percent_te_id);
|
||||
this->fill_percent_te_id = INVALID_TE_ID;
|
||||
HideFillingPercent(&this->fill_percent_te_id);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -463,8 +463,6 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
|
|||
return 0;
|
||||
|
||||
case WM_CHAR: {
|
||||
/* Silently drop all non-text messages as those were handled by WM_KEYDOWN */
|
||||
if (wParam < VK_SPACE) return 0;
|
||||
uint scancode = GB(lParam, 16, 8);
|
||||
uint charcode = wParam;
|
||||
|
||||
|
@ -490,12 +488,13 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
|
|||
case WM_KEYDOWN: {
|
||||
keycode = MapWindowsKey(wParam);
|
||||
|
||||
/* Silently drop all text messages as those will be handled by WM_CHAR
|
||||
* WM_KEYDOWN only handles CTRL+ commands and special keys like VK_LEFT, etc. */
|
||||
if (keycode == 0 || (keycode > WKC_PAUSE && GB(keycode, 13, 4) == 0)) return 0;
|
||||
|
||||
/* Keys handled in WM_CHAR */
|
||||
if ((uint)(GB(keycode, 0, 12) - WKC_NUM_DIV) <= WKC_MINUS - WKC_NUM_DIV) return 0;
|
||||
/* Silently drop all messages handled by WM_CHAR. */
|
||||
MSG msg;
|
||||
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
|
||||
if (msg.message == WM_CHAR && GB(lParam, 16, 8) == GB(msg.lParam, 16, 8)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
HandleKeypress(0 | (keycode << 16));
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue