Implemented in r22518.
Contents |
Goal
When coding houses, industries, airports or objects you are having a hard time, if the tiles are slope- or climate-aware. You have to code a lot of spritelayouts which mostly consist of the same sprites and bounding boxes, and only vary in some groundsprite or some offsets.
To solve that burden it would be nice if register values could be added to certain parts of the spritelayout. Examples:
- The groundsprite should get an offset to match the slope.
- The groundsprite shall get an offset to match the climate.
- The buildingsprite shall be positioned following the slope of the tile.
- The buildingsprite shall be snowy if everything else is snowy.
- Certain parts of the layouts may be hidden depending on surrounding tiles.
Technical Interpretation
- Allow specifiing which sprite to use from a spriteset instead of always using the construction stage.
- Allow specifiing an general offset to the spritenumber of Action A sprites in spritelayouts.
- Allow specifiing an offset to the Z position of a sprite.
- Allow hiding/skipping sprites from sprite layouts.
Technical Restrictions
- Parent sprites with bounding boxes stay parent sprites with bounding boxes.
- Child sprites without bounding boxes stay childsprites without bounding boxes.
- Hiding a parent sprite causes all child sprites within the bounding box to be hidden as well.
- When using the usual construction-stage sprite selection, the number of sprites in the spritesets define the number of construction-stages (max 4). If the number of sprites per spriteset is higher than 4, the construction-stage-selection will use the first four.
Proposal for new Action2 format
Industries/Houses/Airports/Objects
<Sprite-number> * <Length> 02 07/09/0F/11 <set-id> <0x40 + num-sprites> <groundsprite> <flags> [<register/value>]... [<buildingsprite> <flags> (<xoffset> <yoffset> <zoffset> <xextent> <yextent> <zextent> | <xpixeloffset> <ypixeloffset> 80) [<register/value>]... ]...
The spritelayout defines fixed spritesets to use from the Action 1. The registers can be used to individually select sprites from the spritesets instead of always using the construction stage. The registers are evaluated and their values are saved when the Action 2 sprite layout is evaluated. Other callbacks called during drawing (like CB 1E) have no effect on the used values of the registers.
Stations
<Sprite-number> * <Length> 00 04 <num-props> <num-info> <id> 1A <num-layouts> <0x40 + num-sprites> <groundsprite> <flags> [<register/value>]... [<buildingsprite> <flags> (<xoffset> <yoffset> <zoffset> <xextent> <yextent> <zextent> | <xpixeloffset> <ypixeloffset> 80) [<register/value>]... ]...
Property 1A defines the spritelayout using the same format as the action 2 above. Setting property 1A overrides properties 09 and 0A and vice verse, just like setting properties 09 and/or 0A multiple times. The used Action 1 and the used spriteset is selected via an Action 1/2/3 chain and using the usual "loading stages" for "litte" or "lots of cargo". With similar means as Action 0 property 13 bit 0 multiple spritesets from different Action 1 can be used.
The sprites and the registers in the spritelayout define which sprite to use from the selected spriteset. The registers are evaluated and their values are saved when the Action 2 responsible for a particular entry in the spritelayout is resolved.
Details
<0x40 + num-sprite>: Number of sprites in the layout. Add 0x40 to identify the new format with register modifiers.
<flags>: Word value with these flags:
Bit | Hex | Parentsprite | Groundsprite/Childsprite |
---|---|---|---|
0 | 0001 | Skip bounding box including child sprites | Skip sprite |
1 | 0002 | Add offset to sprite, disable default usage of construction stage or railtype-offset | |
2 | 0004 | Add offset to recoloursprite | |
3 | 0008 | Recolour sprite is from Action 1 (will be affected by the same construction stage resp. railtype-offsets as sprites, unless bit 2 is set) | |
4 | 0010 | Add offset for <xoffset> and <yoffset> | Add offset for <xpixeloffset> |
5 | 0020 | Add offset for <zoffset> | Add offset for <ypixeloffset> |
6 | 0040 | Resolve sprite with Variable 10 set to a specific value (*) | |
7 | 0080 | Resolve recoloursprite with Variable 10 set to a specific value (*) | |
8..15 | Reserved, should be zero. If the GRF sets unknown bits, it will be disabled. |
(*) The Action 1/2/3 chain is resolved multiple times, sprites can be part of different Action 1:
The associated value in <register/value> is the raw value (not a register!) to put into Variable 10 while resolving the sprites.
- Only valid for stations,
- only allowed values currently 0-7,
- the value '2' is used when resolving custom foundations, (so, do not conflict with that)
- even if the sprite is not from an Action 1, the value still defines which Action2 chains defines the values for the referenced registers.
- The register for "Add offset to recoloursprite" is defined by the Action 1/2/3 chain with Variable 10 as defined for the recolour sprite. :*The other registers are defined by the Action 1/2/3 chain with Variable 10 as defined for the sprite.
- If no variable 10 values are defined, then station property 13 bit 0 takes effect; i.e. variable 10 is set to 0 or 1 depending on the bit and whether the first groundsprite is resolved or a different sprite. This applies to both the groundsprite and the palette of the groundsprite.
<register/value>: Temporary storage registers to add to the individual parts. The register values are considered signed. The order of the registers is the same as the bits in <flags>. If a bit is not set, then no registers appears for it. Most bits require one register.
- <xoffset> and <yoffset> can only be enabled together, using two registers,
- the "skip bounding box"-register uses value 1 to draw the sprite, and 0 to skip it,
- the "recolorsprite from Action 1" uses no register at all,
- the Variable 10 values are not set via a register, but via a byte-constant.
Example
The example consists of
- a climate-dependant slope-aware groundsprite,
- a building,
- a snow layer on top of the building.
-1 * -1 02 0F 40 81 // Procedure to compute the slope-dependent spriteoffset 41 00 1F \b 18 \wx 8000 00 00 // flat \wx 8001 01 01 // normal slopes \wx 8002 02 02 \wx 8003 03 03 \wx 8004 04 04 \wx 8005 05 05 \wx 8006 06 06 \wx 8007 07 07 \wx 8008 08 08 \wx 8009 09 09 \wx 800A 0A 0A \wx 800B 0B 0B \wx 800C 0C 0C \wx 800D 0D 0D \wx 800E 0E 0E \wx 800F 1D 1D // steep slopes \wx 8010 1B 1B \wx 8011 17 17 \wx 8012 -1 * -1 02 0F 41 81 // Procedure to compute the climate-dependent spriteoffset 62 00 0A 07 \wx 91C6 01 01 // desert \wx 91C6 04 04 // snow \wx 8F8D // normal -1 * -1 02 0F 42 82 // Procedure to compute the height offset in the middle of the tile 41 00 1F \b 9 \wx 8004 03 03 // 2-corner inclined slopes \wx 8004 06 06 \wx 8004 09 09 \wx 8004 0C 0C \wx 8008 07 07 // 3-corner slopes \wx 8008 0B 0B \wx 8008 0D 0D \wx 8008 0E 0E \wx 8008 10 1F // steep slopes \wx 8000 // rest, no offset -1 * -1 01 0F \b 2 \b* 1 -1 ugly_building.png ? ? 01 ? ? ? ? -1 pretty_snow.png ? ? 01 ? ? ? ? -1 * -1 02 0F 00 42 \dx 0 \wx02 10 // Draw groundsprite from register 0x10. \dx 80000000 \wx20 00 00 00 10 10 30 11 // Draw building sprite at z-postion from register 0x11. \dx 80000001 \wx01 00 00 80 12 // Draw snow-overlay relative to building sprite, but only if register 0x12 is zero. -1 * -1 02 0F 00 81 7E 40 20 FF // Get slope offset from procedure 40 \2+ 7E 41 20 FF // Add climate offset from procedure 41 \2sto 1A 20 10 // Store in register 0x10 \2rst 7E 42 20 FF // Get height offset in the middle of the tile \2sto 1A 20 11 // Store in register 0x11 \2rst 62 00 2C 01 // Test snow bit, 1 if snowy, 0 if not \2sto 1A 00 12 // Store in register 0x12 \b 1 \wx 0 00 00 // always procede at 00 \wx 0 -1 * -1 03 0F 01 ?? \b 0 00 // always procede at 00