train_cmd.c
changeset 3977 edb5b94e2094
parent 3956 0f43adbc293a
child 3985 87cf4955787d
equal deleted inserted replaced
3976:b52d2c1acc5c 3977:edb5b94e2094
    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"
       
    29 #include "newgrf_callbacks.h"
    28 #include "newgrf_callbacks.h"
    30 #include "newgrf_engine.h"
    29 #include "newgrf_engine.h"
    31 #include "newgrf_text.h"
    30 #include "newgrf_text.h"
    32 #include "direction.h"
    31 #include "direction.h"
    33 #include "yapf/yapf.h"
    32 #include "yapf/yapf.h"
    90 		bool wagon_has_power = true;
    89 		bool wagon_has_power = true;
    91 
    90 
    92 		/* Power is not added for articulated parts */
    91 		/* Power is not added for articulated parts */
    93 		if (IsArticulatedPart(u)) continue;
    92 		if (IsArticulatedPart(u)) continue;
    94 
    93 
    95 		if (IsLevelCrossingTile(u->tile)) {
    94 		if (IsBridgeTile(u->tile) && IsBridgeMiddle(u->tile) && DiagDirToAxis(DirToDiagDir(u->direction)) == GetBridgeAxis(u->tile)) {
       
    95 			if (!HasPowerOnRail(u->u.rail.railtype, GetRailTypeOnBridge(u->tile))) engine_has_power = false;
       
    96 			if (!HasPowerOnRail(v->u.rail.railtype, GetRailTypeOnBridge(u->tile))) wagon_has_power = false;
       
    97 		} else if (IsLevelCrossingTile(u->tile)) {
    96 			if (!HasPowerOnRail(u->u.rail.railtype, GetRailTypeCrossing(u->tile)))	engine_has_power = false;
    98 			if (!HasPowerOnRail(u->u.rail.railtype, GetRailTypeCrossing(u->tile)))	engine_has_power = false;
    97 			if (!HasPowerOnRail(v->u.rail.railtype, GetRailTypeCrossing(u->tile)))	wagon_has_power = false;
    99 			if (!HasPowerOnRail(v->u.rail.railtype, GetRailTypeCrossing(u->tile)))	wagon_has_power = false;
    98 		} else {
   100 		} else {
    99 			if (!HasPowerOnRail(u->u.rail.railtype, GetRailType(u->tile))) engine_has_power = false;
   101 			if (!HasPowerOnRail(u->u.rail.railtype, GetRailType(u->tile))) engine_has_power = false;
   100 			if (!HasPowerOnRail(v->u.rail.railtype, GetRailType(u->tile))) wagon_has_power = false;
   102 			if (!HasPowerOnRail(v->u.rail.railtype, GetRailType(u->tile))) wagon_has_power = false;
  1523 
  1525 
  1524 		/* update other vars */
  1526 		/* update other vars */
  1525 		UpdateVarsAfterSwap(a);
  1527 		UpdateVarsAfterSwap(a);
  1526 		UpdateVarsAfterSwap(b);
  1528 		UpdateVarsAfterSwap(b);
  1527 
  1529 
  1528 		/* call the proper EnterTile function unless we are in a wormhole */
  1530 		VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
  1529 		if (!(a->u.rail.track & 0x40)) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
  1531 		VehicleEnterTile(b, b->tile, b->x_pos, b->y_pos);
  1530 		if (!(b->u.rail.track & 0x40)) VehicleEnterTile(b, b->tile, b->x_pos, b->y_pos);
       
  1531 	} else {
  1532 	} else {
  1532 		if (!(a->u.rail.track & 0x80)) a->direction = ReverseDir(a->direction);
  1533 		if (!(a->u.rail.track & 0x80)) a->direction = ReverseDir(a->direction);
  1533 		UpdateVarsAfterSwap(a);
  1534 		UpdateVarsAfterSwap(a);
  1534 
  1535 
  1535 		if (!(a->u.rail.track & 0x40)) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
  1536 		VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
  1536 	}
  1537 	}
  1537 
  1538 
  1538 	/* Update train's power incase tiles were different rail type */
  1539 	/* Update train's power incase tiles were different rail type */
  1539 	TrainPowerChanged(v);
  1540 	TrainPowerChanged(v);
  1540 }
  1541 }
  1848 		tfdd.tile = tile;
  1849 		tfdd.tile = tile;
  1849 		tfdd.best_length = 0;
  1850 		tfdd.best_length = 0;
  1850 		return tfdd;
  1851 		return tfdd;
  1851 	}
  1852 	}
  1852 
  1853 
       
  1854 	if (v->u.rail.track == 0x40) tile = GetVehicleOutOfTunnelTile(v);
       
  1855 
  1853 	if (_patches.yapf.rail_use_yapf) {
  1856 	if (_patches.yapf.rail_use_yapf) {
  1854 		bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
  1857 		bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
  1855 		tfdd.best_length = found ? max_distance / 2 : -1; // some fake distance or NOT_FOUND
  1858 		tfdd.best_length = found ? max_distance / 2 : -1; // some fake distance or NOT_FOUND
  1856 	} else if (_patches.new_pathfinding_all) {
  1859 	} else if (_patches.new_pathfinding_all) {
  1857 		NPFFoundTargetData ftd;
  1860 		NPFFoundTargetData ftd;
  2565 static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
  2568 static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
  2566 {
  2569 {
  2567 	byte new_z, old_z;
  2570 	byte new_z, old_z;
  2568 
  2571 
  2569 	// need this hint so it returns the right z coordinate on bridges.
  2572 	// need this hint so it returns the right z coordinate on bridges.
       
  2573 	_get_z_hint = v->z_pos;
  2570 	new_z = GetSlopeZ(v->x_pos, v->y_pos);
  2574 	new_z = GetSlopeZ(v->x_pos, v->y_pos);
       
  2575 	_get_z_hint = 0;
  2571 
  2576 
  2572 	old_z = v->z_pos;
  2577 	old_z = v->z_pos;
  2573 	v->z_pos = new_z;
  2578 	v->z_pos = new_z;
  2574 
  2579 
  2575 	if (new_tile) {
  2580 	if (new_tile) {
  2639 {
  2644 {
  2640 	switch (GetTileType(tile)) {
  2645 	switch (GetTileType(tile)) {
  2641 		case MP_RAILWAY:
  2646 		case MP_RAILWAY:
  2642 		case MP_STATION:
  2647 		case MP_STATION:
  2643 			// normal tracks, jump to owner check
  2648 			// normal tracks, jump to owner check
       
  2649 			break;
       
  2650 
       
  2651 		case MP_TUNNELBRIDGE:
       
  2652 			if (IsBridge(tile) && IsBridgeMiddle(tile)) {
       
  2653 				// is train going over the bridge?
       
  2654 				if (v->z_pos > GetTileMaxZ(tile)) return true;
       
  2655 			}
  2644 			break;
  2656 			break;
  2645 
  2657 
  2646 		case MP_STREET:
  2658 		case MP_STREET:
  2647 			// tracks over roads, do owner check of tracks
  2659 			// tracks over roads, do owner check of tracks
  2648 			return
  2660 			return
  2981 				if (prev == NULL) AffectSpeedByDirChange(v, chosen_dir);
  2993 				if (prev == NULL) AffectSpeedByDirChange(v, chosen_dir);
  2982 
  2994 
  2983 				v->direction = chosen_dir;
  2995 				v->direction = chosen_dir;
  2984 			}
  2996 			}
  2985 		} else {
  2997 		} else {
  2986 			/* in tunnel on on a bridge */
  2998 			/* in tunnel */
  2987 			GetNewVehiclePos(v, &gp);
  2999 			GetNewVehiclePos(v, &gp);
  2988 
  3000 
  2989 			SetSpeedLimitOnBridge(v);
  3001 			// Check if to exit the tunnel...
  2990 
  3002 			if (!IsTunnelTile(gp.new_tile) ||
  2991 			if (!(IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) || !(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y) & 0x4)) {
  3003 					!(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y)&0x4) ) {
  2992 				v->x_pos = gp.x;
  3004 				v->x_pos = gp.x;
  2993 				v->y_pos = gp.y;
  3005 				v->y_pos = gp.y;
  2994 				VehiclePositionChanged(v);
  3006 				VehiclePositionChanged(v);
  2995 				if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v);
       
  2996 				continue;
  3007 				continue;
  2997 			}
  3008 			}
  2998 		}
  3009 		}
  2999 
  3010 
  3000 		/* update image of train, as well as delta XY */
  3011 		/* update image of train, as well as delta XY */
  3087 
  3098 
  3088 	/* Check if the wagon was on a road/rail-crossing and disable it if no
  3099 	/* Check if the wagon was on a road/rail-crossing and disable it if no
  3089 	 * others are on it */
  3100 	 * others are on it */
  3090 	DisableTrainCrossing(v->tile);
  3101 	DisableTrainCrossing(v->tile);
  3091 
  3102 
  3092 	if ( (v->u.rail.track == 0x40 && v->vehstatus & VS_HIDDEN) ) { // inside a tunnel
  3103 	if (v->u.rail.track == 0x40) { // inside a tunnel
  3093 		TileIndex endtile = CheckTunnelBusy(v->tile, NULL);
  3104 		TileIndex endtile = CheckTunnelBusy(v->tile, NULL);
  3094 
  3105 
  3095 		if (endtile == INVALID_TILE) return; // tunnel is busy (error returned)
  3106 		if (endtile == INVALID_TILE) return; // tunnel is busy (error returned)
  3096 
  3107 
  3097 		switch (v->direction) {
  3108 		switch (v->direction) {
  3118 	static const DirDiff delta[] = {
  3129 	static const DirDiff delta[] = {
  3119 		DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
  3130 		DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
  3120 	};
  3131 	};
  3121 
  3132 
  3122 	do {
  3133 	do {
  3123 		/* We don't need to twist around vehicles if they're not visible */
  3134 		//I need to buffer the train direction
       
  3135 		if (!(v->u.rail.track & 0x40)) {
       
  3136 			v->direction = ChangeDir(v->direction, delta[GB(Random(), 0, 2)]);
       
  3137 		}
  3124 		if (!(v->vehstatus & VS_HIDDEN)) {
  3138 		if (!(v->vehstatus & VS_HIDDEN)) {
  3125 			v->direction = ChangeDir(v->direction, delta[GB(Random(), 0, 2)]);
       
  3126 			BeginVehicleMove(v);
  3139 			BeginVehicleMove(v);
  3127 			UpdateTrainDeltaXY(v, v->direction);
  3140 			UpdateTrainDeltaXY(v, v->direction);
  3128 			v->cur_image = GetTrainImage(v, v->direction);
  3141 			v->cur_image = GetTrainImage(v, v->direction);
  3129 			/* Refrain from updating the z position of the vehicle when on
  3142 			AfterSetTrainPos(v, false);
  3130 			   a bridge, because AfterSetTrainPos will put the vehicle under
       
  3131 			   the bridge in that case */
       
  3132 			if (!(v->u.rail.track & 0x40)) AfterSetTrainPos(v, false);
       
  3133 		}
  3143 		}
  3134 	} while ((v = v->next) != NULL);
  3144 	} while ((v = v->next) != NULL);
  3135 }
  3145 }
  3136 
  3146 
  3137 static void HandleCrashedTrain(Vehicle *v)
  3147 static void HandleCrashedTrain(Vehicle *v)
  3138 {
  3148 {
  3139 	int state = ++v->u.rail.crash_anim_pos;
  3149 	int state = ++v->u.rail.crash_anim_pos;
  3140 	uint32 r;
  3150 	uint32 r;
  3141 	Vehicle *u;
  3151 	Vehicle *u;
  3142 
  3152 
  3143 	if (state == 4 && !(v->u.rail.track & VS_HIDDEN)) {
  3153 	if (state == 4 && v->u.rail.track != 0x40) {
  3144 		CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
  3154 		CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
  3145 	}
  3155 	}
  3146 
  3156 
  3147 	if (state <= 200 && CHANCE16R(1, 7, r)) {
  3157 	if (state <= 200 && CHANCE16R(1, 7, r)) {
  3148 		int index = (r * 10 >> 16);
  3158 		int index = (r * 10 >> 16);
  3225 	if (v->u.rail.track & 0x40) return true; // exit if inside a tunnel
  3235 	if (v->u.rail.track & 0x40) return true; // exit if inside a tunnel
  3226 	if (v->u.rail.track & 0x80) return true; // exit if inside a depot
  3236 	if (v->u.rail.track & 0x80) return true; // exit if inside a depot
  3227 
  3237 
  3228 	tile = v->tile;
  3238 	tile = v->tile;
  3229 
  3239 
  3230 	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
  3240 	// tunnel entrance?
  3231 		DiagDirection dir;
  3241 	if (IsTunnelTile(tile) &&
  3232 
  3242 			DiagDirToDir(GetTunnelDirection(tile)) == v->direction) {
  3233 		if (IsTunnel(tile)) {
  3243 		return true;
  3234 			dir = GetTunnelDirection(tile);
       
  3235 		} else {
       
  3236 			dir = GetBridgeRampDirection(tile);
       
  3237 		}
       
  3238 		if (DiagDirToDir(dir) == v->direction) return true;
       
  3239 	}
  3244 	}
  3240 
  3245 
  3241 	// depot?
  3246 	// depot?
  3242 	/* XXX -- When enabled, this makes it possible to crash trains of others
  3247 	/* XXX -- When enabled, this makes it possible to crash trains of others
  3243 	     (by building a depot right against a station) */
  3248 	     (by building a depot right against a station) */