ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/material.C
Revision: 1.4
Committed: Tue Nov 10 00:01:31 2009 UTC (14 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.3: +9 -0 lines
Log Message:
store hash in shstr

File Contents

# User Rev Content
1 root 1.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 root 1.3 //+GPL
29    
30 root 1.1 /* convert materialname to materialtype_t */
31    
32     materialtype_t *
33     name_to_material (const shstr_cmp name)
34     {
35     for (materialtype_t *mt = materialt; mt; mt = mt->next)
36     if (name == mt->name)
37     return mt;
38    
39     return 0;
40     }
41    
42     /* when doing transmutation of objects, we have to recheck the resistances,
43     * as some that did not apply previously, may apply now.
44     */
45     void
46     transmute_materialname (object *op, const object *change)
47     {
48     materialtype_t *mt;
49     int j;
50    
51     if (!op->materialname)
52     return;
53    
54     if (op->materialname != change->materialname)
55     return;
56    
57     if (!op->is_armor ())
58     return;
59    
60     mt = name_to_material (op->materialname);
61     if (!mt)
62     {
63     LOG (llevError, "archetype '%s>%s' uses nonexistent material '%s'\n", &op->arch->archname, &op->name, &op->materialname);
64     return;
65     }
66    
67     for (j = 0; j < NROFATTACKS; j++)
68     if (op->resist[j] == 0 && change->resist[j] != 0)
69     {
70     op->resist[j] += mt->mod[j];
71     if (op->resist[j] > 100)
72     op->resist[j] = 100;
73     if (op->resist[j] < -100)
74     op->resist[j] = -100;
75     }
76     }
77    
78     /* set the materialname and type for an item */
79     void
80     set_materialname (object *op, int difficulty, materialtype_t *nmt)
81     {
82     materialtype_t *mt, *lmt;
83    
84     if (!op->materialname)
85     return;
86    
87     if (nmt)
88     lmt = nmt;
89     else
90     {
91     lmt = 0;
92    
93     for (mt = materialt; mt; mt = mt->next)
94     if (op->materials & mt->material && rndm (1, 100) <= mt->chance &&
95     difficulty >= mt->difficulty && (op->magic >= mt->magic || mt->magic == 0))
96     {
97     lmt = mt;
98     if (!(op->is_weapon () || op->is_armor ()))
99     break;
100     }
101     }
102    
103     if (lmt)
104     {
105     if (op->stats.dam && op->is_weapon ())
106     {
107     op->stats.dam += lmt->damage;
108     if (op->stats.dam < 1)
109     op->stats.dam = 1;
110     }
111    
112     if (op->stats.sp && op->type == BOW)
113     op->stats.sp += lmt->sp;
114     if (op->stats.wc && op->is_weapon ())
115     op->stats.wc += lmt->wc;
116     if (op->is_armor ())
117     {
118     if (op->stats.ac)
119     op->stats.ac += lmt->ac;
120    
121     for (int j = 0; j < NROFATTACKS; j++)
122     if (op->resist[j] != 0)
123     {
124     op->resist[j] += lmt->mod[j];
125     if (op->resist[j] > 100)
126     op->resist[j] = 100;
127     if (op->resist[j] < -100)
128     op->resist[j] = -100;
129     }
130     }
131    
132     op->materialname = lmt->name;
133     /* dont make it unstackable if it doesn't need to be */
134     if (op->is_weapon () || op->is_armor ())
135     {
136     op->weight = (op->weight * lmt->weight) / 100;
137     op->value = (op->value * lmt->value) / 100;
138     }
139     }
140     }
141    
142 root 1.2 //TODO: make this a constructor
143     static materialtype_t *
144     get_empty_mat (void)
145     {
146     materialtype_t *mt;
147     int i;
148    
149     mt = new materialtype_t;
150    
151     mt->name = shstr_unknown;
152     mt->description = 0;
153    
154     for (i = 0; i < NROFATTACKS; i++)
155     {
156     mt->save[i] = 0;
157     mt->mod[i] = 0;
158     }
159    
160     mt->chance = 0;
161     mt->difficulty = 0;
162     mt->magic = 0;
163     mt->damage = 0;
164     mt->wc = 0;
165     mt->ac = 0;
166     mt->sp = 0;
167     mt->weight = 100;
168     mt->value = 100;
169     mt->density = 1;
170     mt->next = 0;
171    
172     return mt;
173     }
174    
175 root 1.3 //-GPL
176    
177 root 1.4 const materialtype_t *
178     object::dominant_material () const
179     {
180     if (materialtype_t *mt = name_to_material (materialname))
181     return mt;
182    
183     return name_to_material (shstr_unknown);
184     }
185    
186 root 1.2 void
187     load_materials (void)
188     {
189     char filename[MAX_BUF];
190    
191     sprintf (filename, "%s/materials", settings.datadir);
192     LOG (llevDebug, "Reading material type data from %s...\n", filename);
193    
194     //TODO: somehow free old materials, or update them in-place
195     materialt = 0;
196    
197     object_thawer thawer (filename);
198    
199     if (!thawer)
200     {
201     LOG (llevError, "Cannot open %s for reading\n", filename);
202     goto done;
203     }
204    
205     while (thawer.kw != KW_name)
206     {
207     thawer.next ();
208    
209     if (thawer.kw == KW_EOF)
210     goto done;
211     }
212    
213     materialtype_t *mt;
214    
215     for (;;)
216     {
217     switch (thawer.kw)
218     {
219     case KW_name:
220     mt = get_empty_mat ();
221     mt->next = materialt;
222     materialt = mt;
223    
224     thawer.get (mt->name);
225     mt->description = mt->name;
226     break;
227    
228     case KW_description:
229     thawer.get (mt->description);
230     break;
231    
232     case KW_material:
233     thawer.get (mt->material);
234     break;
235    
236     case KW_saves:
237     {
238     const char *cp = thawer.get_str () - 1;
239    
240     for (int i = 0; i < NROFATTACKS; i++)
241     {
242     if (!cp)
243     {
244     mt->save[i] = 0;
245     continue;
246     }
247    
248     int value;
249     ++cp;
250     sscanf (cp, "%d", &value);
251     mt->save[i] = (sint8) value;
252     cp = strchr (cp, ',');
253     }
254     }
255     break;
256    
257     case KW_mods:
258     {
259     const char *cp = thawer.get_str () - 1;
260    
261     for (int i = 0; i < NROFATTACKS; i++)
262     {
263     if (!cp)
264     {
265     mt->save[i] = 0;
266     continue;
267     }
268    
269     ++cp;
270     int value;
271     sscanf (cp, "%d", &value);
272     mt->mod[i] = (sint8) value;
273     cp = strchr (cp, ',');
274     }
275     }
276     break;
277    
278     case KW_chance: thawer.get (mt->chance); break;
279     case KW_difficulty: // cf+ alias, not original cf
280     case KW_diff: thawer.get (mt->difficulty); break;
281     case KW_magic: thawer.get (mt->magic); break;
282     case KW_dam: // cf+ alias, not original cf
283     case KW_damage: thawer.get (mt->damage); break;
284     case KW_wc: thawer.get (mt->wc); break;
285     case KW_ac: thawer.get (mt->ac); break;
286     case KW_sp: thawer.get (mt->sp); break;
287     case KW_weight: thawer.get (mt->weight); break;
288     case KW_value: thawer.get (mt->value); break;
289     case KW_density: thawer.get (mt->density); break;
290    
291     case KW_EOF:
292     goto done;
293    
294     default:
295     if (!thawer.parse_error ("materials file", "materials"))
296     goto done;
297     break;
298     }
299    
300     thawer.next ();
301     }
302    
303     done:
304     if (!materialt)
305     materialt = get_empty_mat ();
306    
307     LOG (llevDebug, "Done.\n");
308     }
309