--- deliantra/server/common/material.C 2009/11/04 00:02:48 1.1
+++ deliantra/server/common/material.C 2012/11/04 01:01:13 1.19
@@ -1,34 +1,109 @@
/*
* 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
*/
#include
#include
-/* convert materialname to materialtype_t */
+//+GPL
-materialtype_t *
-name_to_material (const shstr_cmp name)
+materialtype_t *materialt;
+
+/*
+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)
@@ -37,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;
-
- 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;
- }
- }
+ materialtype_t *lmt = 0;
+
+ //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)
{
@@ -107,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)
@@ -120,20 +212,145 @@
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;
}
}
}
+//-GPL
+
+void
+_reload_materials ()
+{
+ object_thawer thawer (settings.datadir, "materials");
+
+ if (!thawer)
+ {
+ LOG (llevError, "unable to load %s for reading\n", thawer.name);
+ return;
+ }
+
+ while (thawer.kw != KW_name)
+ {
+ thawer.next ();
+
+ if (thawer.kw == KW_EOF)
+ return;
+ }
+
+ materialtype_t *mt;
+
+ for (;;)
+ {
+ switch (thawer.kw)
+ {
+ case KW_name:
+ coroapi::cede_to_tick ();
+
+ {
+ // 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:
+ thawer.get (mt->description);
+ break;
+
+ case KW_material:
+ thawer.get (mt->material);
+ break;
+
+ case KW_saves:
+ {
+ const char *cp = thawer.get_str () - 1;
+
+ for (int i = 0; i < NROFATTACKS; i++)
+ {
+ if (!cp)
+ {
+ mt->save[i] = 0;
+ continue;
+ }
+
+ int value;
+ ++cp;
+ sscanf (cp, "%d", &value);
+ mt->save[i] = (sint8) value;
+ cp = strchr (cp, ',');
+ }
+ }
+ break;
+
+ case KW_mods:
+ {
+ const char *cp = thawer.get_str () - 1;
+
+ for (int i = 0; i < NROFATTACKS; i++)
+ {
+ if (!cp)
+ {
+ mt->save[i] = 0;
+ continue;
+ }
+
+ ++cp;
+ int value;
+ sscanf (cp, "%d", &value);
+ mt->mod[i] = (sint8) value;
+ cp = strchr (cp, ',');
+ }
+ }
+ break;
+
+ case KW_chance: thawer.get (mt->chance); break;
+ case KW_difficulty: // cf+ alias, not original cf
+ case KW_diff: thawer.get (mt->difficulty); break;
+ case KW_magic: thawer.get (mt->magic); break;
+ case KW_dam: // cf+ alias, not original cf
+ case KW_damage: thawer.get (mt->damage); break;
+ case KW_wc: thawer.get (mt->wc); break;
+ case KW_ac: thawer.get (mt->ac); break;
+ case KW_sp: thawer.get (mt->sp); break;
+ case KW_weight: thawer.get (mt->weight); break;
+ case KW_value: thawer.get (mt->value); break;
+ case KW_density: thawer.get (mt->density); break;
+
+ case KW_EOF:
+ return;
+
+ default:
+ if (!thawer.parse_error ("materials file"))
+ return;
+ break;
+ }
+
+ thawer.next ();
+ }
+}
+