From b8b2df1f2c5679ac2abd67ac6655cfe83592e239 Mon Sep 17 00:00:00 2001 From: dP Date: Mon, 1 Nov 2021 19:10:08 +0300 Subject: [PATCH] Write cmclient-*.grf directly from python instead of using nml inbetween --- bin/data/CMakeLists.txt | 2 +- bin/data/{cmclient-4.grf => cmclient-5.grf} | Bin 99683 -> 100647 bytes grf/cmclient/cmclient-header.nml | 462 -------------------- grf/cmclient/cmclient.nml | 22 +- grf/cmclient/gencmclientgrf.py | 183 ++++++++ grf/cmclient/grf.py | 280 ++++++++++++ grf/cmclient/readgrftest.py | 77 ++++ grf/cmclient/recolourgen.py | 112 ----- grf/cmclient/sprites/toolbar.png | Bin 6592 -> 15308 bytes src/gfxinit.cpp | 2 +- src/network/network_gui.cpp | 17 + src/object_cmd.cpp | 1 + src/table/sprites.h | 20 +- 13 files changed, 594 insertions(+), 584 deletions(-) rename bin/data/{cmclient-4.grf => cmclient-5.grf} (70%) delete mode 100644 grf/cmclient/cmclient-header.nml create mode 100644 grf/cmclient/gencmclientgrf.py create mode 100644 grf/cmclient/grf.py create mode 100644 grf/cmclient/readgrftest.py delete mode 100644 grf/cmclient/recolourgen.py diff --git a/bin/data/CMakeLists.txt b/bin/data/CMakeLists.txt index 63942e14b6..f1b7d731f1 100644 --- a/bin/data/CMakeLists.txt +++ b/bin/data/CMakeLists.txt @@ -1,5 +1,5 @@ set(DATA_SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/cmclient-4.grf + ${CMAKE_CURRENT_SOURCE_DIR}/cmclient-5.grf ) foreach(DATA_SOURCE_FILE IN LISTS DATA_SOURCE_FILES) diff --git a/bin/data/cmclient-4.grf b/bin/data/cmclient-5.grf similarity index 70% rename from bin/data/cmclient-4.grf rename to bin/data/cmclient-5.grf index e36e98676fc281076f5ec0c2c4af393132a55714..9560677488e1b856c777c6a4ebfba06b1bc6f27c 100644 GIT binary patch delta 4190 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 diff --git a/grf/cmclient/cmclient-header.nml b/grf/cmclient/cmclient-header.nml deleted file mode 100644 index 246259289c..0000000000 --- a/grf/cmclient/cmclient-header.nml +++ /dev/null @@ -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] -//} diff --git a/grf/cmclient/cmclient.nml b/grf/cmclient/cmclient.nml index 5d4061a6a0..c8b6fcf956 100644 --- a/grf/cmclient/cmclient.nml +++ b/grf/cmclient/cmclient.nml @@ -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] diff --git a/grf/cmclient/gencmclientgrf.py b/grf/cmclient/gencmclientgrf.py new file mode 100644 index 0000000000..9d101812b0 --- /dev/null +++ b/grf/cmclient/gencmclientgrf.py @@ -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') diff --git a/grf/cmclient/grf.py b/grf/cmclient/grf.py new file mode 100644 index 0000000000..199d231a9f --- /dev/null +++ b/grf/cmclient/grf.py @@ -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(' 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(' 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') \ No newline at end of file diff --git a/grf/cmclient/readgrftest.py b/grf/cmclient/readgrftest.py new file mode 100644 index 0000000000..9a7dcbc2a8 --- /dev/null +++ b/grf/cmclient/readgrftest.py @@ -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(' 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(' 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("}") diff --git a/grf/cmclient/sprites/toolbar.png b/grf/cmclient/sprites/toolbar.png index b98fe27df03b67a35ebd5d0c4ea5d382f80eb471..1a6f8800802b8bb2ea514adab7bd4f8858313d55 100644 GIT binary patch delta 14594 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 Yp99x&G47bbz`(%Z>FVdQ&MBb@09bfJ@&Et; delta 5803 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 diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 0a44ad77d0..924e90f812 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -182,7 +182,7 @@ static void LoadSpriteTables() PAL_DOS != used_set->palette ); } - LoadGrfFile("cmclient-4.grf", CM_SPR_CITYMANIA_BASE - 4, PAL_DOS != used_set->palette); + LoadGrfFile("cmclient-5.grf", CM_SPR_CITYMANIA_BASE, PAL_DOS != used_set->palette); /* Initialize the unicode to sprite mapping table */ InitializeUnicodeGlyphMap(); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 99074991a0..243f99272d 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -33,6 +33,7 @@ #include "../genworld.h" #include "../map_type.h" #include "../guitimer_func.h" +#include "../viewport_func.h" #include "../zoom_func.h" #include "../sprite.h" #include "../settings_internal.h" @@ -1635,6 +1636,14 @@ private: ShowNetworkChatQueryWindow(DESTTYPE_CLIENT, client_id); } + static void CMOnClickCompanyHQ(NetworkClientListWindow *w, Point pt, CompanyID company_id) + { + auto company = Company::GetIfValid(company_id); + if (company == nullptr || company->location_of_HQ == INVALID_TILE) return; + if (citymania::_fn_mod) ShowExtraViewportWindow(company->location_of_HQ); + else ScrollMainWindowToTile(company->location_of_HQ); + } + /** * Part of RebuildList() to create the information for a single company. * @param company_id The company to build the list for. @@ -1645,6 +1654,14 @@ private: ButtonCommon *chat_button = new CompanyButton(SPR_CHAT, company_id == COMPANY_SPECTATOR ? STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP : STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyChat); if (_network_server) this->buttons[line_count].emplace_back(new CompanyButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP, COLOUR_RED, company_id, &NetworkClientListWindow::OnClickCompanyAdmin, company_id == COMPANY_SPECTATOR)); + /* CityMania code start */ + auto company = Company::GetIfValid(company_id); + if (company != nullptr) { + ButtonCommon *hq_button = new CompanyButton(CM_SPR_HQ, STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::CMOnClickCompanyHQ); + if (company->location_of_HQ == INVALID_TILE) hq_button->disabled = true; + this->buttons[line_count].emplace_back(hq_button); + } + /* CityMania code end */ this->buttons[line_count].emplace_back(chat_button); if (client_playas != company_id) this->buttons[line_count].emplace_back(new CompanyButton(SPR_JOIN, STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyJoin, company_id != COMPANY_SPECTATOR && Company::Get(company_id)->is_ai)); diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index cd080ca538..b75088168d 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -339,6 +339,7 @@ CommandCost CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 hq_score = UpdateCompanyRatingAndValue(c, false); c->location_of_HQ = tile; SetWindowDirty(WC_COMPANY, c->index); + InvalidateWindowData(WC_CLIENT_LIST, 0); } break; } diff --git a/src/table/sprites.h b/src/table/sprites.h index bc2ae29c9c..600f95509d 100644 --- a/src/table/sprites.h +++ b/src/table/sprites.h @@ -309,10 +309,21 @@ static const uint16 EMPTY_BOUNDING_BOX_SPRITE_COUNT = 1; static const SpriteID SPR_PALETTE_BASE = SPR_EMPTY_BOUNDING_BOX + EMPTY_BOUNDING_BOX_SPRITE_COUNT; static const uint16 PALETTE_SPRITE_COUNT = 1; -/* zoning stuff */ +/* CityMania extra sprites */ static const SpriteID CM_SPR_CITYMANIA_BASE = SPR_PALETTE_BASE + PALETTE_SPRITE_COUNT; -static const SpriteID CM_SPR_RAIL_COPY_PASTE = CM_SPR_CITYMANIA_BASE; -static const SpriteID CM_SPR_INNER_HIGHLIGHT_BASE = CM_SPR_CITYMANIA_BASE + 2; +static const SpriteID CM_SPR_RAIL_COPY_PASTE = CM_SPR_CITYMANIA_BASE + 2; +static const SpriteID CM_SPR_HQ = CM_SPR_CITYMANIA_BASE + 4; +static const SpriteID CM_SPR_PLAYER1 = CM_SPR_CITYMANIA_BASE + 5; +static const SpriteID CM_SPR_PLAYER2 = CM_SPR_PLAYER1 + 1; +static const SpriteID CM_SPR_PLAYER3 = CM_SPR_PLAYER1 + 2; +static const SpriteID CM_SPR_PLAYER4 = CM_SPR_PLAYER1 + 3; +static const SpriteID CM_SPR_PLAYER_W1 = CM_SPR_PLAYER1 + 4; +static const SpriteID CM_SPR_PLAYER_W2 = CM_SPR_PLAYER1 + 5; +static const SpriteID CM_SPR_HOST1 = CM_SPR_PLAYER1 + 8; +static const SpriteID CM_SPR_HOST2 = CM_SPR_PLAYER1 + 9; +static const SpriteID CM_SPR_HOST3 = CM_SPR_PLAYER1 + 10; +static const SpriteID CM_SPR_HOST4 = CM_SPR_PLAYER1 + 11; +static const SpriteID CM_SPR_INNER_HIGHLIGHT_BASE = CM_SPR_CITYMANIA_BASE + 17; static const SpriteID CM_SPR_IMG_COMPANY_CARGO = CM_SPR_INNER_HIGHLIGHT_BASE + 19; static const SpriteID CM_SPR_IMG_COMPANY_GOAL = CM_SPR_INNER_HIGHLIGHT_BASE + 20; static const SpriteID CM_SPR_IMG_HOUSE_NEW = CM_SPR_INNER_HIGHLIGHT_BASE + 21; @@ -326,7 +337,7 @@ static const SpriteID CM_SPR_PALETTE_ZONING_YELLOW = CM_SPR_INNER_HIGHLIGHT_ static const SpriteID CM_SPR_PALETTE_ZONING_PURPLE = CM_SPR_INNER_HIGHLIGHT_BASE + 29; static const SpriteID CM_SPR_INNER_HIGHLIGHT_COUNT = 30; -static const SpriteID CM_SPR_BORDER_HIGHLIGHT_BASE = CM_SPR_INNER_HIGHLIGHT_BASE + CM_SPR_INNER_HIGHLIGHT_COUNT + 1; +static const SpriteID CM_SPR_BORDER_HIGHLIGHT_BASE = CM_SPR_INNER_HIGHLIGHT_BASE + CM_SPR_INNER_HIGHLIGHT_COUNT; static const SpriteID CM_SPR_BORDER_HIGHLIGHT_COUNT = 19 * 19; static const SpriteID CM_PALETTE_TINT_BASE = CM_SPR_BORDER_HIGHLIGHT_BASE + CM_SPR_BORDER_HIGHLIGHT_COUNT; static const SpriteID CM_PALETTE_TINT_RED_DEEP = CM_PALETTE_TINT_BASE; @@ -351,7 +362,6 @@ static const SpriteID CM_PALETTE_SHADE_SW = CM_PALETTE_TINT_BASE + static const SpriteID CM_PALETTE_SHADE_W = CM_PALETTE_TINT_BASE + 19; static const SpriteID CM_PALETTE_SHADE_NW = CM_PALETTE_TINT_BASE + 20; static const SpriteID CM_PALETTE_TINT_COUNT = 13 + 8; - /* From where can we start putting NewGRFs? */ static const SpriteID SPR_NEWGRFS_BASE = CM_PALETTE_TINT_BASE + CM_PALETTE_TINT_COUNT;