51 static void attack_hth(
object *
pl,
int dir,
const char *
string,
object *skill);
72 if (
skill_names[i] == NULL && skill_faces[i] == NULL) {
82 LOG(
llevError,
"init_skills: too many skills, increase MAX_SKILLS and rebuild server!");
102 skill_faces[i] = NULL;
121 assert(
"invalid skill!");
148 if (!skill && !skill_tool)
213 int num_names, highest_level_skill=0, i;
219 if (!strchr(name,
',')) {
220 skill_names[0] = name;
221 skill_tools[0] = NULL;
227 ourname = strdup(name);
229 if ((skill_names[0] = strtok_r(ourname,
",", &lasts)) == NULL) {
231 LOG(
llevError,
"find_skill_by_name: strtok_r returned null, but strchr did not?\n");
235 skill_tools[0] = NULL;
239 while ((skill_names[num_names] = strtok_r(NULL,
",", &lasts)) != NULL) {
243 while (isspace(*skill_names[num_names]))
244 skill_names[num_names]++;
245 skills[num_names] = NULL;
246 skill_tools[num_names] = NULL;
261 for (i = 0; i<num_names; i++) {
262 if (!strncasecmp(skill_names[i], tmp->skill, strlen(skill_names[i])) &&
263 strlen(tmp->skill) >= strlen(skill_names[i])) {
264 if (tmp->type ==
SKILL) {
268 highest_level_skill=i;
277 skill_tools[i] = tmp;
287 return adjust_skill_tool(who, skills[highest_level_skill], skill_tools[highest_level_skill]);
313 object *skill = NULL, *skill_tool = NULL;
320 if (tmp->type ==
SKILL && tmp->subtype == skillno)
326 else if (tmp->type ==
SKILL_TOOL && tmp->subtype == skillno) {
444 int success = 0, exp = 0;
461 LOG(
llevError,
"do_skill: asked for skill %s but couldn't find matching SKILL archetype.\n", skill->
skill);
481 "You come to earth.");
485 "You rise into the air!.");
492 exp = success =
steal(op, dir, skill);
496 exp = success =
pick_lock(op, dir, skill);
500 exp = success =
hide(op, skill);
504 success =
jump(op, dir, skill);
547 exp = success =
singing(op, dir, skill);
580 "This skill is not currently implemented.");
586 "There is no special attack for this skill.");
594 *data = {op, part, skill, dir,
string};
596 success =
pray(op, skill);
613 "This skill is already in effect.");
621 *data = {op, part, skill, dir,
string};
694 float base, value, lvl_mult;
720 op_lvl += 5*abs(op->
magic);
728 return ((int64_t)(op_exp*0.1)+1);
751 lvl_mult = (float)op_lvl/(
float)(skill->
level ? skill->
level : 1);
756 value = base*lvl_mult;
760 #ifdef SKILL_UTIL_DEBUG 761 LOG(
llevDebug,
"calc_skill_exp(): who: %s(lvl:%d) op:%s(lvl:%d)\n", who->
name, skill->
level, op ? op->
name :
"", op_lvl);
763 return ((int64_t)value);
786 if (!scroll->
skill) {
787 LOG(
llevError,
"skill scroll %s does not have skill pointer set.\n", scroll->
name);
797 if (inv->type ==
SKILL && !strncasecmp(scroll->
skill, inv->skill, strlen(scroll->
skill))) {
818 LOG(
llevError,
"skill scroll %s does not have valid skill name (%s).\n", scroll->
name, scroll->
skill);
844 rv = (int)((100.0f*((
float)a)/((
float)b))+0.5f);
865 return num == 0 ? 1 : floor( log10( labs(num) ) ) + 1;
886 int i, num_skills_found = 0;
889 const char *search = parms;
890 bool long_format =
false;
892 if ( parms && strncmp(parms,
"-l",2) == 0 ) {
895 while ( *search && *search !=
' ' ) ++search;
896 while ( *search ==
' ' ) ++search;
899 if (tmp->type ==
SKILL) {
900 if (search && strstr(tmp->name, search) == NULL)
906 snprintf(skills[num_skills_found++],
MAX_BUF,
"[fixed]%-20slvl:%3d (xp:%" FMT64 "/%" FMT64 ")%-*sperm lvl:%3d (xp:%" FMT64 "/%" FMT64 ") ",
907 tmp->name, tmp->level,
916 snprintf(skills[num_skills_found++],
MAX_BUF,
"[fixed]%-20slvl:%3d (xp:%" FMT64 "/%" FMT64 "/%d%%)",
917 tmp->name, tmp->level,
923 snprintf(skills[num_skills_found++],
MAX_BUF,
"[fixed]%-20slvl:%3d (xp:%" FMT64 "/%" FMT64 ")",
924 tmp->name, tmp->level,
936 "Your character has too many skills.\n" 937 "Something isn't right - contact the server admin");
943 if ( search && *search ) {
945 "Player skills%s: (matching '%s')", long_format ?
" (long format)":
"",search);
948 "Player skills%s:", long_format ?
" (long format)":
"");
951 if (num_skills_found > 1)
952 qsort(skills, num_skills_found,
MAX_BUF, (
int (*)(
const void *,
const void *))strcmp);
954 for (i = 0; i < num_skills_found; i++) {
960 if (strcmp(cp,
"none") == 0)
964 "You can handle %d weapon improvements.\n" 966 "Your equipped item power is %d out of %d\n",
968 cp ? cp :
"no god at current time",
997 if (tmp->type ==
SKILL 999 && !strncasecmp(
string, tmp->skill,
MIN(strlen(
string), strlen(tmp->skill)))) {
1004 && !strncasecmp(
string, tmp->skill,
MIN(strlen(
string), strlen(tmp->skill)))) {
1011 "Unable to find skill %s",
1016 len = strlen(skop->
skill);
1023 if (len >= strlen(
string)) {
1027 while (*
string == 0x20)
1029 if (strlen(
string) == 0)
1033 #ifdef SKILL_UTIL_DEBUG 1034 LOG(
llevDebug,
"use_skill() got skill: %s\n", sknum > -1 ? skills[sknum].name :
"none");
1067 object *best_skill = NULL;
1086 "Unable to find skill %s - using default unarmed skill",
1118 if (tmp->type ==
SKILL) {
1129 for (i = 0; i < last_skill; i++) {
1188 "You have no unarmed combat skills!");
1198 "Couldn't change to skill %s",
1211 LOG(
llevError,
"Player %s does not have current weapon set but flag_ready_weapon is set\n", op->
name);
1253 }
else if (
string != NULL) {
1339 "There is nothing to attack!");
1369 if (weapon != NULL) {
1376 "You are unable to unwield %s in order to attack with %s.",
1377 weaponname, skill->
name);
1381 "You unwield your weapon in order to attack.");
1412 "You have no ready weapon to attack with!");
#define AP_UNAPPLY
Item is to be remvoed.
void show_skills(object *op, const char *parms)
Displays a player's skill list, and some other non skill related info (god, max weapon improvements...
int apply_special(object *who, object *op, int aflags)
Apply an object.
const char * determine_god(object *op)
Determines if op worships a god.
object * ranges[range_size]
Object for each range.
int change_skill(object *who, object *new_skill, int flag)
This changes the object's skill to new_skill.
#define FLAG_UNPAID
Object hasn't been paid for yet.
#define UP_OBJ_FACE
Only thing that changed was the face.
Spell-related defines: spellpath, subtypes, ...
static void attack_hth(object *pl, int dir, const char *string, object *skill)
This handles all hand-to-hand attacks.
int skill_ident(object *pl, object *skill)
Main identification skill handling.
struct archetype * arch
Pointer to archetype.
#define MSG_TYPE_SKILL_LIST
List of skills.
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
#define OB_TYPE_MOVE_BLOCK(ob1, type)
Basic macro to see if if ob1 can not move onto a space based on the 'type' move_block parameter Add c...
int do_skill(object *op, object *part, object *skill, int dir, const char *string)
Main skills use function-similar in scope to cast_spell().
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
int attack_ob(object *op, object *hitter)
Simple wrapper for attack_ob_simple(), will use hitter's values.
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
static int digits_in_long(int64_t num)
Gives the number of digits that ld will print for a long int.
void archetypes_for_each(arch_op op)
New face structure - this enforces the notion that data is face by face only - you can not change the...
int shop_describe(const object *op)
Give the player a description of the shop on their current map.
int64_t calc_skill_exp(const object *who, const object *op, const object *skill)
Calculates amount of experience can be gained for successful use of a skill.
partylist * party
Party this player is part of.
sstring add_string(const char *str)
Share a string.
int pick_lock(object *pl, int dir, object *skill)
Lock pick handling.
void skill_attack(object *tmp, object *pl, int dir, const char *string, object *skill)
Core routine for use when we attack using a skills system.
void link_player_skills(object *op)
This function goes through the player inventory and sets up the last_skills[] array in the player obj...
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
Changes experience to a player/monster.
#define MSG_TYPE_SKILL_MISSING
Don't have the skill.
int16_t y
Position in the map for this object.
object * object_find_by_type_applied(const object *who, int type)
Find applied object in inventory.
int8_t magic
Any magical bonuses to this item.
int is_dragon_pl(const object *op)
Checks if player is a dragon.
sstring add_refcount(sstring str)
Like add_string(), but the string is already a shared string.
#define MSG_TYPE_SKILL_ERROR
Doing something wrong.
int64_t level_exp(int level, double expmul)
Returns how much experience is needed for a player to become the given level.
int jump(object *pl, int dir, object *skill)
Jump skill handling.
object * chosen_skill
The skill chosen to use.
int remove_trap(object *op, object *skill)
This skill will disarm any previously discovered trap.
void clear_skill(object *who)
This function just clears the chosen_skill and range_skill values in the player.
Global type definitions and header inclusions.
#define AP_APPLY
Item is to be applied.
struct player * contr
Pointer to the player which control this object.
double expmul
needed experience = (calc_exp*expmul) - means some races/classes can need less/more exp to gain level...
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
int exp_level(int64_t exp)
Returns the level for a given exp.
#define FLAG_CAN_ROLL
Object can be rolled.
rangetype shoottype
Which range-attack is being used by player.
int use_alchemy(object *op)
Handle use_skill for alchemy-like items.
Allows the use of a skill.
static int free_skill_index()
#define FLAG_READY_SKILL
(Monster or Player) has a skill readied
int16_t level
Level of creature or object.
int skill_throw(object *op, object *part, int dir, object *skill)
Throwing skill handling.
const char * skill_names[MAX_SKILLS]
Will contain a number-name mapping for skills, initialized by init_skills().
uint8_t hide
The object is hidden, not invisible.
#define FLAG_ALIVE
Object can fight (or be fought)
#define MSG_TYPE_VICTIM
Something bad is happening to the player.
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
void player_start_repeat(player *pl, const char *action, repeat_cb cb)
Start repeating an action.
void init_skills(void)
This just sets up the skill_names table above.
#define FLAG_CAN_USE_SKILL
The monster can use skills.
int hide(object *op, object *skill)
Main hide handling.
#define QUERY_FLAG(xyz, p)
uint8_t unarmed_skills[UNARMED_SKILLS_COUNT]
Table of unarmed attack skills.
sstring anim_suffix
Used to determine combined animations.
void query_name(const object *op, char *buf, size_t size)
Describes an item.
#define PERM_EXP(exptotal)
Convert saved total experience into permanent experience.
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
sstring msg
If this is a book/sign/magic mouth/etc.
const Face * skill_faces[MAX_SKILLS]
Will contain the face numbers for the skills, initialized by init_skill().
bool do_skill_cb(player *pl, void *data)
#define MSG_TYPE_VICTIM_WAS_HIT
Player was hit by something.
int steal(object *op, int dir, object *skill)
Main stealing function.
const Face * face
Face with colors.
#define AP_NOPRINT
Don't print messages - caller will do that may be some that still print.
#define P_OUT_OF_MAP
This space is outside the map.
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Gets the blocking state of a square.
#define MSG_TYPE_ATTACK_MISS
attack didn't hit
struct Settings settings
Global settings.
static object * adjust_skill_tool(object *who, object *skill, object *skill_tool)
This returns specified skill if it can be used, potentially using tool to help.
#define MSG_TYPE_SKILL_FAILURE
Failure in using skill.
uint8_t simple_exp
If true, use the simple experience system.
int random_roll(int min, int max, const object *op, int goodbad)
Roll a random number between min and max.
int get_learn_spell(int stat)
void do_harvest(object *pl, int dir, object *skill)
Player is trying to harvest something.
void fatal(enum fatal_error err)
fatal() is meant to be called whenever a fatal signal is intercepted.
living stats
Str, Con, Dex, etc.
#define MAX_BUF
Used for all kinds of things.
#define MSG_TYPE_ATTACK
Attack related messages.
sstring skill_messages[MAX_SKILLS]
Will contain the message for the skills, initialized by init_skill().
int16_t invisible
How much longer the object will be invis.
#define MSG_TYPE_ATTACK_DID_HIT
Player hit something else.
object * find_skill_by_number(object *who, int skillno)
This returns the first skill pointer of the given subtype (the one that accumulates exp...
float speed_left
How much speed is left to spend this round.
struct mapstruct * map
Pointer to the map in which this object is present.
Skill-related defines, including subtypes.
object * find_skill_by_name(object *who, const char *name)
This returns the skill pointer of the given name (the one that accumulates exp, has the level...
#define FLAG_READY_WEAPON
(Monster or Player) has a weapon readied
static int clipped_percent(int64_t a, int64_t b)
Gives a percentage clipped to 0% -> 100% of a/b.
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
int8_t facing
Object is oriented/facing that way.
static void do_each_skill(archetype *at)
uint8_t permanent_exp_ratio
How much exp should be 'permenant' and unable to be lost.
int pray(object *pl, object *skill)
Praying skill handling.
Object structure, the core of Crossfire.
int use_skill(object *op, const char *string)
Similar to invoke command, it executes the skill in the direction that the user is facing...
static event_registration m
Also see SKILL_TOOL (74) below.
static void do_skill_attack(object *tmp, object *op, const char *string, object *skill)
We have got an appropriate opponent from either move_player_attack() or skill_attack().
object * object_find_by_type_and_skill(const object *who, int type, const char *skill)
Find object in inventory by type and skill.
sstring name
The name of the object, obviously...
Only for debugging purposes.
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
This rolls up wall, blocks_magic, blocks_view, etc, all into one function that just returns a P_...
int singing(object *pl, int dir, object *skill)
Singing skill handling.
#define CLEAR_FLAG(xyz, p)
uint8_t type
PLAYER, BULLET, etc.
rangetype
What range is currently selected by the player.
#define FLAG_APPLIED
Object is ready for use by living.
int find_traps(object *pl, object *skill)
Checks for traps on the spaces around the player or in certain objects.
int learn_skill(object *pl, object *scroll)
Player is trying to learn a skill.
sstring skill
Name of the skill this object uses/grants.
#define MSG_TYPE_SKILL
Messages related to skill use.
object * give_skill_by_name(object *op, const char *skill_name)
Given the skill name skill_name, we find the skill archetype/object, set appropriate values...
#define NDI_UNIQUE
Print immediately, don't buffer.
int use_oratory(object *pl, int dir, object *skill)
Oratory skill handling.
uint32_t tmp_invis
Will invis go away when we attack?
C function wrappers to interact with assets.
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
object * current_weapon
Pointer to the weapon currently used.
Structure containing object statistics.
#define MSG_TYPE_SKILL_SUCCESS
Successfully used skill.
const char * unarmed_skill
Prefered skill to use in unarmed combat.
uint8_t subtype
Subtype of object.
uint16_t difficulty
What level the player should be to play here.
#define MAX_SKILLS
This is the maximum number of skills the game may handle.
#define SK_SUBTRACT_SKILL_EXP
Used when removing exp.
int16_t item_power
Total item power of objects equipped.
#define P_IS_ALIVE
Something alive is on this space.
void object_update(object *op, int action)
object_update() updates the array which represents the map.
int get_skill_client_code(const char *skill_name)
Return the code of the skill for a client, the index in the skill_names array.
int write_on_item(object *pl, const char *params, object *skill)
Implement the 'inscription' skill, which checks for the required skills and marked items before runni...
static void attack_melee_weapon(object *op, int dir, const char *string, object *skill)
This handles melee weapon attacks -b.t.
void meditate(object *pl, object *skill)
Meditation skill handling.
object clone
An object from which to do object_copy()
static object * find_best_player_hth_skill(object *op)
Finds the best unarmed skill the player has, and returns it.
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
void * repeat_func_data
Arguments to pass into repeat_func.
void apply_anim_suffix(object *who, const char *suffix)
Applies a compound animation to an object.
#define FLAG_FREED
Object is in the list of free objects.