Atrinik Server  4.0
apply.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
33 #include <global.h>
34 #include <object.h>
35 #include <player.h>
36 #include <object_methods.h>
37 
50 int
51 common_object_apply (object *op, object *applier, int aflags)
52 {
53  if (op->msg != NULL) {
54  draw_info(COLOR_WHITE, applier, op->msg);
55  return OBJECT_METHOD_OK;
56  }
57 
59 }
60 
72 static bool
73 object_apply_item_check_type (object *op, object *tmp)
74 {
75  if (!QUERY_FLAG(tmp, FLAG_APPLIED)) {
76  return false;
77  }
78 
79  if (op->type != CONTAINER &&
80  op->type == tmp->type &&
82  return true;
83  }
84 
85  if (OBJECT_IS_RANGED(op) && OBJECT_IS_RANGED(tmp)) {
86  return true;
87  }
88 
89  if (OBJECT_IS_AMMO(op) && OBJECT_IS_AMMO(tmp)) {
90  return true;
91  }
92 
93  return false;
94 }
95 
109 int
110 object_apply_item (object *op, object *applier, int aflags)
111 {
112  SOFT_ASSERT_RC(op != NULL, OBJECT_METHOD_UNHANDLED,
113  "Object to apply is NULL.");
114  SOFT_ASSERT_RC(applier != NULL, OBJECT_METHOD_UNHANDLED,
115  "Applier is NULL.");
116 
117  if (applier->type != PLAYER) {
119  }
120 
121  /* The item must be in the applier's inventory in order to be equipped. */
122  if (op->env != applier) {
123  return OBJECT_METHOD_ERROR;
124  }
125 
126  int basic_aflag = aflags & APPLY_BASIC_FLAGS;
127 
128  if (!QUERY_FLAG(op, FLAG_APPLIED)) {
129  if (QUERY_FLAG(op, FLAG_QUEST_ITEM)) {
130  draw_info(COLOR_WHITE, applier,
131  "You feel you should turn it in first...");
132  return OBJECT_METHOD_ERROR;
133  }
134  } else {
135  /* Always apply, so no reason to unapply. */
136  if (basic_aflag == APPLY_ALWAYS) {
137  return OBJECT_METHOD_OK;
138  }
139 
140  if (!(aflags & APPLY_IGNORE_CURSE) &&
141  (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED))) {
142  draw_info_format(COLOR_WHITE, applier,
143  "No matter how hard you try, you just can't "
144  "remove it!");
145  return OBJECT_METHOD_ERROR;
146  }
147 
148  if (QUERY_FLAG(op, FLAG_PERM_CURSED)) {
149  SET_FLAG(op, FLAG_CURSED);
150  }
151 
152  if (QUERY_FLAG(op, FLAG_PERM_DAMNED)) {
153  SET_FLAG(op, FLAG_DAMNED);
154  }
155 
157  esrv_update_item(UPD_FLAGS, op);
158  char *name = object_get_name_s(op, applier);
159 
160  switch (op->type) {
161  case WEAPON:
162  CLEAR_FLAG(applier, FLAG_READY_WEAPON);
163  draw_info_format(COLOR_WHITE, applier, "You unwield %s.", name);
164  break;
165 
166  case ARMOUR:
167  case HELMET:
168  case SHIELD:
169  case RING:
170  case BOOTS:
171  case GLOVES:
172  case AMULET:
173  case GIRDLE:
174  case BRACERS:
175  case CLOAK:
176  case PANTS:
177  case TRINKET:
178  draw_info_format(COLOR_WHITE, applier, "You unwear %s.", name);
179  break;
180 
181  case BOW:
182  case WAND:
183  case ROD:
184  case SPELL:
185  case SKILL:
186  case ARROW:
187  case CONTAINER:
188  draw_info_format(COLOR_WHITE, applier, "You unready %s.", name);
189  break;
190 
191  default:
192  draw_info_format(COLOR_WHITE, applier, "You unapply %s.", name);
193  break;
194  }
195 
196  efree(name);
197  living_update(applier);
198 
199  if (!(aflags & APPLY_NO_MERGE)) {
200  object_merge(op);
201  }
202 
203  return OBJECT_METHOD_OK;
204  }
205 
206  if (basic_aflag == APPLY_ALWAYS_UNAPPLY) {
207  return OBJECT_METHOD_OK;
208  }
209 
210  if (op->type != TRINKET) {
211  bool ring_left = false;
212 
213  /* This goes through and checks to see if the player already has
214  * something of that type applied - if so, unapply it. */
215  FOR_INV_PREPARE(applier, tmp) {
216  if (tmp == op || !object_apply_item_check_type(op, tmp)) {
217  continue;
218  }
219 
220  if (tmp->type == RING && !ring_left) {
221  ring_left = true;
222  continue;
223  }
224 
225  int ret = object_apply(tmp, applier, APPLY_ALWAYS_UNAPPLY);
226  if (ret != OBJECT_METHOD_OK) {
227  return OBJECT_METHOD_ERROR;
228  }
229  } FOR_INV_FINISH();
230  }
231 
232  if (!QUERY_FLAG(op, FLAG_CAN_STACK)) {
233  op = object_stack_get_reinsert(op, 1);
234  }
235 
236  char *name = object_get_name_s(op, applier);
237 
238  switch (op->type) {
239  case WEAPON:
240  if (!QUERY_FLAG(applier, FLAG_USE_WEAPON)) {
241  draw_info_format(COLOR_WHITE, applier, "You can't use %s.", name);
242  efree(name);
243  return OBJECT_METHOD_ERROR;
244  }
245 
246  draw_info_format(COLOR_WHITE, applier, "You wield %s.", name);
247  SET_FLAG(op, FLAG_APPLIED);
248  SET_FLAG(applier, FLAG_READY_WEAPON);
249  break;
250 
251  case SHIELD:
252  case ARMOUR:
253  case HELMET:
254  case BOOTS:
255  case GLOVES:
256  case GIRDLE:
257  case BRACERS:
258  case CLOAK:
259  case PANTS:
260  if (!QUERY_FLAG(applier, FLAG_USE_ARMOUR)) {
261  draw_info_format(COLOR_WHITE, applier, "You can't use %s.", name);
262  efree(name);
263  return OBJECT_METHOD_ERROR;
264  }
265 
266  case RING:
267  case AMULET:
268  case TRINKET:
269  draw_info_format(COLOR_WHITE, applier, "You wear %s.", name);
270  SET_FLAG(op, FLAG_APPLIED);
271  break;
272 
273  case WAND:
274  case ROD:
275  case BOW:
276  case SPELL:
277  case SKILL:
278  case ARROW:
279  case CONTAINER:
280  if (op->type == SPELL &&
281  SKILL_LEVEL(CONTR(applier), SK_WIZARDRY_SPELLS) < op->level) {
282  draw_info_format(COLOR_WHITE, applier,
283  "Your wizardry spells skill is too low to use %s.",
284  name);
285  efree(name);
286  return OBJECT_METHOD_ERROR;
287  }
288 
289  draw_info_format(COLOR_WHITE, applier, "You ready %s.", name);
290  SET_FLAG(op, FLAG_APPLIED);
291 
292  if (op->type == BOW) {
293  draw_info_format(COLOR_WHITE, applier,
294  "You will now fire %s with %s.",
295  op->race != NULL ? op->race : "nothing",
296  name);
297  }
298 
299  break;
300 
301  default:
302  draw_info_format(COLOR_WHITE, applier, "You apply %s.", name);
303  }
304 
305  efree(name);
306 
307  if (!QUERY_FLAG(op, FLAG_APPLIED)) {
308  SET_FLAG(op, FLAG_APPLIED);
309  }
310 
311  living_update(applier);
313 
314  if (QUERY_FLAG(op, FLAG_PERM_CURSED)) {
315  SET_FLAG(op, FLAG_CURSED);
316  }
317 
318  if (QUERY_FLAG(op, FLAG_PERM_DAMNED)) {
319  SET_FLAG(op, FLAG_DAMNED);
320  }
321 
322  esrv_update_item(UPD_FLAGS, op);
323 
324  if (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED)) {
325  draw_info(COLOR_WHITE, applier, "Oops, it feels deadly cold!");
326  }
327 
328  return OBJECT_METHOD_OK;
329 }
int common_object_apply(object *op, object *applier, int aflags)
Definition: apply.c:51
const char * race
Definition: object.h:174
#define FLAG_CURSED
Definition: define.h:1154
Always apply, never unapply.
Definition: define.h:1490
Allow unapplying cursed items.
Definition: define.h:1495
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:1691
#define FLAG_IS_THROWN
Definition: define.h:1170
#define FOR_INV_FINISH()
Definition: define.h:1698
#define WAND
Definition: define.h:445
#define GIRDLE
Definition: define.h:461
#define BOW
Definition: define.h:174
#define OBJECT_METHOD_ERROR
#define SHIELD
Definition: define.h:214
#define FLAG_PERM_CURSED
Definition: define.h:1306
#define FLAG_READY_WEAPON
Definition: define.h:1190
Always unapply, never apply.
Definition: define.h:1491
#define BRACERS
Definition: define.h:433
#define PLAYER
Definition: define.h:122
static bool object_apply_item_check_type(object *op, object *tmp)
Definition: apply.c:73
#define QUERY_FLAG(xyz, p)
Definition: define.h:761
#define FLAG_PERM_DAMNED
Definition: define.h:1310
int object_apply(object *op, object *applier, int aflags)
char * object_get_name_s(const object *op, const object *caller)
Definition: item.c:398
#define ARMOUR
Definition: define.h:182
#define FLAG_BEEN_APPLIED
Definition: define.h:934
#define FLAG_DAMNED
Definition: define.h:1158
#define FLAG_QUEST_ITEM
Definition: define.h:1233
Do not merge unapplied items.
Definition: define.h:1494
#define OBJECT_IS_RANGED(_ob)
Definition: object.h:828
#define FLAG_USE_WEAPON
Definition: define.h:1094
#define SET_FLAG(xyz, p)
Definition: define.h:741
struct obj * env
Definition: object.h:130
#define CONTAINER
Definition: define.h:493
#define ARROW
Definition: define.h:170
#define ROD
Definition: define.h:130
#define OBJECT_METHOD_UNHANDLED
object * object_merge(object *op)
Definition: object.c:479
#define FLAG_APPLIED
Definition: define.h:1182
int object_apply_item(object *op, object *applier, int aflags)
Definition: apply.c:110
#define RING
Definition: define.h:320
#define FLAG_CAN_STACK
Definition: define.h:1016
Used internally.
Definition: define.h:1492
void esrv_update_item(int flags, object *op)
Definition: item.c:639
#define SKILL
Definition: define.h:246
uint8_t type
Definition: object.h:360
#define CLEAR_FLAG(xyz, p)
Definition: define.h:751
#define WEAPON
Definition: define.h:178
const char * msg
Definition: object.h:183
int living_update(object *op)
Definition: living.c:1661
#define OBJECT_METHOD_OK
#define FLAG_USE_ARMOUR
Definition: define.h:1090
#define HELMET
Definition: define.h:218
#define BOOTS
Definition: define.h:413
#define GLOVES
Definition: define.h:417
#define PANTS
Definition: define.h:222
#define AMULET
Definition: define.h:234
#define CLOAK
Definition: define.h:381
int8_t level
Definition: object.h:347
#define OBJECT_IS_AMMO(_ob)
Definition: object.h:833
object * object_stack_get_reinsert(object *op, uint32_t nrof)
Definition: object.c:2046
#define SPELL
Definition: define.h:210