--- deliantra/server/common/material.C 2009/11/10 00:01:31 1.4
+++ deliantra/server/common/material.C 2012/11/04 01:01:13 1.19
@@ -1,24 +1,24 @@
/*
* This file is part of Deliantra, the Roguelike Realtime MMORPG.
- *
- * Copyright (©) 2005,2006,2007,2008,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
- * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
- * Copyright (©) 1992,2007 Frank Tore Johansen
- *
+ *
+ * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
+ * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
+ * Copyright (©) 1992 Frank Tore Johansen
+ *
* Deliantra is free software: you can redistribute it and/or modify it under
* the terms of the Affero GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the Affero GNU General Public License
* and the GNU General Public License along with this program. If not, see
* .
- *
+ *
* The authors can be reached via e-mail to
*/
@@ -27,10 +27,83 @@
//+GPL
-/* convert materialname to materialtype_t */
+materialtype_t *materialt;
-materialtype_t *
-name_to_material (const shstr_cmp name)
+/*
+materialtype material[NROFMATERIALS] = {
+ * P M F E C C A D W G P S P T F C D D C C G H B I *
+ * H A I L O O C R E H O L A U E A E E H O O O L N *
+ * Y G R E L N I A A O I O R R A N P A A U D L I T *
+ * S I E C D F D I P S S W A N R C L T O N Y N R *
+ * I C T U N O T O L E E H S T P D N *
+ {"paper", {15,10,17, 9, 5, 7,13, 0,20,15, 0,0,0,0,0,10,0,0,0,0,0,0,0,0}},
+ {"metal", { 2,12, 3,12, 2,10, 7, 0,20,15, 0,0,0,0,0,10,0,0,0,0,0,0,0,0}},
+ {"glass", {14,11, 8, 3,10, 5, 1, 0,20,15, 0,0,0,0,0, 0,0,0,0,0,0,0,0,0}},
+ {"leather", { 5,10,10, 3, 3,10,10, 0,20,15, 0,0,0,0,0,12,0,0,0,0,0,0,0,0}},
+ {"wood", {10,11,13, 2, 2,10, 9, 0,20,15, 0,0,0,0,0,12,0,0,0,0,0,0,0,0}},
+ {"organics", { 3,12, 9,11, 3,10, 9, 0,20,15, 0,0,0,0,0, 0,0,0,0,0,0,0,0,0}},
+ {"stone", { 2, 5, 2, 2, 2, 2, 1, 0,20,15, 0,0,0,0,0, 5,0,0,0,0,0,0,0,0}},
+ {"cloth", {14,11,13, 4, 4, 5,10, 0,20,15, 0,0,0,0,0, 5,0,0,0,0,0,0,0,0}},
+ {"adamant", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0, 0,0,0,0,0,0,0,0,0}},
+ {"liquid", { 0, 8, 9, 6,17, 0,15, 0,20,15,12,0,0,0,0,11,0,0,0,0,0,0,0,0}},
+ {"soft metal",{ 6,12, 6,14, 2,10, 1, 0,20,15, 0,0,0,0,0,10,0,0,0,0,0,0,0,0}},
+ {"bone", {10, 9, 4, 5, 3,10,10, 0,20,15, 0,0,0,0,0, 2,0,0,0,0,0,0,0,0}},
+ {"ice", {14,11,16, 5, 0, 5, 6, 0,20,15, 0,0,0,0,0, 7,0,0,0,0,0,0,0,0}}
+};
+*/
+
+materialtype_t::materialtype_t ()
+{
+ next = 0;
+ reset ();
+}
+
+void
+materialtype_t::reset ()
+{
+ name = shstr_unknown;
+ description = shstr_unknown_material_description;
+ material = 0;
+
+ for (int i = 0; i < NROFATTACKS; i++)
+ {
+ save [i] = 0;
+ mod [i] = 0;
+ }
+
+ chance = 0;
+ difficulty = 0;
+ magic = 0;
+ damage = 0;
+ wc = 0;
+ ac = 0;
+ sp = 0;
+ weight = 100;
+ value = 100;
+ density = 1000;
+}
+
+// create a new material of the given name
+static materialtype_t *
+dummy_material (shstr_tmp name)
+{
+ materialtype_t *mt = new materialtype_t;
+ mt->name = name;
+
+ // make it susceptible to attacks
+ for (int i = 0; i < NROFATTACKS; i++)
+ {
+ mt->save [i] = 10;
+ mt->mod [i] = 9;
+ }
+
+ mt->next = materialt; materialt = mt;
+
+ return mt;
+}
+
+static materialtype_t *
+find (const shstr_tmp name)
{
for (materialtype_t *mt = materialt; mt; mt = mt->next)
if (name == mt->name)
@@ -39,66 +112,84 @@
return 0;
}
+/* convert materialname to materialtype_t */
+materialtype_t *
+name_to_material (const shstr_tmp name)
+{
+ materialtype_t *mt = find (name);
+
+ if (!mt)
+ {
+ LOG (llevError, "name_to_material called with nonexistent material '%s'\n", &name);
+ mt = dummy_material (name);
+ }
+
+ return mt;
+}
+
+void
+object_thawer::get (materialtype_t *&mt) const
+{
+ shstr name;
+ get (name);
+
+ mt = find (name);
+
+ if (!mt)
+ {
+ parse_error (format ("material called %s requested, but not found, creating dummy material.\n", &name));
+ mt = dummy_material (name);
+ }
+}
+
/* when doing transmutation of objects, we have to recheck the resistances,
* as some that did not apply previously, may apply now.
*/
void
transmute_materialname (object *op, const object *change)
{
- materialtype_t *mt;
- int j;
-
- if (!op->materialname)
+ if (!op->is_armor ())
return;
- if (op->materialname != change->materialname)
+ if (op->material == MATERIAL_NULL)
return;
- if (!op->is_armor ())
+ if (op->material != change->material)
return;
- mt = name_to_material (op->materialname);
- if (!mt)
- {
- LOG (llevError, "archetype '%s>%s' uses nonexistent material '%s'\n", &op->arch->archname, &op->name, &op->materialname);
- return;
- }
+ materialtype_t *mt = op->material;
- for (j = 0; j < NROFATTACKS; j++)
+ for (int j = 0; j < NROFATTACKS; j++)
if (op->resist[j] == 0 && change->resist[j] != 0)
{
op->resist[j] += mt->mod[j];
- if (op->resist[j] > 100)
- op->resist[j] = 100;
- if (op->resist[j] < -100)
- op->resist[j] = -100;
+
+ if (op->resist[j] > 100) op->resist[j] = 100;
+ if (op->resist[j] < -100) op->resist[j] = -100;
}
}
/* set the materialname and type for an item */
void
-set_materialname (object *op, int difficulty, materialtype_t *nmt)
+select_material (object *op, int difficulty)
{
- materialtype_t *mt, *lmt;
-
- if (!op->materialname)
+ if (op->material != MATERIAL_NULL || !op->materials)
return;
- if (nmt)
- lmt = nmt;
- else
- {
- lmt = 0;
+ materialtype_t *lmt = 0;
- for (mt = materialt; mt; mt = mt->next)
- if (op->materials & mt->material && rndm (1, 100) <= mt->chance &&
- difficulty >= mt->difficulty && (op->magic >= mt->magic || mt->magic == 0))
- {
- lmt = mt;
- if (!(op->is_weapon () || op->is_armor ()))
- break;
- }
- }
+ //TODL: dead code?
+ for (materialtype_t *mt = materialt; mt; mt = mt->next)
+ if (op->materials & mt->material
+ && difficulty >= mt->difficulty
+ && rndm (1, 100) <= mt->chance
+ && (op->magic >= mt->magic || mt->magic == 0))
+ {
+ lmt = mt;
+
+ if (!(op->is_weapon () || op->is_armor ()))
+ break;
+ }
if (lmt)
{
@@ -109,10 +200,9 @@
op->stats.dam = 1;
}
- if (op->stats.sp && op->type == BOW)
- op->stats.sp += lmt->sp;
- if (op->stats.wc && op->is_weapon ())
- op->stats.wc += lmt->wc;
+ if (op->stats.sp && op->type == BOW ) op->stats.sp += lmt->sp;
+ if (op->stats.wc && op->is_weapon ()) op->stats.wc += lmt->wc;
+
if (op->is_armor ())
{
if (op->stats.ac)
@@ -122,84 +212,33 @@
if (op->resist[j] != 0)
{
op->resist[j] += lmt->mod[j];
- if (op->resist[j] > 100)
- op->resist[j] = 100;
- if (op->resist[j] < -100)
- op->resist[j] = -100;
+ if (op->resist[j] > 100) op->resist[j] = 100;
+ if (op->resist[j] < -100) op->resist[j] = -100;
}
}
- op->materialname = lmt->name;
+ op->material = lmt;
+
/* dont make it unstackable if it doesn't need to be */
if (op->is_weapon () || op->is_armor ())
{
- op->weight = (op->weight * lmt->weight) / 100;
- op->value = (op->value * lmt->value) / 100;
+ op->weight = op->weight * lmt->weight / 100;
+ op->value = op->value * lmt->value / 100;
}
}
}
-//TODO: make this a constructor
-static materialtype_t *
-get_empty_mat (void)
-{
- materialtype_t *mt;
- int i;
-
- mt = new materialtype_t;
-
- mt->name = shstr_unknown;
- mt->description = 0;
-
- for (i = 0; i < NROFATTACKS; i++)
- {
- mt->save[i] = 0;
- mt->mod[i] = 0;
- }
-
- mt->chance = 0;
- mt->difficulty = 0;
- mt->magic = 0;
- mt->damage = 0;
- mt->wc = 0;
- mt->ac = 0;
- mt->sp = 0;
- mt->weight = 100;
- mt->value = 100;
- mt->density = 1;
- mt->next = 0;
-
- return mt;
-}
-
//-GPL
-const materialtype_t *
-object::dominant_material () const
-{
- if (materialtype_t *mt = name_to_material (materialname))
- return mt;
-
- return name_to_material (shstr_unknown);
-}
-
void
-load_materials (void)
+_reload_materials ()
{
- char filename[MAX_BUF];
-
- sprintf (filename, "%s/materials", settings.datadir);
- LOG (llevDebug, "Reading material type data from %s...\n", filename);
-
- //TODO: somehow free old materials, or update them in-place
- materialt = 0;
-
- object_thawer thawer (filename);
+ object_thawer thawer (settings.datadir, "materials");
if (!thawer)
{
- LOG (llevError, "Cannot open %s for reading\n", filename);
- goto done;
+ LOG (llevError, "unable to load %s for reading\n", thawer.name);
+ return;
}
while (thawer.kw != KW_name)
@@ -207,7 +246,7 @@
thawer.next ();
if (thawer.kw == KW_EOF)
- goto done;
+ return;
}
materialtype_t *mt;
@@ -217,12 +256,26 @@
switch (thawer.kw)
{
case KW_name:
- mt = get_empty_mat ();
- mt->next = materialt;
- materialt = mt;
+ coroapi::cede_to_tick ();
- thawer.get (mt->name);
- mt->description = mt->name;
+ {
+ // create a new dummy material, or find the existing material
+ shstr name;
+ thawer.get (name);
+
+ mt = find (name);
+
+ if (mt)
+ mt->reset ();
+ else
+ {
+ mt = new materialtype_t;
+ mt->next = materialt; materialt = mt;
+ }
+
+ mt->name = name;
+ mt->description = name;
+ }
break;
case KW_description:
@@ -289,21 +342,15 @@
case KW_density: thawer.get (mt->density); break;
case KW_EOF:
- goto done;
+ return;
default:
- if (!thawer.parse_error ("materials file", "materials"))
- goto done;
+ if (!thawer.parse_error ("materials file"))
+ return;
break;
}
thawer.next ();
}
-
-done:
- if (!materialt)
- materialt = get_empty_mat ();
-
- LOG (llevDebug, "Done.\n");
}