|
|
|
@ -973,12 +973,13 @@ static const GRFFile *GetEngineGrfFile(EngineID engine_type)
|
|
|
|
|
* Resolver of a vehicle (chain).
|
|
|
|
|
* @param engine_type Engine type
|
|
|
|
|
* @param v %Vehicle being resolved.
|
|
|
|
|
* @param wagon_override Application of wagon overrides.
|
|
|
|
|
* @param info_view Indicates if the item is being drawn in an info window.
|
|
|
|
|
* @param callback Callback ID.
|
|
|
|
|
* @param callback_param1 First parameter (var 10) of the callback.
|
|
|
|
|
* @param callback_param2 Second parameter (var 18) of the callback.
|
|
|
|
|
*/
|
|
|
|
|
VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle *v, bool info_view,
|
|
|
|
|
VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle *v, WagonOverride wagon_override, bool info_view,
|
|
|
|
|
CallbackID callback, uint32 callback_param1, uint32 callback_param2)
|
|
|
|
|
: ResolverObject(GetEngineGrfFile(engine_type), callback, callback_param1, callback_param2),
|
|
|
|
|
self_scope(*this, engine_type, v, info_view),
|
|
|
|
@ -986,55 +987,37 @@ VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle
|
|
|
|
|
relative_scope(*this, engine_type, v, info_view),
|
|
|
|
|
cached_relative_count(0)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Retrieve the SpriteGroup for the specified vehicle.
|
|
|
|
|
* If the vehicle is not specified, the purchase list group for the engine is
|
|
|
|
|
* chosen. For trains, an additional engine override lookup is performed.
|
|
|
|
|
* @param engine Engine type of the vehicle.
|
|
|
|
|
* @param v The vehicle itself.
|
|
|
|
|
* @param use_cache Use cached override
|
|
|
|
|
* @returns The selected SpriteGroup for the vehicle.
|
|
|
|
|
*/
|
|
|
|
|
static const SpriteGroup *GetVehicleSpriteGroup(EngineID engine, const Vehicle *v, bool use_cache = true)
|
|
|
|
|
{
|
|
|
|
|
const SpriteGroup *group;
|
|
|
|
|
CargoID cargo;
|
|
|
|
|
|
|
|
|
|
if (v == NULL) {
|
|
|
|
|
cargo = CT_PURCHASE;
|
|
|
|
|
if (wagon_override == WO_SELF) {
|
|
|
|
|
this->root_spritegroup = GetWagonOverrideSpriteSet(engine_type, CT_DEFAULT, engine_type);
|
|
|
|
|
} else {
|
|
|
|
|
cargo = v->cargo_type;
|
|
|
|
|
if (wagon_override != WO_NONE && v != NULL && v->IsGroundVehicle()) {
|
|
|
|
|
assert(v->engine_type == engine_type); // overrides make little sense with fake scopes
|
|
|
|
|
|
|
|
|
|
if (v->IsGroundVehicle()) {
|
|
|
|
|
/* For trains we always use cached value, except for callbacks because the override spriteset
|
|
|
|
|
* to use may be different than the one cached. It happens for callback 0x15 (refit engine),
|
|
|
|
|
* as v->cargo_type is temporary changed to the new type */
|
|
|
|
|
if (use_cache && v->type == VEH_TRAIN) {
|
|
|
|
|
group = Train::From(v)->tcache.cached_override;
|
|
|
|
|
if (wagon_override == WO_CACHED && v->type == VEH_TRAIN) {
|
|
|
|
|
this->root_spritegroup = Train::From(v)->tcache.cached_override;
|
|
|
|
|
} else {
|
|
|
|
|
group = GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, v->GetGroundVehicleCache()->first_engine);
|
|
|
|
|
this->root_spritegroup = GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, v->GetGroundVehicleCache()->first_engine);
|
|
|
|
|
}
|
|
|
|
|
if (group != NULL) return group;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Engine *e = Engine::Get(engine);
|
|
|
|
|
|
|
|
|
|
assert(cargo < lengthof(e->grf_prop.spritegroup));
|
|
|
|
|
group = e->grf_prop.spritegroup[cargo];
|
|
|
|
|
if (group != NULL) return group;
|
|
|
|
|
|
|
|
|
|
/* Fall back to the default set if the selected cargo type is not defined */
|
|
|
|
|
return e->grf_prop.spritegroup[CT_DEFAULT];
|
|
|
|
|
if (this->root_spritegroup == NULL) {
|
|
|
|
|
const Engine *e = Engine::Get(engine_type);
|
|
|
|
|
CargoID cargo = v != NULL ? v->cargo_type : CT_PURCHASE;
|
|
|
|
|
assert(cargo < lengthof(e->grf_prop.spritegroup));
|
|
|
|
|
this->root_spritegroup = e->grf_prop.spritegroup[cargo] != NULL ? e->grf_prop.spritegroup[cargo] : e->grf_prop.spritegroup[CT_DEFAULT];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type)
|
|
|
|
|
{
|
|
|
|
|
VehicleResolverObject object(engine, v, false, CBID_NO_CALLBACK, image_type);
|
|
|
|
|
const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v), object);
|
|
|
|
|
VehicleResolverObject object(engine, v, VehicleResolverObject::WO_CACHED, false, CBID_NO_CALLBACK, image_type);
|
|
|
|
|
const SpriteGroup *group = object.Resolve();
|
|
|
|
|
if (group == NULL || group->GetNumResults() == 0) return 0;
|
|
|
|
|
|
|
|
|
|
return group->GetResult() + (direction % group->GetNumResults());
|
|
|
|
@ -1049,15 +1032,14 @@ SpriteID GetRotorOverrideSprite(EngineID engine, const Aircraft *v, bool info_vi
|
|
|
|
|
assert(e->type == VEH_AIRCRAFT);
|
|
|
|
|
assert(!(e->u.air.subtype & AIR_CTOL));
|
|
|
|
|
|
|
|
|
|
VehicleResolverObject object(engine, v, info_view, CBID_NO_CALLBACK, image_type);
|
|
|
|
|
const SpriteGroup *group = GetWagonOverrideSpriteSet(engine, CT_DEFAULT, engine);
|
|
|
|
|
group = SpriteGroup::Resolve(group, object);
|
|
|
|
|
VehicleResolverObject object(engine, v, VehicleResolverObject::WO_SELF, info_view, CBID_NO_CALLBACK, image_type);
|
|
|
|
|
const SpriteGroup *group = object.Resolve();
|
|
|
|
|
|
|
|
|
|
if (group == NULL || group->GetNumResults() == 0) return 0;
|
|
|
|
|
|
|
|
|
|
if (v == NULL) return group->GetResult();
|
|
|
|
|
if (v == NULL || info_view) return group->GetResult();
|
|
|
|
|
|
|
|
|
|
return group->GetResult() + (info_view ? 0 : (v->Next()->Next()->state % group->GetNumResults()));
|
|
|
|
|
return group->GetResult() + (v->Next()->Next()->state % group->GetNumResults());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1083,11 +1065,8 @@ bool UsesWagonOverride(const Vehicle *v)
|
|
|
|
|
*/
|
|
|
|
|
uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v)
|
|
|
|
|
{
|
|
|
|
|
VehicleResolverObject object(engine, v, false, callback, param1, param2);
|
|
|
|
|
const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v, false), object);
|
|
|
|
|
if (group == NULL) return CALLBACK_FAILED;
|
|
|
|
|
|
|
|
|
|
return group->GetCallbackResult();
|
|
|
|
|
VehicleResolverObject object(engine, v, VehicleResolverObject::WO_UNCACHED, false, callback, param1, param2);
|
|
|
|
|
return object.ResolveCallback();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -1102,13 +1081,9 @@ uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, Eng
|
|
|
|
|
*/
|
|
|
|
|
uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v, const Vehicle *parent)
|
|
|
|
|
{
|
|
|
|
|
VehicleResolverObject object(engine, v, false, callback, param1, param2);
|
|
|
|
|
VehicleResolverObject object(engine, v, VehicleResolverObject::WO_NONE, false, callback, param1, param2);
|
|
|
|
|
object.parent_scope.SetVehicle(parent);
|
|
|
|
|
|
|
|
|
|
const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(engine, v, false), object);
|
|
|
|
|
if (group == NULL) return CALLBACK_FAILED;
|
|
|
|
|
|
|
|
|
|
return group->GetCallbackResult();
|
|
|
|
|
return object.ResolveCallback();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1133,10 +1108,10 @@ static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, byte base_rando
|
|
|
|
|
/* We can't trigger a non-existent vehicle... */
|
|
|
|
|
assert(v != NULL);
|
|
|
|
|
|
|
|
|
|
VehicleResolverObject object(v->engine_type, v, false, CBID_RANDOM_TRIGGER);
|
|
|
|
|
VehicleResolverObject object(v->engine_type, v, VehicleResolverObject::WO_CACHED, false, CBID_RANDOM_TRIGGER);
|
|
|
|
|
object.trigger = trigger;
|
|
|
|
|
|
|
|
|
|
const SpriteGroup *group = SpriteGroup::Resolve(GetVehicleSpriteGroup(v->engine_type, v), object);
|
|
|
|
|
const SpriteGroup *group = object.Resolve();
|
|
|
|
|
if (group == NULL) return;
|
|
|
|
|
|
|
|
|
|
byte new_random_bits = Random();
|
|
|
|
@ -1300,7 +1275,7 @@ void CommitVehicleListOrderChanges()
|
|
|
|
|
*/
|
|
|
|
|
void FillNewGRFVehicleCache(const Vehicle *v)
|
|
|
|
|
{
|
|
|
|
|
VehicleResolverObject ro(v->engine_type, v);
|
|
|
|
|
VehicleResolverObject ro(v->engine_type, v, VehicleResolverObject::WO_NONE);
|
|
|
|
|
|
|
|
|
|
/* These variables we have to check; these are the ones with a cache. */
|
|
|
|
|
static const int cache_entries[][2] = {
|
|
|
|
|