train_cmd.c
changeset 1917 74cab7e464d1
parent 1909 8ef1a310dd39
child 1921 263f1bcfc038
equal deleted inserted replaced
1916:efad85af0599 1917:74cab7e464d1
    58 	// store consist weight in cache
    58 	// store consist weight in cache
    59 	v->u.rail.cached_weight = weight;
    59 	v->u.rail.cached_weight = weight;
    60 }
    60 }
    61 
    61 
    62 /**
    62 /**
    63  * Recalculates the cached stuff of a train. Should be called each time a vehicle is added to/removed from
    63  * Recalculates the cached stuff of a train. Should be called each time a vehicle is added
    64  * the consist, and when the game is loaded.
    64  * to/removed from the chain, and when the game is loaded.
    65  * @param v First vehicle of the consist.
    65  * Note: this needs to be called too for 'wagon chains' (in the depot, without an engine)
       
    66  * @param v First vehicle of the chain.
    66  */
    67  */
    67 void TrainConsistChanged(Vehicle *v) {
    68 void TrainConsistChanged(Vehicle *v) {
    68 	const RailVehicleInfo *rvi_v = RailVehInfo(v->engine_type);
    69 	const RailVehicleInfo *rvi_v;
    69 	Vehicle *u;
    70 	Vehicle *u;
    70 	uint16 max_speed = 0xFFFF;
    71 	uint16 max_speed = 0xFFFF;
    71 	uint32 power = 0;
    72 	uint32 power = 0;
       
    73 	EngineID first_engine;
       
    74 
       
    75 	assert(v->type == VEH_Train);
       
    76 
       
    77 	assert(v->subtype == TS_Front_Engine || v->subtype == TS_Free_Car);
       
    78 
       
    79 	rvi_v = RailVehInfo(v->engine_type);
       
    80 	first_engine = (v->subtype == TS_Front_Engine) ? v->engine_type : INVALID_VEHICLE;
    72 
    81 
    73 	for (u = v; u != NULL; u = u->next) {
    82 	for (u = v; u != NULL; u = u->next) {
    74 		const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
    83 		const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
       
    84 
       
    85 		// update the 'first engine'
       
    86 		u->u.rail.first_engine = (v == u) ? INVALID_VEHICLE : first_engine;
    75 
    87 
    76 		// power is the sum of the powers of all engines and powered wagons in the consist
    88 		// power is the sum of the powers of all engines and powered wagons in the consist
    77 		power += rvi_u->power;
    89 		power += rvi_u->power;
    78 
    90 
    79 		// check if its a powered wagon
    91 		// check if its a powered wagon
   447 
   459 
   448 			v->subtype = TS_Free_Car;
   460 			v->subtype = TS_Free_Car;
   449 			if (u != NULL) {
   461 			if (u != NULL) {
   450 				u->next = v;
   462 				u->next = v;
   451 				v->subtype = TS_Not_First;
   463 				v->subtype = TS_Not_First;
   452 				v->u.rail.first_engine = u->u.rail.first_engine;
       
   453 				if (v->u.rail.first_engine == 0xffff && u->subtype == TS_Front_Engine)
       
   454 					v->u.rail.first_engine = u->engine_type;
       
   455 			} else {
       
   456 				v->u.rail.first_engine = 0xffff;
       
   457 			}
   464 			}
   458 
   465 
   459 			v->cargo_type = rvi->cargo_type;
   466 			v->cargo_type = rvi->cargo_type;
   460 			v->cargo_cap = rvi->capacity;
   467 			v->cargo_cap = rvi->capacity;
   461 			v->value = value;
   468 			v->value = value;
   469 			v->cur_image = 0xAC2;
   476 			v->cur_image = 0xAC2;
   470 
   477 
   471 			_new_wagon_id = v->index;
   478 			_new_wagon_id = v->index;
   472 
   479 
   473 			VehiclePositionChanged(v);
   480 			VehiclePositionChanged(v);
       
   481 			TrainConsistChanged(GetFirstVehicleInChain(v));
   474 
   482 
   475 			InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
   483 			InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
   476 		}
   484 		}
   477 	}
   485 	}
   478 
   486 
   545 	u->x_pos = v->x_pos;
   553 	u->x_pos = v->x_pos;
   546 	u->y_pos = v->y_pos;
   554 	u->y_pos = v->y_pos;
   547 	u->z_pos = v->z_pos;
   555 	u->z_pos = v->z_pos;
   548 	u->z_height = 6;
   556 	u->z_height = 6;
   549 	u->u.rail.track = 0x80;
   557 	u->u.rail.track = 0x80;
   550 	v->u.rail.first_engine = 0xffff;
       
   551 	u->vehstatus = v->vehstatus & ~VS_STOPPED;
   558 	u->vehstatus = v->vehstatus & ~VS_STOPPED;
   552 	u->subtype = TS_Not_First;
   559 	u->subtype = TS_Not_First;
   553 	u->spritenum = v->spritenum + 1;
   560 	u->spritenum = v->spritenum + 1;
   554 	u->cargo_type = v->cargo_type;
   561 	u->cargo_type = v->cargo_type;
   555 	u->cargo_cap = v->cargo_cap;
   562 	u->cargo_cap = v->cargo_cap;
   618 			v->x_pos = (x |= _vehicle_initial_x_fract[dir]);
   625 			v->x_pos = (x |= _vehicle_initial_x_fract[dir]);
   619 			v->y_pos = (y |= _vehicle_initial_y_fract[dir]);
   626 			v->y_pos = (y |= _vehicle_initial_y_fract[dir]);
   620 			v->z_pos = GetSlopeZ(x,y);
   627 			v->z_pos = GetSlopeZ(x,y);
   621 			v->z_height = 6;
   628 			v->z_height = 6;
   622 			v->u.rail.track = 0x80;
   629 			v->u.rail.track = 0x80;
   623 			v->u.rail.first_engine = 0xffff;
       
   624 			v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
   630 			v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
   625 			v->spritenum = rvi->image_index;
   631 			v->spritenum = rvi->image_index;
   626 			v->cargo_type = rvi->cargo_type;
   632 			v->cargo_type = rvi->cargo_type;
   627 			v->cargo_cap = rvi->capacity;
   633 			v->cargo_cap = rvi->capacity;
   628 			v->max_speed = rvi->max_speed;
   634 			v->max_speed = rvi->max_speed;
   703 // returns the new value of first
   709 // returns the new value of first
   704 static Vehicle *UnlinkWagon(Vehicle *v, Vehicle *first)
   710 static Vehicle *UnlinkWagon(Vehicle *v, Vehicle *first)
   705 {
   711 {
   706 	Vehicle *u;
   712 	Vehicle *u;
   707 
   713 
   708 	v->u.rail.first_engine = INVALID_VEHICLE;
       
   709 
       
   710 	// unlinking the first vehicle of the chain?
   714 	// unlinking the first vehicle of the chain?
   711 	if (v == first) {
   715 	if (v == first) {
   712 		v = v->next;
   716 		v = v->next;
   713 		if (v == NULL) return NULL;
   717 		if (v == NULL) return NULL;
   714 
   718 
   715 		for (u = v; u != NULL; u = u->next) u->u.rail.first_engine = v->engine_type;
       
   716 		v->subtype = TS_Free_Car;
   719 		v->subtype = TS_Free_Car;
   717 		return v;
   720 		return v;
   718 	}
   721 	}
   719 
   722 
   720 	for (u = first; u->next != v; u = u->next) {}
   723 	for (u = first; u->next != v; u = u->next) {}
   836 			// unlink ALL wagons
   839 			// unlink ALL wagons
   837 			if (src != src_head) {
   840 			if (src != src_head) {
   838 				Vehicle *v = src_head;
   841 				Vehicle *v = src_head;
   839 				while (v->next != src) v=v->next;
   842 				while (v->next != src) v=v->next;
   840 				v->next = NULL;
   843 				v->next = NULL;
       
   844 			} else {
       
   845 				src_head = NULL;
   841 			}
   846 			}
   842 		} else {
   847 		} else {
   843 			// unlink single wagon from linked list
   848 			// unlink single wagon from linked list
   844 			UnlinkWagon(src, src_head);
   849 			src_head = UnlinkWagon(src, src_head);
   845 			src->next = NULL;
   850 			src->next = NULL;
   846 		}
   851 		}
   847 
   852 
   848 		if (dst == NULL) {
   853 		if (dst == NULL) {
   849 			// move the train to an empty line. for locomotives, we set the type to 0. for wagons, 4.
   854 			// move the train to an empty line. for locomotives, we set the type to 0. for wagons, 4.
   852 					// setting the type to 0 also involves setting up the orders field.
   857 					// setting the type to 0 also involves setting up the orders field.
   853 					src->subtype = TS_Front_Engine;
   858 					src->subtype = TS_Front_Engine;
   854 					assert(src->orders == NULL);
   859 					assert(src->orders == NULL);
   855 					src->num_orders = 0;
   860 					src->num_orders = 0;
   856 				}
   861 				}
   857 				dst_head = src;
       
   858 			} else {
   862 			} else {
   859 				src->subtype = TS_Free_Car;
   863 				src->subtype = TS_Free_Car;
   860 			}
   864 			}
   861 			src->u.rail.first_engine = 0xffff;
   865 			dst_head = src;
   862 		} else {
   866 		} else {
   863 			if (src->subtype == TS_Front_Engine) {
   867 			if (src->subtype == TS_Front_Engine) {
   864 				// the vehicle was previously a loco. need to free the order list and delete vehicle windows etc.
   868 				// the vehicle was previously a loco. need to free the order list and delete vehicle windows etc.
   865 				DeleteWindowById(WC_VEHICLE_VIEW, src->index);
   869 				DeleteWindowById(WC_VEHICLE_VIEW, src->index);
   866 				DeleteVehicleOrders(src);
   870 				DeleteVehicleOrders(src);
   867 			}
   871 			}
   868 
   872 
   869 			src->subtype = TS_Not_First;
   873 			src->subtype = TS_Not_First;
   870 			src->unitnumber = 0; // doesn't occupy a unitnumber anymore.
   874 			src->unitnumber = 0; // doesn't occupy a unitnumber anymore.
   871 
   875 
   872 			// setup first_engine
       
   873 			src->u.rail.first_engine = dst->u.rail.first_engine;
       
   874 			if (src->u.rail.first_engine == 0xffff && dst->subtype == TS_Front_Engine)
       
   875 				src->u.rail.first_engine = dst->engine_type;
       
   876 
       
   877 			// link in the wagon(s) in the chain.
   876 			// link in the wagon(s) in the chain.
   878 			{
   877 			{
   879 				Vehicle *v;
   878 				Vehicle *v;
   880 
   879 
   881 				for (v = src; v->next != NULL; v = v->next) {
   880 				for (v = src; v->next != NULL; v = v->next) {};
   882 					v->next->u.rail.first_engine = v->u.rail.first_engine;
       
   883 				}
       
   884 				v->next = dst->next;
   881 				v->next = dst->next;
   885 			}
   882 			}
   886 			dst->next = src;
   883 			dst->next = src;
   887 		}
   884 		}
   888 
   885 
   889 		if (src_head->subtype == TS_Front_Engine) {
   886 		if (src_head) {
   890 			TrainConsistChanged(src_head);
   887 			TrainConsistChanged(src_head);
   891 			UpdateTrainAcceleration(src_head);
   888 			if (src_head->subtype == TS_Front_Engine) {
   892 		}
   889 				UpdateTrainAcceleration(src_head);
   893 		InvalidateWindow(WC_VEHICLE_DETAILS, src_head->index);
   890 				InvalidateWindow(WC_VEHICLE_DETAILS, src_head->index);
   894 		InvalidateWindow(WC_VEHICLE_REFIT, src_head->index);
   891 				/* Update the refit button and window */
       
   892 				InvalidateWindow(WC_VEHICLE_REFIT, src_head->index);
       
   893 				InvalidateWindowWidget(WC_VEHICLE_VIEW, src_head->index, 12);
       
   894 			}
       
   895 			/* Update the depot window */
       
   896 			InvalidateWindow(WC_VEHICLE_DEPOT, src_head->tile);
       
   897 		};
   895 
   898 
   896 		if (dst_head) {
   899 		if (dst_head) {
       
   900 			TrainConsistChanged(dst_head);
   897 			if (dst_head->subtype == TS_Front_Engine) {
   901 			if (dst_head->subtype == TS_Front_Engine) {
   898 				TrainConsistChanged(dst_head);
       
   899 				UpdateTrainAcceleration(dst_head);
   902 				UpdateTrainAcceleration(dst_head);
   900 			}
   903 				InvalidateWindow(WC_VEHICLE_DETAILS, dst_head->index);
   901 			InvalidateWindow(WC_VEHICLE_DETAILS, dst_head->index);
   904 				/* Update the refit button and window */
   902 			/* Update the refit button and window */
   905 				InvalidateWindowWidget(WC_VEHICLE_VIEW, dst_head->index, 12);
   903 			InvalidateWindowWidget(WC_VEHICLE_VIEW, dst_head->index, 12);
   906 				InvalidateWindow(WC_VEHICLE_REFIT, dst_head->index);
   904 			InvalidateWindow(WC_VEHICLE_REFIT, dst_head->index);
   907 			}
   905 		}
   908 			/* Update the depot window */
   906 
   909 			InvalidateWindow(WC_VEHICLE_DEPOT, dst_head->tile);
   907 		/* I added this to so that the refit buttons get updated */
   910 		}
   908 		InvalidateWindowWidget(WC_VEHICLE_VIEW, src_head->index, 12);
   911 
   909 		InvalidateWindow(WC_VEHICLE_DEPOT, src_head->tile);
       
   910 		RebuildVehicleLists();
   912 		RebuildVehicleLists();
   911 	}
   913 	}
   912 
   914 
   913 	return 0;
   915 	return 0;
   914 }
   916 }
  1046 				/* 4 If the second wagon was an engine, update it to front_engine
  1048 				/* 4 If the second wagon was an engine, update it to front_engine
  1047 					* which UnlinkWagon() has changed to TS_Free_Car */
  1049 					* which UnlinkWagon() has changed to TS_Free_Car */
  1048 				if (switch_engine) first->subtype = TS_Front_Engine;
  1050 				if (switch_engine) first->subtype = TS_Front_Engine;
  1049 
  1051 
  1050 				/* 5. If the train still exists, update its acceleration, window, etc. */
  1052 				/* 5. If the train still exists, update its acceleration, window, etc. */
  1051 				if (first != NULL && first->subtype == TS_Front_Engine) {
  1053 				if (first != NULL) {
  1052 					InvalidateWindow(WC_VEHICLE_DETAILS, first->index);
       
  1053 					InvalidateWindow(WC_VEHICLE_REFIT, first->index);
       
  1054 					TrainConsistChanged(first);
  1054 					TrainConsistChanged(first);
  1055 					UpdateTrainAcceleration(first);
  1055 					if (first->subtype == TS_Front_Engine) {
       
  1056 						InvalidateWindow(WC_VEHICLE_DETAILS, first->index);
       
  1057 						InvalidateWindow(WC_VEHICLE_REFIT, first->index);
       
  1058 						UpdateTrainAcceleration(first);
       
  1059 					}
  1056 				}
  1060 				}
  1057 
  1061 
  1058 
  1062 
  1059 				/* (6.) Borked AI. If it sells an engine it expects all wagons lined
  1063 				/* (6.) Borked AI. If it sells an engine it expects all wagons lined
  1060 				* up on a new line to be added to the newly built loco. Replace it is.
  1064 				* up on a new line to be added to the newly built loco. Replace it is.
  1101 					DeleteVehicle(v);
  1105 					DeleteVehicle(v);
  1102 				}
  1106 				}
  1103 			}
  1107 			}
  1104 
  1108 
  1105 			/* 3. If it is still a valid train after selling, update its acceleration and cached values */
  1109 			/* 3. If it is still a valid train after selling, update its acceleration and cached values */
  1106 			if ((flags & DC_EXEC) && first != NULL && first->subtype == TS_Front_Engine) {
  1110 			if ((flags & DC_EXEC) && first != NULL) {
  1107 				TrainConsistChanged(first);
  1111 				TrainConsistChanged(first);
  1108 				UpdateTrainAcceleration(first);
  1112 				if (first->subtype == TS_Front_Engine)
       
  1113 					UpdateTrainAcceleration(first);
  1109 			}
  1114 			}
  1110 		} break;
  1115 		} break;
  1111 	}
  1116 	}
  1112 	return cost;
  1117 	return cost;
  1113 }
  1118 }