1 #include "city_figure.h"
2
3 #include "city/view.h"
4 #include "figure/formation.h"
5 #include "figure/image.h"
6 #include "figuretype/editor.h"
7 #include "graphics/image.h"
8 #include "graphics/text.h"
9
draw_figure_with_cart(const figure * f,int x,int y)10 static void draw_figure_with_cart(const figure *f, int x, int y)
11 {
12 if (f->y_offset_cart >= 0) {
13 image_draw(f->image_id, x, y);
14 image_draw(f->cart_image_id, x + f->x_offset_cart, y + f->y_offset_cart);
15 } else {
16 image_draw(f->cart_image_id, x + f->x_offset_cart, y + f->y_offset_cart);
17 image_draw(f->image_id, x, y);
18 }
19 }
20
draw_hippodrome_horse(const figure * f,int x,int y)21 static void draw_hippodrome_horse(const figure *f, int x, int y)
22 {
23 int val = f->wait_ticks_missile;
24 switch (city_view_orientation()) {
25 case DIR_0_TOP:
26 x += 10;
27 if (val <= 10) {
28 y -= 2;
29 } else if (val <= 11) {
30 y -= 10;
31 } else if (val <= 12) {
32 y -= 18;
33 } else if (val <= 13) {
34 y -= 16;
35 } else if (val <= 20) {
36 y -= 14;
37 } else if (val <= 21) {
38 y -= 10;
39 } else {
40 y -= 2;
41 }
42 break;
43 case DIR_2_RIGHT:
44 x -= 10;
45 if (val <= 9) {
46 y -= 12;
47 } else if (val <= 10) {
48 y += 4;
49 } else if (val <= 11) {
50 x -= 5;
51 y += 2;
52 } else if (val <= 13) {
53 x -= 5;
54 } else if (val <= 20) {
55 y -= 2;
56 } else if (val <= 21) {
57 y -= 6;
58 } else {
59 y -= 12;
60 }
61 case DIR_4_BOTTOM:
62 x += 20;
63 if (val <= 9) {
64 y += 4;
65 } else if (val <= 10) {
66 x += 10;
67 y += 4;
68 } else if (val <= 11) {
69 x += 10;
70 y -= 4;
71 } else if (val <= 13) {
72 y -= 6;
73 } else if (val <= 20) {
74 y -= 12;
75 } else if (val <= 21) {
76 y -= 10;
77 } else {
78 y -= 2;
79 }
80 break;
81 case DIR_6_LEFT:
82 x -= 10;
83 if (val <= 9) {
84 y -= 12;
85 } else if (val <= 10) {
86 y += 4;
87 } else if (val <= 11) {
88 y += 2;
89 } else if (val <= 13) {
90 // no change
91 } else if (val <= 20) {
92 y -= 2;
93 } else if (val <= 21) {
94 y -= 6;
95 } else {
96 y -= 12;
97 }
98 break;
99 }
100 draw_figure_with_cart(f, x, y);
101 }
102
draw_fort_standard(const figure * f,int x,int y)103 static void draw_fort_standard(const figure *f, int x, int y)
104 {
105 if (!formation_get(f->formation_id)->in_distant_battle) {
106 // base
107 image_draw(f->image_id, x, y);
108 // flag
109 int flag_height = image_get(f->cart_image_id)->height;
110 image_draw(f->cart_image_id, x, y - flag_height);
111 // top icon
112 int icon_image_id = image_group(GROUP_FIGURE_FORT_STANDARD_ICONS) + f->formation_id - 1;
113 image_draw(icon_image_id, x, y - image_get(icon_image_id)->height - flag_height);
114 }
115 }
116
draw_map_flag(const figure * f,int x,int y)117 static void draw_map_flag(const figure *f, int x, int y)
118 {
119 // base
120 image_draw(f->image_id, x, y);
121 // flag
122 image_draw(f->cart_image_id, x, y - image_get(f->cart_image_id)->height);
123 // flag number
124 int number = 0;
125 int id = f->resource_id;
126 if (id >= MAP_FLAG_INVASION_MIN && id < MAP_FLAG_INVASION_MAX) {
127 number = id - MAP_FLAG_INVASION_MIN + 1;
128 } else if (id >= MAP_FLAG_FISHING_MIN && id < MAP_FLAG_FISHING_MAX) {
129 number = id - MAP_FLAG_FISHING_MIN + 1;
130 } else if (id >= MAP_FLAG_HERD_MIN && id < MAP_FLAG_HERD_MAX) {
131 number = id - MAP_FLAG_HERD_MIN + 1;
132 }
133 if (number > 0) {
134 text_draw_number_colored(number, '@', " ", x + 6, y + 7, FONT_NORMAL_PLAIN, COLOR_WHITE);
135 }
136 }
137
tile_cross_country_offset_to_pixel_offset(int cross_country_x,int cross_country_y,int * pixel_x,int * pixel_y)138 static void tile_cross_country_offset_to_pixel_offset(int cross_country_x, int cross_country_y,
139 int *pixel_x, int *pixel_y)
140 {
141 int dir = city_view_orientation();
142 if (dir == DIR_0_TOP || dir == DIR_4_BOTTOM) {
143 int base_pixel_x = 2 * cross_country_x - 2 * cross_country_y;
144 int base_pixel_y = cross_country_x + cross_country_y;
145 *pixel_x = dir == DIR_0_TOP ? base_pixel_x : -base_pixel_x;
146 *pixel_y = dir == DIR_0_TOP ? base_pixel_y : -base_pixel_y;
147 } else {
148 int base_pixel_x = 2 * cross_country_x + 2 * cross_country_y;
149 int base_pixel_y = cross_country_x - cross_country_y;
150 *pixel_x = dir == DIR_2_RIGHT ? base_pixel_x : -base_pixel_x;
151 *pixel_y = dir == DIR_6_LEFT ? base_pixel_y : -base_pixel_y;
152 }
153 }
154
tile_progress_to_pixel_offset_x(int direction,int progress)155 static int tile_progress_to_pixel_offset_x(int direction, int progress)
156 {
157 if (progress >= 15) {
158 return 0;
159 }
160 switch (direction) {
161 case DIR_0_TOP:
162 case DIR_2_RIGHT:
163 return 2 * progress - 28;
164 case DIR_1_TOP_RIGHT:
165 return 4 * progress - 56;
166 case DIR_4_BOTTOM:
167 case DIR_6_LEFT:
168 return 28 - 2 * progress;
169 case DIR_5_BOTTOM_LEFT:
170 return 56 - 4 * progress;
171 default:
172 return 0;
173 }
174 }
175
tile_progress_to_pixel_offset_y(int direction,int progress)176 static int tile_progress_to_pixel_offset_y(int direction, int progress)
177 {
178 if (progress >= 15) {
179 return 0;
180 }
181 switch (direction) {
182 case DIR_0_TOP:
183 case DIR_6_LEFT:
184 return 14 - progress;
185 case DIR_2_RIGHT:
186 case DIR_4_BOTTOM:
187 return progress - 14;
188 case DIR_3_BOTTOM_RIGHT:
189 return 2 * progress - 28;
190 case DIR_7_TOP_LEFT:
191 return 28 - 2 * progress;
192 default:
193 return 0;
194 }
195 }
196
tile_progress_to_pixel_offset(int direction,int progress,int * pixel_x,int * pixel_y)197 static void tile_progress_to_pixel_offset(int direction, int progress, int *pixel_x, int *pixel_y)
198 {
199 *pixel_x = tile_progress_to_pixel_offset_x(direction, progress);
200 *pixel_y = tile_progress_to_pixel_offset_y(direction, progress);
201 }
202
adjust_pixel_offset(const figure * f,int * pixel_x,int * pixel_y)203 static void adjust_pixel_offset(const figure *f, int *pixel_x, int *pixel_y)
204 {
205 // determining x/y offset on tile
206 int x_offset = 0;
207 int y_offset = 0;
208 if (f->use_cross_country) {
209 tile_cross_country_offset_to_pixel_offset(
210 f->cross_country_x % 15, f->cross_country_y % 15, &x_offset, &y_offset);
211 y_offset -= f->missile_damage;
212 } else {
213 int direction = figure_image_normalize_direction(f->direction);
214 tile_progress_to_pixel_offset(direction, f->progress_on_tile, &x_offset, &y_offset);
215 y_offset -= f->current_height;
216 if (f->figures_on_same_tile_index && f->type != FIGURE_BALLISTA) {
217 // an attempt to not let people walk through each other
218 static const int BUSY_ROAD_X_OFFSETS[] = {
219 0, 8, 8, -8, -8, 0, 16, 0, -16, 8, -8, 16, -16, 16, -16, 8, -8, 0, 24, 0, -24, 0, 0, 0
220 };
221 static const int BUSY_ROAD_Y_OFFSETS[] = {
222 0, 0, 8, 8, -8, -16, 0, 16, 0, -16, 16, 8, -8, -8, 8, 16, -16, -24, 0, 24, 0, 0, 0, 0
223 };
224 x_offset += BUSY_ROAD_X_OFFSETS[f->figures_on_same_tile_index];
225 y_offset += BUSY_ROAD_Y_OFFSETS[f->figures_on_same_tile_index];
226 }
227 }
228
229 x_offset += 29;
230 y_offset += 15;
231
232 const image *img = f->is_enemy_image ? image_get_enemy(f->image_id) : image_get(f->image_id);
233 *pixel_x += x_offset - img->sprite_offset_x;
234 *pixel_y += y_offset - img->sprite_offset_y;
235 }
236
draw_figure(const figure * f,int x,int y,int highlight)237 static void draw_figure(const figure *f, int x, int y, int highlight)
238 {
239 if (f->cart_image_id) {
240 switch (f->type) {
241 case FIGURE_CART_PUSHER:
242 case FIGURE_WAREHOUSEMAN:
243 case FIGURE_LION_TAMER:
244 case FIGURE_DOCKER:
245 case FIGURE_NATIVE_TRADER:
246 case FIGURE_IMMIGRANT:
247 case FIGURE_EMIGRANT:
248 draw_figure_with_cart(f, x, y);
249 break;
250 case FIGURE_HIPPODROME_HORSES:
251 draw_hippodrome_horse(f, x, y);
252 break;
253 case FIGURE_FORT_STANDARD:
254 draw_fort_standard(f, x, y);
255 break;
256 case FIGURE_MAP_FLAG:
257 draw_map_flag(f, x, y);
258 break;
259 default:
260 image_draw(f->image_id, x, y);
261 break;
262 }
263 } else {
264 if (f->is_enemy_image) {
265 image_draw_enemy(f->image_id, x, y);
266 } else {
267 image_draw(f->image_id, x, y);
268 if (highlight) {
269 image_draw_blend_alpha(f->image_id, x, y, COLOR_MASK_LEGION_HIGHLIGHT);
270 }
271 }
272 }
273 }
274
city_draw_figure(const figure * f,int x,int y,int highlight)275 void city_draw_figure(const figure *f, int x, int y, int highlight)
276 {
277 adjust_pixel_offset(f, &x, &y);
278 draw_figure(f, x, y, highlight);
279 }
280
city_draw_selected_figure(const figure * f,int x,int y,pixel_coordinate * coord)281 void city_draw_selected_figure(const figure *f, int x, int y, pixel_coordinate *coord)
282 {
283 adjust_pixel_offset(f, &x, &y);
284 draw_figure(f, x, y, 0);
285 coord->x = x;
286 coord->y = y;
287 }
288