engine.c
changeset 426 381172276dc6
parent 414 4629d4bf7f14
child 433 a2cbd6cf3f37
equal deleted inserted replaced
425:97d601c182f0 426:381172276dc6
   241 	 * to prevent leaks. But first we need to refcount the SpriteGroup.
   241 	 * to prevent leaks. But first we need to refcount the SpriteGroup.
   242 	 * --pasky */
   242 	 * --pasky */
   243 	_engine_custom_sprites[engine][cargo] = *group;
   243 	_engine_custom_sprites[engine][cargo] = *group;
   244 }
   244 }
   245 
   245 
       
   246 static struct RealSpriteGroup *
       
   247 ResolveVehicleSpriteGroup(struct SpriteGroup *spritegroup, struct Vehicle *veh)
       
   248 {
       
   249 	switch (spritegroup->type) {
       
   250 		case SGT_REAL:
       
   251 			return &spritegroup->g.real;
       
   252 
       
   253 		case SGT_DETERMINISTIC: {
       
   254 			struct DeterministicSpriteGroup *dsg = &spritegroup->g.determ;
       
   255 			struct SpriteGroup *target;
       
   256 			int value = -1;
       
   257 
       
   258 			//debug("[%p] Having fun resolving variable %x", dsg->variable);
       
   259 
       
   260 			if ((dsg->variable >> 6) == 0) {
       
   261 				/* General property */
       
   262 				value = GetDeterministicSpriteValue(dsg->variable);
       
   263 
       
   264 			} else {
       
   265 				/* Station-specific property. */
       
   266 				if (dsg->var_scope == VSG_SCOPE_PARENT) {
       
   267 					/* First engine in the vehicle chain */
       
   268 					if (veh != NULL && veh->type == VEH_Train)
       
   269 						veh = GetFirstVehicleInChain(veh);
       
   270 				}
       
   271 
       
   272 				if (dsg->variable == 0x40) {
       
   273 					if (veh && veh->type == VEH_Train) {
       
   274 						Vehicle *u = GetFirstVehicleInChain(veh);
       
   275 						byte chain_before = 0, chain_after = 0;
       
   276 
       
   277 						while (u != veh) {
       
   278 							u = u->next;
       
   279 							chain_before++;
       
   280 						}
       
   281 						while (u->next != NULL) {
       
   282 							u = u->next;
       
   283 							chain_after++;
       
   284 						};
       
   285 
       
   286 						value = chain_before << 16 | chain_after << 8
       
   287 						        | (chain_before + chain_after + 1);
       
   288 					} else {
       
   289 						value = 1; /* 1 vehicle in the chain */
       
   290 					}
       
   291 
       
   292 				} else {
       
   293 					// TTDPatch runs on little-endian arch;
       
   294 					// Variable is 0x80 + offset in TTD's vehicle structure
       
   295 					switch (dsg->variable - 0x80) {
       
   296 #define veh_prop(id_, value_) case id_: if (veh != NULL) value = value_; break /* XXX factorise "if" */
       
   297 						veh_prop(0x00, veh->type);
       
   298 						veh_prop(0x01, veh->subtype);
       
   299 						veh_prop(0x04, veh->index);
       
   300 						veh_prop(0x05, veh->index & 0xFF);
       
   301 						/* XXX? Is THIS right? */
       
   302 						veh_prop(0x0A, veh->next_order_param << 8 | veh->next_order);
       
   303 						veh_prop(0x0B, veh->next_order);
       
   304 						veh_prop(0x0C, veh->num_orders);
       
   305 						veh_prop(0x0D, veh->cur_order_index);
       
   306 						veh_prop(0x10, veh->load_unload_time_rem);
       
   307 						veh_prop(0x11, veh->load_unload_time_rem & 0xFF);
       
   308 						veh_prop(0x12, veh->date_of_last_service);
       
   309 						veh_prop(0x13, veh->date_of_last_service & 0xFF);
       
   310 						veh_prop(0x14, veh->service_interval);
       
   311 						veh_prop(0x15, veh->service_interval & 0xFF);
       
   312 						veh_prop(0x16, veh->last_station_visited);
       
   313 						veh_prop(0x17, veh->tick_counter);
       
   314 						veh_prop(0x18, veh->max_speed);
       
   315 						veh_prop(0x19, veh->max_speed & 0xFF);
       
   316 						veh_prop(0x1F, veh->direction);
       
   317 						veh_prop(0x28, veh->cur_image);
       
   318 						veh_prop(0x29, veh->cur_image & 0xFF);
       
   319 						veh_prop(0x32, veh->vehstatus);
       
   320 						veh_prop(0x33, veh->vehstatus);
       
   321 						veh_prop(0x34, veh->cur_speed);
       
   322 						veh_prop(0x35, veh->cur_speed & 0xFF);
       
   323 						veh_prop(0x36, veh->subspeed);
       
   324 						veh_prop(0x37, veh->acceleration);
       
   325 						veh_prop(0x39, veh->cargo_type);
       
   326 						veh_prop(0x3A, veh->cargo_cap);
       
   327 						veh_prop(0x3B, veh->cargo_cap & 0xFF);
       
   328 						veh_prop(0x3C, veh->cargo_count);
       
   329 						veh_prop(0x3D, veh->cargo_count & 0xFF);
       
   330 						veh_prop(0x3E, veh->cargo_source); // Probably useless; so what
       
   331 						veh_prop(0x3F, veh->cargo_days);
       
   332 						veh_prop(0x40, veh->age);
       
   333 						veh_prop(0x41, veh->age & 0xFF);
       
   334 						veh_prop(0x42, veh->max_age);
       
   335 						veh_prop(0x43, veh->max_age & 0xFF);
       
   336 						veh_prop(0x44, veh->build_year);
       
   337 						veh_prop(0x45, veh->unitnumber);
       
   338 						veh_prop(0x46, veh->engine_type);
       
   339 						veh_prop(0x47, veh->engine_type & 0xFF);
       
   340 						veh_prop(0x48, veh->spritenum);
       
   341 						veh_prop(0x49, veh->day_counter);
       
   342 						veh_prop(0x4A, veh->breakdowns_since_last_service);
       
   343 						veh_prop(0x4B, veh->breakdown_ctr);
       
   344 						veh_prop(0x4C, veh->breakdown_delay);
       
   345 						veh_prop(0x4D, veh->breakdown_chance);
       
   346 						veh_prop(0x4E, veh->reliability);
       
   347 						veh_prop(0x4F, veh->reliability & 0xFF);
       
   348 						veh_prop(0x50, veh->reliability_spd_dec);
       
   349 						veh_prop(0x51, veh->reliability_spd_dec & 0xFF);
       
   350 						veh_prop(0x52, veh->profit_this_year);
       
   351 						veh_prop(0x53, veh->profit_this_year & 0xFFFFFF);
       
   352 						veh_prop(0x54, veh->profit_this_year & 0xFFFF);
       
   353 						veh_prop(0x55, veh->profit_this_year & 0xFF);
       
   354 						veh_prop(0x56, veh->profit_last_year);
       
   355 						veh_prop(0x57, veh->profit_last_year & 0xFF);
       
   356 						veh_prop(0x58, veh->profit_last_year);
       
   357 						veh_prop(0x59, veh->profit_last_year & 0xFF);
       
   358 						veh_prop(0x5A, veh->next_in_chain_old);
       
   359 						veh_prop(0x5B, veh->next_in_chain_old & 0xFF);
       
   360 						veh_prop(0x5C, veh->value);
       
   361 						veh_prop(0x5D, veh->value & 0xFFFFFF);
       
   362 						veh_prop(0x5E, veh->value & 0xFFFF);
       
   363 						veh_prop(0x5F, veh->value & 0xFF);
       
   364 						veh_prop(0x60, veh->string_id);
       
   365 						veh_prop(0x61, veh->string_id & 0xFF);
       
   366 						/* 00h..07h=sub image? 40h=in tunnel; actually some kind of status
       
   367 						 * aircraft: >=13h when in flight
       
   368 						 * train, ship: 80h=in depot
       
   369 						 * rv: 0feh=in depot */
       
   370 						/* TODO veh_prop(0x62, veh->???); */
       
   371 
       
   372 						/* TODO: The rest is per-vehicle, I hope no GRF file looks so far.
       
   373 						 * But they won't let us have an easy ride so surely *some* GRF
       
   374 						 * file does. So someone needs to do this too. --pasky */
       
   375 
       
   376 #undef veh_prop
       
   377 					}
       
   378 				}
       
   379 			}
       
   380 
       
   381 			target = value != -1 ? EvalDeterministicSpriteGroup(dsg, value) : dsg->default_group;
       
   382 			//debug("Resolved variable %x: %d", dsg->variable, value);
       
   383 			return ResolveVehicleSpriteGroup(target, veh);
       
   384 		}
       
   385 
       
   386 		default:
       
   387 		case SGT_RANDOM:
       
   388 			error("I don't know how to handle random spritegroups yet!");
       
   389 			return NULL;
       
   390 	}
       
   391 }
       
   392 
   246 int GetCustomEngineSprite(byte engine, Vehicle *v, byte direction)
   393 int GetCustomEngineSprite(byte engine, Vehicle *v, byte direction)
   247 {
   394 {
   248 	struct SpriteGroup *group;
   395 	struct SpriteGroup *group;
   249 	struct RealSpriteGroup *rsg;
   396 	struct RealSpriteGroup *rsg;
   250 	uint16 overriding_engine = -1;
   397 	uint16 overriding_engine = -1;
   268 
   415 
   269 		overset = GetWagonOverrideSpriteSet(engine, overriding_engine);
   416 		overset = GetWagonOverrideSpriteSet(engine, overriding_engine);
   270 		if (overset) group = overset;
   417 		if (overset) group = overset;
   271 	}
   418 	}
   272 
   419 
   273 	/* TODO: Resolve surreal groups properly. --pasky */
   420 	rsg = ResolveVehicleSpriteGroup(group, v);
   274 	rsg = TriviallyGetRSG(group);
   421 
   275 
   422 	if (rsg->sprites_per_set == 0 && cargo != 29) { /* XXX magic number */
   276 	if (!rsg->sprites_per_set && cargo != 29) {
       
   277 		// This group is empty but perhaps there'll be a default one.
   423 		// This group is empty but perhaps there'll be a default one.
   278 		/* TODO: Resolve surreal groups properly. --pasky */
   424 		rsg = ResolveVehicleSpriteGroup(&_engine_custom_sprites[engine][29], v);
   279 		rsg = TriviallyGetRSG(&_engine_custom_sprites[engine][29]);
       
   280 	}
   425 	}
   281 
   426 
   282 	if (!rsg->sprites_per_set) {
   427 	if (!rsg->sprites_per_set) {
   283 		// This group is empty. This function users should therefore
   428 		// This group is empty. This function users should therefore
   284 		// look up the sprite number in _engine_original_sprites.
   429 		// look up the sprite number in _engine_original_sprites.