예제 #1
0
        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;
        }
예제 #2
0
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);
}
예제 #3
0
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;
}
예제 #5
0
파일: mount.c 프로젝트: KillerMud/Source
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;
}
예제 #6
0
파일: mount.c 프로젝트: KillerMud/Source
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;
}
예제 #7
0
파일: track.c 프로젝트: blanciq/bq-killer
//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 );
}
예제 #8
0
파일: track.c 프로젝트: blanciq/bq-killer
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;
}
예제 #9
0
/*
 * 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
예제 #10
0
파일: track.c 프로젝트: Sembiance/kotrd
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;
}
예제 #11
0
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);
}
예제 #12
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;
}
예제 #13
0
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);
    }
}
예제 #14
0
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);
}
예제 #15
0
/*
 * 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);
}
예제 #16
0
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);
}
예제 #17
0
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);
}
예제 #18
0
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);
    }
}
예제 #19
0
파일: herbs.c 프로젝트: KillerMud/Source
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;
}