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 |