Atrinik Server  4.0
object_methods.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 
30 #include <global.h>
31 #include <plugin.h>
32 #include <arch.h>
33 #include <player.h>
34 #include <object.h>
35 #include <object_methods.h>
36 
40 static object_methods_t object_type_methods[OBJECT_TYPE_MAX];
41 
46 
51 
52 #define OBJECT_TYPE_DECLARE
53 #include <object_type_list.h>
54 #undef OBJECT_TYPE_DECLARE
55 
62 static void
64 {
65  memset(methods, 0, sizeof(*methods));
66 }
67 
71 void
73 {
74  object_methods_init_one(&object_methods_base);
75  object_methods_base.apply_func =
77  object_methods_base.describe_func =
78  common_object_describe;
79  object_methods_base.process_func =
81  object_methods_base.move_on_func =
83  object_methods_base.projectile_fire_func =
85  object_methods_base.projectile_move_func =
87  object_methods_base.projectile_hit_func =
89  object_methods_base.projectile_stop_func =
91 
92  for (size_t i = 0; i < arraysize(object_type_methods); i++) {
93  object_methods_init_one(&object_type_methods[i]);
94  object_type_methods[i].fallback = &object_methods_base;
95  }
96 
97 #include <object_type_list.h>
98 }
99 
110 {
111  SOFT_ASSERT_RC(type >= 0 && type < OBJECT_TYPE_MAX,
112  &object_methods_base,
113  "Invalid object type: %d",
114  type);
115  return &object_type_methods[type];
116 }
117 
119 void
120 object_cb_init (object *op)
121 {
122  HARD_ASSERT(op != NULL);
123  HARD_ASSERT(op->head == NULL);
124 
125  for (object_methods_t *methods = &object_type_methods[op->type];
126  methods != NULL;
127  methods = methods->fallback) {
128  if (methods->init_func != NULL) {
129  methods->init_func(op);
130  break;
131  }
132  }
133 }
134 
136 void
137 object_cb_deinit (object *op)
138 {
139  HARD_ASSERT(op != NULL);
140  HARD_ASSERT(op->head == NULL);
141 
142  for (object_methods_t *methods = &object_type_methods[op->type];
143  methods != NULL;
144  methods = methods->fallback) {
145  if (methods->deinit_func != NULL) {
146  methods->deinit_func(op);
147  break;
148  }
149  }
150 }
151 
153 int
154 object_apply (object *op, object *applier, int aflags)
155 {
156  HARD_ASSERT(op != NULL);
157  HARD_ASSERT(applier != NULL);
158 
159  applier = HEAD(applier);
160 
161  for (object_methods_t *methods = &object_type_methods[op->type];
162  methods != NULL;
163  methods = methods->fallback) {
164  if (methods->apply_func != NULL) {
165  return methods->apply_func(op, applier, aflags);
166  }
167  }
168 
170 }
171 
173 void
174 object_process (object *op)
175 {
176  HARD_ASSERT(op != NULL);
177 
178  /* No need to process objects inside creators. */
179  if (op->env != NULL && op->env->type == CREATOR) {
180  return;
181  }
182 
183  if (common_object_process_pre(op)) {
184  return;
185  }
186 
187  if (HAS_EVENT(op, EVENT_TIME) &&
188  trigger_event(EVENT_TIME, NULL, op, NULL, NULL, 0, 0, 0, 0) != 0) {
189  return;
190  }
191 
192  for (object_methods_t *methods = &object_type_methods[op->type];
193  methods != NULL;
194  methods = methods->fallback) {
195  if (methods->process_func != NULL) {
196  methods->process_func(op);
197  return;
198  }
199  }
200 }
201 
203 char *
204 object_describe (object *op, object *observer, char *buf, size_t size)
205 {
206  HARD_ASSERT(op != NULL);
207  HARD_ASSERT(observer != NULL);
208  HARD_ASSERT(buf != NULL);
209 
210  for (object_methods_t *methods = &object_type_methods[op->type];
211  methods != NULL;
212  methods = methods->fallback) {
213  if (methods->describe_func != NULL) {
214  methods->describe_func(op, observer, buf, size);
215  return buf;
216  }
217  }
218 
219  buf[0] = '\0';
220  return buf;
221 }
222 
224 int
225 object_move_on (object *op, object *victim, object *originator, int state)
226 {
227  HARD_ASSERT(op != NULL);
228  HARD_ASSERT(victim != NULL);
229 
230  op = HEAD(op);
231  victim = HEAD(victim);
232 
234  victim,
235  op,
236  originator,
237  NULL,
238  0,
239  0,
240  0,
241  0) != 0) {
242  return OBJECT_METHOD_OK;
243  }
244 
245  for (object_methods_t *methods = &object_type_methods[op->type];
246  methods != NULL;
247  methods = methods->fallback) {
248  if (methods->move_on_func != NULL) {
249  if (object_move_on_recursion_depth >= 500) {
250  LOG(INFO,
251  "Aborting recursion, op: %s, victim: %s",
252  object_get_str(op),
253  object_get_str(victim));
254  return OBJECT_METHOD_OK;
255  }
256 
258  int ret = methods->move_on_func(op, victim, originator, state);
260 
261  return ret;
262  }
263  }
264 
266 }
267 
269 int
270 object_trigger (object *op, object *cause, int state)
271 {
272  HARD_ASSERT(op != NULL);
273  HARD_ASSERT(cause != NULL);
274 
275  for (object_methods_t *methods = &object_type_methods[op->type];
276  methods != NULL;
277  methods = methods->fallback) {
278  if (methods->trigger_func != NULL) {
279  return methods->trigger_func(op, cause, state);
280  }
281  }
282 
284 }
285 
287 int
288 object_trigger_button (object *op, object *cause, int state)
289 {
290  HARD_ASSERT(op != NULL);
291  HARD_ASSERT(cause != NULL);
292 
293  for (object_methods_t *methods = &object_type_methods[op->type];
294  methods != NULL;
295  methods = methods->fallback) {
296  if (methods->trigger_button_func != NULL) {
297  return methods->trigger_button_func(op, cause, state);
298  }
299  }
300 
302 }
303 
305 void
307 {
308  HARD_ASSERT(op != NULL);
309 
310  for (object_methods_t *methods = &object_type_methods[op->type];
311  methods != NULL;
312  methods = methods->fallback) {
313  if (methods->insert_map_func != NULL) {
314  methods->insert_map_func(op);
315  return;
316  }
317  }
318 }
319 
321 void
323 {
324  HARD_ASSERT(op != NULL);
325 
326  for (object_methods_t *methods = &object_type_methods[op->type];
327  methods != NULL;
328  methods = methods->fallback) {
329  if (methods->remove_map_func != NULL) {
330  methods->remove_map_func(op);
331  return;
332  }
333  }
334 }
335 
337 void
339 {
340  HARD_ASSERT(op != NULL);
341 
342  for (object_methods_t *methods = &object_type_methods[op->type];
343  methods != NULL;
344  methods = methods->fallback) {
345  if (methods->remove_inv_func != NULL) {
346  methods->remove_inv_func(op);
347  return;
348  }
349  }
350 }
351 
353 object *
354 object_projectile_fire (object *op, object *shooter, int dir)
355 {
356  HARD_ASSERT(op != NULL);
357  HARD_ASSERT(shooter != NULL);
358 
359  for (object_methods_t *methods = &object_type_methods[op->type];
360  methods != NULL;
361  methods = methods->fallback) {
362  if (methods->projectile_fire_func != NULL) {
363  return methods->projectile_fire_func(op, shooter, dir);
364  }
365  }
366 
367  return NULL;
368 }
369 
371 object *
373 {
374  HARD_ASSERT(op != NULL);
375 
376  for (object_methods_t *methods = &object_type_methods[op->type];
377  methods != NULL;
378  methods = methods->fallback) {
379  if (methods->projectile_move_func != NULL) {
380  return methods->projectile_move_func(op);
381  }
382  }
383 
384  return NULL;
385 }
386 
388 int
389 object_projectile_hit (object *op, object *victim)
390 {
391  HARD_ASSERT(op != NULL);
392  HARD_ASSERT(victim != NULL);
393 
394  for (object_methods_t *methods = &object_type_methods[op->type];
395  methods != NULL;
396  methods = methods->fallback) {
397  if (methods->projectile_hit_func != NULL) {
398  return methods->projectile_hit_func(op, victim);
399  }
400  }
401 
403 }
404 
406 object *
407 object_projectile_stop (object *op, int reason)
408 {
409  HARD_ASSERT(op != NULL);
410 
411  if (trigger_event(EVENT_STOP, NULL, op, NULL, NULL, 0, 0, 0, 0) != 0) {
412  return op;
413  }
414 
415  for (object_methods_t *methods = &object_type_methods[op->type];
416  methods != NULL;
417  methods = methods->fallback) {
418  if (methods->projectile_stop_func != NULL) {
419  return methods->projectile_stop_func(op, reason);
420  }
421  }
422 
423  return NULL;
424 }
425 
427 int
428 object_ranged_fire (object *op, object *shooter, int dir, double *delay)
429 {
430  HARD_ASSERT(op != NULL);
431  HARD_ASSERT(shooter != NULL);
432 
433  /* No direction, try to get a direction to the player's target, if any. */
434  if (dir == 0 &&
435  op->type == BOW &&
436  shooter->type == PLAYER &&
437  OBJECT_VALID(CONTR(shooter)->target_object,
438  CONTR(shooter)->target_object_count)) {
439  dir = object_dir_to_target(shooter, CONTR(shooter)->target_object);
440  }
441 
442  if (dir == 0) {
443  dir = shooter->direction;
444  SOFT_ASSERT_RC(dir != 0,
446  "Direction is zero, op: %s, shooter: %s",
447  object_get_str(op),
448  object_get_str(shooter));
449  }
450 
451  if (QUERY_FLAG(shooter, FLAG_CONFUSED)) {
452  dir = get_randomized_dir(dir);
453  }
454 
455  shooter->direction = dir;
456 
457  for (object_methods_t *methods = &object_type_methods[op->type];
458  methods != NULL;
459  methods = methods->fallback) {
460  if (methods->ranged_fire_func != NULL) {
461  return methods->ranged_fire_func(op, shooter, dir, delay);
462  }
463  }
464 
466 }
467 
469 void
470 object_auto_apply (object *op)
471 {
472  HARD_ASSERT(op != NULL);
473  HARD_ASSERT(QUERY_FLAG(op, FLAG_AUTO_APPLY));
474 
476 
477  if (op->env != NULL && op->env->type == PLAYER) {
478  LOG(ERROR,
479  "Object with auto_apply (%s) found in %s.",
480  object_get_str(op),
481  object_get_str(op->env));
482  return;
483  }
484 
485  for (object_methods_t *methods = &object_type_methods[op->type];
486  methods != NULL;
487  methods = methods->fallback) {
488  if (methods->auto_apply_func != NULL) {
489  methods->auto_apply_func(op);
490  return;
491  }
492  }
493 
494  log_error("Object with auto_apply flag was not handled: %s",
495  object_get_str(op));
496 }
497 
499 int
501  object **ret,
502  int difficulty,
503  treasure_affinity_t *affinity,
504  int flags)
505 {
506  HARD_ASSERT(op != NULL);
507  HARD_ASSERT(ret != NULL);
508  SOFT_ASSERT_RC(difficulty > 0,
510  "Invalid difficulty: %d",
511  difficulty);
512 
513  if (op->arch == NULL) {
514  log_error("Object has no arch: %s", object_get_str(op));
515  object_remove(op, 0);
516  object_destroy(op);
517  return OBJECT_METHOD_ERROR;
518  }
519 
520  *ret = op;
521 
522  for (object_methods_t *methods = &object_type_methods[op->type];
523  methods != NULL;
524  methods = methods->fallback) {
525  if (methods->process_treasure_func != NULL) {
526  return methods->process_treasure_func(op,
527  ret,
528  difficulty,
529  affinity,
530  flags);
531  }
532  }
533 
535 }
int common_object_apply(object *op, object *applier, int aflags)
Definition: apply.c:51
void object_destroy(object *ob)
Definition: object.c:1441
int object_move_on(object *op, object *victim, object *originator, int state)
object *(* projectile_stop_func)(object *op, int reason)
void object_process(object *op)
static object_methods_t object_methods_base
void object_auto_apply(object *op)
object_methods_t * object_methods_get(int type)
int trigger_event(int event_type, object *const activator, object *const me, object *const other, const char *msg, int parm1, int parm2, int parm3, int flags)
Definition: plugins.c:510
#define CREATOR
Definition: define.h:242
uint8_t type
One of operation types.
Definition: sound_ambient.c:45
int get_randomized_dir(int dir)
Definition: move.c:53
object * common_object_projectile_move(object *op)
Definition: projectile.c:152
int(* move_on_func)(object *op, object *victim, object *originator, int state)
#define BOW
Definition: define.h:174
object * object_projectile_move(object *op)
#define OBJECT_METHOD_ERROR
void(* describe_func)(object *op, object *observer, char *buf, size_t size)
int(* apply_func)(object *op, object *applier, int aflags)
static int object_move_on_recursion_depth
#define HAS_EVENT(ob, event)
Definition: plugin.h:179
#define PLAYER
Definition: define.h:122
#define QUERY_FLAG(xyz, p)
Definition: define.h:761
#define EVENT_TIME
Definition: plugin.h:89
struct archetype * arch
Definition: object.h:225
void object_cb_remove_map(object *op)
static object_methods_t object_type_methods[OBJECT_TYPE_MAX]
void object_remove(object *op, int flags)
Definition: object.c:1623
char * object_describe(object *op, object *observer, char *buf, size_t size)
int common_object_move_on(object *op, object *victim, object *originator, int state)
Definition: move_on.c:37
int object_projectile_hit(object *op, object *victim)
#define EVENT_TRIGGER
Definition: plugin.h:93
int object_apply(object *op, object *applier, int aflags)
const char * object_get_str(const object *op)
Definition: object.c:3151
int8_t direction
Definition: object.h:350
int object_trigger_button(object *op, object *cause, int state)
struct obj * env
Definition: object.h:130
void common_object_process(object *op)
Definition: process.c:165
object * common_object_projectile_stop_missile(object *op, int reason)
Definition: projectile.c:182
int common_object_projectile_hit(object *op, object *victim)
Definition: projectile.c:344
object * object_projectile_fire(object *op, object *shooter, int dir)
#define HEAD(op)
Definition: object.h:657
#define OBJECT_METHOD_UNHANDLED
void(* process_func)(object *op)
int common_object_process_pre(object *op)
Definition: process.c:123
int object_ranged_fire(object *op, object *shooter, int dir, double *delay)
object * common_object_projectile_fire_missile(object *op, object *shooter, int dir)
Definition: projectile.c:301
void object_methods_init(void)
object *(* projectile_move_func)(object *op)
void object_cb_remove_inv(object *op)
void object_cb_deinit(object *op)
uint8_t type
Definition: object.h:360
#define CLEAR_FLAG(xyz, p)
Definition: define.h:751
int object_process_treasure(object *op, object **ret, int difficulty, treasure_affinity_t *affinity, int flags)
int(* projectile_hit_func)(object *op, object *victim)
object *(* projectile_fire_func)(object *op, object *shooter, int dir)
#define OBJECT_METHOD_OK
#define OBJECT_VALID(_ob_, _count_)
Definition: object.h:548
struct object_methods * fallback
struct obj * head
Definition: object.h:136
int object_trigger(object *op, object *cause, int state)
#define FLAG_CONFUSED
Definition: define.h:872
object * object_projectile_stop(object *op, int reason)
#define FLAG_AUTO_APPLY
Definition: define.h:938
#define EVENT_STOP
Definition: plugin.h:87
void object_cb_init(object *op)
int object_dir_to_target(object *op, object *target)
Definition: object.c:2310
void object_cb_insert_map(object *op)
static void object_methods_init_one(object_methods_t *methods)
static PyMethodDef methods[]