train_cmd.c
branch0.5
changeset 5513 0d3227e250eb
parent 5509 0b111f4e6dc9
child 5518 d5923d3fa08c
equal deleted inserted replaced
5512:52869fa67090 5513:0d3227e250eb
  2913 		UpdateSignalsOnSegment(tile, _otherside_signal_directions[i]);
  2913 		UpdateSignalsOnSegment(tile, _otherside_signal_directions[i]);
  2914 	}
  2914 	}
  2915 }
  2915 }
  2916 
  2916 
  2917 
  2917 
  2918 typedef struct TrainCollideChecker {
       
  2919 	const Vehicle *v;
       
  2920 	const Vehicle *v_skip;
       
  2921 } TrainCollideChecker;
       
  2922 
       
  2923 static void *FindTrainCollideEnum(Vehicle *v, void *data)
       
  2924 {
       
  2925 	const TrainCollideChecker* tcc = data;
       
  2926 
       
  2927 	if (v != tcc->v &&
       
  2928 			v != tcc->v_skip &&
       
  2929 			v->type == VEH_Train &&
       
  2930 			v->u.rail.track != 0x80 &&
       
  2931 			myabs(v->z_pos - tcc->v->z_pos) <= 6 &&
       
  2932 			myabs(v->x_pos - tcc->v->x_pos) < 6 &&
       
  2933 			myabs(v->y_pos - tcc->v->y_pos) < 6) {
       
  2934 		return v;
       
  2935 	} else {
       
  2936 		return NULL;
       
  2937 	}
       
  2938 }
       
  2939 
       
  2940 static void SetVehicleCrashed(Vehicle *v)
  2918 static void SetVehicleCrashed(Vehicle *v)
  2941 {
  2919 {
  2942 	Vehicle *u;
  2920 	Vehicle *u;
  2943 
  2921 
  2944 	if (v->u.rail.crash_anim_pos != 0) return;
  2922 	if (v->u.rail.crash_anim_pos != 0) return;
  2958 	uint num = 0;
  2936 	uint num = 0;
  2959 	BEGIN_ENUM_WAGONS(v)
  2937 	BEGIN_ENUM_WAGONS(v)
  2960 		if (v->cargo_type == CT_PASSENGERS) num += v->cargo_count;
  2938 		if (v->cargo_type == CT_PASSENGERS) num += v->cargo_count;
  2961 	END_ENUM_WAGONS(v)
  2939 	END_ENUM_WAGONS(v)
  2962 	return num;
  2940 	return num;
       
  2941 }
       
  2942 
       
  2943 typedef struct TrainCollideChecker {
       
  2944 	Vehicle *v;
       
  2945 	const Vehicle *v_skip;
       
  2946 	uint num;
       
  2947 } TrainCollideChecker;
       
  2948 
       
  2949 static void *FindTrainCollideEnum(Vehicle *v, void *data)
       
  2950 {
       
  2951 	TrainCollideChecker* tcc = (TrainCollideChecker*)data;
       
  2952 
       
  2953 	if (v != tcc->v &&
       
  2954 			v != tcc->v_skip &&
       
  2955 			v->type == VEH_Train &&
       
  2956 			v->u.rail.track != 0x80 &&
       
  2957 			myabs(v->z_pos - tcc->v->z_pos) < 6 &&
       
  2958 			myabs(v->x_pos - tcc->v->x_pos) < 6 &&
       
  2959 			myabs(v->y_pos - tcc->v->y_pos) < 6 ) {
       
  2960 
       
  2961 		Vehicle *coll = GetFirstVehicleInChain(v);
       
  2962 
       
  2963 		/* it can't collide with its own wagons */
       
  2964 		if (tcc->v == coll ||
       
  2965 			(tcc->v->u.rail.track == 0x40 && (tcc->v->direction & 2) != (v->direction & 2)))
       
  2966 			return NULL;
       
  2967 
       
  2968 		/* two drivers + passengers killed in train tcc->v (if it was not crashed already) */
       
  2969 		if (!(tcc->v->vehstatus & VS_CRASHED)) {
       
  2970 			tcc->num += 2 + CountPassengersInTrain(tcc->v);
       
  2971 			SetVehicleCrashed(tcc->v);
       
  2972 		}
       
  2973 
       
  2974 		if (!(coll->vehstatus & VS_CRASHED)) {
       
  2975 			/* two drivers + passengers killed in train coll (if it was not crashed already) */
       
  2976 			tcc->num += 2 + CountPassengersInTrain(coll);
       
  2977 			SetVehicleCrashed(coll);
       
  2978 		}
       
  2979 	}
       
  2980 
       
  2981 	return NULL;
  2963 }
  2982 }
  2964 
  2983 
  2965 /*
  2984 /*
  2966  * Checks whether the specified train has a collision with another vehicle. If
  2985  * Checks whether the specified train has a collision with another vehicle. If
  2967  * so, destroys this vehicle, and the other vehicle if its subtype has TS_Front.
  2986  * so, destroys this vehicle, and the other vehicle if its subtype has TS_Front.
  2969  * plays a sound.
  2988  * plays a sound.
  2970  */
  2989  */
  2971 static void CheckTrainCollision(Vehicle *v)
  2990 static void CheckTrainCollision(Vehicle *v)
  2972 {
  2991 {
  2973 	TrainCollideChecker tcc;
  2992 	TrainCollideChecker tcc;
  2974 	Vehicle *coll;
       
  2975 	Vehicle *realcoll;
       
  2976 	uint num;
       
  2977 
  2993 
  2978 	/* can't collide in depot */
  2994 	/* can't collide in depot */
  2979 	if (v->u.rail.track == 0x80) return;
  2995 	if (v->u.rail.track == 0x80) return;
  2980 
  2996 
  2981 	assert(v->u.rail.track == 0x40 || TileVirtXY(v->x_pos, v->y_pos) == v->tile);
  2997 	assert(v->u.rail.track == 0x40 || TileVirtXY(v->x_pos, v->y_pos) == v->tile);
  2982 
  2998 
  2983 	tcc.v = v;
  2999 	tcc.v = v;
  2984 	tcc.v_skip = v->next;
  3000 	tcc.v_skip = v->next;
  2985 
  3001 	tcc.num = 0;
  2986 	/* find colliding vehicle */
  3002 
  2987 	realcoll = VehicleFromPos(TileVirtXY(v->x_pos, v->y_pos), &tcc, FindTrainCollideEnum);
  3003 	/* find colliding vehicles */
  2988 	if (realcoll == NULL) return;
  3004 	VehicleFromPos(v->tile, &tcc, FindTrainCollideEnum);
  2989 
  3005 
  2990 	coll = GetFirstVehicleInChain(realcoll);
  3006 	/* any dead -> no crash */
  2991 
  3007 	if (tcc.num == 0) return;
  2992 	/* it can't collide with its own wagons */
  3008 
  2993 	if (v == coll ||
  3009 	SetDParam(0, tcc.num);
  2994 			(v->u.rail.track & 0x40 && (v->direction & 2) != (realcoll->direction & 2)))
       
  2995 		return;
       
  2996 
       
  2997 	//two drivers + passangers killed in train v
       
  2998 	num = 2 + CountPassengersInTrain(v);
       
  2999 	if (!(coll->vehstatus & VS_CRASHED))
       
  3000 		//two drivers + passangers killed in train coll (if it was not crashed already)
       
  3001 		num += 2 + CountPassengersInTrain(coll);
       
  3002 
       
  3003 	SetVehicleCrashed(v);
       
  3004 	if (IsFrontEngine(coll)) SetVehicleCrashed(coll);
       
  3005 
       
  3006 	SetDParam(0, num);
       
  3007 	AddNewsItem(STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL,
  3010 	AddNewsItem(STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL,
  3008 		NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ACCIDENT, 0),
  3011 		NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ACCIDENT, 0),
  3009 		v->index,
  3012 		v->index,
  3010 		0
  3013 		0
  3011 	);
  3014 	);