/* /lib/abilities.c
* From the Dead Souls V LPC Library
* Handles learned traits
* Created by Descartes of Borg 950122
* Version: @(#) abilities.c 1.22@(#)
* Last modified: 97/01/03
*/
private int Level = 1;
private mapping Skills = ([]);
private static mapping SkillsBonus = ([]);
// abstract methods
varargs void eventPrint(string str, mixed args...);
// end abstract methods
string array GetPrimarySkills();
varargs void SetSkill(string skill, int level, int cls);
/* ***************** abilities.c attributes ***************** */
/* GetBaseSkillLevel() returns the unmodified skill level */
int GetBaseSkillLevel(string skill) {
if( !Skills[skill] ) {
return 0;
}
else {
return Skills[skill]["level"];
}
}
int GetLevel() {
return Level;
}
/* static int ResetLevel()
*
* description
* takes the average skill level of the primary skills and divided by 4
* and sets the level to that number
*
* returns the new level
*/
int ResetLevel() {
string array skills = GetPrimarySkills();
int num = sizeof(skills);
int points = 0;
if( num < 1 ) {
return (Level = 1);
}
foreach(string skill in skills) {
points += Skills[skill]["level"];
}
Level = (points/num)/2;
if( Level < 1 ) {
Level = 1;
}
return Level;
}
int SetLevel(int x) {
string array skills = GetPrimarySkills();
int i;
foreach(string skill in skills) {
SetSkill(skill, 2*x);
}
return (Level = x);
}
int GetMaxSkillPoints(string skill, int level) {
if( !Skills[skill] ) {
return 0;
}
else if( level == 0 ) {
return 200;
}
else {
int cl, x;
if( !(cl = Skills[skill]["class"]) ) {
return level * 600;
}
if( cl > 4 ) {
cl = 4;
}
if( cl < 1 ) {
cl = 4;
}
x = level;
while( cl-- ) {
x *= level;
}
return (x * 400);
}
}
string array GetPrimarySkills() {
return filter(keys(Skills), (: Skills[$1]["class"] == 1 :));
}
/* varargs int AddSkill(string skill, int classes)
* string skill - the skill being added (required)
* int classes - the class of the skill (optional)
*
* defaults
* classes defaults to 1, primary class
*
* description
* Used to add a new ability to the list of abilities. "skill" is the name
* of the skill being added, and "class" represents the ranking of that skill
*
* returns 1 on success, 0 on failure
*/
varargs int AddSkill(string skill, int cls) {
if( !stringp(skill) ) {
error("Bad argument 1 to AddSkill().\n\tExpected: string, Got: " +
typeof(skill) + "\n");
}
if( !nullp(Skills[skill]) ) {
return 0;
}
if( !cls ) {
cls = 1;
}
else if( cls < 0 || cls > 4) {
return 0;
}
Skills[skill] = ([ "points" : 0, "level" : 0, "class" : cls ]);
return 1;
}
mapping GetSkill(string skill) {
return copy(Skills[skill]);
}
void RemoveSkill(string skill) {
if( !Skills[skill] ) {
return;
}
map_delete(Skills, skill);
ResetLevel();
}
/* varargs void SetSkill(string skill, int level, int classes)
* string skill - the name of the skill being set (required)
* int level - the level to which that skill is being set (required)
* int classes - the class to which the skill is being set (optional)
*
* defaults
* classes will default to 1, primary class
*
* description
* sets the skill "skill" to the level "level"
* if a classes is given, its class is set to it, otherwise the class is
* set to 1
* usefule mostly for monster types, probably should have override
* protections in the user object (should use AddSkill() for users)
*/
varargs void SetSkill(string skill, int level, int cls) {
if( !stringp(skill) ) {
error("Bad argument 1 to SetSkill().\n\tExpected: string, Got: " +
typeof(skill) + "\n");
}
if( !cls ) {
if( Skills[skill] ) {
cls = Skills[skill]["class"];
}
else {
cls = 1;
}
}
else if( cls < 1 || cls > 4) {
return 0;
}
Skills[skill] = ([ "points" : 0, "level" : level, "class" : cls ]);
}
string array GetSkills() {
return keys(Skills);
}
void AddSkillBonus(string skill, function f) {
if( !SkillsBonus[skill] ) {
SkillsBonus[skill] = ([]);
}
SkillsBonus[skill][previous_object()] = f;
}
varargs void RemoveSkillBonus(string skill, object ob) {
if( !SkillsBonus[skill] ) {
return;
}
if( !ob ) {
ob = previous_object();
}
if( !ob || !SkillsBonus[skill][ob] ) {
return;
}
map_delete(SkillsBonus[skill], ob);
}
int GetSkillBonus(string skill) {
object ob;
int x = 0;
if( !SkillsBonus[skill] ) {
return 0;
}
foreach(ob in keys(SkillsBonus[skill])) {
if( !ob ) continue;
else x += evaluate(SkillsBonus[skill][ob], skill);
}
return x;
}
int GetSkillClass(string skill) {
if( !Skills[skill] ) {
return 0;
}
else {
return Skills[skill]["class"];
}
}
/* GetSkillLevel() returns the base skill level + any bonuses */
int GetSkillLevel(string skill) {
return (GetBaseSkillLevel(skill) + GetSkillBonus(skill));
}
/* int AddSkillPoints(string skill, int x)
* string name - the skill to which points are being added
* int x - the number of points being added
*
* description
* adds "x" points to the total for skill "skill"
* if the points go over the max for the current skill level,
* then the level is raised 1
* if the points go under 0, then the skill level is lowered
*
* returns the skill level after addition
*/
int AddSkillPoints(string name, int x) {
int y;
if( !Skills[name] ) {
return 0;
}
Skills[name]["points"] += x;
while( Skills[name]["points"] < 0 ) { /* lost skills! */
if( Skills[name]["level"] == 1 ) {
Skills[name]["points"] = 0;
}
else {
int tmp;
tmp = --Skills[name]["level"];
Skills[name]["points"] += GetMaxSkillPoints(name, tmp);
if( Skills[name]["class"] == 1 ) {
ResetLevel();
}
}
}
y = GetMaxSkillPoints(name, Skills[name]["level"]);
while( Skills[name]["points"] > y ) {
int max;
if( Skills[name]["class"] == 1 ) {
max = 2;
}
else {
max = 1;
}
if( Skills[name]["level"] >= ((GetLevel()+max) *2) ) {
Skills[name]["points"] = y;
}
else {
eventPrint("%^YELLOW%^You are a bit more adept with your " +
name + ".");
Skills[name]["level"]++;
Skills[name]["points"] -= y;
if( Skills[name]["class"] == 1 ) {
ResetLevel();
}
}
y = GetMaxSkillPoints(name, Skills[name]["level"]);
}
return Skills[name]["level"];
}
/* ******************* abilities.c events ********************* */
/**
* Trains a skill based on a scale of 1-100 in favour of success and 1-100
* against success. Any particular thing (like calculating whether a player
* hits an enemy) determins whether an operation succeeds or fails. For
* example, pro = melee attack, con = melee defense. While the con may
* be greater than the pro, combat may randomize that. You still reward
* based on the absolutes. Success is flagged to this method. The value of
* training looks like this:
* highest- pro: 0, con: 100, success: 1
* moderate- pro: 100, con: 0, success: 1
* moderate- pro: 0, con 100, success: 0
* low- pro: 100, con: 0, success: 0
* This means if you have everything going against you and you succeed, you
* get the highest reward. If you have everything going for you and you fail,
* you get nothing.
* Adjustments are made for your level and any multiplier bonuses.
*/
varargs void eventTrainSkill(string skill, int pro, int con, int array a...) {
int level = (GetLevel()/8 + 1);
int val, success, bonus;
if( sizeof(a) ) {
success = a[0];
if( sizeof(a) == 2 ) {
bonus = a[1];
}
else {
bonus = 1;
}
}
else {
success = 1;
bonus = 1;
}
if( con > 100 ) {
con = 100;
}
if( con < 0 ) {
con = 0;
}
if( pro > 100 ) {
pro = 100;
}
if( pro < 0 ) {
pro = 0;
}
val = (con - pro + (200*success) + 100)/8;
AddSkillPoints(skill, (bonus * val * level * level) + 1);
}
/* ****************** abilities.c driver applies **************** */
static void create() {
}