summaryrefslogtreecommitdiff
path: root/vehicle.c
diff options
context:
space:
mode:
authorbjarni <bjarni@openttd.org>2005-07-31 13:08:08 +0000
committerbjarni <bjarni@openttd.org>2005-07-31 13:08:08 +0000
commit546c34f2e5e6b130cdbc9201fe465548c1e54ee5 (patch)
treecf8e1be453d176ec2f818199cf430b90a6bf02d8 /vehicle.c
parent50e41dc1d14114b90fa56579937f16c3de88eb75 (diff)
downloadopenttd-546c34f2e5e6b130cdbc9201fe465548c1e54ee5.tar.xz
(svn r2764) -Feature: Clone vehicles
-This allows a player to clone an excisting vehicle of his own -[fix]: this uncovered an excisting bug in CmdBuildRailVehicle() where depots could build trains of the wrong track type. This is fixed -Thanks to Celestar for drawing the sprites and _luca_ for including them in openttd.grf
Diffstat (limited to 'vehicle.c')
-rw-r--r--vehicle.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/vehicle.c b/vehicle.c
index dda0d2b26..5b889eb8b 100644
--- a/vehicle.c
+++ b/vehicle.c
@@ -21,6 +21,7 @@
#include "vehicle_gui.h"
#include "depot.h"
#include "station.h"
+#include "gui.h"
#include "rail.h"
#define INVALID_COORD (-0x8000)
@@ -1669,6 +1670,122 @@ void MaybeReplaceVehicle(Vehicle *v)
_current_player = OWNER_NONE;
}
+int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 veh1_veh2, uint32 mode);
+int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2);
+int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2);
+int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2);
+int32 CmdBuildShip(int x, int y, uint32 flags, uint32 p1, uint32 p2);
+int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2);
+
+
+typedef int32 VehBuildProc(int x, int y, uint32 flags, uint32 p1, uint32 p2);
+
+static VehBuildProc * const _veh_build_proc_table[] = {
+ CmdBuildRailVehicle,
+ CmdBuildRoadVeh,
+ CmdBuildShip,
+ CmdBuildAircraft,
+};
+
+static VehicleID * _new_vehicle_id_proc_table[] = {
+ &_new_train_id,
+ &_new_roadveh_id,
+ &_new_ship_id,
+ &_new_aircraft_id,
+};
+
+/** Clone a vehicle. If it is a train, it will clone all the cars too
+ * @param x,y unused
+ * @param p1 the original vehicle's index
+ * @param p2 1 = shared orders, else copied orders
+ */
+int32 CmdCloneVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+{
+ Vehicle *vfront, *v;
+ Vehicle *wfront, *w1, *w2;
+ int cost, total_cost;
+ VehBuildProc *proc;
+ VehicleID *new_id;
+ uint refit_command = 0;
+ byte needs_refitting = 255;
+
+ if (!IsVehicleIndex(p1))
+ return CMD_ERROR;
+ v = GetVehicle(p1);
+ wfront = v;
+ w1 = v;
+ vfront = v;
+
+ if (!CheckOwnership(v->owner))
+ return CMD_ERROR;
+
+ if (v->type == VEH_Train && v->subtype != TS_Front_Engine) return CMD_ERROR;
+
+ //no need to check if it is a depot since the build command do that
+ switch (v->type) {
+ case VEH_Train: refit_command = CMD_REFIT_RAIL_VEHICLE; break;
+ case VEH_Road: break;
+ case VEH_Ship: refit_command = CMD_REFIT_SHIP; break;
+ case VEH_Aircraft: refit_command = CMD_REFIT_AIRCRAFT; break;
+ default: return CMD_ERROR;
+ }
+
+ proc = _veh_build_proc_table[v->type - VEH_Train];
+ new_id = _new_vehicle_id_proc_table[v->type - VEH_Train];
+ total_cost = proc(x, y, flags, v->engine_type, 1);
+ if (total_cost == CMD_ERROR)
+ return CMD_ERROR;
+
+ if (flags & DC_EXEC) {
+ wfront = GetVehicle(*new_id);
+ w1 = wfront;
+ CmdCloneOrder(x, y, flags, (v->index << 16) | w1->index, p2 & 1 ? CO_SHARE : CO_COPY);
+
+ if (wfront->cargo_type != v->cargo_type) {
+ //a refit is needed
+ needs_refitting = v->cargo_type;
+ }
+ }
+ if (v->type == VEH_Train) {
+ // now we handle the cars
+ v = v->next;
+ while (v != NULL) {
+ cost = proc(x, y, flags, v->engine_type, 1);
+ if (cost == CMD_ERROR)
+ return CMD_ERROR;
+ total_cost += cost;
+
+ if (flags & DC_EXEC) {
+ // add this unit to the end of the train
+ w2 = GetVehicle(RailVehInfo(v->engine_type)->flags & RVI_WAGON ? _new_wagon_id : _new_train_id);
+ CmdMoveRailVehicle(x, y, flags, (w1->index << 16) | w2->index, 0);
+ w1 = w2;
+ }
+ v = v->next;
+ }
+
+ if (flags & DC_EXEC) {
+ _new_train_id = wfront->index;
+ v = vfront;
+ w1 = wfront;
+ while (w1 != NULL && v != NULL) {
+ w1->spritenum = v->spritenum; // makes sure that multiheaded engines are facing the correct way
+ if (w1->cargo_type != v->cargo_type) // checks if a refit is needed
+ needs_refitting = v->cargo_type;
+ w1 = w1->next;
+ v = v->next;
+ }
+
+ }
+ }
+ if (flags && DC_EXEC && needs_refitting != 255 && v->type != VEH_Road) { // right now we do not refit road vehicles
+ if (DoCommandByTile(wfront->tile, wfront->index, needs_refitting, 0, refit_command) != CMD_ERROR)
+ DoCommandByTile(wfront->tile, wfront->index, needs_refitting, DC_EXEC, refit_command);
+ }
+ return total_cost;
+}
+
+
/** Give a custom name to your vehicle
* @param x,y unused
* @param p1 vehicle ID to name