/**********************************************************************
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 "map_man.hh" #include "map_cell.hh" #include "g1_object.hh" #include "tile.hh" #include "map.hh" #include "compress/rle.hh" #include "loaders/dir_save.hh" #include "loaders/dir_load.hh" #include "saver_id.hh" #include "map_vert.hh" g1_object_chain_class *g1_map_cell_class::get_solid_list() { if (!object_list || !object_list->object->get_flag(g1_object_class::BLOCKING)) return 0; else return object_list; } g1_object_chain_class *g1_map_cell_class::get_non_solid_list() { g1_object_chain_class *p=object_list; while (p && p->object->get_flag(g1_object_class::BLOCKING)) p=p->next; return p; } void g1_map_cell_class::add_object(g1_object_chain_class &o) { if (!object_list || o.object->get_flag(g1_object_class::BLOCKING)) // add solids to front of list { o.next=object_list; object_list=&o; } else { // add non solids after all solids g1_object_chain_class *last=object_list, *p=object_list->next; while (p && p->object->get_flag(g1_object_class::BLOCKING)) { last=p; p=p->next; } o.next=last->next; last->next=&o; } } i4_bool g1_map_cell_class::remove_object(g1_object_chain_class &o) { if (&o==object_list) { object_list=o.next; return i4_T; } else { g1_object_chain_class *c=object_list, *last; while (c && c!=&o) { last=c; c=c->next; } if (!c) { i4_warning("map_cell::remove_object, object not in cell"); return i4_F; } last->next=o.next; return i4_T; } } void g1_map_cell_class::init(w16 _type, g1_rotation_type rot, i4_bool mirrored) { object_list=0; type=_type; flags=FOGGED; top_left_normal=0x8000; bottom_right_normal=0x8000; g1_tile_man.get(_type)->apply_to_cell(*this); set_rotation(rot); if (mirrored) flags|=MIRRORED; } void g1_map_cell_class::recalc_top_left(int cx, int cy) { int mw=g1_get_map()->width(), mh=g1_get_map()->height(); I4_ASSERT(cx<=mw && cy<=mh, "recalc normal : vert out of range"); if (cx==mw-1 || cy==mh-1) top_left_normal=(31) | (15<<5) | (15<<10); // normal = 0,0,1 else { g1_map_vertex_class *v=g1_get_map()->vertex(cx,cy); float h0=v->get_height(), h2=v[mw+1].get_height(), h3=v[mw+1+1].get_height(); i4_3d_vector v1(1, 0, h3-h2), v2(0, -1, h0-h2); i4_3d_vector normal; normal.cross(v2,v1); normal.normalize(); top_left_normal=g1_normal_to_16(normal); } } void g1_map_cell_class::recalc_bottom_right(int cx, int cy) { int mw=g1_get_map()->width(), mh=g1_get_map()->height(); if (cx>=mw || cy>=mh) bottom_right_normal=(31) | (15<<5) | (15<<10); // normal = 0,0,1 else { g1_map_vertex_class *v=g1_get_map()->vertex(cx,cy); float h0=v->get_height(), h1=v[1].get_height(), h3=v[mw+1+1].get_height(); i4_3d_vector v1(-1, 0, h0-h1), v2(0, 1, h3-h1); i4_3d_vector normal; normal.cross(v2,v1); normal.normalize(); bottom_right_normal=g1_normal_to_16(normal); } } void g1_save_map_cells(g1_map_cell_class *list, int lsize, i4_saver_class *fp) { int i,j; i4_rle_classfp16(fp); fp->mark_section("golgotha cell type v1"); for (i=0; i mark_section("golgotha cell flags v2"); for (i=0; i mark_section("golgotha cell normals v1"); for (i=0; i fp16(fp); ////////////////////////////////////////////////////////// // support for old formats if (!fp->goto_section("golgotha cell type v1")) { g1_get_map()->mark_for_recalc(G1_RECALC_STATIC_LIGHT); if (fp->goto_section(OLD_G1_SECTION_CELL_V6)) { for (i=0; i goto_section(OLD_G1_SECTION_CELL_V5)) { for (i=0; i goto_section(OLD_G1_SECTION_CELL_V4)) { for (i=0; i goto_section(OLD_G1_SECTION_CELL_V3)) { for (i=0; i goto_section(OLD_G1_SECTION_CELL_V2)) { for (i=0; i goto_section("golgotha cell flags v2")) { for (i=0; i goto_section("golgotha cell flags v1")) { for (i=0; i apply_to_cell(list[i]); if (fp->goto_section("golgotha cell normals v1")) { for (i=0; i read_16()]; flags=fp->read_8(); fp->read_8(); fp->read_16(); // nearest node gone top_left_normal=0x8000; bottom_right_normal=0x8000; } void g1_map_cell_class::load_v3(i4_file_class *fp, w16 *tile_remap) { object_list=0; type=tile_remap[fp->read_16()]; flags=fp->read_16(); fp->read_8(); // height not used anymore fp->read_16(); // nearest node gone top_left_normal=0x8000; bottom_right_normal=0x8000; } void g1_map_cell_class::load_v4(i4_file_class *fp, w16 *tile_remap) { object_list=0; type=tile_remap[fp->read_16()]; flags=fp->read_16(); fp->read_16(); // nearest node gone if (type==0) flags |= IS_GROUND; top_left_normal=0x8000; bottom_right_normal=0x8000; } void g1_map_cell_class::load_v5(i4_file_class *fp, w16 *tile_remap) { object_list=0; type = tile_remap[fp->read_16()]; fp->read_8(); flags=fp->read_16(); fp->read_16(); // nearest_node gone if (type==0) flags |= IS_GROUND; top_left_normal=0x8000; bottom_right_normal=0x8000; } void g1_map_cell_class::load_v6(i4_file_class *fp, w16 *tile_remap) { object_list=0; type = tile_remap[fp->read_16()]; fp->read_8(); w32 blah = fp->read_32(); // height info not used anymoe if (blah) { fp->read_8(); fp->read_16(); fp->read_float(); fp->read_float(); } flags=fp->read_16(); fp->read_16(); // nearest_node gone if (type==0) flags |= IS_GROUND; top_left_normal=0x8000; bottom_right_normal=0x8000; } void g1_map_cell_class::unfog(int x, int y) { flags&=~FOGGED; g1_map_vertex_class *v=g1_verts+x+y*(g1_map_width+1); v->set_flag(g1_map_vertex_class::FOGGED,0); v++; v->set_flag(g1_map_vertex_class::FOGGED,0); v+=g1_map_width; v->set_flag(g1_map_vertex_class::FOGGED,0); v++; v->set_flag(g1_map_vertex_class::FOGGED,0); }