src/roadveh_cmd.cpp
branchgamebalance
changeset 9911 0b8b245a2391
parent 9910 0b2aebc8283e
child 9912 1ac8aac92385
equal deleted inserted replaced
9910:0b2aebc8283e 9911:0b8b245a2391
   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;