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