train_cmd.c
changeset 5573 afa6f92a71fd
parent 5568 75f13d7bfaed
child 5588 1bcb6b4c01d8
equal deleted inserted replaced
5572:220d67208783 5573:afa6f92a71fd
    23 #include "sound.h"
    23 #include "sound.h"
    24 #include "depot.h"
    24 #include "depot.h"
    25 #include "waypoint.h"
    25 #include "waypoint.h"
    26 #include "vehicle_gui.h"
    26 #include "vehicle_gui.h"
    27 #include "train.h"
    27 #include "train.h"
       
    28 #include "bridge.h"
    28 #include "newgrf_callbacks.h"
    29 #include "newgrf_callbacks.h"
    29 #include "newgrf_engine.h"
    30 #include "newgrf_engine.h"
    30 #include "newgrf_sound.h"
    31 #include "newgrf_sound.h"
    31 #include "newgrf_text.h"
    32 #include "newgrf_text.h"
    32 #include "direction.h"
    33 #include "direction.h"
   103 		bool wagon_has_power = true;
   104 		bool wagon_has_power = true;
   104 
   105 
   105 		/* Power is not added for articulated parts */
   106 		/* Power is not added for articulated parts */
   106 		if (IsArticulatedPart(u)) continue;
   107 		if (IsArticulatedPart(u)) continue;
   107 
   108 
   108 		if (IsBridgeTile(u->tile) && IsBridgeMiddle(u->tile) && DiagDirToAxis(DirToDiagDir(u->direction)) == GetBridgeAxis(u->tile)) {
   109 		if (IsLevelCrossingTile(u->tile)) {
   109 			if (!HasPowerOnRail(u->u.rail.railtype, GetRailTypeOnBridge(u->tile))) engine_has_power = false;
       
   110 			if (!HasPowerOnRail(v->u.rail.railtype, GetRailTypeOnBridge(u->tile))) wagon_has_power = false;
       
   111 		} else if (IsLevelCrossingTile(u->tile)) {
       
   112 			if (!HasPowerOnRail(u->u.rail.railtype, GetRailTypeCrossing(u->tile))) engine_has_power = false;
   110 			if (!HasPowerOnRail(u->u.rail.railtype, GetRailTypeCrossing(u->tile))) engine_has_power = false;
   113 			if (!HasPowerOnRail(v->u.rail.railtype, GetRailTypeCrossing(u->tile))) wagon_has_power = false;
   111 			if (!HasPowerOnRail(v->u.rail.railtype, GetRailTypeCrossing(u->tile))) wagon_has_power = false;
   114 		} else {
   112 		} else {
   115 			if (!HasPowerOnRail(u->u.rail.railtype, GetRailType(u->tile))) engine_has_power = false;
   113 			if (!HasPowerOnRail(u->u.rail.railtype, GetRailType(u->tile))) engine_has_power = false;
   116 			if (!HasPowerOnRail(v->u.rail.railtype, GetRailType(u->tile))) wagon_has_power = false;
   114 			if (!HasPowerOnRail(v->u.rail.railtype, GetRailType(u->tile))) wagon_has_power = false;
  1599 
  1597 
  1600 		/* update other vars */
  1598 		/* update other vars */
  1601 		UpdateVarsAfterSwap(a);
  1599 		UpdateVarsAfterSwap(a);
  1602 		UpdateVarsAfterSwap(b);
  1600 		UpdateVarsAfterSwap(b);
  1603 
  1601 
  1604 		VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
  1602 		/* call the proper EnterTile function unless we are in a wormhole */
  1605 		VehicleEnterTile(b, b->tile, b->x_pos, b->y_pos);
  1603 		if (!(a->u.rail.track & 0x40)) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
       
  1604 		if (!(b->u.rail.track & 0x40)) VehicleEnterTile(b, b->tile, b->x_pos, b->y_pos);
  1606 	} else {
  1605 	} else {
  1607 		if (!(a->u.rail.track & 0x80)) a->direction = ReverseDir(a->direction);
  1606 		if (!(a->u.rail.track & 0x80)) a->direction = ReverseDir(a->direction);
  1608 		UpdateVarsAfterSwap(a);
  1607 		UpdateVarsAfterSwap(a);
  1609 
  1608 
  1610 		VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
  1609 		if (!(a->u.rail.track & 0x40)) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
  1611 	}
  1610 	}
  1612 
  1611 
  1613 	/* Update train's power incase tiles were different rail type */
  1612 	/* Update train's power incase tiles were different rail type */
  1614 	TrainPowerChanged(v);
  1613 	TrainPowerChanged(v);
  1615 }
  1614 }
  1938 		tfdd.tile = tile;
  1937 		tfdd.tile = tile;
  1939 		tfdd.best_length = 0;
  1938 		tfdd.best_length = 0;
  1940 		return tfdd;
  1939 		return tfdd;
  1941 	}
  1940 	}
  1942 
  1941 
  1943 	if (v->u.rail.track == 0x40) tile = GetVehicleOutOfTunnelTile(v);
       
  1944 
       
  1945 	if (_patches.yapf.rail_use_yapf) {
  1942 	if (_patches.yapf.rail_use_yapf) {
  1946 		bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
  1943 		bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
  1947 		tfdd.best_length = found ? max_distance / 2 : -1; // some fake distance or NOT_FOUND
  1944 		tfdd.best_length = found ? max_distance / 2 : -1; // some fake distance or NOT_FOUND
  1948 	} else if (_patches.new_pathfinding_all) {
  1945 	} else if (_patches.new_pathfinding_all) {
  1949 		NPFFoundTargetData ftd;
  1946 		NPFFoundTargetData ftd;
  2731 static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
  2728 static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
  2732 {
  2729 {
  2733 	byte new_z, old_z;
  2730 	byte new_z, old_z;
  2734 
  2731 
  2735 	// need this hint so it returns the right z coordinate on bridges.
  2732 	// need this hint so it returns the right z coordinate on bridges.
  2736 	_get_z_hint = v->z_pos;
       
  2737 	new_z = GetSlopeZ(v->x_pos, v->y_pos);
  2733 	new_z = GetSlopeZ(v->x_pos, v->y_pos);
  2738 	_get_z_hint = 0;
       
  2739 
  2734 
  2740 	old_z = v->z_pos;
  2735 	old_z = v->z_pos;
  2741 	v->z_pos = new_z;
  2736 	v->z_pos = new_z;
  2742 
  2737 
  2743 	if (new_tile) {
  2738 	if (new_tile) {
  2807 {
  2802 {
  2808 	switch (GetTileType(tile)) {
  2803 	switch (GetTileType(tile)) {
  2809 		case MP_RAILWAY:
  2804 		case MP_RAILWAY:
  2810 		case MP_STATION:
  2805 		case MP_STATION:
  2811 			// normal tracks, jump to owner check
  2806 			// normal tracks, jump to owner check
  2812 			break;
       
  2813 
       
  2814 		case MP_TUNNELBRIDGE:
       
  2815 			if (IsBridge(tile) && IsBridgeMiddle(tile)) {
       
  2816 				// is train going over the bridge?
       
  2817 				if (v->z_pos > GetTileMaxZ(tile)) return true;
       
  2818 			}
       
  2819 			break;
  2807 			break;
  2820 
  2808 
  2821 		case MP_STREET:
  2809 		case MP_STREET:
  2822 			// tracks over roads, do owner check of tracks
  2810 			// tracks over roads, do owner check of tracks
  2823 			return
  2811 			return
  3156 				if (prev == NULL) AffectSpeedByDirChange(v, chosen_dir);
  3144 				if (prev == NULL) AffectSpeedByDirChange(v, chosen_dir);
  3157 
  3145 
  3158 				v->direction = chosen_dir;
  3146 				v->direction = chosen_dir;
  3159 			}
  3147 			}
  3160 		} else {
  3148 		} else {
  3161 			/* in tunnel */
  3149 			/* in tunnel on on a bridge */
  3162 			GetNewVehiclePos(v, &gp);
  3150 			GetNewVehiclePos(v, &gp);
  3163 
  3151 
  3164 			// Check if to exit the tunnel...
  3152 			SetSpeedLimitOnBridge(v);
  3165 			if (!IsTunnelTile(gp.new_tile) ||
  3153 
  3166 					!(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y)&0x4) ) {
  3154 			if (!(IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) || !(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y) & 0x4)) {
  3167 				v->x_pos = gp.x;
  3155 				v->x_pos = gp.x;
  3168 				v->y_pos = gp.y;
  3156 				v->y_pos = gp.y;
  3169 				VehiclePositionChanged(v);
  3157 				VehiclePositionChanged(v);
       
  3158 				if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v);
  3170 				continue;
  3159 				continue;
  3171 			}
  3160 			}
  3172 		}
  3161 		}
  3173 
  3162 
  3174 		/* update image of train, as well as delta XY */
  3163 		/* update image of train, as well as delta XY */
  3261 
  3250 
  3262 	/* Check if the wagon was on a road/rail-crossing and disable it if no
  3251 	/* Check if the wagon was on a road/rail-crossing and disable it if no
  3263 	 * others are on it */
  3252 	 * others are on it */
  3264 	DisableTrainCrossing(v->tile);
  3253 	DisableTrainCrossing(v->tile);
  3265 
  3254 
  3266 	if (v->u.rail.track == 0x40) { // inside a tunnel
  3255 	if ( (v->u.rail.track == 0x40 && v->vehstatus & VS_HIDDEN) ) { // inside a tunnel
  3267 		TileIndex endtile = CheckTunnelBusy(v->tile, NULL);
  3256 		TileIndex endtile = CheckTunnelBusy(v->tile, NULL);
  3268 
  3257 
  3269 		if (endtile == INVALID_TILE) return; // tunnel is busy (error returned)
  3258 		if (endtile == INVALID_TILE) return; // tunnel is busy (error returned)
  3270 
  3259 
  3271 		switch (v->direction) {
  3260 		switch (v->direction) {
  3292 	static const DirDiff delta[] = {
  3281 	static const DirDiff delta[] = {
  3293 		DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
  3282 		DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
  3294 	};
  3283 	};
  3295 
  3284 
  3296 	do {
  3285 	do {
  3297 		//I need to buffer the train direction
  3286 		/* We don't need to twist around vehicles if they're not visible */
  3298 		if (!(v->u.rail.track & 0x40)) {
  3287 		if (!(v->vehstatus & VS_HIDDEN)) {
  3299 			v->direction = ChangeDir(v->direction, delta[GB(Random(), 0, 2)]);
  3288 			v->direction = ChangeDir(v->direction, delta[GB(Random(), 0, 2)]);
  3300 		}
       
  3301 		if (!(v->vehstatus & VS_HIDDEN)) {
       
  3302 			BeginVehicleMove(v);
  3289 			BeginVehicleMove(v);
  3303 			UpdateTrainDeltaXY(v, v->direction);
  3290 			UpdateTrainDeltaXY(v, v->direction);
  3304 			v->cur_image = GetTrainImage(v, v->direction);
  3291 			v->cur_image = GetTrainImage(v, v->direction);
  3305 			AfterSetTrainPos(v, false);
  3292 			/* Refrain from updating the z position of the vehicle when on
       
  3293 			   a bridge, because AfterSetTrainPos will put the vehicle under
       
  3294 			   the bridge in that case */
       
  3295 			if (!(v->u.rail.track & 0x40)) AfterSetTrainPos(v, false);
  3306 		}
  3296 		}
  3307 	} while ((v = v->next) != NULL);
  3297 	} while ((v = v->next) != NULL);
  3308 }
  3298 }
  3309 
  3299 
  3310 static void HandleCrashedTrain(Vehicle *v)
  3300 static void HandleCrashedTrain(Vehicle *v)
  3311 {
  3301 {
  3312 	int state = ++v->u.rail.crash_anim_pos;
  3302 	int state = ++v->u.rail.crash_anim_pos;
  3313 	uint32 r;
  3303 	uint32 r;
  3314 	Vehicle *u;
  3304 	Vehicle *u;
  3315 
  3305 
  3316 	if (state == 4 && v->u.rail.track != 0x40) {
  3306 	if (state == 4 && !(v->u.rail.track & VS_HIDDEN)) {
  3317 		CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
  3307 		CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
  3318 	}
  3308 	}
  3319 
  3309 
  3320 	if (state <= 200 && CHANCE16R(1, 7, r)) {
  3310 	if (state <= 200 && CHANCE16R(1, 7, r)) {
  3321 		int index = (r * 10 >> 16);
  3311 		int index = (r * 10 >> 16);
  3400 	if (v->u.rail.track & 0x40) return true; // exit if inside a tunnel
  3390 	if (v->u.rail.track & 0x40) return true; // exit if inside a tunnel
  3401 	if (v->u.rail.track & 0x80) return true; // exit if inside a depot
  3391 	if (v->u.rail.track & 0x80) return true; // exit if inside a depot
  3402 
  3392 
  3403 	tile = v->tile;
  3393 	tile = v->tile;
  3404 
  3394 
  3405 	// tunnel entrance?
  3395 	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
  3406 	if (IsTunnelTile(tile) &&
  3396 		DiagDirection dir;
  3407 			DiagDirToDir(GetTunnelDirection(tile)) == v->direction) {
  3397 
  3408 		return true;
  3398 		dir = IsTunnel(tile) ? GetTunnelDirection(tile) : GetBridgeRampDirection(tile);
       
  3399 		if (DiagDirToDir(dir) == v->direction) return true;
  3409 	}
  3400 	}
  3410 
  3401 
  3411 	// depot?
  3402 	// depot?
  3412 	/* XXX -- When enabled, this makes it possible to crash trains of others
  3403 	/* XXX -- When enabled, this makes it possible to crash trains of others
  3413 	     (by building a depot right against a station) */
  3404 	     (by building a depot right against a station) */