summaryrefslogtreecommitdiff
path: root/order_cmd.c
diff options
context:
space:
mode:
authortruelight <truelight@openttd.org>2004-08-09 17:04:08 +0000
committertruelight <truelight@openttd.org>2004-08-09 17:04:08 +0000
commitefaeb275f78e18d594d9ee8ff04eccd2dc59512c (patch)
treebc8e1f56d77706d14d048cb2d99e53291930b520 /order_cmd.c
downloadopenttd-efaeb275f78e18d594d9ee8ff04eccd2dc59512c.tar.xz
(svn r1) Import of revision 975 of old (crashed) SVN
Diffstat (limited to 'order_cmd.c')
-rw-r--r--order_cmd.c332
1 files changed, 332 insertions, 0 deletions
diff --git a/order_cmd.c b/order_cmd.c
new file mode 100644
index 000000000..ab4e06484
--- /dev/null
+++ b/order_cmd.c
@@ -0,0 +1,332 @@
+#include "stdafx.h"
+#include "ttd.h"
+#include "vehicle.h"
+#include "command.h"
+#include "station.h"
+#include "player.h"
+
+/* p1 & 0xFFFF = vehicle
+ * p1 >> 16 = index in order list
+ * p2 = order command to insert
+ */
+int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+{
+ Vehicle *v = &_vehicles[p1 & 0xFFFF];
+ int sel = p1 >> 16;
+ int t;
+
+ if (sel > v->num_orders) return_cmd_error(STR_EMPTY);
+ if (_ptr_to_next_order == endof(_order_array)) return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS);
+ if (v->num_orders >= 40) return_cmd_error(STR_8832_TOO_MANY_ORDERS);
+
+ // for ships, make sure that the station is not too far away from the previous destination.
+ if (v->type == VEH_Ship && IS_HUMAN_PLAYER(v->owner) &&
+ sel != 0 && ((t=v->schedule_ptr[sel-1])&OT_MASK) == OT_GOTO_STATION) {
+
+ int dist = GetTileDist(DEREF_STATION(t >> 8)->xy, DEREF_STATION(p2 >> 8)->xy);
+ if (dist >= 130)
+ return_cmd_error(STR_0210_TOO_FAR_FROM_PREVIOUS_DESTINATIO);
+ }
+
+ if (flags & DC_EXEC) {
+ uint16 *s1, *s2;
+ Vehicle *u;
+
+ s1 = &v->schedule_ptr[sel];
+ s2 = _ptr_to_next_order++;
+ do s2[1] = s2[0]; while (--s2 >= s1);
+ s1[0] = (uint16)p2;
+
+ s1 = v->schedule_ptr;
+
+ FOR_ALL_VEHICLES(u) {
+ if (u->type != 0 && u->schedule_ptr != NULL) {
+ if (s1 < u->schedule_ptr) {
+ u->schedule_ptr++;
+ } else if (s1 == u->schedule_ptr) { // handle shared orders
+ u->num_orders++;
+
+ if ((byte)sel <= u->cur_order_index) {
+ sel++;
+ if ((byte)sel < u->num_orders)
+ u->cur_order_index = sel;
+ }
+ InvalidateWindow(WC_VEHICLE_VIEW, u->index);
+ InvalidateWindow(WC_VEHICLE_ORDERS, u->index);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int32 DecloneOrder(Vehicle *dst, uint32 flags)
+{
+ if (_ptr_to_next_order == endof(_order_array))
+ return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS);
+
+ if (flags & DC_EXEC) {
+ DeleteVehicleSchedule(dst);
+
+ dst->num_orders = 0;
+ *(dst->schedule_ptr = _ptr_to_next_order++) = 0;
+
+ InvalidateWindow(WC_VEHICLE_ORDERS, dst->index);
+ }
+ return 0;
+}
+
+/* p1 = vehicle
+ * p2 = sel
+ */
+int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+{
+ Vehicle *v = &_vehicles[p1], *u;
+ uint sel = (uint)p2;
+
+ _error_message = STR_EMPTY;
+ if (sel >= v->num_orders)
+ return DecloneOrder(v, flags);
+
+ if (flags & DC_EXEC) {
+ uint16 *s1;
+
+ s1 = &v->schedule_ptr[sel];
+
+ // copy all orders to get rid of the hole
+ do s1[0] = s1[1]; while (++s1 != _ptr_to_next_order);
+ _ptr_to_next_order--;
+
+ s1 = v->schedule_ptr;
+
+ FOR_ALL_VEHICLES(u) {
+ if (u->type != 0 && u->schedule_ptr != NULL) {
+ if (s1 < u->schedule_ptr) {
+ u->schedule_ptr--;
+ } else if (s1 == u->schedule_ptr) {// handle shared orders
+ u->num_orders--;
+ if ((byte)sel < u->cur_order_index)
+ u->cur_order_index--;
+
+ if ((byte)sel == u->cur_order_index && (u->next_order&(OT_MASK|OF_NON_STOP)) == (OT_LOADING|OF_NON_STOP))
+ u->next_order = OT_LOADING;
+
+ InvalidateWindow(WC_VEHICLE_VIEW, u->index);
+ InvalidateWindow(WC_VEHICLE_ORDERS, u->index);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* p1 = vehicle */
+int32 CmdSkipOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+{
+ if (flags & DC_EXEC) {
+ Vehicle *v = &_vehicles[p1];
+
+ {
+ byte b = v->cur_order_index + 1;
+ if (b >= v->num_orders) b = 0;
+ v->cur_order_index = b;
+
+ if (v->type == VEH_Train)
+ v->u.rail.days_since_order_progr = 0;
+ }
+
+ if ((v->next_order&(OT_MASK|OF_NON_STOP)) == (OT_LOADING|OF_NON_STOP))
+ v->next_order = OT_LOADING;
+
+ InvalidateWindow(WC_VEHICLE_ORDERS, v->index);
+ }
+ return 0;
+}
+
+/* p1 = vehicle
+ * p2&0xFF = sel
+ * p2>>8 = mode
+ */
+int32 CmdModifyOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+{
+ Vehicle *v = &_vehicles[p1];
+ byte sel = (byte)p2;
+ uint16 *sched;
+
+ if (sel >= v->num_orders)
+ return CMD_ERROR;
+
+ sched = &v->schedule_ptr[sel];
+ if (!((*sched & OT_MASK) == OT_GOTO_STATION ||
+ ((*sched & OT_MASK) == OT_GOTO_DEPOT && (p2>>8) != 1)))
+ return CMD_ERROR;
+
+ if (flags & DC_EXEC) {
+ switch(p2 >> 8) {
+ case 0: // full load
+ *sched ^= OF_FULL_LOAD;
+ if ((*sched & OT_MASK) != OT_GOTO_DEPOT)
+ *sched &= ~OF_UNLOAD;
+ break;
+ case 1: // unload
+ *sched ^= OF_UNLOAD;
+ *sched &= ~OF_FULL_LOAD;
+ break;
+ case 2: // non stop
+ *sched ^= OF_NON_STOP;
+ break;
+ }
+ sched = v->schedule_ptr;
+
+ FOR_ALL_VEHICLES(v) {
+ if (v->schedule_ptr == sched)
+ InvalidateWindow(WC_VEHICLE_ORDERS, v->index);
+ }
+
+ }
+
+ return 0;
+}
+
+// Clone an order
+// p1 & 0xFFFF is destination vehicle
+// p1 >> 16 is source vehicle
+
+// p2 is
+// 0 - clone
+// 1 - copy
+// 2 - unclone
+
+
+int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+{
+ Vehicle *dst = &_vehicles[p1 & 0xFFFF];
+
+ if (!(dst->type && dst->owner == _current_player))
+ return CMD_ERROR;
+
+ switch(p2) {
+
+ // share vehicle orders?
+ case 0: {
+ Vehicle *src = &_vehicles[p1 >> 16];
+
+ // sanity checks
+ if (!(src->owner == _current_player && dst->type == src->type && dst != src))
+ return CMD_ERROR;
+
+ if (flags & DC_EXEC) {
+ DeleteVehicleSchedule(dst);
+ dst->schedule_ptr = src->schedule_ptr;
+ dst->num_orders = src->num_orders;
+
+ InvalidateWindow(WC_VEHICLE_ORDERS, src->index);
+ InvalidateWindow(WC_VEHICLE_ORDERS, dst->index);
+ }
+ break;
+ }
+
+ // copy vehicle orders?
+ case 1: {
+ Vehicle *src = &_vehicles[p1 >> 16];
+ int delta;
+
+ // sanity checks
+ if (!(src->owner == _current_player && dst->type == src->type && dst != src))
+ return CMD_ERROR;
+
+ // make sure there's orders available
+ delta = IsScheduleShared(dst) ? src->num_orders + 1 : src->num_orders - dst->num_orders;
+ if (delta > endof(_order_array) - _ptr_to_next_order)
+ return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS);
+
+ if (flags & DC_EXEC) {
+ DeleteVehicleSchedule(dst);
+ dst->schedule_ptr = _ptr_to_next_order;
+ dst->num_orders = src->num_orders;
+ _ptr_to_next_order += src->num_orders + 1;
+ memcpy(dst->schedule_ptr, src->schedule_ptr, (src->num_orders + 1) * sizeof(uint16));
+
+ InvalidateWindow(WC_VEHICLE_ORDERS, dst->index);
+ }
+ break;
+ }
+
+ // declone vehicle orders?
+ case 2: return DecloneOrder(dst, flags);
+ }
+
+ return 0;
+}
+
+void BackupVehicleOrders(Vehicle *v, BackuppedOrders *bak)
+{
+ Vehicle *u = IsScheduleShared(v);
+ uint16 *sched, ord, *os;
+
+ bak->orderindex = v->cur_order_index;
+ bak->service_interval = v->service_interval;
+
+ if ((v->string_id & 0xF800) != 0x7800) {
+ bak->name[0] = 0;
+ } else {
+ GetName(v->string_id & 0x7FF, bak->name);
+ }
+
+ os = bak->order;
+ // stored shared orders in this special way?
+ if (u) {
+ os[0] = 0xFFFF;
+ os[1] = u->index;
+ return;
+ }
+
+ sched = v->schedule_ptr;
+ do {
+ ord = *sched++;
+ *os++ = ord;
+ } while (ord != 0);
+}
+
+void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak)
+{
+ uint16 ord, *os;
+ int ind;
+
+ if (bak->name[0]) {
+ strcpy((char*)_decode_parameters, bak->name);
+ DoCommandP(0, v->index, 0, NULL, CMD_NAME_VEHICLE);
+ }
+
+ DoCommandP(0, v->index, bak->orderindex|(bak->service_interval<<16) , NULL, CMD_RESTORE_ORDER_INDEX | CMD_ASYNC);
+
+ os = bak->order;
+ if (os[0] == 0xFFFF) {
+ DoCommandP(0, v->index | os[1]<<16, 0, NULL, CMD_CLONE_ORDER);
+ return;
+ }
+
+ ind = 0;
+ while ((ord = *os++) != 0) {
+ if (!DoCommandP(0, v->index + (ind << 16), ord, NULL, CMD_INSERT_ORDER | CMD_ASYNC))
+ break;
+ ind++;
+ }
+}
+
+/* p1 = vehicle
+ * upper 16 bits p2 = service_interval
+ * lower 16 bits p2 = cur_order_index
+ */
+int32 CmdRestoreOrderIndex(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+{
+ // nonsense to update the windows, since, train rebought will have its window deleted
+ if (flags & DC_EXEC) {
+ Vehicle *v = &_vehicles[p1];
+ v->service_interval = (uint16)(p2>>16);
+ v->cur_order_index = (byte)(p2&0xFFFF);
+ }
+ return 0;
+}