#include <tasks.h> #include <weapon.h> // Remove this to disable logging to /log/BAD_WEAPONS // and creator informs when judging #define DEBUG 1 #define COST 25 #define SKILL "general.evaluating.weapons" #define QUEST_AVE 140 #define QUEST_MAX 570 #define LEARN 5 #define TEACH 50 inherit COMMAND_BASE; nosave string *_attack_types = ({ "blunt", "sharp", "pierce" }); varargs int *calc_rating( object weapon, object player ) { int i, size; int ave = 0; int max = 0; int *damage; mixed *data; data = (mixed *)weapon->query_attack_data(); if ( !( size = sizeof( data ) ) ) return ({ 0, 0 }); for ( i = 0; i < size; i += W_ARRAY_SIZE ) { if ( member_array( data[ i + W_TYPE ], _attack_types ) == -1 ) continue; damage = data[ i + W_DAMAGE ]; ave += ( data[ i + W_CHANCE ] * ( damage[ F_FIXED ] + ( damage[ F_NUM ] * ( 1 + damage[ F_DIE ] ) ) / 2 ) ) / 100; max += damage[ F_FIXED ] + damage[ F_NUM ] * damage[ F_DIE ]; } #ifdef DEBUG debug_printf("[%s - ave: %d max: %d]\n", weapon->short(), ave, max ); #endif return ({ ave, max }); } /* calc_rating() */ void judge_against( object player, object first, object second ) { int grain, rating, rating_1, rating_2, difficulty, margin, *data_1, *data_2; data_1 = calc_rating( first, player ); data_2 = calc_rating( second, player ); difficulty = data_1[ 0 ] - data_2[ 0 ]; if ( difficulty > 0 ) difficulty = QUEST_AVE - difficulty; else difficulty = QUEST_AVE + difficulty; margin = ( difficulty + ( difficulty * ( data_1[ 1 ] + data_2[ 1 ] ) ) / ( 2 * QUEST_MAX ) ) / 2; switch ( TASKER->perform_task(this_player(), SKILL, difficulty - 25, TM_COMMAND) ) { case AWARD: tell_object( player, "%^YELLOW%^"+ replace( ({ "As you scrutinise $weapons$, you " "recognise an aspect of judging that you didn't use before.", "You realise something else that you can use to better judge " "$weapons$.", "As you inspect $weapons$, you feel a sense " "of surety in your judgement." })[ random( 3 ) ], "$weapons$", query_multiple_short( ({ first, second }), "the" ) ) + "%^RESET%^\n" ); case SUCCEED: break; default: tell_object( player, "You examine "+ query_multiple_short( ({ first, second }), "the" ) + " closely, but you're not sure which is " "better.\n" ); return; } grain = sqrt( (int)this_player()->query_skill_bonus( SKILL ) ); if ( grain > 12 ) grain = 12; rating_1 = QUEST_AVE * data_1[ 1 ] + QUEST_MAX * data_1[ 0 ]; rating_1 = ( grain * rating_1 + QUEST_AVE * QUEST_MAX ) / ( 2 * QUEST_AVE * QUEST_MAX ); rating_2 = QUEST_AVE * data_2[ 1 ] + QUEST_MAX * data_2[ 0 ]; rating_2 = ( grain * rating_2 + QUEST_AVE * QUEST_MAX ) / ( 2 * QUEST_AVE * QUEST_MAX ); rating = rating_1 - rating_2; if ( rating > 0 ) rating++; else rating--; rating = 6 + rating / 2; if ( rating > 12 ) rating = 12; if ( rating < 0 ) rating = 0; if ( rating == 6 ) { tell_object( player, "You think that " + query_multiple_short( ({ first, second }), "the" ) + " are exactly the same.\n" ); return; } tell_object( player, "You think that " + first->the_short() +" is "+ ({ "amazingly worse", "extremely worse", "very much worse", "much worse", "worse", "a bit worse", "!", "a bit better", "better", "much better", "very much better", "extremely better", "amazingly better" })[ rating ] +" than "+ second->the_short() +".\n" ); } /* judge_against() */ void judge_weapon( object player, object weapon ) { int grain, rating, margin, *data; data = calc_rating( weapon, player ); margin = ( data[ 0 ] + ( data[ 0 ] * data[ 1 ] ) / QUEST_MAX ) / 2; switch ( TASKER->perform_task(this_player(), SKILL, data[ 0 ] + 25, TM_COMMAND) ) { case AWARD: tell_object( player, "%^YELLOW%^"+ replace( ({ "As you scrutinise $weapon$, you " "recognise an aspect of judging that you didn't use before.", "You realise something else that you can use to judge " "$weapon$.", "As you inspect $weapon$, you feel a sense of " "surety in your judgement." })[ random( 3 ) ], "$weapon$", weapon->the_short() ) +"%^RESET%^\n" ); case SUCCEED: break; default: tell_object( player, "You think that " + weapon->the_short() + " is a good weapon, but you're not sure.\n" ); return; } grain = sqrt( player->query_skill_bonus( SKILL ) / 2 ); if ( grain > 14 ) grain = 14; rating = QUEST_AVE * data[ 1 ] + QUEST_MAX * data[ 0 ]; rating = ( grain * rating + QUEST_AVE * QUEST_MAX ) / ( 2 * QUEST_AVE * QUEST_MAX ); rating += 14 - grain; if ( rating > 14 ) { #ifdef DEBUG log_file( "BAD_WEAPON", "%s exceeds weapon specifications, rating is " "%d.\n", file_name( weapon ), rating ); #endif tell_object( player, "Please inform a creator that " + weapon->the_short() + " exceeds weapon specifications.\n" ); return; } tell_object( player, "You think that "+ weapon->the_short() +" is " + ({ "an atrocius", "an extremely poor", "a very poor", "a rather poor", "a poor", "a pretty poor", "a quite poor", "a reasonable", "a quite good", "a pretty good", "a good", "a rather good", "a very good", "an extremely good", "an excellent" })[ rating ] + " weapon.\n" ); } /* judge_weapon() */ int valid_weapon( object player, object ob ) { if ( living( ob ) ) { if ( ob == player ) { add_failed_mess( "You stare at your muscles for a moment, " "and decide that you're more than capable of destroying " "any enemy that decides to interfer with you.\n" ); return 0; } add_failed_mess( "You stare at $I for a while, but decide it " "would be better if you considered them instead.\n", ({ ob }) ); return 0; } if ( !ob->query_weapon() ) { add_failed_mess( "$C$$I is not a weapon.\n", ({ ob }) ); return 0; } return 1; } /* valid_weapon() */ int cmd( object first, object second ) { object *indirect_obs; int cost; function judge_func; if ( !valid_weapon( this_player(), first ) ) { return 0; } cost = COST; if ( second ) { if ( !valid_weapon( this_player(), second ) ) { return 0; } cost *= 2; indirect_obs = ({ first, second }); judge_func = (: judge_against :); } else { indirect_obs = ({ first }); judge_func = (: judge_weapon :); } if ( this_player()->query_specific_gp( "other" ) < cost ) { add_failed_mess( "You can't muster the energy to scrutinise " "$I at the moment.\n", indirect_obs ); return 0; } this_player()->adjust_gp( -cost ); call_out( judge_func, 0, this_player(), first, second ); add_succeeded_mess( "$N look$s closely at $I.\n", indirect_obs ); return 1; } /* cmd() */ mixed *query_patterns() { return ({ "<indirect:object'weapon'>", (: cmd( $1[0], 0 ) :), "<indirect:object'weapon'> against <indirect:object'weapon'>", (: cmd( $1[0][0], $1[1][0] ) :) }); } /* query_patterns() */