3059 v->current_order.flags = 0; |
3090 v->current_order.flags = 0; |
3060 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
3091 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
3061 } |
3092 } |
3062 } |
3093 } |
3063 } else { |
3094 } else { |
3064 /* A new tile is about to be entered. */ |
3095 /* A new tile is about to be entered normally (not from bridge wormhole to ramp) */ |
3065 |
|
3066 byte bits; |
|
3067 /* Determine what direction we're entering the new tile from */ |
3096 /* Determine what direction we're entering the new tile from */ |
3068 dir = GetNewVehicleDirectionByTile(gp.new_tile, gp.old_tile); |
3097 dir = GetNewVehicleDirectionByTile(gp.new_tile, gp.old_tile); |
3069 enterdir = DirToDiagDir(dir); |
3098 enterdir = DirToDiagDir(dir); |
3070 assert(enterdir==0 || enterdir==1 || enterdir==2 || enterdir==3); |
3099 assert(enterdir==0 || enterdir==1 || enterdir==2 || enterdir==3); |
3071 new_tile: |
3100 } |
3072 |
3101 } |
3073 /* Get the status of the tracks in the new tile and mask |
3102 if (entering_new_tile && !in_tunnel_or_bridge) { |
3074 * away the bits that aren't reachable. */ |
3103 /* A new tile is about to be entered. */ |
3075 ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL) & _reachable_tracks[enterdir]; |
3104 byte bits; |
3076 |
3105 |
3077 /* Combine the from & to directions. |
3106 /* Get the status of the tracks in the new tile and mask |
3078 * Now, the lower byte contains the track status, and the byte at bit 16 contains |
3107 * away the bits that aren't reachable. */ |
3079 * the signal status. */ |
3108 ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL) & _reachable_tracks[enterdir]; |
3080 tracks = ts | (ts >> 8); |
3109 |
3081 bits = tracks & 0xFF; |
3110 /* Combine the from & to directions. |
3082 if ((_patches.new_pathfinding_all || _patches.yapf.rail_use_yapf) && _patches.forbid_90_deg && prev == NULL) { |
3111 * Now, the lower byte contains the track status, and the byte at bit 16 contains |
3083 /* We allow wagons to make 90 deg turns, because forbid_90_deg |
3112 * the signal status. */ |
3084 * can be switched on halfway a turn */ |
3113 tracks = ts | (ts >> 8); |
3085 bits &= ~TrackCrossesTracks(FIND_FIRST_BIT(v->u.rail.track)); |
3114 bits = tracks & 0xFF; |
|
3115 if ((_patches.new_pathfinding_all || _patches.yapf.rail_use_yapf) && _patches.forbid_90_deg && prev == NULL) { |
|
3116 /* We allow wagons to make 90 deg turns, because forbid_90_deg |
|
3117 * can be switched on halfway a turn */ |
|
3118 bits &= ~TrackCrossesTracks(FIND_FIRST_BIT(v->u.rail.track)); |
|
3119 } |
|
3120 |
|
3121 if (bits == 0) { |
|
3122 DEBUG(misc, 2, "%x == 0", bits); |
|
3123 goto invalid_rail; |
|
3124 } |
|
3125 |
|
3126 /* Check if the new tile contrains tracks that are compatible |
|
3127 * with the current train, if not, bail out. */ |
|
3128 if (!CheckCompatibleRail(v, gp.new_tile)) { |
|
3129 DEBUG(misc, 2, "!CheckCompatibleRail(%p, %x)", v, gp.new_tile); |
|
3130 goto invalid_rail; |
|
3131 } |
|
3132 |
|
3133 if (prev == NULL) { |
|
3134 /* Currently the locomotive is active. Determine which one of the |
|
3135 * available tracks to choose */ |
|
3136 chosen_track = 1 << ChooseTrainTrack(v, gp.new_tile, enterdir, bits); |
|
3137 assert(chosen_track & tracks); |
|
3138 |
|
3139 /* Check if it's a red signal and that force proceed is not clicked. */ |
|
3140 if ( (tracks>>16)&chosen_track && v->u.rail.force_proceed == 0) goto red_light; |
|
3141 } else { |
|
3142 static byte _matching_tracks[8] = {0x30, 1, 0xC, 2, 0x30, 1, 0xC, 2}; |
|
3143 |
|
3144 /* The wagon is active, simply follow the prev vehicle. */ |
|
3145 chosen_track = (byte)(_matching_tracks[GetDirectionToVehicle(prev, gp.x, gp.y)] & bits); |
|
3146 } |
|
3147 |
|
3148 /* make sure chosen track is a valid track */ |
|
3149 assert(chosen_track==1 || chosen_track==2 || chosen_track==4 || chosen_track==8 || chosen_track==16 || chosen_track==32); |
|
3150 |
|
3151 /* Update XY to reflect the entrance to the new tile, and select the direction to use */ |
|
3152 { |
|
3153 const byte *b = _initial_tile_subcoord[FIND_FIRST_BIT(chosen_track)][enterdir]; |
|
3154 gp.x = (gp.x & ~0xF) | b[0]; |
|
3155 gp.y = (gp.y & ~0xF) | b[1]; |
|
3156 chosen_dir = b[2]; |
|
3157 } |
|
3158 |
|
3159 /* Call the landscape function and tell it that the vehicle entered the tile */ |
|
3160 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
|
3161 if (r & 0x8) { |
|
3162 DEBUG(misc, 2, "%x & 0x8 (new tile)", r); |
|
3163 goto invalid_rail; |
|
3164 } |
|
3165 |
|
3166 if (IsLevelCrossingTile(v->tile) && v->next == NULL) { |
|
3167 UnbarCrossing(v->tile); |
|
3168 MarkTileDirtyByTile(v->tile); |
|
3169 } |
|
3170 |
|
3171 if (IsFrontEngine(v)) v->load_unload_time_rem = 0; |
|
3172 |
|
3173 if (!(r&0x4)) { |
|
3174 v->tile = gp.new_tile; |
|
3175 |
|
3176 if (GetTileRailType(gp.new_tile, chosen_track) != GetTileRailType(gp.old_tile, v->u.rail.track)) { |
|
3177 TrainPowerChanged(GetFirstVehicleInChain(v)); |
3086 } |
3178 } |
3087 |
3179 |
3088 if (bits == 0) { |
3180 v->u.rail.track = chosen_track; |
3089 DEBUG(misc, 2, "%x == 0", bits); |
3181 assert(v->u.rail.track); |
3090 goto invalid_rail; |
3182 } |
3091 } |
3183 |
3092 |
3184 if (IsFrontEngine(v)) TrainMovedChangeSignals(gp.new_tile, enterdir); |
3093 /* Check if the new tile contrains tracks that are compatible |
3185 |
3094 * with the current train, if not, bail out. */ |
3186 /* Signals can only change when the first |
3095 if (!CheckCompatibleRail(v, gp.new_tile)) { |
3187 * (above) or the last vehicle moves. */ |
3096 DEBUG(misc, 2, "!CheckCompatibleRail(%p, %x)", v, gp.new_tile); |
3188 if (v->next == NULL) |
3097 goto invalid_rail; |
3189 TrainMovedChangeSignals(gp.old_tile, ReverseDiagDir(enterdir)); |
3098 } |
3190 |
3099 |
3191 if (prev == NULL) AffectSpeedByDirChange(v, chosen_dir); |
3100 if (prev == NULL) { |
3192 |
3101 /* Currently the locomotive is active. Determine which one of the |
3193 v->direction = chosen_dir; |
3102 * available tracks to choose */ |
|
3103 chosen_track = 1 << ChooseTrainTrack(v, gp.new_tile, enterdir, bits); |
|
3104 assert(chosen_track & tracks); |
|
3105 |
|
3106 /* Check if it's a red signal and that force proceed is not clicked. */ |
|
3107 if ( (tracks>>16)&chosen_track && v->u.rail.force_proceed == 0) goto red_light; |
|
3108 } else { |
|
3109 static byte _matching_tracks[8] = {0x30, 1, 0xC, 2, 0x30, 1, 0xC, 2}; |
|
3110 |
|
3111 /* The wagon is active, simply follow the prev vehicle. */ |
|
3112 chosen_track = (byte)(_matching_tracks[GetDirectionToVehicle(prev, gp.x, gp.y)] & bits); |
|
3113 } |
|
3114 |
|
3115 /* make sure chosen track is a valid track */ |
|
3116 assert(chosen_track==1 || chosen_track==2 || chosen_track==4 || chosen_track==8 || chosen_track==16 || chosen_track==32); |
|
3117 |
|
3118 /* Update XY to reflect the entrance to the new tile, and select the direction to use */ |
|
3119 { |
|
3120 const byte *b = _initial_tile_subcoord[FIND_FIRST_BIT(chosen_track)][enterdir]; |
|
3121 gp.x = (gp.x & ~0xF) | b[0]; |
|
3122 gp.y = (gp.y & ~0xF) | b[1]; |
|
3123 chosen_dir = b[2]; |
|
3124 } |
|
3125 |
|
3126 /* Call the landscape function and tell it that the vehicle entered the tile */ |
|
3127 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
|
3128 if (r & 0x8) { |
|
3129 DEBUG(misc, 2, "%x & 0x8 (new tile)", r); |
|
3130 goto invalid_rail; |
|
3131 } |
|
3132 |
|
3133 if (IsLevelCrossingTile(v->tile) && v->next == NULL) { |
|
3134 UnbarCrossing(v->tile); |
|
3135 MarkTileDirtyByTile(v->tile); |
|
3136 } |
|
3137 |
|
3138 if (IsFrontEngine(v)) v->load_unload_time_rem = 0; |
|
3139 |
|
3140 if (!(r&0x4)) { |
|
3141 v->tile = gp.new_tile; |
|
3142 |
|
3143 if (GetTileRailType(gp.new_tile, chosen_track) != GetTileRailType(gp.old_tile, v->u.rail.track)) { |
|
3144 TrainPowerChanged(GetFirstVehicleInChain(v)); |
|
3145 } |
|
3146 |
|
3147 v->u.rail.track = chosen_track; |
|
3148 assert(v->u.rail.track); |
|
3149 } |
|
3150 |
|
3151 if (IsFrontEngine(v)) TrainMovedChangeSignals(gp.new_tile, enterdir); |
|
3152 |
|
3153 /* Signals can only change when the first |
|
3154 * (above) or the last vehicle moves. */ |
|
3155 if (v->next == NULL) |
|
3156 TrainMovedChangeSignals(gp.old_tile, ReverseDiagDir(enterdir)); |
|
3157 |
|
3158 if (prev == NULL) AffectSpeedByDirChange(v, chosen_dir); |
|
3159 |
|
3160 v->direction = chosen_dir; |
|
3161 } |
|
3162 } else { |
|
3163 uint32 res; |
|
3164 /* in tunnel on on a bridge */ |
|
3165 GetNewVehiclePos(v, &gp); |
|
3166 |
|
3167 SetSpeedLimitOnBridge(v); |
|
3168 |
|
3169 if (!(IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) || !((res = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y)) & 0x4)) { |
|
3170 v->x_pos = gp.x; |
|
3171 v->y_pos = gp.y; |
|
3172 VehiclePositionChanged(v); |
|
3173 if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v); |
|
3174 continue; |
|
3175 } |
|
3176 |
|
3177 if (IsBridgeTile(gp.new_tile) && res & 0x4) { |
|
3178 /* ok we have just left the bridge (because the status was "onbridge" before and we got |
|
3179 a return value of 4 from VehicleEnterTile. we know the enterdir from the bridge ramp |
|
3180 direction, and act as if we entered the tile normally (hence the goto) */ |
|
3181 enterdir = ReverseDiagDir(GetBridgeRampDirection(gp.new_tile)); |
|
3182 goto new_tile; |
|
3183 } |
|
3184 } |
3194 } |
3185 |
3195 |
3186 /* update image of train, as well as delta XY */ |
3196 /* update image of train, as well as delta XY */ |
3187 newdir = GetNewVehicleDirection(v, gp.x, gp.y); |
3197 newdir = GetNewVehicleDirection(v, gp.x, gp.y); |
3188 UpdateTrainDeltaXY(v, newdir); |
3198 UpdateTrainDeltaXY(v, newdir); |