Crossfire Server, Trunk  R22047
holy.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 <assert.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "libproto.h"
26 #include "living.h"
27 #include "spells.h"
28 
29 #include "assets.h"
30 
37 static godlink *init_godslist(void) {
38  godlink *gl = (godlink *)malloc(sizeof(godlink));
39  if (gl == NULL)
41  gl->name = NULL; /* how to describe the god to the player */
42  gl->arch = NULL; /* pointer to the archetype of this god */
43  gl->id = 0; /* id of the god */
44  gl->next = NULL; /* next god in this linked list */
45 
46  return gl;
47 }
48 
55 static void add_god_to_list(archetype *god_arch) {
56  godlink *god;
57 
58  if (!god_arch) {
59  LOG(llevError, "ERROR: Tried to add null god to list!\n");
60  return;
61  }
62  if (!(god_arch->clone.type == GOD)) {
63  return;
64  }
65 
66  god = init_godslist();
67 
68  god->arch = god_arch;
69  god->name = add_string(god_arch->clone.name);
70  if (!first_god)
71  god->id = 1;
72  else {
73  god->id = first_god->id+1;
74  god->next = first_god;
75  }
76  first_god = god;
77 
78 #ifdef DEBUG_GODS
79  LOG(llevDebug, "Adding god %s (%d) to list\n", god->name, god->id);
80 #endif
81 }
86 void init_gods(void) {
87  archetype *at = NULL;
88 
89  LOG(llevDebug, "Initializing gods...\n");
90 
92 
93  LOG(llevDebug, "done.\n");
94 }
95 
103  godlink *god = first_god;
104  int i;
105 
106  if (god)
107  for (i = RANDOM()%(god->id)+1; god; god = god->next)
108  if (god->id == i)
109  break;
110 
111  if (!god)
112  LOG(llevError, "get_rand_god(): can't find a random god!\n");
113  return god;
114 }
115 
124 const object *pntr_to_god_obj(godlink *godlnk) {
125  if (godlnk && godlnk->arch)
126  return &godlnk->arch->clone;
127  return NULL;
128 }
129 
138 int describe_god(const object *god, int what, StringBuffer *buf, size_t maxlen) {
139  int hassomething = 0, real = 0;
140  char temp[HUGE_BUF];
141  StringBuffer *add;
142  const char *name;
143 
144  name = god->name;
145 
146  /* preamble.. */
147  assert(buf);
148  stringbuffer_append_printf(buf, "This document contains knowledge concerning the diety %s", name);
149 
150  /* Always have as default information the god's descriptive terms. */
151  if (nstrtok(god->msg, ",") > 0) {
152  stringbuffer_append_string(buf, ", known as");
153  stringbuffer_append_string(buf, strtoktolin(god->msg, ",", temp, sizeof(temp)));
154  } else
155  stringbuffer_append_string(buf, "...");
156 
157  stringbuffer_append_string(buf, "\n ---\n");
158 
159  if (what & GOD_PATHS) {
160  /* spell paths */
161  int has_effect = 0;
162 
163  add = stringbuffer_new();
164  stringbuffer_append_printf(add, "It is rarely known fact that the priests of %s are mystically transformed. Effects of this include:\n", name);
165 
166  if (god->path_attuned) {
167  has_effect = 1;
168  describe_spellpath_attenuation("Attuned", god->path_attuned, add);
169  }
170  if (god->path_repelled) {
171  has_effect = 1;
172  describe_spellpath_attenuation("Repelled", god->path_repelled, add);
173  }
174  if (god->path_denied) {
175  has_effect = 1;
176  describe_spellpath_attenuation("Denied", god->path_denied, add);
177  }
178  if (has_effect) {
179  stringbuffer_append_string(add, "\n ---\n");
180 
181  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
183  free(stringbuffer_finish(add));
184  hassomething = 1;
185  } else {
186  free(stringbuffer_finish(add));
187  return real;
188  }
189  } else {
190  free(stringbuffer_finish(add));
191  }
192  what |= GOD_PATHS;
193  }
194 
195  if (what & GOD_IMMUNITIES) {
196  int has_effect = 0, tmpvar;
197  char tmpbuf[MAX_BUF];
198 
199  add = stringbuffer_new();
200  stringbuffer_append_printf(add, "\nThe priests of %s are known to make cast a mighty prayer of possession which gives the recipient ", name);
201 
202  for (tmpvar = 0; tmpvar < NROFATTACKS; tmpvar++) {
203  if (god->resist[tmpvar] == 100) {
204  has_effect = 1;
205  snprintf(tmpbuf, MAX_BUF, "Immunity to %s", attacktype_desc[tmpvar]);
206  }
207  }
208  if (has_effect) {
209  stringbuffer_append_printf(add, "%s\n ---\n", tmpbuf);
210  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
212  free(stringbuffer_finish(add));
213  hassomething = 1;
214  } else {
215  free(stringbuffer_finish(add));
216  return real;
217  }
218  } else {
219  free(stringbuffer_finish(add));
220  }
221  real |= GOD_IMMUNITIES;
222  }
223 
224  if (what & GOD_BLESSED) {
225  char *cp = stringbuffer_finish(describe_resistance(god, 1, 1, NULL));
226 
227  if (*cp) { /* This god does have protections */
228  add = stringbuffer_new();
229  stringbuffer_append_printf(add, "\nThe priests of %s are known to be able to bestow a blessing which makes the recipient %s\n ---\n", name, cp);
230 
231  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
233  free(stringbuffer_finish(add));
234  hassomething = 1;
235  } else {
236  free(stringbuffer_finish(add));
237  return real;
238  }
239  }
240  free(cp);
241  real |= GOD_BLESSED;
242  }
243 
244  if (what & GOD_SACRED) {
245  if (god->race && !(god->path_denied&PATH_SUMMON)) {
246  int i = nstrtok(god->race, ",");
247  add = stringbuffer_new();
248  stringbuffer_append_printf(add, "Creatures sacred to %s include the\n", name);
249 
250  if (i > 1)
251  stringbuffer_append_printf(add, "following races:%s\n ---\n", strtoktolin(god->race, ",", temp, sizeof(temp)));
252  else
253  stringbuffer_append_printf(add, "race of %s\n ---\n", strtoktolin(god->race, ",", temp, sizeof(temp)));
254 
255  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
257  free(stringbuffer_finish(add));
258  hassomething = 1;
259  } else {
260  free(stringbuffer_finish(add));
261  return real;
262  }
263  }
264  real |= GOD_SACRED;
265  }
266 
267  if (what & GOD_RESISTANCES) {
268  char *cp;
269  cp = stringbuffer_finish(describe_resistance(god, 1, 1, NULL));
270 
271  if (*cp) { /* This god does have protections */
272  add = stringbuffer_new();
273  stringbuffer_append_printf(add, "%s has a potent aura which is extended to faithful priests. The effects of this aura include:\n%s\n ---\n", name, cp);
274 
275  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
277  free(stringbuffer_finish(add));
278  hassomething = 1;
279  } else {
280  free(stringbuffer_finish(add));
281  return real;
282  }
283  }
284  free(cp);
285  real |= GOD_RESISTANCES;
286  }
287 
288  if (what & GOD_HOLYWORD) {
289  if ((god->slaying) && !(god->path_denied&PATH_TURNING)) {
290  add = stringbuffer_new();
291  stringbuffer_append_printf(add, "The holy words of %s have the power to slay creatures belonging to the ", name);
292 
293  if (nstrtok(god->slaying, ",") > 1)
294  stringbuffer_append_printf(add, "following races:%s\n ---\n", strtoktolin(god->slaying, ",", temp, sizeof(temp)));
295  else
296  stringbuffer_append_printf(add, "race of%s\n ---\n", strtoktolin(god->slaying, ",", temp, sizeof(temp)));
297 
298  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
300  free(stringbuffer_finish(add));
301  hassomething = 1;
302  } else {
303  free(stringbuffer_finish(add));
304  return real;
305  }
306  }
307  real |= GOD_HOLYWORD;
308  }
309 
310  if (what & GOD_ENEMY) {
311  if (god->title) {
312  add = stringbuffer_new();
313  stringbuffer_append_printf(add, "The gods %s and %s are enemies.\n ---\n", name, god->title);
314 
315  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
317  free(stringbuffer_finish(add));
318  hassomething = 1;
319  } else {
320  free(stringbuffer_finish(add));
321  return real;
322  }
323  }
324  real |= GOD_ENEMY;
325  }
326 
327  if (hassomething == 0) {
328  /* we got no information beyond the preamble! */
329  stringbuffer_append_string(buf, " Unfortunately the rest of the information is hopelessly garbled!\n ---\n");
330  }
331 
332  return real;
333 }
334 
338 void free_all_god(void) {
339  godlink *god, *godnext;
340 
341  LOG(llevDebug, "Freeing god information\n");
342  for (god = first_god; god; god = godnext) {
343  godnext = god->next;
344  if (god->name)
345  free_string(god->name);
346  free(god);
347  }
348  first_god = NULL;
349 }
350 
351 #define DESCRIBE_ABILITY(retbuf, variable, name) \
352  if (variable) { \
353  int i, j = 0; \
354  strcat(retbuf, "(" name ": "); \
355  for (i = 0; i < NROFATTACKS; i++) \
356  if (variable&(1<<i)) { \
357  if (j) \
358  strcat(retbuf, ", "); \
359  else \
360  j = 1; \
361  strcat(retbuf, attacks[i]); \
362  } \
363  strcat(retbuf, ")"); \
364  }
365 
366 #define DESCRIBE_PATH(retbuf, variable, name) \
367  if (variable) { \
368  int i, j = 0; \
369  strcat(retbuf, "(" name ": "); \
370  for (i = 0; i < NRSPELLPATHS; i++) \
371  if (variable&(1<<i)) { \
372  if (j) \
373  strcat(retbuf, ", "); \
374  else \
375  j = 1; \
376  strcat(retbuf, spellpathnames[i]); \
377  } \
378  strcat(retbuf, ")"); \
379  }
380 
387 void dump_gods(void) {
388  godlink *glist;
389 
390  fprintf(stderr, "\n");
391  for (glist = first_god; glist; glist = glist->next) {
392  const object *god = pntr_to_god_obj(glist);
393  char tmpbuf[HUGE_BUF], *final;
394  int tmpvar, gifts = 0;
395 
396  fprintf(stderr, "GOD: %s\n", god->name);
397  fprintf(stderr, " avatar stats:\n");
398  fprintf(stderr, " S:%d C:%d D:%d I:%d W:%d P:%d\n", god->stats.Str, god->stats.Con, god->stats.Dex, god->stats.Int, god->stats.Wis, god->stats.Pow);
399  fprintf(stderr, " lvl:%d speed:%4.2f\n", god->level, god->speed);
400  fprintf(stderr, " wc:%d ac:%d hp:%d dam:%d\n", god->stats.wc, god->stats.ac, god->stats.hp, god->stats.dam);
401  fprintf(stderr, " enemy: %s\n", god->title ? god->title : "NONE");
402  if (god->other_arch) {
403  object *serv = &god->other_arch->clone;
404  fprintf(stderr, " servant stats: (%s)\n", god->other_arch->name);
405  fprintf(stderr, " S:%d C:%d D:%d I:%d W:%d P:%d\n", serv->stats.Str, serv->stats.Con, serv->stats.Dex, serv->stats.Int, serv->stats.Wis, serv->stats.Pow);
406  fprintf(stderr, " lvl:%d speed:%4.2f\n", serv->level, serv->speed);
407  fprintf(stderr, " wc:%d ac:%d hp:%d dam:%d\n", serv->stats.wc, serv->stats.ac, serv->stats.hp, serv->stats.dam);
408  } else
409  fprintf(stderr, " servant: NONE\n");
410  fprintf(stderr, " aligned_race(s): %s\n", god->race);
411  fprintf(stderr, " enemy_race(s): %s\n", (god->slaying ? god->slaying : "none"));
412  final = stringbuffer_finish(describe_resistance(god, 1, 1, NULL));
413  fprintf(stderr, "%s", final);
414  free(final);
415  snprintf(tmpbuf, sizeof(tmpbuf), " attacktype:");
416  if ((tmpvar = god->attacktype)) {
417  strcat(tmpbuf, "\n ");
418  DESCRIBE_ABILITY(tmpbuf, tmpvar, "Attacks");
419  }
420  strcat(tmpbuf, "\n aura:");
421 
422  strcat(tmpbuf, "\n paths:");
423  if ((tmpvar = god->path_attuned)) {
424  strcat(tmpbuf, "\n ");
425  DESCRIBE_PATH(tmpbuf, tmpvar, "Attuned");
426  }
427  if ((tmpvar = god->path_repelled)) {
428  strcat(tmpbuf, "\n ");
429  DESCRIBE_PATH(tmpbuf, tmpvar, "Repelled");
430  }
431  if ((tmpvar = god->path_denied)) {
432  strcat(tmpbuf, "\n ");
433  DESCRIBE_PATH(tmpbuf, tmpvar, "Denied");
434  }
435  fprintf(stderr, "%s\n", tmpbuf);
436  fprintf(stderr, " Desc: %s", god->msg ? god->msg : "---\n");
437  fprintf(stderr, " Priest gifts/limitations: ");
438  if (!QUERY_FLAG(god, FLAG_USE_WEAPON)) { gifts = 1; fprintf(stderr, "\n weapon use is forbidden"); }
439  if (!QUERY_FLAG(god, FLAG_USE_ARMOUR)) { gifts = 1; fprintf(stderr, "\n no armour may be worn"); }
440  if (QUERY_FLAG(god, FLAG_UNDEAD)) { gifts = 1; fprintf(stderr, "\n is undead"); }
441  if (QUERY_FLAG(god, FLAG_SEE_IN_DARK)) { gifts = 1; fprintf(stderr, "\n has infravision "); }
442  if (QUERY_FLAG(god, FLAG_XRAYS)) { gifts = 1; fprintf(stderr, "\n has X-ray vision"); }
443  if (QUERY_FLAG(god, FLAG_REFL_MISSILE)) { gifts = 1; fprintf(stderr, "\n reflect missiles"); }
444  if (QUERY_FLAG(god, FLAG_REFL_SPELL)) { gifts = 1; fprintf(stderr, "\n reflect spells"); }
445  if (QUERY_FLAG(god, FLAG_STEALTH)) { gifts = 1; fprintf(stderr, "\n is stealthy"); }
446  if (QUERY_FLAG(god, FLAG_MAKE_INVIS)) { gifts = 1; fprintf(stderr, "\n is (permanently) invisible"); }
447  if (QUERY_FLAG(god, FLAG_BLIND)) { gifts = 1; fprintf(stderr, "\n is blind"); }
448  if (god->last_heal) { gifts = 1; fprintf(stderr, "\n hp regenerate at %d", god->last_heal); }
449  if (god->last_sp) { gifts = 1; fprintf(stderr, "\n sp regenerate at %d", god->last_sp); }
450  if (god->last_eat) { gifts = 1; fprintf(stderr, "\n digestion is %s (%d)", god->last_eat < 0 ? "slowed" : "faster", god->last_eat); }
451  if (god->last_grace) { gifts = 1; fprintf(stderr, "\n grace regenerates at %d", god->last_grace); }
452  if (god->stats.luck) { gifts = 1; fprintf(stderr, "\n luck is %d", god->stats.luck); }
453  if (!gifts) fprintf(stderr, "NONE");
454  fprintf(stderr, "\n\n");
455  }
456 }
#define FLAG_SEE_IN_DARK
Definition: define.h:338
#define GOD_BLESSED
Definition: god.h:28
#define PATH_TURNING
Definition: spells.h:29
void stringbuffer_append_stringbuffer(StringBuffer *sb, const StringBuffer *sb2)
Definition: stringbuffer.c:131
StringBuffer * buf
Definition: readable.c:1591
#define FLAG_USE_ARMOUR
Definition: define.h:296
struct archt * arch
Definition: god.h:14
void fatal(enum fatal_error err)
Definition: utils.c:597
void archetypes_for_each(arch_op op)
Definition: assets.cpp:300
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
void free_string(sstring str)
Definition: shstr.c:280
#define HUGE_BUF
Definition: define.h:37
#define FLAG_STEALTH
Definition: define.h:313
#define GOD_HOLYWORD
Definition: god.h:25
Definition: god.h:12
#define FLAG_USE_WEAPON
Definition: define.h:297
void dump_gods(void)
Definition: holy.c:387
const char * name
Definition: god.h:13
#define FLAG_UNDEAD
Definition: define.h:270
#define GOD_RESISTANCES
Definition: god.h:26
int nstrtok(const char *buf1, const char *buf2)
Definition: readable.c:637
#define FLAG_REFL_SPELL
Definition: define.h:275
#define DESCRIBE_ABILITY(retbuf, variable, name)
Definition: holy.c:351
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.c:95
#define snprintf
Definition: win32.h:46
#define GOD_IMMUNITIES
Definition: god.h:29
godlink * get_rand_god(void)
Definition: holy.c:102
size_t stringbuffer_length(StringBuffer *sb)
Definition: stringbuffer.c:162
const object * pntr_to_god_obj(godlink *godlnk)
Definition: holy.c:124
#define FLAG_XRAYS
Definition: define.h:301
EXTERN godlink * first_god
Definition: global.h:120
int describe_god(const object *god, int what, StringBuffer *buf, size_t maxlen)
Definition: holy.c:138
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
static void add_god_to_list(archetype *god_arch)
Definition: holy.c:55
EXTERN const char *const attacktype_desc[NROFATTACKS]
Definition: attack.h:138
struct glnk * next
Definition: god.h:16
#define MAX_BUF
Definition: define.h:35
static godlink * init_godslist(void)
Definition: holy.c:37
#define FLAG_BLIND
Definition: define.h:337
#define RANDOM()
Definition: define.h:681
#define GOD_ENEMY
Definition: god.h:24
#define DESCRIBE_PATH(retbuf, variable, name)
Definition: holy.c:366
#define GOD_PATHS
Definition: god.h:30
#define GOD_SACRED
Definition: god.h:27
#define NROFATTACKS
Definition: attack.h:17
void init_gods(void)
Definition: holy.c:86
#define FLAG_MAKE_INVIS
Definition: define.h:329
char * strtoktolin(const char *buf1, const char *buf2, char *retbuf, size_t size)
Definition: readable.c:667
sstring add_string(const char *str)
Definition: shstr.c:124
StringBuffer * describe_resistance(const object *op, int newline, int use_media_tags, StringBuffer *buf)
Definition: item.c:367
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.c:104
StringBuffer * describe_spellpath_attenuation(const char *attenuation, int value, StringBuffer *buf)
Definition: utils.c:534
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
void free_all_god(void)
Definition: holy.c:338
#define FLAG_REFL_MISSILE
Definition: define.h:273
int id
Definition: god.h:15
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
#define PATH_SUMMON
Definition: spells.h:19