Crossfire Server, Trunk  R20513
potion.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #include "global.h"
20 
21 #include <string.h>
22 
23 #include "ob_methods.h"
24 #include "ob_types.h"
25 #include "sounds.h"
26 #include "sproto.h"
27 
28 static method_ret potion_type_apply(ob_methods *context, object *potion,
29  object *applier, int aflags);
30 
34 void init_type_potion(void) {
36 }
37 
46 static method_ret potion_type_apply(ob_methods *context, object *potion,
47  object *applier, int aflags) {
48  int got_one = 0, i;
49  object *force;
50 
51  if (applier->type == PLAYER) {
52  if (!QUERY_FLAG(potion, FLAG_IDENTIFIED))
53  potion = identify(potion);
54  }
55 
56  apply_handle_yield(potion);
57 
58  /* Potion of restoration - only for players */
59  if (applier->type == PLAYER && (potion->attacktype&AT_DEPLETE)) {
60  if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) {
61  drain_stat(applier);
62  fix_object(applier);
64  return METHOD_OK;
65  }
66 
67  if (remove_depletion(applier, potion->level) == 0)
69  "Your potion had no effect.");
70 
72  return METHOD_OK;
73  }
74 
75  /* improvement potion - only for players */
76  if (applier->type == PLAYER && potion->attacktype&AT_GODPOWER) {
77  for (i = 1; i < MIN(11, applier->level); i++) {
78  if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) {
79  if (applier->contr->levhp[i] != 1) {
80  applier->contr->levhp[i] = 1;
81  break;
82  }
83  if (applier->contr->levsp[i] != 1) {
84  applier->contr->levsp[i] = 1;
85  break;
86  }
87  if (applier->contr->levgrace[i] != 1) {
88  applier->contr->levgrace[i] = 1;
89  break;
90  }
91  } else {
92  if (applier->contr->levhp[i] < 9) {
93  applier->contr->levhp[i] = 9;
94  break;
95  }
96  if (applier->contr->levsp[i] < 6) {
97  applier->contr->levsp[i] = 6;
98  break;
99  }
100  if (applier->contr->levgrace[i] < 3) {
101  applier->contr->levgrace[i] = 3;
102  break;
103  }
104  }
105  }
106  /* Just makes checking easier */
107  if (i < MIN(11, applier->level))
108  got_one = 1;
109  if (!QUERY_FLAG(potion, FLAG_CURSED) && !QUERY_FLAG(potion, FLAG_DAMNED)) {
110  if (got_one) {
111  fix_object(applier);
113  "The Gods smile upon you and remake you a little more in their image."
114  "You feel a little more perfect.");
115  } else
117  "The potion had no effect - you are already perfect");
118  } else { /* cursed potion */
119  if (got_one) {
120  fix_object(applier);
122  "The Gods are angry and punish you.");
123  } else
125  "You are fortunate that you are so pathetic.");
126  }
128  return METHOD_OK;
129  }
130 
131  /* A potion that casts a spell. Healing, restore spellpoint
132  * (power potion) and heroism all fit into this category.
133  * Given the spell object code, there is no limit to the number
134  * of spells that potions can be cast, but direction is
135  * problematic to try and imbue fireball potions for example.
136  */
137  if (potion->inv) {
138  if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) {
139  object *fball;
140 
142  "Yech! Your lungs are on fire!");
143  /* Explodes a fireball centered at player */
145  fball->dam_modifier = random_roll(1, applier->level, applier, PREFER_LOW)/5+1;
146  fball->stats.maxhp = random_roll(1, applier->level, applier, PREFER_LOW)/10+2;
147  object_insert_in_map_at(fball, applier->map, NULL, 0, applier->x, applier->y);
148  } else
149  cast_spell(applier, potion, applier->facing, potion->inv, NULL);
150 
152  /* if youre dead, no point in doing this... */
153  if (!QUERY_FLAG(applier, FLAG_REMOVED))
154  fix_object(applier);
155  return METHOD_OK;
156  }
157 
158  /* Deal with protection potions */
159  force = NULL;
160  for (i = 0; i < NROFATTACKS; i++) {
161  if (potion->resist[i]) {
162  if (!force)
163  force = create_archetype(FORCE_NAME);
164  memcpy(force->resist, potion->resist, sizeof(potion->resist));
165  force->type = POTION_RESIST_EFFECT;
166  force->speed = 0.2;
167  force->duration = 100;
168  break; /* Only need to find one protection since we cappliery entire batch */
169  }
170  }
171  /* This is a protection potion */
172  if (force) {
173  char name[MAX_BUF];
174  int resist = i;
175 
176  /* cursed items last longer */
177  if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) {
178  draw_ext_info_format(NDI_RED|NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_CURSED, "The %s was cursed!", potion->name);
179  force->duration *= 10;
180  for (i = 0; i < NROFATTACKS; i++)
181  if (force->resist[i] > 0)
182  force->resist[i] = -force->resist[i]; /* prot => vuln */
183  }
184  force->speed_left = -1;
185  /* set name for expiry messages */
186  snprintf(name, MAX_BUF, "resistance to %s", change_resist_msg[resist]);
187  free_string(force->name);
188  force->name = add_string(name);
189  store_spell_expiry(force);
190  force = object_insert_in_ob(force, applier);
191  CLEAR_FLAG(potion, FLAG_APPLIED);
192  SET_FLAG(force, FLAG_APPLIED);
193  change_abil(applier, force);
195 
196  if (potion->other_arch != NULL && applier->map != NULL) {
197  object_insert_in_map_at(arch_to_object(potion->other_arch), applier->map, NULL, INS_ON_TOP, applier->x, applier->y);
198  }
199 
200  return METHOD_OK;
201  }
202 
203  /* Only thing left are the stat potions */
204  if (applier->type == PLAYER) { /* only for players */
205  if ((QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED))
206  && potion->value != 0)
207  CLEAR_FLAG(potion, FLAG_APPLIED);
208  else
209  SET_FLAG(potion, FLAG_APPLIED);
210  if (!change_abil(applier, potion))
212  "Nothing happened.");
213  }
214 
215  /* CLEAR_FLAG is so that if the character has other potions
216  * that were grouped with the one consumed, his
217  * stat will not be raised by them. fix_object just clears
218  * up all the stats.
219  */
220  CLEAR_FLAG(potion, FLAG_APPLIED);
221  fix_object(applier);
223  return METHOD_OK;
224 }
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Sends message to player(s).
Definition: main.c:315
Sound-related defines.
#define FLAG_DAMNED
The object is very cursed.
Definition: define.h:318
void drain_stat(object *op)
Drains a random stat from op.
Definition: living.c:712
uint8_t dam_modifier
How going up in level affects damage.
Definition: object.h:407
#define AT_DEPLETE
Definition: attack.h:92
#define SET_FLAG(xyz, p)
Definition: define.h:223
Typedefs for ob_methods.
Definition: ob_methods.h:45
#define MSG_TYPE_APPLY_FAILURE
Apply OK, but no/bad result.
Definition: newclient.h:599
void apply_handle_yield(object *tmp)
This checks whether the object has a "on_use_yield" field, and if so generated and drops matching ite...
Definition: apply.c:125
static method_ret potion_type_apply(ob_methods *context, object *potion, object *applier, int aflags)
Handles applying a potion.
Definition: potion.c:46
#define EXPLODING_FIREBALL
This is used for fumbles - this arch is all set up to do the right just by inserting it...
Definition: spells.h:174
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.c:280
int8_t levsp[11]
What sp bonus the player gained on that level.
Definition: player.h:168
int16_t duration
How long the spell lasts.
Definition: object.h:403
#define PREFER_LOW
Definition: define.h:600
Global type definitions and header inclusions.
struct archt * other_arch
Pointer used for various things - mostly used for what this objects turns into or what this object cr...
Definition: object.h:413
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
#define MIN(x, y)
Definition: compat.h:17
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:232
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
int change_abil(object *op, object *tmp)
Permanently alters an object&#39;s stats/flags based on another object.
Definition: living.c:394
int16_t y
Position in the map for this object.
Definition: object.h:326
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.c:1921
#define NDI_RED
Definition: newclient.h:224
int16_t maxhp
Max hit points.
Definition: living.h:40
#define AT_GODPOWER
Definition: attack.h:96
object * create_archetype(const char *name)
Finds which archetype matches the given name, and returns a new object containing a copy of the arche...
Definition: arch.c:620
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
float speed_left
How much speed is left to spend this round.
Definition: object.h:329
#define INS_ON_TOP
Always put object on top.
Definition: object.h:571
#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
#define snprintf
Definition: win32.h:46
#define FLAG_IDENTIFIED
Player knows full info about item.
Definition: define.h:261
const char * name
The name of the object, obviously...
Definition: object.h:311
EXTERN const char *const change_resist_msg[NROFATTACKS]
Definition: attack.h:135
See Potion.
Definition: object.h:111
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
float speed
The overall speed of this object.
Definition: object.h:328
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
int16_t x
Definition: object.h:326
int8_t levhp[11]
What hp bonus the player gained on that level.
Definition: player.h:167
Object type variables.
int16_t resist[NROFATTACKS]
Resistance adjustments for attacks.
Definition: object.h:341
#define FLAG_CURSED
The object is cursed.
Definition: define.h:317
See Player.
Definition: object.h:107
void store_spell_expiry(object *spell)
Stores in the spell when to warn player of expiration.
Definition: spell_util.c:2006
const char * name
Usually monster-name/combination.
Definition: treasure.h:83
uint32_t attacktype
Bitmask of attacks this object does.
Definition: object.h:342
#define object_decrease_nrof_by_one(xyz)
Definition: compat.h:28
living stats
Str, Con, Dex, etc.
Definition: object.h:368
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
int remove_depletion(object *op, int level)
Remove depletion from op, if present, and warn player of such restorations.
Definition: living.c:751
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:235
#define NROFATTACKS
Definition: attack.h:17
#define MSG_TYPE_APPLY_SUCCESS
Was able to apply object.
Definition: newclient.h:598
#define FORCE_NAME
Definition: spells.h:169
sstring add_string(const char *str)
This will add &#39;str&#39; to the hash table.
Definition: shstr.c:124
object * identify(object *op)
Identifies an item.
Definition: item.c:1437
#define MSG_TYPE_APPLY_CURSED
Applied a cursed object (BAD)
Definition: newclient.h:600
struct obj * inv
Pointer to the first object in the inventory.
Definition: object.h:290
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:245
A force, holding the effect of a resistance potion.
Definition: object.h:225
int random_roll(int min, int max, const object *op, int goodbad)
Roll a random number between min and max.
Definition: utils.c:42
void init_type_potion(void)
Initializer for the potion object type.
Definition: potion.c:34
int8_t levgrace[11]
What grace bonus the player gained on that level.
Definition: player.h:169
Object type functions and variables.
int16_t level
Level of creature or object.
Definition: object.h:351
int8_t facing
Object is oriented/facing that way.
Definition: object.h:335
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.c:1120
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.c:571
int32_t value
How much money it is worth (or contains)
Definition: object.h:350
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Main dispatch when someone casts a spell.
Definition: spell_util.c:1471