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