void do_taste(struct char_data *ch, char *argument, int cmd) { struct affected_type af; char arg[MAX_STRING_LENGTH]; char buf[MAX_STRING_LENGTH]; struct obj_data *temp; one_argument(argument,arg); if(!(temp = get_obj_in_list_vis(ch,arg,ch->carrying))) { act("You can't find it!",FALSE,ch,0,0,TO_CHAR); return; } if(temp->obj_flags.type_flag==ITEM_DRINKCON) { do_sip(ch,argument,0); return; } if(!(temp->obj_flags.type_flag==ITEM_FOOD)) { act("Taste that?!? Your stomach refuses!",FALSE,ch,0,0,TO_CHAR); return; } act("$n tastes the $o", FALSE, ch, temp, 0, TO_ROOM); act("You taste the $o", FALSE, ch, temp, 0, TO_CHAR); gain_condition(ch,FULL,1); if(GET_COND(ch,FULL)>20) act("You are full.",FALSE,ch,0,0,TO_CHAR); if(temp->obj_flags.value[3]&&!IS_AFFECTED(ch,AFF_POISON)) /* The shit was poisoned ! */ { act("Ooups, it did not taste good at all!",FALSE,ch,0,0,TO_CHAR); af.type = SPELL_POISON; af.duration = 2; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_POISON; affect_to_char(ch,&af); } temp->obj_flags.value[0]--; if(!temp->obj_flags.value[0]) /* Nothing left */ { act("There is nothing left now.",FALSE,ch,0,0,TO_CHAR); extract_obj(temp); } return; }
void do_eat(struct char_data *ch, char *argument, int cmd) { char buf[100]; struct obj_data *temp; struct affected_type af; one_argument(argument,buf); if(!(temp = get_obj_in_list_vis(ch,buf,ch->carrying))) { act("You can't find it!",FALSE,ch,0,0,TO_CHAR); return; } if((temp->obj_flags.type_flag != ITEM_FOOD) && (GET_LEVEL(ch) < 22)) { act("Your stomach refuses to eat that!?!",FALSE,ch,0,0,TO_CHAR); return; } if(GET_COND(ch,FULL)>20) /* Stomach full */ { act("You are to full to eat more!",FALSE,ch,0,0,TO_CHAR); return; } act("$n eats $p",TRUE,ch,temp,0,TO_ROOM); act("You eat the $o.",FALSE,ch,temp,0,TO_CHAR); gain_condition(ch,FULL,temp->obj_flags.value[0]); if(GET_COND(ch,FULL)>20) act("You are full.",FALSE,ch,0,0,TO_CHAR); if(temp->obj_flags.value[3] && (GET_LEVEL(ch) < 21)) /* The shit was poisoned ! */ { act("Ooups, it tasted rather strange ?!!?",FALSE,ch,0,0,TO_CHAR); act("$n coughs and utters some strange sounds.",FALSE,ch,0,0,TO_ROOM); af.type = SPELL_POISON; af.duration = temp->obj_flags.value[0]*2; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_POISON; affect_join(ch,&af, FALSE, FALSE); } extract_obj(temp); }
/* Update PCs, NPCs, and objects */ void point_update(void) { struct char_data *i, *next_char; struct obj_data *j, *next_thing, *jj, *next_thing2; /* characters */ for (i = character_list; i; i = next_char) { next_char = i->next; gain_condition(i, FULL, -1); gain_condition(i, DRUNK, -1); gain_condition(i, THIRST, -1); if (GET_POS(i) >= POS_STUNNED) { GET_HIT(i) = MIN(GET_HIT(i) + hit_gain(i), GET_MAX_HIT(i)); GET_MANA(i) = MIN(GET_MANA(i) + mana_gain(i), GET_MAX_MANA(i)); GET_MOVE(i) = MIN(GET_MOVE(i) + move_gain(i), GET_MAX_MOVE(i)); if (AFF_FLAGGED(i, AFF_POISON)) if (damage(i, i, 2, SPELL_POISON) == -1) continue; /* Oops, they died. -gg 6/24/98 */ if (GET_POS(i) <= POS_STUNNED) update_pos(i); } else if (GET_POS(i) == POS_INCAP) { if (damage(i, i, 1, TYPE_SUFFERING) == -1) continue; } else if (GET_POS(i) == POS_MORTALLYW) { if (damage(i, i, 2, TYPE_SUFFERING) == -1) continue; } if (!IS_NPC(i)) { update_char_objects(i); if (GET_LEVEL(i) < idle_max_level) check_idling(i); } } /* objects */ for (j = object_list; j; j = next_thing) { next_thing = j->next; /* Next in object list */ /* If this is a corpse */ if (IS_CORPSE(j)) { /* timer count down */ if (GET_OBJ_TIMER(j) > 0) GET_OBJ_TIMER(j)--; if (!GET_OBJ_TIMER(j)) { if (j->carried_by) act("$p decays in your hands.", FALSE, j->carried_by, j, 0, TO_CHAR); else if ((IN_ROOM(j) != NOWHERE) && (world[IN_ROOM(j)].people)) { act("A quivering horde of maggots consumes $p.", TRUE, world[IN_ROOM(j)].people, j, 0, TO_ROOM); act("A quivering horde of maggots consumes $p.", TRUE, world[IN_ROOM(j)].people, j, 0, TO_CHAR); } for (jj = j->contains; jj; jj = next_thing2) { next_thing2 = jj->next_content; /* Next in inventory */ obj_from_obj(jj); if (j->in_obj) obj_to_obj(jj, j->in_obj); else if (j->carried_by) obj_to_room(jj, IN_ROOM(j->carried_by)); else if (IN_ROOM(j) != NOWHERE) obj_to_room(jj, IN_ROOM(j)); else core_dump(); } extract_obj(j); } } /* If the timer is set, count it down and at 0, try the trigger */ /* note to .rej hand-patchers: make this last in your point-update() */ else if (GET_OBJ_TIMER(j)>0) { GET_OBJ_TIMER(j)--; if (!GET_OBJ_TIMER(j)) timer_otrigger(j); } } }
void regen_update( void ) { CharData *i, *next_char; int hit, mana, move; int vivify_level; for( i = character_list; i; i = next_char ) { next_char = i->next; if(affected_by_spell(i, SKILL_EMACIATED) && (GET_COND(i, HUNGER) != 0 || IS_VAMPIRE(i)) && GET_COND(i, THIRST) != 0) { if(!affected_by_spell(i, SKILL_EMACIATED_MANA) && !affected_by_spell(i, SKILL_EMACIATED_HIT)) affect_from_char(i, SKILL_EMACIATED); else if(percentSuccess(4)) { affect_from_char(i, SKILL_EMACIATED_MANA); affect_from_char(i, SKILL_EMACIATED_HIT); } } // Dwarves sober up 3x faster than most races (unless they drink more...) if(IS_DWARF(i) && !number(0, 35)) gain_condition(i, DRUNK, -1); vivify_level = spell_level(i, SPELL_VIVIFY); affect_from_char(i, SPELL_VIVIFY); if(GET_POS(i) <= POS_MEDITATING) { add_affect(i, i, SPELL_VIVIFY, MIN(vivify_level + 1, 100), APPLY_NONE, 0, -1, 0, FALSE, FALSE, FALSE, FALSE); } if(GET_POS(i) >= POS_MORTALLYW) { hit = hit_gain(i); mana = mana_gain(i); move = move_gain(i); if(affected_by_spell(i, SPELL_VIVIFY)) { if(hit > 0) hit += spell_level(i, SPELL_VIVIFY) * GET_MAX_HIT(i)/600; if(mana > 0) mana += spell_level(i, SPELL_VIVIFY) * GET_MAX_MANA(i)/600; if(move > 0) move += spell_level(i, SPELL_VIVIFY) * GET_MAX_MOVE(i)/600; } // Regeneration is increased on pvp holidays. If you're incapactitated, you will // eventually recover. if(pvpHoliday(i)) { if (GET_POS(i) < POS_SLEEPING) hit = 20; else { hit = (hit > 0) ? hit *3 : 20; mana = (mana > 0) ? mana*2 : 40; move = (move > 0) ? move*2 : 40; } } // 72 seconds per tick... if(hit < 0 || GET_HIT(i) < GET_MAX_HIT(i)) { if(hit>0) GET_HIT(i) += hit/72 + (hit % 72 > number(0, 71)? 1:0); else GET_HIT(i) = MAX(GET_HIT(i) + hit/72 + (-hit % 72 > number(0, 71)?-1:0), -9); } else { int surplus = (GET_HIT(i) - GET_MAX_HIT(i)); GET_HIT(i) -= surplus / 72 + (surplus % 72 > number(0, 71)? 1:0); } if(mana>0) GET_MANA(i) = MAX(MIN(GET_MANA(i) + mana/72 + (mana % 72 > number(0, 71)?1:0), GET_MAX_MANA(i)), 0); else GET_MANA(i) = MIN(GET_MANA(i) + mana/72 + (-mana % 72 > number(0, 71)?-1:0), GET_MAX_MANA(i)); if(move>0) GET_MOVE(i) = MIN(GET_MOVE(i) + move/72 + (move % 72 > number(0, 71)?1:0), GET_MAX_MOVE(i)); else GET_MOVE(i) = MAX(MIN(GET_MOVE(i) + move/72 + (-move % 72 > number(0, 71)?-1:0), GET_MAX_MOVE(i)), 0); update_pos(i); } } }
/* ** Update PCs, NPCs, and objects */ void point_update( void ) { int slot; void update_char_objects(CharData * ch); /* handler.c */ void extract_obj(ObjData * obj); /* handler.c */ void update_char_quests(CharData * ch); /* quest.c */ CharData *i, *next_char; ObjData *j, *next_thing, *jj, *next_thing2, *debugnext; int loopvar; /* characters */ for( i = character_list; i; i = next_char ) { next_char = i->next; // state flags i->tickstate = 0; /* dismount anyone who's gotten separated from their steed */ /* Note that it's superfluous to check for both rider AND mount */ if (i->rider && i->rider->in_room != i->in_room) { i->rider->mount = NULL; i->rider = NULL; } /* Prayer timer */ if (i->player_specials->saved.prayer_time > 0) { if (i->player_specials->saved.prayer_time == 1) { i->player_specials->saved.prayer_time = 0; send_to_char("Your prayers will be heard once again.\r\n", i); } else i->player_specials->saved.prayer_time -= 1; } for(slot = 0; slot<4; slot++) { if (COOLDOWN(i, slot) ) { COOLDOWN(i, slot) -= 1; if (!COOLDOWN(i, slot) ) { switch( GET_CLASS(i) ) { case CLASS_DEATH_KNIGHT: break; case CLASS_SOLAMNIC_KNIGHT: break; case CLASS_MAGIC_USER: break; case CLASS_SHADOW_DANCER: if(slot == SLOT_SLIPPERY_MIND) break; else if(slot == SLOT_NODESHIFT) sendChar(i, "You may once again shift your spectrum.\r\n"); else sendChar(i, "ERROR!\r\n"); break; case CLASS_THIEF: if(slot== SLOT_BLACKJACK) { sendChar(i, "You are able to use blackjack again.\r\n"); break; } else sendChar(i, "ERROR!\r\n"); case CLASS_ASSASSIN: if(slot == SLOT_DETERRENCE) sendChar(i, "You are able to use deterrence again.\r\n"); else sendChar(i, "ERROR!\r\n"); break; case CLASS_CLERIC: if(slot == SLOT_SHADOW_FORM) sendChar(i, "You are ready to enter shadow form again..\r\n"); else sendChar(i, "ERROR!\r\n"); case CLASS_WARRIOR: if(slot == SLOT_REDOUBT) sendChar(i, "You can shield yourself again.\r\n"); else if(slot == SLOT_COMMANDING_SHOUT) sendChar(i, "You can shout commands again.\r\n"); else sendChar(i, "ERROR!\r\n"); break; case CLASS_SHOU_LIN: break; case CLASS_RANGER: break; case CLASS_NECROMANCER: if(slot == SLOT_QUICKEN) sendChar(i, "You may once again rise from the grave.\r\n"); else if(slot == SLOT_METAMORPHOSIS) sendChar(i, "You may once again metamorphisize.\r\n"); else sendChar(i, "ERROR!\r\n"); break; default: sendChar(i, "ERROR!\r\n"); break; } } } } if( IS_AFFECTED(i, AFF_PLAGUE )) infectious(i); if( !IS_NPC(i) ) { update_char_objects(i); if( GET_LEVEL(i) < LVL_GOD ) check_idling(i); update_char_quests(i); } gain_condition(i, HUNGER, IS_AFFECTED(i, AFF_REGENERATE)? -2:-1); gain_condition(i, DRUNK, -1); /* Amara get thirsty in different ways */ if (IS_AMARA(i)) { if (IN_ROOM(i) >= 0 && IN_ROOM(i) <= top_of_world) { switch (SECT(IN_ROOM(i))) { case SECT_WATER_SWIM: case SECT_WATER_NOSWIM: gain_condition(i, THIRST, 1); break; case SECT_UNDERWATER: case SECT_UNDERWATER_RIVER: gain_condition(i, THIRST, 24); break; default: gain_condition(i, THIRST, -2); break; } } else gain_condition(i, THIRST, -2); } else gain_condition(i, THIRST, -1); }/* for */ debugnext = NULL; /* objects */ for( j = object_list; j; j = next_thing ) { next_thing = j->next; /* Next in object list */ debugnext = j; // we didn't crash if we got here if( IS_SET_AR( j->obj_flags.extra_flags, ITEM_TIMED )) { if( GET_OBJ_TIMER(j) > 0 ) GET_OBJ_TIMER(j)--; if (GET_OBJ_TIMER(j) == 0) { if(contains_soulbound(j)) { GET_OBJ_TIMER(j) = 1; continue; } if (SCRIPT_CHECK(j, OTRIG_TIMER)) { REMOVE_BIT_AR(j->obj_flags.extra_flags, ITEM_TIMED); timer_otrigger(j); continue; // don't do anything more with this } } if( GET_OBJ_TYPE(j) == ITEM_KEY ) { static char *keyVaporMsgs[] = { "$p vanishes with a flash.", "$p begins to shake violently.", "$p begins to vibrate.", "$p begins to hum.", "$p begins to glow." }; if( GET_OBJ_TIMER(j) < (sizeof( keyVaporMsgs )/sizeof( *keyVaporMsgs ))) { int vaporMsg = GET_OBJ_TIMER(j); if( j->carried_by ) act( keyVaporMsgs[ vaporMsg ], FALSE, j->carried_by, j, 0, TO_CHAR); else if( j->worn_by ) { act( keyVaporMsgs[ vaporMsg ], FALSE, j->worn_by, j, 0, TO_CHAR); for( loopvar = 0; loopvar < NUM_WEARS; loopvar++ ) { if( j->worn_by->equipment[loopvar] == j ) j->worn_by->equipment[loopvar] = 0; } } else if( j->in_room != NOWHERE && world[j->in_room].people ) { act( keyVaporMsgs[ vaporMsg ], FALSE, world[j->in_room].people, j, 0, TO_CHAR); act( keyVaporMsgs[ vaporMsg ], FALSE, world[j->in_room].people, j, 0, TO_ROOM); } extract_obj(j); continue; }/* ITEM_KEY has timed out */ }/* if ITEM_KEY */ else if (GET_OBJ_TYPE(j) == ITEM_AFFECT) { if (!GET_OBJ_TIMER(j)) { if (j->in_room != NOWHERE && world[j->in_room].people) { act(j->action_description, FALSE, world[j->in_room].people, j, 0, TO_CHAR); act(j->action_description, FALSE, world[j->in_room].people, j, 0, TO_ROOM); } extract_obj(j); continue; // object gone, don't act further on it! } } else if( !GET_OBJ_TIMER(j) ) { /* The object timed out - delete it */ if( j->carried_by ) act( "$p crumbles to dust and is blown away.", FALSE, j->carried_by, j, 0, TO_CHAR ); else if( j->worn_by ) { act("$p crumbles to dust and is blown away.", FALSE, j->worn_by, j, 0, TO_CHAR); unequip_char( j->worn_by, j->worn_at ); } else if( j->in_room != NOWHERE && world[j->in_room].people ) { act( "$p crumbles to dust and is blown away.", FALSE, world[j->in_room].people, j, 0, TO_CHAR); act( "$p crumbles to dust and is blown away.", FALSE, world[j->in_room].people, j, 0, TO_ROOM); } extract_obj(j); continue; // object gone, don't act further on it! } } /* if OBJ_TIMED */ /* if this looks like a portal */ if ( (GET_OBJ_RNUM(j) >= 0 && GET_OBJ_RNUM(j) <= top_of_objt) && obj_index[GET_OBJ_RNUM(j)].func == portal_proc && GET_OBJ_TYPE(j) == ITEM_OTHER ) { /* Mage created portals are type other, permanent portals are type portal. */ /* Permanent portals thus don't decay. */ if (GET_OBJ_VAL(j, 2) > 0) GET_OBJ_VAL(j,2)--; } /* ** Digger */ /* If this is a corpse */ if ((GET_OBJ_TYPE(j) == ITEM_CONTAINER) && GET_OBJ_VAL(j, 3)) { /* timer count down */ if (GET_OBJ_TIMER(j) > 0) GET_OBJ_TIMER(j)--; // PC corpses which are empty will decay eventually.. if(!CAN_WEAR(j, ITEM_WEAR_TAKE) && !(j->contains)) { GET_OBJ_TIMER(j) = MAX(GET_OBJ_TIMER(j) / 3, 0); } if (!GET_OBJ_TIMER(j)) { if(contains_soulbound(j)) { GET_OBJ_TIMER(j) = 1; continue; } if (j->carried_by) act("$p decays in your hands.", FALSE, j->carried_by, j, 0, TO_CHAR); else if ((j->in_room != NOWHERE) && (world[j->in_room].people)) { static char *decay_messages[] = { "A quivering hoard of maggots consumes $p.", "A flock of vultures swoop down from the sky to devour $p.", "The $p rots and decays as the shards of bone are blown to the four winds.", "The $p rots and decays leaving behind the pungent stench of death.", "A bolt of holy fire streaks from the heavens to burn the corpse of $p to ash.", "The $p rots to ash and is swept away by the winds of time." }; int decay_idx = (int)( random() % ( sizeof( decay_messages ) / sizeof( *decay_messages ))); act( decay_messages[ decay_idx ], TRUE, world[j->in_room].people, j, 0, TO_ROOM); act( decay_messages[ decay_idx ], TRUE, world[j->in_room].people, j, 0, TO_CHAR); }/* JBP */ for (jj = j->contains; jj; jj = next_thing2) { next_thing2 = jj->next_content; /* Next in inventory */ obj_from_obj(jj); if (j->in_obj) { if ( GET_OBJ_TYPE(j) != ITEM_KEY && GET_OBJ_TYPE(j) != ITEM_SCROLL && GET_OBJ_TYPE(j) != ITEM_POTION && GET_OBJ_TYPE(j) != ITEM_DUST && (GET_OBJ_VNUM(j) == 1460 || GET_OBJ_VNUM(j) == 1461 || GET_OBJ_VNUM(j) == 1462 ) ) continue; // Refrigeration to keep food from rotting. obj_to_obj(jj, j->in_obj); } else if (j->carried_by) obj_to_room(jj, j->carried_by->in_room); else if (j->in_room != NOWHERE) obj_to_room(jj, j->in_room); else { /* OLD WAY: assert(FALSE); */ mudlog(NRM, LVL_IMMORT, TRUE, "SYSERR: Something is wrong with a container." ); obj_to_room(jj, real_room(1201)); } } extract_obj(j); } } /* Imhotep: Added support for ITEM_TROPHY pieces that decay after * a given MUD date */ if(IS_OBJ_STAT(j, ITEM_TROPHY)) { if(GET_OBJ_TIMER(j) < TICKS_SO_FAR) { if (j->carried_by) act("$p shimmers and vanishes out of your hands!", FALSE, j->carried_by, j, 0, TO_CHAR); else if (j->worn_by) { act("$p shimmers and vanishes!", FALSE, j->worn_by, j, 0, TO_CHAR); unequip_char(j->worn_by, j->worn_at); } else if (j->in_room != NOWHERE && world[j->in_room].people) { act("$p shimmers and vanishes!", FALSE, world[j->in_room].people, j, 0, TO_CHAR); act("$p shimmers and vanishes!", FALSE, world[j->in_room].people, j, 0, TO_ROOM); } extract_obj(j); continue; } } } }/* point_update */
void fire_effect(void *vo, int level, int dam, int target) { if (target == TARGET_ROOM) /* nail objects on the floor */ { ROOM_INDEX_DATA *room = (ROOM_INDEX_DATA *) vo; OBJ_DATA *obj, *obj_next; for (obj = room->contents; obj != NULL; obj = obj_next) { obj_next = obj->next_content; fire_effect(obj,level,dam,TARGET_OBJ); } return; } if (target == TARGET_CHAR) /* do the effect on a victim */ { CHAR_DATA *victim = (CHAR_DATA *) vo; OBJ_DATA *obj, *obj_next; /* chance of blindness */ if (!IS_AFFECTED(victim,AFF_BLIND) && !saves_spell(level / 4 + dam / 20, victim,DAM_FIRE)) { AFFECT_DATA af; act("$n is blinded by smoke!",victim,NULL,NULL,TO_ROOM); act("Your eyes tear up from smoke...you can't see a thing!", victim,NULL,NULL,TO_CHAR); af.where = TO_AFFECTS; af.type = skill_lookup("fire breath"); af.level = level; af.duration = number_range(0,level/10); af.location = APPLY_HITROLL; af.modifier = -4; af.bitvector = AFF_BLIND; affect_to_char(victim,&af); } /* getting thirsty */ if (!IS_NPC(victim)) gain_condition(victim,COND_THIRST,dam/20); /* let's toast some gear! */ for (obj = victim->carrying; obj != NULL; obj = obj_next) { obj_next = obj->next_content; fire_effect(obj,level,dam,TARGET_OBJ); } return; } if (target == TARGET_OBJ) /* toast an object */ { OBJ_DATA *obj = (OBJ_DATA *) vo; OBJ_DATA *t_obj,*n_obj; int chance = level / 4 + dam / 10; char *msg; if (IS_OBJ_STAT(obj,ITEM_BURN_PROOF) || IS_OBJ_STAT(obj,ITEM_NOPURGE) || number_range(0,4) == 0) return; if (chance > 25) chance = (chance - 25) / 2 + 25; if (chance > 50) chance = (chance - 50) / 2 + 50; if (IS_OBJ_STAT(obj,ITEM_BLESS)) chance -= 5; chance -= obj->level * 2; switch ( obj->item_type ) { default: return; case ITEM_CONTAINER: msg = "$p ignites and burns!"; break; case ITEM_POTION: chance += 25; msg = "$p bubbles and boils!"; break; case ITEM_SCROLL: chance += 50; msg = "$p crackles and burns!"; break; case ITEM_STAFF: chance += 10; msg = "$p smokes and chars!"; break; case ITEM_WAND: msg = "$p sparks and sputters!"; break; case ITEM_FOOD: msg = "$p blackens and crisps!"; break; case ITEM_PILL: msg = "$p melts and drips!"; break; } chance = URANGE(5,chance,95); if (number_percent() > chance) return; if (obj->carried_by != NULL) act( msg, obj->carried_by, obj, NULL, TO_ALL ); else if (obj->in_room != NULL && obj->in_room->people != NULL) act(msg,obj->in_room->people,obj,NULL,TO_ALL); if (obj->contains) { /* dump the contents */ for (t_obj = obj->contains; t_obj != NULL; t_obj = n_obj) { n_obj = t_obj->next_content; obj_from_obj(t_obj); if (obj->in_room != NULL) obj_to_room(t_obj,obj->in_room); else if (obj->carried_by != NULL) obj_to_room(t_obj,obj->carried_by->in_room); else { extract_obj(t_obj); continue; } fire_effect(t_obj,level/2,dam/2,TARGET_OBJ); } } extract_obj( obj ); return; } }
void cold_effect(void *vo, int level, int dam, int target) { if (target == TARGET_ROOM) /* nail objects on the floor */ { ROOM_INDEX_DATA *room = (ROOM_INDEX_DATA *) vo; OBJ_DATA *obj, *obj_next; for (obj = room->contents; obj != NULL; obj = obj_next) { obj_next = obj->next_content; cold_effect(obj,level,dam,TARGET_OBJ); } return; } if (target == TARGET_CHAR) /* whack a character */ { CHAR_DATA *victim = (CHAR_DATA *) vo; OBJ_DATA *obj, *obj_next; /* chill touch effect */ if (!saves_spell(level/4 + dam / 20, victim, DAM_COLD)) { AFFECT_DATA af; act("$n turns blue and shivers.",victim,NULL,NULL,TO_ROOM); act("A chill sinks deep into your bones.",victim,NULL,NULL,TO_CHAR); af.where = TO_AFFECTS; af.type = skill_lookup("chill touch"); af.level = level; af.duration = 6; af.location = APPLY_STR; af.modifier = -1; af.bitvector = 0; affect_join( victim, &af ); } /* hunger! (warmth sucked out */ if (!IS_NPC(victim)) gain_condition(victim,COND_HUNGER,dam/20); /* let's toast some gear */ for (obj = victim->carrying; obj != NULL; obj = obj_next) { obj_next = obj->next_content; cold_effect(obj,level,dam,TARGET_OBJ); } return; } if (target == TARGET_OBJ) /* toast an object */ { OBJ_DATA *obj = (OBJ_DATA *) vo; int chance = level / 4 + dam / 10; char *msg; if (IS_OBJ_STAT(obj,ITEM_BURN_PROOF) || IS_OBJ_STAT(obj,ITEM_NOPURGE) || number_range(0,4) == 0) return; if (chance > 25) chance = (chance - 25) / 2 + 25; if (chance > 50) chance = (chance - 50) / 2 + 50; if (IS_OBJ_STAT(obj,ITEM_BLESS)) chance -= 5; chance -= obj->level * 2; switch(obj->item_type) { default: return; case ITEM_POTION: msg = "$p freezes and shatters!"; chance += 25; break; case ITEM_DRINK_CON: msg = "$p freezes and shatters!"; chance += 5; break; } chance = URANGE(5,chance,95); if (number_percent() > chance) return; if (obj->carried_by != NULL) act(msg,obj->carried_by,obj,NULL,TO_ALL); else if (obj->in_room != NULL && obj->in_room->people != NULL) act(msg,obj->in_room->people,obj,NULL,TO_ALL); extract_obj(obj); return; } }
void do_drink(struct char_data *ch, char *argument, int cmd) { char buf[100]; struct obj_data *temp; struct affected_type af; int amount,i; one_argument(argument,buf); if(!(temp = get_obj_in_list_vis(ch,buf,ch->carrying))) { act("You can't find it!",FALSE,ch,0,0,TO_CHAR); return; } if (temp->obj_flags.type_flag!=ITEM_DRINKCON) { act("You can't drink from that!",FALSE,ch,0,0,TO_CHAR); return; } if((GET_COND(ch,DRUNK)>10)&&(GET_COND(ch,THIRST)>0)) /* The pig is drunk */ { act("You simply fail to reach your mouth!", FALSE, ch, 0, 0, TO_CHAR); act("$n tried to drink but missed $s mouth!", TRUE, ch, 0, 0, TO_ROOM); return; } if((GET_COND(ch,FULL)>20)&&(GET_COND(ch,THIRST)>0)) /* Stomach full */ { act("Your stomach can't contain anymore!",FALSE,ch,0,0,TO_CHAR); return; } if (temp->obj_flags.type_flag==ITEM_DRINKCON){ if(temp->obj_flags.value[1]>0) /* Not empty */ { sprintf(buf,"$n drinks %s from $p",drinks[temp->obj_flags.value[2]]); act(buf, TRUE, ch, temp, 0, TO_ROOM); sprintf(buf,"You drink the %s.\n\r",drinks[temp->obj_flags.value[2]]); send_to_char(buf,ch); if (drink_aff[temp->obj_flags.value[2]][DRUNK] > 0 ) amount = (25-GET_COND(ch,THIRST))/drink_aff[temp->obj_flags.value[2]][DRUNK]; else amount = number(3,10); amount = MIN(amount,temp->obj_flags.value[1]); weight_change_object(temp, -amount); /* Subtract amount */ gain_condition(ch,DRUNK,(int)((int)drink_aff [temp->obj_flags.value[2]][DRUNK]*amount)/4); gain_condition(ch,FULL,(int)((int)drink_aff [temp->obj_flags.value[2]][FULL]*amount)/4); gain_condition(ch,THIRST,(int)((int)drink_aff [temp->obj_flags.value[2]][THIRST]*amount)/4); if(GET_COND(ch,DRUNK)>10) act("You feel drunk.",FALSE,ch,0,0,TO_CHAR); if(GET_COND(ch,THIRST)>20) act("You do not feel thirsty.",FALSE,ch,0,0,TO_CHAR); if(GET_COND(ch,FULL)>20) act("You are full.",FALSE,ch,0,0,TO_CHAR); if(temp->obj_flags.value[3]) /* The shit was poisoned ! */ { act("Ooups, it tasted rather strange ?!!?",FALSE,ch,0,0,TO_CHAR); act("$n chokes and utters some strange sounds.", TRUE,ch,0,0,TO_ROOM); af.type = SPELL_POISON; af.duration = amount*3; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_POISON; affect_join(ch,&af, FALSE, FALSE); } /* empty the container, and no longer poison. */ temp->obj_flags.value[1]-= amount; if(!temp->obj_flags.value[1]) { /* The last bit */ temp->obj_flags.value[2]=0; temp->obj_flags.value[3]=0; name_from_drinkcon(temp); } return; } } act("It's empty already.",FALSE,ch,0,0,TO_CHAR); return; }
void do_sip(struct char_data *ch, char *argument, int cmd) { struct affected_type af; char arg[MAX_STRING_LENGTH]; char buf[MAX_STRING_LENGTH]; struct obj_data *temp; one_argument(argument,arg); if(!(temp = get_obj_in_list_vis(ch,arg,ch->carrying))) { act("You can't find it!",FALSE,ch,0,0,TO_CHAR); return; } if(temp->obj_flags.type_flag!=ITEM_DRINKCON) { act("You can't sip from that!",FALSE,ch,0,0,TO_CHAR); return; } if(GET_COND(ch,DRUNK)>10) /* The pig is drunk ! */ { act("You simply fail to reach your mouth!",FALSE,ch,0,0,TO_CHAR); act("$n tries to sip, but fails!",TRUE,ch,0,0,TO_ROOM); return; } if(!temp->obj_flags.value[1]) /* Empty */ { act("But there is nothing in it?",FALSE,ch,0,0,TO_CHAR); return; } act("$n sips from the $o",TRUE,ch,temp,0,TO_ROOM); sprintf(buf,"It tastes like %s.\n\r",drinks[temp->obj_flags.value[2]]); send_to_char(buf,ch); gain_condition(ch,DRUNK,(int)(drink_aff[temp->obj_flags.value[2]][DRUNK]/4)); gain_condition(ch,FULL,(int)(drink_aff[temp->obj_flags.value[2]][FULL]/4)); gain_condition(ch,THIRST,(int)(drink_aff[temp->obj_flags.value[2]][THIRST]/4)); weight_change_object(temp, -1); /* Subtract one unit */ if(GET_COND(ch,DRUNK)>10) act("You feel drunk.",FALSE,ch,0,0,TO_CHAR); if(GET_COND(ch,THIRST)>20) act("You do not feel thirsty.",FALSE,ch,0,0,TO_CHAR); if(GET_COND(ch,FULL)>20) act("You are full.",FALSE,ch,0,0,TO_CHAR); if(temp->obj_flags.value[3]&&!IS_AFFECTED(ch,AFF_POISON)) /* The shit was poisoned ! */ { act("But it also had a strange taste!",FALSE,ch,0,0,TO_CHAR); af.type = SPELL_POISON; af.duration = 3; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_POISON; affect_to_char(ch,&af); } temp->obj_flags.value[1]--; if(!temp->obj_flags.value[1]) /* The last bit */ { temp->obj_flags.value[2]=0; temp->obj_flags.value[3]=0; name_from_drinkcon(temp); } return; }
/* * Update all chars, including mobs. */ void char_update( void ) { CHAR_DATA *ch; CHAR_DATA *ch_next; CHAR_DATA *ch_quit; ch_quit = NULL; /* update save counter */ save_number++; if (save_number > 29) save_number = 0; for ( ch = char_list; ch != NULL; ch = ch_next ) { AFFECT_DATA *paf; AFFECT_DATA *paf_next; ch_next = ch->next; if ( ch->timer > 30 ) ch_quit = ch; if ( ch->position >= POS_STUNNED ) { /* check to see if we need to go home */ if (IS_NPC(ch) && ch->zone != NULL && ch->zone != ch->in_room->area && ch->desc == NULL && ch->fighting == NULL && !IS_AFFECTED(ch,AFF_CHARM) && number_percent() < 5) { act("$n wanders on home.",ch,NULL,NULL,TO_ROOM); extract_char(ch,TRUE); continue; } if ( ch->hit < ch->max_hit ) ch->hit += hit_gain(ch); else ch->hit = ch->max_hit; if ( ch->mana < ch->max_mana ) ch->mana += mana_gain(ch); else ch->mana = ch->max_mana; if ( ch->move < ch->max_move ) ch->move += move_gain(ch); else ch->move = ch->max_move; } if ( ch->position == POS_STUNNED ) update_pos( ch ); if ( !IS_NPC(ch) && ch->level < LEVEL_IMMORTAL ) { OBJ_DATA *obj; if ( ( obj = get_eq_char( ch, WEAR_LIGHT ) ) != NULL && obj->item_type == ITEM_LIGHT && obj->value[2] > 0 ) { if ( --obj->value[2] == 0 && ch->in_room != NULL ) { --ch->in_room->light; act( "$p goes out.", ch, obj, NULL, TO_ROOM ); act( "$p flickers and goes out.", ch, obj, NULL, TO_CHAR ); extract_obj( obj ); } else if ( obj->value[2] <= 5 && ch->in_room != NULL) act("$p flickers.",ch,obj,NULL,TO_CHAR); } if (IS_IMMORTAL(ch)) ch->timer = 0; if ( ++ch->timer >= 12 ) { if ( ch->was_in_room == NULL && ch->in_room != NULL ) { ch->was_in_room = ch->in_room; if ( ch->fighting != NULL ) stop_fighting( ch, TRUE ); act( "$n disappears into the void.", ch, NULL, NULL, TO_ROOM ); send_to_char( "You disappear into the void.\n\r", ch ); if (ch->level > 1) save_char_obj( ch ); char_from_room( ch ); char_to_room( ch, get_room_index( ROOM_VNUM_LIMBO ) ); } } gain_condition( ch, COND_DRUNK, -1 ); gain_condition( ch, COND_FULL, ch->size > SIZE_MEDIUM ? -4 : -2 ); gain_condition( ch, COND_THIRST, -1 ); gain_condition( ch, COND_HUNGER, ch->size > SIZE_MEDIUM ? -2 : -1); } for ( paf = ch->affected; paf != NULL; paf = paf_next ) { paf_next = paf->next; if ( paf->duration > 0 ) { paf->duration--; if (number_range(0,4) == 0 && paf->level > 0) paf->level--; /* spell strength fades with time */ } else if ( paf->duration < 0 ) ; else { if ( paf_next == NULL || paf_next->type != paf->type || paf_next->duration > 0 ) { if ( paf->type > 0 && skill_table[paf->type].msg_off ) { send_to_char( skill_table[paf->type].msg_off, ch ); send_to_char( "\n\r", ch ); } } affect_remove( ch, paf ); } } /* * Careful with the damages here, * MUST NOT refer to ch after damage taken, * as it may be lethal damage (on NPC). */ if (is_affected(ch, gsn_plague) && ch != NULL) { AFFECT_DATA *af, plague; CHAR_DATA *vch; int dam; if (ch->in_room == NULL) continue; act("$n writhes in agony as plague sores erupt from $s skin.", ch,NULL,NULL,TO_ROOM); send_to_char("You writhe in agony from the plague.\n\r",ch); for ( af = ch->affected; af != NULL; af = af->next ) { if (af->type == gsn_plague) break; } if (af == NULL) { REMOVE_BIT(ch->affected_by,AFF_PLAGUE); continue; } if (af->level == 1) continue; plague.where = TO_AFFECTS; plague.type = gsn_plague; plague.level = af->level - 1; plague.duration = number_range(1,2 * plague.level); plague.location = APPLY_STR; plague.modifier = -5; plague.bitvector = AFF_PLAGUE; for ( vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room) { if (!saves_spell(plague.level - 2,vch,DAM_DISEASE) && !IS_IMMORTAL(vch) && !IS_AFFECTED(vch,AFF_PLAGUE) && number_bits(4) == 0) { send_to_char("You feel hot and feverish.\n\r",vch); act("$n shivers and looks very ill.",vch,NULL,NULL,TO_ROOM); affect_join(vch,&plague); } } dam = UMIN(ch->level,af->level/5+1); ch->mana -= dam; ch->move -= dam; damage( ch, ch, dam, gsn_plague,DAM_DISEASE,FALSE); } else if ( IS_AFFECTED(ch, AFF_POISON) && ch != NULL && !IS_AFFECTED(ch,AFF_SLOW)) { AFFECT_DATA *poison; poison = affect_find(ch->affected,gsn_poison); if (poison != NULL) { act( "$n shivers and suffers.", ch, NULL, NULL, TO_ROOM ); send_to_char( "You shiver and suffer.\n\r", ch ); damage(ch,ch,poison->level/10 + 1,gsn_poison, DAM_POISON,FALSE); } } else if ( ch->position == POS_INCAP && number_range(0,1) == 0) { damage( ch, ch, 1, TYPE_UNDEFINED, DAM_NONE,FALSE); } else if ( ch->position == POS_MORTAL ) { damage( ch, ch, 1, TYPE_UNDEFINED, DAM_NONE,FALSE); } } /* * Autosave and autoquit. * Check that these chars still exist. */ for ( ch = char_list; ch != NULL; ch = ch_next ) { ch_next = ch->next; if (ch->desc != NULL && ch->desc->descriptor % 30 == save_number) { save_char_obj(ch); } if (ch == ch_quit) { do_function(ch, &do_quit, "" ); } } return; }
/* * Update all chars, including mobs. */ void char_update (void) { CHAR_DATA *ch = NULL; CHAR_DATA *ch_next; CHAR_DATA *ch_quit; ch_quit = NULL; /* update save counter */ save_number++; if (save_number > 29) save_number = 0; for (ch = char_list; ch != NULL; ch = ch_next) { AFFECT_DATA *paf; AFFECT_DATA *paf_next; ch_next = ch->next; if(!ch->infight) { ch->hit = ch->max_hit; ch->mana = ch->max_mana; ch->move = ch->max_move; update_pos (ch); } if (ch->timer > 30) ch_quit = ch; if (ch->position == POS_STUNNED) update_pos (ch); if (!IS_NPC (ch) && ch->level < LEVEL_IMMORTAL) { if (IS_IMMORTAL (ch)) ch->timer = 0; if (++ch->timer >= 12) { if (ch->was_in_room == NULL && ch->in_room != NULL) { ch->was_in_room = ch->in_room; act ("$n disappears into the void.", ch, NULL, NULL, TO_ROOM); send_to_char ("You disappear into the void.\n\r", ch); if (ch->level > 1) save_char_obj (ch); char_from_room (ch); char_to_room (ch, get_room_index (2)); } } gain_condition (ch, COND_DRUNK, -1); gain_condition (ch, COND_FULL, ch->size > SIZE_MEDIUM ? -4 : -2); gain_condition (ch, COND_THIRST, -1); gain_condition (ch, COND_HUNGER, ch->size > SIZE_MEDIUM ? -2 : -1); } for (paf = ch->affected; paf != NULL; paf = paf_next) { paf_next = paf->next; if (paf->duration > 0) { paf->duration--; if (number_range (0, 4) == 0 && paf->level > 0) paf->level--; /* spell strength fades with time */ } else if (paf->duration < 0); else { if (paf_next == NULL || paf_next->type != paf->type || paf_next->duration > 0) { if (paf->type > 0 && skill_table[paf->type].msg_off) { send_to_char (skill_table[paf->type].msg_off, ch); send_to_char ("\n\r", ch); } } affect_remove (ch, paf); } } /* * Careful with the damages here, * MUST NOT refer to ch after damage taken, * as it may be lethal damage (on NPC). */ if (ch->position == POS_INCAP && number_range (0, 1) == 0) { damage (ch, ch, 1, TYPE_UNDEFINED, ELE_NON, FALSE); } else if (ch->position == POS_MORTAL) { damage (ch, ch, 1, TYPE_UNDEFINED, ELE_NON, FALSE); } } /* * Autosave and autoquit. * Check that these chars still exist. */ for (ch = char_list; ch != NULL; ch = ch_next) { /* * Edwin's fix for possible pet-induced problem * JR -- 10/15/00 */ if (!IS_VALID(ch)) { bug("update_char: Trying to work with an invalidated character.\n",0); break; } ch_next = ch->next; if (ch->desc != NULL && ch->desc->descriptor % 30 == save_number) { save_char_obj (ch); } if (ch == ch_quit) { do_function (ch, &do_quit, ""); } } return; }