Write cmclient-*.grf directly from python instead of using nml inbetween
This commit is contained in:
@@ -1,462 +0,0 @@
|
||||
grf {
|
||||
grfid: "CMC\01";
|
||||
name: string(STR_GRF_NAME);
|
||||
desc: string(STR_GRF_DESCRIPTION);
|
||||
version: 1;
|
||||
min_compatible_version: 1;
|
||||
}
|
||||
|
||||
replace toolbar(10000, "sprites/toolbar.png") {
|
||||
[ 0, 0, 20, 14, 0, 0]
|
||||
}
|
||||
|
||||
alternative_sprites(toolbar, ZOOM_LEVEL_IN_2X, BIT_DEPTH_8BPP) {
|
||||
[ 32, 0, 40, 40, 0, 0, "sprites/toolbar.png"]
|
||||
}
|
||||
|
||||
replace inner_highlight(10001, "sprites/innerhighlight00.png") {
|
||||
[ 18, 8, 64, 31, -31, 7]
|
||||
[ 98, 8, 64, 31, -31, 7]
|
||||
[178, 8, 64, 23, -31, 7]
|
||||
[258, 8, 64, 23, -31, 7]
|
||||
[338, 8, 64, 31, -31, 7]
|
||||
[418, 8, 64, 31, -31, 7]
|
||||
[498, 8, 64, 23, -31, 7]
|
||||
[578, 8, 64, 23, -31, 7]
|
||||
[658, 8, 64, 39, -31, -1]
|
||||
[ 2, 72, 64, 39, -31, -1]
|
||||
[ 82, 72, 64, 31, -31, -1]
|
||||
[162, 72, 64, 31, -31, -1]
|
||||
[242, 72, 64, 39, -31, -1]
|
||||
[322, 72, 64, 39, -31, -1]
|
||||
[402, 72, 64, 31, -31, -1]
|
||||
[482, 72, 64, 47, -31, -9]
|
||||
[562, 72, 64, 15, -31, 7]
|
||||
[642, 72, 64, 31, -31, -1]
|
||||
[722, 72, 64, 31, -31, -1]
|
||||
[ 2, 136, 20, 14, 1, 5]
|
||||
[ 34, 136, 20, 20, 0, 0]
|
||||
[185, 125, 18, 15, -8, 7]
|
||||
|
||||
// red
|
||||
recolour_sprite {
|
||||
0x01..0x09: 0x00;
|
||||
0x0A..0x0B: 0xB6;
|
||||
0x0C..0x0D: 0xB7;
|
||||
0x0E..0x0F: 0xB8;
|
||||
0x10..0xFF: 0x00;
|
||||
}
|
||||
|
||||
// green
|
||||
recolour_sprite {
|
||||
0x0A..0x0B: 0xCF;
|
||||
0x0C..0x0D: 0xD0;
|
||||
0x0E..0x0F: 0xD1;
|
||||
}
|
||||
|
||||
// black
|
||||
recolour_sprite {
|
||||
0x0A..0x0B: 0x10;
|
||||
0x0C..0x0D: 0x11;
|
||||
0x0E..0x0F: 0x12;
|
||||
}
|
||||
|
||||
// ligth blue
|
||||
recolour_sprite {
|
||||
0x0A..0x0B: 0x96;
|
||||
0x0C..0x0D: 0x97;
|
||||
0x0E..0x0F: 0x98;
|
||||
}
|
||||
|
||||
// orange
|
||||
recolour_sprite {
|
||||
0x0A..0x0B: 0xB9;
|
||||
0x0C..0x0D: 0xBA;
|
||||
0x0E..0x0F: 0xBB;
|
||||
}
|
||||
|
||||
// white
|
||||
recolour_sprite {
|
||||
0x0A..0x0B: 0x0D;
|
||||
0x0C..0x0D: 0x0E;
|
||||
0x0E..0x0F: 0x0F;
|
||||
}
|
||||
|
||||
// white (yellow)
|
||||
recolour_sprite {
|
||||
0x0A..0x0B: 0x32;
|
||||
0x0C..0x0D: 0x33;
|
||||
0x0E..0x0F: 0x34;
|
||||
}
|
||||
|
||||
// white (purple)
|
||||
recolour_sprite {
|
||||
0x0A..0x0B: 0xAC;
|
||||
0x0C..0x0D: 0xAD;
|
||||
0x0E..0x0F: 0xAE;
|
||||
}
|
||||
}
|
||||
|
||||
replace border_highlight(10030, "sprites/borderhighlight.png") {
|
||||
[ 10, 10, 64, 31, -31, 7]
|
||||
[ 84, 10, 64, 31, -31, 7]
|
||||
[ 158, 10, 64, 31, -31, 7]
|
||||
[ 232, 10, 64, 31, -31, 7]
|
||||
[ 306, 10, 64, 31, -31, 7]
|
||||
[ 380, 10, 64, 31, -31, 7]
|
||||
[ 454, 10, 64, 31, -31, 7]
|
||||
[ 528, 10, 64, 31, -31, 7]
|
||||
[ 602, 10, 64, 31, -31, 7]
|
||||
[ 676, 10, 64, 31, -31, 7]
|
||||
[ 750, 10, 64, 31, -31, 7]
|
||||
[ 824, 10, 64, 31, -31, 7]
|
||||
[ 898, 10, 64, 31, -31, 7]
|
||||
[ 972, 10, 64, 31, -31, 7]
|
||||
[1046, 10, 64, 31, -31, 7]
|
||||
[1120, 10, 64, 31, -31, 7]
|
||||
[1194, 10, 64, 31, -31, 7]
|
||||
[1268, 10, 64, 31, -31, 7]
|
||||
[1342, 10, 64, 31, -31, 7]
|
||||
[ 10, 51, 64, 31, -31, 7]
|
||||
[ 84, 51, 64, 31, -31, 7]
|
||||
[ 158, 51, 64, 31, -31, 7]
|
||||
[ 232, 51, 64, 31, -31, 7]
|
||||
[ 306, 51, 64, 31, -31, 7]
|
||||
[ 380, 51, 64, 31, -31, 7]
|
||||
[ 454, 51, 64, 31, -31, 7]
|
||||
[ 528, 51, 64, 31, -31, 7]
|
||||
[ 602, 51, 64, 31, -31, 7]
|
||||
[ 676, 51, 64, 31, -31, 7]
|
||||
[ 750, 51, 64, 31, -31, 7]
|
||||
[ 824, 51, 64, 31, -31, 7]
|
||||
[ 898, 51, 64, 31, -31, 7]
|
||||
[ 972, 51, 64, 31, -31, 7]
|
||||
[1046, 51, 64, 31, -31, 7]
|
||||
[1120, 51, 64, 31, -31, 7]
|
||||
[1194, 51, 64, 31, -31, 7]
|
||||
[1268, 51, 64, 31, -31, 7]
|
||||
[1342, 51, 64, 31, -31, 7]
|
||||
[ 10, 92, 64, 23, -31, 7]
|
||||
[ 84, 92, 64, 23, -31, 7]
|
||||
[ 158, 92, 64, 23, -31, 7]
|
||||
[ 232, 92, 64, 23, -31, 7]
|
||||
[ 306, 92, 64, 23, -31, 7]
|
||||
[ 380, 92, 64, 23, -31, 7]
|
||||
[ 454, 92, 64, 23, -31, 7]
|
||||
[ 528, 92, 64, 23, -31, 7]
|
||||
[ 602, 92, 64, 23, -31, 7]
|
||||
[ 676, 92, 64, 23, -31, 7]
|
||||
[ 750, 92, 64, 23, -31, 7]
|
||||
[ 824, 92, 64, 23, -31, 7]
|
||||
[ 898, 92, 64, 23, -31, 7]
|
||||
[ 972, 92, 64, 23, -31, 7]
|
||||
[1046, 92, 64, 23, -31, 7]
|
||||
[1120, 92, 64, 23, -31, 7]
|
||||
[1194, 92, 64, 23, -31, 7]
|
||||
[1268, 92, 64, 23, -31, 7]
|
||||
[1342, 92, 64, 23, -31, 7]
|
||||
[ 10, 125, 64, 23, -31, 7]
|
||||
[ 84, 125, 64, 23, -31, 7]
|
||||
[ 158, 125, 64, 23, -31, 7]
|
||||
[ 232, 125, 64, 23, -31, 7]
|
||||
[ 306, 125, 64, 23, -31, 7]
|
||||
[ 380, 125, 64, 23, -31, 7]
|
||||
[ 454, 125, 64, 23, -31, 7]
|
||||
[ 528, 125, 64, 23, -31, 7]
|
||||
[ 602, 125, 64, 23, -31, 7]
|
||||
[ 676, 125, 64, 23, -31, 7]
|
||||
[ 750, 125, 64, 23, -31, 7]
|
||||
[ 824, 125, 64, 23, -31, 7]
|
||||
[ 898, 125, 64, 23, -31, 7]
|
||||
[ 972, 125, 64, 23, -31, 7]
|
||||
[1046, 125, 64, 23, -31, 7]
|
||||
[1120, 125, 64, 23, -31, 7]
|
||||
[1194, 125, 64, 23, -31, 7]
|
||||
[1268, 125, 64, 23, -31, 7]
|
||||
[1342, 125, 64, 23, -31, 7]
|
||||
[ 10, 158, 64, 31, -31, 7]
|
||||
[ 84, 158, 64, 31, -31, 7]
|
||||
[ 158, 158, 64, 31, -31, 7]
|
||||
[ 232, 158, 64, 31, -31, 7]
|
||||
[ 306, 158, 64, 31, -31, 7]
|
||||
[ 380, 158, 64, 31, -31, 7]
|
||||
[ 454, 158, 64, 31, -31, 7]
|
||||
[ 528, 158, 64, 31, -31, 7]
|
||||
[ 602, 158, 64, 31, -31, 7]
|
||||
[ 676, 158, 64, 31, -31, 7]
|
||||
[ 750, 158, 64, 31, -31, 7]
|
||||
[ 824, 158, 64, 31, -31, 7]
|
||||
[ 898, 158, 64, 31, -31, 7]
|
||||
[ 972, 158, 64, 31, -31, 7]
|
||||
[1046, 158, 64, 31, -31, 7]
|
||||
[1120, 158, 64, 31, -31, 7]
|
||||
[1194, 158, 64, 31, -31, 7]
|
||||
[1268, 158, 64, 31, -31, 7]
|
||||
[1342, 158, 64, 31, -31, 7]
|
||||
[ 10, 199, 64, 31, -31, 7]
|
||||
[ 84, 199, 64, 31, -31, 7]
|
||||
[ 158, 199, 64, 31, -31, 7]
|
||||
[ 232, 199, 64, 31, -31, 7]
|
||||
[ 306, 199, 64, 31, -31, 7]
|
||||
[ 380, 199, 64, 31, -31, 7]
|
||||
[ 454, 199, 64, 31, -31, 7]
|
||||
[ 528, 199, 64, 31, -31, 7]
|
||||
[ 602, 199, 64, 31, -31, 7]
|
||||
[ 676, 199, 64, 31, -31, 7]
|
||||
[ 750, 199, 64, 31, -31, 7]
|
||||
[ 824, 199, 64, 31, -31, 7]
|
||||
[ 898, 199, 64, 31, -31, 7]
|
||||
[ 972, 199, 64, 31, -31, 7]
|
||||
[1046, 199, 64, 31, -31, 7]
|
||||
[1120, 199, 64, 31, -31, 7]
|
||||
[1194, 199, 64, 31, -31, 7]
|
||||
[1268, 199, 64, 31, -31, 7]
|
||||
[1342, 199, 64, 31, -31, 7]
|
||||
[ 10, 240, 64, 23, -31, 7]
|
||||
[ 84, 240, 64, 23, -31, 7]
|
||||
[ 158, 240, 64, 23, -31, 7]
|
||||
[ 232, 240, 64, 23, -31, 7]
|
||||
[ 306, 240, 64, 23, -31, 7]
|
||||
[ 380, 240, 64, 23, -31, 7]
|
||||
[ 454, 240, 64, 23, -31, 7]
|
||||
[ 528, 240, 64, 23, -31, 7]
|
||||
[ 602, 240, 64, 23, -31, 7]
|
||||
[ 676, 240, 64, 23, -31, 7]
|
||||
[ 750, 240, 64, 23, -31, 7]
|
||||
[ 824, 240, 64, 23, -31, 7]
|
||||
[ 898, 240, 64, 23, -31, 7]
|
||||
[ 972, 240, 64, 23, -31, 7]
|
||||
[1046, 240, 64, 23, -31, 7]
|
||||
[1120, 240, 64, 23, -31, 7]
|
||||
[1194, 240, 64, 23, -31, 7]
|
||||
[1268, 240, 64, 23, -31, 7]
|
||||
[1342, 240, 64, 23, -31, 7]
|
||||
[ 10, 273, 64, 23, -31, 7]
|
||||
[ 84, 273, 64, 23, -31, 7]
|
||||
[ 158, 273, 64, 23, -31, 7]
|
||||
[ 232, 273, 64, 23, -31, 7]
|
||||
[ 306, 273, 64, 23, -31, 7]
|
||||
[ 380, 273, 64, 23, -31, 7]
|
||||
[ 454, 273, 64, 23, -31, 7]
|
||||
[ 528, 273, 64, 23, -31, 7]
|
||||
[ 602, 273, 64, 23, -31, 7]
|
||||
[ 676, 273, 64, 23, -31, 7]
|
||||
[ 750, 273, 64, 23, -31, 7]
|
||||
[ 824, 273, 64, 23, -31, 7]
|
||||
[ 898, 273, 64, 23, -31, 7]
|
||||
[ 972, 273, 64, 23, -31, 7]
|
||||
[1046, 273, 64, 23, -31, 7]
|
||||
[1120, 273, 64, 23, -31, 7]
|
||||
[1194, 273, 64, 23, -31, 7]
|
||||
[1268, 273, 64, 23, -31, 7]
|
||||
[1342, 273, 64, 23, -31, 7]
|
||||
[ 10, 306, 64, 39, -31, -1]
|
||||
[ 84, 306, 64, 39, -31, -1]
|
||||
[ 158, 306, 64, 39, -31, -1]
|
||||
[ 232, 306, 64, 39, -31, -1]
|
||||
[ 306, 306, 64, 39, -31, -1]
|
||||
[ 380, 306, 64, 39, -31, -1]
|
||||
[ 454, 306, 64, 39, -31, -1]
|
||||
[ 528, 306, 64, 39, -31, -1]
|
||||
[ 602, 306, 64, 39, -31, -1]
|
||||
[ 676, 306, 64, 39, -31, -1]
|
||||
[ 750, 306, 64, 39, -31, -1]
|
||||
[ 824, 306, 64, 39, -31, -1]
|
||||
[ 898, 306, 64, 39, -31, -1]
|
||||
[ 972, 306, 64, 39, -31, -1]
|
||||
[1046, 306, 64, 39, -31, -1]
|
||||
[1120, 306, 64, 39, -31, -1]
|
||||
[1194, 306, 64, 39, -31, -1]
|
||||
[1268, 306, 64, 39, -31, -1]
|
||||
[1342, 306, 64, 39, -31, -1]
|
||||
[ 10, 355, 64, 39, -31, -1]
|
||||
[ 84, 355, 64, 39, -31, -1]
|
||||
[ 158, 355, 64, 39, -31, -1]
|
||||
[ 232, 355, 64, 39, -31, -1]
|
||||
[ 306, 355, 64, 39, -31, -1]
|
||||
[ 380, 355, 64, 39, -31, -1]
|
||||
[ 454, 355, 64, 39, -31, -1]
|
||||
[ 528, 355, 64, 39, -31, -1]
|
||||
[ 602, 355, 64, 39, -31, -1]
|
||||
[ 676, 355, 64, 39, -31, -1]
|
||||
[ 750, 355, 64, 39, -31, -1]
|
||||
[ 824, 355, 64, 39, -31, -1]
|
||||
[ 898, 355, 64, 39, -31, -1]
|
||||
[ 972, 355, 64, 39, -31, -1]
|
||||
[1046, 355, 64, 39, -31, -1]
|
||||
[1120, 355, 64, 39, -31, -1]
|
||||
[1194, 355, 64, 39, -31, -1]
|
||||
[1268, 355, 64, 39, -31, -1]
|
||||
[1342, 355, 64, 39, -31, -1]
|
||||
[ 10, 404, 64, 31, -31, -1]
|
||||
[ 84, 404, 64, 31, -31, -1]
|
||||
[ 158, 404, 64, 31, -31, -1]
|
||||
[ 232, 404, 64, 31, -31, -1]
|
||||
[ 306, 404, 64, 31, -31, -1]
|
||||
[ 380, 404, 64, 31, -31, -1]
|
||||
[ 454, 404, 64, 31, -31, -1]
|
||||
[ 528, 404, 64, 31, -31, -1]
|
||||
[ 602, 404, 64, 31, -31, -1]
|
||||
[ 676, 404, 64, 31, -31, -1]
|
||||
[ 750, 404, 64, 31, -31, -1]
|
||||
[ 824, 404, 64, 31, -31, -1]
|
||||
[ 898, 404, 64, 31, -31, -1]
|
||||
[ 972, 404, 64, 31, -31, -1]
|
||||
[1046, 404, 64, 31, -31, -1]
|
||||
[1120, 404, 64, 31, -31, -1]
|
||||
[1194, 404, 64, 31, -31, -1]
|
||||
[1268, 404, 64, 31, -31, -1]
|
||||
[1342, 404, 64, 31, -31, -1]
|
||||
[ 10, 445, 64, 31, -31, -1]
|
||||
[ 84, 445, 64, 31, -31, -1]
|
||||
[ 158, 445, 64, 31, -31, -1]
|
||||
[ 232, 445, 64, 31, -31, -1]
|
||||
[ 306, 445, 64, 31, -31, -1]
|
||||
[ 380, 445, 64, 31, -31, -1]
|
||||
[ 454, 445, 64, 31, -31, -1]
|
||||
[ 528, 445, 64, 31, -31, -1]
|
||||
[ 602, 445, 64, 31, -31, -1]
|
||||
[ 676, 445, 64, 31, -31, -1]
|
||||
[ 750, 445, 64, 31, -31, -1]
|
||||
[ 824, 445, 64, 31, -31, -1]
|
||||
[ 898, 445, 64, 31, -31, -1]
|
||||
[ 972, 445, 64, 31, -31, -1]
|
||||
[1046, 445, 64, 31, -31, -1]
|
||||
[1120, 445, 64, 31, -31, -1]
|
||||
[1194, 445, 64, 31, -31, -1]
|
||||
[1268, 445, 64, 31, -31, -1]
|
||||
[1342, 445, 64, 31, -31, -1]
|
||||
[ 10, 486, 64, 39, -31, -1]
|
||||
[ 84, 486, 64, 39, -31, -1]
|
||||
[ 158, 486, 64, 39, -31, -1]
|
||||
[ 232, 486, 64, 39, -31, -1]
|
||||
[ 306, 486, 64, 39, -31, -1]
|
||||
[ 380, 486, 64, 39, -31, -1]
|
||||
[ 454, 486, 64, 39, -31, -1]
|
||||
[ 528, 486, 64, 39, -31, -1]
|
||||
[ 602, 486, 64, 39, -31, -1]
|
||||
[ 676, 486, 64, 39, -31, -1]
|
||||
[ 750, 486, 64, 39, -31, -1]
|
||||
[ 824, 486, 64, 39, -31, -1]
|
||||
[ 898, 486, 64, 39, -31, -1]
|
||||
[ 972, 486, 64, 39, -31, -1]
|
||||
[1046, 486, 64, 39, -31, -1]
|
||||
[1120, 486, 64, 39, -31, -1]
|
||||
[1194, 486, 64, 39, -31, -1]
|
||||
[1268, 486, 64, 39, -31, -1]
|
||||
[1342, 486, 64, 39, -31, -1]
|
||||
[ 10, 535, 64, 39, -31, -1]
|
||||
[ 84, 535, 64, 39, -31, -1]
|
||||
[ 158, 535, 64, 39, -31, -1]
|
||||
[ 232, 535, 64, 39, -31, -1]
|
||||
[ 306, 535, 64, 39, -31, -1]
|
||||
[ 380, 535, 64, 39, -31, -1]
|
||||
[ 454, 535, 64, 39, -31, -1]
|
||||
[ 528, 535, 64, 39, -31, -1]
|
||||
[ 602, 535, 64, 39, -31, -1]
|
||||
[ 676, 535, 64, 39, -31, -1]
|
||||
[ 750, 535, 64, 39, -31, -1]
|
||||
[ 824, 535, 64, 39, -31, -1]
|
||||
[ 898, 535, 64, 39, -31, -1]
|
||||
[ 972, 535, 64, 39, -31, -1]
|
||||
[1046, 535, 64, 39, -31, -1]
|
||||
[1120, 535, 64, 39, -31, -1]
|
||||
[1194, 535, 64, 39, -31, -1]
|
||||
[1268, 535, 64, 39, -31, -1]
|
||||
[1342, 535, 64, 39, -31, -1]
|
||||
[ 10, 584, 64, 31, -31, -1]
|
||||
[ 84, 584, 64, 31, -31, -1]
|
||||
[ 158, 584, 64, 31, -31, -1]
|
||||
[ 232, 584, 64, 31, -31, -1]
|
||||
[ 306, 584, 64, 31, -31, -1]
|
||||
[ 380, 584, 64, 31, -31, -1]
|
||||
[ 454, 584, 64, 31, -31, -1]
|
||||
[ 528, 584, 64, 31, -31, -1]
|
||||
[ 602, 584, 64, 31, -31, -1]
|
||||
[ 676, 584, 64, 31, -31, -1]
|
||||
[ 750, 584, 64, 31, -31, -1]
|
||||
[ 824, 584, 64, 31, -31, -1]
|
||||
[ 898, 584, 64, 31, -31, -1]
|
||||
[ 972, 584, 64, 31, -31, -1]
|
||||
[1046, 584, 64, 31, -31, -1]
|
||||
[1120, 584, 64, 31, -31, -1]
|
||||
[1194, 584, 64, 31, -31, -1]
|
||||
[1268, 584, 64, 31, -31, -1]
|
||||
[1342, 584, 64, 31, -31, -1]
|
||||
[ 10, 625, 64, 47, -31, -9]
|
||||
[ 84, 625, 64, 47, -31, -9]
|
||||
[ 158, 625, 64, 47, -31, -9]
|
||||
[ 232, 625, 64, 47, -31, -9]
|
||||
[ 306, 625, 64, 47, -31, -9]
|
||||
[ 380, 625, 64, 47, -31, -9]
|
||||
[ 454, 625, 64, 47, -31, -9]
|
||||
[ 528, 625, 64, 47, -31, -9]
|
||||
[ 602, 625, 64, 47, -31, -9]
|
||||
[ 676, 625, 64, 47, -31, -9]
|
||||
[ 750, 625, 64, 47, -31, -9]
|
||||
[ 824, 625, 64, 47, -31, -9]
|
||||
[ 898, 625, 64, 47, -31, -9]
|
||||
[ 972, 625, 64, 47, -31, -9]
|
||||
[1046, 625, 64, 47, -31, -9]
|
||||
[1120, 625, 64, 47, -31, -9]
|
||||
[1194, 625, 64, 47, -31, -9]
|
||||
[1268, 625, 64, 47, -31, -9]
|
||||
[1342, 625, 64, 47, -31, -9]
|
||||
[ 10, 682, 64, 15, -31, 7]
|
||||
[ 84, 682, 64, 15, -31, 7]
|
||||
[ 158, 682, 64, 15, -31, 7]
|
||||
[ 232, 682, 64, 15, -31, 7]
|
||||
[ 306, 682, 64, 15, -31, 7]
|
||||
[ 380, 682, 64, 15, -31, 7]
|
||||
[ 454, 682, 64, 15, -31, 7]
|
||||
[ 528, 682, 64, 15, -31, 7]
|
||||
[ 602, 682, 64, 15, -31, 7]
|
||||
[ 676, 682, 64, 15, -31, 7]
|
||||
[ 750, 682, 64, 15, -31, 7]
|
||||
[ 824, 682, 64, 15, -31, 7]
|
||||
[ 898, 682, 64, 15, -31, 7]
|
||||
[ 972, 682, 64, 15, -31, 7]
|
||||
[1046, 682, 64, 15, -31, 7]
|
||||
[1120, 682, 64, 15, -31, 7]
|
||||
[1194, 682, 64, 15, -31, 7]
|
||||
[1268, 682, 64, 15, -31, 7]
|
||||
[1342, 682, 64, 15, -31, 7]
|
||||
[ 10, 707, 64, 31, -31, -1]
|
||||
[ 84, 707, 64, 31, -31, -1]
|
||||
[ 158, 707, 64, 31, -31, -1]
|
||||
[ 232, 707, 64, 31, -31, -1]
|
||||
[ 306, 707, 64, 31, -31, -1]
|
||||
[ 380, 707, 64, 31, -31, -1]
|
||||
[ 454, 707, 64, 31, -31, -1]
|
||||
[ 528, 707, 64, 31, -31, -1]
|
||||
[ 602, 707, 64, 31, -31, -1]
|
||||
[ 676, 707, 64, 31, -31, -1]
|
||||
[ 750, 707, 64, 31, -31, -1]
|
||||
[ 824, 707, 64, 31, -31, -1]
|
||||
[ 898, 707, 64, 31, -31, -1]
|
||||
[ 972, 707, 64, 31, -31, -1]
|
||||
[1046, 707, 64, 31, -31, -1]
|
||||
[1120, 707, 64, 31, -31, -1]
|
||||
[1194, 707, 64, 31, -31, -1]
|
||||
[1268, 707, 64, 31, -31, -1]
|
||||
[1342, 707, 64, 31, -31, -1]
|
||||
[ 10, 748, 64, 31, -31, -1]
|
||||
[ 84, 748, 64, 31, -31, -1]
|
||||
[ 158, 748, 64, 31, -31, -1]
|
||||
[ 232, 748, 64, 31, -31, -1]
|
||||
[ 306, 748, 64, 31, -31, -1]
|
||||
[ 380, 748, 64, 31, -31, -1]
|
||||
[ 454, 748, 64, 31, -31, -1]
|
||||
[ 528, 748, 64, 31, -31, -1]
|
||||
[ 602, 748, 64, 31, -31, -1]
|
||||
[ 676, 748, 64, 31, -31, -1]
|
||||
[ 750, 748, 64, 31, -31, -1]
|
||||
[ 824, 748, 64, 31, -31, -1]
|
||||
[ 898, 748, 64, 31, -31, -1]
|
||||
[ 972, 748, 64, 31, -31, -1]
|
||||
[1046, 748, 64, 31, -31, -1]
|
||||
[1120, 748, 64, 31, -31, -1]
|
||||
[1194, 748, 64, 31, -31, -1]
|
||||
[1268, 748, 64, 31, -31, -1]
|
||||
[1342, 748, 64, 31, -31, -1]
|
||||
//}
|
||||
@@ -9,12 +9,28 @@ grf {
|
||||
replace toolbar(10000, "sprites/toolbar.png") {
|
||||
[ 0, 0, 20, 14, 0, 0]
|
||||
}
|
||||
|
||||
alternative_sprites(toolbar, ZOOM_LEVEL_IN_2X, BIT_DEPTH_8BPP) {
|
||||
[ 32, 0, 40, 40, 0, 0, "sprites/toolbar.png"]
|
||||
}
|
||||
|
||||
replace inner_highlight(10001, "sprites/innerhighlight00.png") {
|
||||
replace ui_icons(10001, "sprites/toolbar.png") {
|
||||
[ 0, 44, 12, 10, 0, 0]
|
||||
|
||||
[ 66, 44, 10, 10, 0, 0]
|
||||
[ 86, 44, 10, 10, 0, 0]
|
||||
[ 106, 44, 10, 10, 0, 0]
|
||||
[ 126, 44, 10, 10, 0, 0]
|
||||
[ 66, 55, 10, 10, 0, 0]
|
||||
[ 86, 55, 10, 10, 0, 0]
|
||||
[ 106, 55, 10, 10, 0, 0]
|
||||
[ 126, 55, 10, 10, 0, 0]
|
||||
[ 66, 66, 10, 10, 0, 0]
|
||||
[ 86, 66, 10, 10, 0, 0]
|
||||
[ 106, 66, 10, 10, 0, 0]
|
||||
[ 126, 66, 10, 10, 0, 0]
|
||||
}
|
||||
|
||||
replace inner_highlight(10014, "sprites/innerhighlight00.png") {
|
||||
[ 18, 8, 64, 31, -31, 7]
|
||||
[ 98, 8, 64, 31, -31, 7]
|
||||
[178, 8, 64, 23, -31, 7]
|
||||
@@ -97,7 +113,7 @@ replace inner_highlight(10001, "sprites/innerhighlight00.png") {
|
||||
}
|
||||
}
|
||||
|
||||
replace border_highlight(10030, "sprites/borderhighlight.png") {
|
||||
replace border_highlight(10044, "sprites/borderhighlight.png") {
|
||||
[ 10, 10, 64, 31, -31, 7]
|
||||
[ 84, 10, 64, 31, -31, 7]
|
||||
[ 158, 10, 64, 31, -31, 7]
|
||||
|
||||
183
grf/cmclient/gencmclientgrf.py
Normal file
183
grf/cmclient/gencmclientgrf.py
Normal file
@@ -0,0 +1,183 @@
|
||||
import grf
|
||||
import spectra
|
||||
|
||||
gen = grf.NewGRF(
|
||||
b'CMC\x01',
|
||||
'CityMania Client Resourse Pack v5',
|
||||
'Provides additional resources for a CityMania patched client (citymania.org/downloads). Should be put in your client data folder. Do not add this to your game via NewGRF options, it may break something.',
|
||||
)
|
||||
|
||||
toolbar_png = grf.ImageFile('sprites/toolbar.png')
|
||||
gen.add_sprite(grf.FileSprite(toolbar_png, 0, 0, 20, 14),
|
||||
grf.FileSprite(toolbar_png, 32, 0, 40, 40, zoom=grf.ZOOM_2X))
|
||||
|
||||
gen.add_sprite(grf.FileSprite(toolbar_png, 0, 44, 12, 10))
|
||||
|
||||
for i in range(3):
|
||||
for j in range(4):
|
||||
gen.add_sprite(grf.FileSprite(toolbar_png, 66 + 20 * j, 44 + 11 * i, 10, 10))
|
||||
|
||||
innerhl_png = grf.ImageFile('sprites/innerhighlight00.png')
|
||||
sprite = lambda *args, **kw: gen.add_sprite(grf.FileSprite(innerhl_png, *args, **kw))
|
||||
sprite( 18, 8, 64, 31, xofs=-31, yofs= 7)
|
||||
sprite( 98, 8, 64, 31, xofs=-31, yofs= 7)
|
||||
sprite(178, 8, 64, 23, xofs=-31, yofs= 7)
|
||||
sprite(258, 8, 64, 23, xofs=-31, yofs= 7)
|
||||
sprite(338, 8, 64, 31, xofs=-31, yofs= 7)
|
||||
sprite(418, 8, 64, 31, xofs=-31, yofs= 7)
|
||||
sprite(498, 8, 64, 23, xofs=-31, yofs= 7)
|
||||
sprite(578, 8, 64, 23, xofs=-31, yofs= 7)
|
||||
sprite(658, 8, 64, 39, xofs=-31, yofs=-1)
|
||||
sprite( 2, 72, 64, 39, xofs=-31, yofs=-1)
|
||||
sprite( 82, 72, 64, 31, xofs=-31, yofs=-1)
|
||||
sprite(162, 72, 64, 31, xofs=-31, yofs=-1)
|
||||
sprite(242, 72, 64, 39, xofs=-31, yofs=-1)
|
||||
sprite(322, 72, 64, 39, xofs=-31, yofs=-1)
|
||||
sprite(402, 72, 64, 31, xofs=-31, yofs=-1)
|
||||
sprite(482, 72, 64, 47, xofs=-31, yofs=-9)
|
||||
sprite(562, 72, 64, 15, xofs=-31, yofs= 7)
|
||||
sprite(642, 72, 64, 31, xofs=-31, yofs=-1)
|
||||
sprite(722, 72, 64, 31, xofs=-31, yofs=-1)
|
||||
sprite( 2, 136, 20, 14, xofs= 1, yofs= 5)
|
||||
sprite( 34, 136, 20, 20, xofs= 0, yofs= 0)
|
||||
sprite(185, 125, 18, 15, xofs= -8, yofs= 7)
|
||||
|
||||
#red
|
||||
gen.add_sprite(grf.PaletteRemap([
|
||||
[0x01, 0x09, 0x00],
|
||||
[0x0A, 0x0B, 0xB6],
|
||||
[0x0C, 0x0D, 0xB7],
|
||||
[0x0E, 0x0F, 0xB8],
|
||||
[0x10, 0xFF, 0x00],
|
||||
]))
|
||||
|
||||
# green
|
||||
gen.add_sprite(grf.PaletteRemap([
|
||||
[0x0A, 0x0B, 0xCF],
|
||||
[0x0C, 0x0D, 0xD0],
|
||||
[0x0E, 0x0F, 0xD1],
|
||||
]))
|
||||
|
||||
# black
|
||||
gen.add_sprite(grf.PaletteRemap([
|
||||
[0x0A, 0x0B, 0x10],
|
||||
[0x0C, 0x0D, 0x11],
|
||||
[0x0E, 0x0F, 0x12],
|
||||
]))
|
||||
|
||||
# ligth blue
|
||||
gen.add_sprite(grf.PaletteRemap([
|
||||
[0x0A, 0x0B, 0x96],
|
||||
[0x0C, 0x0D, 0x97],
|
||||
[0x0E, 0x0F, 0x98],
|
||||
]))
|
||||
|
||||
# orange
|
||||
gen.add_sprite(grf.PaletteRemap([
|
||||
[0x0A, 0x0B, 0xB9],
|
||||
[0x0C, 0x0D, 0xBA],
|
||||
[0x0E, 0x0F, 0xBB],
|
||||
]))
|
||||
|
||||
# white
|
||||
gen.add_sprite(grf.PaletteRemap([
|
||||
[0x0A, 0x0B, 0x0D],
|
||||
[0x0C, 0x0D, 0x0E],
|
||||
[0x0E, 0x0F, 0x0F],
|
||||
]))
|
||||
|
||||
# white (yellow)
|
||||
gen.add_sprite(grf.PaletteRemap([
|
||||
[0x0A, 0x0B, 0x32],
|
||||
[0x0C, 0x0D, 0x33],
|
||||
[0x0E, 0x0F, 0x34],
|
||||
]))
|
||||
|
||||
# white (purple)
|
||||
gen.add_sprite(grf.PaletteRemap([
|
||||
[0x0A, 0x0B, 0xAC],
|
||||
[0x0C, 0x0D, 0xAD],
|
||||
[0x0E, 0x0F, 0xAE],
|
||||
]))
|
||||
|
||||
borderhl_png = grf.ImageFile('sprites/borderhighlight.png')
|
||||
SPRITE_MARGIN = 10
|
||||
TILEDATA = [
|
||||
[ 20, 20, 64, 31, -31, 7],
|
||||
[ 20, 70, 64, 31, -31, 7],
|
||||
[ 20, 120, 64, 23, -31, 7],
|
||||
[ 20, 170, 64, 23, -31, 7],
|
||||
[ 20, 220, 64, 31, -31, 7],
|
||||
[ 20, 270, 64, 31, -31, 7],
|
||||
[ 20, 320, 64, 23, -31, 7],
|
||||
[ 20, 370, 64, 23, -31, 7],
|
||||
[ 20, 420, 64, 39, -31, -1],
|
||||
[ 20, 470, 64, 39, -31, -1],
|
||||
[ 20, 520, 64, 31, -31, -1],
|
||||
[ 20, 570, 64, 31, -31, -1],
|
||||
[ 20, 620, 64, 39, -31, -1],
|
||||
[ 20, 670, 64, 39, -31, -1],
|
||||
[ 20, 720, 64, 31, -31, -1],
|
||||
[ 20, 770, 64, 47, -31, -9],
|
||||
[ 20, 820, 64, 15, -31, 7],
|
||||
[ 20, 870, 64, 31, -31, -1],
|
||||
[ 20, 920, 64, 31, -31, -1],
|
||||
]
|
||||
y = SPRITE_MARGIN
|
||||
for p in TILEDATA:
|
||||
x = SPRITE_MARGIN
|
||||
_, _, w, h, xofs, yofs = p
|
||||
for _ in range(1, 16 + 4):
|
||||
gen.add_sprite(grf.FileSprite(borderhl_png, x, y, w, h, xofs=xofs, yofs=yofs))
|
||||
x += SPRITE_MARGIN + w
|
||||
|
||||
y += h + SPRITE_MARGIN
|
||||
|
||||
|
||||
def gen_tint(tint, ratio):
|
||||
return lambda x: x.blend(tint, ratio=ratio)
|
||||
|
||||
def gen_brightness(level):
|
||||
def func(x):
|
||||
if level > 0:
|
||||
return x.brighten(amount=2.56 * level)
|
||||
else:
|
||||
return x.darken(amount=-2.56 * level)
|
||||
return func
|
||||
|
||||
def gen_white_tint_contrast():
|
||||
def func(x):
|
||||
white = spectra.rgb(1.0, 1.0, 1.0)
|
||||
x = x.blend(white, ratio=0.4)
|
||||
if grf.color_distance(x, white) < 0.5:
|
||||
x = x.blend(spectra.rgb(0.5, 1.0, 0.0), ratio=0.2)
|
||||
return x
|
||||
return func
|
||||
|
||||
|
||||
remap = lambda f: gen.add_sprite(grf.PaletteRemap.from_function(f, remap_water=True))
|
||||
remap(gen_tint(spectra.rgb(1, 0, 0), 0.6)) # deep red tint
|
||||
remap(gen_tint(spectra.rgb(1, 0.5, 0), 0.65)) # deep orange tint
|
||||
remap(gen_tint(spectra.rgb(0, 1, 0), 0.65)) # deep green tint
|
||||
remap(gen_tint(spectra.rgb(0, 1, 1), 0.65)) # deep cyan tint
|
||||
remap(gen_tint(spectra.rgb(1, 0, 0), 0.4)) # red tint
|
||||
remap(gen_tint(spectra.rgb(1, 0.5, 0), 0.4)) # orange tint
|
||||
remap(gen_tint(spectra.rgb(1.0, 1.0, 0), 0.4)) # yellow tint
|
||||
remap(gen_tint(spectra.rgb(1.0, 1.0, 0.5), 0.4)) # yellow white tint
|
||||
remap(gen_white_tint_contrast()) # white tint
|
||||
remap(gen_tint(spectra.rgb(0, 1.0, 0), 0.4)) # green tint
|
||||
remap(gen_tint(spectra.rgb(0, 1.0, 1.0), 0.4)) # cyan tint
|
||||
remap(gen_tint(spectra.rgb(0.5, 1.0, 1.0), 0.4)) # cyan white tint
|
||||
remap(gen_tint(spectra.rgb(0, 0, 1.0), 0.4)) # blue tint
|
||||
|
||||
B = 22.2
|
||||
remap(gen_brightness(21.7 - B)) # shade N
|
||||
remap(gen_brightness(24.2 - B)) # shade NE 27.2
|
||||
remap(gen_brightness(25.7 - B)) # shade E 28.7
|
||||
remap(gen_brightness(23.4 - B)) # shade SE
|
||||
remap(gen_brightness(23.8 - B)) # shade S
|
||||
remap(gen_brightness(18.4 - B)) # shade SW
|
||||
remap(gen_brightness(17.1 - B)) # shade W
|
||||
remap(gen_brightness(17.5 - B)) # shade NW
|
||||
|
||||
gen.write('../../bin/data/cmclient-5.grf')
|
||||
280
grf/cmclient/grf.py
Normal file
280
grf/cmclient/grf.py
Normal file
@@ -0,0 +1,280 @@
|
||||
import math
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
from nml.spriteencoder import SpriteEncoder
|
||||
import spectra
|
||||
import struct
|
||||
import numpy as np
|
||||
|
||||
to_spectra = lambda r, g, b: spectra.rgb(float(r) / 255., float(g) / 255., float(b) / 255.)
|
||||
# working with DOS palette only
|
||||
PALETTE = (0, 0, 255, 16, 16, 16, 32, 32, 32, 48, 48, 48, 64, 64, 64, 80, 80, 80, 100, 100, 100, 116, 116, 116, 132, 132, 132, 148, 148, 148, 168, 168, 168, 184, 184, 184, 200, 200, 200, 216, 216, 216, 232, 232, 232, 252, 252, 252, 52, 60, 72, 68, 76, 92, 88, 96, 112, 108, 116, 132, 132, 140, 152, 156, 160, 172, 176, 184, 196, 204, 208, 220, 48, 44, 4, 64, 60, 12, 80, 76, 20, 96, 92, 28, 120, 120, 64, 148, 148, 100, 176, 176, 132, 204, 204, 168, 72, 44, 4, 88, 60, 20, 104, 80, 44, 124, 104, 72, 152, 132, 92, 184, 160, 120, 212, 188, 148, 244, 220, 176, 64, 0, 4, 88, 4, 16, 112, 16, 32, 136, 32, 52, 160, 56, 76, 188, 84, 108, 204, 104, 124, 220, 132, 144, 236, 156, 164, 252, 188, 192, 252, 208, 0, 252, 232, 60, 252, 252, 128, 76, 40, 0, 96, 60, 8, 116, 88, 28, 136, 116, 56, 156, 136, 80, 176, 156, 108, 196, 180, 136, 68, 24, 0, 96, 44, 4, 128, 68, 8, 156, 96, 16, 184, 120, 24, 212, 156, 32, 232, 184, 16, 252, 212, 0, 252, 248, 128, 252, 252, 192, 32, 4, 0, 64, 20, 8, 84, 28, 16, 108, 44, 28, 128, 56, 40, 148, 72, 56, 168, 92, 76, 184, 108, 88, 196, 128, 108, 212, 148, 128, 8, 52, 0, 16, 64, 0, 32, 80, 4, 48, 96, 4, 64, 112, 12, 84, 132, 20, 104, 148, 28, 128, 168, 44, 28, 52, 24, 44, 68, 32, 60, 88, 48, 80, 104, 60, 104, 124, 76, 128, 148, 92, 152, 176, 108, 180, 204, 124, 16, 52, 24, 32, 72, 44, 56, 96, 72, 76, 116, 88, 96, 136, 108, 120, 164, 136, 152, 192, 168, 184, 220, 200, 32, 24, 0, 56, 28, 0, 72, 40, 4, 88, 52, 12, 104, 64, 24, 124, 84, 44, 140, 108, 64, 160, 128, 88, 76, 40, 16, 96, 52, 24, 116, 68, 40, 136, 84, 56, 164, 96, 64, 184, 112, 80, 204, 128, 96, 212, 148, 112, 224, 168, 128, 236, 188, 148, 80, 28, 4, 100, 40, 20, 120, 56, 40, 140, 76, 64, 160, 100, 96, 184, 136, 136, 36, 40, 68, 48, 52, 84, 64, 64, 100, 80, 80, 116, 100, 100, 136, 132, 132, 164, 172, 172, 192, 212, 212, 224, 40, 20, 112, 64, 44, 144, 88, 64, 172, 104, 76, 196, 120, 88, 224, 140, 104, 252, 160, 136, 252, 188, 168, 252, 0, 24, 108, 0, 36, 132, 0, 52, 160, 0, 72, 184, 0, 96, 212, 24, 120, 220, 56, 144, 232, 88, 168, 240, 128, 196, 252, 188, 224, 252, 16, 64, 96, 24, 80, 108, 40, 96, 120, 52, 112, 132, 80, 140, 160, 116, 172, 192, 156, 204, 220, 204, 240, 252, 172, 52, 52, 212, 52, 52, 252, 52, 52, 252, 100, 88, 252, 144, 124, 252, 184, 160, 252, 216, 200, 252, 244, 236, 72, 20, 112, 92, 44, 140, 112, 68, 168, 140, 100, 196, 168, 136, 224, 200, 176, 248, 208, 184, 255, 232, 208, 252, 60, 0, 0, 92, 0, 0, 128, 0, 0, 160, 0, 0, 196, 0, 0, 224, 0, 0, 252, 0, 0, 252, 80, 0, 252, 108, 0, 252, 136, 0, 252, 164, 0, 252, 192, 0, 252, 220, 0, 252, 252, 0, 204, 136, 8, 228, 144, 4, 252, 156, 0, 252, 176, 48, 252, 196, 100, 252, 216, 152, 8, 24, 88, 12, 36, 104, 20, 52, 124, 28, 68, 140, 40, 92, 164, 56, 120, 188, 72, 152, 216, 100, 172, 224, 92, 156, 52, 108, 176, 64, 124, 200, 76, 144, 224, 92, 224, 244, 252, 200, 236, 248, 180, 220, 236, 132, 188, 216, 88, 152, 172, 244, 0, 244, 245, 0, 245, 246, 0, 246, 247, 0, 247, 248, 0, 248, 249, 0, 249, 250, 0, 250, 251, 0, 251, 252, 0, 252, 253, 0, 253, 254, 0, 254, 255, 0, 255, 76, 24, 8, 108, 44, 24, 144, 72, 52, 176, 108, 84, 210, 146, 126, 252, 60, 0, 252, 84, 0, 252, 104, 0, 252, 124, 0, 252, 148, 0, 252, 172, 0, 252, 196, 0, 64, 0, 0, 255, 0, 0, 48, 48, 0, 64, 64, 0, 80, 80, 0, 255, 255, 0, 32, 68, 112, 36, 72, 116, 40, 76, 120, 44, 80, 124, 48, 84, 128, 72, 100, 144, 100, 132, 168, 216, 244, 252, 96, 128, 164, 68, 96, 140, 255, 255, 255)
|
||||
SAFE_COLORS = set(range(1, 0xD7))
|
||||
SPECTRA_PALETTE = {i:to_spectra(PALETTE[i * 3], PALETTE[i * 3 + 1], PALETTE[i * 3 + 2]) for i in range(256)}
|
||||
WATER_COLORS = set(range(0xF5, 0xFF))
|
||||
|
||||
# ZOOM_OUT_4X, ZOOM_NORMAL, ZOOM_OUT_2X, ZOOM_OUT_8X, ZOOM_OUT_16X, ZOOM_OUT_32X = range(6)
|
||||
ZOOM_4X, ZOOM_NORMAL, ZOOM_2X, ZOOM_8X, ZOOM_16X, ZOOM_32X = range(6)
|
||||
BPP_8, BPP_32 = range(2)
|
||||
|
||||
def color_distance(c1, c2):
|
||||
rmean = (c1.rgb[0] + c2.rgb[0]) / 2.
|
||||
r = c1.rgb[0] - c2.rgb[0]
|
||||
g = c1.rgb[1] - c2.rgb[1]
|
||||
b = c1.rgb[2] - c2.rgb[2]
|
||||
return math.sqrt(
|
||||
((2 + rmean) * r * r) +
|
||||
4 * g * g +
|
||||
(3 - rmean) * b * b)
|
||||
|
||||
|
||||
def find_best_color(x):
|
||||
mj, md = 0, 1e100
|
||||
for j in SAFE_COLORS:
|
||||
c = SPECTRA_PALETTE[j]
|
||||
d = color_distance(x, c)
|
||||
if d < md:
|
||||
mj, md = j, d
|
||||
return mj
|
||||
|
||||
|
||||
# def map_rgb_image(self, im):
|
||||
# assert im.mode == 'RGB', im.mode
|
||||
# data = np.array(im)
|
||||
|
||||
|
||||
class BaseSprite:
|
||||
def get_data(self):
|
||||
raise NotImplemented
|
||||
|
||||
def get_data_size(self):
|
||||
raise NotImplemented
|
||||
|
||||
|
||||
class PaletteRemap(BaseSprite):
|
||||
def __init__(self, ranges=None):
|
||||
self.remap = np.arange(256, dtype=np.uint8)
|
||||
if ranges:
|
||||
self.set_ranges(ranges)
|
||||
|
||||
def get_data(self):
|
||||
return b'\x00' + self.remap.tobytes()
|
||||
|
||||
def get_data_size(self):
|
||||
return 257
|
||||
|
||||
@classmethod
|
||||
def from_function(cls, color_func, remap_water=False):
|
||||
res = cls()
|
||||
for i in SAFE_COLORS:
|
||||
res.remap[i] = find_best_color(color_func(SPECTRA_PALETTE[i]))
|
||||
if remap_water:
|
||||
for i in WATER_COLORS:
|
||||
res.remap[i] = find_best_color(color_func(SPECTRA_PALETTE[i]))
|
||||
return res
|
||||
|
||||
def set_ranges(self, ranges):
|
||||
for r in ranges:
|
||||
f, t, v = r
|
||||
self.remap[f: t + 1] = v
|
||||
|
||||
def remap_image(self, im):
|
||||
assert im.mode == 'P', im.mode
|
||||
data = np.array(im)
|
||||
data = self.remap[data]
|
||||
res = Image.fromarray(data)
|
||||
res.putpalette(PALETTE)
|
||||
return res
|
||||
|
||||
|
||||
class RealSprite(BaseSprite):
|
||||
def __init__(self, w, h, *, xofs=0, yofs=0, zoom=ZOOM_4X):
|
||||
self.sprite_id = None
|
||||
self.w = w
|
||||
self.h = h
|
||||
# self.file = None
|
||||
# self.x = None
|
||||
# self.y = None
|
||||
self.xofs = xofs
|
||||
self.yofs = yofs
|
||||
self.zoom = zoom
|
||||
|
||||
def get_data_size(self):
|
||||
return 4
|
||||
|
||||
def get_data(self):
|
||||
return struct.pack('<I', self.sprite_id)
|
||||
|
||||
def get_real_data(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def draw(self, img):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class ImageFile:
|
||||
def __init__(self, filename, bpp=BPP_8):
|
||||
assert(bpp == BPP_8) # TODO
|
||||
self.filename = filename
|
||||
self.bpp = bpp
|
||||
self._image = None
|
||||
|
||||
def get_image(self):
|
||||
if self._image:
|
||||
return self._image
|
||||
img = Image.open(self.filename)
|
||||
assert (img.mode == 'P') # TODO
|
||||
# pal = img.getpalette()
|
||||
# if pal != PALETTE:
|
||||
# remap = PaletteRemap()
|
||||
# for i in range(256):
|
||||
# remap.remap[i] = find_best_color(to_spectra(pal[3 * i], pal[3 * i + 1], pal[3 * i + 2]))
|
||||
# self._image = remap.remap_image(img)
|
||||
self._image = img
|
||||
return self._image
|
||||
|
||||
|
||||
class FileSprite(RealSprite):
|
||||
def __init__(self, file, x, y, w, h, **kw):
|
||||
assert(isinstance(file, ImageFile))
|
||||
super().__init__(w, h, **kw)
|
||||
self.file = file
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
def get_real_data(self):
|
||||
img = self.file.get_image()
|
||||
img = img.crop((self.x, self.y, self.x + self.w, self.y + self.h))
|
||||
raw_data = img.tobytes()
|
||||
se = SpriteEncoder(True, False, None)
|
||||
data = se.sprite_compress(raw_data)
|
||||
return struct.pack(
|
||||
'<IIBBHHhh',
|
||||
self.sprite_id,
|
||||
len(data) + 10, 0x04,
|
||||
self.zoom,
|
||||
self.h,
|
||||
self.w,
|
||||
self.xofs,
|
||||
self.yofs,
|
||||
) + data
|
||||
# return struct.pack(
|
||||
# '<IIBBHHhhI',
|
||||
# self.sprite_id,
|
||||
# len(data) + 14, 0x0C,
|
||||
# self.zoom,
|
||||
# self.h,
|
||||
# self.w,
|
||||
# self.xofs,
|
||||
# self.yofs,
|
||||
# len(raw_data),
|
||||
# ) + data
|
||||
|
||||
|
||||
|
||||
class SpriteSheet:
|
||||
def __init__(self, sprites=None):
|
||||
self._sprites = list(sprites) if sprites else []
|
||||
|
||||
def make_image(self, filename, padding=5, columns=10):
|
||||
w, h = 0, padding
|
||||
lineofs = []
|
||||
for i in range(0, len(self._sprites), columns):
|
||||
w = max(w, sum(s.w for s in self._sprites[i: i + columns]))
|
||||
lineofs.append(h)
|
||||
h += padding + max((s.h for s in self._sprites[i: i + columns]), default=0)
|
||||
|
||||
w += (columns + 1) * padding
|
||||
im = Image.new('L', (w, h), color=0xff)
|
||||
im.putpalette(PALETTE)
|
||||
|
||||
x = 0
|
||||
for i, s in enumerate(self._sprites):
|
||||
y = lineofs[i // columns]
|
||||
if i % columns == 0:
|
||||
x = padding
|
||||
s.x = x
|
||||
s.y = y
|
||||
s.file = filename
|
||||
s.draw(im)
|
||||
x += s.w + padding
|
||||
|
||||
im.save(filename)
|
||||
|
||||
|
||||
def write_nml(self, file):
|
||||
for s in self._sprites:
|
||||
file.write(s.get_nml())
|
||||
file.write('\n')
|
||||
file.write('\n')
|
||||
|
||||
|
||||
class DummySprite(BaseSprite):
|
||||
def get_data(self):
|
||||
return b'\x00'
|
||||
|
||||
def get_data_size(self):
|
||||
return 1
|
||||
|
||||
|
||||
class DescriptionSprite(BaseSprite):
|
||||
def __init__(self, grfid, name, description):
|
||||
assert isinstance(grfid, bytes)
|
||||
assert isinstance(name, str)
|
||||
assert isinstance(description, str)
|
||||
self.grfid = grfid
|
||||
self.name = name
|
||||
self.description = description
|
||||
self._data = b'\x08\x08' + self.grfid + self.name.encode('utf-8') + b'\x00' + self.description.encode('utf-8') + b'\x00'
|
||||
|
||||
def get_data(self):
|
||||
return self._data
|
||||
|
||||
def get_data_size(self):
|
||||
return len(self._data)
|
||||
|
||||
class NewGRF:
|
||||
def __init__(self, grfid, name, description):
|
||||
self.sprites = []
|
||||
self.sprites.append(DescriptionSprite(grfid, name, description))
|
||||
self._next_sprite_id = 1
|
||||
|
||||
def add_sprite(self, *sprites):
|
||||
if len(sprites) > 1:
|
||||
assert(all(isinstance(s, RealSprite) for s in sprites))
|
||||
assert(len(set(s.zoom for s in sprites)) == len(sprites))
|
||||
|
||||
if isinstance(sprites[0], RealSprite):
|
||||
for s in sprites:
|
||||
s.sprite_id = self._next_sprite_id
|
||||
self._next_sprite_id += 1
|
||||
|
||||
for s in sprites:
|
||||
self.sprites.append(s)
|
||||
|
||||
def _write_pseudo_sprite(self, f, data, grf_type=0xff):
|
||||
f.write(struct.pack('<IB', len(data), grf_type))
|
||||
f.write(data)
|
||||
|
||||
def write(self, filename):
|
||||
data_offset = 14
|
||||
for s in self.sprites:
|
||||
data_offset += s.get_data_size() + 5
|
||||
|
||||
with open(filename, 'wb') as f:
|
||||
f.write(b'\x00\x00GRF\x82\x0d\x0a\x1a\x0a') # file header
|
||||
f.write(struct.pack('<I', data_offset))
|
||||
f.write(b'\x00') # compression(1)
|
||||
# f.write(b'\x04\x00\x00\x00') # num(4)
|
||||
# f.write(b'\xFF') # grf_type(1)
|
||||
# f.write(b'\xb0\x01\x00\x00') # num + 0xff -> recoloursprites() (257 each)
|
||||
self._write_pseudo_sprite(f, b'\x02\x00\x00\x00')
|
||||
|
||||
for s in self.sprites:
|
||||
self._write_pseudo_sprite(f, s.get_data(), grf_type=0xfd if isinstance(s, RealSprite) else 0xff)
|
||||
f.write(b'\x00\x00\x00\x00')
|
||||
for s in self.sprites:
|
||||
if not isinstance(s, RealSprite): continue
|
||||
f.write(s.get_real_data())
|
||||
|
||||
f.write(b'\x00\x00\x00\x00')
|
||||
77
grf/cmclient/readgrftest.py
Normal file
77
grf/cmclient/readgrftest.py
Normal file
@@ -0,0 +1,77 @@
|
||||
import sys
|
||||
import struct
|
||||
from nml import lz77
|
||||
|
||||
|
||||
def hex_str(s):
|
||||
if isinstance(s, (bytes, memoryview)):
|
||||
return ':'.join('{:02x}'.format(b) for b in s)
|
||||
return ':'.join('{:02x}'.format(ord(c)) for c in s)
|
||||
|
||||
|
||||
def read_pseudo_sprite(f):
|
||||
l = struct.unpack('<I', f.read(4))[0]
|
||||
if l == 0:
|
||||
print('End of pseudo sprites')
|
||||
return False
|
||||
grf_type = str(f.read(1))[-3:-1]
|
||||
data = f.read(l)
|
||||
print(f'Sprite({l}, {grf_type}): ', hex_str(data[:100]))
|
||||
return True
|
||||
|
||||
def decode_sprite(f, num):
|
||||
data = b''
|
||||
while num > 0:
|
||||
code = f.read(1)[0]
|
||||
if code >= 128: code -= 256
|
||||
# print(f'Code {code} num {num}')
|
||||
if code >= 0:
|
||||
size = 0x80 if code == 0 else code
|
||||
num -= size
|
||||
if num < 0: raise RuntimeError('Corrupt sprite')
|
||||
data += f.read(size)
|
||||
else:
|
||||
data_offset = ((code & 7) << 8) | f.read(1)[0]
|
||||
#if (dest - data_offset < dest_orig.get()) return WarnCorruptSprite(file, file_pos, __LINE__);
|
||||
size = -(code >> 3)
|
||||
num -= size
|
||||
if num < 0: raise RuntimeError('Corrupt sprite')
|
||||
data += data[-data_offset:size - data_offset]
|
||||
if num != 0: raise RuntimeError('Corrupt sprite')
|
||||
return data
|
||||
|
||||
def read_real_sprite(f):
|
||||
sprite_id = struct.unpack('<I', f.read(4))[0]
|
||||
if sprite_id == 0:
|
||||
print(f'End of real sprites')
|
||||
return False
|
||||
print(f'Real sprite({sprite_id}): ', end='')
|
||||
num, t = struct.unpack('<IB', f.read(5))
|
||||
start_pos = f.tell()
|
||||
print(f'({num}, {t:02x}): ', end='')
|
||||
if t == 0xff:
|
||||
print('non-real (skip)')
|
||||
f.seek(start_pos + num - 1, 0)
|
||||
return True
|
||||
zoom, height, width, x_offs, y_offs = struct.unpack('<BHHhh', f.read(9))
|
||||
bpp = 1 # TODO
|
||||
decomp_size = struct.unpack('<I', f.read(4))[0] if t & 0x08 else width * height * bpp
|
||||
print(f'{width}x{height} zoom={zoom} x_offs={x_offs} y_offs={y_offs} bpp={bpp} decomp_size={decomp_size}')
|
||||
# data = decode_sprite(f, decomp_size)
|
||||
# print('Data: ', hex_str(data[:40]))
|
||||
f.seek(start_pos + num - 1, 0)
|
||||
return True
|
||||
|
||||
with open(sys.argv[1], 'rb') as f:
|
||||
print('Header:', hex_str(f.read(10)))
|
||||
data_offest, compression = struct.unpack('<IB', f.read(5))
|
||||
header_offset = f.tell() - 1
|
||||
print(f'Offset: {data_offest} compresion: {compression}')
|
||||
while read_pseudo_sprite(f):
|
||||
pass
|
||||
real_data_offset = f.tell() - header_offset
|
||||
while read_real_sprite(f):
|
||||
pass
|
||||
if data_offest != real_data_offset:
|
||||
print(f'[ERROR] Data offset check failed: {data_offest} {real_data_offset}')
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
import math
|
||||
import spectra
|
||||
|
||||
# SAFE_COLORS = list(range(0xA0, 0xD8)) + [0xf5]
|
||||
SAFE_COLORS = list(range(1, 0xD7))
|
||||
f = open("../ttd-newgrf-dos.gpl")
|
||||
|
||||
while f.readline().strip() != "#":
|
||||
pass
|
||||
|
||||
|
||||
def color_distance(c1, c2):
|
||||
rmean = (c1.rgb[0] + c2.rgb[0]) / 2.
|
||||
r = c1.rgb[0] - c2.rgb[0]
|
||||
g = c1.rgb[1] - c2.rgb[1]
|
||||
b = c1.rgb[2] - c2.rgb[2]
|
||||
return math.sqrt(
|
||||
((2 + rmean) * r * r) +
|
||||
4 * g * g +
|
||||
(3 - rmean) * b * b)
|
||||
|
||||
# def color_distance(c1, c2):
|
||||
# r = c1[0] - c2[0]
|
||||
# g = c1[1] - c2[1]
|
||||
# b = c1[2] - c2[2]
|
||||
# return math.sqrt(r*r + g*g + b*b)
|
||||
|
||||
def gen_recolor(color_func):
|
||||
def func(x):
|
||||
x = color_func(x)
|
||||
mj, md = 0, 1e100
|
||||
for j, c in colors:
|
||||
if j not in SAFE_COLORS:
|
||||
continue
|
||||
d = color_distance(x, c)
|
||||
if d < md:
|
||||
mj, md = j, d
|
||||
return mj
|
||||
return func
|
||||
|
||||
def gen_tint(tint, ratio):
|
||||
return gen_recolor(lambda x: x.blend(tint, ratio=ratio))
|
||||
|
||||
def gen_brightness(level):
|
||||
def func(x):
|
||||
if level > 0:
|
||||
return x.brighten(amount=2.56 * level)
|
||||
else:
|
||||
return x.darken(amount=-2.56 * level)
|
||||
return gen_recolor(func)
|
||||
|
||||
def gen_white_tint_contrast():
|
||||
def func(x):
|
||||
white = spectra.rgb(1.0, 1.0, 1.0)
|
||||
x = x.blend(white, ratio=0.4)
|
||||
if color_distance(x, white) < 0.5:
|
||||
x = x.blend(spectra.rgb(0.5, 1.0, 0.0), ratio=0.2)
|
||||
return x
|
||||
return gen_recolor(func)
|
||||
|
||||
def gen_palette(func, comment):
|
||||
print(f" // {comment}")
|
||||
print(" recolour_sprite {")
|
||||
print(" ", end="")
|
||||
for i, c in colors:
|
||||
mj = func(c)
|
||||
print(f"0x{i:02x}: 0x{mj:02x};", end=" ")
|
||||
print()
|
||||
print(" }")
|
||||
print()
|
||||
|
||||
|
||||
colors = []
|
||||
for _ in range(256):
|
||||
try:
|
||||
r, g, b, _, i = f.readline().split()
|
||||
except ValueError:
|
||||
break
|
||||
c = spectra.rgb(float(r) / 255., float(g) / 255., float(b) / 255.)
|
||||
# if c in SAFE_COLORS:
|
||||
colors.append((int(i), c))
|
||||
|
||||
|
||||
for l in open("cmclient-header.nml"):
|
||||
print(l, end='')
|
||||
|
||||
# print("replace recolour_palettes(10389) {")
|
||||
gen_palette(gen_tint(spectra.rgb(1, 0, 0), 0.6), "deep red tint")
|
||||
gen_palette(gen_tint(spectra.rgb(1, 0.5, 0), 0.65), "deep orange tint")
|
||||
gen_palette(gen_tint(spectra.rgb(0, 1, 0), 0.65), "deep green tint")
|
||||
gen_palette(gen_tint(spectra.rgb(0, 1, 1), 0.65), "deep cyan tint")
|
||||
gen_palette(gen_tint(spectra.rgb(1, 0, 0), 0.4), "red tint")
|
||||
gen_palette(gen_tint(spectra.rgb(1, 0.5, 0), 0.4), "orange tint")
|
||||
gen_palette(gen_tint(spectra.rgb(1.0, 1.0, 0), 0.4), "yellow tint")
|
||||
gen_palette(gen_tint(spectra.rgb(1.0, 1.0, 0.5), 0.4), "yellow white tint")
|
||||
# gen_palette(gen_tint(spectra.rgb(1.0, 1.0, 1.0), 0.4), "white tint")
|
||||
gen_palette(gen_white_tint_contrast(), "white tint")
|
||||
gen_palette(gen_tint(spectra.rgb(0, 1.0, 0), 0.4), "green tint")
|
||||
gen_palette(gen_tint(spectra.rgb(0, 1.0, 1.0), 0.4), "cyan tint")
|
||||
gen_palette(gen_tint(spectra.rgb(0.5, 1.0, 1.0), 0.4), "cyan white tint")
|
||||
gen_palette(gen_tint(spectra.rgb(0, 0, 1.0), 0.4), "blue tint")
|
||||
|
||||
B = 22.2
|
||||
gen_palette(gen_brightness(21.7 - B), "shade N")
|
||||
gen_palette(gen_brightness(24.2 - B), "shade NE") # 27.2
|
||||
gen_palette(gen_brightness(25.7 - B), "shade E") # 28.7
|
||||
gen_palette(gen_brightness(23.4 - B), "shade SE")
|
||||
gen_palette(gen_brightness(23.8 - B), "shade S")
|
||||
gen_palette(gen_brightness(18.4 - B), "shade SW")
|
||||
gen_palette(gen_brightness(17.1 - B), "shade W")
|
||||
gen_palette(gen_brightness(17.5 - B), "shade NW")
|
||||
print("}")
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 15 KiB |
Reference in New Issue
Block a user