Index: dataobj/tabfile.cc =================================================================== --- dataobj/tabfile.cc (Revision 8938) +++ dataobj/tabfile.cc (Arbeitskopie) @@ -18,6 +18,7 @@ #include "../simdebug.h" #include "../descriptor/image.h" #include "koord.h" +#include "koord3d.h" #include "tabfile.h" @@ -125,6 +126,34 @@ return ret; } +const koord3d &tabfileobj_t::get_koord3d( const char *key, koord3d def ) +{ + static koord3d ret; + ret = def; + + const char *value = get_string(key,NULL); + + if(!value) { + return ret; + } + // 2. Determine value + const char *tmp_y; + for(tmp_y = value; *tmp_y != ','; tmp_y++) { + if(!*tmp_y) { + return ret; + } + } + const char *tmp_z; + for(tmp_z = tmp_y+1; *tmp_z != ','; tmp_z++) { + if(!*tmp_z) { + return ret; + } + } + + ret = koord3d( atoi( value ), atoi( tmp_y + 1 ), atoi( tmp_z + 1 ) ); + return ret; +} + PIXVAL tabfileobj_t::get_color(const char *key, PIXVAL def, uint32 *color_rgb) { const char *value = get_string(key,NULL); Index: dataobj/tabfile.h =================================================================== --- dataobj/tabfile.h (Revision 8938) +++ dataobj/tabfile.h (Arbeitskopie) @@ -15,6 +15,7 @@ class tabfileobj_t; class koord; +class koord3d; class scr_coord; class scr_size; @@ -180,6 +181,9 @@ const koord &get_koord(const char *key, koord def); const scr_size &get_scr_size(const char *key, scr_size def); + // same for koord3d + const koord3d &get_koord3d( const char *key, koord3d def ); + /** * Get a color in the system format when given a #AABBCC * and optionally set RGB888 for a chosen var with color_rgb Index: descriptor/factory_desc.h =================================================================== --- descriptor/factory_desc.h (Revision 8938) +++ descriptor/factory_desc.h (Arbeitskopie) @@ -12,6 +12,7 @@ #include "skin_desc.h" #include "goods_desc.h" #include "../dataobj/koord.h" +#include "../dataobj/koord3d.h" #include "../tpl/weighted_vector_tpl.h" class checksum_t; @@ -100,6 +101,9 @@ koord pos_off; koord xy_off; + vector_tplrotation_position; + vector_tplrotation_xy; + public: const char *get_name() const { return get_images()->get_name(); } const char *get_copyright() const { return get_images()->get_copyright(); } @@ -106,23 +110,33 @@ skin_desc_t const* get_images() const { return get_child(0); } // get the tile with the smoke - koord get_pos_off( koord size, uint8 rotation) const { - switch( rotation%4 ) { - case 1: return koord( size.y-pos_off.y, pos_off.x ); - case 2: return koord( size.x-pos_off.x, size.y-pos_off.y ); - case 3: return koord( pos_off.y, size.x-pos_off.x ); + koord3d get_pos_off( koord size, uint8 rotation ) const { + if( rotation_position.empty() ) { + switch( rotation % 4 ) { + case 1: return koord3d( size.y - pos_off.y, pos_off.x, 0 ); + case 2: return koord3d( size.x - pos_off.x, size.y - pos_off.y, 0 ); + case 3: return koord3d( pos_off.y, size.x - pos_off.x, 0 ); + } + return koord3d(pos_off,0); } - return pos_off; + else { + return rotation_position[ rotation % rotation_position.get_count() ]; + } } // offset in pixel (depends on OBJECT_OFFSET_STEPS==16) koord get_xy_off(uint8 rotation) const { - switch( rotation%4 ) { - case 1: return koord( 0, xy_off.y+xy_off.x/2 ); - case 2: return koord( -xy_off.x, xy_off.y ); - case 3: return koord( 0, xy_off.y-xy_off.x/2 ); + if( rotation_xy.empty() ) { + switch( rotation % 4 ) { + case 1: return koord( 0, xy_off.y + xy_off.x / 2 ); + case 2: return koord( -xy_off.x, xy_off.y ); + case 3: return koord( 0, xy_off.y - xy_off.x / 2 ); + } + return xy_off; } - return xy_off; + else { + return rotation_xy[ rotation % rotation_xy.get_count() ]; + } } }; Index: descriptor/reader/factory_reader.cc =================================================================== --- descriptor/reader/factory_reader.cc (Revision 8938) +++ descriptor/reader/factory_reader.cc (Arbeitskopie) @@ -155,26 +155,47 @@ -obj_desc_t *factory_smoke_reader_t::read_node(FILE *fp, obj_node_info_t &node) +obj_desc_t *factory_smoke_reader_t::read_node( FILE *fp, obj_node_info_t &node ) { - ALLOCA(char, desc_buf, node.size); + ALLOCA( char, desc_buf, node.size ); smoke_desc_t *desc = new smoke_desc_t(); // Hajo: Read data - fread(desc_buf, node.size, 1, fp); + fread( desc_buf, node.size, 1, fp ); char * p = desc_buf; - sint16 x = decode_sint16(p); - sint16 y = decode_sint16(p); - desc->pos_off = koord( x, y ); + // old nodes must have offsets below 128 or they would overflow + const sint16 v = decode_uint16( p ); + int version = abs( v ) < 1024 ? 0 : v - 2048; - x = decode_sint16(p); - y = decode_sint16(p); + if( version == 0 ) { + sint16 y = decode_sint16( p ); + desc->pos_off = koord( v, y ); - desc->xy_off = koord( x, y ); - /*smoke speed*/ decode_sint16(p); + sint16 x = decode_sint16( p ); + y = decode_sint16( p ); + desc->xy_off = koord( x, y ); + /*smoke speed*/ decode_sint16( p ); + } + else if( version == 1 ) { + const sint8 rotations = decode_sint8( p ); + for( int i = 0; i < rotations; i++ ) { + koord3d k; + k.x = decode_sint16( p ); + k.y = decode_sint16( p ); + k.z = decode_sint8( p ); + desc->rotation_position.append( k ); + koord offset; + offset.x = decode_sint16( p ); + offset.y = decode_sint16( p ); + desc->rotation_xy.append( offset ); + } + } + else { + dbg->fatal( "factory_smoke_reader_t::read_node", "Unknown version %i", version ); + } DBG_DEBUG("factory_smoke_reader_t::read_node()","(size %i)",node.size); return desc; Index: descriptor/writer/factory_writer.cc =================================================================== --- descriptor/writer/factory_writer.cc (Revision 8938) +++ descriptor/writer/factory_writer.cc (Arbeitskopie) @@ -2,6 +2,9 @@ #include #include "../../utils/simstring.h" #include "../../dataobj/tabfile.h" +#include "../../dataobj/koord.h" +#include "../../dataobj/koord3d.h" +#include "../../tpl/vector_tpl.h" #include "obj_node.h" #include "../skin_desc.h" #include "../factory_desc.h" @@ -91,20 +94,61 @@ void factory_smoke_writer_t::write_obj(FILE* outfp, obj_node_t& parent, tabfileobj_t& obj) { - obj_node_t node(this, 10, &parent); + // first, find out what kind of format (old or new) + char smoketile[] = "smoketile[0]"; + if( !obj.get( smoketile ) ) { + obj_node_t node( this, 10, &parent ); - xref_writer_t::instance()->write_obj(outfp, node, obj_smoke, obj.get("smoke"), true); - koord const pos_off = obj.get_koord("smoketile", koord(0, 0)); - koord const xy_off = obj.get_koord("smokeoffset", koord(0, 0)); - sint16 const smokespeed = 0; /* was obj.get_int("smokespeed", 0); */ + xref_writer_t::instance()->write_obj( outfp, node, obj_smoke, obj.get( "smoke" ), true ); + koord const pos_off = obj.get_koord( "smoketile", koord( 0, 0 ) ); + koord const xy_off = obj.get_koord( "smokeoffset", koord( 0, 0 ) ); + sint16 const smokespeed = 0; /* was obj.get_int("smokespeed", 0); */ - node.write_sint16(outfp, pos_off.x, 0); - node.write_sint16(outfp, pos_off.y, 2); - node.write_sint16(outfp, xy_off.x, 4); - node.write_sint16(outfp, xy_off.y, 6); - node.write_sint16(outfp, smokespeed, 8); + node.write_sint16( outfp, pos_off.x, 0 ); + node.write_sint16( outfp, pos_off.y, 2 ); + node.write_sint16( outfp, xy_off.x, 4 ); + node.write_sint16( outfp, xy_off.y, 6 ); + node.write_sint16( outfp, smokespeed, 8 ); - node.write(outfp); + node.write( outfp ); + } + else { + // new format, could have definition for each rotation + vector_tpl st; + for( int i = 0; i < 4; i++ ) { + smoketile[ 11 ] = '0' + i; + if( obj.get( smoketile ) ) { + st.append( obj.get_koord3d( smoketile, koord3d( 0, 0, 0 ) ) ); + } + else { + break; + } + } + if( st.get_count() == 3 ) { + dbg->fatal( "factory_smoke_writer_t::write_obj", "Smoke can only hav 1, 2, or 4 rotations!" ); + } + const sint8 rotations = st.get_count(); + char smokeoffset[ 15 ] = "smokeoffset[0]"; + vector_tpl so; + for( int i = 0; i < rotations; i++ ) { + smokeoffset[ 13 ] = '0' + i; + so.append( obj.get_koord( smokeoffset, koord( 0, 0 ) ) ); + } + const sint16 version = 2048 + 1; + + // now we know the size + obj_node_t node( this, 3 + (4 + 5)*rotations, &parent ); + node.write_sint16( outfp, version, 0 ); + node.write_sint8( outfp, rotations, 2 ); + for( int i = 0; i < rotations; i++ ) { + node.write_sint16( outfp, st[ i ].x, 5 + 9*i ); + node.write_sint16( outfp, st[ i ].y, 5 + 9*i + 2 ); + node.write_sint8 ( outfp, st[ i ].z, 5 + 9*i + 4 ); + node.write_sint16( outfp, so[ i ].x, 5 + 9*i + 5 ); + node.write_sint16( outfp, so[ i ].y, 5 + 9*i + 7 ); + } + node.write( outfp ); + } } Index: obj/wolke.cc =================================================================== --- obj/wolke.cc (Revision 8938) +++ obj/wolke.cc (Arbeitskopie) @@ -17,6 +17,7 @@ #include "../tpl/vector_tpl.h" +#define MAX_TIME (2499) vector_tplwolke_t::all_clouds(0); @@ -34,13 +35,13 @@ -wolke_t::wolke_t(koord3d pos, sint8 x_off, sint8 y_off, const skin_desc_t* desc ) : +wolke_t::wolke_t(koord3d pos, sint8 x_off, sint16 y_off, const skin_desc_t* desc ) : obj_no_info_t(pos) { cloud_nr = all_clouds.index_of(desc); - base_y_off = clamp( (sint16)y_off - 8, -128, 127 ); + base_y_off = y_off - 8; set_xoff( x_off ); - set_yoff( base_y_off ); + set_yoff( -8 ); insta_zeit = 0; } @@ -49,7 +50,7 @@ wolke_t::~wolke_t() { mark_image_dirty( get_image(), 0 ); - if( insta_zeit != 2499 ) { + if( insta_zeit != MAX_TIME ) { welt->sync_way_eyecandy.remove( this ); } } @@ -62,7 +63,7 @@ } -image_id wolke_t::get_image() const +image_id wolke_t::get_front_image() const { const skin_desc_t *desc = all_clouds[cloud_nr]; return desc->get_image_id( (insta_zeit*desc->get_count())/2500 ); @@ -94,29 +95,27 @@ sync_result wolke_t::sync_step(uint32 delta_t) { - const image_id old_img = get_image(); - + // we query the image twice, since it may have changed (there are sure more efficient ways for that ... + const image_id old_img = get_front_image(); insta_zeit += delta_t; - if( insta_zeit >= 2499 ) { + if( insta_zeit >= MAX_TIME ) { // delete wolke ... - insta_zeit = 2499; + insta_zeit = MAX_TIME; return SYNC_DELETE; } - const image_id new_img = get_image(); + const image_id new_img = get_front_image(); // move cloud up - const sint8 new_yoff = base_y_off - ((insta_zeit * OBJECT_OFFSET_STEPS) >> 12); - if( new_yoff != get_yoff() || new_img != old_img ) { + const sint8 new_yoff = base_y_off - ((insta_zeit * OBJECT_OFFSET_STEPS) >> 12) - 8; + if( new_img != old_img ) { // move/change cloud ... (happens much more often than image change => image change will be always done when drawing) if( !get_flag( obj_t::dirty ) ) { set_flag( obj_t::dirty ); - mark_image_dirty( old_img, 0 ); - if( new_img != old_img ) { - mark_image_dirty( new_img, 0 ); - } + mark_image_dirty( old_img, new_yoff ); } - set_yoff( new_yoff ); } + set_flag( obj_t::dirty ); + return SYNC_OK; } @@ -126,12 +125,12 @@ { // restore pure yoff set_yoff( base_y_off + 8 ); + // most basic: rotate coordinate obj_t::rotate90(); - // .. and recalc smoke offsets - base_y_off = clamp( (sint16)get_yoff()-8, -128, 127 ); - set_yoff( base_y_off - ((insta_zeit*OBJECT_OFFSET_STEPS) >> 12) ); + insta_zeit = MAX_TIME+1; // delete next step, since offsets could overflown and we may be anyway on the wrong tile } + /***************************** just for compatibility, the old raucher and smoke clouds *********************************/ raucher_t::raucher_t(loadsave_t *file) : obj_t() Index: obj/wolke.h =================================================================== --- obj/wolke.h (Revision 8938) +++ obj/wolke.h (Arbeitskopie) @@ -18,7 +18,7 @@ static vector_tplall_clouds; uint16 insta_zeit; // clouds vanish when insta_zeit>2500 => maximum 5 images ... - sint8 base_y_off; + sint16 base_y_off; // since sint8 may overflow wiht larger pak sizes uint8 cloud_nr; public: @@ -25,7 +25,7 @@ static bool register_desc(const skin_desc_t *desc); wolke_t(loadsave_t *file); - wolke_t(koord3d pos, sint8 xoff, sint8 yoff, const skin_desc_t *cloud ); + wolke_t(koord3d pos, sint8 xoff, sint16 yoff, const skin_desc_t *cloud ); ~wolke_t(); sync_result sync_step(uint32 delta_t) OVERRIDE; @@ -33,11 +33,23 @@ const char* get_name() const OVERRIDE { return "Wolke"; } typ get_typ() const OVERRIDE { return sync_wolke; } - image_id get_image() const OVERRIDE; + image_id get_image() const OVERRIDE { return IMG_EMPTY; } + image_id get_front_image() const OVERRIDE; + void rdwr(loadsave_t *file) OVERRIDE; void rotate90() OVERRIDE; + + /** + * Draw foreground image + * (everything that is in front of vehicles) + */ +#ifdef MULTI_THREAD + virtual void display_after( int xpos, int ypos, const sint8 clip_num ) const { obj_t::display_after( xpos, ypos + base_y_off - ((insta_zeit * OBJECT_OFFSET_STEPS) >> 12), clip_num ); } +#else + virtual void display_after( int xpos, int ypos, bool is_global ) const { obj_t::display_after( xpos, ypos + base_y_off - ((insta_zeit * OBJECT_OFFSET_STEPS) >> 12), is_global ); } +#endif }; Index: simfab.cc =================================================================== --- simfab.cc (Revision 8938) +++ simfab.cc (Arbeitskopie) @@ -1542,8 +1542,8 @@ if(rada) { const koord size = desc->get_building()->get_size(0)-koord(1,1); const uint8 rot = (4-rotate)%desc->get_building()->get_all_layouts(); - koord ro = rada->get_pos_off(size,rot); - grund_t *gr = welt->lookup_kartenboden(pos_origin.get_2d()+ro); + koord3d ro = rada->get_pos_off(size,rot); + grund_t *gr = welt->lookup_kartenboden(pos_origin.get_2d()+ro.get_2d()); // to get same random order on different compilers const sint8 offsetx = ((rada->get_xy_off(rot).x+sim_async_rand(7)-3)*OBJECT_OFFSET_STEPS)/16; const sint8 offsety = ((rada->get_xy_off(rot).y+sim_async_rand(7)-3)*OBJECT_OFFSET_STEPS)/16; Index: simobj.cc =================================================================== --- simobj.cc (Revision 8938) +++ simobj.cc (Arbeitskopie) @@ -257,11 +257,9 @@ { // most basic: rotate coordinate pos.rotate90( welt->get_size().y-1 ); - if(xoff!=0) { - sint8 new_dx = -2*yoff; - yoff = xoff/2; - xoff = new_dx; - } + sint8 new_dx = -2*yoff; + yoff = xoff/2; + xoff = new_dx; }