summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpeter1138 <peter1138@openttd.org>2009-01-06 14:45:38 +0000
committerpeter1138 <peter1138@openttd.org>2009-01-06 14:45:38 +0000
commitc0efc759efe2d1d31f7b4be7a69594800e96fe93 (patch)
treeb15421b827c35a0f165f46308277f43ad88ef9de
parent680175fea01b74a8ba9884c162248302979e4032 (diff)
downloadopenttd-c0efc759efe2d1d31f7b4be7a69594800e96fe93.tar.xz
(svn r14869) -Feature: Allow road vehicles to move multiple steps in a tick (code based on train movement code) and add support for RV prop 15. This gives RVs a maximum speed of 318mph instead 79mph. This only implements higher speeds, not 'realistic acceleration'.
-rw-r--r--src/engine_type.h2
-rw-r--r--src/newgrf.cpp14
-rw-r--r--src/roadveh_cmd.cpp68
3 files changed, 58 insertions, 26 deletions
diff --git a/src/engine_type.h b/src/engine_type.h
index 5f6cdd271..8c681216e 100644
--- a/src/engine_type.h
+++ b/src/engine_type.h
@@ -96,7 +96,7 @@ struct RoadVehicleInfo {
byte running_cost;
byte running_cost_class;
SoundFxByte sfx;
- byte max_speed;
+ uint16 max_speed; ///< Maximum speed in mph/3.2 units
byte capacity;
CargoID cargo_type;
};
diff --git a/src/newgrf.cpp b/src/newgrf.cpp
index 13415f97b..e0cff5836 100644
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -104,6 +104,7 @@ enum {
struct GRFTempEngineData {
uint16 cargo_allowed;
uint16 cargo_disallowed;
+ uint8 rv_max_speed; ///< Temporary storage of RV prop 15, maximum speed in mph/0.8
};
static GRFTempEngineData *_gted;
@@ -790,7 +791,6 @@ static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop
case 0x13: // Power in 10hp
case 0x14: // Weight in 1/4 tons
- case 0x15: // Speed in mph*0.8
/** @todo Support for road vehicles realistic power
* computations (called rvpower in TTDPatch) is just
* missing in OTTD yet. --pasky */
@@ -798,6 +798,10 @@ static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop
ret = CIR_UNHANDLED;
break;
+ case 0x15: // Speed in mph/0.8
+ _gted[e->index].rv_max_speed = grf_load_byte(&buf);
+ break;
+
case 0x16: // Cargos available for refitting
ei->refit_mask = grf_load_dword(&buf);
break;
@@ -6027,6 +6031,14 @@ static void AfterLoadGRFs()
/* Load old shore sprites in new position, if they were replaced by ActionA */
ActivateOldShore();
+ Engine *e;
+ FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
+ if (_gted[e->index].rv_max_speed != 0) {
+ /* Set RV maximum speed from the mph/0.8 unit value */
+ e->u.road.max_speed = _gted[e->index].rv_max_speed * 4;
+ }
+ }
+
/* Deallocate temporary loading data */
free(_gted);
_grm_sprites.clear();
diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp
index bc5414f0d..b0d5407e0 100644
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -625,7 +625,7 @@ static void RoadVehCrash(Vehicle *v)
SndPlayVehicleFx(SND_12_EXPLOSION, v);
}
-static void RoadVehCheckTrainCrash(Vehicle *v)
+static bool RoadVehCheckTrainCrash(Vehicle *v)
{
for (Vehicle *u = v; u != NULL; u = u->Next()) {
if (u->u.road.state == RVSB_WORMHOLE) continue;
@@ -636,9 +636,11 @@ static void RoadVehCheckTrainCrash(Vehicle *v)
if (HasVehicleOnPosXY(v->x_pos, v->y_pos, u, EnumCheckRoadVehCrashTrain)) {
RoadVehCrash(v);
- return;
+ return true;
}
}
+
+ return false;
}
static void HandleBrokenRoadVeh(Vehicle *v)
@@ -812,35 +814,39 @@ static void RoadVehArrivesAt(const Vehicle* v, Station* st)
}
}
-static bool RoadVehAccelerate(Vehicle *v)
+static int RoadVehAccelerate(Vehicle *v)
{
- uint spd = v->cur_speed + 1 + (v->u.road.overtaking != 0 ? 1 : 0);
- byte t;
+ uint oldspeed = v->cur_speed;
+ uint accel = 256 + (v->u.road.overtaking != 0 ? 256 : 0);
+ uint spd = v->subspeed + accel;
+
+ v->subspeed = (uint8)spd;
+
+ int tempmax = v->max_speed;
+ if (v->cur_speed > v->max_speed) {
+ tempmax = v->cur_speed - (v->cur_speed / 10) - 1;
+ }
+
+ v->cur_speed = spd = Clamp(v->cur_speed + ((int)spd >> 8), 0, tempmax);
- /* Clamp */
- spd = min(spd, v->max_speed);
+ /* Apply bridge speed limit */
if (v->u.road.state == RVSB_WORMHOLE && !(v->vehstatus & VS_HIDDEN)) {
- spd = min(spd, GetBridgeSpec(GetBridgeType(v->tile))->speed * 2);
+ v->cur_speed = min(v->cur_speed, GetBridgeSpec(GetBridgeType(v->tile))->speed * 2);
}
- /* updates statusbar only if speed have changed to save CPU time */
- if (spd != v->cur_speed) {
- v->cur_speed = spd;
+ /* Update statusbar only if speed has changed to save CPU time */
+ if (oldspeed != v->cur_speed) {
if (_settings_client.gui.vehicle_speed) {
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
}
}
- /* Decrease somewhat when turning */
- if (!(v->direction & 1)) spd = spd * 3 >> 2;
+ /* Speed is scaled in the same manner as for trains. @see train_cmd.cpp */
+ int scaled_spd = spd * 3 >> 2;
- if (spd == 0) return false;
-
- if ((byte)++spd == 0) return true;
-
- v->progress = (t = v->progress) - (byte)spd;
-
- return (t < v->progress);
+ scaled_spd += v->progress;
+ v->progress = 0;
+ return scaled_spd;
}
static Direction RoadVehGetNewDirection(const Vehicle* v, int x, int y)
@@ -1831,12 +1837,26 @@ static void RoadVehController(Vehicle *v)
if (v->IsInDepot() && RoadVehLeaveDepot(v, true)) return;
- /* Check if vehicle needs to proceed, return if it doesn't */
- if (!RoadVehAccelerate(v)) return;
+ /* Check how far the vehicle needs to proceed */
+ int j = RoadVehAccelerate(v);
+
+ int adv_spd = (v->direction & 1) ? 192 : 256;
+ while (j >= adv_spd) {
+ j -= adv_spd;
- for (Vehicle *prev = NULL; v != NULL; prev = v, v = v->Next()) {
- if (!IndividualRoadVehicleController(v, prev)) break;
+ Vehicle *u = v;
+ for (Vehicle *prev = NULL; u != NULL; prev = u, u = u->Next()) {
+ if (!IndividualRoadVehicleController(u, prev)) break;
+ }
+
+ /* 192 spd used for going straight, 256 for going diagonally. */
+ adv_spd = (v->direction & 1) ? 192 : 256;
+
+ /* Test for a collision, but only if another movement will occur. */
+ if (j >= adv_spd && RoadVehCheckTrainCrash(v)) break;
}
+
+ if (v->progress == 0) v->progress = j;
}
static void AgeRoadVehCargo(Vehicle *v)