/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik Strfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ /*************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * ***************************************************************************/ #if defined(macintosh) #include <types.h> #include <time.h> #else #include <sys/types.h> #include <sys/time.h> #endif #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include "merc.h" #include "interp.h" #include "recycle.h" /* * Lookup a skill by name. */ int skill_lookup (const char *name) { int sn; for (sn = 0; sn < MAX_SKILL; sn++) { if (skill_table[sn].name == NULL) break; if (LOWER (name[0]) == LOWER (skill_table[sn].name[0]) && !str_prefix (name, skill_table[sn].name)) return sn; } return -1; } /* skill_driver: * Does a skill. Checks for targets, shows messages, performs the skill. * Returns true if the character completes the skill. */ bool skill_driver (CHAR_DATA * ch, char *argument, int sn) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; void *vo; int target, sn_target; CHAR_DATA *victim; OBJ_DATA *obj; if (sn < 1) return FALSE; if (ch->position < skill_table[sn].minimum_position) { sendch ("You can't do that in your current position.\n\r", ch); return FALSE; } if (get_skill(ch, sn) < 1) { sendch ("What?\n\r", ch); return FALSE; } argument = one_argument (argument, arg1); one_argument (argument, arg2); // Switch them if needed if (!str_cmp(arg1, "release")) { char t[MAX_INPUT_LENGTH]; sprintf(t, arg2); sprintf(arg2, arg1); sprintf(arg1, t); } /* * Locate targets. */ victim = NULL; obj = NULL; vo = NULL; target = TARGET_NONE; sn_target = skill_table[sn].target; // Look for skills whose targets switch at certain skill levels if (sn_target == TAR_HYBRID6) { if (get_skill(ch, sn) > 5 && !str_cmp(arg1, "all")) sn_target = TAR_AREA_OFF; else sn_target = TAR_CHAR_OFFENSIVE; } switch (sn_target) { default: logstr (LOG_BUG, "skill_driver: bad target for sn %d.", sn); return FALSE; case TAR_IGNORE: case TAR_AREA_OFF: vo = NULL; target = TARGET_NONE; break; case TAR_CHAR_OFFENSIVE: if (arg1[0] == '\0') { if ((victim = ch->fighting) == NULL) { sendch ("Direct that at whom?\n\r", ch); return FALSE; } } else { if ((victim = get_char_room (ch, NULL, arg1)) == NULL) { sendch ("They aren't here.\n\r", ch); return FALSE; } } if (ch == victim) { sendch( "You can't do that to yourself.\n\r", ch ); return FALSE; } if (IS_NPC (victim) && victim->fighting != NULL && !is_same_group (ch, victim->fighting)) { sendch ("Kill stealing is not permitted.\n\r", ch); return FALSE; } if (!IS_NPC (ch)) { if (is_safe (ch, victim) && victim != ch) { sendch ("Not on that target.\n\r", ch); return FALSE; } check_killer (ch, victim); } if (IS_AFFECTED (ch, AFF_CHARM) && ch->master == victim) { sendch ("You can't do that on your own follower.\n\r", ch); return FALSE; } vo = (void *) victim; target = TARGET_CHAR; break; case TAR_CHAR_DEFENSIVE: if (arg1[0] == '\0') { victim = ch; } else { if ((victim = get_char_room (ch, NULL, arg1)) == NULL) { sendch ("They aren't here.\n\r", ch); return FALSE; } } vo = (void *) victim; target = TARGET_CHAR; break; case TAR_CHAR_SELF: if (arg1[0] != '\0' && !is_name (arg1, ch->name)) { sendch ("You cannot do that on another.\n\r", ch); return FALSE; } vo = (void *) ch; target = TARGET_CHAR; break; case TAR_OBJ_INV: if (arg1[0] == '\0') { sendch ("What object should that be done on?\n\r", ch); return FALSE; } if ((obj = get_obj_carry (ch, arg1, ch)) == NULL) { sendch ("You are not carrying that.\n\r", ch); return FALSE; } vo = (void *) obj; target = TARGET_OBJ; break; case TAR_OBJ_CHAR_OFF: if (arg1[0] == '\0') { if ((victim = ch->fighting) == NULL) { sendch ("Do that on whom or what?\n\r", ch); return FALSE; } target = TARGET_CHAR; } else if ((victim = get_char_room (ch, NULL, arg1)) != NULL) { target = TARGET_CHAR; } if (target == TARGET_CHAR) { /* check the sanity of the attack */ if (is_safe_spell (ch, victim, FALSE) && victim != ch) { sendch ("Not on that target.\n\r", ch); return FALSE; } if (IS_AFFECTED (ch, AFF_CHARM) && ch->master == victim) { sendch ("You can't do that on your own follower.\n\r", ch); return FALSE; } if (!IS_NPC (ch)) check_killer (ch, victim); vo = (void *) victim; } else if ((obj = get_obj_here (ch, NULL, arg1)) != NULL) { vo = (void *) obj; target = TARGET_OBJ; } else { sendch ("You don't see that here.\n\r", ch); return FALSE; } break; case TAR_OBJ_CHAR_DEF: if (arg1[0] == '\0') { vo = (void *) ch; target = TARGET_CHAR; } else if ((victim = get_char_room (ch, NULL, arg1)) != NULL) { vo = (void *) victim; target = TARGET_CHAR; } else if ((obj = get_obj_carry (ch, arg1, ch)) != NULL) { vo = (void *) obj; target = TARGET_OBJ; } else { sendch ("You don't see that here.\n\r", ch); return FALSE; } break; } if (ch->pl < 1) { sendch ("You're too exhausted.\n\r", ch); return FALSE; } // Use a ki_loss value based on the skill // Ki loss. // If its a charge type skill, make the initial loss much greater if (skill_table[sn].type == SKILL_CHARGE) ki_loss(ch, skill_table[sn].ki_mod*5); else ki_loss(ch, skill_table[sn].ki_mod); // Message if the skill is started if (skill_table[sn].msg_immediate1) act(skill_table[sn].msg_immediate1,ch,NULL,NULL,TO_CHAR); if (skill_table[sn].msg_immediate2) act(skill_table[sn].msg_immediate2,ch,NULL,NULL,TO_ROOM); // Make the char wait, and get the skill ready to fire (or fire it) if (skill_table[sn].type == SKILL_DELAY) { ch->wait_skill = skill_table[sn].wait; ch->wait_skill_sn = sn; ch->wait_skill_vo = vo; ch->wait_skill_target = target; } else if (skill_table[sn].type == SKILL_IMM) { wait (ch, skill_table[sn].wait); (*skill_table[sn].skill_fun) (ch, vo, target); } else if (skill_table[sn].type == SKILL_CHARGE) { ch->wait_skill = 0; ch->charge = 1; ch->wait_skill_sn = sn; ch->wait_skill_vo = vo; ch->wait_skill_target = target; } if ((sn_target == TAR_CHAR_OFFENSIVE || (sn_target == TAR_OBJ_CHAR_OFF && target == TARGET_CHAR)) && victim != ch && victim->master != ch && victim->fighting == NULL && IS_AWAKE(victim) && !IS_AFFECTED (victim, AFF_CALM) ) { check_killer (victim, ch); begin_combat (victim, ch); } else if (sn_target == TAR_AREA_OFF) { CHAR_DATA *vch; for (vch = ch->in_room->people; vch; vch = vch->next_in_room) { if (IS_NPC(vch) && vch->fighting == NULL && !IS_AFFECTED (vch, AFF_CALM) && !IS_AFFECTED (vch, AFF_CHARM) && IS_AWAKE (vch) && !IS_SET (vch->act, ACT_WIMPY) && !is_same_group(vch, ch) && can_see (vch, ch) ) { check_killer (vch, ch); begin_combat (vch, ch); break; } } } // Immediate "charged" attack if (skill_table[sn].type == SKILL_CHARGE && (!str_cmp(arg1, "release") || !str_cmp(arg2, "release")) ) { // Pulled from do_release act("You release!",ch,NULL,NULL,TO_CHAR); act("$n releases!",ch,NULL,NULL,TO_ROOM); if (skill_table[ch->wait_skill_sn].msg_delay1) act(skill_table[ch->wait_skill_sn].msg_delay1,ch,NULL,NULL,TO_CHAR); if (skill_table[ch->wait_skill_sn].msg_delay2) act(skill_table[ch->wait_skill_sn].msg_delay2,ch,NULL,NULL,TO_ROOM); if (skill_table[ch->wait_skill_sn].skill_fun) (*skill_table[ch->wait_skill_sn].skill_fun) (ch, ch->wait_skill_vo, ch->wait_skill_target); ch->charge = 0; ch->wait_skill_sn = 0; ch->wait_skill_vo = NULL; ch->wait_skill_target = 0; wait (ch, 3 * PULSE_SECOND); } return TRUE; } /* used to get new skills */ void do_gain (CHAR_DATA * ch, char *argument) { char buf[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; CHAR_DATA *trainer; int sn = 0; return; if (IS_NPC (ch)) return; /* find a trainer */ for (trainer = ch->in_room->people; trainer != NULL; trainer = trainer->next_in_room) if (IS_NPC (trainer) && IS_SET (trainer->act, ACT_GAIN)) break; if (trainer == NULL || !can_see (ch, trainer)) { sendch ("You can't do that here.\n\r", ch); return; } one_argument (argument, arg); if (arg[0] == '\0') { do_function (trainer, &do_say, "Pardon me?"); return; } if (!str_prefix (arg, "list")) { int col = 0; sprintf (buf, "%-18s %-5s %-18s %-5s %-18s %-5s\n\r", "skill", "cost", "skill", "cost", "skill", "cost"); sendch (buf, ch); for (sn = 0; sn < MAX_SKILL; sn++) { if (skill_table[sn].name == NULL) break; if (!ch->pcdata->learned[sn] && skill_table[sn].points > 0) { sprintf (buf, "%-18s %-5d ", skill_table[sn].name, skill_table[sn].points); sendch (buf, ch); if (++col % 3 == 0) sendch ("\n\r", ch); } } if (col % 3 != 0) sendch ("\n\r", ch); return; } /* else add a skill */ sn = skill_lookup (argument); if (sn > -1) { bool found; int psn, i; // If the skill has no cost, it can't be learned if (skill_table[sn].points < 1) return; if (ch->pcdata->learned[sn]) { act ("$N tells you 'You already know that skill!'", ch, NULL, trainer, TO_CHAR); return; } found = FALSE; for (i=0; i<MAX_PC_RACE; ++i) { if (skill_table[sn].race_prereq[i] == NULL && i == 0) { // If no races needed for this skill, return that the race was found found = TRUE; break; } else break; if (race_lookup(skill_table[sn].race_prereq[i]) == ch->race) { found = TRUE; break; } } if (!found) { act ("$N tells you 'Those of $t origin may not learn this skill.'", ch, race_table[ch->race].name, trainer, TO_CHAR); return; } if (ch->pl < skill_table[sn].pl_prereq) { act ("$N tells you 'Your powerlevel is not yet high enough.'", ch, NULL, trainer, TO_CHAR); return; } for (i=0; i<5; ++i) { if (skill_table[sn].skill_prereq[i] == NULL) break; psn = skill_lookup(skill_table[sn].skill_prereq[i]); if (skill_table[sn].skill_value[i] > ch->pcdata->learned[psn]) { act ("$N tells you 'Your ability in $t is not yet great enough.'", ch, skill_table[psn].name, trainer, TO_CHAR); return; } } for (i=0; i<MAX_STATS; ++i) { if (ch->perm_stat[i] < skill_table[sn].stat_prereq[i]) { char buf[MAX_STRING_LENGTH]; switch (i) { case STAT_STR: sprintf(buf, "strength"); break; case STAT_WIS: sprintf(buf, "wisdom"); break; case STAT_INT: sprintf(buf, "intelligence"); break; case STAT_DEX: sprintf(buf, "dexterity"); break; case STAT_CON: sprintf(buf, "constitution"); break; default: sprintf(buf, "!error!"); break; } act ("$N tells you 'Your $t is too low to learn this skill.'", ch, buf, trainer, TO_CHAR); return; } } /* add the skill */ ch->pcdata->learned[sn] = 1; act ("$N trains you in the art of $t.", ch, skill_table[sn].name, trainer, TO_CHAR); return; } act ("$N tells you 'I do not understand...'", ch, NULL, trainer, TO_CHAR); } /* RT spells and skills show the players spells (or skills) */ /* void do_spells (CHAR_DATA * ch, char *argument) { BUFFER *buffer; char arg[MAX_INPUT_LENGTH]; char spell_list[LEVEL_HERO + 1][MAX_STRING_LENGTH]; char spell_columns[LEVEL_HERO + 1]; int sn, level, min_lev = 1, max_lev = LEVEL_HERO, ki; bool fAll = FALSE, found = FALSE; char buf[MAX_STRING_LENGTH]; if (IS_NPC (ch)) return; if (argument[0] != '\0') { fAll = TRUE; if (str_prefix (argument, "all")) { argument = one_argument (argument, arg); if (!is_number (arg)) { sendch ("Arguments must be numerical or all.\n\r", ch); return; } max_lev = atoi (arg); if (max_lev < 1 || max_lev > LEVEL_HERO) { sprintf (buf, "Levels must be between 1 and %d.\n\r", LEVEL_HERO); sendch (buf, ch); return; } if (argument[0] != '\0') { argument = one_argument (argument, arg); if (!is_number (arg)) { sendch ("Arguments must be numerical or all.\n\r", ch); return; } min_lev = max_lev; max_lev = atoi (arg); if (max_lev < 1 || max_lev > LEVEL_HERO) { sprintf (buf, "Levels must be between 1 and %d.\n\r", LEVEL_HERO); sendch (buf, ch); return; } if (min_lev > max_lev) { sendch ("That would be silly.\n\r", ch); return; } } } } //initialize data for (level = 0; level < LEVEL_HERO + 1; level++) { spell_columns[level] = 0; spell_list[level][0] = '\0'; } for (sn = 0; sn < MAX_SKILL; sn++) { if (skill_table[sn].name == NULL) break; if ((level = skill_table[sn].skill_level[ch->class]) < LEVEL_HERO + 1 && (fAll || level <= ch->level) && level >= min_lev && level <= max_lev && ch->pcdata->learned[sn] > 0) { found = TRUE; level = skill_table[sn].skill_level[ch->class]; if (ch->level < level) sprintf (buf, "%-18s n/a ", skill_table[sn].name); else { ki = UMAX (skill_table[sn].min_ki, 100 / (2 + ch->level - level)); sprintf (buf, "%-18s %3d ki ", skill_table[sn].name, ki); } if (spell_list[level][0] == '\0') sprintf (spell_list[level], "\n\rLevel %2d: %s", level, buf); else { //append if (++spell_columns[level] % 2 == 0) strcat (spell_list[level], "\n\r "); strcat (spell_list[level], buf); } } } //return results if (!found) { sendch ("No spells found.\n\r", ch); return; } buffer = new_buf (); for (level = 0; level < LEVEL_HERO + 1; level++) if (spell_list[level][0] != '\0') add_buf (buffer, spell_list[level]); add_buf (buffer, "\n\r"); page_to_char (buf_string (buffer), ch); free_buf (buffer); } */ void do_skills (CHAR_DATA * ch, char *argument) { BUFFER *buffer; int sn; bool found=FALSE, bColumn1=TRUE; char buf[MAX_STRING_LENGTH]; char buf_temp[MAX_STRING_LENGTH]; if (IS_NPC (ch)) return; sprintf(buf, " "); for (sn = 0; sn < MAX_SKILL; sn++) { if (skill_table[sn].name == NULL) break; if (ch->pcdata->learned[sn] > 0) { found = TRUE; sprintf (buf_temp, "%-20s %2d.%-2.2d ", skill_table[sn].name, ch->pcdata->learned[sn], 100*ch->pcdata->skill_progress[sn]/(ch->pcdata->learned[sn]*15000)); strcat (buf, buf_temp); if ((bColumn1=!bColumn1)) strcat (buf, "\n\r "); } } /* return results */ if (!found) { sendch ("No skills found.\n\r", ch); return; } buffer = new_buf (); add_buf (buffer, "Skills:\n\r"); add_buf (buffer, buf); add_buf (buffer, "\n\r"); page_to_char (buf_string (buffer), ch); free_buf (buffer); } /* checks for skill improvement */ void check_improve (CHAR_DATA * ch, int sn, bool success, int multiplier, long long int llVictimPl) { //int gain; //int chance; char buf[100]; int gain; if (IS_NPC (ch)) return; if (sn <= 0 || sn >= MAX_SKILL //|| skill_table[sn].points == 0 || ch->pcdata->learned[sn] <= 0 || ch->pcdata->learned[sn] >= 10) return; /* skill is not known, or cant be increased (at max) */ gain = 2 * get_curr_stat (ch, STAT_INT) / multiplier; gain = UMIN(gain * 2, (((2 * llVictimPl * 100) / ch->pl) * gain) / 100); gain = ch->cur_pl * gain / 100; ch->pcdata->skill_progress[sn] += URANGE(1, gain, 100); if (ch->pcdata->skill_progress[sn] < ch->pcdata->learned[sn]*15000) return; if (success) sprintf (buf, "{CYou have become better at %s!{x\n\r", skill_table[sn].name); else sprintf (buf, "{CYou learn from your mistakes, and your %s improves!{x\n\r", skill_table[sn].name); sendch (buf, ch); ch->pcdata->learned[sn]++; ch->pcdata->skill_progress[sn] = 0; ch->train += UMAX(1, ch->pcdata->learned[sn] / 3); return; } /* if (wield != NULL) if (IS_WEAPON_STAT (wield, WEAPON_SHARP)) dam += dam * 1 / 2; if (get_eq_char (ch, WEAR_SHIELD) == NULL) // No shield = more dam = dam * 11 / 10; // Add some weapon bonus here: // Extra damage based on skills if (get_skill (ch, gsn_enhanced_damage) > 0) { // Extra enhanced damage if (number_percent() < 10 + get_skill (ch, gsn_enhanced_damage)*3) { check_improve (ch, gsn_enhanced_damage, TRUE, 5); dam *= UMAX(1, get_skill(ch, gsn_enhanced_damage)+1); } // Failed the check: normal damage else { check_improve (ch, gsn_enhanced_damage, TRUE, 6); // Worse chance to learn: didnt do a 'super' enchanced damage dam *= UMAX(1, (get_skill(ch, gsn_enhanced_damage)+1) / 2); } } */ // Returns a calculated value for chance to hit in melee based on powerlevel, // stats, skill and other conditions, for some skill long long int get_attackhit (CHAR_DATA *ch, int sn) { long long int value; value = get_curr_stat(ch, STAT_DEX); value += sqrt(ch->cur_pl * ch->pl / 100) / 15; value *= UMAX(1,get_skill(ch, sn) / 2); value += GET_HITROLL(ch); if (sn == gsn_heart_shot) value /= 2; else if (sn == gsn_eye_gouge) value /= 10; if (ch->position < POS_FIGHTING) value /= 2; if (IS_AFFECTED (ch, AFF_BLIND)) value -= value / 5; if (IS_AFFECTED (ch, AFF_FLYING)) value += value / 4; if (ch->stance == STANCE_OFFEN) value += value / 4; else if (ch->stance == STANCE_DEFEN) value -= value / 4; else if (ch->stance == STANCE_KAMIK) value += value / 6; // value = 3*value + (get_skill(ch, gsn_kamikaze)-1)*(value/4); // 3*value, +1 1/4 value per skill, after level 1 value = value * (ch->balance+1) / 5; if (ch->cur_pl < 1 && ch->ki < 1) value /= 50; value = 2 * ch->cur_pl * value / 100; return value; } long long int get_attackdam (CHAR_DATA *ch, int sn) { long long int value; value = get_curr_stat(ch, STAT_STR); value += sqrt(ch->cur_pl * ch->pl / 100) / 15; value *= UMAX(1,get_skill(ch, sn) / 2); value += GET_DAMROLL(ch); if (sn == gsn_throat_shot || sn == gsn_sweep || sn == gsn_eye_gouge) value = 1; else if (sn == gsn_knee) value /= 2; else if (sn == gsn_elbow) value /= 5; else if (sn == gsn_heart_shot) value *= 2; if (ch->position < POS_FIGHTING) value /= 2; value = UMAX(1, value); if (ch->stance == STANCE_OFFEN) value += value / 4; else if (ch->stance == STANCE_DEFEN) value -= value / 4; else if (ch->stance == STANCE_KAMIK) value = 4*value + (get_skill(ch, gsn_kamikaze)-1)*(value/4); // 3*value, +1 1/4 value per skill, after level 1 value = value * (ch->balance+1) / 5; value /= 2; if (ch->cur_pl < 1 && ch->ki < 1) value /= 50; value = 2 * ch->cur_pl * value / 100; return value; } long long int get_attackabsorb (CHAR_DATA *ch, int sn, int dam_type) { long long int value; value = get_curr_stat(ch, STAT_STR); value += sqrt(ch->cur_pl * ch->pl / 100) / 50; value *= UMAX(1,get_skill(ch, sn) / 2); // Armor! switch (dam_type) { case DAM_NONE: break; case DAM_PIERCE: value += ch->armor[AC_PIERCE] / 5; break; case DAM_BASH: value += ch->armor[AC_BASH] / 5; break; case DAM_SLASH: value += ch->armor[AC_SLASH] / 5; break; default: value += ch->armor[AC_EXOTIC] / 5; break; } if (!IS_AWAKE (ch)) value /= 4; else if (ch->position < POS_FIGHTING) value /= 2; if (ch->stance == STANCE_OFFEN) value -= value / 4; else if (ch->stance == STANCE_DEFEN) value += value / 4; else if (ch->stance == STANCE_KAMIK) value -= value / 2; if (IS_AFFECTED (ch, AFF_SANCTUARY)) value *= 2; if ((IS_AFFECTED (ch, AFF_PROTECT_EVIL) && IS_EVIL (ch)) || (IS_AFFECTED (ch, AFF_PROTECT_GOOD) && IS_GOOD (ch))) value += value / 4; if (ch->cur_pl < 1 && ch->ki < 1) value /= 50; value = value * (ch->balance+1) / 5; value = 2 * ch->cur_pl * value / 100; return value; } long long int get_attackdodge (CHAR_DATA *ch, int sn) { long long int value; value = get_curr_stat(ch, STAT_DEX); value += sqrt(ch->cur_pl * ch->pl / 100) / 15; value *= UMAX(1,get_skill(ch, sn) / 2); if (!IS_AWAKE (ch)) value /= 4; else if (ch->position < POS_FIGHTING) value /= 2; if (IS_AFFECTED (ch, AFF_BLIND)) value -= value / 5; if (IS_AFFECTED (ch, AFF_FLYING)) value += value / 4; if (ch->stance == STANCE_OFFEN) value -= value / 4; else if (ch->stance == STANCE_DEFEN) value += value / 4; else if (ch->stance == STANCE_KAMIK) value -= value / 2; if (ch->cur_pl < 1 && ch->ki < 1) value /= 50; value = value * (ch->balance+1) / 5; value = 2 * ch->cur_pl * value / 100; return value; } long long int get_kihit (CHAR_DATA *ch, int sn) { long long int value; value = get_curr_stat(ch, STAT_DEX); value += sqrt(ch->cur_pl * ch->pl / 100) / 15; value *= UMAX(1,get_skill(ch, sn) / 2); value += GET_HITROLL(ch); if (ch->position < POS_FIGHTING) value /= 2; if (IS_AFFECTED (ch, AFF_BLIND)) value -= value / 5; if (IS_AFFECTED (ch, AFF_FLYING)) value += value / 4; if (sn == gsn_scattershot) value /= 2; if (ch->cur_pl < 1 && ch->ki < 1) value /= 50; value = value * (ch->balance+1) / 5; value = 2 * ch->cur_pl * value / 100; return value; } long long int get_kidam (CHAR_DATA *ch, int sn) { long long int value; value = (get_curr_stat(ch, STAT_INT) + get_curr_stat(ch,STAT_WIS)) / 2; value += sqrt(ch->cur_pl * ch->pl / 100) / 15; value *= UMAX(1,get_skill(ch, sn) / 2); if (sn == gsn_power_bomb) value *= 4; else if (sn == gsn_spirit_bomb || sn == gsn_death_ball) value *= 4; else if (sn == gsn_finalflash || sn == gsn_kamehameha || gsn_galic_gun) value *= 2; else if (sn == gsn_energy_ball) value /= 2; else if (sn == gsn_energy_beam) value /= 4; else if (sn == gsn_scattershot) value /= 5; if (ch->charge > 0) value = (ch->charge * value) / skill_table[sn].wait; if (ch->charge == 1) // Immediately released skill -- deduction value /= 4; if (ch->cur_pl < 1 && ch->ki < 1) value /= 50; value = value * (ch->balance+1) / 5; value = 2 * ch->cur_pl * value / 100; return value; } long long int get_kiabsorb (CHAR_DATA *ch, int sn, int dam_type) { long long int value; value = get_curr_stat(ch, STAT_STR); value += sqrt(ch->cur_pl * ch->pl / 100) / 50; value *= UMAX(1,get_skill(ch, sn) / 2); // Armor! switch (dam_type) { case DAM_NONE: break; case DAM_PIERCE: value += ch->armor[AC_PIERCE] / 5; break; case DAM_BASH: value += ch->armor[AC_BASH] / 5; break; case DAM_SLASH: value += ch->armor[AC_SLASH] / 5; break; default: value += ch->armor[AC_EXOTIC] / 5; break; } if (!IS_AWAKE (ch)) value /= 4; else if (ch->position < POS_FIGHTING) value /= 2; if (ch->cur_pl < 1 && ch->ki < 1) value /= 50; value = value * (ch->balance+1) / 5; value = 2 * ch->cur_pl * value / 100; return value; }