1550 first = first->next; |
1549 first = first->next; |
1551 length -= 2; |
1550 length -= 2; |
1552 } |
1551 } |
1553 } |
1552 } |
1554 |
1553 |
1555 static TileIndex GetVehicleTileOutOfTunnel(const Vehicle* v, bool reverse) |
|
1556 { |
|
1557 TileIndex tile; |
|
1558 byte direction = (!reverse) ? DirToDiagdir(v->direction) : ReverseDiagdir(v->direction >> 1); |
|
1559 TileIndexDiff delta = TileOffsByDir(direction); |
|
1560 |
|
1561 if (v->u.rail.track != 0x40) return v->tile; |
|
1562 |
|
1563 for (tile = v->tile;; tile += delta) { |
|
1564 if (IsTunnelTile(tile) && GB(_m[tile].m5, 0, 2) != direction && GetTileZ(tile) == v->z_pos) |
|
1565 break; |
|
1566 } |
|
1567 return tile; |
|
1568 } |
|
1569 |
|
1570 static void ReverseTrainDirection(Vehicle *v) |
1554 static void ReverseTrainDirection(Vehicle *v) |
1571 { |
1555 { |
1572 int l = 0, r = -1; |
1556 int l = 0, r = -1; |
1573 Vehicle *u; |
1557 Vehicle *u; |
1574 TileIndex tile; |
|
1575 Trackdir trackdir; |
|
1576 TileIndex pbs_end_tile = v->u.rail.pbs_end_tile; // these may be changed, and we may need |
|
1577 Trackdir pbs_end_trackdir = v->u.rail.pbs_end_trackdir; // the old values, so cache them |
|
1578 |
|
1579 u = GetLastVehicleInChain(v); |
|
1580 tile = GetVehicleTileOutOfTunnel(u, false); |
|
1581 trackdir = ReverseTrackdir(GetVehicleTrackdir(u)); |
|
1582 |
|
1583 if (PBSTileReserved(tile) & (1 << TrackdirToTrack(trackdir))) { |
|
1584 NPFFindStationOrTileData fstd; |
|
1585 NPFFoundTargetData ftd; |
|
1586 |
|
1587 NPFFillWithOrderData(&fstd, v); |
|
1588 |
|
1589 tile = GetVehicleTileOutOfTunnel(u, true); |
|
1590 |
|
1591 DEBUG(pbs, 2) ("pbs: (%i) choose reverse (RV), tile:%x, trackdir:%i",v->unitnumber, u->tile, trackdir); |
|
1592 ftd = NPFRouteToStationOrTile(tile, trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype, PBS_MODE_ANY); |
|
1593 |
|
1594 if (ftd.best_trackdir == 0xFF) { |
|
1595 DEBUG(pbs, 0) ("pbs: (%i) no nodes encountered (RV)", v->unitnumber); |
|
1596 CLRBIT(v->u.rail.flags, VRF_REVERSING); |
|
1597 return; |
|
1598 } |
|
1599 |
|
1600 // we found a way out of the pbs block |
|
1601 if (NPFGetFlag(&ftd.node, NPF_FLAG_PBS_EXIT)) { |
|
1602 if (NPFGetFlag(&ftd.node, NPF_FLAG_PBS_BLOCKED)) { |
|
1603 CLRBIT(v->u.rail.flags, VRF_REVERSING); |
|
1604 return; |
|
1605 } |
|
1606 } |
|
1607 |
|
1608 v->u.rail.pbs_end_tile = ftd.node.tile; |
|
1609 v->u.rail.pbs_end_trackdir = ftd.node.direction; |
|
1610 } |
|
1611 |
|
1612 tile = GetVehicleTileOutOfTunnel(v, false); |
|
1613 trackdir = GetVehicleTrackdir(v); |
|
1614 |
|
1615 if (v->u.rail.pbs_status == PBS_STAT_HAS_PATH) { |
|
1616 TileIndex tile = AddTileIndexDiffCWrap(v->tile, TileIndexDiffCByDir(TrackdirToExitdir(trackdir))); |
|
1617 uint32 ts; |
|
1618 assert(tile != INVALID_TILE); |
|
1619 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL); |
|
1620 ts &= TrackdirReachesTrackdirs(trackdir); |
|
1621 assert(ts != 0 && KillFirstBit2x64(ts) == 0); |
|
1622 trackdir = FindFirstBit2x64(ts); |
|
1623 PBSClearPath(tile, trackdir, pbs_end_tile, pbs_end_trackdir); |
|
1624 v->u.rail.pbs_status = PBS_STAT_NONE; |
|
1625 } else if (PBSTileReserved(tile) & (1 << TrackdirToTrack(trackdir))) { |
|
1626 PBSClearPath(tile, trackdir, pbs_end_tile, pbs_end_trackdir); |
|
1627 if (v->u.rail.track != 0x40) |
|
1628 PBSReserveTrack(tile, trackdir & 7); |
|
1629 }; |
|
1630 |
1558 |
1631 if (IsTileDepotType(v->tile, TRANSPORT_RAIL)) |
1559 if (IsTileDepotType(v->tile, TRANSPORT_RAIL)) |
1632 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
1560 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
1633 |
1561 |
1634 |
1562 |
2038 for (u = v; u != NULL; u = u->next) { |
1966 for (u = v; u != NULL; u = u->next) { |
2039 if (u->u.rail.track != 0x80 || u->tile != v->tile) return false; |
1967 if (u->u.rail.track != 0x80 || u->tile != v->tile) return false; |
2040 } |
1968 } |
2041 |
1969 |
2042 if (v->u.rail.force_proceed == 0) { |
1970 if (v->u.rail.force_proceed == 0) { |
2043 Trackdir trackdir = GetVehicleTrackdir(v); |
|
2044 |
|
2045 if (++v->load_unload_time_rem < 37) { |
1971 if (++v->load_unload_time_rem < 37) { |
2046 InvalidateWindowClasses(WC_TRAINS_LIST); |
1972 InvalidateWindowClasses(WC_TRAINS_LIST); |
2047 return true; |
1973 return true; |
2048 } |
1974 } |
2049 |
1975 |
2050 v->load_unload_time_rem = 0; |
1976 v->load_unload_time_rem = 0; |
2051 |
1977 |
2052 if (PBSIsPbsSegment(v->tile, trackdir)) { |
|
2053 NPFFindStationOrTileData fstd; |
|
2054 NPFFoundTargetData ftd; |
|
2055 |
|
2056 if (PBSTileUnavail(v->tile) & (1 << trackdir)) return true; |
|
2057 |
|
2058 NPFFillWithOrderData(&fstd, v); |
|
2059 |
|
2060 DEBUG(pbs, 2) ("pbs: (%i) choose depot (DP), tile:%x, trackdir:%i",v->unitnumber, v->tile, trackdir); |
|
2061 ftd = NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype, PBS_MODE_GREEN); |
|
2062 |
|
2063 // we found a way out of the pbs block |
|
2064 if (NPFGetFlag(&ftd.node, NPF_FLAG_PBS_EXIT)) { |
|
2065 if (NPFGetFlag(&ftd.node, NPF_FLAG_PBS_BLOCKED) || NPFGetFlag(&ftd.node, NPF_FLAG_PBS_RED)) { |
|
2066 return true; |
|
2067 } else { |
|
2068 v->u.rail.pbs_end_tile = ftd.node.tile; |
|
2069 v->u.rail.pbs_end_trackdir = ftd.node.direction; |
|
2070 goto green; |
|
2071 } |
|
2072 } |
|
2073 } |
|
2074 |
|
2075 if (UpdateSignalsOnSegment(v->tile, v->direction)) { |
1978 if (UpdateSignalsOnSegment(v->tile, v->direction)) { |
2076 InvalidateWindowClasses(WC_TRAINS_LIST); |
1979 InvalidateWindowClasses(WC_TRAINS_LIST); |
2077 return true; |
1980 return true; |
2078 } |
1981 } |
2079 } |
1982 } |
2080 green: |
1983 |
2081 VehicleServiceInDepot(v); |
1984 VehicleServiceInDepot(v); |
2082 InvalidateWindowClasses(WC_TRAINS_LIST); |
1985 InvalidateWindowClasses(WC_TRAINS_LIST); |
2083 TrainPlayLeaveStationSound(v); |
1986 TrainPlayLeaveStationSound(v); |
2084 |
1987 |
2085 v->u.rail.track = 1; |
1988 v->u.rail.track = 1; |
2213 |
2116 |
2214 if (_patches.new_pathfinding_all) { /* Use a new pathfinding for everything */ |
2117 if (_patches.new_pathfinding_all) { /* Use a new pathfinding for everything */ |
2215 NPFFindStationOrTileData fstd; |
2118 NPFFindStationOrTileData fstd; |
2216 NPFFoundTargetData ftd; |
2119 NPFFoundTargetData ftd; |
2217 Trackdir trackdir; |
2120 Trackdir trackdir; |
2218 uint16 pbs_tracks; |
|
2219 |
2121 |
2220 NPFFillWithOrderData(&fstd, v); |
2122 NPFFillWithOrderData(&fstd, v); |
2221 /* The enterdir for the new tile, is the exitdir for the old tile */ |
2123 /* The enterdir for the new tile, is the exitdir for the old tile */ |
2222 trackdir = GetVehicleTrackdir(v); |
2124 trackdir = GetVehicleTrackdir(v); |
2223 assert(trackdir != 0xff); |
2125 assert(trackdir != 0xff); |
2224 |
2126 |
2225 pbs_tracks = PBSTileReserved(tile); |
2127 ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype); |
2226 pbs_tracks |= pbs_tracks << 8; |
|
2227 pbs_tracks &= TrackdirReachesTrackdirs(trackdir); |
|
2228 if (pbs_tracks || (v->u.rail.pbs_status == PBS_STAT_NEED_PATH)) { |
|
2229 DEBUG(pbs, 2) ("pbs: (%i) choosefromblock, tile_org:%x tile_dst:%x trackdir:%i pbs_tracks:%i",v->unitnumber, tile,tile - TileOffsByDir(enterdir), trackdir, pbs_tracks); |
|
2230 // clear the currently planned path |
|
2231 if (v->u.rail.pbs_status != PBS_STAT_NEED_PATH) PBSClearPath(tile, FindFirstBit2x64(pbs_tracks), v->u.rail.pbs_end_tile, v->u.rail.pbs_end_trackdir); |
|
2232 |
|
2233 // try to find a route to a green exit signal |
|
2234 ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype, PBS_MODE_ANY); |
|
2235 |
|
2236 v->u.rail.pbs_end_tile = ftd.node.tile; |
|
2237 v->u.rail.pbs_end_trackdir = ftd.node.direction; |
|
2238 |
|
2239 } else |
|
2240 ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype, PBS_MODE_NONE); |
|
2241 |
2128 |
2242 if (ftd.best_trackdir == 0xff) { |
2129 if (ftd.best_trackdir == 0xff) { |
2243 /* We are already at our target. Just do something */ |
2130 /* We are already at our target. Just do something */ |
2244 //TODO: maybe display error? |
2131 //TODO: maybe display error? |
2245 //TODO: go straight ahead if possible? |
2132 //TODO: go straight ahead if possible? |
2315 trackdir = GetVehicleTrackdir(v); |
2202 trackdir = GetVehicleTrackdir(v); |
2316 trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last)); |
2203 trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last)); |
2317 assert(trackdir != 0xff); |
2204 assert(trackdir != 0xff); |
2318 assert(trackdir_rev != 0xff); |
2205 assert(trackdir_rev != 0xff); |
2319 |
2206 |
2320 ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype, PBS_MODE_NONE); |
2207 ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype); |
2321 |
|
2322 if (ftd.best_bird_dist != 0) { |
2208 if (ftd.best_bird_dist != 0) { |
2323 /* We didn't find anything, just keep on going straight ahead */ |
2209 /* We didn't find anything, just keep on going straight ahead */ |
2324 reverse_best = false; |
2210 reverse_best = false; |
2325 } else { |
2211 } else { |
2326 if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) |
2212 if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) |
2959 //debug("!CheckCompatibleRail(%p, %x)", v, gp.new_tile); |
2845 //debug("!CheckCompatibleRail(%p, %x)", v, gp.new_tile); |
2960 goto invalid_rail; |
2846 goto invalid_rail; |
2961 } |
2847 } |
2962 |
2848 |
2963 if (prev == NULL) { |
2849 if (prev == NULL) { |
2964 byte trackdir; |
|
2965 /* Currently the locomotive is active. Determine which one of the |
2850 /* Currently the locomotive is active. Determine which one of the |
2966 * available tracks to choose */ |
2851 * available tracks to choose */ |
2967 chosen_track = 1 << ChooseTrainTrack(v, gp.new_tile, enterdir, bits); |
2852 chosen_track = 1 << ChooseTrainTrack(v, gp.new_tile, enterdir, bits); |
2968 assert(chosen_track & tracks); |
2853 assert(chosen_track & tracks); |
2969 |
2854 |
2970 trackdir = TrackEnterdirToTrackdir(FIND_FIRST_BIT(chosen_track), enterdir); |
|
2971 assert(trackdir != 0xff); |
|
2972 |
|
2973 if (PBSIsPbsSignal(gp.new_tile,trackdir) && PBSIsPbsSegment(gp.new_tile,trackdir)) { |
|
2974 // encountered a pbs signal, and possible a pbs block |
|
2975 DEBUG(pbs, 3) ("pbs: (%i) arrive AT signal, tile:%x pbs_stat:%i",v->unitnumber, gp.new_tile, v->u.rail.pbs_status); |
|
2976 |
|
2977 if (v->u.rail.pbs_status == PBS_STAT_NONE) { |
|
2978 // we havent planned a path already, so try to find one now |
|
2979 NPFFindStationOrTileData fstd; |
|
2980 NPFFoundTargetData ftd; |
|
2981 |
|
2982 NPFFillWithOrderData(&fstd, v); |
|
2983 |
|
2984 DEBUG(pbs, 2) ("pbs: (%i) choose signal (TC), tile:%x, trackdir:%i",v->unitnumber, gp.new_tile, trackdir); |
|
2985 ftd = NPFRouteToStationOrTile(gp.new_tile, trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype, PBS_MODE_GREEN); |
|
2986 |
|
2987 if (v->u.rail.force_proceed != 0) |
|
2988 goto green_light; |
|
2989 |
|
2990 if (ftd.best_trackdir == 0xFF) |
|
2991 goto red_light; |
|
2992 |
|
2993 // we found a way out of the pbs block |
|
2994 if (NPFGetFlag(&ftd.node, NPF_FLAG_PBS_EXIT)) { |
|
2995 if (NPFGetFlag(&ftd.node, NPF_FLAG_PBS_BLOCKED) || NPFGetFlag(&ftd.node, NPF_FLAG_PBS_RED)) |
|
2996 goto red_light; |
|
2997 else { |
|
2998 v->u.rail.pbs_end_tile = ftd.node.tile; |
|
2999 v->u.rail.pbs_end_trackdir = ftd.node.direction; |
|
3000 goto green_light; |
|
3001 } |
|
3002 |
|
3003 }; |
|
3004 |
|
3005 } else { |
|
3006 // we have already planned a path through this pbs block |
|
3007 // on entering the block, we reset our status |
|
3008 v->u.rail.pbs_status = PBS_STAT_NONE; |
|
3009 goto green_light; |
|
3010 }; |
|
3011 DEBUG(pbs, 3) ("pbs: (%i) no green light found, or was no pbs-block",v->unitnumber); |
|
3012 }; |
|
3013 |
|
3014 /* Check if it's a red signal and that force proceed is not clicked. */ |
2855 /* Check if it's a red signal and that force proceed is not clicked. */ |
3015 if ( (tracks>>16)&chosen_track && v->u.rail.force_proceed == 0) goto red_light; |
2856 if ( (tracks>>16)&chosen_track && v->u.rail.force_proceed == 0) goto red_light; |
3016 } else { |
2857 } else { |
3017 static byte _matching_tracks[8] = {0x30, 1, 0xC, 2, 0x30, 1, 0xC, 2}; |
2858 static byte _matching_tracks[8] = {0x30, 1, 0xC, 2, 0x30, 1, 0xC, 2}; |
3018 |
2859 |
3019 /* The wagon is active, simply follow the prev vehicle. */ |
2860 /* The wagon is active, simply follow the prev vehicle. */ |
3020 chosen_track = (byte)(_matching_tracks[GetDirectionToVehicle(prev, gp.x, gp.y)] & bits); |
2861 chosen_track = (byte)(_matching_tracks[GetDirectionToVehicle(prev, gp.x, gp.y)] & bits); |
3021 } |
2862 } |
3022 green_light: |
|
3023 if (v->next == NULL) |
|
3024 PBSClearTrack(gp.old_tile, FIND_FIRST_BIT(v->u.rail.track)); |
|
3025 |
2863 |
3026 /* make sure chosen track is a valid track */ |
2864 /* make sure chosen track is a valid track */ |
3027 assert(chosen_track==1 || chosen_track==2 || chosen_track==4 || chosen_track==8 || chosen_track==16 || chosen_track==32); |
2865 assert(chosen_track==1 || chosen_track==2 || chosen_track==4 || chosen_track==8 || chosen_track==16 || chosen_track==32); |
3028 |
2866 |
3029 /* Update XY to reflect the entrance to the new tile, and select the direction to use */ |
2867 /* Update XY to reflect the entrance to the new tile, and select the direction to use */ |
3048 v->u.rail.track = chosen_track; |
2886 v->u.rail.track = chosen_track; |
3049 assert(v->u.rail.track); |
2887 assert(v->u.rail.track); |
3050 } |
2888 } |
3051 |
2889 |
3052 if (IsFrontEngine(v)) |
2890 if (IsFrontEngine(v)) |
3053 TrainMovedChangeSignals(gp.new_tile, enterdir); |
2891 TrainMovedChangeSignals(gp.new_tile, enterdir); |
3054 |
2892 |
3055 /* Signals can only change when the first |
2893 /* Signals can only change when the first |
3056 * (above) or the last vehicle moves. */ |
2894 * (above) or the last vehicle moves. */ |
3057 if (v->next == NULL) |
2895 if (v->next == NULL) |
3058 TrainMovedChangeSignals(gp.old_tile, (enterdir) ^ 2); |
2896 TrainMovedChangeSignals(gp.old_tile, (enterdir) ^ 2); |
3059 |
2897 |
3060 if (prev == NULL) { |
2898 if (prev == NULL) { |
3061 AffectSpeedByDirChange(v, chosen_dir); |
2899 AffectSpeedByDirChange(v, chosen_dir); |
3062 } |
2900 } |
3063 |
2901 |
3162 |
3000 |
3163 BeginVehicleMove(v); |
3001 BeginVehicleMove(v); |
3164 EndVehicleMove(v); |
3002 EndVehicleMove(v); |
3165 DeleteVehicle(v); |
3003 DeleteVehicle(v); |
3166 |
3004 |
3167 // clear up reserved pbs tracks |
|
3168 if (PBSTileReserved(v->tile) & v->u.rail.track) { |
|
3169 if (v == u) { |
|
3170 PBSClearPath(v->tile, FIND_FIRST_BIT(v->u.rail.track), v->u.rail.pbs_end_tile, v->u.rail.pbs_end_trackdir); |
|
3171 PBSClearPath(v->tile, FIND_FIRST_BIT(v->u.rail.track) + 8, v->u.rail.pbs_end_tile, v->u.rail.pbs_end_trackdir); |
|
3172 }; |
|
3173 if (v->tile != u->tile) { |
|
3174 PBSClearTrack(v->tile, FIND_FIRST_BIT(v->u.rail.track)); |
|
3175 }; |
|
3176 } |
|
3177 |
|
3178 if (!(v->u.rail.track & 0xC0)) |
3005 if (!(v->u.rail.track & 0xC0)) |
3179 SetSignalsOnBothDir(v->tile, FIND_FIRST_BIT(v->u.rail.track)); |
3006 SetSignalsOnBothDir(v->tile, FIND_FIRST_BIT(v->u.rail.track)); |
3180 |
3007 |
3181 /* Check if the wagon was on a road/rail-crossing and disable it if no |
3008 /* Check if the wagon was on a road/rail-crossing and disable it if no |
3182 * others are on it */ |
3009 * others are on it */ |
3398 v->cur_speed = 0; |
3218 v->cur_speed = 0; |
3399 ReverseTrainDirection(v); |
3219 ReverseTrainDirection(v); |
3400 return false; |
3220 return false; |
3401 } |
3221 } |
3402 |
3222 |
3403 if (v->u.rail.pbs_status == PBS_STAT_HAS_PATH) |
|
3404 return true; |
|
3405 |
|
3406 if ((trackdir != INVALID_TRACKDIR) && (PBSIsPbsSignal(tile,trackdir) && PBSIsPbsSegment(tile,trackdir)) && !(IsTileType(v->tile, MP_STATION) && (v->current_order.station == _m[v->tile].m2))) { |
|
3407 NPFFindStationOrTileData fstd; |
|
3408 NPFFoundTargetData ftd; |
|
3409 |
|
3410 NPFFillWithOrderData(&fstd, v); |
|
3411 |
|
3412 DEBUG(pbs, 2) ("pbs: (%i) choose signal (CEOL), tile:%x trackdir:%i", v->unitnumber, tile, trackdir); |
|
3413 ftd = NPFRouteToStationOrTile(tile, trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.railtype, PBS_MODE_GREEN); |
|
3414 |
|
3415 if (ftd.best_trackdir != 0xFF && NPFGetFlag(&ftd.node, NPF_FLAG_PBS_EXIT)) { |
|
3416 if (!(NPFGetFlag(&ftd.node, NPF_FLAG_PBS_BLOCKED) || NPFGetFlag(&ftd.node, NPF_FLAG_PBS_RED))) { |
|
3417 v->u.rail.pbs_status = PBS_STAT_HAS_PATH; |
|
3418 v->u.rail.pbs_end_tile = ftd.node.tile; |
|
3419 v->u.rail.pbs_end_trackdir = ftd.node.direction; |
|
3420 return true; |
|
3421 } |
|
3422 }; |
|
3423 }; |
|
3424 |
|
3425 // slow down |
3223 // slow down |
3426 v->vehstatus |= VS_TRAIN_SLOWING; |
3224 v->vehstatus |= VS_TRAIN_SLOWING; |
3427 break_speed = _breakdown_speeds[x & 0xF]; |
3225 break_speed = _breakdown_speeds[x & 0xF]; |
3428 if (!(v->direction&1)) break_speed >>= 1; |
3226 if (!(v->direction&1)) break_speed >>= 1; |
3429 if (break_speed < v->cur_speed) v->cur_speed = break_speed; |
3227 if (break_speed < v->cur_speed) v->cur_speed = break_speed; |