35 #define WANT_UNARMED_SKILLS 53 static void attack_hth(
object *
pl,
int dir,
const char *
string,
object *skill);
68 if (
skill_names[i] == NULL && skill_faces[i] == NULL) {
75 if (at->clone.type == SKILL) {
78 LOG(
llevError,
"init_skills: too many skills, increase MAX_SKILLS and rebuild server!");
82 if (at->clone.face != NULL)
83 skill_faces[i] = at->clone.face;
96 skill_faces[i] = NULL;
114 assert(
"invalid skill!");
141 if (!skill && !skill_tool)
206 int num_names, highest_level_skill=0, i;
212 if (!strchr(name,
',')) {
213 skill_names[0] = name;
214 skill_tools[0] = NULL;
220 ourname = strdup(name);
222 if ((skill_names[0] =
strtok_r(ourname,
",", &lasts)) == NULL) {
224 LOG(
llevError,
"find_skill_by_name: strtok_r returned null, but strchr did not?\n");
228 skill_tools[0] = NULL;
232 while ((skill_names[num_names] =
strtok_r(NULL,
",", &lasts)) != NULL) {
236 while (isspace(*skill_names[num_names]))
237 skill_names[num_names]++;
238 skills[num_names] = NULL;
239 skill_tools[num_names] = NULL;
254 for (i = 0; i<num_names; i++) {
255 if (!
strncasecmp(skill_names[i], tmp->skill, strlen(skill_names[i])) &&
256 strlen(tmp->skill) >= strlen(skill_names[i])) {
257 if (tmp->type == SKILL) {
259 if (!skill || tmp->level > skill->level) {
261 highest_level_skill=i;
270 skill_tools[i] = tmp;
280 return adjust_skill_tool(who, skills[highest_level_skill], skill_tools[highest_level_skill]);
306 object *skill = NULL, *skill_tool = NULL;
313 if (tmp->type == SKILL && tmp->subtype == skillno)
319 else if (tmp->type == SKILL_TOOL && tmp->subtype == skillno) {
353 if (who->type != PLAYER)
356 old_range = who->contr->shoottype;
359 if (who->chosen_skill && who->chosen_skill->skill == new_skill->skill) {
366 if (who->chosen_skill)
377 who->contr->shoottype = old_range;
390 who->chosen_skill = NULL;
392 if (who->type == PLAYER) {
422 int do_skill(
object *op,
object *part,
object *skill,
int dir,
const char *
string) {
423 int success = 0, exp = 0;
433 if (skill->type != SKILL && op->type == PLAYER) {
440 LOG(
llevError,
"do_skill: asked for skill %s but couldn't find matching SKILL archetype.\n", skill->skill);
447 if (skill->anim_suffix)
450 switch (skill->subtype) {
460 "You come to earth.");
464 "You rise into the air!.");
471 exp = success =
steal(op, dir, skill);
475 exp = success =
pick_lock(op, dir, skill);
479 exp = success =
hide(op, skill);
483 success =
jump(op, dir, skill);
526 exp = success =
singing(op, dir, skill);
559 "This skill is not currently implemented.");
565 "There is no special attack for this skill.");
569 success =
pray(op, skill);
586 "This skill is already in effect.");
598 LOG(
llevDebug,
"%s attempted to use unknown skill: %d\n", name, op->chosen_skill->stats.sp);
610 if (op->type == PLAYER)
611 op->speed_left -= 1.0;
661 float base, value, lvl_mult;
677 op_lvl =
MAX(who->map->difficulty, 1);
679 }
else if (op->type == RUNE || op->type == TRAP) {
681 op_exp = op->stats.Cha > 1 ? op->stats.Cha : op->stats.exp;
684 op_exp = op->stats.exp;
687 op_lvl += 5*abs(op->magic);
694 if (who->type != PLAYER) {
695 return ((
int64_t)(op_exp*0.1)+1);
703 if (skill->type == SKILL) {
704 base += skill->arch->clone.stats.exp;
706 if (skill->arch->clone.level)
707 lvl_mult = (float)skill->arch->clone.level/100.0;
712 lvl_mult = ((float)skill->arch->clone.level*(
float)op_lvl)/((
float)skill->level*100.0);
718 lvl_mult = (float)op_lvl/(
float)(skill->level ? skill->level : 1);
723 value = base*lvl_mult;
727 #ifdef SKILL_UTIL_DEBUG 728 LOG(
llevDebug,
"calc_skill_exp(): who: %s(lvl:%d) op:%s(lvl:%d)\n", who->name, skill->level, op->name, op_lvl);
753 if (!scroll->skill) {
754 LOG(
llevError,
"skill scroll %s does not have skill pointer set.\n", scroll->name);
764 if (inv->type == SKILL && !
strncasecmp(scroll->skill, inv->skill, strlen(scroll->skill))) {
785 LOG(
llevError,
"skill scroll %s does not have valid skill name (%s).\n", scroll->name, scroll->skill);
811 rv = (int)((100.0f*((
float)a)/((
float)b))+0.5f);
832 return num == 0 ? 1 : floor( log10( labs(num) ) ) + 1;
853 int i, num_skills_found = 0;
856 const char *search = parms;
857 bool long_format =
false;
859 if ( parms && strncmp(parms,
"-l",2) == 0 ) {
862 while ( *search && *search !=
' ' ) ++search;
863 while ( *search ==
' ' ) ++search;
866 if (tmp->type == SKILL) {
867 if (search && strstr(tmp->name, search) == NULL)
874 tmp->name, tmp->level,
884 tmp->name, tmp->level,
891 tmp->name, tmp->level,
903 "Your character has too many skills.\n" 904 "Something isn't right - contact the server admin");
910 if ( search && *search ) {
912 "Player skills%s: (matching '%s')", long_format ?
" (long format)":
"",search);
915 "Player skills%s:", long_format ?
" (long format)":
"");
918 if (num_skills_found > 1)
919 qsort(skills, num_skills_found,
MAX_BUF, (
int (*)(
const void *,
const void *))strcmp);
921 for (i = 0; i < num_skills_found; i++) {
927 if (strcmp(cp,
"none") == 0)
931 "You can handle %d weapon improvements.\n" 933 "Your equipped item power is %d out of %d\n",
935 cp ? cp :
"no god at current time",
936 op->contr->item_power, op->level);
964 if (tmp->type == SKILL
966 && !
strncasecmp(
string, tmp->skill,
MIN(strlen(
string), strlen(tmp->skill)))) {
969 }
else if (tmp->type == SKILL_TOOL
971 && !
strncasecmp(
string, tmp->skill,
MIN(strlen(
string), strlen(tmp->skill)))) {
978 "Unable to find skill %s",
983 len = strlen(skop->skill);
990 if (len >= strlen(
string)) {
994 while (*
string == 0x20)
996 if (strlen(
string) == 0)
1000 #ifdef SKILL_UTIL_DEBUG 1001 LOG(
llevDebug,
"use_skill() got skill: %s\n", sknum > -1 ? skills[sknum].name :
"none");
1005 if (
do_skill(op, op, skop, op->facing,
string))
1034 object *best_skill = NULL;
1037 if (op->contr->unarmed_skill) {
1053 "Unable to find skill %s - using default unarmed skill",
1054 op->contr->unarmed_skill);
1058 for (i = 0; i <
sizeof(unarmed_skills); i++)
1059 if (best_skill->subtype == unarmed_skills[i])
1061 if (i <
sizeof(unarmed_skills))
1083 last_skill =
sizeof(unarmed_skills);
1085 if (tmp->type == SKILL) {
1096 for (i = 0; i < last_skill; i++) {
1131 if (op->type == PLAYER) {
1139 if (op->chosen_skill) {
1142 for (i = 0; unarmed_skills[i] != 0; i++)
1143 if (op->chosen_skill->subtype == unarmed_skills[i]) {
1144 skill = op->chosen_skill;
1155 "You have no unarmed combat skills!");
1160 if (skill != op->chosen_skill) {
1165 "Couldn't change to skill %s",
1175 if (!op->current_weapon) {
1178 LOG(
llevError,
"Player %s does not have current weapon set but flag_ready_weapon is set\n", op->name);
1181 LOG(
llevError,
"Could not find applied weapon on %s\n", op->name);
1182 op->current_weapon = NULL;
1188 op->current_weapon = tmp;
1193 if (!op->chosen_skill || op->current_weapon->skill != op->chosen_skill->skill) {
1195 assert(found_skill != NULL);
1203 if (op->type == PLAYER && op->contr->tmp_invis) {
1204 op->contr->tmp_invis = 0;
1225 if (op->type == PLAYER) {
1231 }
else if (tmp->type == PLAYER) {
1272 void skill_attack(
object *tmp,
object *
pl,
int dir,
const char *
string,
object *skill) {
1304 || tmp2->type == LOCKED_DOOR) {
1306 if ((pl->type == PLAYER && tmp2->type == PLAYER)
1307 && (pl->contr->party != NULL && pl->contr->party == tmp2->contr->party))
1315 if (pl->type == PLAYER)
1317 "There is nothing to attack!");
1342 static void attack_hth(
object *
pl,
int dir,
const char *
string,
object *skill) {
1347 if (weapon != NULL) {
1354 "You are unable to unwield %s in order to attack with %s.",
1355 weaponname, skill->name);
1359 "You unwield your weapon in order to attack.");
1388 if (op->type == PLAYER)
1390 "You have no ready weapon to attack with!");
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
int apply_special(object *who, object *op, int aflags)
const char * determine_god(object *op)
int skill_ident(object *pl, object *skill)
int64_t level_exp(int level, double expmul)
static void attack_melee_weapon(object *op, int dir, const char *string, object *skill)
void apply_anim_suffix(object *who, const char *suffix)
#define MSG_TYPE_SKILL_LIST
sstring add_refcount(sstring str)
object * object_find_by_type_applied(const object *who, int type)
static int digits_in_long(int64_t num)
void link_player_skills(object *op)
static int clipped_percent(int64_t a, int64_t b)
int attack_ob(object *op, object *hitter)
int exp_level(int64_t exp)
const char * skill_names[MAX_SKILLS]
void fatal(enum fatal_error err)
void archetypes_for_each(arch_op op)
int shop_describe(const object *op)
int use_skill(object *op, const char *string)
short freearr_x[SIZEOFFREE]
int pick_lock(object *pl, int dir, object *skill)
static object * adjust_skill_tool(object *who, object *skill, object *skill_tool)
int change_skill(object *who, object *new_skill, int flag)
#define MSG_TYPE_SKILL_MISSING
int do_skill(object *op, object *part, object *skill, int dir, const char *string)
#define MSG_TYPE_SKILL_ERROR
int jump(object *pl, int dir, object *skill)
int remove_trap(object *op, object *skill)
void object_update(object *op, int action)
int64_t calc_skill_exp(const object *who, const object *op, const object *skill)
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
short freearr_y[SIZEOFFREE]
object * give_skill_by_name(object *op, const char *skill_name)
int use_alchemy(object *op)
int skill_throw(object *op, object *part, int dir, object *skill)
#define strtok_r(x, y, z)
#define FLAG_CAN_USE_SKILL
int hide(object *op, object *skill)
int is_dragon_pl(const object *op)
#define PERM_EXP(exptotal)
static void attack_hth(object *pl, int dir, const char *string, object *skill)
void show_skills(object *op, const char *parms)
const Face * skill_faces[MAX_SKILLS]
#define MSG_TYPE_VICTIM_WAS_HIT
int steal(object *op, int dir, object *skill)
#define OB_TYPE_MOVE_BLOCK(ob1, type)
#define GET_MAP_MOVE_BLOCK(M, X, Y)
#define MSG_TYPE_ATTACK_MISS
static object * find_best_player_hth_skill(object *op)
#define MSG_TYPE_SKILL_FAILURE
void do_harvest(object *pl, int dir, object *skill)
#define QUERY_FLAG(xyz, p)
#define CLEAR_FLAG(xyz, p)
static int free_skill_index()
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
#define MSG_TYPE_ATTACK_DID_HIT
int strncasecmp(const char *s1, const char *s2, int n)
int learn_skill(object *pl, object *scroll)
#define FLAG_READY_WEAPON
uint8_t permanent_exp_ratio
int get_skill_client_code(const char *skill_name)
int pray(object *pl, object *skill)
object * object_find_by_type_and_skill(const object *who, int type, const char *skill)
int singing(object *pl, int dir, object *skill)
int find_traps(object *pl, object *skill)
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
int use_oratory(object *pl, int dir, object *skill)
void LOG(LogLevel logLevel, const char *format,...)
int get_learn_spell(int stat)
object * find_skill_by_name(object *who, const char *name)
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
#define MSG_TYPE_SKILL_SUCCESS
void query_name(const object *op, char *buf, size_t size)
#define SK_SUBTRACT_SKILL_EXP
int random_roll(int min, int max, const object *op, int goodbad)
void clear_skill(object *who)
object * find_skill_by_number(object *who, int skillno)
int write_on_item(object *pl, const char *params, object *skill)
void fix_object(object *op)
void meditate(object *pl, object *skill)
void skill_attack(object *tmp, object *pl, int dir, const char *string, object *skill)
static void do_each_skill(archetype *at)
#define FOR_INV_PREPARE(op_, it_)
static void do_skill_attack(object *tmp, object *op, const char *string, object *skill)