1 /*
2 * Copyright (c) 1997 - 2001 Hansj�rg Malthaner
3 *
4 * This file is part of the Simutrans project under the artistic licence.
5 * (see licence.txt)
6 */
7
8 #include <stdio.h>
9
10 #include "../simworld.h"
11 #include "../simobj.h"
12 #include "../player/simplay.h"
13 #include "../boden/grund.h"
14 #include "../display/simimg.h"
15 #include "../bauer/tunnelbauer.h"
16
17 #include "../dataobj/loadsave.h"
18 #include "../dataobj/translator.h"
19
20 #include "../descriptor/tunnel_desc.h"
21
22 #include "leitung2.h"
23 #include "../bauer/wegbauer.h"
24
25 #include "tunnel.h"
26
27 #ifdef MULTI_THREAD
28 #include "../utils/simthread.h"
29 static pthread_mutex_t tunnel_calc_image_mutex;
30 static recursive_mutex_maker_t tunnel_cim_maker(tunnel_calc_image_mutex);
31 #endif
32
33
tunnel_t(loadsave_t * const file)34 tunnel_t::tunnel_t(loadsave_t* const file) : obj_no_info_t()
35 {
36 desc = 0;
37 rdwr(file);
38 image = foreground_image = IMG_EMPTY;
39 broad_type = 0;
40 }
41
42
tunnel_t(koord3d pos,player_t * player,const tunnel_desc_t * desc)43 tunnel_t::tunnel_t(koord3d pos, player_t *player, const tunnel_desc_t *desc) :
44 obj_no_info_t(pos)
45 {
46 assert(desc);
47 this->desc = desc;
48 set_owner( player );
49 image = foreground_image = IMG_EMPTY;
50 broad_type = 0;
51 }
52
53
get_waytype() const54 waytype_t tunnel_t::get_waytype() const
55 {
56 return desc ? desc->get_waytype() : invalid_wt;
57 }
58
59
calc_image()60 void tunnel_t::calc_image()
61 {
62 #ifdef MULTI_THREAD
63 pthread_mutex_lock( &tunnel_calc_image_mutex );
64 #endif
65 const grund_t *gr = welt->lookup(get_pos());
66 if( gr->ist_karten_boden() && desc ) {
67 slope_t::type hang = gr->get_grund_hang();
68
69 broad_type = 0;
70 if( desc->has_broad_portals() ) {
71 ribi_t::ribi dir = ribi_t::rotate90( ribi_type( hang ) );
72 if( dir==0 ) {
73 dbg->error( "tunnel_t::calc_image()", "pos=%s, dir=%i, hang=%i", get_pos().get_str(), dir, hang );
74 }
75 else {
76 const grund_t *gr_l = welt->lookup(get_pos() + dir);
77 tunnel_t* tunnel_l = gr_l ? gr_l->find<tunnel_t>() : NULL;
78 if( tunnel_l && tunnel_l->get_desc() == desc && gr_l->get_grund_hang() == hang ) {
79 broad_type += 1;
80 if( !(tunnel_l->get_broad_type() & 2) ) {
81 tunnel_l->calc_image();
82 }
83 }
84 const grund_t *gr_r = welt->lookup(get_pos() - dir);
85 tunnel_t* tunnel_r = gr_r ? gr_r->find<tunnel_t>() : NULL;
86 if( tunnel_r && tunnel_r->get_desc() == desc && gr_r->get_grund_hang() == hang ) {
87 broad_type += 2;
88 if( !(tunnel_r->get_broad_type() & 1) ) {
89 tunnel_r->calc_image();
90 }
91 }
92 }
93 }
94
95 set_image( desc->get_background_id( hang, get_pos().z >= welt->get_snowline() || welt->get_climate( get_pos().get_2d() ) == arctic_climate, broad_type ) );
96 set_foreground_image( desc->get_foreground_id( hang, get_pos().z >= welt->get_snowline() || welt->get_climate( get_pos().get_2d() ) == arctic_climate, broad_type ) );
97 }
98 else {
99 set_image( IMG_EMPTY );
100 set_foreground_image( IMG_EMPTY );
101 }
102 #ifdef MULTI_THREAD
103 pthread_mutex_unlock( &tunnel_calc_image_mutex );
104 #endif
105 }
106
107
108
rdwr(loadsave_t * file)109 void tunnel_t::rdwr(loadsave_t *file)
110 {
111 xml_tag_t t( file, "tunnel_t" );
112 obj_t::rdwr(file);
113 if( file->is_version_atleast(99, 1) ) {
114 char buf[256];
115 if( file->is_loading() ) {
116 file->rdwr_str(buf, lengthof(buf));
117 desc = tunnel_builder_t::get_desc(buf);
118 if( desc==NULL ) {
119 desc = tunnel_builder_t::get_desc(translator::compatibility_name(buf));
120 }
121 if( desc==NULL ) {
122 welt->add_missing_paks( buf, karte_t::MISSING_WAY );
123 }
124 }
125 else {
126 strcpy( buf, desc->get_name() );
127 file->rdwr_str(buf,0);
128 }
129 }
130 }
131
132
finish_rd()133 void tunnel_t::finish_rd()
134 {
135 const grund_t *gr = welt->lookup(get_pos());
136 player_t *player=get_owner();
137
138 if(desc==NULL) {
139 // find a matching desc
140 if (gr->get_weg_nr(0)==NULL) {
141 // no way? underground powerline
142 if (gr->get_leitung()) {
143 desc = tunnel_builder_t::get_tunnel_desc(powerline_wt, 1, 0);
144 }
145 // no tunnel -> use dummy road tunnel
146 if (desc==NULL) {
147 desc = tunnel_builder_t::get_tunnel_desc(road_wt, 1, 0);
148 }
149 }
150 else {
151 desc = tunnel_builder_t::get_tunnel_desc(gr->get_weg_nr(0)->get_desc()->get_wtyp(), 450, 0);
152 if( desc == NULL ) {
153 dbg->error( "tunnel_t::finish_rd()", "Completely unknown tunnel for this waytype: Lets use a rail tunnel!" );
154 desc = tunnel_builder_t::get_tunnel_desc(track_wt, 1, 0);
155 }
156 }
157 }
158
159 if(player) {
160 // change maintenance
161 weg_t *weg = gr->get_weg(desc->get_waytype());
162 if(weg) {
163 weg->set_max_speed(desc->get_topspeed());
164 player_t::add_maintenance( player, -weg->get_desc()->get_maintenance(), weg->get_desc()->get_finance_waytype());
165 }
166 leitung_t *lt = gr->get_leitung();
167 if(lt) {
168 player_t::add_maintenance( player, -lt->get_desc()->get_maintenance(), powerline_wt );
169 }
170 player_t::add_maintenance( player, desc->get_maintenance(), desc->get_finance_waytype() );
171 }
172 }
173
174
175 // correct speed and maintenance
cleanup(player_t * player2)176 void tunnel_t::cleanup( player_t *player2 )
177 {
178 player_t *player = get_owner();
179 if(player) {
180 // inside tunnel => do nothing but change maintenance
181 const grund_t *gr = welt->lookup(get_pos());
182 if(gr) {
183 weg_t *weg = gr->get_weg( desc->get_waytype() );
184 if(weg) {
185 weg->set_max_speed( weg->get_desc()->get_topspeed() );
186 player_t::add_maintenance( player, weg->get_desc()->get_maintenance(), weg->get_desc()->get_finance_waytype());
187 }
188 player_t::add_maintenance( player, -desc->get_maintenance(), desc->get_finance_waytype() );
189 }
190 }
191 player_t::book_construction_costs(player2, -desc->get_price(), get_pos().get_2d(), desc->get_finance_waytype() );
192 }
193
194
set_image(image_id b)195 void tunnel_t::set_image( image_id b )
196 {
197 mark_image_dirty( image, 0 );
198 mark_image_dirty( b, 0 );
199 image = b;
200 }
201
202
set_foreground_image(image_id b)203 void tunnel_t::set_foreground_image( image_id b )
204 {
205 mark_image_dirty( foreground_image, 0 );
206 mark_image_dirty( b, 0 );
207 foreground_image = b;
208 }
209
210
211 // returns NULL, if removal is allowed
212 // players can remove public owned ways
is_deletable(const player_t * player)213 const char *tunnel_t::is_deletable(const player_t *player)
214 {
215 if (get_player_nr()==welt->get_public_player()->get_player_nr()) {
216 return NULL;
217 }
218 else {
219 return obj_t::is_deletable(player);
220 }
221 }
222