Crossfire Server, Trunk
button.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 <stdlib.h>
22 #include <string.h>
23 
24 #include "sproto.h"
25 
26 static objectlink *get_button_links(const object *button);
27 
41 void trigger_connected(objectlink *ol, object *cause, const int state) {
42  object *tmp;
43 
44  for (; ol; ol = ol->next) {
45  object *part;
46 
47  if (!ol->ob || ol->ob->count != ol->id) {
48  LOG(llevError, "Internal error in trigger_connect. No object associated with link id (%u) (cause='%s'.\n", ol->id, (cause && cause->name) ? cause->name : "");
49  continue;
50  }
51  /* a button link object can become freed when the map is saving. As
52  * a map is saved, objects are removed and freed, and if an object is
53  * on top of a button, this function is eventually called. If a map
54  * is getting moved out of memory, the status of buttons and levers
55  * probably isn't important - it will get sorted out when the map is
56  * re-loaded. As such, just exit this function if that is the case.
57  */
58 
59  if (QUERY_FLAG(ol->ob, FLAG_FREED))
60  return;
61  tmp = ol->ob;
62 
63  /* if the criteria isn't appropriate, don't do anything */
65  continue;
67  continue;
68 
69  if (events_execute_object_event(tmp, EVENT_TRIGGER, cause, NULL, NULL, SCRIPT_FIX_ALL) != 0)
70  continue;
71 
72  switch (tmp->type) {
73  case GATE:
74  case HOLE:
75  tmp->value = tmp->stats.maxsp ? !state : state;
76  tmp->speed = 0.5;
78  break;
79 
80  case CF_HANDLE:
81  SET_ANIMATION(tmp, (tmp->value = tmp->stats.maxsp ? !state : state));
83  break;
84 
85  case SIGN:
86  if (!tmp->stats.food || tmp->last_eat < tmp->stats.food) {
89  tmp->msg);
90  if (tmp->stats.food)
91  tmp->last_eat++;
92  }
93  break;
94 
95  case ALTAR:
96  tmp->value = 1;
97  SET_ANIMATION(tmp, tmp->value);
99  break;
100 
101  case BUTTON:
102  case PEDESTAL:
103  tmp->value = state;
104  SET_ANIMATION(tmp, tmp->value);
106  break;
107 
108  case TIMED_GATE:
109  for (part = tmp; tmp != NULL; tmp = tmp->more) {
110  part->speed = tmp->arch->clone.speed;
111  part->value = tmp->arch->clone.value;
112  part->stats.sp = 1;
113  part->stats.hp = tmp->stats.maxhp;
114  object_update_speed(part);
115  }
116  break;
117 
118  case DIRECTOR:
119  if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */
120  tmp->stats.sp = ((tmp->stats.sp-1)%8)+1;
122  break;
123  case FIREWALL:
124  // Since director is broken out, we don't need to check on firewall type now
125  if (!QUERY_FLAG(tmp, FLAG_ANIMATE)/* && tmp->type == FIREWALL*/)
127  else {
128  if ((tmp->direction += tmp->stats.maxsp) > 8) /* next direction */
129  tmp->direction = ((tmp->direction-1)%8)+1;
131  }
132  break;
133 
134 
135  default:
136  ob_trigger(tmp, cause, state);
137  }
138  }
139 }
140 
149 void push_button(object *op) {
150  /* LOG(llevDebug, "push_button: %s (%d)\n", op->name, op->count); */
152 }
153 
162 void update_button(object *op) {
163  object *tmp, *head;
164  int tot, any_down = 0, old_value = op->value;
165  objectlink *ol;
166 
167  /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */
168  for (ol = get_button_links(op); ol; ol = ol->next) {
169  if (!ol->ob || ol->ob->count != ol->id) {
170  LOG(llevDebug, "Internal error in update_button (%s).\n", op->name);
171  continue;
172  }
173 
174  tmp = ol->ob;
175  if (tmp->type == BUTTON) {
176  tot = 0;
178  /* Bug? The pedestal code below looks for the head of
179  * the object, this bit doesn't. I'd think we should check
180  * for head here also. Maybe it also makese sense to
181  * make the for ab=tmp->above loop common, and alter
182  * behaviour based on object within that loop?
183  */
184 
185  /* Basically, if the move_type matches that on what the
186  * button wants, we count it. The second check is so that
187  * objects don't move (swords, etc) will count. Note that
188  * this means that more work is needed to make buttons
189  * that are only triggered by flying objects.
190  */
191  if ((ab->move_type&tmp->move_on) || ab->move_type == 0)
192  tot += ab->weight*NROF(ab)+ab->carrying;
194 
195  tmp->value = (tot >= tmp->weight) ? 1 : 0;
196  if (tmp->value)
197  any_down = 1;
198  } else if (tmp->type == PEDESTAL) {
199  tmp->value = 0;
200  FOR_ABOVE_PREPARE(tmp, ab) {
201  head = ab->head ? ab->head : ab;
202  /* Same note regarding move_type for buttons above apply here. */
203  if (((head->move_type&tmp->move_on) || ab->move_type == 0)
204  && (head->race == tmp->slaying
205  || ((head->type == SPECIAL_KEY) && (head->slaying == tmp->slaying))
206  || (!strcmp(tmp->slaying, "player") && head->type == PLAYER)))
207  tmp->value = 1;
208  } FOR_ABOVE_FINISH();
209  if (tmp->value)
210  any_down = 1;
211  }
212  }
213  if (any_down) /* If any other buttons were down, force this to remain down */
214  op->value = 1;
215 
216  /* If this button hasn't changed, don't do anything */
217  if (op->value != old_value) {
218  SET_ANIMATION(op, op->value);
220  push_button(op); /* Make all other buttons the same */
221  }
222 }
223 
228  objectlink *ol;
229  oblinkpt *obp;
230 
231  for (obp = m->buttons; obp; obp = obp->next)
232  for (ol = obp->link; ol; ol = ol->next) {
233  if (!ol->ob || ol->ob->count != ol->id) {
234  LOG(llevError, "Internal error in update_button (%s (%dx%d):%u, connected %ld).\n",
235  ol->ob ? ol->ob->name : "null",
236  ol->ob ? ol->ob->x : -1,
237  ol->ob ? ol->ob->y : -1,
238  ol->id,
239  obp->value);
240  continue;
241  }
242  if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL) {
243  update_button(ol->ob);
244  break;
245  }
246  }
247 }
248 
254 void use_trigger(object *op) {
255  /* Toggle value */
256  op->value = !op->value;
257  push_button(op);
258 }
259 
270 void animate_turning(object *op) {
271  if (++op->state >= NUM_ANIMATIONS(op)/8)
272  op->state = 0;
273  // Firewalls use direction instead of sp to avoid issues involving the spell transference.
274  if (op->type == FIREWALL){
275  SET_ANIMATION(op, (op->direction-1)*NUM_ANIMATIONS(op)/8+op->state);
276  }
277  else {
278  SET_ANIMATION(op, (op->stats.sp-1)*NUM_ANIMATIONS(op)/8+op->state);
279  }
281 }
282 
283 #define ARCH_SACRIFICE(xyz) ((xyz)->slaying)
284 #define NROF_SACRIFICE(xyz) ((uint32_t)(xyz)->stats.food)
285 
297 static int matches_sacrifice(const object *altar, const object *sacrifice) {
298  char name[MAX_BUF];
299 
300  if ((QUERY_FLAG(sacrifice, FLAG_ALIVE) && object_value_set(altar, "accept_alive") == false)
301  || QUERY_FLAG(sacrifice, FLAG_IS_LINKED)
302  || sacrifice->type == PLAYER)
303  return 0;
304 
305  query_base_name(sacrifice, 0, name, MAX_BUF);
306  if (ARCH_SACRIFICE(altar) == sacrifice->arch->name
307  || ARCH_SACRIFICE(altar) == sacrifice->name
308  || ARCH_SACRIFICE(altar) == sacrifice->slaying
309  || (!strcmp(ARCH_SACRIFICE(altar), name)))
310  return 1;
311 
312  if (strcmp(ARCH_SACRIFICE(altar), "money") == 0
313  && sacrifice->type == MONEY)
314  return 1;
315 
316  return 0;
317 }
318 
347 int check_altar_sacrifice(const object *altar, const object *sacrifice, int remove_others, int *toremove) {
348  int money;
349  uint32_t wanted, rest;
350 
351  if (!matches_sacrifice(altar, sacrifice))
352  /* New dropped object doesn't match the altar, other objects already on top are not enough to
353  * activate altar, else they would have disappeared. */
354  return 0;
355 
356  /* Check item is paid for. */
357  if (QUERY_FLAG(sacrifice, FLAG_UNPAID)) {
358  return 0;
359  }
360 
361  money = (strcmp(ARCH_SACRIFICE(altar), "money") == 0) ? 1 : 0;
362 
363  /* Easy checks: newly dropped object is enough for sacrifice. */
364  if (money && sacrifice->nrof*sacrifice->value >= NROF_SACRIFICE(altar)) {
365  if (toremove) {
366  *toremove = NROF_SACRIFICE(altar)/sacrifice->value;
367  /* Round up any sacrifices. Altars don't make change either */
368  if (NROF_SACRIFICE(altar)%sacrifice->value)
369  (*toremove)++;
370  }
371  return 1;
372  }
373 
374  if (!money && NROF_SACRIFICE(altar) <= NROF(sacrifice)) {
375  if (toremove)
376  *toremove = NROF_SACRIFICE(altar);
377  return 1;
378  }
379 
380  if (money) {
381  wanted = NROF_SACRIFICE(altar)-sacrifice->nrof*sacrifice->value;
382  } else {
383  wanted = NROF_SACRIFICE(altar)-NROF(sacrifice);
384  }
385  rest = wanted;
386 
387  /* Ok, now we check if we got enough with other items.
388  * We only check items above altar, and not checking again sacrifice.
389  */
391  if (wanted <= 0)
392  break;
393  if (tmp == sacrifice || !matches_sacrifice(altar, tmp))
394  continue;
395  if (money)
396  wanted -= tmp->nrof*tmp->value;
397  else
398  wanted -= NROF(tmp);
399  } FOR_ABOVE_FINISH();
400 
401  if (wanted > 0)
402  /* Not enough value, let's bail out. */
403  return 0;
404 
405  /* From there on, we do have enough objects for the altar. */
406 
407  /* Last dropped object will be totally eaten in any case. */
408  if (toremove)
409  *toremove = NROF(sacrifice);
410 
411  if (!remove_others)
412  return 1;
413 
414  /* We loop again, this time to remove what we need. */
416  if (rest <= 0)
417  break;
418  if (tmp == sacrifice || !matches_sacrifice(altar, tmp))
419  continue;
420  if (money) {
421  wanted = tmp->nrof*tmp->value;
422  if (rest > wanted) {
424  rest -= wanted;
425  } else {
426  wanted = rest/tmp->value;
427  if (rest%tmp->value)
428  wanted++;
429  object_decrease_nrof(tmp, wanted);
430  return 1;
431  }
432  } else
433  if (rest > NROF(tmp)) {
434  rest -= NROF(tmp);
436  } else {
438  return 1;
439  }
440  } FOR_ABOVE_FINISH();
441 
442  /* Something went wrong, we'll be nice and accept the sacrifice anyway. */
443  LOG(llevError, "check_altar_sacrifice on %s: found objects to sacrifice, but couldn't remove them??\n", altar->map->path);
444  return 1;
445 }
446 
463 int operate_altar(object *altar, object **sacrifice) {
464  int number;
465 
466  if (!altar->map) {
467  LOG(llevError, "BUG: operate_altar(): altar has no map\n");
468  return 0;
469  }
470 
471  if (!altar->slaying || altar->value)
472  return 0;
473 
474  if (!check_altar_sacrifice(altar, *sacrifice, 1, &number))
475  return 0;
476 
477  /* check_altar_sacrifice fills in number for us. */
478  *sacrifice = object_decrease_nrof(*sacrifice, number);
479 
480  if (altar->msg)
482  return 1;
483 }
484 
488 static void trigger_move(object *op, int state) { /* 1 down and 0 up */
489  op->stats.wc = state;
490  if (state) {
491  use_trigger(op);
492  if (op->stats.exp > 0) /* check sanity */
493  op->speed = 1.0/op->stats.exp;
494  else
495  op->speed = 1.0;
497  op->speed_left = -1;
498  } else {
499  use_trigger(op);
500  op->speed = 0;
502  }
503 }
504 
518 int check_trigger(object *op, object *cause) {
519  int push = 0, tot = 0;
520  int in_movement = op->stats.wc || op->speed;
521 
522  switch (op->type) {
523  case TRIGGER_BUTTON:
524  if (op->weight > 0) {
525  if (cause) {
527  /* Comment reproduced from update_buttons():
528  * Basically, if the move_type matches that on what the
529  * button wants, we count it. The second check is so that
530  * objects that don't move (swords, etc) will count. Note that
531  * this means that more work is needed to make buttons
532  * that are only triggered by flying objects.
533  */
534  if ((tmp->move_type&op->move_on) || tmp->move_type == 0) {
535  tot += tmp->weight*NROF(tmp)+tmp->carrying;
536  }
538  if (tot >= op->weight)
539  push = 1;
540  if (op->stats.ac == push)
541  return 0;
542  op->stats.ac = push;
543  if (NUM_ANIMATIONS(op) > 1) {
546  }
547  if (in_movement || !push)
548  return 0;
549  }
550  trigger_move(op, push);
551  }
552  return 0;
553 
554  case TRIGGER_PEDESTAL:
555  if (cause) {
557  object *head = tmp->head ? tmp->head : tmp;
558 
559  /* See comment in TRIGGER_BUTTON about move_types */
560  if (((head->move_type&op->move_on) || head->move_type == 0)
561  && (head->race == op->slaying || (!strcmp(op->slaying, "player") && head->type == PLAYER))) {
562  push = 1;
563  break;
564  }
565  } FOR_ABOVE_FINISH();
566  if (op->stats.ac == push)
567  return 0;
568  op->stats.ac = push;
569  if (NUM_ANIMATIONS(op) > 1) {
572  }
573  if (in_movement || !push)
574  return 0;
575  }
576  trigger_move(op, push);
577  return 0;
578 
579  case TRIGGER_ALTAR:
580  if (cause) {
581  if (in_movement)
582  return 0;
583  if (operate_altar(op, &cause)) {
584  if (NUM_ANIMATIONS(op) > 1) {
585  SET_ANIMATION(op, 1);
587  }
588 
589  if (op->last_sp >= 0) {
590  trigger_move(op, 1);
591  if (op->last_sp > 0)
592  op->last_sp = -op->last_sp;
593  } else {
594  /* for trigger altar with last_sp, the ON/OFF
595  * status (-> +/- value) is "simulated":
596  */
597  op->value = !op->value;
598  trigger_move(op, 1);
599  op->last_sp = -op->last_sp;
600  op->value = !op->value;
601  }
602  return cause == NULL;
603  } else {
604  return 0;
605  }
606  } else {
607  if (NUM_ANIMATIONS(op) > 1) {
608  SET_ANIMATION(op, 0);
610  }
611 
612  /* If trigger_altar has "last_sp > 0" set on the map,
613  * it will push the connected value only once per sacrifice.
614  * Otherwise (default), the connected value will be
615  * pushed twice: First by sacrifice, second by reset! -AV
616  */
617  if (!op->last_sp)
618  trigger_move(op, 0);
619  else {
620  op->stats.wc = 0;
621  op->value = !op->value;
622  op->speed = 0;
624  }
625  }
626  return 0;
627 
628  case TRIGGER:
629  if (cause) {
630  if (in_movement)
631  return 0;
632  push = 1;
633  }
634  if (NUM_ANIMATIONS(op) > 1) {
637  }
638  trigger_move(op, push);
639  return 1;
640 
641  default:
642  LOG(llevDebug, "Unknown trigger type: %s (%d)\n", op->name, op->type);
643  return 0;
644  }
645 }
646 
656 void add_button_link(object *button, mapstruct *map, int connected) {
657  oblinkpt *obp;
658  objectlink *ol = get_objectlink();
659 
660  if (!map) {
661  LOG(llevError, "Tried to add button-link without map.\n");
662  free_objectlink(ol);
663  return;
664  }
665 
666  SET_FLAG(button, FLAG_IS_LINKED);
667 
668  ol->ob = button;
669  ol->id = button->count;
670 
671  for (obp = map->buttons; obp && obp->value != connected; obp = obp->next)
672  ;
673 
674  if (obp) {
675  ol->next = obp->link;
676  obp->link = ol;
677  } else {
678  obp = get_objectlinkpt();
679  obp->value = connected;
680 
681  obp->next = map->buttons;
682  map->buttons = obp;
683  obp->link = ol;
684  }
685 }
686 
693 void remove_button_link(object *op) {
694  oblinkpt *obp;
695  objectlink **olp, *ol;
696 
697  if (op->map == NULL) {
698  LOG(llevError, "remove_button_link() in object without map.\n");
699  return;
700  }
701  if (!QUERY_FLAG(op, FLAG_IS_LINKED)) {
702  LOG(llevError, "remove_button_linked() in unlinked object.\n");
703  return;
704  }
705 
706  for (obp = op->map->buttons; obp; obp = obp->next)
707  for (olp = &obp->link; (ol = *olp); olp = &ol->next)
708  if (ol->ob == op) {
709 /* LOG(llevDebug, "Removed link %d in button %s and map %s.\n",
710  obp->value, op->name, op->map->path);
711 */
712  *olp = ol->next;
713  free(ol);
714  return;
715  }
716  LOG(llevError, "remove_button_linked(): couldn't find object.\n");
718 }
719 
727 static objectlink *get_button_links(const object *button) {
728  oblinkpt *obp;
729  objectlink *ol;
730 
731  if (!button->map)
732  return NULL;
733 
734  for (obp = button->map->buttons; obp; obp = obp->next)
735  for (ol = obp->link; ol; ol = ol->next)
736  if (ol->ob == button && ol->id == button->count)
737  return obp->link;
738  return NULL;
739 }
740 
749 int get_button_value(const object *button) {
750  oblinkpt *obp;
751  objectlink *ol;
752 
753  if (!button->map)
754  return 0;
755 
756  for (obp = button->map->buttons; obp; obp = obp->next)
757  for (ol = obp->link; ol; ol = ol->next)
758  if (ol->ob == button && ol->id == button->count)
759  return obp->value;
760  return 0;
761 }
762 
782 object *check_inv_recursive(object *op, const object *trig) {
783  object *ret = NULL;
784 
785  /* First check the object itself. */
786  if ((!trig->stats.hp || (op->type == trig->stats.hp))
787  && (!trig->slaying || (op->slaying == trig->slaying))
788  && (!trig->race || (op->arch->name == trig->race))
789  && (!trig->title || (op->title == trig->title))
791  return op;
792 
794  if (tmp->inv) {
795  ret = check_inv_recursive(tmp, trig);
796  if (ret)
797  return ret;
798  } else if ((!trig->stats.hp || (tmp->type == trig->stats.hp))
799  && (!trig->slaying || (tmp->slaying == trig->slaying))
800  && (!trig->race || (tmp->arch->name == trig->race))
801  && (!trig->title || (tmp->title == trig->title))
803  return tmp;
804  } FOR_INV_FINISH();
805 
806  return NULL;
807 }
808 
809 
825 void check_inv(object *op, object *trig) {
826  object *match;
827 
828  if (op->type != PLAYER)
829  return;
830 
831  match = check_inv_recursive(op, trig);
832  if (match && trig->last_sp) {
833  if (trig->last_heal)
835  use_trigger(trig);
836  } else if (!match && !trig->last_sp)
837  use_trigger(trig);
838 }
UP_OBJ_FACE
#define UP_OBJ_FACE
Definition: object.h:519
TRIGGER
@ TRIGGER
Definition: object.h:129
PLAYER
@ PLAYER
Definition: object.h:107
global.h
CF_HANDLE
@ CF_HANDLE
Definition: object.h:208
object_remove
void object_remove(object *op)
Definition: object.c:1819
llevError
@ llevError
Definition: logger.h:11
NROF_SACRIFICE
#define NROF_SACRIFICE(xyz)
Definition: button.c:284
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
BUTTON
@ BUTTON
Definition: object.h:207
object_update
void object_update(object *op, int action)
Definition: object.c:1420
obj::count
tag_t count
Definition: object.h:302
obj::map
struct mapdef * map
Definition: object.h:300
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
obj::race
sstring race
Definition: object.h:321
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:134
obj::value
int32_t value
Definition: object.h:355
ring_occidental_mages.rest
rest
Definition: ring_occidental_mages.py:16
TIMED_GATE
@ TIMED_GATE
Definition: object.h:128
liv::hp
int16_t hp
Definition: living.h:40
SET_ANIMATION
#define SET_ANIMATION(ob, newanim)
Definition: global.h:159
check_altar_sacrifice
int check_altar_sacrifice(const object *altar, const object *sacrifice, int remove_others, int *toremove)
Definition: button.c:347
oblinkpt::link
struct oblnk * link
Definition: object.h:456
Ice.tmp
int tmp
Definition: Ice.py:207
NDI_NAVY
#define NDI_NAVY
Definition: newclient.h:244
matches_sacrifice
static int matches_sacrifice(const object *altar, const object *sacrifice)
Definition: button.c:297
get_button_links
static objectlink * get_button_links(const object *button)
Definition: button.c:727
oblinkpt
Definition: object.h:455
mapdef::buttons
oblinkpt * buttons
Definition: map.h:347
FOR_ABOVE_PREPARE
#define FOR_ABOVE_PREPARE(op_, it_)
Definition: define.h:687
SIGN
@ SIGN
Definition: object.h:211
ext_info_map
void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1)
Definition: main.c:335
TRIGGER_BUTTON
@ TRIGGER_BUTTON
Definition: object.h:132
push_button
void push_button(object *op)
Definition: button.c:149
remove_button_link
void remove_button_link(object *op)
Definition: button.c:693
events_execute_object_event
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Definition: events.cpp:274
push.connected
connected
Definition: push.py:59
FLAG_ACTIVATE_ON_PUSH
#define FLAG_ACTIVATE_ON_PUSH
Definition: define.h:362
obj::nrof
uint32_t nrof
Definition: object.h:337
FLAG_ALIVE
#define FLAG_ALIVE
Definition: define.h:230
obj::last_heal
int32_t last_heal
Definition: object.h:362
obj::slaying
sstring slaying
Definition: object.h:322
m
static event_registration m
Definition: citylife.cpp:427
NROF
static uint32_t NROF(const object *const ob)
Definition: object.h:611
operate_altar
int operate_altar(object *altar, object **sacrifice)
Definition: button.c:463
disinfect.map
map
Definition: disinfect.py:4
object_decrease_nrof_by_one
#define object_decrease_nrof_by_one(xyz)
Definition: compat.h:32
oblnk::next
struct oblnk * next
Definition: object.h:448
obj::name
sstring name
Definition: object.h:314
oblinkpt::next
struct oblinkpt * next
Definition: object.h:458
push
void push(String_Array *array, const char *string)
Definition: bwp.c:311
FOR_ABOVE_FINISH
#define FOR_ABOVE_FINISH()
Definition: define.h:694
EVENT_TRIGGER
#define EVENT_TRIGGER
Definition: events.h:33
oblinkpt::value
long value
Definition: object.h:457
FLAG_FREED
#define FLAG_FREED
Definition: define.h:233
SCRIPT_FIX_ALL
#define SCRIPT_FIX_ALL
Definition: global.h:377
trigger_move
static void trigger_move(object *op, int state)
Definition: button.c:488
SPECIAL_KEY
@ SPECIAL_KEY
Definition: object.h:124
check_inv
void check_inv(object *op, object *trig)
Definition: button.c:825
HOLE
@ HOLE
Definition: object.h:209
obj::x
int16_t x
Definition: object.h:330
move_firewall
void move_firewall(object *op)
Definition: main.c:344
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
obj::speed
float speed
Definition: object.h:332
push.match
bool match
Definition: push.py:61
check_inv_recursive
object * check_inv_recursive(object *op, const object *trig)
Definition: button.c:782
sproto.h
mapdef
Definition: map.h:317
MSG_SUBTYPE_NONE
#define MSG_SUBTYPE_NONE
Definition: newclient.h:420
oblnk::id
tag_t id
Definition: object.h:449
NDI_BLACK
#define NDI_BLACK
Definition: newclient.h:242
animate_turning
void animate_turning(object *op)
Definition: button.c:270
MAX_BUF
#define MAX_BUF
Definition: define.h:35
MSG_TYPE_DIALOG
#define MSG_TYPE_DIALOG
Definition: newclient.h:400
check_trigger
int check_trigger(object *op, object *cause)
Definition: button.c:518
obj::y
int16_t y
Definition: object.h:330
obj::title
sstring title
Definition: object.h:320
obj::arch
struct archt * arch
Definition: object.h:417
altar_valkyrie.altar
altar
Definition: altar_valkyrie.py:27
obj::type
uint8_t type
Definition: object.h:343
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
obj::stats
living stats
Definition: object.h:373
use_trigger
void use_trigger(object *op)
Definition: button.c:254
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
add_button_link
void add_button_link(object *button, mapstruct *map, int connected)
Definition: button.c:656
FIREWALL
@ FIREWALL
Definition: object.h:168
TRIGGER_ALTAR
@ TRIGGER_ALTAR
Definition: object.h:133
get_button_value
int get_button_value(const object *button)
Definition: button.c:749
give.op
op
Definition: give.py:33
object_value_set
bool object_value_set(const object *op, const char *const key)
Definition: object.c:4347
trigger_connected
void trigger_connected(objectlink *ol, object *cause, const int state)
Definition: button.c:41
update_button
void update_button(object *op)
Definition: button.c:162
FLAG_ACTIVATE_ON_RELEASE
#define FLAG_ACTIVATE_ON_RELEASE
Definition: define.h:363
query_base_name
void query_base_name(const object *op, int plural, char *buf, size_t size)
Definition: item.c:686
obj::last_sp
int32_t last_sp
Definition: object.h:363
PEDESTAL
@ PEDESTAL
Definition: object.h:121
oblnk::ob
object * ob
Definition: object.h:447
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
NUM_ANIMATIONS
#define NUM_ANIMATIONS(ob)
Definition: global.h:168
object_update_speed
void object_update_speed(object *op)
Definition: object.c:1330
obj::head
struct obj * head
Definition: object.h:299
obj::move_type
MoveType move_type
Definition: object.h:429
DIRECTOR
@ DIRECTOR
Definition: object.h:222
FLAG_ANIMATE
#define FLAG_ANIMATE
Definition: define.h:242
ALTAR
@ ALTAR
Definition: object.h:122
FLAG_UNPAID
#define FLAG_UNPAID
Definition: define.h:236
quest.state
state
Definition: quest.py:13
object_decrease_nrof
object * object_decrease_nrof(object *op, uint32_t i)
Definition: object.c:2652
push
Definition: push.py:1
archt::name
sstring name
Definition: object.h:470
ARCH_SACRIFICE
#define ARCH_SACRIFICE(xyz)
Definition: button.c:283
FLAG_IS_LINKED
#define FLAG_IS_LINKED
Definition: define.h:315
MSG_TYPE_SIGN
#define MSG_TYPE_SIGN
Definition: newclient.h:398
update_buttons
void update_buttons(mapstruct *m)
Definition: button.c:227
oblnk
Definition: object.h:446
MSG_TYPE_DIALOG_ALTAR
#define MSG_TYPE_DIALOG_ALTAR
Definition: newclient.h:488
liv::sp
int16_t sp
Definition: living.h:42
ob_trigger
method_ret ob_trigger(object *op, object *cause, int state)
Definition: ob_methods.c:133
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
llevDebug
@ llevDebug
Definition: logger.h:13
MONEY
@ MONEY
Definition: object.h:137
GATE
@ GATE
Definition: object.h:206
give.name
name
Definition: give.py:27