--- deliantra/server/common/material.C 2009/11/04 00:08:44 1.2 +++ deliantra/server/common/material.C 2011/04/23 04:56:46 1.16 @@ -1,9 +1,9 @@ /* * 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 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 @@ -25,10 +25,85 @@ #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; + 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) { @@ -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,73 +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 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) @@ -194,7 +246,7 @@ thawer.next (); if (thawer.kw == KW_EOF) - goto done; + return; } materialtype_t *mt; @@ -204,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: @@ -276,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"); }