115 DrawSprite(6 + _roadveh_images[spritenum], pal, x, y); |
115 DrawSprite(6 + _roadveh_images[spritenum], pal, x, y); |
116 } |
116 } |
117 |
117 |
118 static int32 EstimateRoadVehCost(EngineID engine_type) |
118 static int32 EstimateRoadVehCost(EngineID engine_type) |
119 { |
119 { |
120 return ((_eco->GetPrice(CEconomy::ROADVEH_BASE) >> 3) * RoadVehInfo(engine_type)->base_cost) >> 5; |
120 return ((_eco->GetPrice(CEconomy::ROADVEH_BASE) >> 3) * GetEngineProperty(engine_type, 0x11, RoadVehInfo(engine_type)->base_cost)) >> 5; |
121 } |
121 } |
122 |
122 |
123 /** Build a road vehicle. |
123 /** Build a road vehicle. |
124 * @param tile tile of depot where road vehicle is built |
124 * @param tile tile of depot where road vehicle is built |
125 * @param flags operation to perform |
125 * @param flags operation to perform |
167 x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2; |
167 x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2; |
168 y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2; |
168 y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2; |
169 v->x_pos = x; |
169 v->x_pos = x; |
170 v->y_pos = y; |
170 v->y_pos = y; |
171 v->z_pos = GetSlopeZ(x, y); |
171 v->z_pos = GetSlopeZ(x, y); |
172 v->z_height = 6; |
|
173 |
172 |
174 v->u.road.state = RVSB_IN_DEPOT; |
173 v->u.road.state = RVSB_IN_DEPOT; |
175 v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; |
174 v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; |
176 |
175 |
177 v->spritenum = rvi->image_index; |
176 v->spritenum = rvi->image_index; |
203 v->service_interval = _patches.servint_roadveh; |
202 v->service_interval = _patches.servint_roadveh; |
204 |
203 |
205 v->date_of_last_service = _date; |
204 v->date_of_last_service = _date; |
206 v->build_year = _cur_year; |
205 v->build_year = _cur_year; |
207 |
206 |
208 v->type = VEH_ROAD; |
207 v = new (v) RoadVehicle(); |
209 v->cur_image = 0xC15; |
208 v->cur_image = 0xC15; |
210 v->random_bits = VehicleRandomBits(); |
209 v->random_bits = VehicleRandomBits(); |
211 |
210 |
212 v->vehicle_flags = 0; |
211 v->vehicle_flags = 0; |
213 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
212 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
|
213 |
|
214 v->cargo_cap = GetVehicleProperty(v, 0x0F, rvi->capacity); |
214 |
215 |
215 VehiclePositionChanged(v); |
216 VehiclePositionChanged(v); |
216 |
217 |
217 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
218 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
218 RebuildVehicleLists(); |
219 RebuildVehicleLists(); |
484 |
485 |
485 return 0; |
486 return 0; |
486 } |
487 } |
487 |
488 |
488 |
489 |
489 static void MarkRoadVehDirty(Vehicle *v) |
490 void RoadVehicle::MarkDirty() |
490 { |
491 { |
491 v->cur_image = GetRoadVehImage(v, v->direction); |
492 this->cur_image = GetRoadVehImage(this, this->direction); |
492 MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); |
493 MarkAllViewportsDirty(this->left_coord, this->top_coord, this->right_coord + 1, this->bottom_coord + 1); |
493 } |
494 } |
494 |
495 |
495 static void UpdateRoadVehDeltaXY(Vehicle *v) |
496 void RoadVehicle::UpdateDeltaXY(Direction direction) |
496 { |
497 { |
497 #define MKIT(a,b,c,d) ((a&0xFF)<<24) | ((b&0xFF)<<16) | ((c&0xFF)<<8) | ((d&0xFF)<<0) |
498 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0) |
498 static const uint32 _delta_xy_table[8] = { |
499 static const uint32 _delta_xy_table[8] = { |
499 MKIT(3, 3, -1, -1), |
500 MKIT(3, 3, -1, -1), |
500 MKIT(3, 7, -1, -3), |
501 MKIT(3, 7, -1, -3), |
501 MKIT(3, 3, -1, -1), |
502 MKIT(3, 3, -1, -1), |
502 MKIT(7, 3, -3, -1), |
503 MKIT(7, 3, -3, -1), |
504 MKIT(3, 7, -1, -3), |
505 MKIT(3, 7, -1, -3), |
505 MKIT(3, 3, -1, -1), |
506 MKIT(3, 3, -1, -1), |
506 MKIT(7, 3, -3, -1), |
507 MKIT(7, 3, -3, -1), |
507 }; |
508 }; |
508 #undef MKIT |
509 #undef MKIT |
509 uint32 x = _delta_xy_table[v->direction]; |
510 |
510 v->x_offs = GB(x, 0, 8); |
511 uint32 x = _delta_xy_table[direction]; |
511 v->y_offs = GB(x, 8, 8); |
512 this->x_offs = GB(x, 0, 8); |
512 v->sprite_width = GB(x, 16, 8); |
513 this->y_offs = GB(x, 8, 8); |
513 v->sprite_height = GB(x, 24, 8); |
514 this->sprite_width = GB(x, 16, 8); |
|
515 this->sprite_height = GB(x, 24, 8); |
|
516 this->z_height = 6; |
514 } |
517 } |
515 |
518 |
516 static void ClearCrashedStation(Vehicle *v) |
519 static void ClearCrashedStation(Vehicle *v) |
517 { |
520 { |
518 RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); |
521 RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); |
564 |
567 |
565 uint32 r = Random(); |
568 uint32 r = Random(); |
566 |
569 |
567 v->direction = ChangeDir(v->direction, delta[r & 3]); |
570 v->direction = ChangeDir(v->direction, delta[r & 3]); |
568 BeginVehicleMove(v); |
571 BeginVehicleMove(v); |
569 UpdateRoadVehDeltaXY(v); |
572 v->UpdateDeltaXY(v->direction); |
570 v->cur_image = GetRoadVehImage(v, v->direction); |
573 v->cur_image = GetRoadVehImage(v, v->direction); |
571 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
574 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
572 } |
575 } |
573 |
576 |
574 static void RoadVehIsCrashed(Vehicle *v) |
577 static void RoadVehIsCrashed(Vehicle *v) |
747 default: |
750 default: |
748 v->dest_tile = 0; |
751 v->dest_tile = 0; |
749 break; |
752 break; |
750 } |
753 } |
751 |
754 |
752 InvalidateVehicleOrder(v); |
|
753 } |
|
754 |
|
755 static void HandleRoadVehLoading(Vehicle *v) |
|
756 { |
|
757 switch (v->current_order.type) { |
|
758 case OT_LOADING: { |
|
759 Order b; |
|
760 |
|
761 if (--v->load_unload_time_rem != 0) return; |
|
762 |
|
763 if (CanFillVehicle(v) && (v->current_order.flags & OF_FULL_LOAD || |
|
764 (_patches.gradual_loading && !HASBIT(v->vehicle_flags, VF_LOADING_FINISHED)))) { |
|
765 SET_EXPENSES_TYPE(EXPENSES_ROADVEH_INC); |
|
766 if (LoadUnloadVehicle(v, false)) { |
|
767 InvalidateWindow(WC_ROADVEH_LIST, v->owner); |
|
768 MarkRoadVehDirty(v); |
|
769 } |
|
770 return; |
|
771 } |
|
772 |
|
773 b = v->current_order; |
|
774 v->LeaveStation(); |
|
775 if (!(b.flags & OF_NON_STOP)) return; |
|
776 break; |
|
777 } |
|
778 |
|
779 case OT_DUMMY: break; |
|
780 |
|
781 default: return; |
|
782 } |
|
783 |
|
784 v->cur_order_index++; |
|
785 InvalidateVehicleOrder(v); |
755 InvalidateVehicleOrder(v); |
786 } |
756 } |
787 |
757 |
788 static void StartRoadVehSound(const Vehicle* v) |
758 static void StartRoadVehSound(const Vehicle* v) |
789 { |
759 { |
1309 } |
1279 } |
1310 |
1280 |
1311 if (v->vehstatus & VS_STOPPED) return; |
1281 if (v->vehstatus & VS_STOPPED) return; |
1312 |
1282 |
1313 ProcessRoadVehOrder(v); |
1283 ProcessRoadVehOrder(v); |
1314 HandleRoadVehLoading(v); |
1284 v->HandleLoading(); |
1315 |
1285 |
1316 if (v->current_order.type == OT_LOADING) return; |
1286 if (v->current_order.type == OT_LOADING) return; |
1317 |
1287 |
1318 if (IsRoadVehInDepot(v)) { |
1288 if (IsRoadVehInDepot(v)) { |
1319 /* Vehicle is about to leave a depot */ |
1289 /* Vehicle is about to leave a depot */ |
1343 v->vehstatus &= ~VS_HIDDEN; |
1313 v->vehstatus &= ~VS_HIDDEN; |
1344 v->u.road.state = tdir; |
1314 v->u.road.state = tdir; |
1345 v->u.road.frame = RVC_DEPOT_START_FRAME; |
1315 v->u.road.frame = RVC_DEPOT_START_FRAME; |
1346 |
1316 |
1347 v->cur_image = GetRoadVehImage(v, v->direction); |
1317 v->cur_image = GetRoadVehImage(v, v->direction); |
1348 UpdateRoadVehDeltaXY(v); |
1318 v->UpdateDeltaXY(v->direction); |
1349 SetRoadVehPosition(v,x,y); |
1319 SetRoadVehPosition(v,x,y); |
1350 |
1320 |
1351 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
1321 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
1352 return; |
1322 return; |
1353 } |
1323 } |
1379 } |
1349 } |
1380 |
1350 |
1381 if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && HASBIT(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { |
1351 if ((IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) && HASBIT(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { |
1382 /* Vehicle has just entered a bridge or tunnel */ |
1352 /* Vehicle has just entered a bridge or tunnel */ |
1383 v->cur_image = GetRoadVehImage(v, v->direction); |
1353 v->cur_image = GetRoadVehImage(v, v->direction); |
1384 UpdateRoadVehDeltaXY(v); |
1354 v->UpdateDeltaXY(v->direction); |
1385 SetRoadVehPosition(v,gp.x,gp.y); |
1355 SetRoadVehPosition(v,gp.x,gp.y); |
1386 return; |
1356 return; |
1387 } |
1357 } |
1388 |
1358 |
1389 v->x_pos = gp.x; |
1359 v->x_pos = gp.x; |
1467 v->direction = newdir; |
1437 v->direction = newdir; |
1468 v->cur_speed -= v->cur_speed >> 2; |
1438 v->cur_speed -= v->cur_speed >> 2; |
1469 } |
1439 } |
1470 |
1440 |
1471 v->cur_image = GetRoadVehImage(v, newdir); |
1441 v->cur_image = GetRoadVehImage(v, newdir); |
1472 UpdateRoadVehDeltaXY(v); |
1442 v->UpdateDeltaXY(v->direction); |
1473 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1443 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1474 return; |
1444 return; |
1475 } |
1445 } |
1476 |
1446 |
1477 if (rd.x & RDE_TURNED) { |
1447 if (rd.x & RDE_TURNED) { |
1507 v->direction = newdir; |
1477 v->direction = newdir; |
1508 v->cur_speed -= v->cur_speed >> 2; |
1478 v->cur_speed -= v->cur_speed >> 2; |
1509 } |
1479 } |
1510 |
1480 |
1511 v->cur_image = GetRoadVehImage(v, newdir); |
1481 v->cur_image = GetRoadVehImage(v, newdir); |
1512 UpdateRoadVehDeltaXY(v); |
1482 v->UpdateDeltaXY(v->direction); |
1513 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1483 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1514 return; |
1484 return; |
1515 } |
1485 } |
1516 |
1486 |
1517 /* Calculate new position for the vehicle */ |
1487 /* Calculate new position for the vehicle */ |
1537 v->direction = new_dir; |
1507 v->direction = new_dir; |
1538 v->cur_speed -= (v->cur_speed >> 2); |
1508 v->cur_speed -= (v->cur_speed >> 2); |
1539 if (old_dir != v->u.road.state) { |
1509 if (old_dir != v->u.road.state) { |
1540 /* The vehicle is in a road stop */ |
1510 /* The vehicle is in a road stop */ |
1541 v->cur_image = GetRoadVehImage(v, new_dir); |
1511 v->cur_image = GetRoadVehImage(v, new_dir); |
1542 UpdateRoadVehDeltaXY(v); |
1512 v->UpdateDeltaXY(v->direction); |
1543 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
1513 SetRoadVehPosition(v, v->x_pos, v->y_pos); |
1544 /* Note, return here means that the frame counter is not incremented |
1514 /* Note, return here means that the frame counter is not incremented |
1545 * for vehicles changing direction in a road stop. This causes frames to |
1515 * for vehicles changing direction in a road stop. This causes frames to |
1546 * be repeated. (XXX) Is this intended? */ |
1516 * be repeated. (XXX) Is this intended? */ |
1547 return; |
1517 return; |
1567 * Note, if vehicle is loading/unloading it has already been handled, |
1537 * Note, if vehicle is loading/unloading it has already been handled, |
1568 * so if we get here the vehicle has just arrived or is just ready to leave. */ |
1538 * so if we get here the vehicle has just arrived or is just ready to leave. */ |
1569 if (v->current_order.type != OT_LEAVESTATION && |
1539 if (v->current_order.type != OT_LEAVESTATION && |
1570 v->current_order.type != OT_GOTO_DEPOT) { |
1540 v->current_order.type != OT_GOTO_DEPOT) { |
1571 /* Vehicle has arrived at a bay in a road stop */ |
1541 /* Vehicle has arrived at a bay in a road stop */ |
1572 Order old_order; |
|
1573 |
1542 |
1574 if (IsDriveThroughStopTile(v->tile)) { |
1543 if (IsDriveThroughStopTile(v->tile)) { |
1575 TileIndex next_tile = TILE_ADD(v->tile, TileOffsByDir(v->direction)); |
1544 TileIndex next_tile = TILE_ADD(v->tile, TileOffsByDir(v->direction)); |
1576 RoadStop::Type type = IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK; |
1545 RoadStop::Type type = IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK; |
1577 |
|
1578 assert(HASBIT(v->u.road.state, RVS_IS_STOPPING)); |
|
1579 |
1546 |
1580 /* Check if next inline bay is free */ |
1547 /* Check if next inline bay is free */ |
1581 if (IsDriveThroughStopTile(next_tile) && (GetRoadStopType(next_tile) == type)) { |
1548 if (IsDriveThroughStopTile(next_tile) && (GetRoadStopType(next_tile) == type)) { |
1582 RoadStop *rs_n = GetRoadStopByTile(next_tile, type); |
1549 RoadStop *rs_n = GetRoadStopByTile(next_tile, type); |
1583 |
1550 |
1599 rs->SetEntranceBusy(false); |
1566 rs->SetEntranceBusy(false); |
1600 |
1567 |
1601 v->last_station_visited = GetStationIndex(v->tile); |
1568 v->last_station_visited = GetStationIndex(v->tile); |
1602 |
1569 |
1603 RoadVehArrivesAt(v, st); |
1570 RoadVehArrivesAt(v, st); |
1604 |
|
1605 old_order = v->current_order; |
|
1606 v->BeginLoading(); |
1571 v->BeginLoading(); |
1607 v->current_order.flags = 0; |
1572 |
1608 |
|
1609 if (old_order.type == OT_GOTO_STATION && |
|
1610 v->current_order.dest == v->last_station_visited) { |
|
1611 v->current_order.flags = |
|
1612 (old_order.flags & (OF_FULL_LOAD | OF_UNLOAD | OF_TRANSFER)) | OF_NON_STOP; |
|
1613 } |
|
1614 |
|
1615 SET_EXPENSES_TYPE(EXPENSES_ROADVEH_INC); |
|
1616 if (LoadUnloadVehicle(v, true)) { |
|
1617 InvalidateWindow(WC_ROADVEH_LIST, v->owner); |
|
1618 MarkRoadVehDirty(v); |
|
1619 } |
|
1620 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
|
1621 return; |
1573 return; |
1622 } |
1574 } |
1623 |
1575 |
1624 /* Vehicle is ready to leave a bay in a road stop */ |
1576 /* Vehicle is ready to leave a bay in a road stop */ |
1625 if (v->current_order.type != OT_GOTO_DEPOT) { |
1577 if (v->current_order.type != OT_GOTO_DEPOT) { |
1675 /* Move to next frame unless vehicle arrived at a stop position |
1627 /* Move to next frame unless vehicle arrived at a stop position |
1676 * in a depot or entered a tunnel/bridge */ |
1628 * in a depot or entered a tunnel/bridge */ |
1677 if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++; |
1629 if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) v->u.road.frame++; |
1678 |
1630 |
1679 v->cur_image = GetRoadVehImage(v, v->direction); |
1631 v->cur_image = GetRoadVehImage(v, v->direction); |
1680 UpdateRoadVehDeltaXY(v); |
1632 v->UpdateDeltaXY(v->direction); |
1681 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1633 RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y)); |
1682 } |
1634 } |
1683 |
1635 |
1684 static void AgeRoadVehCargo(Vehicle *v) |
1636 static void AgeRoadVehCargo(Vehicle *v) |
1685 { |
1637 { |
1731 if (v->current_order.type == OT_GOTO_DEPOT && |
1683 if (v->current_order.type == OT_GOTO_DEPOT && |
1732 v->current_order.flags & OF_NON_STOP && |
1684 v->current_order.flags & OF_NON_STOP && |
1733 !CHANCE16(1, 20)) { |
1685 !CHANCE16(1, 20)) { |
1734 return; |
1686 return; |
1735 } |
1687 } |
|
1688 |
|
1689 if (v->current_order.type == OT_LOADING) v->LeaveStation(); |
|
1690 ClearSlot(v); |
1736 |
1691 |
1737 v->current_order.type = OT_GOTO_DEPOT; |
1692 v->current_order.type = OT_GOTO_DEPOT; |
1738 v->current_order.flags = OF_NON_STOP; |
1693 v->current_order.flags = OF_NON_STOP; |
1739 v->current_order.dest = depot->index; |
1694 v->current_order.dest = depot->index; |
1740 v->dest_tile = depot->xy; |
1695 v->dest_tile = depot->xy; |
1851 * @param flags operation to perform |
1806 * @param flags operation to perform |
1852 * @param p1 Vehicle ID of the vehicle to refit |
1807 * @param p1 Vehicle ID of the vehicle to refit |
1853 * @param p2 Bitstuffed elements |
1808 * @param p2 Bitstuffed elements |
1854 * - p2 = (bit 0-7) - the new cargo type to refit to |
1809 * - p2 = (bit 0-7) - the new cargo type to refit to |
1855 * - p2 = (bit 8-15) - the new cargo subtype to refit to |
1810 * - p2 = (bit 8-15) - the new cargo subtype to refit to |
|
1811 * - p2 = (bit 16) - refit only this vehicle (ignored) |
|
1812 * @return cost of refit or error |
1856 */ |
1813 */ |
1857 int32 CmdRefitRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1814 int32 CmdRefitRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1858 { |
1815 { |
1859 Vehicle *v; |
1816 Vehicle *v; |
1860 int32 cost; |
1817 int32 cost; |
1895 CargoID old_cid = rvi->cargo_type; |
1852 CargoID old_cid = rvi->cargo_type; |
1896 /* normally, the capacity depends on the cargo type, a vehicle can |
1853 /* normally, the capacity depends on the cargo type, a vehicle can |
1897 * carry twice as much mail/goods as normal cargo, and four times as |
1854 * carry twice as much mail/goods as normal cargo, and four times as |
1898 * many passengers |
1855 * many passengers |
1899 */ |
1856 */ |
1900 capacity = rvi->capacity; |
1857 capacity = GetVehicleProperty(v, 0x0F, rvi->capacity); |
1901 switch (old_cid) { |
1858 switch (old_cid) { |
1902 case CT_PASSENGERS: break; |
1859 case CT_PASSENGERS: break; |
1903 case CT_MAIL: |
1860 case CT_MAIL: |
1904 case CT_GOODS: capacity *= 2; break; |
1861 case CT_GOODS: capacity *= 2; break; |
1905 default: capacity *= 4; break; |
1862 default: capacity *= 4; break; |