version 1.36 | | version 1.37 |
---|
| | |
/* | | /* |
* static char *rcsid_gods_c = | | * static char *rcsid_gods_c = |
* "$Id: gods.c,v 1.36 2003/06/26 11:27:43 gros Exp $"; | | * "$Id: gods.c,v 1.37 2003/09/13 05:02:10 mwedel Exp $"; |
*/ | | */ |
| | |
/* | | /* |
| | |
#include <sproto.h> | | #include <sproto.h> |
#endif | | #endif |
| | |
static int god_gives_present (object *op, object *god, treasure *tr); | | |
static void follower_remove_similar_item (object *op, object *item); | | |
| | |
int lookup_god_by_name(char *name) { | | int lookup_god_by_name(char *name) { |
int godnr=-1,nmlen = strlen(name); | | int godnr=-1,nmlen = strlen(name); |
| | |
| | |
| | |
if(name) { | | if(name) { |
godlink *gl; | | godlink *gl; |
| | |
for(gl=first_god;gl;gl=gl->next) | | for(gl=first_god;gl;gl=gl->next) |
if(!strcmp(name,gl->name)) break; | | if(!strcmp(name,gl->name)) break; |
if(gl) god=pntr_to_god_obj(gl); | | if(gl) god=pntr_to_god_obj(gl); |
| | |
return god; | | return god; |
} | | } |
| | |
void pray_at_altar(object *pl, object *altar) { | | /* determine_god() - determines if op worships a god. Returns |
| | * the godname if they do. In the case of an NPC, if they have |
| | * no god, we give them a random one. -b.t. |
| | */ |
| | |
| | char *determine_god(object *op) { |
| | int godnr = -1; |
| | |
| | /* spells */ |
| | if ((op->type == SPELL || op->type == SPELL_EFFECT) && |
| | op->title) |
| | { |
| | if (lookup_god_by_name(op->title)>=0) return op->title; |
| | } |
| | |
| | if(op->type!= PLAYER && QUERY_FLAG(op,FLAG_ALIVE)) { |
| | if(!op->title) { |
| | godlink *gl=first_god; |
| | |
| | godnr = rndm(1, gl->id); |
| | while(gl) { |
| | if(gl->id==godnr) break; |
| | gl=gl->next; |
| | } |
| | op->title = add_string(gl->name); |
| | } |
| | return op->title; |
| | } |
| | |
| | |
| | /* The god the player worships is in the praying skill (native skill |
| | * not skill tool). Since a player can only have one instance of |
| | * that skill, once we find it, we can return, either with the |
| | * title or "none". |
| | */ |
| | if(op->type==PLAYER) { |
| | object *tmp; |
| | for (tmp=op->inv; tmp!=NULL; tmp=tmp->below) |
| | if (tmp->type == SKILL && tmp->subtype == SK_PRAYING) { |
| | if (tmp->title) return (tmp->title); |
| | else return("none"); |
| | } |
| | } |
| | return ("none"); |
| | } |
| | |
| | static int same_string (const char *s1, const char *s2) |
| | { |
| | if (s1 == NULL) |
| | if (s2 == NULL) |
| | return 1; |
| | else |
| | return 0; |
| | else |
| | if (s2 == NULL) |
| | return 0; |
| | else |
| | return strcmp (s1, s2) == 0; |
| | } |
| | |
| | |
| | /* |
| | * follower_remove_similar_item - Checks for any occurrence of |
| | * the given 'item' in the inventory of 'op' (recursively). |
| | * Any matching items in the inventory are deleted, and a |
| | * message is displayed to the player. |
| | */ |
| | static void follower_remove_similar_item (object *op, object *item) |
| | { |
| | object *tmp, *next; |
| | |
| | if (op && op->type == PLAYER && op->contr) { |
| | /* search the inventory */ |
| | for (tmp = op->inv; tmp != NULL; tmp = next) { |
| | next = tmp->below; /* backup in case we remove tmp */ |
| | |
| | if (tmp->type == item->type |
| | && same_string (tmp->name, item->name) |
| | && same_string (tmp->title, item->title) |
| | && same_string (tmp->msg, item->msg) |
| | && same_string (tmp->slaying, item->slaying)) { |
| | |
| | /* message */ |
| | if (tmp->nrof > 1) |
| | new_draw_info_format(NDI_UNIQUE,0,op, |
| | "The %s crumble to dust!", query_short_name(tmp)); |
| | else |
| | new_draw_info_format(NDI_UNIQUE,0,op, |
| | "The %s crumbles to dust!", query_short_name(tmp)); |
| | |
| | remove_ob(tmp); /* remove obj from players inv. */ |
| | esrv_del_item(op->contr, tmp->count); /* notify client */ |
| | free_object(tmp); /* free object */ |
| | } |
| | if (tmp->inv) |
| | follower_remove_similar_item(tmp, item); |
| | } |
| | } |
| | } |
| | |
| | /* |
| | * follower_has_similar_item - Checks for any occurrence of |
| | * the given 'item' in the inventory of 'op' (recursively). |
| | * Returns 1 if found, else 0. |
| | */ |
| | static int follower_has_similar_item (object *op, object *item) |
| | { |
| | object *tmp; |
| | |
| | for (tmp = op->inv; tmp != NULL; tmp = tmp->below) { |
| | if (tmp->type == item->type |
| | && same_string (tmp->name, item->name) |
| | && same_string (tmp->title, item->title) |
| | && same_string (tmp->msg, item->msg) |
| | && same_string (tmp->slaying, item->slaying)) |
| | return 1; |
| | if (tmp->inv && follower_has_similar_item (tmp, item)) |
| | return 1; |
| | } |
| | return 0; |
| | } |
| | |
| | static int god_gives_present (object *op, object *god, treasure *tr) |
| | { |
| | object *tmp; |
| | |
| | if (follower_has_similar_item (op, &tr->item->clone)) |
| | return 0; |
| | |
| | tmp = arch_to_object (tr->item); |
| | new_draw_info_format (NDI_UNIQUE, 0, op, |
| | "%s lets %s appear in your hands.", god->name, query_short_name (tmp)); |
| | tmp = insert_ob_in_ob (tmp, op); |
| | if (op->type == PLAYER) |
| | esrv_send_item (op, tmp); |
| | return 1; |
| | } |
| | |
| | void pray_at_altar(object *pl, object *altar, object *skill) { |
object *pl_god=find_god(determine_god(pl)); | | object *pl_god=find_god(determine_god(pl)); |
int return_pray_script; /* GROS : This is for return value of script */ | | int return_pray_script; /* GROS : This is for return value of script */ |
event *evt; | | event *evt; |
| | |
return; | | return; |
| | |
} else if(!strcmp(pl_god->name,altar->other_arch->clone.name)) { /* pray at your gods altar */ | | } else if(!strcmp(pl_god->name,altar->other_arch->clone.name)) { /* pray at your gods altar */ |
int bonus = ((pl->stats.Wis/10)+(SK_level(pl)/10)); | | int bonus = (pl->stats.Wis+skill->level)/10; |
| | |
/* we can get neg grace up faster */ | | /* we can get neg grace up faster */ |
if(pl->stats.grace<0) pl->stats.grace+=(bonus>-1*(pl->stats.grace/10) ? | | if(pl->stats.grace<0) pl->stats.grace+=(bonus>-1*(pl->stats.grace/10) ? |
| | |
if(pl->stats.grace<(2*pl->stats.maxgrace)) { | | if(pl->stats.grace<(2*pl->stats.maxgrace)) { |
pl->stats.grace+=bonus/2; | | pl->stats.grace+=bonus/2; |
} | | } |
/* I think there was a bug here in that this was nested | | |
* in the if immediately above | | |
*/ | | |
if(pl->stats.grace>(2*pl->stats.maxgrace)) { | | if(pl->stats.grace>(2*pl->stats.maxgrace)) { |
pl->stats.grace=(2*pl->stats.maxgrace); | | pl->stats.grace=(2*pl->stats.maxgrace); |
} | | } |
| | |
bonus = MAX(1, bonus + MAX(pl->stats.luck, -3)); /* -- DAMN -- */ | | bonus = MAX(1, bonus + MAX(pl->stats.luck, -3)); /* -- DAMN -- */ |
| | |
if(((random_roll(0, 399, pl, PREFER_LOW))-bonus)<0) | | if(((random_roll(0, 399, pl, PREFER_LOW))-bonus)<0) |
god_intervention(pl,pl_god); | | god_intervention(pl,pl_god, skill); |
| | |
} else { /* praying to another god! */ | | } else { /* praying to another god! */ |
int loss = 0,angry=1; | | int loss = 0,angry=1; |
| | |
*/ | | */ |
if(pl_god->other_arch && (altar->other_arch->name==pl_god->other_arch->name)) { | | if(pl_god->other_arch && (altar->other_arch->name==pl_god->other_arch->name)) { |
angry=2; | | angry=2; |
if(random_roll(0, SK_level(pl)+2, pl, PREFER_LOW)-5 > 0) { | | if(random_roll(0, skill->level+2, pl, PREFER_LOW)-5 > 0) { |
| | object *tmp; |
| | |
/* you really screwed up */ | | /* you really screwed up */ |
angry=3; | | angry=3; |
new_draw_info_format(NDI_UNIQUE|NDI_NAVY,0,pl, | | new_draw_info_format(NDI_UNIQUE|NDI_NAVY,0,pl, |
"Foul Priest! %s punishes you!",pl_god->name); | | "Foul Priest! %s punishes you!",pl_god->name); |
cast_mana_storm(pl,pl_god->level+20); | | tmp=get_archetype(LOOSE_MANA); |
| | cast_magic_storm(pl,tmp, pl_god->level+20); |
} | | } |
new_draw_info_format(NDI_UNIQUE|NDI_NAVY,0,pl, | | new_draw_info_format(NDI_UNIQUE|NDI_NAVY,0,pl, |
"Foolish heretic! %s is livid!",pl_god->name); | | "Foolish heretic! %s is livid!",pl_god->name); |
| | |
"Heretic! %s is angered!",pl_god->name); | | "Heretic! %s is angered!",pl_god->name); |
| | |
/* whether we will be successfull in defecting or not - | | /* whether we will be successfull in defecting or not - |
* we lose experience from the clerical experience obj */ | | * we lose experience from the clerical experience obj |
| | */ |
| | |
loss = 0.1 * (float) pl->chosen_skill->exp_obj->stats.exp; | | loss = 0.1 * (float) skill->stats.exp; |
if(loss) | | if(loss) |
lose_priest_exp(pl, random_roll(0, loss*angry-1, pl, PREFER_LOW)); | | change_exp(pl, -random_roll(0, loss*angry-1, pl, PREFER_LOW), |
| | skill?skill->skill:"none", SK_SUBTRACT_SKILL_EXP); |
| | |
/* May switch Gods, but its random chance based on our current level | | /* May switch Gods, but its random chance based on our current level |
* note it gets harder to swap gods the higher we get */ | | * note it gets harder to swap gods the higher we get |
if((angry==1) && | | */ |
!(random_roll(0, pl->chosen_skill->exp_obj->level, pl, | | if((angry==1) && !(random_roll(0, skill->level, pl, PREFER_LOW))) { |
PREFER_LOW))) { | | |
become_follower(pl,&altar->other_arch->clone); | | become_follower(pl,&altar->other_arch->clone); |
} /* If angry... switching gods */ | | } else { |
else { /* toss this player off the altar. He can try again. */ | | /* toss this player off the altar. He can try again. */ |
new_draw_info_format(NDI_UNIQUE|NDI_NAVY,0,pl, | | new_draw_info(NDI_UNIQUE|NDI_NAVY,0,pl, |
"A divine force pushes you off the altar."); | | "A divine force pushes you off the altar."); |
move_player(pl,absdir(pl->facing + 4)); /* back him off the way he came. */ | | move_player(pl,absdir(pl->facing + 4)); /* back him off the way he came. */ |
} /* didn't successfully change, so forced off altar. */ | | |
} /* If prayed at altar to other god */ | | |
} | | } |
| | } |
static int get_spell_number (object *op) | | |
{ | | |
int spell; | | |
| | |
if (op->slaying && (spell = look_up_spell_name (op->slaying)) >= 0) | | |
return spell; | | |
else | | |
return op->stats.sp; | | |
} | | } |
| | |
static void check_special_prayers (object *op, object *god) | | static void check_special_prayers (object *op, object *god) |
| | |
*/ | | */ |
treasure *tr; | | treasure *tr; |
object *tmp, *next_tmp; | | object *tmp, *next_tmp; |
int spell; | | int remove=0; |
| | |
/* Outer loop iterates over all special prayer marks */ | | /* Outer loop iterates over all special prayer marks */ |
for (tmp = op->inv; tmp; tmp = next_tmp) | | for (tmp = op->inv; tmp; tmp = next_tmp) { |
{ | | |
next_tmp = tmp->below; | | next_tmp = tmp->below; |
| | |
if (tmp->type != FORCE || tmp->slaying == NULL | | if (tmp->type != FORCE || tmp->slaying == NULL |
|| strcmp (tmp->slaying, "special prayer") != 0) | | || strcmp (tmp->slaying, "special prayer") != 0) |
continue; | | continue; |
spell = tmp->stats.sp; | | |
| | |
if (god->randomitems == NULL) { | | if (god->randomitems == NULL) { |
LOG (llevError, "BUG: check_special_prayers(): %s without " | | LOG (llevError, "BUG: check_special_prayers(): god %s without randomitems\n", god->name); |
"randomitems\n", god->name); | | do_forget_spell (op, tmp->name); |
do_forget_spell (op, spell); | | |
continue; | | continue; |
} | | } |
| | |
/* Inner loop tries to find the special prayer in the god's treasure | | /* Inner loop tries to find the special prayer in the god's treasure |
* list. */ | | * list. We default that the spell should be removed. |
| | */ |
| | remove=1; |
for (tr = god->randomitems->items; tr; tr = tr->next) | | for (tr = god->randomitems->items; tr; tr = tr->next) |
{ | | { |
object *item; | | object *item; |
| | |
continue; | | continue; |
item = &tr->item->clone; | | item = &tr->item->clone; |
| | |
if (item->type == SPELLBOOK && get_spell_number (item) == spell) | | if (tr->item->clone.type == SPELL && tr->item->clone.name == tmp->name) { |
{ | | remove=0; |
/* Current god allows this special prayer. */ | | |
spell = -1; | | |
break; | | break; |
} | | } |
} | | } |
| | if (remove) |
if (spell >= 0) | | do_forget_spell (op, tmp->name); |
do_forget_spell (op, spell); | | |
} | | } |
} | | } |
| | |
| | |
* items (from the former cult). | | * items (from the former cult). |
*/ | | */ |
void become_follower (object *op, object *new_god) { | | void become_follower (object *op, object *new_god) { |
object *exp_obj = op->chosen_skill->exp_obj; /* obj. containing god data */ | | |
object *old_god = NULL; /* old god */ | | object *old_god = NULL; /* old god */ |
treasure *tr; | | treasure *tr; |
object *item; | | object *item, *skop; |
int i; | | int i; |
| | |
/* get old god */ | | old_god = find_god(determine_god(op)); |
if (exp_obj->title) | | |
old_god = find_god(exp_obj->title); | | |
| | |
/* take away any special god-characteristic items. */ | | /* take away any special god-characteristic items. */ |
for(item=op->inv;item!=NULL;item=item->below) { | | for(item=op->inv;item!=NULL;item=item->below) { |
if(QUERY_FLAG(item,FLAG_STARTEQUIP) && item->invisible) { | | if(QUERY_FLAG(item,FLAG_STARTEQUIP) && item->invisible) { |
/* remove all invisible startequ. items which are | | /* remove all invisible startequip items which are |
not skill, exp or force */ | | * not skill, exp or force |
| | */ |
if(item->type==SKILL || item->type==EXPERIENCE || | | if(item->type==SKILL || item->type==EXPERIENCE || |
item->type==FORCE) continue; | | item->type==FORCE) continue; |
remove_ob(item); | | remove_ob(item); |
| | |
} | | } |
} | | } |
| | |
/* give the player any special god-characteristic-items. */ | | |
for(tr=new_god->randomitems->items; tr!=NULL; tr = tr->next) { | | |
if(tr->item && tr->item->clone.invisible && tr->item->clone.type != SPELLBOOK && | | |
tr->item->clone.type != BOOK) | | |
god_gives_present(op,new_god,tr); } | | |
| | |
if(!op||!new_god) return; | | if(!op||!new_god) return; |
| | |
if(op->race&&new_god->slaying&&strstr(op->race,new_god->slaying)) { | | if(op->race&&new_god->slaying&&strstr(op->race,new_god->slaying)) { |
new_draw_info_format(NDI_UNIQUE|NDI_NAVY,0,op,"Fool! %s detests your kind!", | | new_draw_info_format(NDI_UNIQUE|NDI_NAVY,0,op,"Fool! %s detests your kind!", |
new_god->name); | | new_god->name); |
if(random_roll(0, op->level-1, op, PREFER_LOW)-5>0) | | if(random_roll(0, op->level-1, op, PREFER_LOW)-5>0) { |
cast_mana_storm(op,new_god->level+10); | | object *tmp = get_archetype(LOOSE_MANA); |
| | cast_magic_storm(op,tmp, new_god->level+10); |
| | } |
return; | | return; |
} | | } |
| | |
| | |
| | /* give the player any special god-characteristic-items. */ |
| | for(tr=new_god->randomitems->items; tr!=NULL; tr = tr->next) { |
| | if(tr->item && tr->item->clone.invisible && tr->item->clone.type != SPELLBOOK && |
| | tr->item->clone.type != BOOK) |
| | god_gives_present(op,new_god,tr); } |
| | |
| | |
new_draw_info_format(NDI_UNIQUE|NDI_NAVY,0,op, | | new_draw_info_format(NDI_UNIQUE|NDI_NAVY,0,op, |
"You become a follower of %s!",new_god->name); | | "You become a follower of %s!",new_god->name); |
| | |
if(exp_obj->title) { /* get rid of old god */ | | for (skop = op->inv; skop != NULL; skop=skop->below) |
| | if (skop->type == SKILL && skop->subtype == SK_PRAYING) break; |
| | |
| | /* Player has no skill - give them the skill */ |
| | if (!skop) { |
| | /* The arhetype should always be defined - if we crash here because it doesn't, |
| | * things are really messed up anyways. |
| | */ |
| | skop = give_skill_by_name(op, get_archetype_by_type_subtype(SKILL, SK_PRAYING)->clone.skill); |
| | } |
| | |
| | if(skop->title) { /* get rid of old god */ |
new_draw_info_format(NDI_UNIQUE,0,op, | | new_draw_info_format(NDI_UNIQUE,0,op, |
"%s's blessing is withdrawn from you.",exp_obj->title); | | "%s's blessing is withdrawn from you.",skop->title); |
CLEAR_FLAG(exp_obj,FLAG_APPLIED); | | /* The point of this is to really show what abilities the player just lost */ |
(void) change_abil(op,exp_obj); | | if (QUERY_FLAG(skop, FLAG_APPLIED)) { |
free_string(exp_obj->title); | | CLEAR_FLAG(skop,FLAG_APPLIED); |
| | (void) change_abil(op,skop); |
| | } |
| | free_string(skop->title); |
} | | } |
| | |
/* now change to the new gods attributes to exp_obj */ | | /* now change to the new gods attributes to exp_obj */ |
exp_obj->title = add_string(new_god->name); | | skop->title = add_string(new_god->name); |
exp_obj->path_attuned=new_god->path_attuned; | | skop->path_attuned=new_god->path_attuned; |
exp_obj->path_repelled=new_god->path_repelled; | | skop->path_repelled=new_god->path_repelled; |
exp_obj->path_denied=new_god->path_denied; | | skop->path_denied=new_god->path_denied; |
/* copy god's resistances */ | | /* copy god's resistances */ |
memcpy(exp_obj->resist, new_god->resist, sizeof(new_god->resist)); | | memcpy(skop->resist, new_god->resist, sizeof(new_god->resist)); |
| | |
/* make sure that certain immunities do NOT get passed | | /* make sure that certain immunities do NOT get passed |
* to the follower! */ | | * to the follower! |
| | */ |
for (i=0; i<NROFATTACKS; i++) | | for (i=0; i<NROFATTACKS; i++) |
if (exp_obj->resist[i] > 30 && (i==ATNR_FIRE || i==ATNR_COLD || | | if (skop->resist[i] > 30 && (i==ATNR_FIRE || i==ATNR_COLD || |
i==ATNR_ELECTRICITY || i==ATNR_POISON)) | | i==ATNR_ELECTRICITY || i==ATNR_POISON)) |
exp_obj->resist[i] = 30; | | skop->resist[i] = 30; |
| | |
exp_obj->stats.hp= (sint16) new_god->last_heal; | | skop->stats.hp= (sint16) new_god->last_heal; |
exp_obj->stats.sp= (sint16) new_god->last_sp; | | skop->stats.sp= (sint16) new_god->last_sp; |
exp_obj->stats.grace= (sint16) new_god->last_grace; | | skop->stats.grace= (sint16) new_god->last_grace; |
exp_obj->stats.food= (sint16) new_god->last_eat; | | skop->stats.food= (sint16) new_god->last_eat; |
exp_obj->stats.luck= (sint8) new_god->stats.luck; | | skop->stats.luck= (sint8) new_god->stats.luck; |
/* gods may pass on certain flag properties */ | | /* gods may pass on certain flag properties */ |
update_priest_flag(new_god,exp_obj,FLAG_SEE_IN_DARK); | | update_priest_flag(new_god,skop,FLAG_SEE_IN_DARK); |
update_priest_flag(new_god,exp_obj,FLAG_REFL_SPELL); | | update_priest_flag(new_god,skop,FLAG_REFL_SPELL); |
update_priest_flag(new_god,exp_obj,FLAG_REFL_MISSILE); | | update_priest_flag(new_god,skop,FLAG_REFL_MISSILE); |
update_priest_flag(new_god,exp_obj,FLAG_STEALTH); | | update_priest_flag(new_god,skop,FLAG_STEALTH); |
update_priest_flag(new_god,exp_obj,FLAG_MAKE_INVIS); | | update_priest_flag(new_god,skop,FLAG_MAKE_INVIS); |
update_priest_flag(new_god,exp_obj,FLAG_UNDEAD); | | update_priest_flag(new_god,skop,FLAG_UNDEAD); |
update_priest_flag(new_god,exp_obj,FLAG_BLIND); | | update_priest_flag(new_god,skop,FLAG_BLIND); |
update_priest_flag(new_god,exp_obj,FLAG_XRAYS); /* better have this if blind! */ | | update_priest_flag(new_god,skop,FLAG_XRAYS); /* better have this if blind! */ |
| | |
new_draw_info_format(NDI_UNIQUE,0,op, | | new_draw_info_format(NDI_UNIQUE,0,op, |
"You are bathed in %s's aura.",new_god->name); | | "You are bathed in %s's aura.",new_god->name); |
| | |
/* Weapon/armour use are special...handle flag toggles here as this can | | /* Weapon/armour use are special...handle flag toggles here as this can |
* only happen when gods are worshipped and if the new priest could | | * only happen when gods are worshipped and if the new priest could |
* have used armour/weapons in the first place */ | | * have used armour/weapons in the first place */ |
update_priest_flag(new_god,exp_obj,FLAG_USE_WEAPON); | | update_priest_flag(new_god,skop,FLAG_USE_WEAPON); |
update_priest_flag(new_god,exp_obj,FLAG_USE_ARMOUR); | | update_priest_flag(new_god,skop,FLAG_USE_ARMOUR); |
| | |
if(worship_forbids_use(op,exp_obj,FLAG_USE_WEAPON,"weapons")) | | if(worship_forbids_use(op,skop,FLAG_USE_WEAPON,"weapons")) |
stop_using_item(op,WEAPON,2); | | stop_using_item(op,WEAPON,2); |
| | |
if(worship_forbids_use(op,exp_obj,FLAG_USE_ARMOUR,"armour")) { | | if(worship_forbids_use(op,skop,FLAG_USE_ARMOUR,"armour")) { |
stop_using_item(op,ARMOUR,1); | | stop_using_item(op,ARMOUR,1); |
stop_using_item(op,HELMET,1); | | stop_using_item(op,HELMET,1); |
stop_using_item(op,BOOTS,1); | | stop_using_item(op,BOOTS,1); |
| | |
stop_using_item(op,SHIELD,1); | | stop_using_item(op,SHIELD,1); |
} | | } |
| | |
SET_FLAG(exp_obj,FLAG_APPLIED); | | SET_FLAG(skop,FLAG_APPLIED); |
(void) change_abil(op,exp_obj); | | (void) change_abil(op,skop); |
| | |
check_special_prayers (op, new_god); | | check_special_prayers (op, new_god); |
} | | } |
| | |
} | | } |
| | |
| | |
/* determine_god() - determines if op worships a god. Returns | | |
* the godname if they do. In the case of an NPC, if they have | | |
* no god, we give them a random one. -b.t. | | |
*/ | | |
| | |
char *determine_god(object *op) { | | |
int godnr = -1; | | |
| | |
/* spells */ | | |
if ((op->type == FBULLET || op->type == CONE || op->type == FBALL | | |
|| op->type == SWARM_SPELL) && op->title) | | |
{ | | |
if(lookup_god_by_name(op->title)>=0) return op->title; | | |
} | | |
| | |
if(op->type!= PLAYER && QUERY_FLAG(op,FLAG_ALIVE)) { | | |
if(!op->title) { | | |
godlink *gl=first_god; | | |
| | |
godnr = rndm(1, gl->id); | | |
while(gl) { | | |
if(gl->id==godnr) break; | | |
gl=gl->next; | | |
} | | |
op->title = add_string(gl->name); | | |
} | | |
return op->title; | | |
} | | |
| | |
| | |
/* If we are player, lets search a bit harder for the god. This | | |
* is a fix for perceive self (before, we just looked at the active | | |
* skill.) | | |
*/ | | |
if(op->type==PLAYER) { | | |
object *tmp; | | |
for (tmp=op->inv; tmp!=NULL; tmp=tmp->below) | | |
{ | | |
if (tmp->type == SKILL) /* GROS: This is for the flower's bug */ | | |
{ | | |
if (tmp->exp_obj && tmp->exp_obj->title) | | |
return tmp->exp_obj->title; | | |
} | | |
} | | |
| | |
} | | |
| | |
return ("none"); | | |
} | | |
| | |
| | |
archetype *determine_holy_arch (object *god, const char *type) | | archetype *determine_holy_arch (object *god, const char *type) |
{ | | { |
| | |
return (30 + (level - 40) / 4) / difficulty; | | return (30 + (level - 40) / 4) / difficulty; |
} | | } |
| | |
static int god_enchants_weapon (object *op, object *god, object *tr) | | static int god_enchants_weapon (object *op, object *god, object *tr, object *skill) |
{ | | { |
char buf[MAX_BUF]; | | char buf[MAX_BUF]; |
object *weapon; | | object *weapon; |
| | |
} | | } |
| | |
/* Higher magic value */ | | /* Higher magic value */ |
tmp = follower_level_to_enchantments (SK_level (op), tr->level); | | tmp = follower_level_to_enchantments (skill->level, tr->level); |
if (weapon->magic < tmp) { | | if (weapon->magic < tmp) { |
new_draw_info (NDI_UNIQUE, 0, op, | | new_draw_info (NDI_UNIQUE, 0, op, |
"A phosphorescent glow envelops your weapon!"); | | "A phosphorescent glow envelops your weapon!"); |
| | |
return 0; | | return 0; |
} | | } |
| | |
static int same_string (const char *s1, const char *s2) | | |
{ | | |
if (s1 == NULL) | | |
if (s2 == NULL) | | |
return 1; | | |
else | | |
return 0; | | |
else | | |
if (s2 == NULL) | | |
return 0; | | |
else | | |
return strcmp (s1, s2) == 0; | | |
} | | |
| | |
/* | | |
* follower_has_similar_item - Checks for any occurrence of | | |
* the given 'item' in the inventory of 'op' (recursively). | | |
* Returns 1 if found, else 0. | | |
*/ | | |
static int follower_has_similar_item (object *op, object *item) | | |
{ | | |
object *tmp; | | |
| | |
for (tmp = op->inv; tmp != NULL; tmp = tmp->below) { | | |
if (tmp->type == item->type | | |
&& same_string (tmp->name, item->name) | | |
&& same_string (tmp->title, item->title) | | |
&& same_string (tmp->msg, item->msg) | | |
&& same_string (tmp->slaying, item->slaying)) | | |
return 1; | | |
if (tmp->inv && follower_has_similar_item (tmp, item)) | | |
return 1; | | |
} | | |
return 0; | | |
} | | |
| | |
/* | | |
* follower_remove_similar_item - Checks for any occurrence of | | |
* the given 'item' in the inventory of 'op' (recursively). | | |
* Any matching items in the inventory are deleted, and a | | |
* message is displayed to the player. | | |
*/ | | |
static void follower_remove_similar_item (object *op, object *item) | | |
{ | | |
object *tmp, *next; | | |
| | |
if (op && op->type == PLAYER && op->contr) { | | |
/* search the inventory */ | | |
for (tmp = op->inv; tmp != NULL; tmp = next) { | | |
next = tmp->below; /* backup in case we remove tmp */ | | |
| | |
if (tmp->type == item->type | | |
&& same_string (tmp->name, item->name) | | |
&& same_string (tmp->title, item->title) | | |
&& same_string (tmp->msg, item->msg) | | |
&& same_string (tmp->slaying, item->slaying)) { | | |
| | |
/* message */ | | |
if (tmp->nrof > 1) | | |
new_draw_info_format(NDI_UNIQUE,0,op, | | |
"The %s crumble to dust!", query_short_name(tmp)); | | |
else | | |
new_draw_info_format(NDI_UNIQUE,0,op, | | |
"The %s crumbles to dust!", query_short_name(tmp)); | | |
| | |
remove_ob(tmp); /* remove obj from players inv. */ | | |
esrv_del_item(op->contr, tmp->count); /* notify client */ | | |
free_object(tmp); /* free object */ | | |
} | | |
if (tmp->inv) | | |
follower_remove_similar_item(tmp, item); | | |
} | | |
} | | |
} | | |
| | |
static int god_gives_present (object *op, object *god, treasure *tr) | | |
{ | | |
object *tmp; | | |
| | |
if (follower_has_similar_item (op, &tr->item->clone)) | | |
return 0; | | |
| | |
tmp = arch_to_object (tr->item); | | |
new_draw_info_format (NDI_UNIQUE, 0, op, | | |
"%s lets %s appear in your hands.", god->name, query_short_name (tmp)); | | |
tmp = insert_ob_in_ob (tmp, op); | | |
if (op->type == PLAYER) | | |
esrv_send_item (op, tmp); | | |
return 1; | | |
} | | |
| | |
| | |
/* god_intervention() - called from praying() currently. Every | | /* god_intervention() - called from praying() currently. Every |
* once in a while the god will intervene to help the worshiper. | | * once in a while the god will intervene to help the worshiper. |
| | |
* priest. -b.t. | | * priest. -b.t. |
*/ | | */ |
| | |
void god_intervention (object *op, object *god) | | void god_intervention (object *op, object *god, object *skill) |
{ | | { |
int level = SK_level (op); | | |
treasure *tr; | | treasure *tr; |
| | |
if ( ! god || ! god->randomitems) { | | if ( ! god || ! god->randomitems) { |
LOG (llevError, "BUG: god_intervention(): no god or god without " | | LOG (llevError, |
"randomitems\n"); | | "BUG: god_intervention(): no god or god without randomitems\n"); |
return; | | return; |
} | | } |
| | |
| | |
treasurelist *tl = find_treasurelist (tr->name); | | treasurelist *tl = find_treasurelist (tr->name); |
if (tl == NULL) | | if (tl == NULL) |
continue; | | continue; |
| | |
new_draw_info (NDI_UNIQUE, 0, op, "Something appears before your " | | new_draw_info (NDI_UNIQUE, 0, op, "Something appears before your " |
"eyes. You catch it before it falls to the ground."); | | "eyes. You catch it before it falls to the ground."); |
| | |
create_treasure (tl, op, GT_STARTEQUIP | GT_ONLY_GOOD | | create_treasure (tl, op, GT_STARTEQUIP | GT_ONLY_GOOD |
| GT_UPDATE_INV, level, 0); | | | GT_UPDATE_INV, skill->level, 0); |
return; | | return; |
} | | } |
| | |
| | |
| | |
/* Grace limit */ | | /* Grace limit */ |
if (item->type == BOOK && item->invisible | | if (item->type == BOOK && item->invisible |
&& strcmp (item->name, "grace limit") == 0) | | && strcmp (item->name, "grace limit") == 0) { |
{ | | |
if (op->stats.grace < item->stats.grace | | if (op->stats.grace < item->stats.grace |
|| op->stats.grace < op->stats.maxgrace) | | || op->stats.grace < op->stats.maxgrace) { |
{ | | object *tmp; |
| | |
/* Follower lacks the required grace for the following | | /* Follower lacks the required grace for the following |
* treasure list items. */ | | * treasure list items. */ |
(void) cast_change_attr (op, op, 0, SP_HOLY_POSSESSION); | | |
| | tmp = get_archetype(HOLY_POSSESSION); |
| | (void) cast_change_ability(op, op, tmp, 0); |
| | free_object(tmp); |
return; | | return; |
} | | } |
continue; | | continue; |
| | |
if (item->type == BOOK && item->invisible | | if (item->type == BOOK && item->invisible |
&& strcmp (item->name, "heal spell") == 0) | | && strcmp (item->name, "heal spell") == 0) |
{ | | { |
if (cast_heal (op, 0, get_spell_number (item))) | | object *tmp; |
return; | | int success; |
else | | |
continue; | | tmp = get_archetype_by_object_name(item->slaying); |
| | |
| | success = cast_heal (op, op, tmp, 0); |
| | free_object(tmp); |
| | if (success) return; |
| | else continue; |
} | | } |
| | |
/* Remove curse */ | | /* Remove curse */ |
| | |
if (item->type == BOOK && item->invisible | | if (item->type == BOOK && item->invisible |
&& strcmp (item->name, "enchant weapon") == 0) | | && strcmp (item->name, "enchant weapon") == 0) |
{ | | { |
if (god_enchants_weapon (op, god, item)) | | if (god_enchants_weapon (op, god, item, skill)) |
return; | | return; |
else | | else |
continue; | | continue; |
} | | } |
| | |
/* Spellbooks - works correctly only for prayers */ | | /* Spellbooks - works correctly only for prayers */ |
if (item->type == SPELLBOOK) | | if (item->type == SPELL) |
{ | | { |
int spell = get_spell_number (item); | | if (check_spell_known (op, item->name)) |
if (check_spell_known (op, spell)) | | |
continue; | | continue; |
if (spells[spell].level > level) | | if (item->level > skill->level) |
continue; | | continue; |
if (item->invisible) { | | |
new_draw_info_format(NDI_UNIQUE, 0, op, | | new_draw_info_format(NDI_UNIQUE, 0, op, |
"%s grants you use of a special prayer!", god->name); | | "%s grants you use of a special prayer!", god->name); |
do_learn_spell (op, spell, 1); | | do_learn_spell (op, item, 1); |
return; | | |
} | | |
if ( ! QUERY_FLAG (item, FLAG_STARTEQUIP)) { | | |
LOG (llevError, "BUG: visible spellbook in %s's treasure list " | | |
"lacks FLAG_STARTEQUIP\n", god->name); | | |
continue; | | |
} | | |
if ( ! item->stats.Wis) { | | |
LOG (llevError, "BUG: visible spellbook in %s's treasure list " | | |
"doesn't contain a special prayer\n", god->name); | | |
continue; | | |
} | | |
if (god_gives_present (op, god, tr)) | | |
return; | | return; |
else | | |
continue; | | |
} | | } |
| | |
/* Other gifts */ | | /* Other gifts */ |
| | |
| | |
int god_examines_priest (object *op, object *god) { | | int god_examines_priest (object *op, object *god) { |
int reaction=1; | | int reaction=1; |
object *item=NULL; | | object *item=NULL, *skop; |
| | |
for(item=op->inv;item;item=item->below) { | | for(item=op->inv;item;item=item->below) { |
if(QUERY_FLAG(item,FLAG_APPLIED)) { | | if(QUERY_FLAG(item,FLAG_APPLIED)) { |
| | |
| | |
/* well, well. Looks like we screwed up. Time for god's revenge */ | | /* well, well. Looks like we screwed up. Time for god's revenge */ |
if(reaction<0) { | | if(reaction<0) { |
char buf[MAX_BUF]; | | |
int loss = 10000000; | | int loss = 10000000; |
int angry = abs(reaction); | | int angry = abs(reaction); |
if(op->chosen_skill->exp_obj) | | |
loss = 0.05 * (float) op->chosen_skill->exp_obj->stats.exp; | | |
lose_priest_exp(op, random_roll(0, loss*angry-1, op, PREFER_LOW)); | | |
if(random_roll(0, angry, op, PREFER_LOW)) | | |
cast_mana_storm(op,SK_level(op)+(angry*3)); | | |
sprintf(buf,"%s becomes angry and punishes you!",god->name); | | |
new_draw_info(NDI_UNIQUE|NDI_NAVY,0,op,buf); | | |
} | | |
| | |
| | for (skop = op->inv; skop != NULL; skop=skop->below) |
| | if (skop->type == SKILL && skop->subtype == SK_PRAYING) break; |
| | |
| | if (skop) |
| | loss = 0.05 * (float) skop->stats.exp; |
| | change_exp(op, -random_roll(0, loss*angry-1, op, PREFER_LOW), |
| | skop?skop->skill:"none", SK_SUBTRACT_SKILL_EXP); |
| | if(random_roll(0, angry, op, PREFER_LOW)) { |
| | object *tmp = get_archetype(LOOSE_MANA); |
| | cast_magic_storm(op,tmp,op->level+(angry*3)); |
| | } |
| | new_draw_info_format(NDI_UNIQUE|NDI_NAVY,0,op, |
| | "%s becomes angry and punishes you!",god->name); |
| | } |
return reaction; | | return reaction; |
} | | } |
| | |
| | |
object *god=find_god(determine_god(caster)); | | object *god=find_god(determine_god(caster)); |
int caster_is_spell=0; | | int caster_is_spell=0; |
| | |
if(caster->type==FBULLET | | if (caster->type==SPELL_EFFECT || caster->type == SPELL) caster_is_spell=1; |
||caster->type==CONE | | |
||caster->type==FBALL | | |
||caster->type==SWARM_SPELL) caster_is_spell=1; | | |
| | |
if ( ! god || (spellop->attacktype & AT_HOLYWORD && ! god->race)) { | | if ( ! god || (spellop->attacktype & AT_HOLYWORD && ! god->race)) { |
if ( ! caster_is_spell) | | if ( ! caster_is_spell) |
| | |
return 1; | | return 1; |
} | | } |
| | |
void lose_priest_exp(object *pl, int loss) { | | |
| | |
if(!pl||pl->type!=PLAYER||!pl->chosen_skill | | |
||!pl->chosen_skill->exp_obj) | | |
{ | | |
LOG(llevError,"Bad call to lose_priest_exp() \n"); | | |
return; | | |
} | | |
if((loss = check_exp_loss(pl->chosen_skill->exp_obj,loss))) { | | |
pl->chosen_skill->exp_obj->stats.exp -= loss; | | |
pl->stats.exp -= loss; | | |
player_lvl_adj(pl, pl->chosen_skill->exp_obj); | | |
player_lvl_adj(pl, NULL); | | |
} | | |
} | | |