vehicle.c
changeset 2563 abf7a5e73988
parent 2558 64d44eaf39ee
child 2564 24533c2db978
equal deleted inserted replaced
2562:5c34e4b3ec13 2563:abf7a5e73988
  1401 	} else if (age == 366*1 || age == 366*2 || age == 366*3 || age == 366*4 || age == 366*5) {
  1401 	} else if (age == 366*1 || age == 366*2 || age == 366*3 || age == 366*4 || age == 366*5) {
  1402 		ShowVehicleGettingOld(v, STR_01A2_IS_GETTING_VERY_OLD_AND);
  1402 		ShowVehicleGettingOld(v, STR_01A2_IS_GETTING_VERY_OLD_AND);
  1403 	}
  1403 	}
  1404 }
  1404 }
  1405 
  1405 
  1406 extern int32 EstimateTrainCost(const RailVehicleInfo *rvi);
       
  1407 extern int32 EstimateRoadVehCost(EngineID engine_type);
       
  1408 extern int32 EstimateShipCost(EngineID engine_type);
       
  1409 extern int32 EstimateAircraftCost(EngineID engine_type);
       
  1410 extern int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2);
       
  1411 extern int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2);
       
  1412 extern int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2);
       
  1413 
       
  1414 int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 veh1_veh2, uint32 mode);
       
  1415 int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2);
       
  1416 int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2);
       
  1417 int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2);
       
  1418 int32 CmdBuildShip(int x, int y, uint32 flags, uint32 p1, uint32 p2);
       
  1419 int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2);
       
  1420 
       
  1421 typedef int32 VehBuildProc(int x, int y, uint32 flags, uint32 p1, uint32 p2);
       
  1422 
       
  1423 static VehBuildProc * const _veh_build_cmd_table[] = {
       
  1424 	CmdBuildRailVehicle,
       
  1425 	CmdBuildRoadVeh,
       
  1426 	CmdBuildShip,
       
  1427 	CmdBuildAircraft,
       
  1428 };
       
  1429 
       
  1430 static VehicleID * _new_vehicle_id_proc_table[] = {
  1406 static VehicleID * _new_vehicle_id_proc_table[] = {
  1431 	&_new_train_id,
  1407 	&_new_train_id,
  1432 	&_new_roadveh_id,
  1408 	&_new_roadveh_id,
  1433 	&_new_ship_id,
  1409 	&_new_ship_id,
  1434 	&_new_aircraft_id,
  1410 	&_new_aircraft_id,
  1435 };
  1411 };
  1436 
  1412 
  1437 /** Clone a vehicle. If it is a train, it will clone all the cars too
  1413 /** Clone a vehicle. If it is a train, it will clone all the cars too
  1438   * @param x,y unused
  1414 * @param x,y depot where the cloned vehicle is build
  1439   * @param p1 the original vehicle's index
  1415 * @param p1 the original vehicle's index
  1440   * @param p2 1 = shared orders, else copied orders
  1416 * @param p2 1 = shared orders, else copied orders
  1441   */
  1417 */
  1442 int32 CmdCloneVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
  1418 int32 CmdCloneVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
  1443 {
  1419 {
  1444 	Vehicle *vfront, *v;
  1420 	Vehicle *v_front, *v;
  1445 	Vehicle *wfront, *w1, *w2;
  1421 	Vehicle *w_front, *w, *w_rear;
  1446 	int cost, total_cost;
  1422 	int cost, total_cost = 0;
  1447 	VehBuildProc *proc;
       
  1448 	VehicleID *new_id;
  1423 	VehicleID *new_id;
  1449 	uint refit_command = 0;
       
  1450 	byte needs_refitting = 255;
       
  1451 
  1424 
  1452 	if (!IsVehicleIndex(p1))
  1425 	if (!IsVehicleIndex(p1))
  1453 		return CMD_ERROR;
  1426 		return CMD_ERROR;
  1454 	v = GetVehicle(p1);
  1427 	v = GetVehicle(p1);
  1455 	wfront = v;
  1428 	v_front = v;
  1456 	w1 = v;
  1429 	w = NULL;
  1457 	vfront = v;
  1430 	w_front = NULL;
       
  1431 	w_rear = NULL;
       
  1432 
       
  1433 
       
  1434 	/*
       
  1435 	 * v_front is the front engine in the original vehicle
       
  1436 	 * v is the car/vehicle of the original vehicle, that is currently being copied
       
  1437 	 * w_front is the front engine of the cloned vehicle
       
  1438 	 * w is the car/vehicle currently being cloned
       
  1439 	 * w_rear is the rear end of the cloned train. It's used to add more cars and is only used by trains
       
  1440 	 */
  1458 
  1441 
  1459 	if (!CheckOwnership(v->owner))
  1442 	if (!CheckOwnership(v->owner))
  1460 		return CMD_ERROR;
  1443 		return CMD_ERROR;
  1461 
  1444 
  1462 	if (v->type == VEH_Train && v->subtype != TS_Front_Engine) return CMD_ERROR;
  1445 	if (v->type == VEH_Train && v->subtype != TS_Front_Engine) return CMD_ERROR;
  1463 
  1446 
  1464 	//no need to check if it is a depot since the build command do that
       
  1465 	switch (v->type) {
       
  1466 		case VEH_Train:		refit_command = CMD_REFIT_RAIL_VEHICLE; break;
       
  1467 		case VEH_Road:		break;
       
  1468 		case VEH_Ship:		refit_command = CMD_REFIT_SHIP; break;
       
  1469 		case VEH_Aircraft:	refit_command = CMD_REFIT_AIRCRAFT; break;
       
  1470 		default: return CMD_ERROR;
       
  1471 	}
       
  1472 
       
  1473 	proc = _veh_build_cmd_table[v->type - VEH_Train];
       
  1474 	new_id = _new_vehicle_id_proc_table[v->type - VEH_Train];
  1447 	new_id = _new_vehicle_id_proc_table[v->type - VEH_Train];
  1475 	total_cost = proc(x, y, flags, v->engine_type, 3);
  1448 
  1476 	if (total_cost == CMD_ERROR)
  1449 	do {
  1477 		return CMD_ERROR;
  1450 		cost = DoCommand(x, y, v->engine_type, 3, flags, CMD_BUILD_VEH(v->type));
       
  1451 
       
  1452 		if (CmdFailed(cost)) return cost;
       
  1453 
       
  1454 		total_cost += cost;
       
  1455 
       
  1456 		if (flags & DC_EXEC) {
       
  1457 			if (v->type == VEH_Train && RailVehInfo(v->engine_type)->flags & RVI_WAGON) {
       
  1458 				w = GetVehicle(_new_wagon_id);
       
  1459 			} else {
       
  1460 				w = GetVehicle(*new_id);
       
  1461 			}
       
  1462 
       
  1463 			if (v->type != VEH_Road) { // road vehicles can't be refitted
       
  1464 				if (v->cargo_type != w->cargo_type) {
       
  1465 					DoCommand(x, y, w->index, v->cargo_type, flags, CMD_REFIT_VEH(v->type));
       
  1466 				}
       
  1467 			}
       
  1468 
       
  1469 			if (v->type == VEH_Train && v->subtype != TS_Front_Engine) {
       
  1470 				// this s a train car
       
  1471 
       
  1472 				// add this unit to the end of the train
       
  1473 				DoCommand(x, y, (w_rear->index << 16) | w->index, 1, flags, CMD_MOVE_RAIL_VEHICLE);
       
  1474 			} else {
       
  1475 				// this is a front engine or not a train. It need orders
       
  1476 				w_front = w;
       
  1477 				DoCommand(x, y, (v->index << 16) | w->index, p2 & 1 ? CO_SHARE : CO_COPY, flags, CMD_CLONE_ORDER);
       
  1478 			}
       
  1479 			w_rear = w;	// trains needs to know the last car in the train, so they can add more in next loop
       
  1480 		}
       
  1481 	} while (v->type == VEH_Train && (v=v->next) != NULL);
  1478 
  1482 
  1479 	if (flags & DC_EXEC) {
  1483 	if (flags & DC_EXEC) {
  1480 		wfront = GetVehicle(*new_id);
  1484 		v = v_front;
  1481 		w1 = wfront;
  1485 		w = w_front;
  1482 		CmdCloneOrder(x, y, flags, (v->index << 16) | w1->index, p2 & 1 ? CO_SHARE : CO_COPY);
  1486 		if (v->type == VEH_Train) {
  1483 
  1487 			_new_train_id = w_front->index;  // _new_train_id needs to be the front engine due to the callback function
  1484 		if (wfront->cargo_type != v->cargo_type) {
  1488 
  1485 			//a refit is needed
  1489 			while (w != NULL && v != NULL) { // checking both just in case something went wrong
  1486 			needs_refitting = v->cargo_type;
  1490 				w->spritenum = v->spritenum; // makes sure that multiheaded engines are facing the correct way
  1487 		}
  1491 				w = w->next;
  1488 	}
       
  1489 	if (v->type == VEH_Train) {
       
  1490 		// now we handle the cars
       
  1491 		v = v->next;
       
  1492 		while (v != NULL) {
       
  1493 			cost = proc(x, y, flags, v->engine_type, 3);
       
  1494 			if (cost == CMD_ERROR)
       
  1495 				return CMD_ERROR;
       
  1496 			total_cost += cost;
       
  1497 
       
  1498 			if (flags & DC_EXEC) {
       
  1499 				// add this unit to the end of the train
       
  1500 				w2 = GetVehicle(RailVehInfo(v->engine_type)->flags & RVI_WAGON ? _new_wagon_id : _new_train_id);
       
  1501 				CmdMoveRailVehicle(x, y, flags, (w1->index << 16) | w2->index, 0);
       
  1502 				w1 = w2;
       
  1503 			}
       
  1504 			v = v->next;
       
  1505 		}
       
  1506 
       
  1507 		if (flags & DC_EXEC) {
       
  1508 			_new_train_id = wfront->index;
       
  1509 			v = vfront;
       
  1510 			w1 = wfront;
       
  1511 			while (w1 != NULL && v != NULL) {
       
  1512 				w1->spritenum = v->spritenum; // makes sure that multiheaded engines are facing the correct way
       
  1513 				if (w1->cargo_type != v->cargo_type)	// checks if a refit is needed
       
  1514 					needs_refitting = v->cargo_type;
       
  1515 				w1 = w1->next;
       
  1516 				v = v->next;
  1492 				v = v->next;
  1517 			}
  1493 			}
  1518 
  1494 		}
  1519 		}
       
  1520 	}
       
  1521 	if (flags & DC_EXEC && needs_refitting != 255 && vfront->type != VEH_Road) {	// right now we do not refit road vehicles
       
  1522 		if (DoCommandByTile(wfront->tile, wfront->index, needs_refitting, 0, refit_command) != CMD_ERROR)
       
  1523 			DoCommandByTile(wfront->tile, wfront->index, needs_refitting, DC_EXEC, refit_command);
       
  1524 	}
  1495 	}
  1525 	return total_cost;
  1496 	return total_cost;
  1526 }
  1497 }
  1527 
  1498 
  1528 /* Replaces a vehicle (used to be called autorenew)
  1499 /* Replaces a vehicle (used to be called autorenew)