void affect_join(struct char_data *ch, struct affected_type *af, bool add_dur, bool avg_dur, bool add_mod, bool avg_mod) { struct affected_type *hjp, *next; bool found = FALSE; for (hjp = ch->affected; !found && hjp; hjp = next) { next = hjp->next; if ((hjp->spell == af->spell) && (hjp->location == af->location)) { if (add_dur) af->duration += hjp->duration; else if (avg_dur) af->duration = (af->duration+hjp->duration)/2; if (add_mod) af->modifier += hjp->modifier; else if (avg_mod) af->modifier = (af->modifier+hjp->modifier)/2; affect_remove(ch, hjp); affect_to_char(ch, af); found = TRUE; } } if (!found) affect_to_char(ch, af); }
int spell_ethereal_wolf_howl( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( is_affected( victim, sn ) || is_affected( ch, sn ) ) { return SKPELL_MISSED; } af.type = sn; af.level = level; af.duration = level / 5; af.location = APPLY_DAMROLL; af.modifier = ( level / 5 ) * -1; af.bitvector = 0; affect_to_char( victim, &af ); af.location = APPLY_HITROLL; af.modifier = ( level / 5 ) * -1; affect_to_char( victim, &af ); af.location = APPLY_DAMROLL; af.modifier = level / 5; affect_to_char( ch, &af ); af.location = APPLY_HITROLL; af.modifier = level / 5; affect_to_char( ch, &af ); return SKPELL_NO_DAMAGE; }
void affect_join( struct char_data *ch, struct affected_type *af, bool avg_dur, bool avg_mod ) { struct affected_type *hjp; bool found = FALSE; for (hjp = ch->affected; !found && hjp; hjp = hjp->next) { if ( hjp->type == af->type ) { af->duration += hjp->duration; if (avg_dur) af->duration /= 2; af->modifier += hjp->modifier; if (avg_mod) af->modifier /= 2; affect_remove(ch, hjp); affect_to_char(ch, af); found = TRUE; } } if (!found) affect_to_char(ch, af); }
void sun_blind(struct char_data *ch) { struct affected_type af; if (get_max_level(ch) >= LOW_IMMORTAL) return; if (IS_AFFECTED2(ch, AFF2_SUN_BLIND)) return; if (IS_AFFECTED(ch, AFF_BLIND)) return; if (affected_by_spell(ch, SPELL_SUN_BLIND)) affect_from_char(ch, SPELL_SUN_BLIND); send_to_char("Aaarrrggghh! The sun burns your eyes!\n\r", ch); af.type = SPELL_SUN_BLIND; af.location = APPLY_HITROLL; af.modifier = -4; af.duration = (number(1, 2) + (5 - get_max_level(ch) / 10)); af.bitvector = 0; affect_to_char(ch, &af); af.location = APPLY_AC; af.modifier = +20; affect_to_char(ch, &af); af.modifier = 0; af.location = APPLY_BV2; af.bitvector = AFF2_SUN_BLIND; affect_to_char(ch, &af); }
void spell_feeblemind(byte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; int t,i; if (!saves_spell(victim, SAVING_SPELL)) { /* eld - I took the liberty of adding this little dandy.. In my opinion, */ /* this spell should not be accumulative. */ if(affected_by_spell(victim, SPELL_FEEBLEMIND)) { send_to_char("They are already dumb enough as it is!\n\r", ch); return; } send_to_char("You feel really really dumb\n\r", victim); af.type = SPELL_FEEBLEMIND; af.duration = 24; af.modifier = -5; af.location = APPLY_INT; af.bitvector = 0; affect_to_char(victim, &af); af.type = SPELL_FEEBLEMIND; af.duration = 24; af.modifier = 70; af.location = APPLY_SPELLFAIL; af.bitvector = 0; affect_to_char(victim, &af); /* last, but certainly not least */ if (!victim->skills) return; t = number(1,100); while (1) { for (i=0;i<MAX_SKILLS;i++) { if (victim->skills[i].learned) t--; if (t==0) { victim->skills[i].learned = 0; victim->skills[i].flags = 0; break; } /* eld - what happens if you get outside the for loop? Yer screwed... */ /* this fixes it by giving the function something to do (return) */ } return; } } }
void Weave::UpdateAttunementsFor(CHAR_DATA & ch, int count) { // Determine the modifier from the count static const int BaseValue = 15; int modifier(0); // Only allow non-zero modifiers if the skill is actually possessed if (get_skill(&ch, gsn_attunefount) > 0) { if (count > BaseValue) { // Anything over 15 founts is only worth a single point modifier = (count - BaseValue); count = BaseValue; } // This is a reduced formula using summations so it may not be clear what is going on: // Basically, the first fount is worth 2 * BaseValue, the next is worth 2 * (BaseValue - 1), the next 2 * (BaseValue - 2), and so on, until eventually they are worth exactly 1 each // So for BV = 15, the values are 30, 28, 26, 24, ..., 6, 4, 2, 1, 1, 1, ... modifier += (2 * ((BaseValue * count) - ((count * (count - 1)) / 2))); } // Compare the new modifier to the existing to see whether there is any change int prevModifier(0); AFFECT_DATA * paf(get_affect(&ch, gsn_attunefount)); if (paf != NULL) prevModifier = paf->modifier; if (prevModifier == modifier) return; // Character needs a change; strip any existing effect and add the new one if appropriate affect_strip(&ch, gsn_attunefount); if (modifier == 0) send_to_char("You feel the last of your attunements leave you.\n", &ch); else { // Prepare the effect AFFECT_DATA af = {0}; af.where = TO_AFFECTS; af.type = gsn_attunefount; af.duration = -1; af.modifier = modifier; af.location = APPLY_HIT; affect_to_char(&ch, &af); af.location = APPLY_MANA; affect_to_char(&ch, &af); // Adjust for gains (ignore losses) if (prevModifier < modifier) { ch.hit += (modifier - prevModifier); ch.mana += (modifier - prevModifier); } // Send an echo send_to_char("You feel the power of your attunements shift.\n", &ch); } }
/* * Allows a healer to boost the life force of a recipient (e.g. increase their * max health points and movement for a level's worth of ticks). The modifier * (how much hp and move they receive) will be calculated by the healer's casting * level. This cannot be cast on NPC's as a way to make them stronger. */ void spell_life_boost(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *)vo; AFFECT_DATA af; int modifier = 0; // Not on NPC's if (IS_NPC(victim)) { send_to_char("You failed.\r\n", ch); return; } if (is_affected(victim, sn)) { if (victim == ch) { // Remove the affect so it can be re-added to yourself affect_strip(victim, sn); } else { act("$N is already affected by the increased vitality.", ch, NULL, victim, TO_CHAR); return; } } // Base is the players level modifier = ch->level; // If the player is casting it on themselves we'll give them a 12hp-13hp bonus at 51. Healer's // aren't going to be huge player killers so why not. if (ch == victim) { modifier += ch->level / 4; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.modifier = modifier; af.location = APPLY_HIT; af.bitvector = 0; affect_to_char(victim, &af); af.location = APPLY_MOVE; affect_to_char(victim, &af); act("$N has been vitalized.", victim, NULL, victim, TO_ROOM); send_to_char("You feel an increased vitality.\r\n", victim); return; } // end spell_life_boost
bool spell_causticblast(int sn, int level, CHAR_DATA * ch, void * vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam(dice(level, 4)); // Blast them act("$n unleashes a blast of hissing acid upon $N!", ch, NULL, victim, TO_NOTVICT); act("You unleash a blast of hissing acid upon $N!", ch, NULL, victim, TO_CHAR); act("$n unleashes a blast of hissing acid upon you!", ch, NULL, victim, TO_VICT); if (saves_spell(level, ch, victim, DAM_ACID)) { damage_old(ch, victim, dam / 2, sn, DAM_ACID, true); return true; } damage_old(ch, victim, dam, sn, DAM_ACID, true); if (!IS_VALID(victim) || victim->in_room != ch->in_room) return true; act("The acid eats away at you, leaving painful, ugly scars!", victim, NULL, NULL, TO_CHAR); act("The acid eats away at $m, leaving painful, ugly scars!", victim, NULL, NULL, TO_ROOM); // Apply -charisma AFFECT_DATA af = {0}; af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level / 2; af.location = APPLY_CHR; af.modifier = -1; affect_to_char(victim, &af); // Apply burning for (AFFECT_DATA * paf(get_affect(victim, sn)); paf != NULL; paf = get_affect(victim, sn, paf)) { if (paf->location == APPLY_NONE) { paf->duration = UMAX(2, paf->duration); paf->modifier = UMIN(100, paf->modifier + 1); return true; } } af.duration = 2; af.location = APPLY_NONE; af.modifier = 1; affect_to_char(victim, &af); return true; }
/* affect_update: called from comm.c (causes spells to wear off) */ void affect_update(void) { struct affected_type *af, *next; struct char_data *i; for (i = character_list; i; i = i->next) { for (af = i->affected; af; af = next) { next = af->next; if (af->duration >= 1) af->duration--; else if (af->duration == -1) /* No action */ af->duration = -1; /* GODs only! unlimited */ else { if ((af->type > 0) && (af->type <= MAX_SPELLS)) if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) if (spell_info[af->type].wear_off_msg) send_to_char(i, "%s\r\n", spell_info[af->type].wear_off_msg); affect_remove(i, af); /** Add Fatigue if coming down from berserk */ if(af->type == SKILL_BERSERK){ //|| af->type == adrenaline shot){ af->type = 1; //Banankick: not sure if this works. af->duration = 10; af->modifier = -10; af->location = APPLY_EVASION; //APPLY_NONE? af->bitvector = AFF_FATIGUED; affect_to_char(i, &af); } } } } }
/* * A spell to help the healer resist some offensive magics against it. Healer's don't * have many offensive weapons and thus are vulnerable characters, this should help * at least protect them a little more from spells. This should be set to target * char_self so it can only be cast on the healer themselves. We don't want to create * super chars with saves who make casters worthless. */ void spell_magic_resistance(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *)vo; AFFECT_DATA af; if (is_affected(victim, sn)) { affect_strip(victim, sn); } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.modifier = (ch->level / 10) * -1; af.location = APPLY_SAVES; af.bitvector = 0; affect_to_char(victim, &af); act("$N has an enhanced resistance to magic.", victim, NULL, victim, TO_ROOM); send_to_char("You feel an enhanced resistance to magic.\r\n", victim); return; } // end magic resistance
/* * Sense affliction will allow the healer to see an (Affliction) flag on a player when * they do a 'look' in the room if a player is afflicted by something the healer can * cure. If the healer looks at the person specifically they will see everything they * are afflicted with that they can cure specifically. The healer can cast this on * themselves but not others. This has a long duration and is not dispelable. I * suppose this could also have just been a skill. */ void spell_sense_affliction(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *)vo; AFFECT_DATA af; if (is_affected(victim, sn)) { // Remove the affect so it can be re-added to yourself affect_strip(victim, sn); } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = ch->level + (ch->level / 2); af.modifier = 0; af.location = APPLY_NONE; af.bitvector = 0; affect_to_char(victim, &af); send_to_char("Your senses for those afflicted are heightened.\r\n", victim); if (ch != victim) { act("$N's senses for those afflicted are heightened.", victim, NULL, victim, TO_ROOM); } return; } // end spell_sense_affliction
void renew_affect (CHAR_DATA * ch, AFFECT_DATA * aff) { AFFECT_DATA *paf; AFFECT_DATA pasaf; bool foundd; foundd = FALSE; bzero (&pasaf, sizeof (pasaf)); pasaf.type = aff->type; pasaf.duration = aff->duration; pasaf.location = aff->location; pasaf.modifier = aff->modifier; pasaf.bitvector = aff->bitvector; pasaf.bitvector2 = aff->bitvector2; for (paf = ch->affected; paf != NULL; paf = paf->next) { if (paf->type == aff->type && paf->location == aff->location) { paf->duration = aff->duration; foundd = TRUE; } } if (!foundd) affect_to_char (ch, &pasaf); return; }
/* * Enhanced recovery will allow the recipient to heal more on every tick. Originally this * spell was written for another class (on 5/26/2000) but it fits better under a healer. */ void spell_enhanced_recovery(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *)vo; AFFECT_DATA af; if (is_affected(victim, sn)) { if (victim == ch) { // Remove the affect so it can be re-added to yourself affect_strip(victim, sn); } else { act("$N is already blessed with enhanced recovery.", ch, NULL, victim, TO_CHAR); return; } } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (ch->level / 2); af.modifier = 0; af.location = APPLY_NONE; af.bitvector = 0; affect_to_char(victim, &af); act("$N has been blessed with an enhanced recovery.", victim, NULL, victim, TO_ROOM); send_to_char("You feel blessed with a enhanced recovery.\r\n", victim); } // end spell_enhanced_recovery
int load_char_affects(Character *ch) { char buf[400]; sql_stmt *stmt; int total = 0; int len = sprintf(buf, "select * from char_affect where characterId=%" PRId64, ch->id); if (sql_query(buf, len, &stmt) != SQL_OK) { log_data("could not prepare statement"); return 0; } while (sql_step(stmt) != SQL_DONE) { int affId = sql_col_int(stmt, "affectId"); Affect *aff = load_affect_by_id(affId); if (aff != 0) { aff->duration = sql_col_int(stmt, "duration"); affect_to_char(ch, aff); } total++; } if (sql_finalize(stmt) != SQL_OK) { log_data("could not finalize statement"); } return total; }
bool spell_innerflame_master(int sn, int level, CHAR_DATA *ch, void *vo, OBJ_DATA *obj) { AFFECT_DATA af; if ( is_affected(ch, gsn_innerflame_novice) || is_affected(ch, gsn_innerflame_intermediate) || is_affected(ch, gsn_innerflame_advanced) || is_affected(ch, gsn_innerflame_expert) || is_affected(ch, gsn_innerflame_master)) return FALSE; af.type = sn; af.duration = 15; af.location = 0; af.modifier = 0; af.bitvector = 0; af.save = TRUE; affect_to_char(ch, &af); act("You concentrate on your inner flame.", ch, NULL, NULL, TO_CHAR); act("$n concentrates on $s inner flame.", ch, NULL, NULL, TO_ROOM); return TRUE; }
void do_drowfire(CHAR_DATA * ch, char *argument) { AFFECT_DATA af; CHAR_DATA *victim; if (ch->race != RACE_DROW) { send_to_char(AT_GREY, "Drowfire by a non-drow?\n\r", ch); return; } if (argument[0] != '\0') { if (!(victim = get_char_room(ch, argument))) { send_to_char(C_DEFAULT, "They aren't here.\n\r", ch); return; } } else { if (!(victim = ch->fighting)) { send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch); return; } } if (is_affected(victim, gsn_drowfire)) return; WAIT_STATE(ch, skill_table[gsn_drowfire].beats); af.type = gsn_drowfire; af.level = ch->level; af.duration = ch->level / 10; af.location = APPLY_AC; af.modifier = 5 * ch->level; af.bitvector = 0; affect_to_char(victim, &af); af.location = APPLY_HITROLL; af.modifier = 0 - ch->level / 5; af.bitvector = 0; affect_to_char(victim, &af); send_to_char(AT_PINK, "You are surrounded by a purple outline.\n\r", victim); act(AT_PINK, "$n is surrounded by a purple outline.", victim, NULL, NULL, TO_ROOM); if (!victim->fighting) set_fighting(victim, ch); return; }
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_pray( CHAR_DATA * ch, char * argument ) { if ( !IS_GOOD( ch ) ) { send_to_char( AT_BLUE, "Thalador forgives some of your sins.\n\r", ch ); ch->alignment += 10; } else if ( !IS_NPC( ch ) && ch->pcdata->learned[ gsn_prayer ] < number_percent() ) { send_to_char( AT_BLUE, "Thalador smiles upon you, and sends you a gold coin.\n\r", ch ); ch->money.gold += 1; } else if ( !is_affected( ch, gsn_prayer ) ) { AFFECT_DATA af; af.duration = ch->level / 3; af.level = ch->level; af.type = gsn_prayer; af.bitvector = 0; af.location = APPLY_HIT; af.modifier = number_range( ch->level, ch->level * 2 ); affect_to_char( ch, &af ); af.location = APPLY_MANA; af.modifier = number_range( ch->level / 2, ch->level ); affect_to_char( ch, &af ); af.location = APPLY_INT; af.modifier = ( ( ch->level - 1 ) / 50 ) + 1; affect_to_char( ch, &af ); af.location = APPLY_DEX; affect_to_char( ch, &af ); send_to_char( AT_BLUE, "Thalador places his blessing upon you.\n\r", ch ); update_skpell( ch, gsn_prayer ); } else { send_to_char( AT_BLUE, "Thalador frowns at your greed.\n\r", ch ); ch->alignment -= 10; } send_to_char( AT_GREY, "You fall to the ground, unconscious.\n\r", ch ); act( AT_GREY, "$n falls to the ground, unconscious.", ch, NULL, NULL, TO_ROOM ); STUN_CHAR( ch, 4, STUN_COMMAND ); return; }
void remove_sun_blind(struct char_data *ch) { struct affected_type af; if (get_max_level(ch) >= LOW_IMMORTAL) return; send_to_char("Your vision begins to return.\n\r", ch); act("$n's vision begins to return.\n\r", TRUE, ch, 0, 0, TO_ROOM); affect_from_char(ch, SPELL_SUN_BLIND); af.type = SPELL_SUN_BLIND; af.location = APPLY_HITROLL; af.modifier = -2; af.duration = 1; af.bitvector = 0; affect_to_char(ch, &af); af.location = APPLY_AC; af.modifier = +10; affect_to_char(ch, &af); }
void swordtech(CHAR_DATA * ch, long bit) { AFFECT_DATA af; if(!ch || IS_NPC(ch)) return; af.type = gsn_swordtech; af.duration = 3 + ch->pcdata->stats[UNI_GEN]; af.modifier = 0; af.location = 0; af.bitvector = bit; affect_to_char(ch, &af); }
bool spell_ordainsanctum(int sn, int level, CHAR_DATA * ch, void * vo, int target) { // Sanity check if (ch->in_room == NULL) { bug("Ordain sanctum called from null room", 0); return false; } // Check for cooldown if (is_affected(ch, sn)) { send_to_char("You are not yet ready to ordain this ground.\n", ch); return false; } // Check for effect already present if (room_is_affected(ch->in_room, sn)) { send_to_char("This place has already been ordained as a sanctum.\n", ch); return false; } // Check for annointing oil OBJ_DATA * obj(lookup_obj_extra_flag(ch, ITEM_ANNOINTINGOIL)); if (obj == NULL) { send_to_char("You cannot ordain this place without holy oil.\n", ch); return false; } // Ordain the room act("You murmur a soft chant, pouring out $p as you do so.", ch, obj, NULL, TO_CHAR); act("$n murmurs a soft chant, pouring out $p as $e does so.", ch, obj, NULL, TO_ROOM); act("As the last of the oil is poured out, you sense a certain protective aura fill this place.", ch, NULL, NULL, TO_ALL); AFFECT_DATA af = {0}; af.where = TO_ROOM; af.type = sn; af.level = level; af.duration = (level / 12); affect_to_room(ch->in_room, &af); // Apply a cooldown af.duration = 14; affect_to_char(ch, &af); return true; }
void affect_join(struct char_data * ch, struct affected_type * af, bool add_dur, bool avg_dur, bool add_mod, bool avg_mod) { struct affected_type *hjp; bool found = FALSE; for (hjp = ch->affected; !found && hjp; hjp = hjp->next) { if ((hjp->type == af->type) && (hjp->location == af->location)) { if (add_dur) { af->duration += hjp->duration; } if (avg_dur) { af->duration >>= 1; } if (add_mod) { af->modifier += hjp->modifier; } if (avg_mod) { af->modifier >>= 1; } affect_remove(ch, hjp, 0); affect_to_char(ch, af); found = TRUE; } } if (!found) { affect_to_char(ch, af); } }
/* * A healing spell that will return small bits of health over the period of a few ticks * outside of the normal tick cycle. This will cost half as much as a heal (because it * can only be cast once and is spread out. Players will get 10hp every half tick if * they are below their max health. */ void spell_vitalizing_presence(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *)vo; AFFECT_DATA af; if (is_affected(victim, sn)) { if (victim == ch) { // Remove the affect so it can be re-added to yourself affect_strip(victim, sn); } else { act("$N is already affected by the vitalizing presence.", ch, NULL, victim, TO_CHAR); return; } } af.where = TO_AFFECTS; af.type = sn; af.level = level; // Lasts longer on yourself if (ch == victim) { af.duration = 10; } else { af.duration = 5; } af.modifier = 0; af.location = APPLY_NONE; af.bitvector = 0; affect_to_char(victim, &af); act("$N is vitalized with a healing presence.", victim, NULL, victim, TO_ROOM); send_to_char("You are vitalized with a healing presence.\r\n", victim); return; } // end spell_vitalizing_presence
void handle_waterwheel_crystal_destroyed(CHAR_DATA & ch, OBJ_DATA & obj) { // Look for the effect AFFECT_DATA * paf(get_obj_affect(&obj, gsn_constructwaterwheel)); if (paf == NULL) return; // Echoes act("As you destroy $p, a surge of energy rushes from it and into you!", &ch, &obj, NULL, TO_CHAR); act("As $n destroys $p, a flash of blue light shines out from it, focused on $m!", &ch, &obj, NULL, TO_ROOM); // Strip the effect from the char if present for (AFFECT_DATA * waf(get_affect(&ch, gsn_constructwaterwheel)); waf != NULL; waf = get_affect(&ch, gsn_constructwaterwheel, waf)) { if (waf->location == APPLY_MANA) { affect_remove(&ch, waf); break; } } // Determine modifier int modifier(paf->duration); if (number_percent() <= get_skill(&ch, gsn_stonecraft)) check_improve(&ch, NULL, gsn_stonecraft, true, 4); else { check_improve(&ch, NULL, gsn_stonecraft, false, 4); modifier /= 2; } // Grant the new effect AFFECT_DATA af = {0}; af.where = TO_AFFECTS; af.type = gsn_constructwaterwheel; af.level = paf->level; af.modifier = UMAX(1, modifier); af.duration = af.modifier; af.location = APPLY_MANA; affect_to_char(&ch, &af); }
/* * Add or enhance an affect. */ void affect_join( CHAR_DATA *ch, AFFECT_DATA *paf ) { AFFECT_DATA *paf_old; bool found; found = FALSE; for ( paf_old = ch->affected; paf_old != NULL; paf_old = paf_old->next ) { if ( paf_old->type == paf->type && paf_old->flags == paf->flags ) { paf->strength = (paf->strength += paf_old->strength) / 2; paf->duration += paf_old->duration; paf->modifier += paf_old->modifier; affect_remove( ch, paf_old ); break; } } affect_to_char( ch, paf ); return; }
bool spell_hoarfrost(int sn, int level, CHAR_DATA * ch, void * vo, int target) { // Sanity check if (ch->in_room == NULL || !ON_GROUND(ch)) { send_to_char("There is no solid ground here to rime over.\n", ch); return false; } // Check for cooldown if (is_affected(ch, sn)) { send_to_char("You are not prepared to conjure more hoarfrost yet.\n", ch); return false; } // Check for the room already having some if (room_is_affected(ch->in_room, sn)) { send_to_char("This place is already coated in hoarfrost.\n", ch); return false; } act("You spin in a slow circle, chanting softly as a thin layer of ice coats the ground.", ch, NULL, NULL, TO_CHAR); act("$n spins in a slow circle, chanting softly as a thin layer of ice coats the ground.", ch, NULL, NULL, TO_ROOM); // Add the effect AFFECT_DATA af = {0}; af.where = TO_ROOM; af.type = sn; af.level = level; af.duration = (level / 10); affect_to_room(ch->in_room, &af); // Add a cooldown af.duration = 8; affect_to_char(ch, &af); return true; }
void Forge::CompleteWeapon(CHAR_DATA & ch, ForgeContext & context) { // Determine the number of bonus points to spend bool forgeMaster(false); int bonusPoints(ch.level / 2); if (number_percent() <= get_skill(&ch, gsn_forgemaster)) { check_improve(&ch, NULL, gsn_forgemaster, true, 4); forgeMaster = true; bonusPoints += 10; } else check_improve(&ch, NULL, gsn_forgemaster, false, 4); if (ch.in_room != NULL && room_is_affected(ch.in_room, gsn_lavaforge)) bonusPoints += 20; if (context.named) bonusPoints += 60; bonusPoints -= context.flaws * 20; switch (Luck::Check(ch)) { case Luck::Lucky: bonusPoints += 5; break; case Luck::Unlucky: bonusPoints -= 5; break; default: break; } bonusPoints = UMAX(0, bonusPoints); // Build the special odds ranges from the weapon and base objects std::vector<std::pair<unsigned int, const SpecialInfo *> > specials; unsigned int nextIndex(0); for (SpecialMap::const_iterator iter(Specials().begin()); iter != Specials().end(); ++iter) { // Make sure there are sufficient points for at least 1 level of this special if (bonusPoints < iter->second.cost) continue; // Calculate odds unsigned int oddsRange(CalculateOddsRange(iter->second, context.weaponInfo->weapon, context.materials)); if (oddsRange == 0) continue; // Add in the range specials.push_back(std::make_pair(nextIndex, &iter->second)); nextIndex += oddsRange; } // Now choose the special types, up to three std::vector<const SpecialInfo *> chosenSpecials; if (nextIndex > 0) { for (size_t i(0); i < 3; ++i) { // Choose an index at random and find the associated special unsigned int index(number_range(0, nextIndex - 1)); for (size_t j(0); j + 1 < specials.size(); ++j) { if (specials[j].first <= index && specials[j + 1].first > index) { // Found the matching special, now verify that it is acceptable in the face of other chosen ones const SpecialInfo * chosenSpecial(specials[j].second); for (size_t k(0); k < chosenSpecials.size(); ++k) { // No duplicates and no more than one uniqueclass if (chosenSpecials[k] == chosenSpecial || (chosenSpecials[k]->uniqueClass && chosenSpecial->uniqueClass)) { chosenSpecial = NULL; break; } } if (chosenSpecial != NULL) chosenSpecials.push_back(chosenSpecial); break; } } } } // Create the base object OBJ_DATA * obj(create_object(get_obj_index(OBJ_VNUM_FORGEWEAPON), 0)); if (obj == NULL) { bug("Forge weapon failed due to bad obj creation", 0); send_to_char("An error has occurred, please contact the gods.\n", &ch); return; } // Fill out the basic info; use the first material as the object's material obj->level = ch.level; obj->weight = number_range(context.weaponInfo->minWeight, (context.weaponInfo->minWeight * 23) / 20); obj->weight = UMIN(obj->weight, context.weight); obj->size = context.weaponInfo->objSize; obj->cost = ((bonusPoints * bonusPoints) / 2) + number_range(0, 300); if (!context.materials.empty()) obj->material = context.materials[0]; if (!context.weaponInfo->damverbs.empty()) copy_string(obj->obj_str, context.weaponInfo->damverbs[number_range(0, context.weaponInfo->damverbs.size() - 1)].c_str()); obj->value[0] = context.weaponInfo->type; obj->value[1] = 10 + (ch.level / 10) + context.weaponInfo->dammod + (context.named ? 1 : 0); obj->value[2] = 2; obj->value[3] = context.weaponInfo->damtype; if (context.weaponInfo->twohanded) SET_BIT(obj->value[4], WEAPON_TWO_HANDS); // Now choose from the selected specials at random until out of points or possible specials while (bonusPoints > 0 && !chosenSpecials.empty()) { // Choose a special and add it in size_t index(number_range(0, chosenSpecials.size() - 1)); chosenSpecials[index]->callback(*obj); bonusPoints -= UMAX(1, chosenSpecials[index]->cost); // Remove the special if too costly for the remaining points or only one allowed if (bonusPoints < chosenSpecials[index]->cost || !chosenSpecials[index]->multipleAllowed) { chosenSpecials[index] = chosenSpecials[chosenSpecials.size() - 1]; chosenSpecials.pop_back(); } } // Compensate for bad luck with increased damage if (context.named && bonusPoints >= 10) ++obj->value[1]; // Choose an adjective from the set of common adjectives plus the weapon-specific adjectives WordList adjectives(Adjectives()); for (size_t i(0); i < context.weaponInfo->adjectives.size(); ++i) adjectives.push_back(context.weaponInfo->adjectives[i]); std::string adjective; if (!adjectives.empty()) adjective = adjectives[number_range(0, adjectives.size() - 1)]; // Break down the material set to only unique materials std::set<int> materials; for (size_t i(0); i < context.materials.size(); ++i) materials.insert(context.materials[i]); std::string materialAdjective; switch (materials.size()) { case 0: break; case 1: materialAdjective = material_table[context.materials[0]].name; break; case 2: { std::set<int>::iterator iter(materials.begin()); materialAdjective = material_table[*iter].name; materialAdjective += '-'; ++iter; materialAdjective += material_table[*iter].name; break; } default: materialAdjective = material_table[context.materials[0]].name; materialAdjective += "-alloyed"; break; } // Build the short desc std::ostringstream shortDesc; if (!adjective.empty()) shortDesc << adjective << ' '; if (!materialAdjective.empty()) shortDesc << materialAdjective << ' '; shortDesc << context.weaponInfo->name; std::string weaponShort(shortDesc.str()); if (!weaponShort.empty()) weaponShort = std::string(indefiniteArticleFor(weaponShort[0])) + ' ' + weaponShort; SetBasicDescs(*obj, weaponShort.c_str(), false); // Set up the exdesc std::ostringstream exdesc; switch (number_range(0, 2)) { case 0: exdesc << "Forged"; break; case 1: exdesc << "Formed"; break; default: exdesc << "Wrought"; break; } exdesc << " from "; switch (materials.size()) { case 0: exdesc << " pure metal"; break; case 1: exdesc << " pure " << material_table[context.materials[0]].name; break; case 2: { std::set<int>::iterator iter(materials.begin()); exdesc << "an alloy of " << material_table[*iter].name << " and "; ++iter; exdesc << material_table[*iter].name; break; } default: exdesc << " a metal alloy"; break; } exdesc << ", this "; if (!adjective.empty()) exdesc << adjective << ' '; exdesc << context.weaponInfo->name; if (IS_OBJ_STAT(obj, ITEM_GLOW)) exdesc << " gleams brightly."; else if (IS_OBJ_STAT(obj, ITEM_DARK)) exdesc << " seems to drink the light into its dark surface."; else if (IS_OBJ_STAT(obj, ITEM_HUM)) exdesc << " hums faintly."; else if (IS_OBJ_STAT(obj, ITEM_NODESTROY)) exdesc << " seems nearly indestructible."; else if (context.named) exdesc << " radiates an aura of power."; else if (forgeMaster) exdesc << " has been masterfully crafted."; else exdesc << " has been well-crafted."; exdesc << ' '; switch (number_range(0, 5)) { case 0: exdesc << "The bands of metal which comprise it have been folded over and over to toughen the final product."; break; case 1: exdesc << "Bands of metal flash-forged together serve to harden the weapon against wear."; break; case 2: exdesc << "Carved into the weapon's length are small straight-lined runes, etched with obvious care."; break; case 3: exdesc << "Folds of the metal have been beaten into the weapon's surface, reinforcing the craftsmanship."; break; case 4: exdesc << "Ornate filigree runs the length of the weapon, decorating it in gleaming metal."; break; default: exdesc << "The lines of the weapon are simple and unadorned, lending it a certain grim elegance."; break; } if (!context.weaponInfo->sentences.empty() && number_bits(1) == 0) exdesc << ' ' << context.weaponInfo->sentences[number_range(0, context.weaponInfo->sentences.size() - 1)]; if (TraitCount(*obj, Trait_Parry) > 0) exdesc << " Forged with unusual precision, the balance of this piece lends itself well to parrying blows."; if (TraitCount(*obj, Trait_Casting) > 0) exdesc << " A sense of focus permeates this piece, as though it has been well-prepared for the channeling of mystical energies."; switch (context.flaws) { case 0: switch (number_range(0, 3)) { case 0: exdesc << " The work is flawless, bearing no sign of weakness."; break; case 1: exdesc << " Clearly well-fashioned, this " << context.weaponInfo->name << " has been made to stand the test of time."; break; case 2: exdesc << " No trace of imperfection mars the surface of this beautiful " << context.weaponInfo->name << '.'; break; default: exdesc << " There is no sign of seam or solder, as though the weapon was cast as a single, perfect unit."; break; } break; case 1: switch (number_range(0, 2)) { case 0: exdesc << " A few minor imperfections mar the otherwise smooth surface of the " << context.weaponInfo->name << '.'; break; case 1: exdesc << " Though not immediately-visible, a couple of minor flaws are evident upon closer inspection."; break; default: exdesc << " Some dents remain from the original crafting, slightly weakening the metalwork."; break; } break; default: switch (number_range(0, 2)) { case 0: exdesc << " Significant flaws are evident along the " << context.weaponInfo->name << "'s length."; break; default: exdesc << " Several seams show clearly on the weapon's surface, evidence of clumsy forgework."; break; } break; } // Apply the desc exdesc << '\n'; EXTRA_DESCR_DATA * extraDesc(new_extra_descr()); copy_string(extraDesc->keyword, obj->name); copy_string(extraDesc->description, exdesc.str().c_str()); extraDesc->description = format_string(extraDesc->description); extraDesc->next = obj->extra_descr; obj->extra_descr = extraDesc; // Give the object to the char obj_to_char(obj, &ch); // Echoes (and charge max mana for the naming, if present) act("You quench the metalwork, now shaped into $p.", &ch, obj, NULL, TO_CHAR); act("$n quenches the metalwork, now shaped into $p.", &ch, obj, NULL, TO_ROOM); if (context.named) { act("You can feel the air about it charged with power drained from your very being, as the newly-forged weapon lies waiting to receive its true Name.", &ch, obj, NULL, TO_CHAR); ch.max_mana = UMAX(0, ch.max_mana - NamingManaCost); if (!IS_NPC(&ch)) ch.pcdata->perm_mana = UMAX(0, ch.pcdata->perm_mana - NamingManaCost); ch.mana = UMIN(ch.mana, ch.max_mana); // Add an effect to the char to indicate he can name the object AFFECT_DATA af = {0}; af.where = TO_AFFECTS; af.type = gsn_forgeweapon; af.location = APPLY_HIDE; af.duration = -1; af.point = obj; af.level = ch.level; affect_to_char(&ch, &af); } }
void Forge::CreateWeapon(CHAR_DATA & ch, const char * argument) { // Perform basic skill check int skill(get_skill(&ch, gsn_forgeweapon)); if (skill <= 0) { send_to_char("Huh?\n", &ch); return; } // Check for cooldown for (AFFECT_DATA * paf(get_affect(&ch, gsn_forgeweapon)); paf != NULL; paf = get_affect(&ch, gsn_forgeweapon, paf)) { if (paf->point == NULL && paf->location == APPLY_NONE) { send_to_char("You are not ready for the trying process of forging another weapon just yet.\n", &ch); return; } } // Check for naming AFFECT_DATA * nameAff(FindNameEffect(ch)); if (nameAff != NULL) { OBJ_DATA * nameObj(FindNameableObject(ch, *nameAff)); if (nameObj != NULL) { act("You must first confer a true Name upon $p.", &ch, nameObj, NULL, TO_CHAR); return; } // No longer has the obj, so just clean up the effect and move on affect_remove(&ch, nameAff); } // Get the weapon type name char arg[MAX_INPUT_LENGTH]; argument = one_argument(argument, arg); if (arg[0] == '\0') { send_to_char("Which type of weapon did you wish to forge?\n", &ch); return; } // Begin building the context, starting with the weapon type std::auto_ptr<ForgeContext> context(new ForgeContext); context->skill = skill; context->weaponInfo = LookupWeapon(arg); if (context->weaponInfo == NULL) { send_to_char("You do not know how to make weapons of that type.\n", &ch); return; } // Check for mana int manaCost(skill_table[gsn_forgeweapon].min_mana); if (ch.mana < manaCost) { send_to_char("You are too weary to forge a weapon right now.\n", &ch); return; } // Get the first object std::vector<OBJ_DATA*> baseObjects; if (!ObtainBaseObject(*context, baseObjects, ch, argument)) return; // Check for an alloy argument = one_argument(argument, arg); if (arg[0] != '\0' && !str_prefix(arg, "alloy")) { if (!ObtainBaseObject(*context, baseObjects, ch, argument)) return; argument = one_argument(argument, arg); } // Check for name if (arg[0] != '\0' && !str_prefix(arg, "name")) { // Verify max mana if (ch.max_mana < NamingManaCost) { send_to_char("You lack the will to speak a true Name.\n", &ch); return; } // Verify lava forge if (ch.in_room == NULL || !room_is_affected(ch.in_room, gsn_lavaforge)) { send_to_char("You may only confer a true Name from the heat of the earth itself, at a lava forge.\n", &ch); return; } context->named = true; argument = one_argument(argument, arg); } // Check for superfluous arguments if (arg[0] != '\0') { send_to_char("Syntax: forgeweapon <type> <base_object> [alloy <base_object>] [name]\n", &ch); return; } // Check for sufficient weight if (context->weight < context->weaponInfo->minWeight) { std::ostringstream mess; mess << "Forging a " << context->weaponInfo->name << " requires more raw material than that!\n"; send_to_char(mess.str().c_str(), &ch); return; } // Build object list to help with echoes std::ostringstream objMess; objMess << baseObjects[0]->short_descr; for (size_t i(1); (i + 1) < baseObjects.size(); ++i) objMess << ", " << baseObjects[i]->short_descr; if (baseObjects.size() > 1) objMess << " and " << baseObjects[baseObjects.size() - 1]->short_descr; std::string objList(objMess.str()); // Perform initial echoes std::ostringstream mess; mess << "With a blast of heat and flame, you render down " << objList << " into a liquid mass of metal."; act(mess.str().c_str(), &ch, NULL, NULL, TO_CHAR); mess.str(""); mess << "With a blast of heat and flame, $n renders down " << objList << " into a liquid mass of metal."; act(mess.str().c_str(), &ch, NULL, NULL, TO_ROOM); // Destroy the objects for (size_t i(0); i < baseObjects.size(); ++i) extract_obj(baseObjects[i]); // Set up the echo affect callbacks struct CallbackHandler { static bool HandleMove(CHAR_DATA * ch, ROOM_INDEX_DATA *, EchoAffect *, void * tag) { HandleCancel(ch, tag); return true; } static bool HandlePositionChange(CHAR_DATA * ch, int newPos, EchoAffect *, void * tag) { HandleCancel(ch, tag); return true; } static bool HandleCast(CHAR_DATA * ch, int, int, void *, int, EchoAffect *, void * tag) { HandleCancel(ch, tag); return true; } static bool CheckFailure(CHAR_DATA * ch, EchoAffect *, void * tag) { // Check for skill ForgeContext * context(static_cast<ForgeContext*>(tag)); if (number_percent() <= context->skill) { check_improve(ch, NULL, gsn_forgeweapon, true, 6); return false; } // Failed; increase the flaw count ++context->flaws; if (number_percent() <= context->flaws * 25) { // Fatal error act("You lose focus on your work, destroying it completely!", ch, NULL, NULL, TO_CHAR); act("$n loses focus on $s work, destroying it completely!", ch, NULL, NULL, TO_ROOM); check_improve(ch, NULL, gsn_forgeweapon, false, 6); delete context; return true; } // Non-fatal error act("You make a small error while folding the metal, introducing a slight flaw into the weapon.", ch, NULL, NULL, TO_CHAR); check_improve(ch, NULL, gsn_forgeweapon, false, 6); return false; } static bool Finish(CHAR_DATA * ch, EchoAffect *, void * tag) { std::auto_ptr<ForgeContext> context(static_cast<ForgeContext*>(tag)); CompleteWeapon(*ch, *context); return false; } private: static void HandleCancel(CHAR_DATA * ch, void * tag) { std::auto_ptr<ForgeContext> context(static_cast<ForgeContext*>(tag)); send_to_char("You abandon your efforts at the forge, letting the partially-worked metal run away to uselessness.\n", ch); act("$n abandons $s efforts at the forge, allowing the partially-worked metal to run away uselessly.", ch, NULL, NULL, TO_ROOM); } }; // Prepare the echoAffect EchoAffect * echoAff(new EchoAffect(1)); echoAff->SetPositionCallback(&CallbackHandler::HandlePositionChange); echoAff->SetMoveCallback(&CallbackHandler::HandleMove); echoAff->SetCastCallback(&CallbackHandler::HandleCast); // Add in lines echoAff->AddLine(&CallbackHandler::CheckFailure, "Working the mass carefully, you begin to shape the metal.", "Working the mass carefully, $n begins to shape the metal."); mess.str(""); mess << "As you fold the metal over itself time and again, it starts to take on the distinctive shape of a "; mess << context->weaponInfo->name << "."; std::ostringstream omess; omess << "As $n folds the metal over itself time and again, it starts to take on the distinctive shape of a "; omess << context->weaponInfo->name << "."; echoAff->AddLine(&CallbackHandler::CheckFailure, mess.str().c_str(), omess.str().c_str()); echoAff->AddLine(&CallbackHandler::CheckFailure, "Molding the weapon with magic and skill, you bring your work near completion.", "Molding the weapon with magic and skill, $n brings $s work near completion."); echoAff->AddLine(&CallbackHandler::Finish, ""); // Finish applying the effect echoAff->SetTag(context.release()); EchoAffect::ApplyToChar(&ch, echoAff); // Apply a cooldown AFFECT_DATA af = {0}; af.where = TO_AFFECTS; af.type = gsn_forgeweapon; af.location = APPLY_NONE; af.duration = 60; af.level = ch.level; affect_to_char(&ch, &af); // Charge mana and lag expend_mana(&ch, manaCost); WAIT_STATE(&ch, skill_table[gsn_forgeweapon].beats); }
void do_pipe ( CHAR_DATA *ch, char *argument ) { OBJ_DATA * pObj; OBJ_DATA * qObj; char *pipe_name; char pipe_name_2[MAX_INPUT_LENGTH]; int amount, range, weed_amount, weed_type, dex, wis, con; AFFECT_DATA *old_smoke, *old_poison; AFFECT_DATA new_smoke, poison; int dur = 1, old_dur = 0, old_level = 0, level = 1; char buf[ MAX_INPUT_LENGTH ]; char arg1[ MAX_INPUT_LENGTH ]; char arg2[ MAX_INPUT_LENGTH ]; char arg3[ MAX_INPUT_LENGTH ]; char arg4[ MAX_INPUT_LENGTH ]; // mobom dziêkujemy bez komunikatu if ( IS_NPC( ch ) ) { return ; } // w czasie walki dziêkujemy z komunikatem if ( ch->position == POS_FIGHTING || ch->fighting != NULL ) { send_to_char( "Lepiej skup siê na walce.\n\r", ch ); return; } argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); argument = one_argument( argument, arg3 ); argument = one_argument( argument, arg4 ); pObj = get_obj_carry( ch, arg2, ch ); if ( arg1[ 0 ] == '\0' ) { send_to_char( "Co takiego chcesz zrobiæ z fajk±?\n\r", ch ); send_to_char( "{R[PORADA]:{y 'Je¿eli nie wiesz, co mo¿esz, wpisz {Rhelp pipe{x / {Cpomoc fajka{x.{Y'{x\n\r", ch ); return; } if ( !str_prefix( arg1, "smoke" ) || !str_prefix( arg1, "pal" )) { if ( arg2[ 0 ] == '\0' ) { send_to_char( "Paliæ co?\n\r", ch ); return ; } // je¿eli obiekt nieistnieje w inventory, to mo¿e kto¶ co¶ takiego trzyma if ( pObj == NULL ) pObj = get_eq_char( ch, WEAR_HOLD ); if ( pObj == NULL ) { send_to_char( "Potrzebujesz fajki ¿eby paliæ ziele fajkowe.\n\r", ch ); return ; } /*if ( ( pObj = get_obj_carry( ch, arg2, ch ) ) == NULL ) { send_to_char( "Potrzebujesz fajki ¿eby paliæ ziele fajkowe.\n\r", ch ); return ; }*/ if ( pObj->item_type != ITEM_PIPE ) { send_to_char( "Potrzebujesz fajki ¿eby paliæ ziele fajkowe.\n\r", ch ); return ; } /* Gdy fajka jest pusta... */ if ( pObj->value[ 1 ] <= 0 ) { act( "W $j nie ma niczego, co móg³by¶ paliæ! Jest pusta.", ch, pObj, NULL, TO_CHAR ); act( "$n spogl±da z dziwnym smutkiem na $h.", ch, pObj, NULL, TO_ROOM ); return ; } /* Gdy fajka jest zgaszona*/ if ( pObj->value[ 0 ] == 0 ) { act( "Przecie¿ $p jest zgaszona!", ch, pObj, NULL, TO_CHAR ); return ; } /* Flaga informujaca o tym, ze gracz sobie pociagnal dymka... */ if ( !EXT_IS_SET( ch->act, PLR_SMOKED ) ) EXT_SET_BIT( ch->act, PLR_SMOKED ); if ( is_affected( ch, gsn_on_smoke ) ) { old_smoke = affect_find( ch->affected, gsn_on_smoke ); old_dur = old_smoke->duration; old_level = old_smoke->level; affect_strip( ch, gsn_on_smoke ); } level = weed_table[ pObj->value[2] ].weed_affect[0]; dur += old_dur; level += old_level; new_smoke.where = TO_AFFECTS; new_smoke.type = gsn_on_smoke; new_smoke.level = level; new_smoke.duration = UMIN( dur, number_range( 5, 7 ) ); new_smoke.rt_duration = 0; new_smoke.location = APPLY_NONE; new_smoke.modifier = 0; new_smoke.bitvector = &AFF_NONE; if ( level > number_range( 5, 7 ) && weed_table[ pObj->value[2] ].weed_affect[0] && number_percent() < weed_table[ pObj->value[2] ].weed_affect[1] ) { send_to_char( "\n\rZaczynasz czuæ siê jako¶ dziwnie. Przed oczyma zaczynaj± lataæ ci kolorowe plamki.\n\r", ch ); act( "\n\r$n zaczyna wygl±dajaæ jako¶ dziwnie blado.", ch, pObj, NULL, TO_ROOM ); if ( dice( 1, 2 ) == 1 ) new_smoke.bitvector = &AFF_HALLUCINATIONS_NEGATIVE; else new_smoke.bitvector = &AFF_HALLUCINATIONS_POSITIVE; } new_smoke.visible = FALSE; affect_to_char( ch, &new_smoke, NULL, FALSE ); if ( number_percent() < weed_table[ pObj->value[2] ].weed_affect[2] ) { if( is_affected(ch,gsn_poison )) { old_poison = affect_find( ch->affected, gsn_poison ); old_poison->duration += stat_throw(ch,STAT_CON) ? number_range(2,4) : number_range(4,8); if( old_poison->level < UMIN( weed_table[ pObj->value[2] ].weed_affect[0], 3) ) old_poison->level = UMIN( weed_table[ pObj->value[2] ].weed_affect[0], 3); act( "$n jeszcze bardziej zielenieje na twarzy.", ch, pObj, NULL, TO_ROOM ); send_to_char( "Czujesz siê jeszcze gorzej.\n\r", ch ); } else { poison.where = TO_AFFECTS; poison.type = gsn_poison; poison.level = UMIN( weed_table[ pObj->value[2] ].weed_affect[0], 3); poison.duration = stat_throw(ch,STAT_CON) ? number_range(2,4) : number_range(4,8); poison.rt_duration = 0; poison.location = APPLY_NONE; poison.modifier = 0; poison.bitvector = &AFF_NONE; poison.visible = FALSE; affect_to_char( ch, &poison, NULL, FALSE ); send_to_char( "Momentalnie zaczynasz czuæ siê jako¶ niedobrze. Bardzo niedobrze.\n\r", ch ); act( "$n widocznie zielenieje na twarzy.", ch, pObj, NULL, TO_ROOM ); } } /* Troche losowosci */ range = number_range( 1, 9 ); switch ( range ) { case 1: act( "$n zaci±ga siê g³êboko $j.", ch, pObj, NULL, TO_ROOM ); act( "Zaci±gasz siê g³êboko $j.", ch, pObj, NULL, TO_CHAR ); break; case 2: act( "$n pyka sobie $h przez chwilê.", ch, pObj, NULL, TO_ROOM ); act( "Pykasz sobie $h przez chwilê.", ch, pObj, NULL, TO_CHAR ); break; case 3: act( "$n wci±ga gwa³townie dym z $f.", ch, pObj, NULL, TO_ROOM ); act( "Wci±gasz gwa³townie dym z $f.", ch, pObj, NULL, TO_CHAR ); break; case 4: act( "$n zaci±ga siê delikatnie $j.", ch, pObj, NULL, TO_ROOM ); act( "Zaci±gasz siê delikatnie $j.", ch, pObj, NULL, TO_CHAR ); break; case 5: act( "Widzisz jak $n zaci±ga siê lekko $j.", ch, pObj, NULL, TO_ROOM ); act( "Zaci±gasz siê lekko $j.", ch, pObj, NULL, TO_CHAR ); break; case 6: act( "Dostrzegasz, jak $n z wpraw± zaci±ga siê dymkiem z $f.", ch, pObj, NULL, TO_ROOM ); act( "Z wielk± wpraw± zaci±gasz siê dymkiem z $f.", ch, pObj, NULL, TO_CHAR ); break; case 7: act( "$n jakby od niechcenia pali przez chwilê swoj± $h.", ch, pObj, NULL, TO_ROOM ); act( "Przez chwilkê machinalnie palisz sobie swoj± $h.", ch, pObj, NULL, TO_CHAR ); break; case 8: act( "$n z u¶miechem kurzy sobie $h.", ch, pObj, NULL, TO_ROOM ); act( "Kurzysz sobiê $h, u¶miechaj±c siê przy tym b³ogo.", ch, pObj, NULL, TO_CHAR ); break; default: act( "$n pali sobie przez chwilkê $h.", ch, pObj, NULL, TO_ROOM ); act( "Palisz sobie przez chwilkê $h.", ch, pObj, NULL, TO_CHAR ); break; } amount = number_range( 1, 3 ); // moze sie palic szybciej, lub wolniej (o 1, 2 lub o 3) if ( pObj->value[ 0 ] == 1 ) // sprawdzamy czy fajeczka jest zapalona { pObj->value[ 1 ] -= amount; // wypalamy zawartosc fajeczki //pObj->short_descr = capitalize(pObj->short_descr ); amount = number_range( 1, 7 ); switch ( amount ) { case 1: act( "Nad $j trzyman± przez $z unosi siê w±ska stru¿ka dymu.", ch, pObj, NULL, TO_ROOM ); act( "Nad $j unosi siê w±ska stru¿ka dymu.", ch, pObj, NULL, TO_CHAR ); break; case 2: act( "Nad $j $z unosz± siê ma³e, ciemne chmurki dymu.", ch, pObj, NULL, TO_ROOM ); act( "Nad $j unosz± siê ma³e, ciemne chmurki dymu.", ch, pObj, NULL, TO_CHAR ); break; case 3: act( "Widzisz jak w $f $z tl± siê ma³e, jasne iskierki.", ch, pObj, NULL, TO_ROOM ); act( "Widzisz kilka ma³ych, jasnych iskierek tl±cych siê w $k.", ch, pObj, NULL, TO_CHAR ); break; case 4: act( "Dostrzegasz, ¿e nad $f trzyman± przez $z unosi siê gêsta smuga dymu.", ch, pObj, NULL, TO_ROOM ); act( "Dosrzegasz unosz±c± siê nad $f gêst± smugê dymu.", ch, pObj, NULL, TO_CHAR ); break; case 5: act( "S³yszysz jak zawarto¶æ $f $z lekko syczy tl±c siê.", ch, pObj, NULL, TO_ROOM ); act( "S³yszysz jak zawarto¶æ $f lekko syczy tl±c siê.", ch, pObj, NULL, TO_CHAR ); break; case 6: act( "Czujesz delikatny aromat jakoby zio³owego dymu, bij±cy od $z i jego $f.", ch, pObj, NULL, TO_ROOM ); act( "Czujesz bij±cy od $f lekki, jakby zio³owy aromat.", ch, pObj, NULL, TO_CHAR ); break; default: act( "Zawarto¶æ $f nale¿±cej do $z tli siê lekko.", ch, pObj, NULL, TO_ROOM ); act( "Zawarto¶æ $f tli siê lekko.", ch, pObj, NULL, TO_CHAR ); break; } if ( pObj->value[ 1 ] <= 0 ) { act( "Ostatnie, tl±ce siê iskierki gasn±, kiedy wypali³a siê ca³a zawarto¶æ $f.", ch, pObj, NULL, TO_CHAR ); act( "Widzisz jak $p $z ga¶nie z lekkim sykiem.", ch, pObj, NULL, TO_ROOM ); pObj->value[ 0 ] = 0; pObj->value[ 1 ] = 0; pObj->value [ 2 ] = 0; } } return ; } if ( !str_prefix( arg1, "exhale" ) || !str_prefix( arg1, "wydech" )) { // Potrzebne staty do testow na 'triki'... dex = get_curr_stat_deprecated(ch,STAT_DEX); con = get_curr_stat_deprecated(ch,STAT_CON); wis = get_curr_stat_deprecated(ch,STAT_WIS); /* Zeby "wydychac" flaga palenia musi byc nalozona na gracza - sprawdzanie */ if ( !EXT_IS_SET( ch->act, PLR_SMOKED ) ) { send_to_char( "Jak chcesz to zrobiæ? Najpierw musisz zaci±gn±æ siê dymem!\n\r", ch ); return ; } /* Pomocy! if ( !str_prefix( arg2, "help" ) || !str_prefix( arg2, "pomoc" )) { act( "{R[PORADA]:{x\n\r", ch, NULL, NULL, TO_CHAR ); act( "{YZanim bêdziesz <&móg³/mog³a/mog³o> wydychaæ dym musisz paliæ fajkê.{x", ch, NULL, NULL, TO_CHAR ); act( "{YPo tym jak skoñczysz rozkoszowaæ siê bogatym smakiem ziela fajkowego...{x", ch, NULL, NULL, TO_CHAR ); act( "{YMo¿esz wydychaæ tytoniowy dym na ró¿ne sposoby, ¿eby uatrakcyjniæ palenie.{x", ch, NULL, NULL, TO_CHAR ); act( "{YSpróbuj tych oto typów wydechu, aby zadziwiæ znajomych:{x \n\r", ch, NULL, NULL, TO_CHAR ); act( "Angielskie komendy: RINGS, LINES, SPHERE, WEB, PHOENIX, HORNS, NAME", ch, NULL, NULL, TO_CHAR ); act( "Polskie komendy: KO£A, LINIE, KULA, SIEÆ, FENIKS, ROGI, IMIÊ\n\r", ch, NULL, NULL, TO_CHAR ); act( "\n\r{YSk³adnia angielska: {Gpipe exhale <nazwa figury>{x.", ch, NULL, NULL, TO_CHAR ); act( "{YSk³adnia polska: {Gfajka wydech <nazwa figury>{x.\n\r", ch, NULL, NULL, TO_CHAR ); return ; }*/ if ( arg2[ 0 ] == '\0' ) { switch ( number_range ( 1, 5 ) ) { case 1: act( "$n wydycha ustami ob³ok bladego, szarego dymu.", ch, NULL, NULL, TO_ROOM ); act( "Wydychasz ustami ob³ok szarego, bladego dymu.", ch, NULL, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); return ; case 2: act( "$n wydycha nosem ob³ok bladego, szarego dymu.", ch, NULL, NULL, TO_ROOM ); act( "Wydychasz nosem ob³ok szarego, bladego dymu.", ch, NULL, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); return ; case 3: act( "$n spokojnie wydycha ustami ob³ok bladego, szarego dymu.", ch, NULL, NULL, TO_ROOM ); act( "Spokojnie wydychasz ustami ob³ok szarego, bladego dymu.", ch, NULL, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); return ; case 4: act( "$n spokojnie wydycha nosem ob³ok bladego, szarego dymu.", ch, NULL, NULL, TO_ROOM ); act( "Spokojnie wydychasz nosem ob³ok szarego, bladego dymu.", ch, NULL, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); return ; default: act( "$n wydycha ob³ok bladego, szarego dymu.", ch, NULL, NULL, TO_ROOM ); act( "Wydychasz ob³ok szarego, bladego dymu.", ch, NULL, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); return ; } } else if ( !str_prefix( arg2, "ko³a" ) || !str_prefix( arg2, "rings" ) ) { if ( dice( 2, dex - 10 ) >= 4 && dice( 2, con - 6 ) > 6 ) { act( "$n niespodziewanie wypuszcza z ust kilka du¿ych, zadziwiaj±co okr±g³ych kó³ z dymu, które uk³adaj± siê w ¶mieszny tunel zawieszony w powietrzu!", ch, NULL, NULL, TO_ROOM ); act( "Wypuszczasz z ust kilka du¿ych, zadziwiaj±co okr±g³ych kó³ z dymu, które uk³adaj± siê w ¶mieszny tunel zawieszony w powietrzu!", ch, NULL, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); return ; } else { switch ( number_range ( 1, 4 ) ) { case 1: act( "$n nagle robi dziwn± minê, po czym momentalnie dostaje ataku kaszlu.", ch, pObj, NULL, TO_ROOM ); act( "Próbujesz zrobiæ sztuczkê, jednak w ostatniej chwili dym zacz±³ gry¼æ ciê w gar³o i <&dosta³e¶/dosta³a¶/dosta³o¶> ataku kaszlu!", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 2: act( "Widzisz jak $n koncentruje siê przez chwilkê, aby po chwili wypu¶ciæ z ust niekszta³tn± chmurê dymu.", ch, pObj, NULL, TO_ROOM ); act( "Koncentrujesz siê przez chwilkê, chc±c wypu¶ciæ z ust chmurê dymu w kszta³cie ko³a, jednak nie udaje ci siê to.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 3: act( "$n nagle zielenieje na twarzy, a z jego nosa zaczynaj± wylatywaæ szare stru¿ki dymu.", ch, pObj, NULL, TO_ROOM ); act( "W ostatniej chwili przygotowañ do zrobienia sztuczki krztusisz siê i bezwiednie wypuszczasz dym nosem.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; default: EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); act( "$n próbuje zrobiæ jak±¶ sztuczkê z wypuszczeniem z ust dymu, jednak udaje mu siê jedynie uformowaæ dym w bezkszta³tn± chmurê.", ch, pObj, NULL, TO_ROOM ); act( "Starasz siê wypu¶ciæ z ust kilka kszta³tnych kó³, jednak nie udaje ci siê, a dym przybiera kszta³t nieforemnej chmury.", ch, pObj, NULL, TO_CHAR ); break; } } } else if ( !str_prefix( arg2, "linie" ) || !str_prefix( arg2, "lines" )) { if ( dice( 2, dex - 10 ) > 5 && dice( 2, con - 8 ) >= 5 ) { act( "$n wydycha d³ug± smugê dymu w kszta³cie piêknej, prostej linii, zdaj±c± siê pi±æ w kierunku nieba!", ch, NULL, NULL, TO_ROOM ); act( "Wydychasz d³ug± smugê dymu w kszta³cie piêknej, prostej linii, zdaj±c± siê pi±æ w kierunku nieba!", ch, NULL, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); return ; } else { switch ( number_range ( 1, 5 ) ) { case 1: act( "$n nagle robi dziwn± minê, po czym momentalnie dostaje ataku kaszlu.", ch, pObj, NULL, TO_ROOM ); act( "Próbujesz zrobiæ sztuczkê, jednak w ostatniej chwili dym zacz±³ gry¼æ ciê w gar³o i <&dosta³e¶/dosta³a¶/dosta³o¶> ataku kaszlu!", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 2: act( "Widzisz jak $n koncentruje siê przez chwilkê, aby po chwili wypu¶ciæ z ust niekszta³tn± chmurê dymu.", ch, pObj, NULL, TO_ROOM ); act( "Koncentrujesz siê przez chwilkê, chc±c wypu¶ciæ z ust chmurê dymu w kszta³cie linii, jednak nie udaje ci siê to.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 3: act( "$n nagle zielenieje na twarzy, a z jego nosa zaczynaj± wylatywaæ szare stru¿ki dymu.", ch, pObj, NULL, TO_ROOM ); act( "W ostatniej chwili przygotowañ do zrobienia sztuczki krztusisz siê i bezwiednie wypuszczasz dym nosem.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 4: act( "$n z gracj± zaczyna wypuszczaæ z ust kilka chmurek dymu, które niespodziewanie szybko rozp³ywaj± siê w powietrzu.", ch, pObj, NULL, TO_ROOM ); act( "W skupieniu wypuszczasz z ust kilka chmurek dymu, te jednak rozp³ywaj± siê szybko w powietrzu zanim zd±zy³y siê uformowaæ w jaki¶ kszta³t.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; default: act( "$n próbuje zrobiæ jak±¶ sztuczkê z wypuszczeniem z ust dymu, jednak udaje mu siê jedynie uformowaæ dym w bezkszta³tn± chmurê.", ch, pObj, NULL, TO_ROOM ); act( "Starasz siê wypu¶ciæ z ust prost± liniê dymu, jednak nie udaje ci siê, a dym przybiera kszta³t nieforemnej chmury.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; } } } else if ( !str_prefix( arg2, "kula" ) || !str_prefix( arg2, "sphere" )) { if ( dice( 2, dex - 5 ) >= 7 && dice( 3, con - 2 ) > 15 ) { act( "$n wypuszcza z ust jedn±, niesamowicie okr±g³a, chmurê dymu w kszta³cie idealnej kuli!", ch, NULL, NULL, TO_ROOM ); act( "Wypuszczasz z ust du¿±, niesamowicie okr±g³±, chmurê dymu w kszta³cie idealnej kuli!", ch, NULL, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); return ; } else { switch ( number_range ( 1, 5 ) ) { case 1: act( "$n nagle robi dziwn± minê, po czym momentalnie dostaje ataku kaszlu.", ch, pObj, NULL, TO_ROOM ); act( "Próbujesz zrobiæ sztuczkê, jednak w ostatniej chwili dym zacz±³ gry¼æ ciê w gar³o i <&dosta³e¶/dosta³a¶/dosta³o¶> ataku kaszlu!", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 2: act( "Widzisz jak $n koncentruje siê przez chwilkê, aby po chwili wypu¶ciæ z ust niekszta³tn± chmurê dymu.", ch, pObj, NULL, TO_ROOM ); act( "Koncentrujesz siê przez chwilkê, chc±c wypu¶ciæ z ust chmurê dymu w kszta³cie kuli, jednak nie udaje ci siê to.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 3: act( "$n nagle zielenieje na twarzy, a z jego nosa zaczynaj± wylatywaæ szare stru¿ki dymu.", ch, pObj, NULL, TO_ROOM ); act( "W ostatniej chwili przygotowañ do zrobienia sztuczki krztusisz siê i bezwiednie wypuszczasz dym nosem.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 4: act( "$n nagle zaczyna kaszlaæ dymem, a dym który ulatuje z jego ust tworzy dziwn± chmurkê.", ch, pObj, NULL, TO_ROOM ); act( "Niespodziewanie co¶ ci nie wychodzi, krztusisz siê i kaszlaj±c panicznie wypuszczasz z ust resztki dymu.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; default: act( "$n próbuje zrobiæ jak±¶ sztuczkê z wypuszczeniem z ust dymu, jednak udaje mu siê jedynie uformowaæ dym w bezkszta³tn± chmurê.", ch, pObj, NULL, TO_ROOM ); act( "Starasz siê wypu¶ciæ z ust kulê dymu, jednak nie udaje ci siê, a dym przybiera kszta³t nieforemnej chmury.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; } } } else if ( !str_prefix( arg2, "sieæ" ) || !str_prefix( arg2, "web" )) { if ( dice( 2, dex - 5 ) >= 15 && dice( 2, con - 8 ) > 6 ) { act( "$n wydycha kilkana¶cie cieniutkich, zwiewnych pasemek dymu, które niespodziewanie ³±cz± siê tworz±c delikatn±, prawie pajêcz±, sieæ w powietrzu!", ch, NULL, NULL, TO_ROOM ); act( "Wydychasz kilkana¶cie cieniutkich, zwiewnych pasemek dymu, które niespodziewanie ³±cz± siê tworz±c delikatn±, prawie pajêcz±, sieæ w powietrzu!", ch, NULL, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); return ; } else { switch ( number_range ( 1, 5 ) ) { case 1: act( "$n nagle robi dziwn± minê, po czym momentalnie dostaje ataku kaszlu.", ch, pObj, NULL, TO_ROOM ); act( "Próbujesz zrobiæ sztuczkê, jednak w ostatniej chwili dym zacz±³ gry¼æ ciê w gar³o i <&dosta³e¶/dosta³a¶/dosta³o¶> ataku kaszlu!", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 2: act( "Widzisz jak $n koncentruje siê przez chwilkê, aby po chwili wypu¶ciæ z ust niekszta³tn± chmurê dymu.", ch, pObj, NULL, TO_ROOM ); act( "Koncentrujesz siê przez chwilkê, chc±c wypu¶ciæ z ust chmurê dymu w kszta³cie kuli, jednak nie udaje ci siê to.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 3: act( "$n nagle zielenieje na twarzy, a z jego nosa zaczynaj± wylatywaæ szare stru¿ki dymu.", ch, pObj, NULL, TO_ROOM ); act( "W ostatniej chwili przygotowañ do zrobienia sztuczki krztusisz siê i bezwiednie wypuszczasz dym nosem.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 4: act( "$n wydycha szybk± seriê w±skich dymków, które wydaj± siê pe³zaæ w powietrzu jak niepos³usze robaczki, szybko rozp³ywaj±ce siê w powietrzu.", ch, pObj, NULL, TO_ROOM ); act( "Szybko wydychasz seriê w±skich dymków chc±c z nich uformowaæ pajêczynê, te jednak szybko rozp³ywaj± siê w powietrzu.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; default: act( "$n próbuje zrobiæ jak±¶ sztuczkê z wypuszczeniem z ust dymu, jednak udaje mu siê jedynie uformowaæ dym w bezkszta³tn± chmurê.", ch, pObj, NULL, TO_ROOM ); act( "Starasz siê wypu¶ciæ z ust seriê dymków, jednak nie udaje ci siê, a sam dym przybiera kszta³t nieforemnej chmury.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; } } } else if ( !str_prefix( arg2, "feniks" ) || !str_prefix( arg2, "phoenix" ) || !str_prefix( arg2, "fenix" ) ) { if ( dice( 2, dex - 10 ) >= 8 && dice( 2, con - 10 ) >= 8 && dice( 2, wis - 10 ) >= 5 ) { act( "$n wydycha serie ma³ych chmurek dymu, które na chwilê uk³adaj± siê w wizerunek feniksa, tylko po to, aby chwilê pó¼niej rozp³ynê³y siê, niczym proch.", ch, NULL, NULL, TO_ROOM ); act( "Wydychasz serie ma³ych chmurek dymu, które na chwilê uk³adaj± siê w wizerunek feniksa, tylko po to, aby chwilê pó¼niej rozp³ynê³y siê, niczym proch.", ch, NULL, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); return ; } else { switch ( number_range ( 1, 7 ) ) { case 1: act( "$n nagle robi dziwn± minê, po czym momentalnie dostaje ataku kaszlu.", ch, pObj, NULL, TO_ROOM ); act( "Próbujesz zrobiæ sztuczkê, jednak w ostatniej chwili dym zacz±³ gry¼æ ciê w gar³o i <&dosta³e¶/dosta³a¶/dosta³o¶> ataku kaszlu!", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 2: act( "Widzisz jak $n koncentruje siê przez chwilkê, aby po chwili wypu¶ciæ z ust niekszta³tn± chmurê dymu.", ch, pObj, NULL, TO_ROOM ); act( "Koncentrujesz siê przez chwilkê, chc±c wypu¶ciæ z ust chmurê dymu w kszta³cie linii, jednak nie udaje ci siê to.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 3: act( "$n nagle zielenieje na twarzy, a z jego nosa zaczynaj± wylatywaæ szare stru¿ki dymu.", ch, pObj, NULL, TO_ROOM ); act( "W ostatniej chwili przygotowañ do zrobienia sztuczki krztusisz siê i bezwiednie wypuszczasz dym nosem.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 4: act( "$n w wielkim skupieniu wydycha kilkana¶cie dymków, które zaczynaj± uk³adaæ siê w powietrzu w co¶ przypominaj±cego hybrydê szczura z ludzkimi nogami... Czy to by³o zamierzone?", ch, pObj, NULL, TO_ROOM ); act( "W wielkim skupieniu wydychasz kilkana¶cie dymków, które niespodziewanie zamiast feniksa uk³adaj± siê w co¶ przypominaj±cego po³±czenie szczura z ludzkimi nogami! Okropne.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 5: act( "$n, z grymasem na twarzy, wypuszcza z ust kilkana¶cie dymków, które uk³adaj± siê w powietrzu w jaki¶ dziwny ptakopodobny twór, wygl±daj±cy dosyæ ohydnie.", ch, pObj, NULL, TO_ROOM ); act( "Czuj±c, ¿e co¶ pójdzie ¼le wypuszczasz z ust kilkana¶cie dymków, które uk³adaj± siê w powietrzu w jaki¶ bezkszta³tny, ptakopodobny twór.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 6: act( "$n, z wyrazem pewno¶ci siebie na twarzy, wydycha seriê ma³ych dymków, które nagle ³±cz± siê w powietrzu tworz±c pewien du¿y, oble¶ny kszta³t... Hmm, to ciekawe. K±tem oka widzisz, ¿e $n siê rumieni na widok swojego dzie³a.", ch, pObj, NULL, TO_ROOM ); act( "Wypuszczasz z ust kilkana¶cie ma³ych dymków, które nagle ³±cz± siê w powietrzu, tworz±c naprawdê du¿y, oble¶ny kszta³t. Chyba siê zaraz spalisz ze wstydu!", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; default: act( "$n próbuje zrobiæ jak±¶ sztuczkê z wypuszczeniem z ust dymu, jednak udaje mu siê jedynie uformowaæ dym w bezkszta³tn± chmurê.", ch, pObj, NULL, TO_ROOM ); act( "Starasz siê wypu¶ciæ z ust kilkana¶cie dymków, jednak nie udaje ci siê, a sam dym przybiera kszta³t nieforemnej chmury.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; } } } else if ( !str_prefix( arg2, "rogi" ) || !str_prefix( arg2, "horns" )) { if ( dice( 2, dex - 10 ) >= 9 && dice( 2, con - 6 ) >= 10 ) { act( "$n wydycha dwie grube smugi dymu, które uk³adaj± siê nad $m niczym para wielkich rogów!", ch, NULL, NULL, TO_ROOM ); act( "Wydychasz dwie grube smugi dymu, które uk³adaj± sie nad tob± niczym para wielkich rogów!", ch, NULL, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); return ; } else { switch ( number_range ( 1, 4 ) ) { case 1: act( "$n nagle robi dziwn± minê, po czym momentalnie dostaje ataku kaszlu.", ch, pObj, NULL, TO_ROOM ); act( "Próbujesz zrobiæ sztuczkê, jednak w ostatniej chwili dym zacz±³ gry¼æ ciê w gar³o i <&dosta³e¶/dosta³a¶/dosta³o¶> ataku kaszlu!", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 2: act( "Widzisz jak $n koncentruje siê przez chwilkê, aby po chwili wypu¶ciæ z ust niekszta³tn± chmurê dymu.", ch, pObj, NULL, TO_ROOM ); act( "Koncentrujesz siê przez chwilkê, chc±c wypu¶ciæ z ust chmurê dymu w kszta³cie linii, jednak nie udaje ci siê to.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 3: act( "$n nagle zielenieje na twarzy, a z jego nosa zaczynaj± wylatywaæ szare stru¿ki dymu.", ch, pObj, NULL, TO_ROOM ); act( "W ostatniej chwili przygotowañ do zrobienia sztuczki krztusisz siê i bezwiednie wypuszczasz dym nosem.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; default: act( "$n próbuje zrobiæ jak±¶ sztuczkê z wypuszczeniem z ust dymu, jednak udaje mu siê jedynie uformowaæ dym w bezkszta³tn± chmurê.", ch, pObj, NULL, TO_ROOM ); act( "Starasz siê wypu¶ciæ z ust prost± liniê dymu, jednak nie udaje ci siê, a dym przybiera kszta³t nieforemnej chmury.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; } } } else if ( !str_prefix( arg2, "imiê" ) || !str_prefix( arg2, "name" )) { if ( dice( 2, dex - 10 ) >= 8 && dice( 2, con - 8 ) >= 9 && dice( 2, wis - 10 ) > 6 ) { act( "$n wypuszcza z ust kilkana¶cie ma³ych dymków, które niespodziewanie tworz± w powietrzu napis '$n'! Niesamowite!", ch, NULL, NULL, TO_ROOM ); act( "Wypuszczasz z ust kilkana¶cie ma³ych dymków, które niespodziewanie tworz± w powietrzu napis '$n'! ¦wietnie!", ch, NULL, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); return ; } else { switch ( number_range ( 1, 6 ) ) { case 1: act( "$n nagle robi dziwn± minê, po czym momentalnie dostaje ataku kaszlu.", ch, pObj, NULL, TO_ROOM ); act( "Próbujesz zrobiæ sztuczkê, jednak w ostatniej chwili dym zacz±³ gry¼æ ciê w gar³o i <&dosta³e¶/dosta³a¶/dosta³o¶> ataku kaszlu!", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 2: act( "Widzisz jak $n koncentruje siê przez chwilkê, aby po chwili wypu¶ciæ z ust niekszta³tn± chmurê dymu.", ch, pObj, NULL, TO_ROOM ); act( "Koncentrujesz siê przez chwilkê, chc±c wypu¶ciæ z ust chmurê dymu w kszta³cie linii, jednak nie udaje ci siê to.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 3: act( "$n nagle zielenieje na twarzy, a z jego nosa zaczynaj± wylatywaæ szare stru¿ki dymu.", ch, pObj, NULL, TO_ROOM ); act( "W ostatniej chwili przygotowañ do zrobienia sztuczki krztusisz siê i bezwiednie wypuszczasz dym nosem.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 4: act( "$n, z wyrazem pewno¶ci siebie na twarzy, wydycha seriê ma³ych dymków, które nagle ³±cz± siê w powietrzu tworz±c pewien du¿y, oble¶ny kszta³t... Hmm, to ciekawe. K±tem oka widzisz, ¿e $n siê rumieni na widok swojego dzie³a.", ch, pObj, NULL, TO_ROOM ); act( "Wypuszczasz z ust kilkana¶cie ma³ych dymków, które nagle ³±cz± siê w powietrzu, tworz±c naprawdê du¿y, oble¶ny kszta³t. Chyba siê zaraz spalisz ze wstydu!", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; case 5: print_char( ch, "Wydychasz w wielkim skupieniu kilkana¶cie szarych dymków, które niespodziewanie tworz± w powietrzu bezsensowny napis '%s'!", gen_random_str( 4, 8 ) ); sprintf( buf, "$n wydycha w wielkim skupieniu kilkana¶cie szarych dymków, które niespodziewanie tworz± w powietrzu bezsensowny napis '%s'!\n\r", gen_random_str( 4, 8 ) ); act( buf, ch, NULL, NULL, TO_ROOM ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; default: act( "$n próbuje zrobiæ jak±¶ sztuczkê z wypuszczeniem z ust dymu, jednak udaje mu siê jedynie uformowaæ dym w bezkszta³tn± chmurê.", ch, pObj, NULL, TO_ROOM ); act( "Starasz siê wypu¶ciæ z ust kilka dziwnych chmurek dymu, jednak nie udaje ci siê, a dym przybiera kszta³t nieforemnej chmury.", ch, pObj, NULL, TO_CHAR ); EXT_REMOVE_BIT( ch->act, PLR_SMOKED ); break; } } } else { send_to_char( "Huh?! Nie znasz takiej sztuczki!\n\r", ch ); return; } } // Nabijanie fajki if ( !str_prefix( arg1, "tamp" ) || !str_prefix( arg1, "nabij" )) { // Seria zabezpieczen... if ( pObj == NULL ) pObj = get_eq_char( ch, WEAR_HOLD ); if ( pObj == NULL ) { act( "Co chcesz nabiæ?", ch, pObj, NULL, TO_CHAR ); return ; } if ( pObj->item_type != ITEM_PIPE ) { send_to_char( "Mo¿esz nabijaæ jedynie fajki!\n\r", ch ); return ; } if ( ( qObj = get_obj_carry( ch, arg3, ch ) ) == NULL ) { act( "Czym chcesz nabiæ $h?", ch, pObj, NULL, TO_CHAR ); return ; } if ( qObj->item_type != ITEM_WEED ) { pipe_name = capitalize( pObj->name4 ); sprintf( pipe_name_2, "%s mo¿esz nabiæ jedynie jakim¶ rodzajem ziela.", pipe_name ); act( pipe_name_2, ch, pObj, NULL, TO_CHAR ); } else if ( pObj->value[ 0 ] == 1 ) { pipe_name = capitalize( pObj->short_descr ); sprintf( pipe_name_2, "%s jest zapalona, nie mo¿esz jej teraz nabijaæ!", pipe_name ); act( pipe_name_2, ch, pObj, NULL, TO_CHAR ); return ; } else if ( pObj->value[ 1 ] > 0 ) { pipe_name = capitalize( pObj->short_descr ); sprintf( pipe_name_2, "%s jest ju¿ czym¶ nabita. Przed ponownym nabiciem opró¿nij j±.", pipe_name ); act( pipe_name_2, ch, pObj, NULL, TO_CHAR ); return ; } else { // Nabijanie fajki, przepisywanie wartosci ziela do fajeczki. weed_amount = qObj->value [ 0 ]; weed_type = qObj->value [ 1 ]; pObj->value [ 1 ] = weed_amount; pObj->value [ 2 ] = weed_type; print_char( ch, "Nabijasz %s %s.\n\r", pObj->name4, qObj->name5 ); sprintf( buf, "$n nabija %s %s.\n\r", pObj->name4, qObj->name5 ); act( buf, ch, NULL, NULL, TO_ROOM ); extract_obj( qObj ); return ; } } // zapalanie if ( !str_prefix( arg1, "light" ) || !str_prefix( arg1, "zapal" )) { pObj = get_obj_carry( ch, arg2, ch ); if ( pObj == NULL ) pObj = get_eq_char( ch, WEAR_HOLD ); if ( pObj == NULL ) { act( "Co chcesz zapaliæ?", ch, pObj, NULL, TO_CHAR ); return ; } if ( pObj->item_type != ITEM_PIPE ) { send_to_char( "Mo¿esz zapalaæ jedynie fajki!\n\r", ch ); return ; } else if ( pObj->value[ 0 ] == 1 ) { pipe_name = capitalize( pObj->short_descr ); sprintf( pipe_name_2, "%s jest ju¿ zapalona.", pipe_name ); act( pipe_name_2, ch, pObj, NULL, TO_CHAR ); return ; } else if ( pObj->value[ 2 ] == 4 ) { act( "Zawarto¶æ $f jest mokra! Nie dasz rady tego zapaliæ.", ch, pObj, NULL, TO_CHAR ); act( "Lepiej wyczy¶æ $h i nape³nij j± czym¶ suchym, najlepiej zielem fajkowym.", ch, pObj, NULL, TO_CHAR ); return ; } else { pObj->value [ 0 ] = 1; act( "Zapalaj±c $h zaczynasz czuæ przyjemny, delikatny zapach palonego ziela.", ch, pObj, NULL, TO_CHAR ); act( "$n zapala $h. Czujesz jak w powietrzu zaczyna unosiæ siê lekki zapach palonego ziela.", ch, pObj, NULL, TO_ROOM ); return ; } } // gaszenie if ( !str_prefix( arg1, "extinguish" ) || !str_prefix( arg1, "zga¶" )) { /*if ( ( pObj = get_obj_carry( ch, arg2, ch ) ) == NULL ) { act( "Co chcesz zgasiæ?", ch, pObj, NULL, TO_CHAR ); return ; }*/ if ( pObj == NULL ) pObj = get_eq_char( ch, WEAR_HOLD ); if ( pObj == NULL ) { act( "Co chcesz zgasiæ?", ch, pObj, NULL, TO_CHAR ); return ; } if ( pObj->item_type != ITEM_PIPE ) { send_to_char( "Mo¿esz gasiæ jedynie fajki!\n\r", ch ); return ; } else if ( pObj->value[ 0 ] == 0 ) { pipe_name = capitalize( pObj->short_descr ); sprintf( pipe_name_2, "%s jest ju¿ zgaszona.", pipe_name ); act( pipe_name_2, ch, pObj, NULL, TO_CHAR ); return ; } else { pObj->value [ 0 ] = 0; act( "Gasz±c $h widzisz jak ostatnie iskierki ognia bledn± i znikaj±.", ch, pObj, NULL, TO_CHAR ); act( "$n gasi $h.", ch, pObj, NULL, TO_ROOM ); return ; } } // czyszczenie / opró¿nianie if ( !str_prefix( arg1, "clean" ) || !str_prefix( arg1, "wyczy¶æ" )) { /*if ( ( pObj = get_obj_carry( ch, arg2, ch ) ) == NULL ) { act( "Co chcesz wyczy¶ciæ?", ch, pObj, NULL, TO_CHAR ); return ; }*/ if ( pObj == NULL ) pObj = get_eq_char( ch, WEAR_HOLD ); if ( pObj == NULL ) { act( "Co chcesz wyczy¶ciæ?", ch, pObj, NULL, TO_CHAR ); return ; } if ( pObj->item_type != ITEM_PIPE ) { send_to_char( "Mo¿esz czy¶ciæ jedynie fajki!\n\r", ch ); return ; } else if ( pObj->value[ 0 ] == 1 ) { act( "Mo¿e lepiej najpierw zga¶ $h?", ch, pObj, NULL, TO_CHAR ); return ; } else if ( pObj->value[ 1 ] == 0 ) { act( "Ogl±dasz z dum± $h, po czym pucujesz j± dok³adnie rêkawem. Teraz jest naprawdê czysta!", ch, pObj, NULL, TO_CHAR ); act( "$n z dum± pucuje $h, u¶miechaj±c siê przy tym tajemniczo.", ch, pObj, NULL, TO_ROOM ); return ; } else { pObj->value [ 1 ] = 0; pObj->value [ 2 ] = 0; act( "Wysypujesz zawarto¶æ $f. Teraz jest pusta.", ch, pObj, NULL, TO_CHAR ); act( "$n wysypuje zawarto¶æ $f.", ch, pObj, NULL, TO_ROOM ); return ; } } send_to_char( "Huh?\n\r", ch ); return; }
void Drakes::AdjustDrake(CHAR_DATA & ch, CHAR_DATA & drake, int stoneType, const Info & info, int level, Age age) { // Set the appropriate strings const char * stoneName(material_table[stoneType].name); std::string shortDesc(BuildShortDesc(stoneName, age)); std::string longDesc(shortDesc + " is here.\n"); longDesc[0] = UPPER(longDesc[0]); setName(drake, shortDesc.c_str()); copy_string(drake.short_descr, shortDesc.c_str()); copy_string(drake.long_descr, longDesc.c_str()); copy_string(drake.description, BuildDescription(ch, stoneName, age).c_str()); // Seed any random values with ch's id srand(ch.id + 12345); // Adjust damage type and damverb drake.dam_type = info.damageType; const char * damverb("strike"); switch (info.damageType) { case DAM_BASH: switch ((rand() + stoneType) % 3) { case 0: damverb = "slam"; break; case 1: damverb = "smash"; break; case 2: damverb = "crush"; break; } break; case DAM_SLASH: switch ((rand() + stoneType) % 3) { case 0: damverb = "slice"; break; case 1: damverb = "claw"; break; case 2: damverb = "talon"; break; } break; case DAM_PIERCE: switch ((rand() + stoneType) % 2) { case 0: damverb = "bite"; break; case 1: damverb = "strike"; break; } break; } copy_string(drake.dam_verb, damverb); // Perform basic adjustments drake.level = UMAX(1, level + age); drake.damroll = (level / 10) + (age * 4); drake.hitroll = (level * 2) / 3; drake.damage[0] = (level * 2) / 3; drake.damage[1] = 4; drake.damage[2] = drake.damroll; drake.max_hit = dice(level * 4, 19) + 400 + (age * 100); // Adjust for damage and hp mods drake.damage[0] = (drake.damage[0] * (100 + info.damageMod)) / 100; drake.max_hit = (drake.max_hit * (100 + info.hpMod)) / 100; // Adjust stats for (size_t i(0); i < MAX_STATS; ++i) { drake.perm_stat[i] = 18 + age; drake.mod_stat[i] = 18 + age; drake.max_stat[i] = 18 + age; } // Fill in resistances for (size_t i(0); i < info.resistances.size(); ++i) drake.resist[info.resistances[i].type] = info.resistances[i].modBase + (age * info.resistances[i].modStep); // Restore random seed srand(time(0)); // Determine duration until next age level up int duration((age + 1) * 260); if (age == Ancient) duration = -1; else duration = (duration * (100 + info.maturationMod)) / 100; // Mark the drake's stone type and age in the modifier and level fields AFFECT_DATA af = {0}; af.where = TO_AFFECTS; af.type = gsn_wakenedstone; af.modifier = stoneType; af.level = age; af.duration = duration; affect_to_char(&drake, &af); // Adjust the drake's level for overwhelm drake.level += SpecialCount(drake, Overwhelm); }