src/newgrf_engine.cpp
branchgamebalance
changeset 9911 0b8b245a2391
parent 9910 0b2aebc8283e
child 9912 1ac8aac92385
equal deleted inserted replaced
9910:0b2aebc8283e 9911:0b8b245a2391
    61 	wo->trains = trains;
    61 	wo->trains = trains;
    62 	wo->train_id = MallocT<byte>(trains);
    62 	wo->train_id = MallocT<byte>(trains);
    63 	memcpy(wo->train_id, train_id, trains);
    63 	memcpy(wo->train_id, train_id, trains);
    64 }
    64 }
    65 
    65 
    66 static const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, byte overriding_engine)
    66 const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, byte overriding_engine)
    67 {
    67 {
    68 	const WagonOverrides *wos = &_engine_wagon_overrides[engine];
    68 	const WagonOverrides *wos = &_engine_wagon_overrides[engine];
    69 	int i;
       
    70 
    69 
    71 	/* XXX: This could turn out to be a timesink on profiles. We could
    70 	/* XXX: This could turn out to be a timesink on profiles. We could
    72 	 * always just dedicate 65535 bytes for an [engine][train] trampoline
    71 	 * always just dedicate 65535 bytes for an [engine][train] trampoline
    73 	 * for O(1). Or O(logMlogN) and searching binary tree or smt. like
    72 	 * for O(1). Or O(logMlogN) and searching binary tree or smt. like
    74 	 * that. --pasky */
    73 	 * that. --pasky */
    75 
    74 
    76 	for (i = 0; i < wos->overrides_count; i++) {
    75 	for (int i = 0; i < wos->overrides_count; i++) {
    77 		const WagonOverride *wo = &wos->overrides[i];
    76 		const WagonOverride *wo = &wos->overrides[i];
    78 		int j;
    77 
    79 
    78 		if (wo->cargo != cargo && wo->cargo != CT_DEFAULT) continue;
    80 		for (j = 0; j < wo->trains; j++) {
    79 
    81 			if (wo->train_id[j] == overriding_engine && (wo->cargo == cargo || wo->cargo == CT_DEFAULT)) return wo->group;
    80 		for (int j = 0; j < wo->trains; j++) {
       
    81 			if (wo->train_id[j] == overriding_engine) return wo->group;
    82 		}
    82 		}
    83 	}
    83 	}
    84 	return NULL;
    84 	return NULL;
    85 }
    85 }
    86 
    86 
   244  */
   244  */
   245 static byte MapAircraftMovementState(const Vehicle *v)
   245 static byte MapAircraftMovementState(const Vehicle *v)
   246 {
   246 {
   247 	const Station *st = GetStation(v->u.air.targetairport);
   247 	const Station *st = GetStation(v->u.air.targetairport);
   248 	const AirportFTAClass *afc = st->Airport();
   248 	const AirportFTAClass *afc = st->Airport();
   249 	byte amdflag = afc->MovingData(v->u.air.pos)->flag;
   249 	uint16 amdflag = afc->MovingData(v->u.air.pos)->flag;
   250 
   250 
   251 	switch (v->u.air.state) {
   251 	switch (v->u.air.state) {
   252 		case HANGAR:
   252 		case HANGAR:
   253 			/* The international airport is a special case as helicopters can land in
   253 			/* The international airport is a special case as helicopters can land in
   254 			 * front of the hanger. Helicopters also change their air.state to
   254 			 * front of the hanger. Helicopters also change their air.state to
   311 			} else {
   311 			} else {
   312 				return AMS_TTDP_HELI_TAKEOFF_HELIPORT;
   312 				return AMS_TTDP_HELI_TAKEOFF_HELIPORT;
   313 			}
   313 			}
   314 
   314 
   315 		case FLYING:
   315 		case FLYING:
   316 			return AMS_TTDP_FLIGHT_TO_TOWER;
   316 			return amdflag & AMED_HOLD ? AMS_TTDP_FLIGHT_APPROACH : AMS_TTDP_FLIGHT_TO_TOWER;
   317 
   317 
   318 		case LANDING: // Descent
   318 		case LANDING: // Descent
   319 			return AMS_TTDP_FLIGHT_DESCENT;
   319 			return AMS_TTDP_FLIGHT_DESCENT;
   320 
   320 
   321 		case ENDLANDING: // On the runway braking
   321 		case ENDLANDING: // On the runway braking
   466 	if (parameter >= file->param_end) return 0;
   466 	if (parameter >= file->param_end) return 0;
   467 	return file->param[parameter];
   467 	return file->param[parameter];
   468 }
   468 }
   469 
   469 
   470 
   470 
       
   471 static uint8 LiveryHelper(EngineID engine, const Vehicle *v)
       
   472 {
       
   473 	const Livery *l;
       
   474 
       
   475 	if (v == NULL) {
       
   476 		l = GetEngineLivery(engine, _current_player, INVALID_ENGINE, NULL);
       
   477 	} else if (v->type == VEH_TRAIN) {
       
   478 		l = GetEngineLivery((v->u.rail.first_engine != INVALID_ENGINE && (IsArticulatedPart(v) || UsesWagonOverride(v))) ? v->u.rail.first_engine : v->engine_type, v->owner, v->u.rail.first_engine, v);
       
   479 	} else {
       
   480 		l = GetEngineLivery(v->engine_type, v->owner, INVALID_ENGINE, v);
       
   481 	}
       
   482 
       
   483 	return l->colour1 + l->colour2 * 16;
       
   484 }
       
   485 
       
   486 
   471 static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
   487 static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
   472 {
   488 {
   473 	const Vehicle *v = GRV(object);
   489 	const Vehicle *v = GRV(object);
   474 
   490 
   475 	if (v == NULL) {
   491 	if (v == NULL) {
   476 		/* Vehicle does not exist, so we're in a purchase list */
   492 		/* Vehicle does not exist, so we're in a purchase list */
   477 		switch (variable) {
   493 		switch (variable) {
   478 			case 0x43: return _current_player; // Owner information
   494 			case 0x43: return _current_player | (LiveryHelper(object->u.vehicle.self_type, NULL) << 24); // Owner information
   479 			case 0x46: return 0;               // Motion counter
   495 			case 0x46: return 0;               // Motion counter
   480 			case 0x48: return GetEngine(object->u.vehicle.self_type)->flags; // Vehicle Type Info
   496 			case 0x48: return GetEngine(object->u.vehicle.self_type)->flags; // Vehicle Type Info
   481 			case 0xC4: return clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year
   497 			case 0xC4: return clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year
   482 			case 0xDA: return INVALID_VEHICLE; // Next vehicle
   498 			case 0xDA: return INVALID_VEHICLE; // Next vehicle
   483 			case 0x7F: return GetGRFParameter(object->u.vehicle.self_type, parameter); // Read GRF parameter
   499 			case 0x7F: return GetGRFParameter(object->u.vehicle.self_type, parameter); // Read GRF parameter
   542 
   558 
   543 			return cargo_classes | (common_cargo_type << 8) | (user_def_data << 24);
   559 			return cargo_classes | (common_cargo_type << 8) | (user_def_data << 24);
   544 		}
   560 		}
   545 
   561 
   546 		case 0x43: // Player information
   562 		case 0x43: // Player information
   547 			return v->owner;
   563 			return v->owner | (GetPlayer(v->owner)->is_ai ? 0x10000 : 0) | (LiveryHelper(v->engine_type, v) << 24);
   548 
   564 
   549 		case 0x44: // Aircraft information
   565 		case 0x44: // Aircraft information
   550 			if (v->type != VEH_AIRCRAFT) return UINT_MAX;
   566 			if (v->type != VEH_AIRCRAFT) return UINT_MAX;
   551 
   567 
   552 			{
   568 			{
   570 					default:               airporttype = ATP_TTDP_LARGE; break;
   586 					default:               airporttype = ATP_TTDP_LARGE; break;
   571 				}
   587 				}
   572 
   588 
   573 				return (altitude << 8) | airporttype;
   589 				return (altitude << 8) | airporttype;
   574 			}
   590 			}
       
   591 
       
   592 		case 0x45: { // Curvature info
       
   593 			/* Format: xxxTxBxF
       
   594 			 * F - previous wagon to current wagon, 0 if vehicle is first
       
   595 			 * B - current wagon to next wagon, 0 if wagon is last
       
   596 			 * T - previous wagon to next wagon, 0 in an S-bend
       
   597 			 */
       
   598 			if (v->type != VEH_TRAIN) return 0;
       
   599 
       
   600 			const Vehicle *u_p = GetPrevVehicleInChain(v);
       
   601 			const Vehicle *u_n = v->next;
       
   602 			DirDiff f = (u_p == NULL) ?  DIRDIFF_SAME : DirDifference(u_p->direction, v->direction);
       
   603 			DirDiff b = (u_n == NULL) ?  DIRDIFF_SAME : DirDifference(v->direction, u_n->direction);
       
   604 			DirDiff t = ChangeDirDiff(f, b);
       
   605 
       
   606 			return ((t > DIRDIFF_REVERSE ? t | 8 : t) << 16) |
       
   607 			       ((b > DIRDIFF_REVERSE ? b | 8 : b) <<  8) |
       
   608 			       ( f > DIRDIFF_REVERSE ? f | 8 : f);
       
   609 		}
   575 
   610 
   576 		case 0x46: // Motion counter
   611 		case 0x46: // Motion counter
   577 			return v->motion_counter;
   612 			return v->motion_counter;
   578 
   613 
   579 		case 0x47: { // Vehicle cargo info
   614 		case 0x47: { // Vehicle cargo info
   733 				case 0x62: return MapAircraftMovementState(v);  // Current movement state
   768 				case 0x62: return MapAircraftMovementState(v);  // Current movement state
   734 				case 0x63: return v->u.air.targetairport;       // Airport to which the action refers
   769 				case 0x63: return v->u.air.targetairport;       // Airport to which the action refers
   735 				case 0x66: return MapAircraftMovementAction(v); // Current movement action
   770 				case 0x66: return MapAircraftMovementAction(v); // Current movement action
   736 			}
   771 			}
   737 			break;
   772 			break;
       
   773 
       
   774 		default: break;
   738 	}
   775 	}
   739 
   776 
   740 	DEBUG(grf, 1, "Unhandled vehicle property 0x%X, type 0x%X", variable, v->type);
   777 	DEBUG(grf, 1, "Unhandled vehicle property 0x%X, type 0x%X", variable, v->type);
   741 
   778 
   742 	*available = false;
   779 	*available = false;
   813 		cargo = CT_PURCHASE;
   850 		cargo = CT_PURCHASE;
   814 	} else {
   851 	} else {
   815 		cargo = v->cargo_type;
   852 		cargo = v->cargo_type;
   816 
   853 
   817 		if (v->type == VEH_TRAIN) {
   854 		if (v->type == VEH_TRAIN) {
   818 			group = GetWagonOverrideSpriteSet(engine, cargo, v->u.rail.first_engine);
   855 			group = v->u.rail.cached_override;
   819 
       
   820 			if (group != NULL) return group;
   856 			if (group != NULL) return group;
   821 		}
   857 		}
   822 	}
   858 	}
   823 
   859 
   824 	group = _engine_custom_sprites[engine][cargo];
   860 	group = _engine_custom_sprites[engine][cargo];
   875  * @return true if it is using an override, false otherwise
   911  * @return true if it is using an override, false otherwise
   876  */
   912  */
   877 bool UsesWagonOverride(const Vehicle* v)
   913 bool UsesWagonOverride(const Vehicle* v)
   878 {
   914 {
   879 	assert(v->type == VEH_TRAIN);
   915 	assert(v->type == VEH_TRAIN);
   880 	return GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, v->u.rail.first_engine) != NULL;
   916 	return v->u.rail.cached_override != NULL;
   881 }
   917 }
   882 
   918 
   883 /**
   919 /**
   884  * Evaluate a newgrf callback for vehicles
   920  * Evaluate a newgrf callback for vehicles
   885  * @param callback The callback to evalute
   921  * @param callback The callback to evalute
   934 
   970 
   935 	return group->g.callback.result;
   971 	return group->g.callback.result;
   936 }
   972 }
   937 
   973 
   938 
   974 
   939 /* Callback 36 handler */
   975 /* Callback 36 handlers */
   940 uint GetVehicleProperty(const Vehicle *v, uint8 property, uint orig_value)
   976 uint GetVehicleProperty(const Vehicle *v, uint8 property, uint orig_value)
   941 {
   977 {
   942 	uint16 callback = GetVehicleCallback(CBID_VEHICLE_MODIFY_PROPERTY, property, 0, v->engine_type, v);
   978 	uint16 callback = GetVehicleCallback(CBID_VEHICLE_MODIFY_PROPERTY, property, 0, v->engine_type, v);
       
   979 	if (callback != CALLBACK_FAILED) return callback;
       
   980 
       
   981 	return orig_value;
       
   982 }
       
   983 
       
   984 
       
   985 uint GetEngineProperty(EngineID engine, uint8 property, uint orig_value)
       
   986 {
       
   987 	uint16 callback = GetVehicleCallback(CBID_VEHICLE_MODIFY_PROPERTY, property, 0, engine, NULL);
   943 	if (callback != CALLBACK_FAILED) return callback;
   988 	if (callback != CALLBACK_FAILED) return callback;
   944 
   989 
   945 	return orig_value;
   990 	return orig_value;
   946 }
   991 }
   947 
   992