Crossfire Server, Trunk  1.75.0
button.cpp
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 
23 #include "global.h"
24 
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "sproto.h"
29 
30 static objectlink *get_button_links(const object *button);
31 
45 void trigger_connected(objectlink *ol, object *cause, const int state) {
46  object *tmp;
47 
48  for (; ol; ol = ol->next) {
49  object *part;
50 
51  if (!ol->ob || ol->ob->count != ol->id) {
52  LOG(llevError, "Internal error in trigger_connect. No object associated with link id (%u) (cause='%s'.\n", ol->id, (cause && cause->name) ? cause->name : "");
53  continue;
54  }
55  /* a button link object can become freed when the map is saving. As
56  * a map is saved, objects are removed and freed, and if an object is
57  * on top of a button, this function is eventually called. If a map
58  * is getting moved out of memory, the status of buttons and levers
59  * probably isn't important - it will get sorted out when the map is
60  * re-loaded. As such, just exit this function if that is the case.
61  */
62 
63  if (QUERY_FLAG(ol->ob, FLAG_FREED))
64  return;
65  tmp = ol->ob;
66 
67  /* if the criteria isn't appropriate, don't do anything */
68  if (state && !QUERY_FLAG(tmp, FLAG_ACTIVATE_ON_PUSH))
69  continue;
70  if (!state && !QUERY_FLAG(tmp, FLAG_ACTIVATE_ON_RELEASE))
71  continue;
72 
73  if (events_execute_object_event(tmp, EVENT_TRIGGER, cause, NULL, NULL, SCRIPT_FIX_ALL) != 0)
74  continue;
75 
76  switch (tmp->type) {
77  case GATE:
78  case HOLE:
79  tmp->value = tmp->stats.maxsp ? !state : state;
80  tmp->speed = 0.5;
82  break;
83 
84  case CF_HANDLE:
85  SET_ANIMATION(tmp, (tmp->value = tmp->stats.maxsp ? !state : state));
87  break;
88 
89  case SIGN:
90  if (!tmp->stats.food || tmp->last_eat < tmp->stats.food) {
93  tmp->msg);
94  if (tmp->stats.food)
95  tmp->last_eat++;
96  }
97  break;
98 
99  case ALTAR:
100  tmp->value = 1;
101  SET_ANIMATION(tmp, tmp->value);
103  break;
104 
105  case BUTTON:
106  case PEDESTAL:
107  tmp->value = state;
108  SET_ANIMATION(tmp, tmp->value);
110  break;
111 
112  case TIMED_GATE:
113  for (part = tmp; tmp != NULL; tmp = tmp->more) {
114  part->speed = tmp->arch->clone.speed;
115  part->value = tmp->arch->clone.value;
116  part->stats.sp = 1;
117  part->stats.hp = tmp->stats.maxhp;
118  object_update_speed(part);
119  }
120  break;
121 
122  case DIRECTOR:
123  if ((tmp->stats.sp += tmp->stats.maxsp) > 8) /* next direction */
124  tmp->stats.sp = ((tmp->stats.sp-1)%8)+1;
125  animate_turning(tmp);
126  break;
127  case FIREWALL:
128  // Since director is broken out, we don't need to check on firewall type now
129  if (!QUERY_FLAG(tmp, FLAG_ANIMATE)/* && tmp->type == FIREWALL*/)
130  move_firewall(tmp);
131  else {
132  if ((tmp->direction += tmp->stats.maxsp) > 8) /* next direction */
133  tmp->direction = ((tmp->direction-1)%8)+1;
134  animate_turning(tmp);
135  }
136  break;
137 
138 
139  default:
140  ob_trigger(tmp, cause, state);
141  }
142  }
143 }
144 
150 void push_button(object *op) {
151  /* LOG(llevDebug, "push_button: %s (%d)\n", op->name, op->count); */
153 }
154 
163 void update_button(object *op) {
164  object *tmp, *head;
165  int tot, any_down = 0, old_value = op->value;
166  objectlink *ol;
167 
168  /* LOG(llevDebug, "update_button: %s (%d)\n", op->name, op->count); */
169  for (ol = get_button_links(op); ol; ol = ol->next) {
170  if (!ol->ob || ol->ob->count != ol->id) {
171  LOG(llevDebug, "Internal error in update_button (%s).\n", op->name);
172  continue;
173  }
174 
175  tmp = ol->ob;
176  if (tmp->type == BUTTON) {
177  tot = 0;
178  FOR_ABOVE_PREPARE(tmp, ab)
179  /* Bug? The pedestal code below looks for the head of
180  * the object, this bit doesn't. I'd think we should check
181  * for head here also. Maybe it also makese sense to
182  * make the for ab=tmp->above loop common, and alter
183  * behaviour based on object within that loop?
184  */
185 
186  /* Basically, if the move_type matches that on what the
187  * button wants, we count it. The second check is so that
188  * objects don't move (swords, etc) will count. Note that
189  * this means that more work is needed to make buttons
190  * that are only triggered by flying objects.
191  */
192  if ((ab->move_type&tmp->move_on) || ab->move_type == 0)
193  tot += ab->weight*NROF(ab)+ab->carrying;
195 
196  tmp->value = (tot >= tmp->weight) ? 1 : 0;
197  if (tmp->value)
198  any_down = 1;
199  } else if (tmp->type == PEDESTAL) {
200  tmp->value = 0;
201  FOR_ABOVE_PREPARE(tmp, ab) {
202  head = ab->head ? ab->head : ab;
203  /* Same note regarding move_type for buttons above apply here. */
204  if (((head->move_type&tmp->move_on) || ab->move_type == 0)
205  && (head->race == tmp->slaying
206  || ((head->type == SPECIAL_KEY) && (head->slaying == tmp->slaying))
207  || (!strcmp(tmp->slaying, "player") && head->type == PLAYER)))
208  tmp->value = 1;
209  } FOR_ABOVE_FINISH();
210  if (tmp->value)
211  any_down = 1;
212  }
213  }
214  if (any_down) /* If any other buttons were down, force this to remain down */
215  op->value = 1;
216 
217  /* If this button hasn't changed, don't do anything */
218  if (op->value != old_value) {
219  SET_ANIMATION(op, op->value);
221  push_button(op); /* Make all other buttons the same */
222  }
223 }
224 
229  objectlink *ol;
230  oblinkpt *obp;
231 
232  for (obp = m->buttons; obp; obp = obp->next)
233  for (ol = obp->link; ol; ol = ol->next) {
234  if (!ol->ob || ol->ob->count != ol->id) {
235  LOG(llevError, "Internal error in update_button (%s (%dx%d):%u, connected %ld).\n",
236  ol->ob ? ol->ob->name : "null",
237  ol->ob ? ol->ob->x : -1,
238  ol->ob ? ol->ob->y : -1,
239  ol->id,
240  obp->value);
241  continue;
242  }
243  if (ol->ob->type == BUTTON || ol->ob->type == PEDESTAL) {
244  update_button(ol->ob);
245  break;
246  }
247  }
248 }
249 
255 void use_trigger(object *op) {
256  /* Toggle value */
257  op->value = !op->value;
258  push_button(op);
259 }
260 
271 void animate_turning(object *op) {
272  if (++op->state >= NUM_ANIMATIONS(op)/8)
273  op->state = 0;
274  // Firewalls use direction instead of sp to avoid issues involving the spell transference.
275  if (op->type == FIREWALL){
276  SET_ANIMATION(op, (op->direction-1)*NUM_ANIMATIONS(op)/8+op->state);
277  }
278  else {
279  SET_ANIMATION(op, (op->stats.sp-1)*NUM_ANIMATIONS(op)/8+op->state);
280  }
282 }
283 
284 #define ARCH_SACRIFICE(xyz) ((xyz)->slaying)
285 #define NROF_SACRIFICE(xyz) ((uint32_t)(xyz)->stats.food)
286 
298 static int matches_sacrifice(const object *altar, const object *sacrifice) {
299  char name[MAX_BUF];
300 
301  if ((QUERY_FLAG(sacrifice, FLAG_ALIVE) && object_value_set(altar, "accept_alive") == false)
302  || QUERY_FLAG(sacrifice, FLAG_IS_LINKED)
303  || sacrifice->type == PLAYER)
304  return 0;
305 
306  query_base_name(sacrifice, 0, name, MAX_BUF);
307  if (ARCH_SACRIFICE(altar) == sacrifice->arch->name
308  || ARCH_SACRIFICE(altar) == sacrifice->name
309  || ARCH_SACRIFICE(altar) == sacrifice->slaying
310  || (!strcmp(ARCH_SACRIFICE(altar), name)))
311  return 1;
312 
313  if (strcmp(ARCH_SACRIFICE(altar), "money") == 0
314  && sacrifice->type == MONEY)
315  return 1;
316 
317  return 0;
318 }
319 
348 int check_altar_sacrifice(const object *altar, const object *sacrifice, int remove_others, int *toremove) {
349  int money;
350  uint32_t wanted, rest;
351 
352  if (!matches_sacrifice(altar, sacrifice))
353  /* New dropped object doesn't match the altar, other objects already on top are not enough to
354  * activate altar, else they would have disappeared. */
355  return 0;
356 
357  /* Check item is paid for. */
358  if (QUERY_FLAG(sacrifice, FLAG_UNPAID)) {
359  return 0;
360  }
361 
362  money = (strcmp(ARCH_SACRIFICE(altar), "money") == 0) ? 1 : 0;
363 
364  /* Easy checks: newly dropped object is enough for sacrifice. */
365  if (money && sacrifice->nrof*sacrifice->value >= NROF_SACRIFICE(altar)) {
366  if (toremove) {
367  *toremove = NROF_SACRIFICE(altar)/sacrifice->value;
368  /* Round up any sacrifices. Altars don't make change either */
369  if (NROF_SACRIFICE(altar)%sacrifice->value)
370  (*toremove)++;
371  }
372  return 1;
373  }
374 
375  if (!money && NROF_SACRIFICE(altar) <= NROF(sacrifice)) {
376  if (toremove)
377  *toremove = NROF_SACRIFICE(altar);
378  return 1;
379  }
380 
381  if (money) {
382  wanted = NROF_SACRIFICE(altar)-sacrifice->nrof*sacrifice->value;
383  } else {
384  wanted = NROF_SACRIFICE(altar)-NROF(sacrifice);
385  }
386  rest = wanted;
387 
388  /* Ok, now we check if we got enough with other items.
389  * We only check items above altar, and not checking again sacrifice.
390  */
391  FOR_ABOVE_PREPARE(altar, tmp) {
392  if (wanted <= 0)
393  break;
394  if (tmp == sacrifice || !matches_sacrifice(altar, tmp))
395  continue;
396  if (money)
397  wanted -= tmp->nrof*tmp->value;
398  else
399  wanted -= NROF(tmp);
400  } FOR_ABOVE_FINISH();
401 
402  if (wanted > 0)
403  /* Not enough value, let's bail out. */
404  return 0;
405 
406  /* From there on, we do have enough objects for the altar. */
407 
408  /* Last dropped object will be totally eaten in any case. */
409  if (toremove)
410  *toremove = NROF(sacrifice);
411 
412  if (!remove_others)
413  return 1;
414 
415  /* We loop again, this time to remove what we need. */
416  FOR_ABOVE_PREPARE(altar, tmp) {
417  if (rest <= 0)
418  break;
419  if (tmp == sacrifice || !matches_sacrifice(altar, tmp))
420  continue;
421  if (money) {
422  wanted = tmp->nrof*tmp->value;
423  if (rest > wanted) {
424  object_remove(tmp);
425  rest -= wanted;
426  } else {
427  wanted = rest/tmp->value;
428  if (rest%tmp->value)
429  wanted++;
430  object_decrease_nrof(tmp, wanted);
431  return 1;
432  }
433  } else
434  if (rest > NROF(tmp)) {
435  rest -= NROF(tmp);
436  object_remove(tmp);
437  } else {
438  object_decrease_nrof(tmp, rest);
439  return 1;
440  }
441  } FOR_ABOVE_FINISH();
442 
443  /* Something went wrong, we'll be nice and accept the sacrifice anyway. */
444  LOG(llevError, "check_altar_sacrifice on %s: found objects to sacrifice, but couldn't remove them??\n", altar->map->path);
445  return 1;
446 }
447 
464 int operate_altar(object *altar, object **sacrifice) {
465  int number;
466 
467  if (!altar->map) {
468  LOG(llevError, "BUG: operate_altar(): altar has no map\n");
469  return 0;
470  }
471 
472  if (!altar->slaying || altar->value)
473  return 0;
474 
475  if (!check_altar_sacrifice(altar, *sacrifice, 1, &number))
476  return 0;
477 
478  /* check_altar_sacrifice fills in number for us. */
479  *sacrifice = object_decrease_nrof(*sacrifice, number);
480 
481  if (altar->msg)
483  return 1;
484 }
485 
489 static void trigger_move(object *op, int state) { /* 1 down and 0 up */
490  op->stats.wc = state;
491  if (state) {
492  use_trigger(op);
493  if (op->stats.exp > 0) /* check sanity */
494  op->speed = 1.0/op->stats.exp;
495  else
496  op->speed = 1.0;
498  op->speed_left = -1;
499  } else {
500  use_trigger(op);
501  op->speed = 0;
503  }
504 }
505 
519 int check_trigger(object *op, object *cause) {
520  int push = 0, tot = 0;
521  int in_movement = op->stats.wc || op->speed;
522 
523  switch (op->type) {
524  case TRIGGER_BUTTON:
525  if (op->weight > 0) {
526  if (cause) {
527  FOR_ABOVE_PREPARE(op, tmp)
528  /* Comment reproduced from update_buttons():
529  * Basically, if the move_type matches that on what the
530  * button wants, we count it. The second check is so that
531  * objects that don't move (swords, etc) will count. Note that
532  * this means that more work is needed to make buttons
533  * that are only triggered by flying objects.
534  */
535  if ((tmp->move_type&op->move_on) || tmp->move_type == 0) {
536  tot += tmp->weight*NROF(tmp)+tmp->carrying;
537  }
539  if (tot >= op->weight)
540  push = 1;
541  if (op->stats.ac == push)
542  return 0;
543  op->stats.ac = push;
544  if (NUM_ANIMATIONS(op) > 1) {
545  SET_ANIMATION(op, push);
547  }
548  if (in_movement || !push)
549  return 0;
550  }
551  trigger_move(op, push);
552  }
553  return 0;
554 
555  case TRIGGER_PEDESTAL:
556  if (cause) {
557  FOR_ABOVE_PREPARE(op, tmp) {
558  object *head = tmp->head ? tmp->head : tmp;
559 
560  /* See comment in TRIGGER_BUTTON about move_types */
561  if (((head->move_type&op->move_on) || head->move_type == 0)
562  && (head->race == op->slaying || (!strcmp(op->slaying, "player") && head->type == PLAYER))) {
563  push = 1;
564  break;
565  }
566  } FOR_ABOVE_FINISH();
567  if (op->stats.ac == push)
568  return 0;
569  op->stats.ac = push;
570  if (NUM_ANIMATIONS(op) > 1) {
571  SET_ANIMATION(op, push);
573  }
574  if (in_movement || !push)
575  return 0;
576  }
577  trigger_move(op, push);
578  return 0;
579 
580  case TRIGGER_ALTAR:
581  if (cause) {
582  if (in_movement)
583  return 0;
584  if (operate_altar(op, &cause)) {
585  if (NUM_ANIMATIONS(op) > 1) {
586  SET_ANIMATION(op, 1);
588  }
589 
590  if (op->last_sp >= 0) {
591  trigger_move(op, 1);
592  if (op->last_sp > 0)
593  op->last_sp = -op->last_sp;
594  } else {
595  /* for trigger altar with last_sp, the ON/OFF
596  * status (-> +/- value) is "simulated":
597  */
598  op->value = !op->value;
599  trigger_move(op, 1);
600  op->last_sp = -op->last_sp;
601  op->value = !op->value;
602  }
603  return cause == NULL;
604  } else {
605  return 0;
606  }
607  } else {
608  if (NUM_ANIMATIONS(op) > 1) {
609  SET_ANIMATION(op, 0);
611  }
612 
613  /* If trigger_altar has "last_sp > 0" set on the map,
614  * it will push the connected value only once per sacrifice.
615  * Otherwise (default), the connected value will be
616  * pushed twice: First by sacrifice, second by reset! -AV
617  */
618  if (!op->last_sp)
619  trigger_move(op, 0);
620  else {
621  op->stats.wc = 0;
622  op->value = !op->value;
623  op->speed = 0;
625  }
626  }
627  return 0;
628 
629  case TRIGGER:
630  if (cause) {
631  if (in_movement)
632  return 0;
633  push = 1;
634  }
635  if (NUM_ANIMATIONS(op) > 1) {
636  SET_ANIMATION(op, push);
638  }
639  trigger_move(op, push);
640  return 1;
641 
642  default:
643  LOG(llevDebug, "Unknown trigger type: %s (%d)\n", op->name, op->type);
644  return 0;
645  }
646 }
647 
658 void add_button_link(object *button, mapstruct *map, int connected) {
659  oblinkpt *obp;
660  objectlink *ol = get_objectlink();
661 
662  if (!map) {
663  LOG(llevError, "Tried to add button-link without map.\n");
664  free_objectlink(ol);
665  return;
666  }
667 
668  SET_FLAG(button, FLAG_IS_LINKED);
669 
670  ol->ob = button;
671  ol->id = button->count;
672 
673  for (obp = map->buttons; obp && obp->value != connected; obp = obp->next)
674  ;
675 
676  if (obp) {
677  ol->next = obp->link;
678  obp->link = ol;
679  } else {
680  obp = get_objectlinkpt();
681  obp->value = connected;
682 
683  obp->next = map->buttons;
684  map->buttons = obp;
685  obp->link = ol;
686  }
687 }
688 
695 void remove_button_link(object *op) {
696  oblinkpt *obp;
697  objectlink **olp, *ol;
698 
699  if (op->map == NULL) {
700  LOG(llevError, "remove_button_link() in object without map.\n");
701  return;
702  }
703  if (!QUERY_FLAG(op, FLAG_IS_LINKED)) {
704  LOG(llevError, "remove_button_linked() in unlinked object.\n");
705  return;
706  }
707 
708  for (obp = op->map->buttons; obp; obp = obp->next)
709  for (olp = &obp->link; (ol = *olp); olp = &ol->next)
710  if (ol->ob == op) {
711 /* LOG(llevDebug, "Removed link %d in button %s and map %s.\n",
712  obp->value, op->name, op->map->path);
713 */
714  *olp = ol->next;
715  free(ol);
716  return;
717  }
718  LOG(llevError, "remove_button_linked(): couldn't find object.\n");
720 }
721 
729 static objectlink *get_button_links(const object *button) {
730  oblinkpt *obp;
731  objectlink *ol;
732 
733  if (!button->map)
734  return NULL;
735 
736  for (obp = button->map->buttons; obp; obp = obp->next)
737  for (ol = obp->link; ol; ol = ol->next)
738  if (ol->ob == button && ol->id == button->count)
739  return obp->link;
740  return NULL;
741 }
742 
751 int get_button_value(const object *button) {
752  oblinkpt *obp;
753  objectlink *ol;
754 
755  if (!button->map)
756  return 0;
757 
758  for (obp = button->map->buttons; obp; obp = obp->next)
759  for (ol = obp->link; ol; ol = ol->next)
760  if (ol->ob == button && ol->id == button->count)
761  return obp->value;
762  return 0;
763 }
764 
784 object *check_inv_recursive(object *op, const object *trig) {
785  object *ret = NULL;
786 
787  /* First check the object itself. */
788  if ((!trig->stats.hp || (op->type == trig->stats.hp))
789  && (!trig->slaying || (op->slaying == trig->slaying))
790  && (!trig->race || (op->arch->name == trig->race))
791  && (!trig->title || (op->title == trig->title))
792  && (QUERY_FLAG(op, FLAG_UNPAID) == QUERY_FLAG(trig, FLAG_UNPAID)))
793  return op;
794 
795  FOR_INV_PREPARE(op, tmp) {
796  if (tmp->inv) {
797  ret = check_inv_recursive(tmp, trig);
798  if (ret)
799  return ret;
800  } else if ((!trig->stats.hp || (tmp->type == trig->stats.hp))
801  && (!trig->slaying || (tmp->slaying == trig->slaying))
802  && (!trig->race || (tmp->arch->name == trig->race))
803  && (!trig->title || (tmp->title == trig->title))
804  && (QUERY_FLAG(tmp, FLAG_UNPAID) == QUERY_FLAG(trig, FLAG_UNPAID)))
805  return tmp;
806  } FOR_INV_FINISH();
807 
808  return NULL;
809 }
810 
811 
827 void check_inv(object *op, object *trig) {
828  object *match;
829 
830  if (op->type != PLAYER)
831  return;
832 
833  match = check_inv_recursive(op, trig);
834  if (match && trig->last_sp) {
835  if (trig->last_heal)
837  use_trigger(trig);
838  } else if (!match && !trig->last_sp)
839  use_trigger(trig);
840 }
object_value_set
bool object_value_set(const object *op, const char *const key)
Determine if an extra value is set.
Definition: object.cpp:4361
check_inv
void check_inv(object *op, object *trig)
Function to search the inventory, of a player and then based on a set of conditions,...
Definition: button.cpp:827
living::exp
int64_t exp
Experience.
Definition: living.h:47
TRIGGER
@ TRIGGER
Definition: object.h:134
PLAYER
@ PLAYER
Definition: object.h:112
global.h
CF_HANDLE
@ CF_HANDLE
Definition: object.h:213
living::maxhp
int16_t maxhp
Max hit points.
Definition: living.h:41
FLAG_ACTIVATE_ON_RELEASE
#define FLAG_ACTIVATE_ON_RELEASE
connected object is activated when 'released'
Definition: define.h:350
llevError
@ llevError
Problems requiring server admin to fix.
Definition: logger.h:11
FLAG_ANIMATE
#define FLAG_ANIMATE
The object looks at archetype for faces.
Definition: define.h:229
LOG
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:82
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:369
FLAG_IS_LINKED
#define FLAG_IS_LINKED
The object is linked with other objects.
Definition: define.h:302
BUTTON
@ BUTTON
Definition: object.h:212
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:371
ob_trigger
method_ret ob_trigger(object *op, object *cause, int state)
An object is triggered by another one.
Definition: ob_methods.cpp:156
TRIGGER_PEDESTAL
@ TRIGGER_PEDESTAL
Definition: object.h:139
trigger_move
static void trigger_move(object *op, int state)
Definition: button.cpp:489
oblinkpt::next
oblinkpt * next
Next value in the list.
Definition: object.h:472
get_button_links
static objectlink * get_button_links(const object *button)
Return the first objectlink in the objects linked to this one.
Definition: button.cpp:729
mapstruct::buttons
oblinkpt * buttons
Linked list of linked lists of buttons.
Definition: map.h:348
object::arch
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
EVENT_TRIGGER
#define EVENT_TRIGGER
Button pushed, lever pulled, etc.
Definition: events.h:42
object::speed
float speed
Frequency of object 'moves' relative to server tick rate.
Definition: object.h:337
matches_sacrifice
static int matches_sacrifice(const object *altar, const object *sacrifice)
Helper function to check if the item matches altar's requested sacrifice.
Definition: button.cpp:298
object::x
int16_t x
Definition: object.h:335
object::speed_left
float speed_left
How much speed is left to spend this round.
Definition: object.h:338
object::map
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
TIMED_GATE
@ TIMED_GATE
Definition: object.h:133
SET_ANIMATION
#define SET_ANIMATION(ob, newanim)
Definition: global.h:168
object::direction
int8_t direction
Means the object is moving that way.
Definition: object.h:344
object::count
tag_t count
Unique object number for this object.
Definition: object.h:307
NDI_NAVY
#define NDI_NAVY
Definition: newclient.h:248
SCRIPT_FIX_ALL
#define SCRIPT_FIX_ALL
Definition: global.h:381
oblinkpt
Used to link together several object links.
Definition: object.h:469
FOR_ABOVE_PREPARE
#define FOR_ABOVE_PREPARE(op_, it_)
Constructs a loop iterating over all objects above an object.
Definition: define.h:671
SIGN
@ SIGN
Definition: object.h:216
TRIGGER_BUTTON
@ TRIGGER_BUTTON
Definition: object.h:137
object::title
sstring title
Of foo, etc.
Definition: object.h:325
mapstruct::path
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:360
events_execute_object_event
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Execute an event on the specified object.
Definition: events.cpp:309
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
FLAG_ALIVE
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:217
object::y
int16_t y
Position in the map for this object.
Definition: object.h:335
m
static event_registration m
Definition: citylife.cpp:424
FLAG_FREED
#define FLAG_FREED
Object is in the list of free objects.
Definition: define.h:220
get_button_value
int get_button_value(const object *button)
Returns the first value linked to this button.
Definition: button.cpp:751
object_update
void object_update(object *op, int action)
object_update() updates the array which represents the map.
Definition: object.cpp:1419
NROF
static uint32_t NROF(const object *const ob)
Returns ob->nrof, unless it is 0, in which case return 1.
Definition: object.h:625
object_decrease_nrof_by_one
#define object_decrease_nrof_by_one(xyz)
Definition: compat.h:32
object::last_heal
int32_t last_heal
Last healed.
Definition: object.h:367
oblinkpt::link
objectlink * link
Items for this value.
Definition: object.h:470
FLAG_UNPAID
#define FLAG_UNPAID
Object hasn't been paid for yet.
Definition: define.h:223
check_inv_recursive
object * check_inv_recursive(object *op, const object *trig)
Checks object and its inventory for specific item.
Definition: button.cpp:784
FOR_ABOVE_FINISH
#define FOR_ABOVE_FINISH()
Finishes FOR_ABOVE_PREPARE().
Definition: define.h:678
archetype::clone
object clone
An object from which to do object_copy()
Definition: object.h:487
oblinkpt::value
long value
Used as connected value in buttons/gates.
Definition: object.h:471
object::move_type
MoveType move_type
Type of movement this object uses.
Definition: object.h:436
ext_info_map
void void ext_info_map(int color, const mapstruct *map, uint8_t type, uint8_t subtype, const char *str1)
Writes to everyone on the specified map.
Definition: main.cpp:342
object::last_eat
int32_t last_eat
How long since we last ate.
Definition: object.h:366
object::value
int32_t value
How much money it is worth (or contains)
Definition: object.h:360
SPECIAL_KEY
@ SPECIAL_KEY
Definition: object.h:129
HOLE
@ HOLE
Definition: object.h:214
object_update_speed
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.cpp:1334
ARCH_SACRIFICE
#define ARCH_SACRIFICE(xyz)
Definition: button.cpp:284
object::type
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
remove_button_link
void remove_button_link(object *op)
Remove the object from the linked lists of buttons in the map.
Definition: button.cpp:695
move_firewall
void move_firewall(object *op)
Move for FIREWALL.
Definition: main.cpp:351
FOR_INV_FINISH
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:661
object::move_on
MoveType move_on
Move types affected moving on to this space.
Definition: object.h:439
living::food
int32_t food
How much food in stomach.
Definition: living.h:48
sproto.h
living::sp
int16_t sp
Spell points.
Definition: living.h:42
MSG_SUBTYPE_NONE
#define MSG_SUBTYPE_NONE
Definition: newclient.h:424
object::race
sstring race
Human, goblin, dragon, etc.
Definition: object.h:326
add_button_link
void add_button_link(object *button, mapstruct *map, int connected)
Add the given object to the per-map list of connected objects with the given connection ID.
Definition: button.cpp:658
NDI_BLACK
#define NDI_BLACK
Definition: newclient.h:246
MAX_BUF
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
MSG_TYPE_DIALOG
#define MSG_TYPE_DIALOG
NPCs, magic mouths, and altars.
Definition: newclient.h:404
object::head
object * head
Points to the main object of a large body.
Definition: object.h:304
animate_turning
void animate_turning(object *op)
Animates one step of object.
Definition: button.cpp:271
use_trigger
void use_trigger(object *op)
Toggles the state of specified button.
Definition: button.cpp:255
object::weight
int32_t weight
Attributes of the object.
Definition: object.h:375
living::wc
int8_t wc
Weapon Class, lower WC increases probability of hitting.
Definition: living.h:37
object_decrease_nrof
object * object_decrease_nrof(object *op, uint32_t i)
Decreases a specified number from the amount of an object.
Definition: object.cpp:2661
check_trigger
int check_trigger(object *op, object *cause)
Definition: button.cpp:519
NDI_UNIQUE
#define NDI_UNIQUE
Print immediately, don't buffer.
Definition: newclient.h:266
object::slaying
sstring slaying
Which race to do double damage to.
Definition: object.h:327
object::name
sstring name
The name of the object, obviously...
Definition: object.h:319
FLAG_ACTIVATE_ON_PUSH
#define FLAG_ACTIVATE_ON_PUSH
connected object is activated when 'pushed'
Definition: define.h:349
living::maxsp
int16_t maxsp
Max spell points.
Definition: living.h:43
FIREWALL
@ FIREWALL
Definition: object.h:173
TRIGGER_ALTAR
@ TRIGGER_ALTAR
Definition: object.h:138
mapstruct
This is a game-map.
Definition: map.h:320
object::last_sp
int32_t last_sp
As last_heal, but for spell points.
Definition: object.h:368
check_altar_sacrifice
int check_altar_sacrifice(const object *altar, const object *sacrifice, int remove_others, int *toremove)
Checks whether the altar has enough to sacrifice.
Definition: button.cpp:348
object::msg
sstring msg
If this is a book/sign/magic mouth/etc.
Definition: object.h:330
update_buttons
void update_buttons(mapstruct *m)
Updates every button on the map (by calling update_button() for them).
Definition: button.cpp:228
operate_altar
int operate_altar(object *altar, object **sacrifice)
Checks if sacrifice was accepted and removes sacrificed objects.
Definition: button.cpp:464
PEDESTAL
@ PEDESTAL
Definition: object.h:126
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:370
living::ac
int8_t ac
Armor Class, lower AC increases probability of not getting hit.
Definition: living.h:38
NUM_ANIMATIONS
#define NUM_ANIMATIONS(ob)
Definition: global.h:177
UP_OBJ_FACE
#define UP_OBJ_FACE
Only thing that changed was the face.
Definition: object.h:533
DIRECTOR
@ DIRECTOR
Definition: object.h:227
push_button
void push_button(object *op)
Trigger all connections on the map connected to op.
Definition: button.cpp:150
object_remove
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to.
Definition: object.cpp:1818
ALTAR
@ ALTAR
Definition: object.h:127
object::state
uint8_t state
How the object was last drawn (animation)
Definition: object.h:359
archetype::name
sstring name
More definite name, like "generate_kobold".
Definition: object.h:484
object::nrof
uint32_t nrof
Number of objects.
Definition: object.h:342
query_base_name
void query_base_name(const object *op, int plural, char *buf, size_t size)
Query a short name for the item.
Definition: item.cpp:691
object::stats
living stats
Str, Con, Dex, etc.
Definition: object.h:378
MSG_TYPE_SIGN
#define MSG_TYPE_SIGN
Definition: newclient.h:402
object::more
object * more
Pointer to the rest of a large body of objects.
Definition: object.h:303
MSG_TYPE_DIALOG_ALTAR
#define MSG_TYPE_DIALOG_ALTAR
A message from an altar.
Definition: newclient.h:492
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:654
living::hp
int16_t hp
Hit Points.
Definition: living.h:40
llevDebug
@ llevDebug
Only for debugging purposes.
Definition: logger.h:15
update_button
void update_button(object *op)
Updates everything connected with the button op.
Definition: button.cpp:163
MONEY
@ MONEY
Definition: object.h:142
GATE
@ GATE
Definition: object.h:211
trigger_connected
void trigger_connected(objectlink *ol, object *cause, const int state)
Trigger every object in an objectlink.
Definition: button.cpp:45
NROF_SACRIFICE
#define NROF_SACRIFICE(xyz)
Definition: button.cpp:285