--- deliantra/server/common/material.C 2009/11/04 00:02:48 1.1 +++ deliantra/server/common/material.C 2010/04/28 19:49:50 1.13 @@ -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 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,16 +25,82 @@ #include #include -/* convert materialname to materialtype_t */ +//+GPL + +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; + 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; +} +/* convert materialname to materialtype_t */ materialtype_t * -name_to_material (const shstr_cmp name) +name_to_material (const shstr_tmp name) { for (materialtype_t *mt = materialt; mt; mt = mt->next) if (name == mt->name) return mt; - return 0; + LOG (llevError, "name_to_material called with nonexistent material '%s'\n", &name); + + // create a new material of the given 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; } /* when doing transmutation of objects, we have to recheck the resistances, @@ -43,60 +109,48 @@ 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 +161,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 +173,137 @@ 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 +load_materials () +{ + //TODO: somehow free old materials, or update them in-place + // currently we effectively leak them. + material_null.next = 0; materialt = &material_null; + + object_thawer thawer (settings.datadir, "materials"); + + if (!thawer) + { + LOG (llevError, "Cannot open %s for reading\n", thawer.name); + goto done; + } + + while (thawer.kw != KW_name) + { + thawer.next (); + + if (thawer.kw == KW_EOF) + goto done; + } + + materialtype_t *mt; + + for (;;) + { + switch (thawer.kw) + { + case KW_name: + mt = new materialtype_t; + thawer.get (mt->name); + mt->description = mt->name; + + mt->next = materialt; materialt = mt; + 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: + goto done; + + default: + if (!thawer.parse_error ("materials file")) + goto done; + break; } + + thawer.next (); } + +done: + LOG (llevDebug, "Done.\n"); }