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; }
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); }
void Weave::ShowNew(const ROOM_INDEX_DATA & room) { for (CHAR_DATA * ch(room.people); ch != NULL; ch = ch->next_in_room) { // Check for skill if (number_percent() >= get_modifier(ch->affected, gsn_weavesense) && !is_an_avatar(ch)) continue; // Skill check passed check_improve(ch, NULL, gsn_weavesense, TRUE, 4); send_to_char("You sense the Weave twist and flex around you, its primal energy branching and flowing in new patterns!\n", ch); } }
void show_char_to_char_2(struct char_data *victim, struct char_data *ch) { struct gameobject *obj; struct dynamic_skill *skill_peek; int iWear; bool found; if (can_see(victim, ch)) { if (ch == victim) { act("$n glances at $mself.", ch, NULL, NULL, TO_ROOM); } else { act("$n glances at you.", ch, NULL, victim, TO_VICT); act("$n glances at $N.", ch, NULL, victim, TO_NOTVICT); } } show_damage_display(ch, victim); found = false; for (iWear = 0; where_name[iWear].wear_loc >= 0; iWear++) { if ((obj = get_eq_char(victim, where_name[iWear].wear_loc)) != NULL && can_see_obj(ch, obj)) { if (!found) { send_to_char("\n\r", ch); act("$N is using:", ch, NULL, victim, TO_CHAR); found = true; } send_to_char(where_name[iWear].desc, ch); send_to_char("(", ch); send_to_char(format_obj_to_char(obj, ch, true), ch); send_to_char(")", ch); send_to_char("\n\r", ch); } } if (victim != ch && !IS_NPC(ch) && (skill_peek = gsp_peek) != NULL && number_percent() < get_learned_percent(ch, skill_peek)) { send_to_char("\n\rYou peek at the inventory:\n\r", ch); check_improve(ch, skill_peek, true, 4); show_list_to_char(victim->carrying, ch, true, true); } return; }
void do_dismount( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; bool show; int skill = get_skill( ch, gsn_riding ); if ( (victim = ch->mount) == NULL ) { send_to_char( "Przecie¿ nie dosiadasz teraz ¿adnego wierzchowca.\n\r", ch ); return; } if ( ch->position == POS_SLEEPING ) { send_to_char( "¦nisz o zsiadaniu z konia.\n\r", ch ); return; } do_dismount_body(ch); ch->position = POS_STANDING; show = TRUE; if ( IS_NPC( victim ) && HAS_TRIGGER( victim, TRIG_DISMOUNT ) ) { show = !mp_percent_trigger( victim, ch, NULL, NULL, &TRIG_DISMOUNT ); } if ( IS_NPC( victim ) && HAS_TRIGGER( victim, TRIG_MOUNT ) ) { show = FALSE; } if ( show ) { if ( skill == 0 || number_percent() > skill + 5 ) { act( "Nieudolnie próbujesz zsi±¶æ z grzbietu $Z i po chwili l±dujesz na ziemi.", ch, NULL, victim, TO_CHAR ); act( "$n nieudolnie próbuje zsi±¶æ z grzbietu $Z i po chwili l±duje na ziemi.", ch, NULL, victim, TO_NOTVICT ); ch->position = POS_SITTING; ch->move -= number_range(0,4); if ( ch->weight > 900 ) { ch->move -= number_range(0,2); } if ( ch->move < 0 ) { ch->move = 0; } check_improve( ch, NULL, gsn_riding, TRUE, 80 ); } else { act("Zrêcznie zeskakujesz z grzbietu $Z.", ch, NULL, victim, TO_CHAR ); act("$n zrêcznie zeskakuje z grzbietu $Z.", ch, NULL, victim, TO_NOTVICT ); check_improve( ch, NULL, gsn_riding, TRUE, 70 ); } } return; }
void do_mount_on( CHAR_DATA *ch, CHAR_DATA *horse ) { bool show; int skill = get_skill( ch, gsn_riding ); if ( ch->mount ) { print_char(ch, "Przecie¿ dosiadasz ju¿ %s!\n\r", ch->mount->name4); return; } if ( horse == ch ) { send_to_char( "Czego chcesz dosi±¶æ?\n\r", ch ); return; } if ( !IS_NPC(horse) || !EXT_IS_SET(horse->act, ACT_MOUNTABLE ) ) { print_char(ch, "Nie mo¿esz dosi±¶æ %s!\n\r", horse->name2 ); return; } if ( horse->mounting ) { print_char(ch, "%s ju¿ ma je¼dzca.\n\r", horse->short_descr ); return; } if ( horse->master && horse->master != ch ) { act("$N nie pozwala ci na to.", ch, NULL, horse->master, TO_CHAR ); return; } if ( horse->position < POS_STANDING ) { send_to_char( "Wierzchowiec musi staæ, aby mo¿na by³o na niego wsi±¶æ.\n\r", ch ); return; } if ( horse->fighting ) { print_char(ch, "%s teraz walczy, nie dasz rady wsi±¶æ.\n\r", horse->short_descr ); return; } if ( is_fearing( horse, ch ) ) { print_char(ch, "%s zbyt siê ciebie boi, nie dasz rady wsi±¶æ.\n\r", horse->short_descr ); if ( number_percent() < 5 ) { one_hit( horse, ch, TYPE_UNDEFINED, FALSE ); } return; } if ( ch->move <= 0 ) { act( "Jeste¶ zbyt zmêczon<&y/a/e> by dosi±¶æ wierzchowca.", ch, NULL, horse, TO_CHAR ); return; } if (IS_AFFECTED(ch, AFF_SNEAK) || IS_AFFECTED(ch, AFF_HIDE)) { switch (horse->sex) { case SEX_NEUTRAL: act( "Próbujesz dosi±¶æ $C, ale robisz to tak niespodziewanie, ¿e $N umyka przestraszone.", ch, NULL, horse, TO_CHAR ); break; case SEX_MALE: act( "Próbujesz dosi±¶æ $C, ale robisz to tak niespodziewanie, ¿e $N umyka przestraszony.", ch, NULL, horse, TO_CHAR ); break; case SEX_FEMALE: default : act( "Próbujesz dosi±¶æ $C, ale robisz to tak niespodziewanie, ¿e $N umyka przestraszona.", ch, NULL, horse, TO_CHAR ); break; } ch->move -= number_range(1,4); if ( ch->move < 0 ) { ch->move = 0; } return; } if(IS_AFFECTED(ch, AFF_FLYING)) { affect_strip(ch, gsn_fly); } if(IS_AFFECTED(ch, AFF_FLOAT)) { affect_strip(ch, gsn_float); } if ( skill == 0 || number_percent() > skill + 5 ) { act( "Nieudolnie próbujesz dosi±¶æ $C i po chwili l±dujesz na ziemi.", ch, NULL, horse, TO_CHAR ); act( "$n nieudolnie próbuje dosi±¶æ $C i po chwili l±duje na ziemi.", ch, NULL, horse, TO_NOTVICT ); ch->position = POS_SITTING; ch->move -= number_range(0,4); if ( ch->weight > 900 ) { ch->move -= number_range(0,2); } ch->move = UMAX(0,ch->move); check_improve( ch, NULL, gsn_riding, TRUE, 70 ); return; } ch->mount = horse; horse->mounting = ch; horse->default_pos = POS_STANDING; horse->position = POS_STANDING; show = TRUE; if ( IS_NPC( horse ) && HAS_TRIGGER( horse, TRIG_MOUNT ) ) { show = !mp_percent_trigger( horse, ch, NULL, NULL, &TRIG_MOUNT ); } if ( IS_NPC( horse ) && HAS_TRIGGER( horse, TRIG_DISMOUNT ) ) { show = FALSE; } if ( show ) { act( "Umiejêtnie dosiadasz $C.", ch, NULL, horse, TO_CHAR ); act( "$n umiejêtnie dosiada $C.", ch, NULL, horse, TO_NOTVICT ); check_improve( ch, NULL, gsn_riding, TRUE, 10 ); } return; }
//http://code.killer.mud.pl/p/killer-mud/issues/5/ void track_new(CHAR_DATA *ch, int skill, char *argument) { char buf [ MAX_STRING_LENGTH ]; char *messages_czas1[] = { "¶wie¿e", "¶wie¿e", "lekko zatarte", "zatarte", "zatarte", "zatarte", "ledwo rozpoznawalne", "ledwo rozpoznawalne" }; char *messages_czas2[] = { "¶wie¿e", "¶wie¿e", "lekko zatarte", "zatarte", "zatarte", "mocno zatarte", "ledwo rozpoznawalne", "ledwo rozpoznawalne" }; char *messages_czas3[] = { "bardzo ¶wie¿e", "ca³kiem ¶wie¿e", "bardzo lekko zatarte", "lekko zatarte", "zatarte", "mocno zatarte", "ledwo rozpoznawalne", "prawie nierozpoznawalne" }; TRACK_DATA* td = ch->in_room->track_data; if(!td) { act("$n klêka i zaczyna z uwag± przygl±daæ siê ¶ladom.",ch,NULL,NULL,TO_ROOM); act("Klêkasz, przygl±dasz siê ¶ladom, ale nie znajdujesz ¿adnych tropów.",ch,NULL,NULL,TO_CHAR); WAIT_STATE( ch, skill_table[gsn_track].beats ); return; } //cleanup_track_data(ch->in_room); int track_cnt = URANGE( 1, ( (number_range(1, MAX_TRACK_LEN) * skill)/100 + (number_range(1, MAX_TRACK_LEN / 6) * get_curr_stat(ch,STAT_INT)/6)/OLD_28_VALUE/6 ) , MAX_TRACK_LEN ); int i = 0; int succ = 0; // if(debug ==1) bugf("track_cnt %d", track_cnt); while(td) { i++; if(i > track_cnt) break; if ((number_range(1, 100) > skill/20) && is_name( argument, td->ch->ss_data ? td->ch->short_descr : td->ch->name ) ) { int roznica = current_time - td->czas; // if(debug ==1) bugf("roznica %d", roznica); //skill = 1 - 36 sekund, 75 - 3600s - im lepszy skill, tym wiêcej ¶ladów (czas) if(roznica / 96 <= skill) { int czas_message = URANGE(0, roznica / 400, 7) ; char* vdir_name = td->kierunek == -1 ? "do nik±d" : (td->inout == 0 ? dir_name2[td->kierunek] : dir_name_dir[td->kierunek]); char* vinout = td->inout == 0 ? ", prowadz±ce tu," : ", wychodz±ce st±d,"; //skill 0 do 95 //skill/27 0 do 3.52 //kolejno: 0 27 53 81 inf switch(skill/27) { case 0: sprintf( buf, "Znajdujesz jakie¶ ¶lady $Z."); break; case 1: sprintf( buf, "Znajdujesz %s ¶lady $Z.", messages_czas1[czas_message]); break; case 2: sprintf( buf, "Znajdujesz %s ¶lady $Z.", messages_czas2[czas_message]); break; case 3: sprintf( buf, "Znajdujesz %s%s ¶lady $Z prowadz±ce %s.", messages_czas3[czas_message], vinout, vdir_name ); break; default: sprintf( buf, "Znajdujesz %s%s ¶lady $Z prowadz±ce %s.", messages_czas3[czas_message], vinout, vdir_name ); break; } succ=1; act( buf, ch, NULL, td->ch, TO_CHAR ); } } td = td->previous; } if(succ == 0) { act("$n klêka i zaczyna z uwag± przygl±daæ siê ¶ladom.",ch,NULL,NULL,TO_ROOM); act("Klêkasz, przygl±dasz siê ¶ladom, ale nie znajdujesz ¿adnych tropów.",ch,NULL,NULL,TO_CHAR); check_improve(ch, NULL, gsn_track, FALSE, 12); WAIT_STATE( ch, skill_table[gsn_track].beats ); return; } check_improve(ch, NULL, gsn_track, TRUE, 9); WAIT_STATE( ch, skill_table[gsn_track].beats ); }
void do_track( CHAR_DATA *ch, char *argument ) { char buf [ MAX_STRING_LENGTH ]; char arg [ MAX_STRING_LENGTH ]; CHAR_DATA *victim; int direction, skill; bool fArea=TRUE; skill=get_skill(ch, gsn_track); if (IS_NPC(ch)) { return; } if ( ch->mount ) { send_to_char( "Najpierw zsi±d¼ ze swojego wierzchowca.\n\r", ch ); return; } if ( !IS_IMMORTAL( ch ) && IS_AFFECTED( ch, AFF_BLIND ) ) { act("$n klêka i bezradnie potrz±sa g³ow±.",ch,NULL,NULL,TO_ROOM); send_to_char("Klekasz, ale przecie¿ niczego nie widzisz.\n\r",ch); return; } if ( room_is_dark( ch, ch->in_room ) && !(IS_AFFECTED( ch, AFF_DARK_VISION ) || IS_IMMORTAL( ch ) )) { send_to_char("Klekasz, ale jest tu tak ciemno, ¿e niczego nie widzisz.\n\r",ch); return; } // wycinamy niektóre ze sektorów switch ( ch->in_room->sector_type ) { case 6: //woda p³yw case 7: //woda niep case 19: //rzeka case 20: //jezioro case 21: //morze case 22: //ocean case 23: //lawa case 24: //ruchome piaski case 25: //gor±ce ¼ród³o case 34: //pod wod± case 37: //ciemna woda case 39: //podziemne jezioro send_to_char( "Tutaj chyba nie da siê szukaæ ¶ladów.\n\r", ch ); return; } // komunikaty dla tych, którzy nie umiej± szukaæ ¶ladów if ( skill == 0 ) { switch (number_range(1,7)) { case 1: act("$n klêka i nie wie co robiæ dalej.",ch,NULL,NULL,TO_ROOM); send_to_char("Klêkasz i nie za bardzo wiesz co robiæ dalej.\n\r",ch); break; case 2: act("$n klêka i niczego nie widzi.",ch,NULL,NULL,TO_ROOM); send_to_char("Klêkasz i niczego nie widzisz.\n\r",ch); break; case 3: act("$n mocno tupie, klêka i przygl±da siê ¶ladom.",ch,NULL,NULL,TO_ROOM); send_to_char("Mocno tupiesz, klêkasz i przygl±dasz siê ¶ladom.\n\r",ch); break; case 4: act("$n klêka i ¶ledzi tropy, ale nie ma o tym zielonego pojêcia.",ch,NULL,NULL,TO_ROOM); send_to_char("Klêkasz i ¶ledzisz tropy, choæ nie masz o tym zielonego pojêcia.\n\r",ch); break; case 5: act("$n klêka i robi nieszczê¶liw± minê.",ch,NULL,NULL,TO_ROOM); send_to_char("Klêkasz i robisz nieszczê¶liw± minê.\n\r",ch); break; case 6: act("$n rozgl±da siê dooko³a.",ch,NULL,NULL,TO_ROOM); send_to_char("Rozgl±dasz siê dooko³a, ale to nie pomaga.\n\r",ch); break; case 7: act("$n zastanawia siê nad tym, ¿e tropienie to niez³a umiejêtno¶æ.",ch,NULL,NULL,TO_ROOM); send_to_char("Zastanawiasz siê nad tym, ¿e tropienie to niez³a umiejêtno¶æ.\n\r",ch); break; default : send_to_char( "Nie masz pojêcia jak to siê robi.\n\r", ch ); act("$n klêka i ¶ledzi tropy, ale nie ma o tym zielonego pojêcia.",ch,NULL,NULL,TO_ROOM); break; } return; } // bonus/kara od dobrej lokacji s± wiêksze ni¿ od z³ej if ( EXT_IS_SET( ch->in_room->room_flags, ROOM_CONSECRATE )) { if (IS_EVIL( ch ) ) skill -= number_range(1,5); if (IS_GOOD( ch ) ) skill += number_range(1,5); } if ( EXT_IS_SET( ch->in_room->room_flags, ROOM_DESECRATE )) { if (IS_EVIL( ch ) ) skill += number_range(0,4); if (IS_GOOD( ch ) ) skill -= number_range(0,4); } // sprawdzamy czy skill nie zrobi³ siê nam mniejszy ni¿ 1 if (skill < 1) { skill = 1; } // no to zaczynamy w³a¶ciwe trackowanie :D one_argument( argument, arg ); #ifdef ENABLE_NEW_TRACK if(MAX_TRACK_LEN > 0) { track_new(ch, skill, argument); return; } #endif if ( arg[0] == '\0' ) { act("$n klêka i zaczyna z uwag± przygl±daæ siê ¶ladom.",ch,NULL,NULL,TO_ROOM); act("Klêkasz i z uwag± przygl±dasz siê ¶ladom.",ch,NULL,NULL,TO_CHAR); return; } if ( fArea ) { victim = get_char_area( ch, arg ); } else { victim = get_char_world( ch, arg ); } if ( !victim ) { act("$n klêka i zaczyna z uwag± przygl±daæ siê ¶ladom.",ch,NULL,NULL,TO_ROOM); act("Klêkasz, przygl±dasz siê ¶ladom, ale nie znajdujesz ¿adnego tropu.",ch,NULL,NULL,TO_CHAR); WAIT_STATE( ch, skill_table[gsn_track].beats ); return; } if(victim==ch) { act("Zastanawiasz siê przez chwilê czy to ma sens, no có¿...",ch,NULL,NULL,TO_CHAR); return; } if ( ch->in_room == victim->in_room ) { act( "Klêkasz i badasz trop, po chwili zdajesz sobie sprawê, ¿e $N stoi ko³o ciebie.", ch, NULL, victim, TO_CHAR ); act("$n klêka i zaczyna z uwag± przygl±daæ siê ¶ladom.",ch,NULL,NULL,TO_ROOM); return; } if ( skill < number_range( 20, 40 ) ) { act("$n klêka i zaczyna z uwag± przygl±daæ siê ¶ladom.",ch,NULL,NULL,TO_ROOM); act("Klêkasz, przygl±dasz siê ¶ladom, ale nie znajdujesz ¿adnego tropu.",ch,NULL,NULL,TO_CHAR); WAIT_STATE( ch, skill_table[gsn_track].beats ); check_improve(ch, NULL, gsn_track, FALSE, 12); return; } if ( IS_AFFECTED ( victim, AFF_SPIRIT_WALK ) ) { act("$n klêka i zaczyna z uwag± przygl±daæ siê ¶ladom.",ch,NULL,NULL,TO_ROOM); act("Klêkasz, przygl±dasz siê ¶ladom, ale nie znajdujesz ¿adnego tropu.",ch,NULL,NULL,TO_CHAR); WAIT_STATE( ch, skill_table[gsn_track].beats ); return; } else { act("$n klêka i zaczyna z uwag± przygl±daæ siê ¶ladom.",ch,NULL,NULL,TO_ROOM); act("Klêkasz i przygladasz siê ¶ladom, chyba widzisz jaki¶ trop.",ch,NULL,NULL,TO_CHAR); } WAIT_STATE( ch, skill_table[gsn_track].beats ); direction = find_path( ch->in_room->vnum, victim->in_room->vnum, ch, -40000, fArea ); if ( direction == -1 ) { act( "Niestety, nie mo¿esz nic wiêcej odczytaæ ze ¶ladów.", ch, NULL, victim, TO_CHAR ); return; } if ( direction < 0 || direction >= MAX_DIR ) { send_to_char( "Hmm... co¶ jest nie tak.\n\r", ch ); return; } /* * Give a random direction if the player misses the die roll. */ if ( number_percent() > skill ) { do { direction = number_door( ); } while ( !( ch->in_room->exit[direction] ) || !( ch->in_room->exit[direction]->u1.to_room ) ); } check_improve(ch, NULL, gsn_track, TRUE, 9); /* * Display the results of the search. */ sprintf( buf, "Znajdujesz ¶lady $Z prowadz±ce na %s.", direction == 4 ? "górê" : dir_name[direction] ); act( buf, ch, NULL, victim, TO_CHAR ); return; }
/* * Procedure which allows a player to purchase a portal from a mob. The mob must be * set as act portalmerchant. There is a base cost in the portal_shop_table and those * prices will be altered here based on the desination (e.g. it will cost more to create * a portal across continents than it will to travel inter-continent. This procedure * will be called from do_list and do_buy to make it function like a normal shop. */ void process_portal_merchant(CHAR_DATA * ch, char *argument) { int x = 0; char buf[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; bool found = FALSE; CHAR_DATA *mob; OBJ_DATA *portal; int cost = 0; int roll = 0; if ((mob = find_mob_by_act(ch, ACT_IS_PORTAL_MERCHANT)) == NULL) { send_to_char("You must find a portal merchant in order to purchase a portal.\r\n", ch); return; } // Not with people that can't be seen.. this will depend on the mob.. if the mob has detect hidden // or detect invis they will see most people unless they are in another for of non-detect, etc. if (!can_see(mob, ch)) { act("{x$N says '{gI don't trade with folks I can't see, please make yourself 'visible'.{x", ch, NULL, mob, TO_CHAR); return; } // No argument was sent, send them the list of destinations. if (IS_NULLSTR(argument)) { act("{x$N says '{gI offer the creation of portals to following destinations.{x'\r\n", ch, NULL, mob, TO_CHAR); // Loop through the destinations for display for (x = 0; portal_shop_table[x].name != NULL; x++) { int temp_cost = 0; if (same_continent(ch->in_room->vnum, portal_shop_table[x].to_vnum)) { // They're in the same continent, normal cost (converted to gold). temp_cost = portal_shop_table[x].cost / 100; } else { // They are in different continents, double the cost (converted to gold). temp_cost = (portal_shop_table[x].cost / 100) * 2; } // To get the : into the formatted string sprintf(buf2, "{_%s{x:", portal_shop_table[x].name); sprintf(buf, " %-17s{x {c%-40s{x %d gold\r\n", buf2, get_room_name(portal_shop_table[x].to_vnum), temp_cost); send_to_char(buf, ch); } send_to_char("\r\nType buy <location> to purchase a portal to that destination.\r\n", ch); return; } // Did the user select a valid input? for (x = 0; portal_shop_table[x].name != NULL; x++) { if (!str_prefix(argument, portal_shop_table[x].name)) { if (same_continent(ch->in_room->vnum, portal_shop_table[x].to_vnum)) { // They're in the same continent, normal cost (the raw cost). cost = portal_shop_table[x].cost; } else { // They are in different continents, double the cost (the raw cost) cost = (portal_shop_table[x].cost) * 2; } found = TRUE; break; } } // What the location found? if (!found) { act("{x$N says '{gThat is not a place that I know of.{x", ch, NULL, mob, TO_CHAR); return; } // Do they have enough money? if (cost > (ch->gold * 100 + ch->silver)) { act("{x$N says '{gYou do not have enough gold for my services.{x'", ch, NULL, mob, TO_CHAR); return; } // Can the player haggle, if successful, adjust the price down? roll = number_percent(); if (roll < get_skill(ch, gsn_haggle)) { cost -= cost / 2 * roll / 100; sprintf(buf, "You haggle the price down to %d coins.\r\n", cost); send_to_char(buf, ch); check_improve(ch, gsn_haggle, TRUE, 4); } else { check_improve(ch, gsn_haggle, FALSE, 2); } // Slight purchase lag, same as buy. WAIT_STATE(ch, PULSE_VIOLENCE); // Deduct the money. deduct_cost(ch, cost); portal = create_object(get_obj_index(OBJ_VNUM_PORTAL)); portal->timer = 2; // 2 ticks. portal->value[3] = portal_shop_table[x].to_vnum; // Alter the keywords for the portal to include the destination to make the portals easier to use // than the enter 3.portal syntax (if there are multiples in the room) sprintf(buf, "portal gate %s", portal_shop_table[x].name); free_string(portal->name); portal->name = str_dup(buf); // Alter the portal's description to the room, we'll presume we know where these are going. sprintf(buf, "A shimmering black gate rises from the ground, leading to %s.", get_area_name(portal_shop_table[x].to_vnum)); free_string(portal->description); portal->description = str_dup(buf); // Put said object in said room. obj_to_room(portal, ch->in_room); act("$N raises $s hand and begans chanting.", ch, NULL, mob, TO_CHAR); act("$p rises up from the ground.", ch, portal, NULL, TO_ALL); } // end do_portal
void do_track( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; char arg[MAX_STRING_LENGTH]; CHAR_DATA *victim; int direction; bool fArea; one_argument( argument, arg ); if ( !IS_NPC(ch) && !can_use_skpell( ch, gsn_track) ) { send_to_char( "\n\r{WYou find some tracks that look remarkably like your own...{x\n\r",ch); return; } if( arg[0] == '\0' ) { send_to_char( "\n\r{CWhom are you trying to track?{x\n\r", ch ); return; } /* only imps can hunt to different areas */ fArea = ( ch->level < MAX_LEVEL ); /* if (IS_NPC(ch)) victim = get_char_world( ch, arg ); else */ if (fArea) victim = get_char_area( ch, arg ); else victim = get_char_area( ch, arg ); if (IS_SET(ch->in_room->room_flags, ROOM_DRAGONPIT)) { send_to_char("\n\r{CThat would be cheating..{x\n\r", ch ); return; } if( victim == NULL ) { send_to_char("\n\r{RNo-one around by that name.{x\n\r", ch ); return; } if( ch->in_room == victim->in_room ) { act( "\n\r{G$N is here!{x\n\r", ch, NULL, victim, TO_CHAR ); return; } /* * Deduct some movement. */ if( ch->move > 3 ) ch->move -= 3; else { send_to_char( "\n\r{RYou're too exhausted to track anyone!{x\n\r", ch ); return; } act( "\n\r{c$n carefully sniffs the air.{x\n\r", ch, NULL, NULL, TO_ROOM ); WAIT_STATE( ch, skill_table[gsn_track].beats ); direction = find_path( ch->in_room->vnum, victim->in_room->vnum, ch, -40000, fArea ); if( direction == -1 ) { act( "\n\r{GYou couldn't find a path to $N from here.{x\n\r", ch, NULL, victim, TO_CHAR ); return; } if( direction < 0 || direction > 9 ) { send_to_char( "\n\r{CHmm... Something seems to be wrong.{x\n\r", ch ); return; } /* * Give a random direction if the player misses the die roll. */ #if 0 if( ( IS_NPC (ch) && number_percent () > 75) /* NPC @ 25% */ || (!IS_NPC (ch) && number_percent () > /* PC @ norm */ ch->pcdata->learned[gsn_track] ) ) #endif if (!IS_NPC(ch) && number_percent() > ch->pcdata->learned[gsn_track]) { do { direction = number_door(); } while( ( ch->in_room->exit[direction] == NULL ) || ( ch->in_room->exit[direction]->u1.to_room == NULL) ); } /* * Display the results of the search. */ sprintf( buf, "\n\r{C$N is %s from here.{x\n\r", dir_name[direction] ); act( buf, ch, NULL, victim, TO_CHAR ); check_improve(ch,gsn_track,TRUE,1); return; }
int mount_success ( CHAR_DATA *ch, CHAR_DATA *mount, int canattack) { int percent; int success; percent = number_percent() + (ch->level < mount->level ? (mount->level - ch->level) * 3 : (mount->level - ch->level) * 2); if (!ch->fighting) percent -= 25; if (!IS_NPC(ch) && IS_DRUNK(ch)) { percent += ch->pcdata->learned[gsn_riding] / 2; send_to_char("Due to your being under the influence, riding seems a bit harder...\n\r", ch); } success = percent - ch->pcdata->learned[gsn_riding]; if( success <= 0 ) { check_improve(ch, gsn_riding, TRUE, 1); return(1); } else { check_improve(ch, gsn_riding, FALSE, 1); if ( success >= 10 && MOUNTED(ch) == mount) { act("You lose control and fall off of $N.", ch, NULL, mount, TO_CHAR); act("$n loses control and falls off of $N.", ch, NULL, mount, TO_ROOM); act("$n loses control and falls off of you.", ch, NULL, mount, TO_VICT); ch->riding = FALSE; mount->riding = FALSE; if (ch->position>POS_STUNNED) ch->position=POS_SITTING; ch->hit -= 5; update_pos(ch); } if ( success >= 40 && canattack) { act("$N doesn't like the way you've been treating $M.", ch, NULL, mount, TO_CHAR); act("$N doesn't like the way $n has been treating $M.", ch, NULL, mount, TO_ROOM); act("You don't like the way $n has been treating you.", ch, NULL, mount, TO_VICT); act("$N snarls and attacks you!", ch, NULL, mount, TO_CHAR); act("$N snarls and attacks $n!", ch, NULL, mount, TO_ROOM); act("You snarl and attack $n!", ch, NULL, mount, TO_VICT); damage( mount, ch, number_range( 1, mount->level), gsn_kick, DAM_BASH, FALSE,0 ); } } return(0); }
void do_buy_mount( CHAR_DATA *ch, char *argument ) { int cost,roll; char arg[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH]; char color[80], name[30], size[30]; CHAR_DATA *mount; ROOM_INDEX_DATA *pRoomIndexNext; ROOM_INDEX_DATA *in_room; name[0] = '\0'; size[0] = '\0'; color[0] = '\0'; if ( IS_NPC(ch) ) return; if (!IS_NPC(ch) && !ch->pcdata->learned[gsn_riding]) { send_to_char("How do you expect to buy a horse when you can't even ride?\n\r", ch); return; } argument = one_argument(argument,arg); pRoomIndexNext = get_room_index( ch->in_room->vnum + 1 ); if ( pRoomIndexNext == NULL ) { bug( "Do_buy: bad mount shop at vnum %d.", ch->in_room->vnum ); send_to_char( "I'm afraid the stalls where I keep my mounts don't exist.\n\r", ch ); return; } in_room = ch->in_room; ch->in_room = pRoomIndexNext; mount = get_char_room( ch, arg ); ch->in_room = in_room; if ( mount == NULL) { send_to_char( "Sorry, we don't sell any of those here.\n\r", ch ); return; } if ( !IS_SET(mount->act3, ACT3_MOUNT) ) { send_to_char( "Sorry, we don't sell any of those here.\n\r", ch ); return; } if ( MOUNTED(ch) || ch->mount != NULL) { send_to_char("You already have a mount.\n\r",ch); return; } cost = 100 * ch->level; if ( ch->gold < cost ) { send_to_char( "You can't afford it.\n\r", ch ); return; } roll = number_percent(); if (!IS_NPC(ch) && roll < ch->pcdata->learned[gsn_haggle]) { cost -= cost / 2 * roll / 100; sprintf(buf,"You haggle the price down to %d coins.\n\r",cost); send_to_char(buf,ch); check_improve(ch,gsn_haggle,TRUE,4); } ch->gold -= cost; mount = create_mobile( mount->pIndexData ); mount->comm = COMM_NOTELL|COMM_NOSHOUT|COMM_NOCHANNELS; mount->max_hit = mount->hit = (ch->level * 4) - (25 + number_range(1,50)); if( mount->max_hit < 25 ) mount->max_hit = mount->hit = 25; mount->max_mana = mount->mana = 50; mount->max_move = mount->move = 200 + ch->level * 10; mount->level = ch->level / 1.25; mount->sex = ch->sex; switch( number_range(1,11) ) { case 1: strcpy(color, "dappled grey" ); break; case 2: strcpy(color, "charcoal grey" ); break; case 3: strcpy(color, "midnight black" ); break; case 4: strcpy(color, "dark burgundy" ); break; case 5: strcpy(color, "cream yellow" ); break; case 6: strcpy(color, "pure white"); break; case 7: strcpy(color, "dark brown"); break; case 8: strcpy(color, "light brown"); break; case 9: strcpy(color, "white and brown spotted"); break; case 10: strcpy(color, "black and white spotted"); break; case 11: strcpy(color, "purple and green striped"); strcpy(size, "mutant "); mount->hit += 100; mount->max_hit += 100; break; } if( ch->level >= 41 ) { strcpy(name, "pegasus"); SET_BIT(mount->affected_by, AFF_FLYING); } else if( ch->level >= 30 ) { if (ch->sex == 1) strcpy(name, "gelding"); else { strcpy(name, "mare"); strcat(size, "majestic "); } } else if( ch->level >= 20 ) { if (ch->sex == 1) strcpy(name, "stallion"); else strcpy(name, "mare"); } else if( ch->level >= 15 ) { strcpy(name, "horse"); } else if( ch->level >= 10 ) { strcpy(name, "horse"); strcat(size, "small "); } else { strcpy(name, "pony"); } argument = one_argument( argument, arg ); if ( arg[0] != '\0' ) sprintf( buf, "%s %s", name, arg ); else sprintf( buf, "%s", name ); free_string( mount->name ); mount->name = str_dup( buf ); sprintf( buf, "a %s%s %s", size, color, name ); free_string( mount->short_descr ); mount->short_descr = str_dup( buf ); sprintf( buf, "A %s%s %s is standing here.\n\r", size, color, name ); free_string( mount->long_descr ); mount->long_descr = str_dup( buf ); sprintf( buf, "%sThe name %s is branded on its hind leg.\n\r", mount->description, ch->name ); free_string( mount->description ); mount->description = str_dup( buf ); char_to_room( mount, ch->in_room ); add_follower( mount, ch ); act( "$n bought $N as a mount.", ch, NULL, mount, TO_ROOM ); sprintf( buf, "Enjoy your %s.\n\r", name ); send_to_char( buf, ch); do_mount( ch, name ); return; }
void Weave::ShowWeave(CHAR_DATA & ch, const ROOM_INDEX_DATA & room) { // Check for skill bool hasGraven(is_affected(&ch, gsn_gravenmind)); bool gravenOnly(false); if (number_percent() > get_modifier(ch.affected, gsn_weavesense) && !is_an_avatar(&ch)) { if (hasGraven) gravenOnly = true; else return; } // Check for sundered weave if (area_is_affected(room.area, gsn_sunderweave)) return; // Check for a fount check_improve(&ch, NULL, gsn_weavesense, TRUE, 4); std::ostringstream mess; mess << std::hex; bool anyWeave(false); if (room.ley_group != NULL) { if (room.ley_group->HasFount() && (!gravenOnly || room.ley_group->FountOrderPower() > 0)) { anyWeave = true; long attunedID(room.ley_group->AttunedID()); if (attunedID != LeyGroup::Unattuned) mess << ((attunedID == ch.id) ? "[{WResonant{x] " : "[{WDissonant{x] "); if (gravenOnly) mess << "A sense of deep, humming power fills this place, marking it as a nexus of order."; else { // Note that founts don't get modified by normal ley modifiers mess << GenerateFountDescription(room.ley_group->FountOrderPower(), room.ley_group->FountPositivePower(), AdjacentLeyRooms(room, &room)); if (IS_IMMORTAL((&ch))) mess << " {c[ID: " << reinterpret_cast<unsigned long>(&room) << "]{x"; } mess << "\n"; } // Check for ley lines if (!gravenOnly) { for (unsigned int i(0); i < room.ley_group->LineCount(); ++i) { anyWeave = true; const LeyInfo & leyLine(room.ley_group->Line(i)); mess << GenerateLineDescription(ApplyOrderModifiers(leyLine.OrderPower, room), ApplyPositiveModifiers(leyLine.PositivePower, room), AdjacentLeyRooms(room, leyLine.ID)); if (IS_IMMORTAL((&ch))) mess << " {c[ID: " << reinterpret_cast<unsigned long>(leyLine.ID) << "]{x"; mess << "\n"; } } } if (hasGraven) { // Graven mind can sense order founts in adjacent rooms for (unsigned int i(0); i < Direction::Max; ++i) { Direction::Value direction(static_cast<Direction::Value>(i)); ROOM_INDEX_DATA * nextRoom(Direction::Adjacent(room, direction)); if (nextRoom != NULL && nextRoom->ley_group != NULL && nextRoom->ley_group->HasFount() && nextRoom->ley_group->FountOrderPower() > 0) { anyWeave = true; mess << "The deep, steady thrum of an order nexus resonates " << Direction::SourceNameFor(direction) << ".\n"; } } } if (anyWeave) { mess << "\n"; send_to_char(mess.str().c_str(), &ch); } }
int mana_gain( CHAR_DATA *ch ) { int gain; int number; if (ch->in_room == NULL) return 0; if ( IS_NPC(ch) ) { gain = 5 + ch->level; switch (ch->position) { default: gain /= 2; break; case POS_SLEEPING: gain = 3 * gain/2; break; case POS_RESTING: break; case POS_FIGHTING: gain /= 3; break; } } else { gain = (get_curr_stat(ch,STAT_WIS) + get_curr_stat(ch,STAT_INT) + ch->level) / 2; number = number_percent(); if (number < get_skill(ch,gsn_meditation)) { gain += number * gain / 100; if (ch->mana < ch->max_mana) check_improve(ch,gsn_meditation,TRUE,8); } if (!class_table[ch->iclass].fMana) gain /= 2; switch ( ch->position ) { default: gain /= 4; break; case POS_SLEEPING: break; case POS_RESTING: gain /= 2; break; case POS_FIGHTING: gain /= 6; break; } if ( ch->pcdata->condition[COND_HUNGER] == 0 ) gain /= 2; if ( ch->pcdata->condition[COND_THIRST] == 0 ) gain /= 2; } gain = gain * ch->in_room->mana_rate / 100; if (ch->on != NULL && ch->on->item_type == ITEM_FURNITURE) gain = gain * ch->on->value[4] / 100; if ( IS_AFFECTED( ch, AFF_POISON ) ) gain /= 4; if (IS_AFFECTED(ch, AFF_PLAGUE)) gain /= 8; if (IS_AFFECTED(ch,AFF_HASTE) || IS_AFFECTED(ch,AFF_SLOW)) gain /=2 ; return UMIN(gain, ch->max_mana - ch->mana); }
/* * Regeneration stuff. */ int hit_gain( CHAR_DATA *ch ) { int gain; int number; if (ch->in_room == NULL) return 0; if ( IS_NPC(ch) ) { gain = 5 + ch->level; if (IS_AFFECTED(ch,AFF_REGENERATION)) gain *= 2; switch(ch->position) { default : gain /= 2; break; case POS_SLEEPING: gain = 3 * gain/2; break; case POS_RESTING: break; case POS_FIGHTING: gain /= 3; break; } } else { gain = UMAX(3,get_curr_stat(ch,STAT_CON) - 3 + ch->level/2); gain += class_table[ch->iclass].hp_max - 10; number = number_percent(); if (number < get_skill(ch,gsn_fast_healing)) { gain += number * gain / 100; if (ch->hit < ch->max_hit) check_improve(ch,gsn_fast_healing,TRUE,8); } switch ( ch->position ) { default: gain /= 4; break; case POS_SLEEPING: break; case POS_RESTING: gain /= 2; break; case POS_FIGHTING: gain /= 6; break; } if ( ch->pcdata->condition[COND_HUNGER] == 0 ) gain /= 2; if ( ch->pcdata->condition[COND_THIRST] == 0 ) gain /= 2; } gain = gain * ch->in_room->heal_rate / 100; if (ch->on != NULL && ch->on->item_type == ITEM_FURNITURE) gain = gain * ch->on->value[3] / 100; if ( IS_AFFECTED(ch, AFF_POISON) ) gain /= 4; if (IS_AFFECTED(ch, AFF_PLAGUE)) gain /= 8; if (IS_AFFECTED(ch,AFF_HASTE) || IS_AFFECTED(ch,AFF_SLOW)) gain /=2 ; return UMIN(gain, ch->max_hit - ch->hit); }
void Drakes::WakenStone(CHAR_DATA & ch, const char * argument, int skill) { // Check for location if (ch.in_room == NULL || !ON_GROUND(&ch)) { send_to_char("You cannot reach the earth from this place.\n", &ch); return; } // Get the location's stone type and use it to lookup the drake info int stoneType(ch.in_room->stone_type); if (stoneType < 0) stoneType = ch.in_room->area->stone_type; const Info * info(Lookup(stoneType)); if (info == NULL) { send_to_char("You probe your will into the earth, but cannot reach its stony heart from here.\n", &ch); return; } // Check whether an argument was provided if (argument[0] == '\0') { std::ostringstream mess; mess << "You probe your will into the earth, which resonates with a strong sense of "; mess << material_table[stoneType].name << ".\n"; send_to_char(mess.str().c_str(), &ch); return; } // Check for an earth elemental pet present CHAR_DATA * elemental(get_char_room(&ch, argument)); if (elemental == NULL) { send_to_char("You see nobody here by that name.\n", &ch); return; } // Verify the elemental if (ch.pet != elemental || elemental->master != &ch || !IS_NPC(elemental) || elemental->pIndexData->vnum != MOB_VNUM_EARTH_ELEMENTAL) { send_to_char("You may only waken an earth elemental which belongs to you.\n", &ch); return; } // Check for mana if (ch.mana < skill_table[gsn_wakenedstone].min_mana) { send_to_char("You lack the energy to waken stone right now.\n", &ch); return; } // Starting echoes act("You bind your will around $N, seeking a path from $M to the stony heart of the earth.", &ch, NULL, elemental, TO_CHAR); act("A steady murmur of energy flows back up the link, pouring into $N!", &ch, NULL, elemental, TO_CHAR); act("The ground begins to throb with energy, concentrated between $n and $N!", &ch, NULL, elemental, TO_ROOM); act("Shards of rock break and fall away from $M as you call out, waking the stone with your power!", &ch, NULL, elemental, TO_CHAR); act("$n calls out suddenly, and shards of rock break and fall away from $M!", &ch, NULL, elemental, TO_ROOM); // Check for skill success if (number_percent() <= skill) { // Make the base mob and adjust for age and type CHAR_DATA * drake(create_mobile(get_mob_index(MOB_VNUM_DRAKE))); AdjustDrake(ch, *drake, stoneType, *info, UMAX(ch.level, elemental->level), Hatchling); drake->hit = drake->max_hit; drake->mana = drake->max_mana; drake->move = drake->max_move; // Replace the elemental with the drake check_improve(&ch, NULL, gsn_wakenedstone, true, 1); char_to_room(drake, ch.in_room); ch.pet = drake; drake->master = &ch; drake->leader = &ch; // Success echo act("The last bits slough away, leaving behind $n.", drake, NULL, NULL, TO_ROOM); } else { // Failure echo act("You lose control, and $N crumbles away completely!", &ch, NULL, elemental, TO_CHAR); act("$N crumbles away completely, reduced to mere dust in moments.", &ch, NULL, elemental, TO_ROOM); } // Destroy the elemental elemental->master = NULL; extract_char(elemental, true); // Charge mana and lag expend_mana(&ch, skill_table[gsn_wakenedstone].min_mana); WAIT_STATE(&ch, skill_table[gsn_wakenedstone].beats); }
void do_constructwaterwheel(CHAR_DATA * ch, char * argument) { // Check for skill int skill(get_skill(ch, gsn_constructwaterwheel)); if (skill <= 0) { send_to_char("Huh?\n", ch); return; } // Check cooldown for (AFFECT_DATA * paf(get_affect(ch, gsn_constructwaterwheel)); paf != NULL; paf = get_affect(ch, gsn_constructwaterwheel, paf)) { if (paf->location == APPLY_NONE) { send_to_char("You are not ready to construct another waterwheel yet.\n", ch); return; } } // Basic room checking if (ch->in_room == NULL || (ch->in_room->sector_type != SECT_WATER_SWIM && ch->in_room->sector_type != SECT_WATER_NOSWIM)) { send_to_char("You may only construct a waterwheel on a river.\n", ch); return; } // Verify this room is a river unsigned int waterCount(0); for (unsigned int i(0); i <= Direction::Up; ++i) { ROOM_INDEX_DATA * room(Direction::Adjacent(*ch->in_room, static_cast<Direction::Value>(i))); if (room != NULL && (room->sector_type == SECT_WATER_SWIM || room->sector_type == SECT_WATER_NOSWIM)) ++waterCount; } if (waterCount < 1 || waterCount > 2) { send_to_char("You may only construct a waterwheel on a river.\n", ch); return; } // Verify that there is not already a waterwheel here for (OBJ_DATA * obj(ch->in_room->contents); obj != NULL; obj = obj->next_content) { if (obj->pIndexData->vnum == OBJ_VNUM_WATERWHEEL) { send_to_char("There is already a waterwheel collecting the power of the river here.\n", ch); return; } } // Verify sufficient mana if (ch->mana < skill_table[gsn_constructwaterwheel].min_mana) { send_to_char("You are too weary to construct a waterwheel right now.\n", ch); return; } // Charge mana and lag expend_mana(ch, skill_table[gsn_constructwaterwheel].min_mana); WAIT_STATE(ch, skill_table[gsn_constructwaterwheel].beats); // Skill check if (number_percent() > skill) { check_improve(ch, NULL, gsn_constructwaterwheel, false, 1); act("You try to construct a waterwheel, but botch it completely.", ch, NULL, NULL, TO_CHAR); act("$n holds out a palm to the earth of the riverbank, but nothing happens.", ch, NULL, NULL, TO_ROOM); return; } check_improve(ch, NULL, gsn_constructwaterwheel, true, 1); // Create the waterwheel OBJ_DATA * wheel(create_object(get_obj_index(OBJ_VNUM_WATERWHEEL), 0)); wheel->level = ch->level; wheel->timer = 200 + (ch->level * 6); obj_to_room(wheel, ch->in_room); // Echoes act("You seize hold of the earth of the riverbank with pure magic, reshaping it to your will!", ch, NULL, NULL, TO_CHAR); act("$n holds out a palm to the earth of the riverbank, which begins to reshape itself in response!", ch, NULL, NULL, TO_ROOM); act("In just moments there stands a functioning waterwheel, which begins to crank from the force of the river!", ch, NULL, NULL, TO_ALL); // Apply cooldown AFFECT_DATA af = {0}; af.where = TO_AFFECTS; af.type = gsn_constructwaterwheel; af.location = APPLY_NONE; af.level = ch->level; af.duration = 360 - (UMAX(0, skill - 70) * 2); affect_to_char(ch, &af); }
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 do_herb( CHAR_DATA *ch, char *argument ) { HERB_IN_ROOM_DATA *temp; sh_int skill , herb_diff //trudnosc ziola , skill_roll; char arg1 [MAX_INPUT_LENGTH]; bool find = FALSE,notfinded = FALSE; if ( IS_NPC( ch ) ) return; argument = one_argument( argument, arg1 ); if ( !ch->in_room ) return; if ( ( skill = get_skill( ch, gsn_herbs_knowledge ) ) <= 0 ) { send_to_char( "Huh?\n\r", ch ); return; } if(room_is_dark(ch, ch->in_room )) { send_to_char( "Ciemno¶æ widze, ciemno¶æ!!!.\n\r", ch ); return; } if ( ch->mount ) { send_to_char( "Twój wierzchowiec w milczeniu zaczyna wcinaæ jakie¶ zielsko.\n\r", ch ); return; } //przeszukiwanie rooma kosztuje troche mova if ( ch->move <= 0 ) { act( "Jeste¶ zbyt zmêczon<&y/a/e> by szukaæ zió³.", ch, NULL, NULL, TO_CHAR ); return; } ch->move -= 1;//zjadamy move... Drake: -4 mv? Jeszcze powiedzmy przy bieganiu po lesie? // Czyli co, szukanie zió³ bardziej mêczy od pracy w kopalni?! =.= if ( ch->move < 0 ) { ch->move = 0; } //Brak zió³ w ROOMIE if( !(temp = ch->in_room->first_herb)){ act( "Badasz najbli¿sz± okolicê w poszukiwaniu jakich¶ zió³ ale nic nie znajdujesz.", ch, NULL, NULL, TO_CHAR ); act( "$n bada najbli¿sz± okolicê w poszukiwaniu jakich¶ zió³ ale nic nie znajduje.", ch, NULL, NULL, TO_ROOM ); return; }//koniec nie ma zió³ //lecimy po li¶cie zió³ // teraz mamy: skill = get_skill( ch, gsn_herbs_knowledge ); //skill gracz for(temp = ch->in_room->first_herb;temp;temp = temp->next) { herb_diff = herb_table[temp->herb].difficult; //trudnosc znalezienia ziola if(temp->herb_status > 1) continue; //znaczy ze juz zerwane lub proba byla //jesli tutaj to sprawdzamy czy uda sie zebrac if(skill >= herb_diff)//proba zerwania { //skill_roll = number_range(1, 100); skill_roll = number_range(1, 100-herb_diff); find = TRUE; if ( FALSE || !str_cmp( ch->name, "Agron" )) { print_char( ch, "\n\rRzut na skill:%d + trudnosc %d > skill = %d.\n\r",skill_roll,herb_diff,skill ); } if (skill_roll+herb_diff > skill ) //nie udany rzut na skill, po prostu koles chujowy skill ma { temp->herb_status = 3; if(notfinded == FALSE){ switch(number_range(1,2)){ case 1: { act( "Znajdujesz i probujesz zebraæ znalezione zio³o, ale w ostatniej chwili rozpada siê ono na nieu¿yteczne kawa³eczki.",ch, NULL, NULL, TO_CHAR ); act( "$n znajduje co¶ jednak w ostatniej chwili za³amuje rêce i rozsypuje dooko³a nieu¿yteczne szcz±tki.",ch, NULL, NULL, TO_ROOM ); break; } case 2: { act( "Bez problemu odnajdujesz i szybkim ruchem starasz siê zebraæ zio³o, jednak ³apiesz w z³ym miejscu i rozrywasz je na kilka bezwarto¶ciowych czê¶ci.",ch, NULL, NULL, TO_CHAR ); act( "$n bez problemu odnajduje i zrywa jak±¶ ro¶linê, ta jednak rozpada siê w jego rêkach.",ch, NULL, NULL, TO_ROOM ); break; } } notfinded = TRUE; } WAIT_STATE( ch, 4 ); continue; } else // zrywamy! { herb_to_char(ch,temp); temp->herb_status = 2; WAIT_STATE( ch, 4 ); } } else continue; } /* obj = create_object( pHerb->herb, FALSE ); act( "Badasz najbli¿sz± okolicê w poszukiwaniu jakich¶ zió³ i po chwili natrafiasz na $h.", ch, obj, NULL, TO_CHAR ); act( "$n bada najbli¿sz± okolicê w poszukiwaniu jakich¶ zió³ i po chwili natrafia na co¶.", ch, obj, NULL, TO_ROOM ); obj_to_char( obj, ch ); */ WAIT_STATE( ch, 24 ); if (!find)//czyli na koniec jesli przelecialo liste i nic nie zostalo znalezione { act( "Badasz najbli¿sz± okolicê w poszukiwaniu jakich¶ zió³ ale nic nie znajdujesz.", ch, NULL, NULL, TO_CHAR ); act( "$n bada najbli¿sz± okolicê w poszukiwaniu jakich¶ zió³ ale nic nie znajduje.", ch, NULL, NULL, TO_ROOM ); return; } //cos znalazl ale nie zebral if(notfinded) check_improve( ch, NULL, gsn_herbs_knowledge, FALSE, 12 ); //tu skill jesli sie udalo, wieksza szansa na nauczenie else check_improve( ch, NULL, gsn_herbs_knowledge, TRUE, 10 ); return; }