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