mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-04 06:00:15 +00:00
(svn r20079) -Codechange [FS#3922]: Add helper functions to deal with the 192-256-magic of vehicle movement.
This commit is contained in:
parent
fabc6b567a
commit
35f4b4155e
@ -734,7 +734,8 @@ static int UpdateAircraftSpeed(Aircraft *v, uint speed_limit = SPEED_LIMIT_NONE,
|
||||
/* Adjust distance moved by plane speed setting */
|
||||
if (_settings_game.vehicle.plane_speed > 1) spd /= _settings_game.vehicle.plane_speed;
|
||||
|
||||
if (!(v->direction & 1)) spd = spd * 3 / 4;
|
||||
/* Convert direction-indepenent speed into direction-dependent speed. (old movement method) */
|
||||
spd = v->GetOldAdvanceSpeed(spd);
|
||||
|
||||
spd += v->progress;
|
||||
v->progress = (byte)spd;
|
||||
|
@ -756,6 +756,13 @@ static void RoadVehArrivesAt(const RoadVehicle *v, Station *st)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function looks at the vehicle and updates its speed (cur_speed
|
||||
* and subspeed) variables. Furthermore, it returns the distance that
|
||||
* the vehicle can drive this tick. #Vehicle::GetAdvanceDistance() determines
|
||||
* the distance to drive before moving a step on the map.
|
||||
* @return distance to drive.
|
||||
*/
|
||||
static int RoadVehAccelerate(RoadVehicle *v)
|
||||
{
|
||||
uint oldspeed = v->cur_speed;
|
||||
@ -786,8 +793,7 @@ static int RoadVehAccelerate(RoadVehicle *v)
|
||||
}
|
||||
}
|
||||
|
||||
/* Speed is scaled in the same manner as for trains. @see train_cmd.cpp */
|
||||
int scaled_spd = spd * 3 >> 2;
|
||||
int scaled_spd = v->GetAdvanceSpeed(spd);
|
||||
|
||||
scaled_spd += v->progress;
|
||||
v->progress = 0;
|
||||
@ -1595,7 +1601,7 @@ static bool RoadVehController(RoadVehicle *v)
|
||||
/* Check how far the vehicle needs to proceed */
|
||||
int j = RoadVehAccelerate(v);
|
||||
|
||||
int adv_spd = (v->direction & 1) ? 192 : 256;
|
||||
int adv_spd = v->GetAdvanceDistance();
|
||||
bool blocked = false;
|
||||
while (j >= adv_spd) {
|
||||
j -= adv_spd;
|
||||
@ -1609,8 +1615,8 @@ static bool RoadVehController(RoadVehicle *v)
|
||||
}
|
||||
if (blocked) break;
|
||||
|
||||
/* 192 spd used for going straight, 256 for going diagonally. */
|
||||
adv_spd = (v->direction & 1) ? 192 : 256;
|
||||
/* Determine distance to next map position */
|
||||
adv_spd = v->GetAdvanceDistance();
|
||||
|
||||
/* Test for a collision, but only if another movement will occur. */
|
||||
if (j >= adv_spd && RoadVehCheckTrainCrash(v)) break;
|
||||
|
@ -346,8 +346,8 @@ static bool ShipAccelerate(Vehicle *v)
|
||||
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
||||
}
|
||||
|
||||
/* Decrease somewhat when turning */
|
||||
if (!(v->direction & 1)) spd = spd * 3 / 4;
|
||||
/* Convert direction-indepenent speed into direction-dependent speed. (old movement method) */
|
||||
spd = v->GetOldAdvanceSpeed(spd);
|
||||
|
||||
if (spd == 0) return false;
|
||||
if ((byte)++spd == 0) return true;
|
||||
|
@ -2839,10 +2839,8 @@ void Train::MarkDirty()
|
||||
/**
|
||||
* This function looks at the vehicle and updates its speed (cur_speed
|
||||
* and subspeed) variables. Furthermore, it returns the distance that
|
||||
* the train can drive this tick. This distance is expressed as 256 * n,
|
||||
* where n is the number of straight (long) tracks the train can
|
||||
* traverse. This means that moving along a straight track costs 256
|
||||
* "speed" and a diagonal track costs 192 "speed".
|
||||
* the train can drive this tick. #Vehicle::GetAdvanceDistance() determines
|
||||
* the distance to drive before moving a step on the map.
|
||||
* @return distance to drive.
|
||||
*/
|
||||
int Train::UpdateSpeed()
|
||||
@ -2869,18 +2867,7 @@ int Train::UpdateSpeed()
|
||||
this->cur_speed = spd = Clamp(this->cur_speed + ((int)spd >> 8), 0, tempmax);
|
||||
}
|
||||
|
||||
/* Scale speed by 3/4. Previously this was only done when the train was
|
||||
* facing diagonally and would apply to however many moves the train made
|
||||
* regardless the of direction actually moved in. Now it is always scaled,
|
||||
* 256 spd is used to go straight and 192 is used to go diagonally
|
||||
* (3/4 of 256). This results in the same effect, but without the error the
|
||||
* previous method caused.
|
||||
*
|
||||
* The scaling is done in this direction and not by multiplying the amount
|
||||
* to be subtracted by 4/3 so that the leftover speed can be saved in a
|
||||
* byte in this->progress.
|
||||
*/
|
||||
int scaled_spd = spd * 3 >> 2;
|
||||
int scaled_spd = this->GetAdvanceSpeed(spd);
|
||||
|
||||
scaled_spd += this->progress;
|
||||
this->progress = 0; // set later in TrainLocoHandler or TrainController
|
||||
@ -3885,7 +3872,7 @@ static bool TrainLocoHandler(Train *v, bool mode)
|
||||
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
|
||||
}
|
||||
|
||||
int adv_spd = (v->direction & 1) ? 192 : 256;
|
||||
int adv_spd = v->GetAdvanceDistance();
|
||||
if (j < adv_spd) {
|
||||
/* if the vehicle has speed 0, update the last_speed field. */
|
||||
if (v->cur_speed == 0) SetLastSpeed(v, v->cur_speed);
|
||||
@ -3897,8 +3884,8 @@ static bool TrainLocoHandler(Train *v, bool mode)
|
||||
TrainController(v, NULL);
|
||||
/* Don't continue to move if the train crashed. */
|
||||
if (CheckTrainCollision(v)) break;
|
||||
/* 192 spd used for going straight, 256 for going diagonally. */
|
||||
adv_spd = (v->direction & 1) ? 192 : 256;
|
||||
/* Determine distance to next map position */
|
||||
adv_spd = v->GetAdvanceDistance();
|
||||
|
||||
/* No more moving this tick */
|
||||
if (j < adv_spd || v->cur_speed == 0) break;
|
||||
|
@ -226,6 +226,53 @@ public:
|
||||
*/
|
||||
virtual void UpdateDeltaXY(Direction direction) {}
|
||||
|
||||
/**
|
||||
* Determines the effective direction-specific vehicle movement speed.
|
||||
*
|
||||
* This method belongs to the old vehicle movement method:
|
||||
* A vehicle moves a step every 256 progress units.
|
||||
* The vehicle speed is scaled by 3/4 when moving in X or Y direction due to the longer distance.
|
||||
*
|
||||
* However, this method is slightly wrong in corners, as the leftover progress is not scaled correctly
|
||||
* when changing movement direction. #GetAdvanceSpeed() and #GetAdvanceDistance() are better wrt. this.
|
||||
*
|
||||
* @param speed Direction-independent unscaled speed.
|
||||
* @return speed scaled by movement direction. 256 units are required for each movement step.
|
||||
*/
|
||||
FORCEINLINE uint GetOldAdvanceSpeed(uint speed)
|
||||
{
|
||||
return (this->direction & 1) ? speed : speed * 3 / 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the effective vehicle movement speed.
|
||||
*
|
||||
* Together with #GetAdvanceDistance() this function is a replacement for #GetOldAdvanceSpeed().
|
||||
*
|
||||
* A vehicle progresses independent of it's movement direction.
|
||||
* However different amounts of "progress" are needed for moving a step in a specific direction.
|
||||
* That way the leftover progress does not need any adaption when changing movement direction.
|
||||
*
|
||||
* @param speed Direction-independent unscaled speed.
|
||||
* @return speed, scaled to match #GetAdvanceDistance().
|
||||
*/
|
||||
static FORCEINLINE uint GetAdvanceSpeed(uint speed)
|
||||
{
|
||||
return speed * 3 / 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the vehicle "progress" needed for moving a step.
|
||||
*
|
||||
* Together with #GetAdvanceSpeed() this function is a replacement for #GetOldAdvanceSpeed().
|
||||
*
|
||||
* @return distance to drive for a movement step on the map.
|
||||
*/
|
||||
FORCEINLINE uint GetAdvanceDistance()
|
||||
{
|
||||
return (this->direction & 1) ? 192 : 256;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the expense type associated to this vehicle type
|
||||
* @param income whether this is income or (running) expenses of the vehicle
|
||||
|
Loading…
Reference in New Issue
Block a user