[Package Index | Mudlib Index | Effect Index]

File /obj/handlers/taskmaster.c

This handler gives access to the functions needed for the taskmaster system. Rewritten by Shrike to include degrees of success.

See also:
help::tasks .c

Written by Deutha

Includes

This class includes the following files /d/ram/task_mappings_triage.h, /d/am/task_mappings_triage.h, /include/task_mappings/adventuring.h, /include/minmax.h, /d/sur/task_mappings_triage.h, /include/task_mapper.h, /include/task_mappings/covert.h, /d/waterways/task_mappings_triage.h, /d/klatch/task_mappings_triage.h, /include/task_mappings/magic.h, /include/task_mappings/faith.h, /d/forn/task_mappings_triage.h, /include/task_mappings/crafts.h, /include/task_mappings/people.h, /d/cwc/task_mappings_triage.h, /include/tasks.h, /include/achievements.h, /include/task_mappings/fighting.h, /d/guilds/task_mappings_triage.h and /d/special/task_mappings_triage.h

Method index

Public Functions

These are functions that everyone can access.

attempt_task
varargs mixed attempt_task(int difficulty,
int bonus,
int upper,
mixed extra,
int degree)

Do not use this function. Use perform_task instead.

See also:
perform_task()


attempt_task_e
varargs mixed attempt_task_e(int difficulty,
int bonus,
int upper,
int half,
int degree)

Do not use this function. Use perform_task instead.

See also:
perform_task()


compare_skills
varargs mixed compare_skills(object offob,
string offskill,
object defob,
string defskill,
int modifier,
int off_tm_type,
int def_tm_type,
int degree,
int offperc,
int defperc)

This function will compare the skills of two objects and return which one won and if the winner got a TM. With equal skills the chances are 50/50 as to who will win. As the balance shifts so do the chances. Additionally a modifier can be applied to account for conditions favouring one or the other. This should be considered a percentage eg. -50 will add 50% to the defenders chances of winning.

Parameters:
offob - The attacking object
offskill - The name of the skill the attacker is using
deffob - The defending object
deffskill - The name of the skill the defender is using
modifier - The percentage modifier
off_tm_type - This should be one of the standard definitions in /include/tasks.h and is for the attacker
def_tm_type - This should be one of the standard definitions in /include/tasks.h and is for the defender
degree - Enable the degree-of-success code. If this is used, the return value becomes a class instead of an int.
offperc - A percentage that should be added to or removed from the attacker's skill, e.g. +100 doubles the skill, and -50% halves it.
defperc - A percentage that should be added to or removed from the defender's skill.

See also:
perform_task()

Example:
This is an example of the simpler, binary success/failure behaviour.

switch(TASKER->compare_skills(attacker, "fighting.melee.sword",
                              defender, "fighting.defence.parry",
                              25, TM_COMMAND, TM_FREE) {
case OFFAWARD:
  tell_object(attacker, "%^@tm%^You manage to grasp one of the "
                        "principles of slicing people up more firmly."
                        "%^RESET%^\n");
case OFFWIN:
  say(defender->one_short() + " loses an arm!\n");
  break;
case DEFAWARD:
  tell_object(defender, "%^@tm%^You feel better able to keep your arms "
                        "attached when parrying unarmed.%^RESET%^\n");
case DEFWIN:
  say(defender->one_short() + " keeps " + defender->query_possesive() +
      " arm attached.\n");
  break;
}

This is an example of the finer grained degree-of-success behaviour.

class tasker_result tr;

tr = (class tasker_result)TASKER->compare_skills(
  attacker, "fighting.melee.sword",
  defender, "fighting.defence.parry",
  25, TM_COMMAND, TM_FREE, 1 );

switch( tr->result ) {
case OFFAWARD:
  tell_object(attacker, "%^@tm%^You manage to grasp one of the "
                        "principles of slicing people up more firmly."
                        "%^RESET%^\n");
case OFFWIN:
  switch( tr->degree ) {
  case TASKER_MARGINAL:
    say( "You just barely scrape your opponent's hand.\n" );
    break;
  case TASKER_NORMAL:
    say( "You slice into your opponent's arm.\n" );
    break;
  case TASKER_EXCEPTIONAL:
    say( "You slice deeply into your opponent's muscle and sinew, and "
      "he screams in pain!\n" );
    break;
  case TASKER_CRITICAL:
    say( "You slice your opponent's arm clean off.  Blood spurts "
      "everywhere like a cherry slurpee machine gone insane!\n" );
    break;
  }
  break;
case DEFAWARD:
  tell_object(defender, "%^@tm%^You feel better able to keep your arms "
                        "attached when parrying unarmed.%^RESET%^\n");
case DEFWIN:
  switch( tr->degree ) {
     ...
     similar code in here...
     ...
  }
  break;
}

is_critical
int is_critical(int margin)

Figure out whether a given margin of success/failure will result in a critical or not. Takes an integer between -100 and 100, representing the margin by which a skillcheck succeeded, and does some logarithmic-type equations to figure out whether it should result in a critical or not.

Parameters:
margin - the margin of success.

Returns:
1 if the result is a critical, 0 otherwise.


load_me
void load_me()
lucky_achievements
void lucky_achievements(object player,
int level)

Adjust Lucky Sod achievements if appropriate. Called from perform_task() as well as various places in /global/group.c when TMs are shared or gained via the inspiration mechanism.

Parameters:
player - the player to be adjusted
level - the TM level - this is the level *before* the skill was increased.


perform_task
varargs mixed perform_task(object person,
string skill,
int difficulty,
int tm_type,
int degree,
int gp_cost)

This function will perform a task. It handles all the stuff about looking up the skill, and giving the tm advance, but doesn't give any messages to the player, you'll have to do that. Please note that while the taskmaster system tries to prevent players gaining too many TMs these checks only work in conjunction with well written TM checks. Giving out infinite TM checks will result in players gaining too many TMs. In other words, do not write TM checks into your code unless you really know what you are doing. As a general rule no task that can be repeated ad infinitum with no limiting factor should give out TMs. The majority of TM attempts should use GPs to conotate an active task that cannot be repeated constantly at no cost. If you set the 'degree' parameter to 1, it will return a 3-element class instead of the standard binary success/failure result.

Parameters:
person - the one attempting the task (could be any living thing)
skill - the skill tested against
difficulty - the lowest bonus where the attempt can succeed
tm_type - This should use one of the standard definitions in /include/tasks.h. They are: TM_FIXED - for use where the difficulty is a fixed value. Because the difficulty is fixed the range of skill bonuses that can be TMed is fixed so this is a very generous value and should be used with great care. TM_FREE - for use when the TM attempt doesn't cost anything. All the other TM types with the exception of TM_NONE and possibly TM_CONTINUOUS should use GPs. If your task does not use GPs it should generally use TM_NONE OR TM_FREE. Since the TM is free there needs to be some other factor that restricts the frequency of attempts, for example consumed materials. Using artificial time restrictions is not a good way to limit these attempts. TM_CONTINUOUS - for use in continuous actions eg. combat or sneak. In general these use up GPs though they may have other limiting factors, such as combat requiring an opponent and causing damage. TM_COMMAND - for use with guild commands. This should only be used if you're writing a guild command that uses GPs. The precise TM chances are calculated based on the skill to maintain balance. TM_RITUAL & TM_SPELL - when the action is a spell. These two special cases are used by the ritual code and the spell code to allow those actions to have specifically calculated chances. TM_NONE - when you want there to be no chance of a TM. Sometimes it is desirable to test the outcome of an action using the TM system but where the action does not deserve a TM chance due to its passive or repeatable nature. In such a case TM_NONE is the correct modifier.
degree - Whether or not to use the degree of success code
gp_cost - The amount of GP that will be consumed by this attempt.

Returns:
BARF if something screwed up, AWARD if the task succeeded, and should give an advance, SUCCEED if it succeeded, FAIL if it failed. If the degree of success code is used, it will pass out a 3-element class. If a gp cost is specified and the player does not have enough gp, NO_GP is returned. The gp check assumes the points skill from the same tree as the skill to be checked.

See also:
compare_skills() and tasker_result .c

Example:
This is an example of the simpler, binary success/failure behaviour.

switch(TASKER->perform_task( person, "covert.manipulation.stealing",
                             300, TM_COMMAND ) ) {
 case AWARD :
   tell_object( person, "%^@tm%^You manage to grasp the principles "
               "of stealing more firmly.%^RESET%^\n" );
   // Note, no break;
 case SUCCEED :
   // Whatever happens when it succeeds
   break;
 default :
   // Whatever happens when it fails
}

This is an example of the finer grained degree-of-success behaviour.

class tasker_result tr;

tr = (class tasker_result)TASKER->perform_task( person,
  "other.direction", 300, TM_FREE, 1, 50 );
switch( tr->result ) {
case AWARD:
  tell_object(attacker, "%^@tm%^You feel very aligned!%^RESET%^\n" );
case SUCCEED:
   switch( tr->degree ) {
   case TASKER_MARGINAL:
      say( "You think he went thataway. Maybe.\n" );
      break;
   case TASKER_NORMAL:
      say( "You're pretty sure he went that way.\n" );
      break;
   case TASKER_EXCEPTIONAL:
      say( "He definitely went thataway!\n" );
      break;
   case TASKER_CRITICAL:
      say( "Your surity that he went thataway is so powerful that even "
        "if he didn't go thataway, he'll be in that direction.\n" );
      break;
  }
  break;
case FAIL:
  switch( tr->degree ) {
     ...
     Boy, it's a good thing I've already explained this, or I'd be
     pretty hard-pressed to think of an example of a critical failure
     for other.direction.  You get the idea.
     ...
  }
  break;
}

save_me
varargs void save_me(int now)
set_control
void set_control(mixed * args)

This function should only be used in the very rare situations where the last skill checked with query_skill_bonus() wasn't the one relevant for the task attempt.

Parameters:
args - an array consisting of ({ object player, string skill })


success_probability
int success_probability(int difficulty,
int bonus,
int tm_type)

This calculates the probability of a skill check succeeding, in 1/1000. If it returns 500, it's 50% fail or succeed, if it returns 1000 it's success every time, etc.

Parameters:
difficulty - The difficulty of the skill check
bonus - The bonus at which the skill check is attempted
tm_type - What kind of skill check, TM_FIXED, TM_COMMAND etc

Returns:
The probability of the check succeeding, -1 if anything failed


write_back_trace
void write_back_trace(string skill,
string trace)