/**********************************************************************
This file is part of Crack dot Com's free source code release of
Golgotha.
for
information about compiling & licensing issues visit this URL
If that doesn't help, contact Jonathan Clark at
golgotha_source@usa.net (Subject should have "GOLG" in it)
***********************************************************************/
#include "image/image.hh"
#include "map.hh"
#include "map_man.hh"
#include "lisp/lisp.hh"
#include "app/app.hh"
#include "video/display.hh"
#include "r1_api.hh"
#include "tmanage.hh"
#include "tile.hh"
#include "status/status.hh"
#include "objs/path_object.hh"
#include "player.hh"
#include "li_objref.hh"
#include "player.hh"
#include "border_frame.hh"
#include "objs/stank.hh"
#include "objs/bases.hh"
#include "map_cell.hh"
#include "map_vert.hh"
#include "time/profile.hh"
#include "g1_render.hh"
static li_g1_ref_class_member start("start");
static float radar_darkness_multiply;
static float game_x_scale, game_y_scale;
static int image_x_add, image_y_add;
inline int get_mat_color(g1_map_cell_class *c)
{
if (c->flags & g1_map_cell_class::FOGGED)
return 0;
r1_texture_handle mat=g1_tile_man.get_texture(c->type);
if (mat==g1_tile_man.get_pink())
return 0;
if (mat)
{
r1_texture_manager_class *tman=g1_render.r_api->get_tmanager();
return tman->average_texture_color(mat,0);
}
else
return 0;
}
void g1_calc_map_area(int max_width, int max_height, int &x1, int &y1, int &x2, int &y2)
{
int map_width= g1_get_map()->width(), map_height=g1_get_map()->height();
int iw=max_width, ih=map_height*max_width/map_width;
if (ih>max_height)
{
ih=max_height;
iw=map_width*max_height/map_height;
}
if (iwwidth();
game_y_scale = ih/(float)g1_get_map()->height();
image_x_add = x1;
image_y_add = y1;
}
static w8 interp_table[32*32*32];
static w8 light_table[32*32*32];
static w8 tables_calced=0;
static int r_shift, g_shift, b_shift;
static void calc_tables(const i4_pal *pal)
{
if (tables_calced) return;
tables_calced=1;
const i4_pixel_format *dst_fmt=&pal->source;
I4_ASSERT(dst_fmt->pixel_depth==I4_16BIT,""); // 16bit only code below
int b_shift=dst_fmt->blue_shift + (dst_fmt->blue_bits-5);
int g_shift=dst_fmt->green_shift + (dst_fmt->green_bits-5);
int r_shift=dst_fmt->red_shift + (dst_fmt->red_bits-5);
w8 *t=interp_table;
for (int c1=0; c1<32; c1++)
for (int c2=0; c2<32; c2++)
{
int d=c2-c1;
for (int r=0; r<32; r++)
*(t++)=d*r/32 + (int)c1;
}
t=light_table;
for (int c=0; c<32; c++)
for (int l=0; l<32; l++)
*(t++)=((int)c * l)/32;
}
inline w8 interpolate_555(w8 c1_0_31, int c2_0_31, int ratio_0_31)
{
return interp_table[(c1_0_31<<10) | (c2_0_31<<5) | (ratio_0_31 << 0)];
}
inline w8 light_555(w8 color_0_31, int light_0_31)
{
return light_table[(color_0_31<<5) | light_0_31];
}
void g1_draw_strategy_border(i4_image_class *im)
{
int mx1,my1,mx2,my2;
g1_calc_map_area(im->width(), im->height(), mx1,my1,mx2,my2);
i4_draw_context_class context(0,0,im->width()-1, im->height()-1);
context.clip.remove_area(mx1,my1,mx2,my2);
int y=my1;
while (y>0) y-=2;
w32 color;
g1_player_piece_class *com=g1_player_man.get_local()->get_commander();
if (com)
color=g1_get_upgrade_color(com->upgrade_level_when_built);
else
color=g1_get_upgrade_color(-1);
color=g1_light_color(color, 0.2);
im->clear(0, context);
for (; yheight(); y+=2)
im->bar(0,y,im->width()-1,y, color, context);
}
void g1_render_map_area(i4_image_class *image,
int ix1, int iy1, int ix2, int iy2,
i4_status_class *status)
{
static g1_map_class *map=0;
static int map_width, map_height;
static const i4_pal *pal;
static i4_image_class *im;
static int mx1,my1,mx2,my2;
static float map_x, map_y, map_x_step, map_y_step;
if (map!=g1_get_map() || im!=image)
{
map=g1_get_map();
im=image;
map_width= map->width();
map_height=map->height();
i4_pal *pal=i4_current_app->get_display()->get_palette();
g1_calc_map_area(image->width(), image->height(), mx1,my1,mx2,my2);
radar_darkness_multiply = 1.0/(255.0 * li_get_float(li_get_value("radar_darkness")));
calc_tables(im->pal);
map_x=x1;
map_y=y1;
map_x_step=map_width/(float)(mx2-mx1+1);
map_y_step=map_height/(float)(my2-my1+1);
}
sw32 x,y;
float r,g,b, map_x, map_y;
for (y=y2; y>=y1;)
{
if (status)
status->update(map_y/(float)g1_get_map()->height());
map_x=0;
// assuming 16bit
w16 *i1 = (w16 *)(((w8 *)im->data) + im->bpl*y + mx1*2);
for (x=mx1; x<=mx2; x++)
{
int i_map_x=i4_f_to_i(map_x), i_map_y=i4_f_to_i(map_y);
g1_map_cell_class *cell1 = map->cell(i_map_x, i_map_y);
w32 color;
if (i_map_xvertex(i_map_x, i_map_y);
float i0=v[0]->get_non_dynamic_ligth_intensity(i_map_x, i_map_y);
float i1=v[1]->get_non_dynamic_ligth_intensity(i_map_x+1, i_map_y);
int lv1=i4_f_to_i(i0*31.0);
int lv2=i4_f_to_i(i1*31.0);
int c1=get_mat_color(cell1);
int c2=get_mat_color(cell1+1);
// seperate color components
c1>>=3;
int b1=c1&31; c1>>=8;
int g1=c1&31; c1>>=8;
int r1=c1&31;
c2>>=3;
int b2=c2&31; c2>>=8;
int g2=c2&31; c2>>=8;
int r2=c2&31;
// interpolate color
int ur=interpolate_555(r1, r2, ratio);
int ug=interpolate_555(g1, g2, ratio);
int ub=interpolate_555(b1, b2, ratio);
// interpolate light value
int lv=interpolate_555(lv1, lv2, ratio);
// apply lighting
int r = light_555(ur, lv);
int g = light_555(ug, lv);
int b = light_555(ub, lv);
color = (r<vertex(i_map_x, i_map_y);
float i0=v[0]->get_non_dynamic_ligth_intensity(i_map_x, i_map_y);
int lv1=i4_f_to_i(i0*31.0);
int c1=get_mat_color(cell1);
// seperate color components
c1>>=3;
int b1=c1&31; c1>>=8;
int g1=c1&31; c1>>=8;
int r1=c1&31;
// apply lighting
int r = light_555(r1, lv1);
int g = light_555(g1, lv1);
int b = light_555(b1, lv1);
color = (r<clear(0, context);
if (interlace)
{
i4_draw_context_class context(0,0, im->width()-1, im->height()-1);
for (y=my1+1; y<=my2; y+=2)
im->bar(0,y,im->width()-1, y, 0, context);
}
g1_draw_takeover_spots(im);
g1_draw_paths(im, 0);
g1_draw_strategy_border(im);
delete status;
return im;
}
void g1_draw_takeover_spots(i4_image_class *im)
{
if (g1_map_is_loaded())
{
i4_draw_context_class context(0,0, im->width()-1, im->height()-1);
int mx1,my1,mx2,my2;
g1_calc_map_area(im->width(), im->height(), mx1,my1,mx2,my2);
for (int i=0; i &objs=g1_player_man.get(i)->owned_objects;
int t=objs.size();
for (int j=0; j>t; j++)
{
g1_path_object_class *p=g1_path_object_class::cast(g1_global_id.checked_get(objs[j]));
if (p)
{
w32 color;
if (p->player_num==g1_player_man.local_player)
color=0x00ff00;
else
color=0xff0000;
int x=i4_f_to_i(game_x_scale * p->x) + image_x_add,
y=im->height()-1-i4_f_to_i(game_y_scale * p->y) + image_y_add;
im->put_pixel(x-1,y, color, context);
im->put_pixel(x,y, color, context);
im->put_pixel(x+1,y, color, context);
im->put_pixel(x,y-1, color, context);
im->put_pixel(x,y+1, color, context);
}
}
}
}
}
static void draw_path_line(i4_image_class *im,
float x1, float y1, // coords in game space
float x2, float y2,
i4_color color,
i4_draw_context_class &context,
i4_rect_list_class *dirty)
{
float tx1=x1 * game_x_scale, ty1=im->height() - 1 -y1 * game_y_scale;
float tx2=x2 * game_x_scale, ty2=im->height() - 1 -y2 * game_y_scale;
int dx1=i4_f_to_i(tx1)+image_x_add, dy1=i4_f_to_i(ty1)+image_y_add,
dx2=i4_f_to_i(tx2)+image_x_add, dy2=i4_f_to_i(ty2)+image_y_add;
im->line(dx1,dy1, dx2,dy2, color, context);
if (dirty)
{
int t;
if (dx1>dx2) { t=dx1; dx1=dx2; dx2=t; }
if (dy1>dy2) { t=dy1; dy1=dy2; dy2=t; }
dirty->add_area(dx1,dy1,dx2,dy2);
}
}
void g1_draw_paths(i4_image_class *im, i4_rect_list_class *dirty)
{
if (g1_map_is_loaded())
{
i4_draw_context_class context(0,0, im->width()-1, im->height()-1);
int mx1,my1,mx2,my2;
g1_calc_map_area(im->width(), im->height(), mx1,my1,mx2,my2);
int player_num=g1_player_man.local_player;
g1_team_type type=g1_player_man.get(player_num)->get_team();
for (g1_path_object_class *po1=g1_path_object_list.first(); po1; po1=po1->next)
{
int tl=po1->total_links(type);
for (int j=0; jget_link(type, j);
if (po2)
draw_path_line(im, po1->x, po1->y, po2->x, po2->y, 0x7f7f7f, context, dirty);
}
}
for (g1_factory_class *f=g1_factory_list.first(); f; f=f->next)
{
if (f->player_num==player_num)
{
g1_object_class *o=f->get_start();
if (o)
{
g1_path_object_class *po=g1_path_object_class::cast(o);
if (po)
{
g1_path_object_class *path[256];
int t=po->find_path(type, path, 256);
for (int j=1; jx, p1->y, p2->x, p2->y, 0x7f7f00, context, dirty);
}
}
}
}
}
}
}