ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/material.C
Revision: 1.2
Committed: Wed Nov 4 00:08:44 2009 UTC (14 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.1: +157 -0 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2005,2006,2007,2008,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 *
8 * Deliantra is free software: you can redistribute it and/or modify it under
9 * the terms of the Affero GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the Affero GNU General Public License
19 * and the GNU General Public License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
21 *
22 * The authors can be reached via e-mail to <support@deliantra.net>
23 */
24
25 #include <global.h>
26 #include <material.h>
27
28 /* convert materialname to materialtype_t */
29
30 materialtype_t *
31 name_to_material (const shstr_cmp name)
32 {
33 for (materialtype_t *mt = materialt; mt; mt = mt->next)
34 if (name == mt->name)
35 return mt;
36
37 return 0;
38 }
39
40 /* when doing transmutation of objects, we have to recheck the resistances,
41 * as some that did not apply previously, may apply now.
42 */
43 void
44 transmute_materialname (object *op, const object *change)
45 {
46 materialtype_t *mt;
47 int j;
48
49 if (!op->materialname)
50 return;
51
52 if (op->materialname != change->materialname)
53 return;
54
55 if (!op->is_armor ())
56 return;
57
58 mt = name_to_material (op->materialname);
59 if (!mt)
60 {
61 LOG (llevError, "archetype '%s>%s' uses nonexistent material '%s'\n", &op->arch->archname, &op->name, &op->materialname);
62 return;
63 }
64
65 for (j = 0; j < NROFATTACKS; j++)
66 if (op->resist[j] == 0 && change->resist[j] != 0)
67 {
68 op->resist[j] += mt->mod[j];
69 if (op->resist[j] > 100)
70 op->resist[j] = 100;
71 if (op->resist[j] < -100)
72 op->resist[j] = -100;
73 }
74 }
75
76 /* set the materialname and type for an item */
77 void
78 set_materialname (object *op, int difficulty, materialtype_t *nmt)
79 {
80 materialtype_t *mt, *lmt;
81
82 if (!op->materialname)
83 return;
84
85 if (nmt)
86 lmt = nmt;
87 else
88 {
89 lmt = 0;
90
91 for (mt = materialt; mt; mt = mt->next)
92 if (op->materials & mt->material && rndm (1, 100) <= mt->chance &&
93 difficulty >= mt->difficulty && (op->magic >= mt->magic || mt->magic == 0))
94 {
95 lmt = mt;
96 if (!(op->is_weapon () || op->is_armor ()))
97 break;
98 }
99 }
100
101 if (lmt)
102 {
103 if (op->stats.dam && op->is_weapon ())
104 {
105 op->stats.dam += lmt->damage;
106 if (op->stats.dam < 1)
107 op->stats.dam = 1;
108 }
109
110 if (op->stats.sp && op->type == BOW)
111 op->stats.sp += lmt->sp;
112 if (op->stats.wc && op->is_weapon ())
113 op->stats.wc += lmt->wc;
114 if (op->is_armor ())
115 {
116 if (op->stats.ac)
117 op->stats.ac += lmt->ac;
118
119 for (int j = 0; j < NROFATTACKS; j++)
120 if (op->resist[j] != 0)
121 {
122 op->resist[j] += lmt->mod[j];
123 if (op->resist[j] > 100)
124 op->resist[j] = 100;
125 if (op->resist[j] < -100)
126 op->resist[j] = -100;
127 }
128 }
129
130 op->materialname = lmt->name;
131 /* dont make it unstackable if it doesn't need to be */
132 if (op->is_weapon () || op->is_armor ())
133 {
134 op->weight = (op->weight * lmt->weight) / 100;
135 op->value = (op->value * lmt->value) / 100;
136 }
137 }
138 }
139
140 //TODO: make this a constructor
141 static materialtype_t *
142 get_empty_mat (void)
143 {
144 materialtype_t *mt;
145 int i;
146
147 mt = new materialtype_t;
148
149 mt->name = shstr_unknown;
150 mt->description = 0;
151
152 for (i = 0; i < NROFATTACKS; i++)
153 {
154 mt->save[i] = 0;
155 mt->mod[i] = 0;
156 }
157
158 mt->chance = 0;
159 mt->difficulty = 0;
160 mt->magic = 0;
161 mt->damage = 0;
162 mt->wc = 0;
163 mt->ac = 0;
164 mt->sp = 0;
165 mt->weight = 100;
166 mt->value = 100;
167 mt->density = 1;
168 mt->next = 0;
169
170 return mt;
171 }
172
173 void
174 load_materials (void)
175 {
176 char filename[MAX_BUF];
177
178 sprintf (filename, "%s/materials", settings.datadir);
179 LOG (llevDebug, "Reading material type data from %s...\n", filename);
180
181 //TODO: somehow free old materials, or update them in-place
182 materialt = 0;
183
184 object_thawer thawer (filename);
185
186 if (!thawer)
187 {
188 LOG (llevError, "Cannot open %s for reading\n", filename);
189 goto done;
190 }
191
192 while (thawer.kw != KW_name)
193 {
194 thawer.next ();
195
196 if (thawer.kw == KW_EOF)
197 goto done;
198 }
199
200 materialtype_t *mt;
201
202 for (;;)
203 {
204 switch (thawer.kw)
205 {
206 case KW_name:
207 mt = get_empty_mat ();
208 mt->next = materialt;
209 materialt = mt;
210
211 thawer.get (mt->name);
212 mt->description = mt->name;
213 break;
214
215 case KW_description:
216 thawer.get (mt->description);
217 break;
218
219 case KW_material:
220 thawer.get (mt->material);
221 break;
222
223 case KW_saves:
224 {
225 const char *cp = thawer.get_str () - 1;
226
227 for (int i = 0; i < NROFATTACKS; i++)
228 {
229 if (!cp)
230 {
231 mt->save[i] = 0;
232 continue;
233 }
234
235 int value;
236 ++cp;
237 sscanf (cp, "%d", &value);
238 mt->save[i] = (sint8) value;
239 cp = strchr (cp, ',');
240 }
241 }
242 break;
243
244 case KW_mods:
245 {
246 const char *cp = thawer.get_str () - 1;
247
248 for (int i = 0; i < NROFATTACKS; i++)
249 {
250 if (!cp)
251 {
252 mt->save[i] = 0;
253 continue;
254 }
255
256 ++cp;
257 int value;
258 sscanf (cp, "%d", &value);
259 mt->mod[i] = (sint8) value;
260 cp = strchr (cp, ',');
261 }
262 }
263 break;
264
265 case KW_chance: thawer.get (mt->chance); break;
266 case KW_difficulty: // cf+ alias, not original cf
267 case KW_diff: thawer.get (mt->difficulty); break;
268 case KW_magic: thawer.get (mt->magic); break;
269 case KW_dam: // cf+ alias, not original cf
270 case KW_damage: thawer.get (mt->damage); break;
271 case KW_wc: thawer.get (mt->wc); break;
272 case KW_ac: thawer.get (mt->ac); break;
273 case KW_sp: thawer.get (mt->sp); break;
274 case KW_weight: thawer.get (mt->weight); break;
275 case KW_value: thawer.get (mt->value); break;
276 case KW_density: thawer.get (mt->density); break;
277
278 case KW_EOF:
279 goto done;
280
281 default:
282 if (!thawer.parse_error ("materials file", "materials"))
283 goto done;
284 break;
285 }
286
287 thawer.next ();
288 }
289
290 done:
291 if (!materialt)
292 materialt = get_empty_mat ();
293
294 LOG (llevDebug, "Done.\n");
295 }
296