/* SillyMUD Distribution V1.1b (c) 1993 SillyMUD Developement See license.doc for distribution terms. SillyMUD is based on DIKUMUD */ #include <stdio.h> #include <string.h> #include <ctype.h> #include "protos.h" extern struct time_info_data time_info; /* In db.c */ extern unsigned char moontype; extern struct weather_data weather_info; extern int gSunSet, gSunRise, gMoonRise, gMoonSet; /* weather.c */ struct PolyType DruidList[17] = { {"bear", 10, 9024}, {"spider", 10, 20010}, {"lamia", 10, 3648}, {"lizard", 10, 6822}, {"bear", 12, 9056}, /* 5 */ {"gator", 12, 9054}, {"basilisk", 13, 7043}, {"snog", 14, 27008}, {"snake", 15, 6517}, {"spider", 15, 6113}, /* 10 */ {"lizard", 16, 6505}, {"allosaurus", 18, 21801}, {"tiger", 28, 9027}, {"mulichort", 30, 15830}, {"tiger", 35, 9055}, /* 15 */ {"lion", 35, 13718}, {"salamander", 35, 25506} /* 17 */ }; /* #define LAST_DRUID_MOB 16, moved to poly.h */ #define VAMPIRE_BAT 3066 void do_changeform(struct char_data *ch, char *argument, int cmd) { char buf[80]; int mobn, X=LAST_DRUID_MOB, found=FALSE, level; struct char_data *mob; struct affected_type af; level = GET_LEVEL(ch, DRUID_LEVEL_IND) ; level = (level ? level : GetMaxLevel(ch)); /* for vampires */ sprintf(buf,"Level %d thing doing a changeform.",level); log(buf); one_argument(argument,buf); if(!*buf) { if (HasClass(ch, CLASS_DRUID)) { send_to_char("You are able to change into the following forms:\n\r",ch); send_to_char("Format: <level> - <name>\n\r",ch); send_to_char(" ", ch); for(mobn=1; LAST_DRUID_MOB+1 >= mobn && level >= DruidList[mobn].level; mobn++) { sprintf(buf,"%2d - %-15s ",DruidList[mobn].level,DruidList[mobn].name); if(!(mobn%3)) strcat(buf,"\n\r "); send_to_char(buf, ch); } send_to_char("\n\rIn order to change into one of these forms enter:\n\r",ch); send_to_char("changeform <name>\n\r",ch); } else if( GET_RACE(ch) == RACE_VAMPIRE) { send_to_char("Vampires may only change into bats.\n\r", ch); } else { send_to_char("Ack, you can't change into anything!\n\r", ch); } return; } if (IS_NPC(ch)) { send_to_char("You don't really want to do that.\n\r",ch); return; } if (affected_by_spell(ch, SKILL_CHANGE_FORM)) { send_to_char("You can only change form once every 8 hours.\n\r", ch); return; } if (HasClass(ch, CLASS_DRUID)) { if(IS_EVIL(ch) || IS_GOOD(ch)) { send_to_char("You unable to change your form. You have strayed too\n\r", ch); send_to_char("far from nature's path to be one with her.\n\r",ch); return; } while (!found) { if (DruidList[X].level > level) { X--; } else { if (!str_cmp(DruidList[X].name, buf)) { mobn = DruidList[X].number; found = TRUE; } else { X--; } if (X < 0) { break; } } } if (!found) { send_to_char("You couldn't summon an image of that creature.\n\r", ch); return; } else { mob = read_mobile(mobn, VIRTUAL); if (mob) { af.type = SKILL_CHANGE_FORM; af.duration = 8; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = 0; affect_to_char(ch, &af); spell_poly_self(level, ch, mob, 0); } else { send_to_char("You couldn't summon an image of that creature.\n\r", ch); return; } } } else if(GET_RACE(ch) == RACE_VAMPIRE) { mob = read_mobile(VAMPIRE_BAT, VIRTUAL); if(mob) { mob->points.max_hit += level*2; GET_HIT(mob) = GET_MAX_HIT(mob); GET_RACE(ch) = RACE_VAMPIRE; SET_BIT(mob->specials.affected_by, AFF_INFRAVISION); if(level > 5) SET_BIT(mob->specials.affected_by, AFF_SENSE_LIFE); if(level > 10) SET_BIT(mob->specials.affected_by2, AFF2_ANIMAL_INVIS); if(level > 15) SET_BIT(mob->specials.affected_by, AFF_TREE_TRAVEL); if(level > 20) SET_BIT(mob->specials.affected_by, AFF_INVISIBLE); if(level > 25) SET_BIT(mob->specials.affected_by, AFF_DETECT_INVISIBLE); if(level > 30) SET_BIT(mob->specials.affected_by, AFF_DETECT_MAGIC); if(level > 35) SET_BIT(mob->specials.affected_by, AFF_SNEAK); if(level > 40) SET_BIT(mob->specials.affected_by, AFF_TRUE_SIGHT); if(level > 45) SET_BIT(mob->specials.affected_by, AFF_GROWTH); af.type = SKILL_CHANGE_FORM; af.duration = 8; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = 0; affect_to_char(ch, &af); spell_poly_self(level, ch, mob, 0); GET_AC(ch) -= level*2; } else { send_to_char("Ack, the bat form is acting screwy, not bats! Bug an imp!\n\r", ch); return; } } else { send_to_char("Try as you might, your body does not alter its shape.\n\r", ch); } } void do_bite(struct char_data *ch, char *argument, int cmd) { char arg[80]; struct char_data *victim; if(GET_RACE(ch) != RACE_VAMPIRE) { do_action(ch, argument, cmd); return; } if (check_peaceful(ch, "You feel too peaceful to contemplate feeding.\n\r")) return; only_argument(argument, arg); if (*arg) { victim = get_char_room_vis(ch, arg); if (victim) { if(GetMaxLevel(victim) >= LOW_IMMORTAL) { send_to_char("Immortals should not be considered food.\n\r", ch); send_to_char("You think someone is eyeing you for lunch.\n\r", victim); return; } else if (!IsHumanoid(victim) || IsUndead(victim)) { send_to_char("How on earth could you consider feeding on such a thing?\n\r", ch); return; } else if (victim == ch) { send_to_char("Suck your own blood? I think not.\n\r", ch); act("$n contemplates feeding on $mself but decides against it.", TRUE, ch, 0, victim, TO_ROOM); return; } else if(IS_AFFECTED(ch, AFF_CHARM) && (ch->master == victim)) { send_to_char("Your master would be very unpleased if you tried that!\n\r", ch); return; } if( (!ch->specials.fighting) ) { if( (!victim->specials.fighting) ) { if (GET_POS(ch)>=POSITION_STANDING) { if (!ch->equipment[WIELD]) { SET_BIT(ch->specials.affected_by2, AFF2_FEEDING); hit(ch, victim, TYPE_UNDEFINED); } else send_to_char("You can't be wielding anything to feed!\n\r", ch); } else send_to_char("Hey, why don't you try doing this when on your feet!\n\r", ch); } else send_to_char("You can't do this when they are fighting!\n\r", ch); } else send_to_char("How can you think about your stomach at a time like this?!?!\n\r", ch); } else send_to_char("Sink your fangs into who?\n\r", ch); } else send_to_char("Sink your fangs into who?\n\r", ch); } void MindflayerAttack(struct char_data *ch, struct char_data *v) { int loss; if(ch->specials.bitten) return; if(number(1,100) > (GetMaxLevel(ch)) + GET_DEX(ch)) return; if (v->equipment[WEAR_HEAD]) { /* hey, this bozo has headgear! */ if(number(1,10) >= (v->equipment[WEAR_HEAD]->obj_flags.value[0])) { /* I figure steel (plate) helm = 30% chance of hitting head */ act("$n almost sucked you with $s tentacles, your headgear blocked it!", FALSE, ch, 0, v, TO_VICT); act("Your tentacles are blocked by $N's headgear!", FALSE, ch, 0, v, TO_CHAR); act("$N's tentacles are blocked by $n's headgear!", FALSE, ch, 0, v, TO_NOTVICT); return; } } if(HitOrMiss(ch, v, CalcThaco(ch)) && GetMaxLevel(v) < LOW_IMMORTAL) { /* ha ha, we suck them */ act("$N screams out in pain as $n's tentacles suck $S energies!", FALSE, ch, 0, v, TO_NOTVICT); act("$n's tentacles momentarily wrap themselves around your head!", FALSE, ch, 0, v, TO_VICT); send_to_char("Blinding pain fills your head, and flashes of red dot your vision.\n\r",v); if(IS_SET(v->player.class, CLASS_MAGIC_USER | CLASS_CLERIC | CLASS_DRUID)) send_to_char("You feel weaker.\n\r", v); act("You wrap your tentacles around $N's head.", FALSE, ch, 0, v, TO_CHAR); loss = number(1,GetMaxLevel(ch)); if(GET_MANA(v) > 0) { GET_MANA(ch) += loss; GET_MANA(v) -= loss; act("You suck away some of $S magical energies!", FALSE, ch, 0, v, TO_CHAR); } else { act("Blech, $E has no more magical energies for you to drain.", FALSE, ch, 0, v, TO_CHAR); } GET_HIT(v) -= loss/2; update_pos(v); if(GET_POS(v) == POSITION_DEAD) DamageEpilog(ch,v); } } void VampireBite(struct char_data *ch, struct char_data *v) { bool to_bite = FALSE; float chance; /* when a vampire attempts to feed I think that they should not */ /* go about pummeling their victims with their fists. Nor should */ /* they kill someone and eat their corpse. They should not be armed, */ /* again, they are trying to subdue and bite. So, here's the biting */ /* part :) */ if(v->specials.bitten) { /* vampire's victim */ chance = GET_STR(v) - GET_STR(ch); chance *= 3.4; /* chance from +51 to -51 */ chance += GetMaxLevel(v) - GetMaxLevel(ch); /* chance is now some # from +100 to -100 */ /* we bite better at night :) */ if(time_info.hours < gSunRise && time_info.hours > gSunSet -1) chance += number(1,50); /* chance from +150 to -50 */ /* for avg str diff of 5, 17%, if same level, chance = 17% + [1->50] */ /* or, about 42% */ /* for str diff of 8, 27%, if 10 level dif., 37%, chance averages 62% */ /* NOTE: This is the chance for the vampire to keep ahold of v */ if(GetMaxLevel(ch) < GetMaxLevel(v)-5) /* life seemed too easy */ chance+=25; if(chance > number(1,100)) { act("$N struggles violently and breaks free of $n's grasp!", FALSE, ch, 0, v, TO_NOTVICT); act("$N struggles violently and breaks free of your grasp!", FALSE, ch, 0, v, TO_CHAR); act("You struggle violently and break free of $n's grasp!", FALSE, ch, 0, v, TO_VICT); v->specials.bitten = FALSE; return; } else { act("$N limply struggles in your grasp.", FALSE, ch, 0, v, TO_CHAR); act("$N limply struggles in $n's clutches.",FALSE, ch, 0, v, TO_NOTVICT); act("You struggle to free yourself of $n's grasp, but can't.", FALSE, ch, 0, v, TO_VICT); to_bite = TRUE; } } else { /* attemp to bite */ if(HitOrMiss(ch, v, CalcThaco(ch))) { to_bite = TRUE; } else { to_bite = FALSE; act("$n bares $s long, sharp fangs and almost bites you!", FALSE, ch, 0, v, TO_VICT); act("$N avoids your fangs!", FALSE, ch, 0, v, TO_CHAR); act("$N narrowly avoids $n's bared fangs!", FALSE, ch, 0, v, TO_NOTVICT); } } if(to_bite) { int loss, ammt; v->specials.bitten = TRUE; loss = number(1,MAX(10, GetMaxLevel(ch))); if(GET_HIT(v) > 0) { act("You savor the salty taste of $N's blood as you drain it.", FALSE, ch, 0, v, TO_CHAR); act("$n sinks $s fangs into $N's neck and drinks deeply.", FALSE, ch, 0, v, TO_NOTVICT); act("$n sinks $s fangs into your neck drains away your essence.", FALSE, ch, 0, v, TO_VICT); gain_condition(ch,FULL, MAX(loss/10,3)); ammt = number(1,loss); if(GET_HIT(v) - ammt <= 0) ammt = ammt = GET_HIT(v); (ammt > 0) ? ammt : 0; GET_HIT(v) -= ammt; GET_HIT(ch) += ammt; loss -= ammt; if(loss > 0) { ammt = number(1, loss); if(GET_MOVE(v) - ammt <= 0) ammt = GET_MOVE(v); ammt = (ammt > 0) ? ammt : 0; GET_MOVE(ch) += ammt; GET_MOVE(v) -= ammt; loss -= ammt; } if(loss > 0) { if(GET_MANA(v) - loss <= 0) loss = GET_MANA(v); loss = (loss > 0) ? loss : 0; GET_MANA(v) -= loss; GET_MANA(ch) += loss; } } else { send_to_char("You cannot drain anything more from this lifeless husk.\n\r", ch); act("You put $N out of $S misery.", FALSE, ch, 0, v, TO_CHAR); act("$n rips out your throat.", FALSE, ch, 0, v, TO_VICT); act("$n rips out $N's throat and drops the lifeless body to the ground.", TRUE, ch, 0, v, TO_NOTVICT); GET_HIT(v) -= 20; update_pos(v); if(GET_POS(v) == POSITION_DEAD) /* and it damn well better be */ DamageEpilog(ch,v); } } } int veggie_gain_mods(struct char_data *ch, int gain, bool msgs) { int bonus=0; if(time_info.hours > gSunRise && time_info.hours < gSunSet) { /* daylight */ if(weather_info.sky < 2) { /* partly cloudy & sunny */ if(!IS_SET(real_roomp(ch->in_room)->room_flags, INDOORS)) { if(!IS_SET(real_roomp(ch->in_room)->room_flags, DARK)) { if(real_roomp(ch->in_room)->sector_type != SECT_INSIDE && real_roomp(ch->in_room)->sector_type != SECT_CITY && real_roomp(ch->in_room)->sector_type != SECT_DESERT) { /* we are now outdoors in good weather with sun! */ bonus += gain>>1; if(msgs) send_to_char("Ahh, this weather is most invigorating.\n\r",ch); } else if( real_roomp(ch->in_room)->sector_type == SECT_DESERT) { bonus -= gain>>2; if(msgs) send_to_char("The heat and dry wind parch your skin.\n\r", ch); } } else { if(msgs) send_to_char("You wish the sun were caressing your limbs once again.\n\r", ch); } } else { /* we are indoors */ if(msgs) send_to_char("You yearn to return outside once again.\n\r", ch); } } /* is raining or worse */ } else if(time_info.hours < gSunRise || time_info.hours > gSunSet) { if(msgs) send_to_char("Your metabolism slows from lack of sunlight.\n\r", ch); bonus -= gain>>2; } return(bonus); } int vamp_gain_mods(struct char_data *ch, int gain, bool msgs) { /* hierarchy of vampire problems in the world: */ /* 1st: gain in sunlight is -1. */ /* 2nd: gain elsewhere is normal */ /* gain during nightimes at 3/4ths or better moons better regen */ if(time_info.hours > gSunRise && time_info.hours < gSunSet - 1) { if(OUTSIDE(ch) && IS_LIGHT(ch->in_room)) { /* we are outside in daylight! nuke the gain! */ if(msgs) send_to_char("You cower in the sunlight.\n\r", ch); return(-gain); } } else if(time_info.hours < gSunRise || time_info.hours > gSunSet) { if(moontype > 20 && moontype < 28 ) { /* 3/4ths or better moon */ if(msgs) send_to_char("The energy of the moon fills your veins.\n\r", ch); return(10); } } return(0); }