Crossfire Server, Trunk  R20513
armour_improver.c
Go to the documentation of this file.
1 /*
2  CrossFire, A Multiplayer game for X-windows
3 
4  Copyright (C) 2007 Crossfire Development Team
5  Copyright (C) 1992 Frank Tore Johansen
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21  The authors can be reached via e-mail at crossfire-devel@real-time.com
22 */
23 
27 #include <global.h>
28 #include <ob_methods.h>
29 #include <ob_types.h>
30 #include <sounds.h>
31 #include <sproto.h>
32 
33 static method_ret armour_improver_type_apply(ob_methods *context, object *lighter, object *applier, int aflags);
34 
40 }
41 
58 static void improve_armour(object *op, object *improver, object *armour) {
59  object *tmp;
60  int oldmagic = armour->magic;
61 
62  if (armour->magic >= settings.armor_max_enchant) {
64  "This armour can not be enchanted any further.");
65  return;
66  }
67 
68  /* Dealing with random artifact armor is a lot trickier
69  * (in terms of value, weight, etc), so take the easy way out
70  * and don't worry about it. Note - maybe add scrolls which
71  * make the random artifact versions (eg, armour of gnarg and
72  * what not?) */
73  if (armour->title) {
75  "This armour will not accept further enchantment.");
76  return;
77  }
78 
79  /* Check item power: if player has it equipped, unequip if armor
80  * would become unwearable. */
81  if (QUERY_FLAG(armour, FLAG_APPLIED)
82  && op->type == PLAYER
83  && (op->contr->item_power+1) > (settings.item_power_factor*op->level)) {
84  apply_special(op, armour, AP_UNAPPLY);
85  if (QUERY_FLAG(armour, FLAG_APPLIED)) {
86  /* Armour is cursed, too bad */
89  "You can't enchant this armour without unapplying it because it would consume your soul!");
90  return;
91  }
92  }
93 
94  /* Split objects if needed. Can't insert tmp until the
95  * end of this function - otherwise it will just re-merge. */
96  if (armour->nrof > 1)
97  tmp = object_split(armour, armour->nrof-1, NULL, 0);
98  else
99  tmp = NULL;
100 
101  armour->magic++;
102 
104  int base = 100;
105  int pow = 0;
106 
107  while (pow < armour->magic) {
108  base = base-(base*settings.armor_speed_improvement)/100;
109  pow++;
110  }
111 
112  ARMOUR_SPEED(armour) = (ARMOUR_SPEED(&armour->arch->clone)*base)/100;
113  } else
114  ARMOUR_SPEED(armour) = (ARMOUR_SPEED(&armour->arch->clone)*(100+armour->magic*settings.armor_speed_improvement))/100;
115 
117  int base = 100;
118  int pow = 0;
119 
120  while (pow < armour->magic) {
121  base = base-(base*settings.armor_weight_reduction)/100;
122  pow++;
123  }
124  armour->weight = (armour->arch->clone.weight*base)/100;
125  } else
126  armour->weight = (armour->arch->clone.weight*(100-armour->magic*settings.armor_weight_reduction))/100;
127 
128  if (armour->weight <= 0) {
129  LOG(llevInfo, "Warning: enchanted armours can have negative weight\n.");
130  armour->weight = 1;
131  }
132 
133  armour->item_power += (armour->magic-oldmagic)*3;
134  if (armour->item_power < 0)
135  armour->item_power = 0;
136 
137  if (op->type == PLAYER) {
139  if (QUERY_FLAG(armour, FLAG_APPLIED))
140  fix_object(op);
141  }
142  object_decrease_nrof_by_one(improver);
143  if (tmp) {
144  object_insert_in_ob(tmp, op);
145  }
146  return;
147 }
148 
163 static method_ret armour_improver_type_apply(ob_methods *context, object *scroll, object *applier, int aflags) {
164  object *armor;
165 
166  if (applier->type != PLAYER)
167  return METHOD_UNHANDLED;
168 
169  if (!QUERY_FLAG(applier, FLAG_WIZCAST)
170  && (get_map_flags(applier->map, NULL, applier->x, applier->y, NULL, NULL)&P_NO_MAGIC)) {
172  "Something blocks the magic of the scroll.");
173  return METHOD_OK;
174  }
175  armor = find_marked_object(applier);
176  if (!armor) {
178  "You need to mark an armor object.");
179  return METHOD_OK;
180  }
181  if (armor->type != ARMOUR
182  && armor->type != CLOAK
183  && armor->type != BOOTS
184  && armor->type != GLOVES
185  && armor->type != BRACERS
186  && armor->type != SHIELD
187  && armor->type != HELMET) {
189  "Your marked item is not armour!");
190  return METHOD_OK;
191  }
192 
194  "Applying armour enchantment.");
195  improve_armour(applier, scroll, armor);
196  return METHOD_OK;
197 }
#define AP_UNAPPLY
Item is to be remvoed.
Definition: define.h:611
int apply_special(object *who, object *op, int aflags)
Apply an object.
Definition: apply.c:1082
Sound-related defines.
static method_ret armour_improver_type_apply(ob_methods *context, object *lighter, object *applier, int aflags)
Applies a scroll of Enchant Armour.
Information.
Definition: logger.h:12
Typedefs for ob_methods.
Definition: ob_methods.h:45
See Bracers.
Definition: object.h:217
See Cloak.
Definition: object.h:204
#define P_NO_MAGIC
Spells (some) can&#39;t pass this object.
Definition: map.h:227
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
Definition: main.c:342
object clone
An object from which to do object_copy()
Definition: object.h:470
See Helmet.
Definition: object.h:136
int armor_max_enchant
Maximum number of times an armor can be enchanted.
Definition: global.h:303
Global type definitions and header inclusions.
See Boots.
Definition: object.h:212
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: main.c:310
#define MSG_TYPE_APPLY
Applying objects.
Definition: newclient.h:384
char method_ret
Define some standard return values for callbacks which don&#39;t need to return any other results...
Definition: ob_methods.h:14
const char * title
Of foo, etc.
Definition: object.h:317
int16_t y
Position in the map for this object.
Definition: object.h:326
static void improve_armour(object *op, object *improver, object *armour)
This code deals with the armour improvment scrolls.
int armor_speed_improvement
Speed improvement.
Definition: global.h:306
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.c:2690
int32_t weight
Attributes of the object.
Definition: object.h:365
#define METHOD_OK
Definition: ob_methods.h:15
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
void init_type_armour_improver(void)
Initializer for the ARMOUR_IMPROVER object type.
#define MSG_TYPE_APPLY_ERROR
Definition: newclient.h:596
uint8_t armor_weight_linear
If 1, weight reduction is linear, else exponantiel.
Definition: global.h:305
#define ARMOUR_SPEED(xyz)
Definition: define.h:480
uint8_t armor_speed_linear
If 1, speed improvement is linear, else exponantiel.
Definition: global.h:307
uint32_t nrof
How many of the objects.
Definition: object.h:333
void register_apply(int ob_type, apply_func method)
Registers the apply method for the given type.
Definition: ob_types.c:62
struct pl * contr
Pointer to the player which control this object.
Definition: object.h:276
int8_t item_power
Power rating of the object.
Definition: object.h:362
object * find_marked_object(object *op)
Return the object the player has marked with the &#39;mark&#39; command below.
Definition: c_object.c:1256
#define UPD_WEIGHT
Definition: newclient.h:291
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define METHOD_UNHANDLED
Definition: ob_methods.h:16
int16_t x
Definition: object.h:326
Object type variables.
See Player.
Definition: object.h:107
See Shield.
Definition: object.h:135
object * object_split(object *orig_ob, uint32_t nr, char *err, size_t size)
object_split(ob,nr) splits up ob into two parts.
Definition: object.c:2463
#define object_decrease_nrof_by_one(xyz)
Definition: compat.h:28
int armor_weight_reduction
Weight reduction per enchantment.
Definition: global.h:304
#define UPD_NROF
Definition: newclient.h:296
#define FLAG_WIZCAST
The wizard can cast spells in no-magic area.
Definition: define.h:290
struct archt * arch
Pointer to archetype.
Definition: object.h:412
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
struct Settings settings
Server settings.
Definition: init.c:40
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:235
#define UPD_NAME
Definition: newclient.h:293
#define MSG_TYPE_APPLY_SUCCESS
Was able to apply object.
Definition: newclient.h:598
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
This rolls up wall, blocks_magic, blocks_view, etc, all into one function that just returns a P_...
Definition: map.c:302
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:245
See Gloves.
Definition: object.h:213
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
int16_t item_power
Total item power of objects equipped.
Definition: player.h:117
See Breastplate Armor.
Definition: object.h:120
Object type functions and variables.
int16_t level
Level of creature or object.
Definition: object.h:351
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.c:1120
int8_t magic
Any magical bonuses to this item.
Definition: object.h:348
float item_power_factor
See note in setings file.
Definition: global.h:301