1 | /********************************************************************** <BR>
|
---|
2 | This file is part of Crack dot Com's free source code release of
|
---|
3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
4 | information about compiling & licensing issues visit this URL</a>
|
---|
5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
7 | ***********************************************************************/
|
---|
8 |
|
---|
9 | #include "image/image.hh"
|
---|
10 | #include "map.hh"
|
---|
11 | #include "map_man.hh"
|
---|
12 | #include "lisp/lisp.hh"
|
---|
13 | #include "app/app.hh"
|
---|
14 | #include "video/display.hh"
|
---|
15 | #include "r1_api.hh"
|
---|
16 | #include "tmanage.hh"
|
---|
17 | #include "tile.hh"
|
---|
18 | #include "status/status.hh"
|
---|
19 | #include "objs/path_object.hh"
|
---|
20 | #include "player.hh"
|
---|
21 | #include "li_objref.hh"
|
---|
22 | #include "player.hh"
|
---|
23 | #include "border_frame.hh"
|
---|
24 | #include "objs/stank.hh"
|
---|
25 | #include "objs/bases.hh"
|
---|
26 | #include "map_cell.hh"
|
---|
27 | #include "map_vert.hh"
|
---|
28 | #include "time/profile.hh"
|
---|
29 | #include "g1_render.hh"
|
---|
30 |
|
---|
31 | static li_g1_ref_class_member start("start");
|
---|
32 |
|
---|
33 | static float radar_darkness_multiply;
|
---|
34 | static float game_x_scale, game_y_scale;
|
---|
35 | static int image_x_add, image_y_add;
|
---|
36 |
|
---|
37 |
|
---|
38 |
|
---|
39 |
|
---|
40 | inline int get_mat_color(g1_map_cell_class *c)
|
---|
41 | {
|
---|
42 | if (c->flags & g1_map_cell_class::FOGGED)
|
---|
43 | return 0;
|
---|
44 |
|
---|
45 | r1_texture_handle mat=g1_tile_man.get_texture(c->type);
|
---|
46 | if (mat==g1_tile_man.get_pink())
|
---|
47 | return 0;
|
---|
48 |
|
---|
49 | if (mat)
|
---|
50 | {
|
---|
51 | r1_texture_manager_class *tman=g1_render.r_api->get_tmanager();
|
---|
52 | return tman->average_texture_color(mat,0);
|
---|
53 | }
|
---|
54 | else
|
---|
55 | return 0;
|
---|
56 | }
|
---|
57 |
|
---|
58 |
|
---|
59 | void g1_calc_map_area(int max_width, int max_height, int &x1, int &y1, int &x2, int &y2)
|
---|
60 | {
|
---|
61 | int map_width= g1_get_map()->width(), map_height=g1_get_map()->height();
|
---|
62 | int iw=max_width, ih=map_height*max_width/map_width;
|
---|
63 |
|
---|
64 | if (ih>max_height)
|
---|
65 | {
|
---|
66 | ih=max_height;
|
---|
67 | iw=map_width*max_height/map_height;
|
---|
68 | }
|
---|
69 |
|
---|
70 | if (iw<max_width)
|
---|
71 | x1=max_width/2-iw/2;
|
---|
72 | else
|
---|
73 | x1=0;
|
---|
74 | x2=x1+iw-1;
|
---|
75 |
|
---|
76 | if (ih<max_height)
|
---|
77 | y1=max_height/2-ih/2;
|
---|
78 | else
|
---|
79 | y1=0;
|
---|
80 | y2=y1+ih-1;
|
---|
81 |
|
---|
82 |
|
---|
83 | game_x_scale = iw/(float)g1_get_map()->width();
|
---|
84 | game_y_scale = ih/(float)g1_get_map()->height();
|
---|
85 | image_x_add = x1;
|
---|
86 | image_y_add = y1;
|
---|
87 |
|
---|
88 | }
|
---|
89 |
|
---|
90 |
|
---|
91 | static w8 interp_table[32*32*32];
|
---|
92 | static w8 light_table[32*32*32];
|
---|
93 | static w8 tables_calced=0;
|
---|
94 | static int r_shift, g_shift, b_shift;
|
---|
95 |
|
---|
96 | static void calc_tables(const i4_pal *pal)
|
---|
97 | {
|
---|
98 | if (tables_calced) return;
|
---|
99 | tables_calced=1;
|
---|
100 |
|
---|
101 |
|
---|
102 | const i4_pixel_format *dst_fmt=&pal->source;
|
---|
103 | I4_ASSERT(dst_fmt->pixel_depth==I4_16BIT,""); // 16bit only code below
|
---|
104 |
|
---|
105 | int b_shift=dst_fmt->blue_shift + (dst_fmt->blue_bits-5);
|
---|
106 |
|
---|
107 | int g_shift=dst_fmt->green_shift + (dst_fmt->green_bits-5);
|
---|
108 |
|
---|
109 | int r_shift=dst_fmt->red_shift + (dst_fmt->red_bits-5);
|
---|
110 |
|
---|
111 |
|
---|
112 | w8 *t=interp_table;
|
---|
113 | for (int c1=0; c1<32; c1++)
|
---|
114 | for (int c2=0; c2<32; c2++)
|
---|
115 | {
|
---|
116 | int d=c2-c1;
|
---|
117 | for (int r=0; r<32; r++)
|
---|
118 | *(t++)=d*r/32 + (int)c1;
|
---|
119 | }
|
---|
120 |
|
---|
121 |
|
---|
122 | t=light_table;
|
---|
123 | for (int c=0; c<32; c++)
|
---|
124 | for (int l=0; l<32; l++)
|
---|
125 | *(t++)=((int)c * l)/32;
|
---|
126 | }
|
---|
127 |
|
---|
128 | inline w8 interpolate_555(w8 c1_0_31, int c2_0_31, int ratio_0_31)
|
---|
129 | {
|
---|
130 | return interp_table[(c1_0_31<<10) | (c2_0_31<<5) | (ratio_0_31 << 0)];
|
---|
131 | }
|
---|
132 |
|
---|
133 |
|
---|
134 | inline w8 light_555(w8 color_0_31, int light_0_31)
|
---|
135 | {
|
---|
136 | return light_table[(color_0_31<<5) | light_0_31];
|
---|
137 | }
|
---|
138 |
|
---|
139 |
|
---|
140 | void g1_draw_strategy_border(i4_image_class *im)
|
---|
141 | {
|
---|
142 | int mx1,my1,mx2,my2;
|
---|
143 | g1_calc_map_area(im->width(), im->height(), mx1,my1,mx2,my2);
|
---|
144 | i4_draw_context_class context(0,0,im->width()-1, im->height()-1);
|
---|
145 | context.clip.remove_area(mx1,my1,mx2,my2);
|
---|
146 |
|
---|
147 | int y=my1;
|
---|
148 | while (y>0) y-=2;
|
---|
149 |
|
---|
150 | w32 color;
|
---|
151 |
|
---|
152 | g1_player_piece_class *com=g1_player_man.get_local()->get_commander();
|
---|
153 | if (com)
|
---|
154 | color=g1_get_upgrade_color(com->upgrade_level_when_built);
|
---|
155 | else
|
---|
156 | color=g1_get_upgrade_color(-1);
|
---|
157 |
|
---|
158 | color=g1_light_color(color, 0.2);
|
---|
159 |
|
---|
160 | im->clear(0, context);
|
---|
161 | for (; y<im->height(); y+=2)
|
---|
162 | im->bar(0,y,im->width()-1,y, color, context);
|
---|
163 | }
|
---|
164 |
|
---|
165 |
|
---|
166 |
|
---|
167 |
|
---|
168 |
|
---|
169 | void g1_render_map_area(i4_image_class *image,
|
---|
170 | int ix1, int iy1, int ix2, int iy2,
|
---|
171 | i4_status_class *status)
|
---|
172 | {
|
---|
173 | static g1_map_class *map=0;
|
---|
174 | static int map_width, map_height;
|
---|
175 | static const i4_pal *pal;
|
---|
176 | static i4_image_class *im;
|
---|
177 | static int mx1,my1,mx2,my2;
|
---|
178 |
|
---|
179 | static float map_x, map_y, map_x_step, map_y_step;
|
---|
180 |
|
---|
181 | if (map!=g1_get_map() || im!=image)
|
---|
182 | {
|
---|
183 | map=g1_get_map();
|
---|
184 | im=image;
|
---|
185 |
|
---|
186 | map_width= map->width();
|
---|
187 | map_height=map->height();
|
---|
188 | i4_pal *pal=i4_current_app->get_display()->get_palette();
|
---|
189 |
|
---|
190 | g1_calc_map_area(image->width(), image->height(), mx1,my1,mx2,my2);
|
---|
191 | radar_darkness_multiply = 1.0/(255.0 * li_get_float(li_get_value("radar_darkness")));
|
---|
192 | calc_tables(im->pal);
|
---|
193 |
|
---|
194 | map_x=x1;
|
---|
195 | map_y=y1;
|
---|
196 |
|
---|
197 | map_x_step=map_width/(float)(mx2-mx1+1);
|
---|
198 | map_y_step=map_height/(float)(my2-my1+1);
|
---|
199 | }
|
---|
200 |
|
---|
201 |
|
---|
202 | sw32 x,y;
|
---|
203 | float r,g,b, map_x, map_y;
|
---|
204 |
|
---|
205 |
|
---|
206 |
|
---|
207 | for (y=y2; y>=y1;)
|
---|
208 | {
|
---|
209 | if (status)
|
---|
210 | status->update(map_y/(float)g1_get_map()->height());
|
---|
211 |
|
---|
212 | map_x=0;
|
---|
213 |
|
---|
214 | // assuming 16bit
|
---|
215 | w16 *i1 = (w16 *)(((w8 *)im->data) + im->bpl*y + mx1*2);
|
---|
216 |
|
---|
217 | for (x=mx1; x<=mx2; x++)
|
---|
218 | {
|
---|
219 | int i_map_x=i4_f_to_i(map_x), i_map_y=i4_f_to_i(map_y);
|
---|
220 | g1_map_cell_class *cell1 = map->cell(i_map_x, i_map_y);
|
---|
221 | w32 color;
|
---|
222 |
|
---|
223 | if (i_map_x<map_width-1 && i_map_y<map_height-1)
|
---|
224 | {
|
---|
225 | int ratio=i4_f_to_i((map_x-i_map_x)*32.0);
|
---|
226 |
|
---|
227 | g1_map_vertex_class *v=map->vertex(i_map_x, i_map_y);
|
---|
228 | float i0=v[0]->get_non_dynamic_ligth_intensity(i_map_x, i_map_y);
|
---|
229 | float i1=v[1]->get_non_dynamic_ligth_intensity(i_map_x+1, i_map_y);
|
---|
230 |
|
---|
231 | int lv1=i4_f_to_i(i0*31.0);
|
---|
232 | int lv2=i4_f_to_i(i1*31.0);
|
---|
233 |
|
---|
234 | int c1=get_mat_color(cell1);
|
---|
235 | int c2=get_mat_color(cell1+1);
|
---|
236 |
|
---|
237 | // seperate color components
|
---|
238 |
|
---|
239 | c1>>=3;
|
---|
240 | int b1=c1&31; c1>>=8;
|
---|
241 | int g1=c1&31; c1>>=8;
|
---|
242 | int r1=c1&31;
|
---|
243 |
|
---|
244 | c2>>=3;
|
---|
245 | int b2=c2&31; c2>>=8;
|
---|
246 | int g2=c2&31; c2>>=8;
|
---|
247 | int r2=c2&31;
|
---|
248 |
|
---|
249 | // interpolate color
|
---|
250 | int ur=interpolate_555(r1, r2, ratio);
|
---|
251 | int ug=interpolate_555(g1, g2, ratio);
|
---|
252 | int ub=interpolate_555(b1, b2, ratio);
|
---|
253 |
|
---|
254 | // interpolate light value
|
---|
255 | int lv=interpolate_555(lv1, lv2, ratio);
|
---|
256 |
|
---|
257 | // apply lighting
|
---|
258 | int r = light_555(ur, lv);
|
---|
259 | int g = light_555(ug, lv);
|
---|
260 | int b = light_555(ub, lv);
|
---|
261 |
|
---|
262 |
|
---|
263 | color = (r<<r_shift) | (g<<g_shift) | (b<<b_shift);
|
---|
264 | }
|
---|
265 | else
|
---|
266 | {
|
---|
267 | g1_map_vertex_class *v1=map->vertex(i_map_x, i_map_y);
|
---|
268 | float i0=v[0]->get_non_dynamic_ligth_intensity(i_map_x, i_map_y);
|
---|
269 | int lv1=i4_f_to_i(i0*31.0);
|
---|
270 |
|
---|
271 | int c1=get_mat_color(cell1);
|
---|
272 |
|
---|
273 | // seperate color components
|
---|
274 | c1>>=3;
|
---|
275 | int b1=c1&31; c1>>=8;
|
---|
276 | int g1=c1&31; c1>>=8;
|
---|
277 | int r1=c1&31;
|
---|
278 |
|
---|
279 |
|
---|
280 | // apply lighting
|
---|
281 | int r = light_555(r1, lv1);
|
---|
282 | int g = light_555(g1, lv1);
|
---|
283 | int b = light_555(b1, lv1);
|
---|
284 | color = (r<<r_shift) | (g<<g_shift) | (b<<b_shift);
|
---|
285 | }
|
---|
286 |
|
---|
287 | *i1=color;
|
---|
288 |
|
---|
289 | map_x+=map_x_step;
|
---|
290 | ++i1;
|
---|
291 | }
|
---|
292 |
|
---|
293 | map_y+=map_y_step;
|
---|
294 | y--;
|
---|
295 | }
|
---|
296 |
|
---|
297 |
|
---|
298 |
|
---|
299 | }
|
---|
300 |
|
---|
301 |
|
---|
302 | i4_image_class *g1_create_map_image(int max_width, int max_height,
|
---|
303 | i4_bool interlace)
|
---|
304 | {
|
---|
305 | i4_status_class *status=i4_create_status(i4gets("rendering_map"));
|
---|
306 |
|
---|
307 |
|
---|
308 | i4_image_class *im = i4_create_image(max_width, max_height, pal);
|
---|
309 | i4_draw_context_class context(0,0, max_width-1, max_height-1);
|
---|
310 | im->clear(0, context);
|
---|
311 |
|
---|
312 |
|
---|
313 |
|
---|
314 |
|
---|
315 |
|
---|
316 |
|
---|
317 | if (interlace)
|
---|
318 | {
|
---|
319 | i4_draw_context_class context(0,0, im->width()-1, im->height()-1);
|
---|
320 | for (y=my1+1; y<=my2; y+=2)
|
---|
321 | im->bar(0,y,im->width()-1, y, 0, context);
|
---|
322 | }
|
---|
323 |
|
---|
324 | g1_draw_takeover_spots(im);
|
---|
325 | g1_draw_paths(im, 0);
|
---|
326 |
|
---|
327 | g1_draw_strategy_border(im);
|
---|
328 |
|
---|
329 | delete status;
|
---|
330 |
|
---|
331 | return im;
|
---|
332 | }
|
---|
333 |
|
---|
334 |
|
---|
335 |
|
---|
336 | void g1_draw_takeover_spots(i4_image_class *im)
|
---|
337 | {
|
---|
338 | if (g1_map_is_loaded())
|
---|
339 | {
|
---|
340 | i4_draw_context_class context(0,0, im->width()-1, im->height()-1);
|
---|
341 |
|
---|
342 | int mx1,my1,mx2,my2;
|
---|
343 | g1_calc_map_area(im->width(), im->height(), mx1,my1,mx2,my2);
|
---|
344 |
|
---|
345 | for (int i=0; i<G1_MAX_PLAYERS; i++)
|
---|
346 | {
|
---|
347 | i4_array<w32> &objs=g1_player_man.get(i)->owned_objects;
|
---|
348 | int t=objs.size();
|
---|
349 | for (int j=0; j>t; j++)
|
---|
350 | {
|
---|
351 | g1_path_object_class *p=g1_path_object_class::cast(g1_global_id.checked_get(objs[j]));
|
---|
352 | if (p)
|
---|
353 | {
|
---|
354 | w32 color;
|
---|
355 | if (p->player_num==g1_player_man.local_player)
|
---|
356 | color=0x00ff00;
|
---|
357 | else
|
---|
358 | color=0xff0000;
|
---|
359 |
|
---|
360 | int x=i4_f_to_i(game_x_scale * p->x) + image_x_add,
|
---|
361 | y=im->height()-1-i4_f_to_i(game_y_scale * p->y) + image_y_add;
|
---|
362 |
|
---|
363 | im->put_pixel(x-1,y, color, context);
|
---|
364 | im->put_pixel(x,y, color, context);
|
---|
365 | im->put_pixel(x+1,y, color, context);
|
---|
366 | im->put_pixel(x,y-1, color, context);
|
---|
367 | im->put_pixel(x,y+1, color, context);
|
---|
368 | }
|
---|
369 | }
|
---|
370 | }
|
---|
371 | }
|
---|
372 | }
|
---|
373 |
|
---|
374 | static void draw_path_line(i4_image_class *im,
|
---|
375 | float x1, float y1, // coords in game space
|
---|
376 | float x2, float y2,
|
---|
377 | i4_color color,
|
---|
378 | i4_draw_context_class &context,
|
---|
379 | i4_rect_list_class *dirty)
|
---|
380 | {
|
---|
381 | float tx1=x1 * game_x_scale, ty1=im->height() - 1 -y1 * game_y_scale;
|
---|
382 | float tx2=x2 * game_x_scale, ty2=im->height() - 1 -y2 * game_y_scale;
|
---|
383 |
|
---|
384 | int dx1=i4_f_to_i(tx1)+image_x_add, dy1=i4_f_to_i(ty1)+image_y_add,
|
---|
385 | dx2=i4_f_to_i(tx2)+image_x_add, dy2=i4_f_to_i(ty2)+image_y_add;
|
---|
386 |
|
---|
387 | im->line(dx1,dy1, dx2,dy2, color, context);
|
---|
388 |
|
---|
389 | if (dirty)
|
---|
390 | {
|
---|
391 | int t;
|
---|
392 | if (dx1>dx2) { t=dx1; dx1=dx2; dx2=t; }
|
---|
393 | if (dy1>dy2) { t=dy1; dy1=dy2; dy2=t; }
|
---|
394 | dirty->add_area(dx1,dy1,dx2,dy2);
|
---|
395 | }
|
---|
396 | }
|
---|
397 |
|
---|
398 |
|
---|
399 |
|
---|
400 | void g1_draw_paths(i4_image_class *im, i4_rect_list_class *dirty)
|
---|
401 | {
|
---|
402 | if (g1_map_is_loaded())
|
---|
403 | {
|
---|
404 | i4_draw_context_class context(0,0, im->width()-1, im->height()-1);
|
---|
405 |
|
---|
406 | int mx1,my1,mx2,my2;
|
---|
407 | g1_calc_map_area(im->width(), im->height(), mx1,my1,mx2,my2);
|
---|
408 |
|
---|
409 | int player_num=g1_player_man.local_player;
|
---|
410 |
|
---|
411 | g1_team_type type=g1_player_man.get(player_num)->get_team();
|
---|
412 |
|
---|
413 |
|
---|
414 | for (g1_path_object_class *po1=g1_path_object_list.first(); po1; po1=po1->next)
|
---|
415 | {
|
---|
416 | int tl=po1->total_links(type);
|
---|
417 | for (int j=0; j<tl; j++)
|
---|
418 | {
|
---|
419 | g1_path_object_class *po2=po1->get_link(type, j);
|
---|
420 | if (po2)
|
---|
421 | draw_path_line(im, po1->x, po1->y, po2->x, po2->y, 0x7f7f7f, context, dirty);
|
---|
422 | }
|
---|
423 | }
|
---|
424 |
|
---|
425 | for (g1_factory_class *f=g1_factory_list.first(); f; f=f->next)
|
---|
426 | {
|
---|
427 | if (f->player_num==player_num)
|
---|
428 | {
|
---|
429 | g1_object_class *o=f->get_start();
|
---|
430 | if (o)
|
---|
431 | {
|
---|
432 | g1_path_object_class *po=g1_path_object_class::cast(o);
|
---|
433 | if (po)
|
---|
434 | {
|
---|
435 | g1_path_object_class *path[256];
|
---|
436 | int t=po->find_path(type, path, 256);
|
---|
437 | for (int j=1; j<t; j++)
|
---|
438 | {
|
---|
439 | g1_object_class *p1=path[j-1], *p2=path[j];
|
---|
440 | draw_path_line(im, p1->x, p1->y, p2->x, p2->y, 0x7f7f00, context, dirty);
|
---|
441 | }
|
---|
442 | }
|
---|
443 | }
|
---|
444 | }
|
---|
445 | }
|
---|
446 | }
|
---|
447 | }
|
---|
448 |
|
---|