Crossfire Server, Branches 1.12  R18729
button.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_button_c =
3  * "$Id: button.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
5 
6 /*
7  CrossFire, A Multiplayer game for X-windows
8 
9  Copyright (C) 2002-2006 Mark Wedel & Crossfire Development Team
10  Copyright (C) 1992 Frank Tore Johansen
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 
26  The authors can be reached via e-mail at crossfire-devel@real-time.com
27 */
28 
34 #include <global.h>
35 #include <sproto.h>
36 
37 static objectlink *get_button_links(const object *button);
38 
52 void trigger_connected(objectlink *ol, object *cause, const int state) {
53  object *tmp;
54 
55  for (; ol; ol = ol->next) {
56  if (!ol->ob || ol->ob->count != ol->id) {
57  LOG(llevError, "Internal error in trigger_connect. No object associated with link id (%d) (cause='%s'.\n", ol->id, (cause && cause->name) ? cause->name : "");
58  continue;
59  }
60  /* a button link object can become freed when the map is saving. As
61  * a map is saved, objects are removed and freed, and if an object is
62  * on top of a button, this function is eventually called. If a map
63  * is getting moved out of memory, the status of buttons and levers
64  * probably isn't important - it will get sorted out when the map is
65  * re-loaded. As such, just exit this function if that is the case.
66  */
67 
68  if (QUERY_FLAG(ol->ob, FLAG_FREED))
69  return;
70  tmp = ol->ob;
71 
72  /* if the criteria isn't appropriate, don't do anything */
73  if (state && !QUERY_FLAG(tmp, FLAG_ACTIVATE_ON_PUSH))
74  continue;
75  if (!state && !QUERY_FLAG(tmp, FLAG_ACTIVATE_ON_RELEASE))
76  continue;
77 
78  /*
79  * (tchize) call the triggers of the activated object.
80  * tmp = activated object
81  * op is activator (aka button)
82  */
83  if (execute_event(tmp, EVENT_TRIGGER, cause, NULL, NULL, SCRIPT_FIX_ALL) != 0)
84  continue;
85 
86  switch (tmp->type) {
87  case GATE:
88  case HOLE:
89  tmp->value = tmp->stats.maxsp ? !state : state;
90  tmp->speed = 0.5;
91  update_ob_speed(tmp);
92  break;
93 
94  case CF_HANDLE:
95  SET_ANIMATION(tmp, (tmp->value = tmp->stats.maxsp ? !state : state));
97  break;
98 
99  case SIGN:
100  if (!tmp->stats.food || tmp->last_eat < tmp->stats.food) {
103  tmp->msg, tmp->msg);
104  if (tmp->stats.food)
105  tmp->last_eat++;
106  }
107  break;
108 
109  case ALTAR:
110  tmp->value = 1;
111  SET_ANIMATION(tmp, tmp->value);
113  break;
114 
115  case BUTTON:
116  case PEDESTAL:
117  tmp->value = state;
118  SET_ANIMATION(tmp, tmp->value);
120  break;
121 
122  case TIMED_GATE:
123  tmp->speed = tmp->arch->clone.speed;
124  update_ob_speed(tmp); /* original values */
125  tmp->value = tmp->arch->clone.value;
126  tmp->stats.sp = 1;
127  tmp->stats.hp = tmp->stats.maxhp;
128  /* Handle multipart gates. We copy the value for the other parts
129  * from the head - this ensures that the data will consistent
130  */
131  for (tmp = tmp->more; tmp != NULL; tmp = tmp->more) {
132  tmp->speed = tmp->head->speed;
133  tmp->value = tmp->head->value;
134  tmp->stats.sp = tmp->head->stats.sp;
135  tmp->stats.hp = tmp->head->stats.hp;
136  update_ob_speed(tmp);
137  }
138  break;
139 
140  case DIRECTOR:
141  case FIREWALL:
142  if (!QUERY_FLAG(tmp, FLAG_ANIMATE)&&tmp->type == FIREWALL)
143  move_firewall(tmp);
144  else {
145  if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */
146  tmp->stats.sp = ((tmp->stats.sp-1)%8)+1;
147  animate_turning(tmp);
148  }
149  break;
150 
151  default:
152  ob_trigger(tmp, cause, state);
153  }
154  }
155 }
156 
165 void push_button(object *op) {
166  /* LOG(llevDebug, "push_button: %s (%d)\n", op->name, op->count); */
168 }
169 
178 void update_button(object *op) {
179  object *ab, *tmp, *head;
180  int tot, any_down = 0, old_value = op->value;
181  objectlink *ol;
182 
183  /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */
184  for (ol = get_button_links(op); ol; ol = ol->next) {
185  if (!ol->ob || ol->ob->count != ol->id) {
186  LOG(llevDebug, "Internal error in update_button (%s).\n", op->name);
187  continue;
188  }
189 
190  tmp = ol->ob;
191  if (tmp->type == BUTTON) {
192  for (ab = tmp->above, tot = 0; ab != NULL; ab = ab->above)
193  /* Bug? The pedestal code below looks for the head of
194  * the object, this bit doesn't. I'd think we should check
195  * for head here also. Maybe it also makese sense to
196  * make the for ab=tmp->above loop common, and alter
197  * behaviour based on object within that loop?
198  */
199 
200  /* Basically, if the move_type matches that on what the
201  * button wants, we count it. The second check is so that
202  * objects don't move (swords, etc) will count. Note that
203  * this means that more work is needed to make buttons
204  * that are only triggered by flying objects.
205  */
206  if ((ab->move_type&tmp->move_on) || ab->move_type == 0)
207  tot += ab->weight*(ab->nrof ? ab->nrof : 1)+ab->carrying;
208 
209  tmp->value = (tot >= tmp->weight) ? 1 : 0;
210  if (tmp->value)
211  any_down = 1;
212  } else if (tmp->type == PEDESTAL) {
213  tmp->value = 0;
214  for (ab = tmp->above; ab != NULL; ab = ab->above) {
215  head = ab->head ? ab->head : ab;
216  /* Same note regarding move_type for buttons above apply here. */
217  if (((head->move_type&tmp->move_on) || ab->move_type == 0)
218  && (head->race == tmp->slaying
219  || ((head->type == SPECIAL_KEY) && (head->slaying == tmp->slaying))
220  || (!strcmp(tmp->slaying, "player") && head->type == PLAYER)))
221  tmp->value = 1;
222  }
223  if (tmp->value)
224  any_down = 1;
225  }
226  }
227  if (any_down) /* If any other buttons were down, force this to remain down */
228  op->value = 1;
229 
230  /* If this button hasn't changed, don't do anything */
231  if (op->value != old_value) {
232  SET_ANIMATION(op, op->value);
234  push_button(op); /* Make all other buttons the same */
235  }
236 }
237 
242  objectlink *ol;
243  oblinkpt *obp;
244 
245  for (obp = m->buttons; obp; obp = obp->next)
246  for (ol = obp->link; ol; ol = ol->next) {
247  if (!ol->ob || ol->ob->count != ol->id) {
248  LOG(llevError, "Internal error in update_button (%s (%dx%d):%d, connected %ld).\n",
249  ol->ob ? ol->ob->name : "null",
250  ol->ob ? ol->ob->x : -1,
251  ol->ob ? ol->ob->y : -1,
252  ol->id,
253  obp->value);
254  continue;
255  }
256  if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL) {
257  update_button(ol->ob);
258  break;
259  }
260  }
261 }
262 
268 void use_trigger(object *op) {
269  /* Toggle value */
270  op->value = !op->value;
271  push_button(op);
272 }
273 
284 void animate_turning(object *op) {
285  if (++op->state >= NUM_ANIMATIONS(op)/8)
286  op->state = 0;
287  SET_ANIMATION(op, (op->stats.sp-1)*NUM_ANIMATIONS(op)/8+op->state);
289 }
290 
291 #define ARCH_SACRIFICE(xyz) ((xyz)->slaying)
292 #define NROF_SACRIFICE(xyz) ((uint32)(xyz)->stats.food)
293 
305 static int matches_sacrifice(const object *altar, const object *sacrifice) {
306  char name[MAX_BUF];
307 
308  if (QUERY_FLAG(sacrifice, FLAG_ALIVE)
309  || QUERY_FLAG(sacrifice, FLAG_IS_LINKED)
310  || sacrifice->type == PLAYER)
311  return 0;
312 
313  query_base_name(sacrifice, 0, name, MAX_BUF);
314  if (ARCH_SACRIFICE(altar) == sacrifice->arch->name
315  || ARCH_SACRIFICE(altar) == sacrifice->name
316  || ARCH_SACRIFICE(altar) == sacrifice->slaying
317  || (!strcmp(ARCH_SACRIFICE(altar), name)))
318  return 1;
319 
320  if (strcmp(ARCH_SACRIFICE(altar), "money") == 0
321  && sacrifice->type == MONEY)
322  return 1;
323 
324  return 0;
325 }
326 
355 int check_altar_sacrifice(const object *altar, const object *sacrifice, int remove_others, int *toremove) {
356  int money;
357  object *tmp;
358  int wanted, rest;
359  object *above;
360 
361  if (!matches_sacrifice(altar, sacrifice))
362  /* New dropped object doesn't match the altar, other objects already on top are not enough to
363  * activate altar, else they would have disappeared. */
364  return 0;
365 
366  /* Check item is paid for. */
367  if (QUERY_FLAG(sacrifice, FLAG_UNPAID)) {
368  return 0;
369  }
370 
371  money = (strcmp(ARCH_SACRIFICE(altar), "money") == 0) ? 1 : 0;
372 
373  /* Easy checks: newly dropped object is enough for sacrifice. */
374  if (money && sacrifice->nrof*sacrifice->value >= NROF_SACRIFICE(altar)) {
375  if (toremove) {
376  *toremove = NROF_SACRIFICE(altar)/sacrifice->value;
377  /* Round up any sacrifices. Altars don't make change either */
378  if (NROF_SACRIFICE(altar)%sacrifice->value)
379  (*toremove)++;
380  }
381  return 1;
382  }
383 
384  if (!money && NROF_SACRIFICE(altar) <= (sacrifice->nrof ? sacrifice->nrof : 1)) {
385  if (toremove)
386  *toremove = NROF_SACRIFICE(altar);
387  return 1;
388  }
389 
390  if (money) {
391  wanted = NROF_SACRIFICE(altar)-sacrifice->nrof*sacrifice->value;
392  } else {
393  wanted = NROF_SACRIFICE(altar)-(sacrifice->nrof ? sacrifice->nrof : 1);
394  }
395  rest = wanted;
396 
397  /* Ok, now we check if we got enough with other items.
398  * We only check items above altar, and not checking again sacrifice.
399  */
400  for (tmp = altar->above; tmp != NULL && wanted > 0; tmp = tmp->above) {
401  if (tmp == sacrifice || !matches_sacrifice(altar, tmp))
402  continue;
403  if (money)
404  wanted -= tmp->nrof*tmp->value;
405  else
406  wanted -= (tmp->nrof ? tmp->nrof : 1);
407  }
408 
409  if (wanted > 0)
410  /* Not enough value, let's bail out. */
411  return 0;
412 
413  /* From there on, we do have enough objects for the altar. */
414 
415  /* Last dropped object will be totally eaten in any case. */
416  if (toremove)
417  *toremove = sacrifice->nrof ? sacrifice->nrof : 1;
418 
419  if (!remove_others)
420  return 1;
421 
422  /* We loop again, this time to remove what we need. */
423  for (tmp = altar->above; tmp != NULL && rest > 0; tmp = above) {
424  above = tmp->above;
425  if (tmp == sacrifice || !matches_sacrifice(altar, tmp))
426  continue;
427  if (money) {
428  wanted = tmp->nrof*tmp->value;
429  if (rest > wanted) {
430  remove_ob(tmp);
431  rest -= wanted;
432  } else {
433  wanted = rest/tmp->value;
434  if (rest%tmp->value)
435  wanted++;
436  decrease_ob_nr(tmp, wanted);
437  return 1;
438  }
439  } else
440  if (rest > (tmp->nrof ? tmp->nrof : 1)) {
441  rest -= (tmp->nrof ? tmp->nrof : 1);
442  remove_ob(tmp);
443  } else {
444  decrease_ob_nr(tmp, rest);
445  return 1;
446  }
447  }
448 
449  /* Something went wrong, we'll be nice and accept the sacrifice anyway. */
450  LOG(llevError, "check_altar_sacrifice on %s: found objects to sacrifice, but couldn't remove them??\n", altar->map->path);
451  return 1;
452 }
453 
470 int operate_altar(object *altar, object **sacrifice) {
471  int number;
472 
473  if (!altar->map) {
474  LOG(llevError, "BUG: operate_altar(): altar has no map\n");
475  return 0;
476  }
477 
478  if (!altar->slaying || altar->value)
479  return 0;
480 
481  if (!check_altar_sacrifice(altar, *sacrifice, 1, &number))
482  return 0;
483 
484  /* check_altar_sacrifice fills in number for us. */
485  *sacrifice = decrease_ob_nr(*sacrifice, number);
486 
487  if (altar->msg)
489  return 1;
490 }
491 
495 static void trigger_move(object *op, int state) { /* 1 down and 0 up */
496  op->stats.wc = state;
497  if (state) {
498  use_trigger(op);
499  if (op->stats.exp > 0) /* check sanity */
500  op->speed = 1.0/op->stats.exp;
501  else
502  op->speed = 1.0;
503  update_ob_speed(op);
504  op->speed_left = -1;
505  } else {
506  use_trigger(op);
507  op->speed = 0;
508  update_ob_speed(op);
509  }
510 }
511 
525 int check_trigger(object *op, object *cause) {
526  object *tmp;
527  int push = 0, tot = 0;
528  int in_movement = op->stats.wc || op->speed;
529 
530  switch (op->type) {
531  case TRIGGER_BUTTON:
532  if (op->weight > 0) {
533  if (cause) {
534  for (tmp = op->above; tmp; tmp = tmp->above)
535  /* Comment reproduced from update_buttons():
536  * Basically, if the move_type matches that on what the
537  * button wants, we count it. The second check is so that
538  * objects that don't move (swords, etc) will count. Note that
539  * this means that more work is needed to make buttons
540  * that are only triggered by flying objects.
541  */
542  if ((tmp->move_type&op->move_on) || tmp->move_type == 0) {
543  tot += tmp->weight*(tmp->nrof ? tmp->nrof : 1)+tmp->carrying;
544  }
545  if (tot >= op->weight)
546  push = 1;
547  if (op->stats.ac == push)
548  return 0;
549  op->stats.ac = push;
550  if (NUM_ANIMATIONS(op) > 1) {
551  SET_ANIMATION(op, push);
553  }
554  if (in_movement || !push)
555  return 0;
556  }
557  trigger_move(op, push);
558  }
559  return 0;
560 
561  case TRIGGER_PEDESTAL:
562  if (cause) {
563  for (tmp = op->above; tmp; tmp = tmp->above) {
564  object *head = tmp->head ? tmp->head : tmp;
565 
566  /* See comment in TRIGGER_BUTTON about move_types */
567  if (((head->move_type&op->move_on) || head->move_type == 0)
568  && (head->race == op->slaying || (!strcmp(op->slaying, "player") && head->type == PLAYER))) {
569  push = 1;
570  break;
571  }
572  }
573  if (op->stats.ac == push)
574  return 0;
575  op->stats.ac = push;
576  if (NUM_ANIMATIONS(op) > 1) {
577  SET_ANIMATION(op, push);
579  }
580  if (in_movement || !push)
581  return 0;
582  }
583  trigger_move(op, push);
584  return 0;
585 
586  case TRIGGER_ALTAR:
587  if (cause) {
588  if (in_movement)
589  return 0;
590  if (operate_altar(op, &cause)) {
591  if (NUM_ANIMATIONS(op) > 1) {
592  SET_ANIMATION(op, 1);
594  }
595 
596  if (op->last_sp >= 0) {
597  trigger_move(op, 1);
598  if (op->last_sp > 0)
599  op->last_sp = -op->last_sp;
600  } else {
601  /* for trigger altar with last_sp, the ON/OFF
602  * status (-> +/- value) is "simulated":
603  */
604  op->value = !op->value;
605  trigger_move(op, 1);
606  op->last_sp = -op->last_sp;
607  op->value = !op->value;
608  }
609  return cause == NULL;
610  } else {
611  return 0;
612  }
613  } else {
614  if (NUM_ANIMATIONS(op) > 1) {
615  SET_ANIMATION(op, 0);
617  }
618 
619  /* If trigger_altar has "last_sp > 0" set on the map,
620  * it will push the connected value only once per sacrifice.
621  * Otherwise (default), the connected value will be
622  * pushed twice: First by sacrifice, second by reset! -AV
623  */
624  if (!op->last_sp)
625  trigger_move(op, 0);
626  else {
627  op->stats.wc = 0;
628  op->value = !op->value;
629  op->speed = 0;
630  update_ob_speed(op);
631  }
632  }
633  return 0;
634 
635  case TRIGGER:
636  if (cause) {
637  if (in_movement)
638  return 0;
639  push = 1;
640  }
641  if (NUM_ANIMATIONS(op) > 1) {
642  SET_ANIMATION(op, push);
644  }
645  trigger_move(op, push);
646  return 1;
647 
648  default:
649  LOG(llevDebug, "Unknown trigger type: %s (%d)\n", op->name, op->type);
650  return 0;
651  }
652 }
653 
663 void add_button_link(object *button, mapstruct *map, int connected) {
664  oblinkpt *obp;
665  objectlink *ol = get_objectlink();
666 
667  if (!map) {
668  LOG(llevError, "Tried to add button-link without map.\n");
669  free_objectlink(ol);
670  return;
671  }
672 
673  SET_FLAG(button, FLAG_IS_LINKED);
674 
675  ol->ob = button;
676  ol->id = button->count;
677 
678  for (obp = map->buttons; obp && obp->value != connected; obp = obp->next)
679  ;
680 
681  if (obp) {
682  ol->next = obp->link;
683  obp->link = ol;
684  } else {
685  obp = get_objectlinkpt();
686  obp->value = connected;
687 
688  obp->next = map->buttons;
689  map->buttons = obp;
690  obp->link = ol;
691  }
692 }
693 
700 void remove_button_link(object *op) {
701  oblinkpt *obp;
702  objectlink **olp, *ol;
703 
704  if (op->map == NULL) {
705  LOG(llevError, "remove_button_link() in object without map.\n");
706  return;
707  }
708  if (!QUERY_FLAG(op, FLAG_IS_LINKED)) {
709  LOG(llevError, "remove_button_linked() in unlinked object.\n");
710  return;
711  }
712 
713  for (obp = op->map->buttons; obp; obp = obp->next)
714  for (olp = &obp->link; (ol = *olp); olp = &ol->next)
715  if (ol->ob == op) {
716 /* LOG(llevDebug, "Removed link %d in button %s and map %s.\n",
717  obp->value, op->name, op->map->path);
718 */
719  *olp = ol->next;
720  free(ol);
721  return;
722  }
723  LOG(llevError, "remove_button_linked(): couldn't find object.\n");
725 }
726 
734 static objectlink *get_button_links(const object *button) {
735  oblinkpt *obp;
736  objectlink *ol;
737 
738  if (!button->map)
739  return NULL;
740 
741  for (obp = button->map->buttons; obp; obp = obp->next)
742  for (ol = obp->link; ol; ol = ol->next)
743  if (ol->ob == button && ol->id == button->count)
744  return obp->link;
745  return NULL;
746 }
747 
756 int get_button_value(const object *button) {
757  oblinkpt *obp;
758  objectlink *ol;
759 
760  if (!button->map)
761  return 0;
762 
763  for (obp = button->map->buttons; obp; obp = obp->next)
764  for (ol = obp->link; ol; ol = ol->next)
765  if (ol->ob == button && ol->id == button->count)
766  return obp->value;
767  return 0;
768 }
769 
788 object *check_inv_recursive(object *op, const object *trig) {
789  object *tmp, *ret = NULL;
790 
791  /* First check the object itself. */
792  if ((!trig->stats.hp || (op->type == trig->stats.hp))
793  && (!trig->slaying || (op->slaying == trig->slaying))
794  && (!trig->race || (op->arch->name == trig->race))
795  && (!trig->title || (op->title == trig->title)))
796  return op;
797 
798  for (tmp = op->inv; tmp; tmp = tmp->below) {
799  if (tmp->inv) {
800  ret = check_inv_recursive(tmp, trig);
801  if (ret)
802  return ret;
803  } else if ((!trig->stats.hp || (tmp->type == trig->stats.hp))
804  && (!trig->slaying || (tmp->slaying == trig->slaying))
805  && (!trig->race || (tmp->arch->name == trig->race))
806  && (!trig->title || (tmp->title == trig->title)))
807  return tmp;
808  }
809 
810  return NULL;
811 }
812 
828 void check_inv(object *op, object *trig) {
829  object *match;
830 
831  if (op->type != PLAYER)
832  return;
833 
834  match = check_inv_recursive(op, trig);
835  if (match && trig->last_sp) {
836  if (trig->last_heal)
837  decrease_ob(match);
838  use_trigger(trig);
839  } else if (!match && !trig->last_sp)
840  use_trigger(trig);
841 }
842 
853 void verify_button_links(const mapstruct *map) {
854  oblinkpt *obp;
855  objectlink *ol;
856 
857  if (!map)
858  return;
859 
860  for (obp = map->buttons; obp; obp = obp->next) {
861  for (ol = obp->link; ol; ol = ol->next) {
862  if (ol->id != ol->ob->count)
863  LOG(llevError, "verify_button_links: object %s on list is corrupt (%d!=%d)\n", ol->ob->name, ol->id, ol->ob->count);
864  }
865  }
866 }
char path[HUGE_BUF]
Definition: map.h:384
#define FLAG_UNPAID
Definition: define.h:532
sint8 ac
Definition: living.h:79
#define UP_OBJ_FACE
Definition: object.h:356
#define FLAG_IS_LINKED
Definition: define.h:612
MoveType move_type
Definition: object.h:277
#define BUTTON
Definition: define.h:274
#define ARCH_SACRIFICE(xyz)
Definition: button.c:291
MoveType move_on
Definition: object.h:280
#define MSG_SUBTYPE_NONE
Definition: newclient.h:339
Definition: object.h:298
const char * race
Definition: object.h:171
static void trigger_move(object *op, int state)
Definition: button.c:495
void push_button(object *op)
Definition: button.c:165
#define SET_FLAG(xyz, p)
Definition: define.h:510
#define MONEY
Definition: define.h:148
#define NROF_SACRIFICE(xyz)
Definition: button.c:292
sint32 last_heal
Definition: object.h:208
void check_inv(object *op, object *trig)
Definition: button.c:828
#define SET_ANIMATION(ob, newanim)
Definition: global.h:247
void query_base_name(const object *op, int plural, char *buf, size_t size)
Definition: item.c:732
object clone
Definition: object.h:326
const char * slaying
Definition: object.h:172
#define MSG_TYPE_SIGN
Definition: newclient.h:320
sint32 last_sp
Definition: object.h:209
void update_object(object *op, int action)
Definition: object.c:1112
#define MSG_TYPE_DIALOG_ALTAR
Definition: newclient.h:406
sint64 exp
Definition: living.h:88
struct obj * above
Definition: object.h:146
sint16 x
Definition: object.h:179
sint16 sp
Definition: living.h:83
#define FLAG_ACTIVATE_ON_PUSH
Definition: define.h:667
#define NDI_BLACK
Definition: newclient.h:195
#define MSG_TYPE_DIALOG
Definition: newclient.h:322
#define SCRIPT_FIX_ALL
Definition: global.h:450
long value
Definition: object.h:309
tag_t id
Definition: object.h:301
#define PLAYER
Definition: define.h:113
sint16 maxsp
Definition: living.h:84
sint16 hp
Definition: living.h:81
struct oblnk * link
Definition: object.h:308
#define NDI_NAVY
Definition: newclient.h:197
#define SPECIAL_KEY
Definition: define.h:133
object * ob
Definition: object.h:299
const char * title
Definition: object.h:170
void remove_ob(object *op)
Definition: object.c:1515
sint16 maxhp
Definition: living.h:82
struct oblinkpt * next
Definition: object.h:310
#define FLAG_ALIVE
Definition: define.h:526
static int matches_sacrifice(const object *altar, const object *sacrifice)
Definition: button.c:305
float speed_left
Definition: object.h:182
sint32 weight
Definition: object.h:216
int check_altar_sacrifice(const object *altar, const object *sacrifice, int remove_others, int *toremove)
Definition: button.c:355
struct mapdef * map
Definition: object.h:155
sint32 carrying
Definition: object.h:218
void remove_button_link(object *op)
Definition: button.c:700
const char * name
Definition: object.h:167
#define PEDESTAL
Definition: define.h:129
struct obj * below
Definition: object.h:145
int operate_altar(object *altar, object **sacrifice)
Definition: button.c:470
void trigger_connected(objectlink *ol, object *cause, const int state)
Definition: button.c:52
uint32 nrof
Definition: object.h:184
void add_button_link(object *button, mapstruct *map, int connected)
Definition: button.c:663
sint16 y
Definition: object.h:179
void use_trigger(object *op)
Definition: button.c:268
#define TRIGGER_PEDESTAL
Definition: define.h:144
void update_buttons(mapstruct *m)
Definition: button.c:241
float speed
Definition: object.h:181
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
#define CLEAR_FLAG(xyz, p)
Definition: define.h:512
uint8 state
Definition: object.h:200
#define TRIGGER
Definition: define.h:139
#define TRIGGER_BUTTON
Definition: define.h:142
#define MAX_BUF
Definition: define.h:81
oblinkpt * buttons
Definition: map.h:373
#define FLAG_ACTIVATE_ON_RELEASE
Definition: define.h:668
sint32 last_eat
Definition: object.h:207
#define SIGN
Definition: define.h:280
sint8 wc
Definition: living.h:79
#define TIMED_GATE
Definition: define.h:138
void move_firewall(object *op)
Definition: standalone.c:188
#define TRIGGER_ALTAR
Definition: define.h:143
object * check_inv_recursive(object *op, const object *trig)
Definition: button.c:788
#define decrease_ob(xyz)
Definition: global.h:276
#define FLAG_ANIMATE
Definition: define.h:538
#define ALTAR
Definition: define.h:130
#define NUM_ANIMATIONS(ob)
Definition: global.h:255
#define FIREWALL
Definition: define.h:204
int get_button_value(const object *button)
Definition: button.c:756
tag_t count
Definition: object.h:157
living stats
Definition: object.h:219
struct archt * arch
Definition: object.h:263
struct oblnk * next
Definition: object.h:300
void verify_button_links(const mapstruct *map)
Definition: button.c:853
object * decrease_ob_nr(object *op, uint32 i)
Definition: object.c:2345
void animate_turning(object *op)
Definition: button.c:284
#define CF_HANDLE
Definition: define.h:275
int execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Definition: standalone.c:225
const char * msg
Definition: object.h:175
void update_button(object *op)
Definition: button.c:178
void update_ob_speed(object *op)
Definition: object.c:1008
struct obj * inv
Definition: object.h:148
#define NDI_UNIQUE
Definition: newclient.h:219
struct obj * head
Definition: object.h:154
#define DIRECTOR
Definition: define.h:294
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
#define HOLE
Definition: define.h:276
int check_trigger(object *op, object *cause)
Definition: button.c:525
method_ret ob_trigger(object *op, object *cause, int state)
Definition: ob_methods.c:144
static objectlink * get_button_links(const object *button)
Definition: button.c:734
Definition: map.h:346
#define GATE
Definition: define.h:273
void push(String_Array *array, const char *string)
Definition: bwp.c:310
struct obj * more
Definition: object.h:153
sint32 value
Definition: object.h:201
void ext_info_map(int color, const mapstruct *map, uint8 type, uint8 subtype, const char *str1, const char *str2)
Definition: standalone.c:184
const char * name
Definition: object.h:322
#define EVENT_TRIGGER
Definition: plugin.h:71
uint8 type
Definition: object.h:189
sint32 food
Definition: living.h:89
#define FLAG_FREED
Definition: define.h:529