1 /*
2  * Copyright (c) 1997 - 2001 Hj. Malthaner
3  *
4  * This file is part of the Simutrans project under the artistic license.
5  * (see license.txt)
6  */
7 
8 #include <stdio.h>
9 #include <string.h>
10 
11 #include "simmem.h"
12 #include "simdebug.h"
13 #include "simfab.h"
14 #include "simhalt.h"
15 #include "simtypes.h"
16 #include "simware.h"
17 #include "simworld.h"
18 #include "dataobj/loadsave.h"
19 #include "dataobj/koord.h"
20 
21 #include "descriptor/goods_desc.h"
22 #include "bauer/goods_manager.h"
23 
24 
25 
26 const goods_desc_t *ware_t::index_to_desc[256];
27 
ware_t()28 ware_t::ware_t() : ziel(), zwischenziel(), zielpos(-1, -1)
29 {
30 	menge = 0;
31 	index = 0;
32 	to_factory = 0;
33 }
34 
35 
ware_t(const goods_desc_t * wtyp)36 ware_t::ware_t(const goods_desc_t *wtyp) : ziel(), zwischenziel(), zielpos(-1, -1)
37 {
38 	menge = 0;
39 	index = wtyp->get_index();
40 	to_factory = 0;
41 }
42 
43 
ware_t(loadsave_t * file)44 ware_t::ware_t(loadsave_t *file)
45 {
46 	rdwr(file);
47 }
48 
49 
rdwr(loadsave_t * file)50 void ware_t::rdwr(loadsave_t *file)
51 {
52 	sint32 amount = menge;
53 	file->rdwr_long(amount);
54 	menge = amount;
55 	if(file->is_version_less(99, 8)) {
56 		sint32 max;
57 		file->rdwr_long(max);
58 	}
59 
60 	if(  file->is_version_atleast(110, 5)  ) {
61 		uint8 factory_going = to_factory;
62 		file->rdwr_byte(factory_going);
63 		to_factory = factory_going;
64 	}
65 	else if(  file->is_loading()  ) {
66 		to_factory = 0;
67 	}
68 
69 	uint8 catg=0;
70 	if(file->is_version_atleast(88, 5)) {
71 		file->rdwr_byte(catg);
72 	}
73 
74 	if(file->is_saving()) {
75 		const char *typ = NULL;
76 		typ = get_desc()->get_name();
77 		file->rdwr_str(typ);
78 	}
79 	else {
80 		char typ[256];
81 		file->rdwr_str(typ, lengthof(typ));
82 		const goods_desc_t *type = goods_manager_t::get_info(typ);
83 		if(type==NULL) {
84 			dbg->warning("ware_t::rdwr()","unknown ware of catg %d!",catg);
85 			index = goods_manager_t::get_info_catg(catg)->get_index();
86 			menge = 0;
87 		}
88 		else {
89 			index = type->get_index();
90 		}
91 	}
92 	// convert coordinate to halt indices
93 	if(file->is_version_atleast(110, 6)) {
94 		// save halt id directly
95 		if(file->is_saving()) {
96 			uint16 halt_id = ziel.is_bound() ? ziel.get_id() : 0;
97 			file->rdwr_short(halt_id);
98 			halt_id = zwischenziel.is_bound() ? zwischenziel.get_id() : 0;
99 			file->rdwr_short(halt_id);
100 		}
101 		else {
102 			uint16 halt_id;
103 			file->rdwr_short(halt_id);
104 			ziel.set_id(halt_id);
105 			file->rdwr_short(halt_id);
106 			zwischenziel.set_id(halt_id);
107 		}
108 
109 	}
110 	else {
111 		// save halthandles via coordinates
112 		if(file->is_saving()) {
113 			koord ziel_koord = ziel.is_bound() ? ziel->get_basis_pos() : koord::invalid;
114 			ziel_koord.rdwr(file);
115 			koord zwischenziel_koord = zwischenziel.is_bound() ? zwischenziel->get_basis_pos() : koord::invalid;
116 			zwischenziel_koord.rdwr(file);
117 		}
118 		else {
119 			koord ziel_koord;
120 			ziel_koord.rdwr(file);
121 			ziel = haltestelle_t::get_halt_koord_index(ziel_koord);
122 			koord zwischen_ziel_koord;
123 			zwischen_ziel_koord.rdwr(file);
124 			zwischenziel = haltestelle_t::get_halt_koord_index(zwischen_ziel_koord);
125 		}
126 	}
127 	zielpos.rdwr(file);
128 	// restore factory-flag
129 	if(  file->is_version_less(110, 5)  &&  file->is_loading()  ) {
130 		if (fabrik_t::get_fab(zielpos)) {
131 			to_factory = 1;
132 		}
133 	}
134 }
135 
136 
finish_rd(karte_t * welt)137 void ware_t::finish_rd(karte_t *welt)
138 {
139 	if(  welt->load_version<=111005  ) {
140 		// since some halt was referred by with several koordinates
141 		// this routine will correct it
142 		if(ziel.is_bound()) {
143 			ziel = haltestelle_t::get_halt_koord_index(ziel->get_init_pos());
144 		}
145 		if(zwischenziel.is_bound()) {
146 			zwischenziel = haltestelle_t::get_halt_koord_index(zwischenziel->get_init_pos());
147 		}
148 	}
149 	update_factory_target();
150 }
151 
152 
rotate90(sint16 y_size)153 void ware_t::rotate90(sint16 y_size )
154 {
155 	zielpos.rotate90( y_size );
156 	update_factory_target();
157 }
158 
159 
update_factory_target()160 void ware_t::update_factory_target()
161 {
162 	if (to_factory) {
163 		// assert that target coordinates are unique for cargo going to the same factory
164 		// as new cargo will be generated with possibly new factory coordinates
165 		fabrik_t *fab = fabrik_t::get_fab(zielpos );
166 		if (fab) {
167 			zielpos = fab->get_pos().get_2d();
168 		}
169 	}
170 }
171 
172 
calc_revenue(const goods_desc_t * desc,waytype_t wt,sint32 speedkmh)173 sint64 ware_t::calc_revenue(const goods_desc_t* desc, waytype_t wt, sint32 speedkmh)
174 {
175 	static karte_ptr_t welt;
176 
177 	const sint32 ref_kmh = welt->get_average_speed( wt );
178 	const sint32 kmh_base = (100 * speedkmh) / ref_kmh - 100;
179 
180 	const sint32 grundwert128    = welt->get_settings().get_bonus_basefactor(); // minimal bonus factor
181 	const sint32 grundwert_bonus = 1000+kmh_base*desc->get_speed_bonus();      // speed bonus factor
182 	// take the larger of both
183 	return desc->get_value() * (grundwert128 > grundwert_bonus ? grundwert128 : grundwert_bonus);
184 }
185 
add_goods(goods_amount_t const number)186 ware_t::goods_amount_t ware_t::add_goods(goods_amount_t const number) {
187 	goods_amount_t const limit = GOODS_AMOUNT_LIMIT - menge;
188 	if (limit < number) {
189 		menge = GOODS_AMOUNT_LIMIT;
190 		return number - limit;
191 	}
192 
193 	menge+= number;
194 	return 0;
195 }
196 
remove_goods(goods_amount_t const number)197 ware_t::goods_amount_t ware_t::remove_goods(goods_amount_t const number) {
198 	if (menge < number) {
199 		goods_amount_t const remainder = number - menge;
200 		menge = 0;
201 		return remainder;
202 	}
203 
204 	menge-= number;
205 	return 0;
206 }
207 
is_goods_amount_maxed() const208 bool ware_t::is_goods_amount_maxed() const {
209 	return menge == GOODS_AMOUNT_LIMIT;
210 }
211