version 1.21 | | version 1.22 |
---|
| | |
/* | | /* |
* static char *rcsid_item_c = | | * static char *rcsid_item_c = |
* "$Id: item.c,v 1.21 2002/05/31 04:18:32 mwedel Exp $"; | | * "$Id: item.c,v 1.22 2002/06/15 05:35:02 mwedel Exp $"; |
*/ | | */ |
| | |
/* | | /* |
| | |
} | | } |
return buf; | | return buf; |
} | | } |
/* | | |
* Returns a pointer to a static buffer which contains a | | /* Break this off from describe_item - that function was way |
* description of the given object. | | * too long, making it difficult to read. This function deals |
* If it is a monster, lots of information about its abilities | | * with describing the monsters & players abilities. It should only |
* will be returned. | | * be called with monster & player objects. Returns a description |
* If it is an item, lots of information about which abilities | | * in a static buffer. |
* will be gained about its user will be returned. | | |
* If it is a player, it writes out the current abilities | | |
* of the player, which is usually gained by the items applied. | | |
*/ | | */ |
| | |
char *describe_item(object *op) { | | static char *describe_monster(object *op) { |
char buf[MAX_BUF]; | | char buf[MAX_BUF]; |
static char retbuf[VERY_BIG_BUF]; | | static char retbuf[VERY_BIG_BUF]; |
| | |
retbuf[0]='\0'; | | retbuf[0]='\0'; |
if(QUERY_FLAG(op,FLAG_MONSTER)) { | | |
| | /* Note that the resolution this provides for players really isn't |
| | * very good. Any player with a speed greater than .67 will |
| | * fall into the 'lightning fast movement' category. |
| | */ |
if(FABS(op->speed)>MIN_ACTIVE_SPEED) { | | if(FABS(op->speed)>MIN_ACTIVE_SPEED) { |
switch((int)((FABS(op->speed))*15)) { | | switch((int)((FABS(op->speed))*15)) { |
case 0: | | case 0: |
| | |
break; | | break; |
} | | } |
} | | } |
} else switch(op->type) { | | if(QUERY_FLAG(op,FLAG_UNDEAD)) |
| | strcat(retbuf,"(undead)"); |
| | if(QUERY_FLAG(op,FLAG_CAN_PASS_THRU)) |
| | strcat(retbuf,"(pass through doors)"); |
| | if(QUERY_FLAG(op,FLAG_SEE_INVISIBLE)) |
| | strcat(retbuf,"(see invisible)"); |
| | if(QUERY_FLAG(op,FLAG_USE_WEAPON)) |
| | strcat(retbuf,"(wield weapon)"); |
| | if(QUERY_FLAG(op,FLAG_USE_BOW)) |
| | strcat(retbuf,"(archer)"); |
| | if(QUERY_FLAG(op,FLAG_USE_ARMOUR)) |
| | strcat(retbuf,"(wear armour)"); |
| | if(QUERY_FLAG(op,FLAG_USE_RING)) |
| | strcat(retbuf,"(wear ring)"); |
| | if(QUERY_FLAG(op,FLAG_USE_SCROLL)) |
| | strcat(retbuf,"(read scroll)"); |
| | if(QUERY_FLAG(op,FLAG_USE_WAND)) |
| | strcat(retbuf,"(fire wand)"); |
| | if(QUERY_FLAG(op,FLAG_USE_ROD)) |
| | strcat(retbuf,"(use rod)"); |
| | if(QUERY_FLAG(op,FLAG_USE_HORN)) |
| | strcat(retbuf,"(use horn)"); |
| | if(QUERY_FLAG(op,FLAG_CAN_USE_SKILL)) |
| | strcat(retbuf,"(skill user)"); |
| | if(QUERY_FLAG(op,FLAG_CAST_SPELL)) |
| | strcat(retbuf,"(spellcaster)"); |
| | if(QUERY_FLAG(op,FLAG_FRIENDLY)) |
| | strcat(retbuf,"(friendly)"); |
| | if(QUERY_FLAG(op,FLAG_UNAGGRESSIVE)) |
| | strcat(retbuf,"(unaggressive)"); |
| | if(QUERY_FLAG(op,FLAG_HITBACK)) |
| | strcat(retbuf,"(hitback)"); |
| | if(op->randomitems != NULL) { |
| | treasure *t; |
| | int first = 1; |
| | for(t=op->randomitems->items; t != NULL; t=t->next) |
| | if(t->item && (t->item->clone.type == ABILITY)) { |
| | if(first) { |
| | first = 0; |
| | strcat(retbuf,"(Spell abilities:)"); |
| | } |
| | strcat(retbuf,"("); |
| | strcat(retbuf,t->item->clone.name); |
| | strcat(retbuf,")"); |
| | } |
| | } |
| | if (op->type == PLAYER) { |
| | if(op->contr->digestion) { |
| | if(op->contr->digestion!=0) |
| | sprintf(buf,"(sustenance%+d)",op->contr->digestion); |
| | strcat(retbuf,buf); |
| | } |
| | if(op->contr->gen_grace) { |
| | sprintf(buf,"(grace%+d)",op->contr->gen_grace); |
| | strcat(retbuf,buf); |
| | } |
| | if(op->contr->gen_sp) { |
| | sprintf(buf,"(magic%+d)",op->contr->gen_sp); |
| | strcat(retbuf,buf); |
| | } |
| | if(op->contr->gen_hp) { |
| | sprintf(buf,"(regeneration%+d)",op->contr->gen_hp); |
| | strcat(retbuf,buf); |
| | } |
| | } |
| | |
| | /* describe attacktypes */ |
| | if (is_dragon_pl(op)) { |
| | /* for dragon players display the attacktypes from clawing skill |
| | * Break apart the for loop - move the comparison checking down - |
| | * this makes it more readable. |
| | */ |
| | object *tmp; |
| | |
| | for (tmp=op->inv; tmp!=NULL; tmp=tmp->below) |
| | if (tmp->type == SKILL && !strcmp(tmp->name, "clawing")) break; |
| | |
| | if (tmp && tmp->attacktype!=0) { |
| | DESCRIBE_ABILITY(retbuf, tmp->attacktype, "Claws"); |
| | } |
| | else { |
| | DESCRIBE_ABILITY(retbuf, op->attacktype, "Attacks"); |
| | } |
| | } |
| | DESCRIBE_PATH(retbuf, op->path_attuned, "Attuned"); |
| | DESCRIBE_PATH(retbuf, op->path_repelled, "Repelled"); |
| | DESCRIBE_PATH(retbuf, op->path_denied, "Denied"); |
| | return retbuf; |
| | } |
| | |
| | |
| | /* |
| | * Returns a pointer to a static buffer which contains a |
| | * description of the given object. |
| | * If it is a monster, lots of information about its abilities |
| | * will be returned. |
| | * If it is an item, lots of information about which abilities |
| | * will be gained about its user will be returned. |
| | * If it is a player, it writes out the current abilities |
| | * of the player, which is usually gained by the items applied. |
| | * It would be really handy to actually pass another object |
| | * pointer on who is examining this object. Then, you could reveal |
| | * certain information depending on what the examiner knows, eg, |
| | * wouldn't need to use the SEE_INVISIBLE flag to know it is |
| | * a dragon player examining food. Could have things like |
| | * a dwarven axe, in which the full abilities are only known to |
| | * dwarves, etc. |
| | * |
| | * This function is really much more complicated than it should |
| | * be, because different objects have different meanings |
| | * for the same field (eg, wands use 'food' for charges). This |
| | * means these special cases need to be worked out. |
| | */ |
| | |
| | char *describe_item(object *op) { |
| | char buf[MAX_BUF]; |
| | static char retbuf[VERY_BIG_BUF]; |
| | int identified,i; |
| | |
| | retbuf[0]='\0'; |
| | if(QUERY_FLAG(op,FLAG_MONSTER) || op->type==PLAYER) { |
| | return describe_monster(op); |
| | } |
| | /* figure this out once, instead of making multiple calls to need_identify. |
| | * also makes the code easier to read. |
| | */ |
| | if (!need_identify(op) || QUERY_FLAG(op, FLAG_IDENTIFIED)) identified = 1; |
| | else identified = 0; |
| | |
| | switch(op->type) { |
case BOW: | | case BOW: |
case ARROW: | | case ARROW: |
case WAND: | | case WAND: |
case ROD: | | case ROD: |
case HORN: | | case HORN: |
case PLAYER: | | |
case WEAPON: | | case WEAPON: |
case ARMOUR: | | case ARMOUR: |
case HELMET: | | case HELMET: |
| | |
case GIRDLE: | | case GIRDLE: |
case BRACERS: | | case BRACERS: |
case CLOAK: | | case CLOAK: |
break; | | break; /* We have more information to do below this switch */ |
| | |
case FOOD: | | case FOOD: |
case FLESH: | | case FLESH: |
case DRINK: | | case DRINK: |
if(!need_identify(op) || QUERY_FLAG(op,FLAG_IDENTIFIED) || QUERY_FLAG(op,FLAG_BEEN_APPLIED)) { | | if(identified || QUERY_FLAG(op,FLAG_BEEN_APPLIED)) { |
sprintf(buf,"(food+%d)", op->stats.food); | | sprintf(buf,"(food+%d)", op->stats.food); |
strcat(retbuf, buf); | | strcat(retbuf, buf); |
| | |
| | |
default: | | default: |
return retbuf; | | return retbuf; |
} | | } |
if(op->type!=PLAYER && !QUERY_FLAG(op,FLAG_MONSTER)) { | | |
if(!need_identify(op) || QUERY_FLAG(op,FLAG_IDENTIFIED) || QUERY_FLAG(op,FLAG_BEEN_APPLIED)) { | | |
| | |
| | /* Down here, we more further describe equipment type items. |
| | * only describe them if they have been identified or the like. |
| | */ |
| | if (identified || QUERY_FLAG(op,FLAG_BEEN_APPLIED)) { |
int attr,val; | | int attr,val; |
| | |
for (attr=0; attr<7; attr++) { | | for (attr=0; attr<7; attr++) { |
| | |
sprintf(buf,"(speed %+d)",op->stats.exp); | | sprintf(buf,"(speed %+d)",op->stats.exp); |
strcat(retbuf,buf); | | strcat(retbuf,buf); |
} | | } |
| | |
switch(op->type) { | | switch(op->type) { |
case BOW: | | case BOW: |
case ARROW: | | case ARROW: |
| | |
strcat(retbuf,buf); | | strcat(retbuf,buf); |
} | | } |
break; | | break; |
| | |
default: | | default: |
break; | | break; |
} | | } |
} | | if(QUERY_FLAG(op,FLAG_XRAYS)) |
if(!need_identify(op) || QUERY_FLAG(op,FLAG_IDENTIFIED)) { | | strcat(retbuf,"(xray-vision)"); |
| | if(QUERY_FLAG(op,FLAG_FLYING)) |
| | strcat(retbuf,"(levitate)"); |
| | if(QUERY_FLAG(op,FLAG_SEE_IN_DARK)) |
| | strcat(retbuf,"(infravision)"); |
| | } /* End if identified or applied */ |
| | |
| | /* This blocks only deals with fully identified object. |
| | * it is intentional that this is not an 'else' from a above - |
| | * in this way, information is added. |
| | */ |
| | if(identified) { |
| | int more_info = 0; |
| | |
switch(op->type) { | | switch(op->type) { |
case ROD: /* These use stats.sp for spell selection and stats.food */ | | case ROD: /* These use stats.sp for spell selection and stats.food */ |
case HORN: /* and stats.hp for spell-point regeneration... */ | | case HORN: /* and stats.hp for spell-point regeneration... */ |
| | |
case FOOD: | | case FOOD: |
case FLESH: | | case FLESH: |
case DRINK: | | case DRINK: |
| | more_info = 0; |
break; | | break; |
default: | | |
| | /* Armor type objects */ |
| | case ARMOUR: |
| | case HELMET: |
| | case SHIELD: |
| | case BOOTS: |
| | case GLOVES: |
| | case GIRDLE: |
| | case BRACERS: |
| | case CLOAK: |
| | if (ARMOUR_SPEED(op)) { |
| | sprintf(buf,"(Max speed %1.2f)", ARMOUR_SPEED(op) / 10.0); |
| | strcat(retbuf, buf); |
| | } |
| | /* Do this in all cases - otherwise it gets confusing - does that |
| | * item have no penality, or is it not fully identified for example. |
| | */ |
| | sprintf(buf,"(Spell regen penalty %d)", ARMOUR_SPELLS(op)); |
| | strcat(retbuf, buf); |
| | more_info=1; |
| | break; |
| | |
| | case WEAPON: |
| | /* Calculate it the same way fix_player does so the results |
| | * make sense. |
| | */ |
| | i = (WEAPON_SPEED(op)*2-op->magic)/2; |
| | if (i<0) i=0; |
| | |
| | sprintf(buf,"(weapon speed %d)", i); |
| | strcat(retbuf, buf); |
| | more_info=1; |
| | break; |
| | |
| | } |
| | if (more_info) { |
if(op->stats.food) { | | if(op->stats.food) { |
if(op->stats.food!=0) | | if(op->stats.food!=0) |
sprintf(buf,"(sustenance%+d)",op->stats.food); | | sprintf(buf,"(sustenance%+d)",op->stats.food); |
/* else | | |
sprintf(buf,"(hunger%+d)",op->stats.food); */ | | |
strcat(retbuf,buf); | | strcat(retbuf,buf); |
} | | } |
if(op->stats.grace) { | | if(op->stats.grace) { |
| | |
strcat(retbuf,buf); | | strcat(retbuf,buf); |
} | | } |
} | | } |
} | | |
} else if(op->type == PLAYER) { | | |
if(op->contr->digestion) { | | |
if(op->contr->digestion!=0) | | |
sprintf(buf,"(sustenance%+d)",op->contr->digestion); | | |
/* else | | |
sprintf(buf,"(hunger%+d)",op->contr->digestion); */ | | |
strcat(retbuf,buf); | | |
} | | |
if(op->contr->gen_grace) { | | |
sprintf(buf,"(grace%+d)",op->contr->gen_grace); | | |
strcat(retbuf,buf); | | |
} | | |
if(op->contr->gen_sp) { | | |
sprintf(buf,"(magic%+d)",op->contr->gen_sp); | | |
strcat(retbuf,buf); | | |
} | | |
if(op->contr->gen_hp) { | | |
sprintf(buf,"(regeneration%+d)",op->contr->gen_hp); | | |
strcat(retbuf,buf); | | |
} | | |
} | | |
if(!need_identify(op) || QUERY_FLAG(op,FLAG_IDENTIFIED) || QUERY_FLAG(op,FLAG_BEEN_APPLIED)) { | | |
if(QUERY_FLAG(op,FLAG_XRAYS)) | | |
strcat(retbuf,"(xray-vision)"); | | |
if(QUERY_FLAG(op,FLAG_FLYING)) | | |
strcat(retbuf,"(levitate)"); | | |
if(QUERY_FLAG(op,FLAG_SEE_IN_DARK)) | | |
strcat(retbuf,"(infravision)"); | | |
} | | |
if(!need_identify(op) || QUERY_FLAG(op,FLAG_IDENTIFIED)) { | | |
if(op->stats.luck) { | | if(op->stats.luck) { |
sprintf(buf,"(luck%+d)",op->stats.luck); | | sprintf(buf,"(luck%+d)",op->stats.luck); |
strcat(retbuf,buf); | | strcat(retbuf,buf); |
| | |
if(QUERY_FLAG(op,FLAG_STEALTH)) | | if(QUERY_FLAG(op,FLAG_STEALTH)) |
strcat(retbuf,"(stealth)"); | | strcat(retbuf,"(stealth)"); |
if(op->slaying!=NULL) { | | if(op->slaying!=NULL) { |
strcat(retbuf,"(slay "); | | sprintf(buf,"(slay %s)",op->slaying); |
strcat(retbuf,op->slaying); | | strcat(retbuf,buf); |
strcat(retbuf,")"); | | |
} | | |
} | | |
if(QUERY_FLAG(op,FLAG_MONSTER)) { | | |
if(QUERY_FLAG(op,FLAG_UNDEAD)) | | |
strcat(retbuf,"(undead)"); | | |
if(QUERY_FLAG(op,FLAG_CAN_PASS_THRU)) | | |
strcat(retbuf,"(pass through doors)"); | | |
if(QUERY_FLAG(op,FLAG_SEE_INVISIBLE)) | | |
strcat(retbuf,"(see invisible)"); | | |
if(QUERY_FLAG(op,FLAG_USE_WEAPON)) | | |
strcat(retbuf,"(wield weapon)"); | | |
if(QUERY_FLAG(op,FLAG_USE_BOW)) | | |
strcat(retbuf,"(archer)"); | | |
if(QUERY_FLAG(op,FLAG_USE_ARMOUR)) | | |
strcat(retbuf,"(wear armour)"); | | |
if(QUERY_FLAG(op,FLAG_USE_RING)) | | |
strcat(retbuf,"(wear ring)"); | | |
if(QUERY_FLAG(op,FLAG_USE_SCROLL)) | | |
strcat(retbuf,"(read scroll)"); | | |
if(QUERY_FLAG(op,FLAG_USE_WAND)) | | |
strcat(retbuf,"(fire wand)"); | | |
if(QUERY_FLAG(op,FLAG_USE_ROD)) | | |
strcat(retbuf,"(use rod)"); | | |
if(QUERY_FLAG(op,FLAG_USE_HORN)) | | |
strcat(retbuf,"(use horn)"); | | |
if(QUERY_FLAG(op,FLAG_CAN_USE_SKILL)) | | |
strcat(retbuf,"(skill user)"); | | |
if(QUERY_FLAG(op,FLAG_CAST_SPELL)) | | |
strcat(retbuf,"(spellcaster)"); | | |
if(QUERY_FLAG(op,FLAG_FRIENDLY)) | | |
strcat(retbuf,"(friendly)"); | | |
if(QUERY_FLAG(op,FLAG_UNAGGRESSIVE)) | | |
strcat(retbuf,"(unaggressive)"); | | |
if(QUERY_FLAG(op,FLAG_HITBACK)) | | |
strcat(retbuf,"(hitback)"); | | |
if(op->randomitems != NULL) { | | |
treasure *t; | | |
int first = 1; | | |
for(t=op->randomitems->items; t != NULL; t=t->next) | | |
if(t->item && (t->item->clone.type == ABILITY)) { | | |
if(first) { | | |
first = 0; | | |
strcat(retbuf,"(Spell abilities:)"); | | |
} | | |
strcat(retbuf,"("); | | |
strcat(retbuf,t->item->clone.name); | | |
strcat(retbuf,")"); | | |
} | | |
} | | |
} | | |
if(!need_identify(op)||QUERY_FLAG(op,FLAG_IDENTIFIED)|| | | |
QUERY_FLAG(op,FLAG_MONSTER)) { | | |
| | |
/* describe attacktypes */ | | |
if (is_dragon_pl(op)) { | | |
/* for dragon players display the attacktypes from clawing skill */ | | |
object *tmp; | | |
| | |
for (tmp=op->inv; tmp!=NULL && !(tmp->type == SKILL && | | |
strcmp(tmp->name, "clawing")==0); tmp=tmp->below); | | |
| | |
if (tmp != NULL && tmp->attacktype!=0) { | | |
DESCRIBE_ABILITY(retbuf, tmp->attacktype, "Claws");} | | |
else { | | |
DESCRIBE_ABILITY(retbuf, op->attacktype, "Attacks");} | | |
} | | } |
else { | | DESCRIBE_ABILITY(retbuf, op->attacktype, "Attacks"); |
DESCRIBE_ABILITY(retbuf, op->attacktype, "Attacks");} | | |
| | |
/* resistance on flesh is only visible for quetzals */ | | /* resistance on flesh is only visible for quetzals */ |
if (op->type != FLESH || QUERY_FLAG(op, FLAG_SEE_INVISIBLE)) | | if (op->type != FLESH || QUERY_FLAG(op, FLAG_SEE_INVISIBLE)) |
strcat(retbuf,describe_resistance(op, 0)); | | strcat(retbuf,describe_resistance(op, 0)); |