/** * This is the training hall inherit. * @author Shaydz */ #include <skills.h> #include <tune.h> #include <config.h> private int cost_div; private int cost_mult; private string teaching_skill; private object teaching_person; int do_cost_to( string skill, int level ); int do_cost_by( string skill, int level ); int do_cost( string skill ); int do_advance( string skill ); int do_advance_to( string skill, int num ); int do_advance_by( string skill, int num ); /** @ignore yes */ void create() { TO->add_help_file("training_hall"); cost_div = COST_DIV; cost_mult = 100; } /* create() */ /** @ignore yes */ void init() { add_command("advance", "<string>", (: do_advance($4[0]) :) ); add_command("advance", "<string> to <number>", (: do_advance_to( $4[0], $4[1] ) :) ); add_command("advance", "<string> by <number>", (: do_advance_by( $4[0], $4[1] ) :) ); add_command("cost", "<string>", (: do_cost($4[0]) :) ); add_command("cost", "<string> to <number>", (: do_cost_to($4[0], $4[1]) :) ); add_command("cost", "<string> by <number>", (: do_cost_by($4[0], $4[1]) :) ); } /* init() */ /** * @ignore yes * Points of interest: * cost_div -> zero gives cost_mult = 10 * cost_div = COST_DIV gives cost_mult = 100 * cost_div -> infinity gives cost_mult = 1000 */ void set_cost_div( int number ) { cost_div = number; /* stands in for infinity */ if( !cost_div ) cost_mult = 1000; else cost_mult = 10 + ( 990 * cost_div ) / ( 10 * COST_DIV + cost_div ); } /* set_cost_div() */ /** @ignore yes */ int query_skill_cost( string skill, int offset ) { float base, total; string *next; next = (string *)SKILL_OB->query_immediate_children( skill ); if( !sizeof( next ) ) { base = (float)STD_GUILD_OBJ->query_skill_cost( skill, TP ); total = base; total *= ( STD_COST * cost_mult ) / 500; total *= ( (int)TP->query_skill( skill ) + offset ) / LEVEL_DIV + 1; total += 30 * base; // this is the new, increased skill cost. return to_int( total * exp( ( TP->query_skill( skill ) + offset ) / 150.0 ) ); } foreach( skill in next ) total += query_skill_cost( skill, offset ); return total; } /* query_skill_cost() */ /** @ignore yes */ int do_advance_internal( string skill, int to, int by ) { string *bits; string skill_name; string outer_name; string place; int lvl; int max_lvl; int tmp; int total_xp; int p_val; int i; place = TO->query_property( "place" ); if(!place) place = "default"; bits = explode( implode( explode( skill, " " ), "." ), "." ); if(strlen(bits[0])==2){ if( bits[0][0..1]!=teaching_skill[0..1] ) { add_failed_mess( "You cannot advance "+skill+" here!\n" ); return 0; } }else{ if( (bits[0]!=teaching_skill) ) { add_failed_mess( "You cannot advance "+skill+" here!\n" ); return 0; } } if( !( skill_name = (string)SKILL_OB->query_skill( bits ) ) ) { add_failed_mess( "The skill "+ skill +" does not exist.\n" ); return 0; } lvl = (int)TP->query_skill( skill_name ); if( !by && to ) by = to - lvl; if( by <= 0 ) { if ( by == 0 ) add_failed_mess( "You are already at level "+ lvl +" at "+ skill_name +".\n" ); else add_failed_mess( "You cannot regress below your current " "skill level!\n" ); return 0; } if( SKILL_OB->query_only_leaf(skill_name) ) { if( sizeof( (mixed)SKILL_OB->query_immediate_children(skill_name) ) ) { add_failed_mess("You can only advance the outer skills " "(eg: general.riding.horse), " "not the internal " "skills (eg: general.riding, or general).\n"); return 0; } } else { bits = explode( skill_name, "." ); if ( sizeof( bits ) > 1 ) { outer_name = implode( bits[ 0 .. sizeof( bits ) - 2 ], "." ); if ( ( ( sizeof( bits ) - 1 ) * 5 ) > (int)TP->query_skill( outer_name ) ) { add_failed_mess( "You are not at a high enough level in " + outer_name + " to advance "+ skill_name +" yet.\n"); return 0; } } } if (!SKILL_OB->query_allowed_to_teach(skill_name)) { add_failed_mess("You cannot learn '"+skill_name+"' from here.\n"); return 0; } max_lvl = (int)STD_GUILD_OBJ->query_skill_max_level( skill_name,TP ); if ( lvl >= max_lvl ) { add_failed_mess( "You cannot advance in "+skill_name+" any further here.\n"); return 0; } p_val = (int)TP->query_value_in( place ); if ( place != "default" ) { p_val += (int)TP->query_value_in( "default" ); } for ( i = 0; i < by; i++ ) { tmp = query_skill_cost( skill_name, i ); if ( (int)TP->query_xp() < tmp + total_xp ) { if ( !i ) { add_failed_mess( "Your lack of experience prevents you improving "+ skill_name +".\n" ); return 0; } else { write( "Your lack of experience prevents you taking all the " "advancement you requested in "+ skill_name +". You are " "only trained up to level "+ ( i + lvl ) +".\n" ); } break; } if ( ( lvl + i ) >= max_lvl ) { write( "This training hall hasn't the resources to train you as far as "+ "you requested in "+ skill_name +". It trains you to level "+ max_lvl +".\n" ); break; } total_xp += tmp; } if (!total_xp) { return notify_fail("OOpps, something has gone wrong.\n"); } TP->adjust_xp( -total_xp ); TP->add_skill_level( skill_name, i, total_xp ); TP->dest_hide_shadow(); event( TO, "guild_advance", bits, lvl, lvl+i ); write("You advance your skill in "+ skill_name +" from "+ lvl +" to "+ ( lvl + i )+" for "+total_xp+" xp.\n"); say( (string)TP->one_short() +" $V$0=advances,advance$V$ "+ "$V$0=" + TP->query_possessive() + ",their$V$ skills.\n"); return 1; } /* do_advance_internal() */ /** @ignore yes */ int do_advance( string skill ) { return do_advance_internal( skill, 0, 1 ); } /* do_advance() */ /** @ignore yes */ int do_advance_by( string skill, int num ) { return do_advance_internal( skill, 0, num ); } /* do_advance_by() */ /** @ignore yes */ int do_advance_to( string skill, int num ) { return do_advance_internal( skill, num, 0 ); } /* do_advance_to() */ /** @ignore yes */ int check_primaries( string lpath, string g_o ) { int i; string dummy, *primaries; primaries = (string *)g_o->query_skills(); if ( member_array( lpath, primaries ) != -1 ) return 1; for ( i = 0; i < sizeof( primaries ); i++ ) if ( sscanf( primaries[ i ], lpath +".%s", dummy ) ) return 1; return 0; } /* check_primaries() */ /** @ignore yes */ string rec_cost( mixed arr, string path, int depth, string g_o, int primaries, int only_leaf, int brief ) { int i, depth_gap, ndots, o_l, tmp, lvl, max_lvl; string str, lpath; str = ""; depth_gap = (depth - 1) * 2; ndots = 19 - depth_gap; for( i = 0; i < sizeof(arr); i += SKILL_ARR_SIZE ) { lpath = path + arr[i]; lvl = (int)TP->query_skill(lpath); max_lvl = ( !g_o ? 5 : (int)g_o->query_skill_max_level( lpath,TP ) ); o_l = only_leaf; if( depth == 1 || primaries ) o_l = SKILL_OB->query_only_leaf( lpath ); if( lvl >= max_lvl ) { if ( (!primaries || check_primaries( lpath, g_o ) ) && !brief ) { str += sprintf( "%*'| 's%-*'.'s%4d/%3d mastered\n", depth_gap, "", ndots, arr[ i ], lvl, max_lvl ); } } else { if( (!primaries && (!o_l || !sizeof(arr[ i + SKILL_BIT]) ) ) || check_primaries( lpath, g_o ) ) { if( ( o_l && sizeof(arr[i + SKILL_BIT]) ) || !SKILL_OB->query_allowed_to_teach(lpath) ) { str += sprintf( "%*'| 's%-*'.'s\n", depth_gap, "", ndots+18, arr[ i ] ); } else { tmp = query_skill_cost( lpath, 0 ); str += sprintf( "%*'| 's%-*'.'s%4d/%3d %6d xp\n", depth_gap, "", ndots, arr[ i ], lvl, max_lvl, tmp); } } else if( !primaries && o_l ) { str += sprintf( "%*'| 's%-*'.'s\n", depth_gap, "", ndots+18, arr[ i ] ); } } if( ( lvl >= depth * 5 ) || primaries || o_l ) { reset_eval_cost(); str += rec_cost( arr[ i + SKILL_BIT ], lpath +".", depth + 1, g_o, primaries, o_l, brief ); } } return str; } /* rec_cost() */ /** @ignore yes */ int do_cost_internal( string skill, int to, int by ) { string *bits; string skill_name; string outer_name; int lvl; int max_lvl; int i; int tmp; bits = explode( implode( explode( skill, " " ), "." ), "." ); if( strlen(bits[0]) == 2 ){ if( bits[0][0..1] != teaching_skill[0..1] ) { add_failed_mess("You cannot advance "+skill+" here, so we can't " "tell you how much it would cost!\n"); return 0; } }else{ if( (bits[0]!=teaching_skill) ) { add_failed_mess( "You cannot advance "+skill+" here!\n" ); return 0; } } if ( !( skill_name = (string)SKILL_OB->query_skill( bits ) ) ) { add_failed_mess( "There is no such skill as " + skill + ".\n" ); return 0; } lvl = (int)TP->query_skill( skill_name ); if ( !by && to ) by = to - lvl; if ( by == 0 ) { add_failed_mess("It won't cost you anything to stay at the same level!\n"); return 0; } if ( by < 0 ) { add_failed_mess("We can't give refund xp for regressing skills!\n"); return 0; } bits = explode( skill_name, "." ); if ( sizeof( bits ) > 1 ) { if (SKILL_OB->query_only_leaf(skill_name)) { if (sizeof((mixed)SKILL_OB->query_immediate_children(skill_name))) { notify_fail("You can only advance the outer skills (eg: " "general.riding.horse), not the internal skills " "(eg: general.riding, or general).\n"); return 0; } } else { outer_name = implode( bits[ 0 .. sizeof( bits ) - 2 ], "." ); if ( ( ( sizeof( bits ) - 1 ) * 5 ) > (int)TP->query_skill( outer_name ) ) { notify_fail( "You are not at a high enough level in "+ outer_name + " to advance "+ skill_name +" yet.\n"); return 0; } } } if (!SKILL_OB->query_allowed_to_teach(skill_name)) { notify_fail("You cannot learn '"+skill_name+"' from here.\n"); return 0; } max_lvl = (int)STD_GUILD_OBJ->query_skill_max_level( skill_name,TP ); if ( lvl >= max_lvl ) { notify_fail( "Our teachers prevent you even considering advancing "+ skill_name +" above level "+ max_lvl +".\n" ); return 0; } for ( i = 0;i < by; i++ ) { if ( ( lvl + i ) >= max_lvl ) { write( "Our teachers prevent you considering all the advancement you "+ "requested. You can only advance up to level "+ max_lvl +" in "+ skill_name +" here.\n"); break; } tmp += query_skill_cost( skill_name, i ); } printf( "It would cost you %d xp to raise %s from level %d to %d.\n", tmp, skill_name, lvl, ( lvl + i ) ); return 1; } /* do_cost_internal() */ /** @ignore yes */ int do_cost( string skill ) { string *bits; mixed arr; int i; string list; bits = explode( implode( explode( skill, " " ), "." ), "." ); if(strlen(bits[0])==2){ if( bits[0][0..1]!=teaching_skill[0..1] ) { add_failed_mess( "You cannot advance "+skill+" here!\n" ); return 0; } } else { if( (bits[0]!=teaching_skill) ) { add_failed_mess( "You cannot advance "+skill+" here!\n" ); return 0; } } arr = (mixed)SKILL_OB->query_skills(); if ( !arr ) { notify_fail( "Hmmm, we appear to have an error here.\n" ); return 0; } i = member_array( skill, arr ); if ( i != -1 ) { list = sprintf( "%-*'='s\n", (int)TP->query_cols()-1, "======SKILLS=======Cur/Max==For Next" ); list += sprintf( "%#*-s\n", (int)TP->query_cols(), rec_cost( arr[ i + 3 ], skill +".", 2, STD_GUILD_OBJ, 0, 0, 0 ) ); list += sprintf( "%*'='|s\n", (int)TP->query_cols()-1, "> You have "+ (int)TP->query_xp() + " points to spend. <" ); TP->more_string( list, capitalize( skill ), 1 ); return 1; } return do_cost_internal(skill, 0, 1); } /* do_cost() */ /** @ignore yes */ int do_cost_to( string skill, int num ) { return do_cost_internal( skill, num, 0 ); } /* do_cost_to() */ /** @ignore yes */ int do_cost_by( string skill, int num ) { return do_cost_internal( skill, 0, num ); } /* do_cost_to() */ /** @ignore yes */ varargs void set_teaching_skill( string skill ) { teaching_skill = skill; } /** @ignore yes */ string query_teaching_skill() { return teaching_skill; }