Crossfire Server, Trunk
holy.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 
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 #include <vector>
31 #include <algorithm>
32 
33 static std::vector<object *> gods;
34 
41 static void add_god_to_list(archetype *god_arch) {
42 
43  if (!god_arch) {
44  LOG(llevError, "ERROR: Tried to add null god to list!\n");
45  return;
46  }
47  if (!(god_arch->clone.type == GOD)) {
48  return;
49  }
50 
51  gods.push_back(&god_arch->clone);
52 
53 #ifdef DEBUG_GODS
54  LOG(llevDebug, "Adding god %s to list\n", god_arch->clone.name, god->id);
55 #endif
56 }
61 void init_gods(void) {
62  LOG(llevDebug, "Initializing gods...\n");
63 
65 
66  LOG(llevDebug, "done.\n");
67 }
68 
75 const object *get_rand_god(void) {
76  if (gods.empty()) {
77  return nullptr;
78  }
79  return gods[RANDOM() % gods.size()];
80 }
81 
92 const char *get_god_for_race(const char *race) {
93 
94  if (race == NULL)
95  return NULL;
96 
97  auto god = std::find_if(gods.begin(), gods.end(), [&] (const object *god) {
98  return god->race && !strcasecmp(god->race, race);
99  });
100  return god == gods.end() ? nullptr : (*god)->name;
101 }
102 
111 int describe_god(const object *god, int what, StringBuffer *buf, size_t maxlen) {
112  int hassomething = 0, real = 0;
113  char temp[HUGE_BUF];
114  StringBuffer *add;
115  const char *name;
116 
117  name = god->name;
118 
119  /* preamble.. */
120  assert(buf);
121  stringbuffer_append_printf(buf, "This document contains knowledge concerning the diety %s", name);
122 
123  /* Always have as default information the god's descriptive terms. */
124  if (nstrtok(god->msg, ",") > 0) {
125  stringbuffer_append_string(buf, ", known as");
126  stringbuffer_append_string(buf, strtoktolin(god->msg, ",", temp, sizeof(temp)));
127  } else
129 
130  stringbuffer_append_string(buf, "\n ---\n");
131 
132  if (what & GOD_PATHS) {
133  /* spell paths */
134  int has_effect = 0;
135 
136  add = stringbuffer_new();
137  stringbuffer_append_printf(add, "It is rarely known fact that the priests of %s are mystically transformed. Effects of this include:\n", name);
138 
139  if (god->path_attuned) {
140  has_effect = 1;
141  describe_spellpath_attenuation("Attuned", god->path_attuned, add);
142  }
143  if (god->path_repelled) {
144  has_effect = 1;
145  describe_spellpath_attenuation("Repelled", god->path_repelled, add);
146  }
147  if (god->path_denied) {
148  has_effect = 1;
149  describe_spellpath_attenuation("Denied", god->path_denied, add);
150  }
151  if (has_effect) {
152  stringbuffer_append_string(add, "\n ---\n");
153 
154  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
156  free(stringbuffer_finish(add));
157  hassomething = 1;
158  } else {
159  free(stringbuffer_finish(add));
160  return real;
161  }
162  } else {
163  free(stringbuffer_finish(add));
164  }
165  what |= GOD_PATHS;
166  }
167 
168  if (what & GOD_IMMUNITIES) {
169  int has_effect = 0, tmpvar;
170  char tmpbuf[MAX_BUF];
171 
172  add = stringbuffer_new();
173  stringbuffer_append_printf(add, "\nThe priests of %s are known to make cast a mighty prayer of possession which gives the recipient ", name);
174 
175  for (tmpvar = 0; tmpvar < NROFATTACKS; tmpvar++) {
176  if (god->resist[tmpvar] == 100) {
177  has_effect = 1;
178  snprintf(tmpbuf, MAX_BUF, "Immunity to %s", attacktype_desc[tmpvar]);
179  }
180  }
181  if (has_effect) {
182  stringbuffer_append_printf(add, "%s\n ---\n", tmpbuf);
183  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
185  free(stringbuffer_finish(add));
186  hassomething = 1;
187  } else {
188  free(stringbuffer_finish(add));
189  return real;
190  }
191  } else {
192  free(stringbuffer_finish(add));
193  }
194  real |= GOD_IMMUNITIES;
195  }
196 
197  if (what & GOD_BLESSED) {
198  char *cp = stringbuffer_finish(describe_resistance(god, 1, 1, NULL));
199 
200  if (*cp) { /* This god does have protections */
201  add = stringbuffer_new();
202  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);
203 
204  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
206  free(stringbuffer_finish(add));
207  hassomething = 1;
208  } else {
209  free(stringbuffer_finish(add));
210  return real;
211  }
212  }
213  free(cp);
214  real |= GOD_BLESSED;
215  }
216 
217  if (what & GOD_SACRED) {
218  if (god->race && !(god->path_denied&PATH_SUMMON)) {
219  int i = nstrtok(god->race, ",");
220  add = stringbuffer_new();
221  stringbuffer_append_printf(add, "Creatures sacred to %s include the\n", name);
222 
223  if (i > 1)
224  stringbuffer_append_printf(add, "following races:%s\n ---\n", strtoktolin(god->race, ",", temp, sizeof(temp)));
225  else
226  stringbuffer_append_printf(add, "race of %s\n ---\n", strtoktolin(god->race, ",", temp, sizeof(temp)));
227 
228  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
230  free(stringbuffer_finish(add));
231  hassomething = 1;
232  } else {
233  free(stringbuffer_finish(add));
234  return real;
235  }
236  }
237  real |= GOD_SACRED;
238  }
239 
240  if (what & GOD_RESISTANCES) {
241  char *cp;
242  cp = stringbuffer_finish(describe_resistance(god, 1, 1, NULL));
243 
244  if (*cp) { /* This god does have protections */
245  add = stringbuffer_new();
246  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);
247 
248  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
250  free(stringbuffer_finish(add));
251  hassomething = 1;
252  } else {
253  free(stringbuffer_finish(add));
254  return real;
255  }
256  }
257  free(cp);
258  real |= GOD_RESISTANCES;
259  }
260 
261  if (what & GOD_HOLYWORD) {
262  if ((god->slaying) && !(god->path_denied&PATH_TURNING)) {
263  add = stringbuffer_new();
264  stringbuffer_append_printf(add, "The holy words of %s have the power to slay creatures belonging to the ", name);
265 
266  if (nstrtok(god->slaying, ",") > 1)
267  stringbuffer_append_printf(add, "following races:%s\n ---\n", strtoktolin(god->slaying, ",", temp, sizeof(temp)));
268  else
269  stringbuffer_append_printf(add, "race of%s\n ---\n", strtoktolin(god->slaying, ",", temp, sizeof(temp)));
270 
271  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
273  free(stringbuffer_finish(add));
274  hassomething = 1;
275  } else {
276  free(stringbuffer_finish(add));
277  return real;
278  }
279  }
280  real |= GOD_HOLYWORD;
281  }
282 
283  if (what & GOD_ENEMY) {
284  if (god->title) {
285  add = stringbuffer_new();
286  stringbuffer_append_printf(add, "The gods %s and %s are enemies.\n ---\n", name, god->title);
287 
288  if ((maxlen == 0) || (stringbuffer_length(add) + stringbuffer_length(buf) < maxlen)) {
290  free(stringbuffer_finish(add));
291  hassomething = 1;
292  } else {
293  free(stringbuffer_finish(add));
294  return real;
295  }
296  }
297  real |= GOD_ENEMY;
298  }
299 
300  if (hassomething == 0) {
301  /* we got no information beyond the preamble! */
302  stringbuffer_append_string(buf, " Unfortunately the rest of the information is hopelessly garbled!\n ---\n");
303  }
304 
305  return real;
306 }
307 
319 const object *find_god(const char *name) {
320  auto found = std::find_if(gods.begin(), gods.end(), [&] (const object *god) {
321  return !strcmp(name, god->name);
322  });
323  return found == gods.end() ? nullptr : *found;
324 }
325 
329 void free_all_god(void) {
330  gods.clear();
331 }
332 
333 #define DESCRIBE_ABILITY(retbuf, variable, name) \
334  if (variable) { \
335  int i, j = 0; \
336  strcat(retbuf, "(" name ": "); \
337  for (i = 0; i < NROFATTACKS; i++) \
338  if (variable&(1<<i)) { \
339  if (j) \
340  strcat(retbuf, ", "); \
341  else \
342  j = 1; \
343  strcat(retbuf, attacks[i]); \
344  } \
345  strcat(retbuf, ")"); \
346  }
347 
348 #define DESCRIBE_PATH(retbuf, variable, name) \
349  if (variable) { \
350  int i, j = 0; \
351  strcat(retbuf, "(" name ": "); \
352  for (i = 0; i < NRSPELLPATHS; i++) \
353  if (variable&(1<<i)) { \
354  if (j) \
355  strcat(retbuf, ", "); \
356  else \
357  j = 1; \
358  strcat(retbuf, spellpathnames[i]); \
359  } \
360  strcat(retbuf, ")"); \
361  }
362 
369 void dump_gods(void) {
370 #if 0
371  godlink *glist;
372 
373  fprintf(stderr, "\n");
374  for (glist = first_god; glist; glist = glist->next) {
375  const object *god = &glist->arch->clone;
376  char tmpbuf[HUGE_BUF], *final;
377  int tmpvar, gifts = 0;
378 
379  fprintf(stderr, "GOD: %s\n", god->name);
380  fprintf(stderr, " avatar stats:\n");
381  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);
382  fprintf(stderr, " lvl:%d speed:%4.2f\n", god->level, god->speed);
383  fprintf(stderr, " wc:%d ac:%d hp:%d dam:%d\n", god->stats.wc, god->stats.ac, god->stats.hp, god->stats.dam);
384  fprintf(stderr, " enemy: %s\n", god->title ? god->title : "NONE");
385  if (god->other_arch) {
386  object *serv = &god->other_arch->clone;
387  fprintf(stderr, " servant stats: (%s)\n", god->other_arch->name);
388  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);
389  fprintf(stderr, " lvl:%d speed:%4.2f\n", serv->level, serv->speed);
390  fprintf(stderr, " wc:%d ac:%d hp:%d dam:%d\n", serv->stats.wc, serv->stats.ac, serv->stats.hp, serv->stats.dam);
391  } else
392  fprintf(stderr, " servant: NONE\n");
393  fprintf(stderr, " aligned_race(s): %s\n", god->race);
394  fprintf(stderr, " enemy_race(s): %s\n", (god->slaying ? god->slaying : "none"));
395  final = stringbuffer_finish(describe_resistance(god, 1, 1, NULL));
396  fprintf(stderr, "%s", final);
397  free(final);
398  snprintf(tmpbuf, sizeof(tmpbuf), " attacktype:");
399  if ((tmpvar = god->attacktype)) {
400  strcat(tmpbuf, "\n ");
401  DESCRIBE_ABILITY(tmpbuf, tmpvar, "Attacks");
402  }
403  strcat(tmpbuf, "\n aura:");
404 
405  strcat(tmpbuf, "\n paths:");
406  if ((tmpvar = god->path_attuned)) {
407  strcat(tmpbuf, "\n ");
408  DESCRIBE_PATH(tmpbuf, tmpvar, "Attuned");
409  }
410  if ((tmpvar = god->path_repelled)) {
411  strcat(tmpbuf, "\n ");
412  DESCRIBE_PATH(tmpbuf, tmpvar, "Repelled");
413  }
414  if ((tmpvar = god->path_denied)) {
415  strcat(tmpbuf, "\n ");
416  DESCRIBE_PATH(tmpbuf, tmpvar, "Denied");
417  }
418  fprintf(stderr, "%s\n", tmpbuf);
419  fprintf(stderr, " Desc: %s", god->msg ? god->msg : "---\n");
420  fprintf(stderr, " Priest gifts/limitations: ");
421  if (!QUERY_FLAG(god, FLAG_USE_WEAPON)) { gifts = 1; fprintf(stderr, "\n weapon use is forbidden"); }
422  if (!QUERY_FLAG(god, FLAG_USE_ARMOUR)) { gifts = 1; fprintf(stderr, "\n no armour may be worn"); }
423  if (QUERY_FLAG(god, FLAG_UNDEAD)) { gifts = 1; fprintf(stderr, "\n is undead"); }
424  if (QUERY_FLAG(god, FLAG_SEE_IN_DARK)) { gifts = 1; fprintf(stderr, "\n has infravision "); }
425  if (QUERY_FLAG(god, FLAG_XRAYS)) { gifts = 1; fprintf(stderr, "\n has X-ray vision"); }
426  if (QUERY_FLAG(god, FLAG_REFL_MISSILE)) { gifts = 1; fprintf(stderr, "\n reflect missiles"); }
427  if (QUERY_FLAG(god, FLAG_REFL_SPELL)) { gifts = 1; fprintf(stderr, "\n reflect spells"); }
428  if (QUERY_FLAG(god, FLAG_STEALTH)) { gifts = 1; fprintf(stderr, "\n is stealthy"); }
429  if (QUERY_FLAG(god, FLAG_MAKE_INVIS)) { gifts = 1; fprintf(stderr, "\n is (permanently) invisible"); }
430  if (QUERY_FLAG(god, FLAG_BLIND)) { gifts = 1; fprintf(stderr, "\n is blind"); }
431  if (god->last_heal) { gifts = 1; fprintf(stderr, "\n hp regenerate at %d", god->last_heal); }
432  if (god->last_sp) { gifts = 1; fprintf(stderr, "\n sp regenerate at %d", god->last_sp); }
433  if (god->last_eat) { gifts = 1; fprintf(stderr, "\n digestion is %s (%d)", god->last_eat < 0 ? "slowed" : "faster", god->last_eat); }
434  if (god->last_grace) { gifts = 1; fprintf(stderr, "\n grace regenerates at %d", god->last_grace); }
435  if (god->stats.luck) { gifts = 1; fprintf(stderr, "\n luck is %d", god->stats.luck); }
436  if (!gifts) fprintf(stderr, "NONE");
437  fprintf(stderr, "\n\n");
438  }
439 #endif
440 }
PATH_TURNING
#define PATH_TURNING
Definition: spells.h:29
global.h
GOD_IMMUNITIES
#define GOD_IMMUNITIES
Definition: god.h:18
liv::dam
int16_t dam
Definition: living.h:46
stringbuffer_length
size_t stringbuffer_length(StringBuffer *sb)
Definition: stringbuffer.cpp:218
llevError
@ llevError
Definition: logger.h:11
GOD_PATHS
#define GOD_PATHS
Definition: god.h:19
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
FLAG_UNDEAD
#define FLAG_UNDEAD
Definition: define.h:270
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:324
archetypes_for_each
void archetypes_for_each(arch_op op)
Definition: assets.cpp:305
liv::wc
int8_t wc
Definition: living.h:37
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Definition: stringbuffer.cpp:138
liv::Str
int8_t Str
Definition: living.h:36
FLAG_SEE_IN_DARK
#define FLAG_SEE_IN_DARK
Definition: define.h:337
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
obj::path_attuned
uint32_t path_attuned
Definition: object.h:351
liv::hp
int16_t hp
Definition: living.h:40
strtoktolin
char * strtoktolin(const char *buf1, const char *buf2, char *retbuf, size_t size)
Definition: readable.cpp:680
obj::path_denied
uint32_t path_denied
Definition: object.h:353
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
obj::msg
sstring msg
Definition: object.h:328
dump_gods
void dump_gods(void)
Definition: holy.cpp:369
GOD_BLESSED
#define GOD_BLESSED
Definition: god.h:17
FLAG_STEALTH
#define FLAG_STEALTH
Definition: define.h:312
FLAG_BLIND
#define FLAG_BLIND
Definition: define.h:336
buf
StringBuffer * buf
Definition: readable.cpp:1611
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
GOD_HOLYWORD
#define GOD_HOLYWORD
Definition: god.h:14
find_god
const object * find_god(const char *name)
Definition: holy.cpp:319
archt
Definition: object.h:472
obj::last_heal
int32_t last_heal
Definition: object.h:365
obj::slaying
sstring slaying
Definition: object.h:325
init_gods
void init_gods(void)
Definition: holy.cpp:61
liv::luck
int8_t luck
Definition: living.h:39
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
get_rand_god
const object * get_rand_god(void)
Definition: holy.cpp:75
obj::name
sstring name
Definition: object.h:317
describe_resistance
StringBuffer * describe_resistance(const object *op, int newline, int use_media_tags, StringBuffer *buf)
Definition: item.cpp:369
DESCRIBE_ABILITY
#define DESCRIBE_ABILITY(retbuf, variable, name)
Definition: holy.cpp:333
obj::path_repelled
uint32_t path_repelled
Definition: object.h:352
describe_spellpath_attenuation
StringBuffer * describe_spellpath_attenuation(const char *attenuation, int value, StringBuffer *buf)
Definition: utils.cpp:517
FLAG_MAKE_INVIS
#define FLAG_MAKE_INVIS
Definition: define.h:328
PATH_SUMMON
#define PATH_SUMMON
Definition: spells.h:19
obj::other_arch
struct archt * other_arch
Definition: object.h:421
obj::speed
float speed
Definition: object.h:335
liv::Con
int8_t Con
Definition: living.h:36
get_god_for_race
const char * get_god_for_race(const char *race)
Definition: holy.cpp:92
FLAG_USE_WEAPON
#define FLAG_USE_WEAPON
Definition: define.h:296
stringbuffer_append_string
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Definition: stringbuffer.cpp:95
liv::Int
int8_t Int
Definition: living.h:36
add_god_to_list
static void add_god_to_list(archetype *god_arch)
Definition: holy.cpp:41
MAX_BUF
#define MAX_BUF
Definition: define.h:35
free_all_god
void free_all_god(void)
Definition: holy.cpp:329
RANDOM
#define RANDOM()
Definition: define.h:644
StringBuffer
Definition: stringbuffer.cpp:25
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
GOD_RESISTANCES
#define GOD_RESISTANCES
Definition: god.h:15
obj::title
sstring title
Definition: object.h:323
FLAG_REFL_SPELL
#define FLAG_REFL_SPELL
Definition: define.h:275
obj::type
uint8_t type
Definition: object.h:346
obj::last_grace
int16_t last_grace
Definition: object.h:367
spells.h
obj::stats
living stats
Definition: object.h:376
attacktype_desc
const char *const attacktype_desc[NROFATTACKS]
Definition: init.cpp:40
DESCRIBE_PATH
#define DESCRIBE_PATH(retbuf, variable, name)
Definition: holy.cpp:348
archt::clone
object clone
Definition: object.h:476
liv::Dex
int8_t Dex
Definition: living.h:36
FLAG_USE_ARMOUR
#define FLAG_USE_ARMOUR
Definition: define.h:295
liv::Wis
int8_t Wis
Definition: living.h:36
GOD_ENEMY
#define GOD_ENEMY
Definition: god.h:13
obj::last_sp
int32_t last_sp
Definition: object.h:366
assets.h
stringbuffer_append_stringbuffer
void stringbuffer_append_stringbuffer(StringBuffer *sb, const StringBuffer *sb2)
Definition: stringbuffer.cpp:165
gods
static std::vector< object * > gods
Definition: holy.cpp:33
obj::last_eat
int32_t last_eat
Definition: object.h:364
liv::ac
int8_t ac
Definition: living.h:38
archt::name
sstring name
Definition: object.h:473
FLAG_XRAYS
#define FLAG_XRAYS
Definition: define.h:300
describe_god
int describe_god(const object *god, int what, StringBuffer *buf, size_t maxlen)
Definition: holy.cpp:111
obj::attacktype
uint32_t attacktype
Definition: object.h:350
guildbuy.temp
def temp
Definition: guildbuy.py:26
nstrtok
int nstrtok(const char *buf1, const char *buf2)
Definition: readable.cpp:638
living.h
obj::resist
int16_t resist[NROFATTACKS]
Definition: object.h:349
liv::Pow
int8_t Pow
Definition: living.h:36
obj::level
int16_t level
Definition: object.h:359
GOD
@ GOD
Definition: object.h:151
libproto.h
llevDebug
@ llevDebug
Definition: logger.h:13
GOD_SACRED
#define GOD_SACRED
Definition: god.h:16
give.name
name
Definition: give.py:27