 |
Crossfire Server, Trunk
1.75.0
|
Go to the documentation of this file.
39 #define SPECIALISATION_EFFECT 0.5
42 #define DISAPPROVAL_RATIO 0.2
45 #define NEUTRAL_RATIO 0.8
48 #define MAX_BUY_REDUCTION 0.1f
50 #define MAX_SELL_EXTRA 0.1f
53 static uint64_t
value_limit(uint64_t val,
int quantity,
const object *who,
int isshop);
59 #define LARGEST_COIN_GIVEN 2
62 static const char *const coins[] = {
77 const int number =
NROF(obj);
79 uint64_t val = (uint64_t)obj->
value * number;
84 float ratio = atof(key);
94 if (!identified && obj->
arch) {
113 if (obj->
arch != NULL && identified) {
115 val *= pow(1.15, diff);
147 int lev_identify = 0;
163 val += val * (sin(tmp->
count) / sqrt(lev_identify * 3 + 1.0));
174 return tanh((charisma+15.0)/20);
199 const float adj_val = val * adj / E;
200 if (getenv(
"CF_DEBUG_SHOP")) {
201 LOG(
llevDebug,
"price_buy %s %lu*adj(%.2f)/E(%.2f) = %.2f\n",
202 tmp->
arch->
name, val, adj, E, adj_val);
204 if (std::isfinite(adj_val)) {
221 const uint64_t adj_val = val * adj * spec * E;
224 int number =
NROF(tmp);
225 uint64_t limval =
value_limit(adj_val, number, who, 1);
227 if (getenv(
"CF_DEBUG_SHOP")) {
228 LOG(
llevDebug,
"price_sell %s %lu*adj(%.2f)*s(%.2f)*E(%.2f) = %lu limited to %lu\n",
229 tmp->
arch->
name, val, adj, spec, E, adj_val, limval);
249 if (
coins[*cointype] == NULL)
280 int cointype = largest_coin;
288 if (cost == UINT64_MAX) {
309 cost -= (uint64_t)num*(uint64_t)coin->
clone.
value;
316 if (next_coin == NULL)
322 cost -= (uint64_t)num*(uint64_t)coin->
clone.
value;
434 LOG(
llevError,
"Query money called with non player/container\n");
438 if (tmp->type ==
MONEY) {
439 total += (uint64_t)tmp->nrof*(uint64_t)tmp->value;
442 && (tmp->race == NULL || strstr(tmp->race,
"gold"))) {
474 && (pouch->race == NULL || strstr(pouch->race,
"gold"))) {
479 LOG(
llevError,
"pay_for_amount: Cannot remove enough money -- %" FMT64U " remains\n", to_pay);
503 assert(to_pay >= reduction);
518 && (pouch->race == NULL || strstr(pouch->race,
"gold"))) {
523 LOG(
llevError,
"pay_for_item: Cannot remove enough money -- %" FMT64U " remains\n", to_pay);
549 if ((int64_t)coin_objs[i]->nrof * coin_objs[i]->value > remain) {
550 num_coins = remain/coin_objs[i]->
value;
551 if ((uint64_t)num_coins*(uint64_t)coin_objs[i]->value < (uint64_t) remain) {
555 num_coins = coin_objs[i]->
nrof;
557 remain -= (int64_t)num_coins*(int64_t)coin_objs[i]->
value;
558 coin_objs[i]->
nrof -= num_coins;
564 while (remain < 0 && count >= 0) {
565 num_coins = -remain/coin_objs[count]->
value;
566 coin_objs[count]->
nrof += num_coins;
567 remain += num_coins*coin_objs[count]->
value;
583 static void add_value(
object *coin_objs[], int64_t value) {
589 nrof = (uint32_t)(value/coin_objs[i]->value);
590 value -= nrof*coin_objs[i]->
value;
591 coin_objs[i]->
nrof += nrof;
610 for (i = 0; i < objects_len; i++) {
639 object *other_money[16];
640 size_t other_money_len;
653 if (tmp->type ==
MONEY) {
656 && (tmp->value == tmp->arch->clone.value)) {
660 if (coin_objs[i] != NULL) {
663 coin_objs[i]->
nrof += tmp->nrof;
673 if (other_money_len >=
sizeof(other_money)/
sizeof(*other_money)) {
674 LOG(
llevError,
"pay_for_item: Cannot store non-standard money object %s\n", tmp->arch->name);
677 other_money[other_money_len++] = tmp;
686 if (coin_objs[i] == NULL) {
693 coin_objs[i]->
nrof = 0;
700 for (i = 0; i < other_money_len && remain > 0; i++) {
704 coin = other_money[i];
727 if (
a == UINT64_MAX) {
731 if (UINT64_MAX -
a < b) {
755 callback(item,
data);
785 *unpaid_price = args.
price;
803 coincount[i] += item->
nrof;
843 uint64_t unpaid_price = 0;
847 LOG(
llevError,
"can_pay(): called against something that isn't a player\n");
858 if (unpaid_price > player_wealth) {
860 int denominations = 0;
861 char *value =
cost_str(unpaid_price);
863 snprintf(
buf,
sizeof(
buf),
"You have %d unpaid items that would cost you %s, ",
unpaid_count, value);
866 if (coincount[i] > 0 &&
coins[i]) {
867 if (denominations == 0)
868 snprintf(
buf+strlen(
buf),
sizeof(
buf)-strlen(
buf),
"but you only have");
873 snprintf(coinbuf,
sizeof(coinbuf),
" %u %s,", coincount[i], arch->
clone.
name_pl);
874 snprintf(
buf+strlen(
buf),
sizeof(
buf)-strlen(
buf),
"%s", coinbuf);
878 if (denominations == 0)
879 snprintf(
buf+strlen(
buf),
sizeof(
buf)-strlen(
buf),
"but you don't have any money.");
880 else if (denominations > 1)
890 object *
pl = (
object *)
data;
902 "You lack %s to buy %s.",
921 char *reduction_str =
cost_str(reduction);
924 "You paid %s for %s after bargaining a reduction of %s.",
925 value, name_op, reduction_str);
931 "You paid %s for %s.",
976 LOG(
llevDebug,
"Object other than player tried to sell something.\n");
991 "We're not interested in %s.",
999 if (extra_gain > 0) {
1001 char *extra_str =
cost_str(extra_gain);
1003 "You receive %s for %s, after bargaining for %s more than proposed.", value_str, obj_name, extra_str);
1005 price += extra_gain;
1008 "You receive %s for %s.", value_str, obj_name);
1021 && strstr(pouch->race,
"gold")) {
1022 int w = at->
clone.
weight*(100-pouch->stats.Str)/100;
1028 && (!pouch->weight_limit || pouch->carrying+w <= pouch->weight_limit)) {
1029 if (pouch->weight_limit
1030 && (pouch->weight_limit-pouch->carrying)/w < n)
1031 n = (pouch->weight_limit-pouch->carrying)/w;
1082 LOG(
llevError,
"shop_specialisation_ratio: passed a NULL item for map %s\n", map->
path);
1085 if (item->
type == (uint8_t)-1) {
1086 LOG(
llevError,
"shop_specialisation_ratio: passed an item with an invalid type\n");
1095 for (i = 0; i < items[0].
index; i++)
1096 if (items[i].typenum == item->
type || (items[i].
typenum == -1 && likedness == 0.001))
1097 likedness = items[i].
strength/100.0;
1099 if (likedness > 1.0) {
1100 LOG(
llevDebug,
"shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->
type, map->
path);
1103 if (likedness < -1.0) {
1104 LOG(
llevDebug,
"shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->
type, map->
path);
1107 ratio = ratio+(1.0-ratio)*likedness;
1132 return tanh(-greed+2.0)/2 + 0.5;
1136 double approval = 1.0;
1164 static uint64_t
value_limit(uint64_t val,
int quantity,
const object *who,
int isshop) {
1165 uint64_t newval, unit_price;
1168 unit_price = val/quantity;
1169 if (!isshop || !who) {
1170 if (unit_price > 10000)
1171 newval = 8000+
isqrt(unit_price)*20;
1173 newval = unit_price;
1176 LOG(
llevError,
"value_limit: asked shop price for ob %s on NULL map\n", who->
name);
1180 if (map->
shopmin && unit_price < map->shopmin)
1182 else if (unit_price > map->
shopmax/2)
1184 else if (unit_price > 10000)
1185 newval = 8000+
isqrt(unit_price)*20;
1187 newval = unit_price;
1203 char tmp[
MAX_BUF] =
"\0", *value;
1215 "From looking at the nearby shop you determine that it trades in:");
1221 pos += strlen(tmp+pos);
1226 strcpy(tmp,
"a little of everything.");
1237 "It won't trade for items above %s.",
1246 "It won't trade in items worth less than %s.",
1255 "It tends to overcharge massively.");
1259 "It tends to overcharge substantially.");
1263 "It tends to overcharge slightly.");
1267 "It tends to undercharge.");
1274 "You think the shopkeeper likes you.");
1275 else if (opinion > 0.5)
1278 "The shopkeeper seems unconcerned by you.");
1282 "The shopkeeper seems to have taken a dislike to you.");
1285 "There is no shop nearby.");
1301 if (!ob->
map)
return 0;
double shopgreed
How much our shopkeeper overcharges.
#define EVENT_GSOLD
Player sold object in shop, but global.
sstring name_pl
The plural name of the object.
char * cost_approx_str(const object *tmp, object *who)
Return a textual cost approximation in a newly-allocated string.
int8_t strength
The degree of specialisation the shop has in this item, as a percentage from -100 to 100.
double shop_approval(const mapstruct *map, const object *player)
Return the approval ratio for a shop for a given player.
void sell_item(object *op, object *pl)
Player is selling an item.
struct Settings settings
Server settings.
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
static float shop_cha_modifier(int charisma)
Calculate the buy price multiplier based on a player's charisma.
int16_t max_level
This is read out of exp_table.
@ llevError
Error, serious thing.
object * find_skill_by_number(object *who, int skillno)
This returns the first skill pointer of the given subtype (the one that accumulates exp,...
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
object * inv
Pointer to the first object in the inventory.
#define LARGEST_COIN_GIVEN
Never give amber or jade, but accept them.
#define MAX_SELL_EXTRA
Maximum price increase when selling an item with bargaining skill.
#define QUERY_FLAG(xyz, p)
uint64_t shopmin
Minimum price a shop will trade for.
static uint64_t compute_price_variation_with_bargaining(object *pl, uint64_t price, float max_variation)
Compute a percent of the price which will be used as extra or reduction.
static void unpaid_iter(object *item, void(*callback)(object *item, void *data), void *data)
Search for unpaid items in 'item' and call 'callback' on each item.
#define EVENT_GBOUGHT
Player bought object in shop, but global.
object * object_merge(object *op, object *top)
This function goes through all objects below and including top, and merges op to the first matching o...
char * cost_str(uint64_t cost)
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
static archetype * find_next_coin(uint64_t c, int *cointype)
Find the coin type that is worth more than 'c'.
static void add_value(object *coin_objs[], int64_t value)
This function adds a given amount to a list of coins.
static event_registration c
struct archetype * arch
Pointer to archetype.
#define SPECIALISATION_EFFECT
This is a measure of how effective store specialisation is.
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
static bool coords_in_shop(mapstruct *map, int x, int y)
Check if the given map coordinates are in a shop.
uint64_t price_approx(const object *tmp, object *who)
Adjust the value of the given item based on the player's skills.
static void insert_objects(object *pl, object *container, object *objects[], int objects_len)
Insert a list of objects into a player object.
struct mapstruct * map
Pointer to the map in which this object is present.
int identifyskill
Skill used to identify this object class.
int index
Being the size of the shopitems array.
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
tag_t count
Unique object number for this object.
void object_copy(const object *src_ob, object *dest_ob)
Copy object first frees everything allocated by the second object, and then copies the contents of th...
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
#define FLAG_BLESSED
Item has a blessing, opposite of cursed/damned.
static void shop_pay_unpaid_callback(object *op, void *data)
#define MSG_TYPE_SHOP_PAYMENT
Messages about payment, lack of funds.
static const char *const coins[]
Coins to use for shopping.
int rndm(int min, int max)
Returns a number between min and max.
#define SK_EXP_NONE
Player gets nothing.
#define NEUTRAL_RATIO
Price a shopkeeper will give someone they neither like nor dislike.
char path[HUGE_BUF]
Filename of the map.
const char * object_get_value(const object *op, const char *const key)
Get an extra value by key.
#define MSG_TYPE_SHOP_MISC
Random messages.
#define FLAG_APPLIED
Object is ready for use by living.
int16_t level
Level of creature or object.
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Execute an event on the specified object.
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
int pay_for_item(object *op, object *pl, uint64_t reduction)
Player attemps to buy an item, if she has enough money then remove coins as needed from active contai...
#define NUM_COINS
Number of coin types.
static StringBuffer * real_money_value(const object *coin, StringBuffer *buf)
Returns a string representing the money's value, in plain coins.
struct shopitems * shopitems
List of item-types the map's shop will trade in.
Link an object type with skill needed to identify, and general name.
int16_t y
Position in the map for this object.
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects,...
static uint32_t NROF(const object *const ob)
Returns ob->nrof, unless it is 0, in which case return 1.
#define FLAG_WAS_WIZ
Player was once a wiz.
const typedata * get_typedata(int itemtype)
uint64_t shop_price_sell(const object *tmp, object *who)
Adjust the value of an item to be sold based on the player's bargaining skill and charisma.
void query_name(const object *op, char *buf, size_t size)
Describes an item.
#define EVENT_SELLING
Object is being sold by another one.
int shop_pay_unpaid(object *pl, object *op)
Pay as many unpaid items as possible, recursing on op->inv and op->below.
uint64_t query_money(const object *op)
Determine the amount of money the given object contains, including what is inside containers.
static double shop_specialisation_ratio(const object *item, const mapstruct *map)
Returns the ratio of the price that a shop will offer for an item based on the shop's specialisation.
char * shoprace
The preffered race of the local shopkeeper.
object clone
An object from which to do object_copy()
#define FOR_OB_AND_BELOW_FINISH()
Finishes FOR_OB_AND_BELOW_PREPARE().
int32_t value
How much money it is worth (or contains)
int is_identified(const object *op)
Return true if the item is identified, either because it is of a type that doesn't ever need identifi...
int isqrt(int n)
Compute the square root.
char * cost_string_from_value(uint64_t cost, int largest_coin)
Converts a price to number of coins.
uint8_t type
PLAYER, BULLET, etc.
#define FLAG_DAMNED
The object is very cursed.
int8_t magic
Any magical bonuses to this item.
#define MAX_BUY_REDUCTION
Maximum price reduction when buying an item with bargaining skill.
const char * name_pl
Plural name.
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
int32_t food
How much food in stomach.
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
Changes experience to a player/monster.
@ SK_BARGAINING
Bargaining.
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
uint64_t add_with_overflow(uint64_t a, uint64_t b)
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Append a string to a string buffer instance.
#define FOR_OB_AND_BELOW_PREPARE(op_)
Constructs a loop iterating over an object and all objects below it in the same pile.
#define MAX_BUF
Used for all kinds of things.
int shop_describe(const object *op)
A player is examining a shop, so describe it.
object * object_new(void)
Grabs an object from the list of unused objects, makes sure it is initialised, and returns it.
int typenum
Itemtype number we need to match, -1 if it is the default price.
#define EVENT_BOUGHT
Object is being bought by player.
uint64_t shopmax
MMaximum price a shop will offer.
int32_t weight
Attributes of the object.
A buffer that will be expanded as content is added to it.
static uint64_t value_limit(uint64_t val, int quantity, const object *who, int isshop)
Limit the value of items based on the wealth of the shop.
static void count_coins(object *item, uint32_t *coincount)
Count the number of coins for each type, for all items below item and in inventory.
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
uint64_t shop_price_buy(const object *tmp, object *who)
Adjust the value of an item to be bought based on the player's bargaining skill and charisma.
#define NDI_UNIQUE
Print immediately, don't buffer.
sstring name
The name of the object, obviously...
#define MSG_TYPE_SHOP_SELL
Messages about selling items.
const char * name
Name of the item in question, null if it is the default item.
bool shop_contains(object *ob)
Check if an object is in a shop.
void stringbuffer_delete(StringBuffer *sb)
Totally delete a string buffer.
static int64_t remove_value(object *coin_objs[], int64_t remain)
This function removes a given amount from a list of coins.
uint64_t price_base(const object *obj)
Price an item based on its value or archetype value, type, identification/BUC status,...
Magical Runes Runes are magical inscriptions on the dungeon floor
archetype * find_archetype(const char *name)
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
object * objects
Pointer to the list of used objects.
Shop-related information for a map.
void make_list_like(char *input)
Taking a string as an argument, mutate it into a string that looks like a list.
#define CLEAR_FLAG(xyz, p)
float shop_efficiency(const object *player)
Return the shop's efficiency (E) for a player, a number greater than (but not equal to) zero and less...
#define MSG_TYPE_SHOP_LISTING
Shop listings - inventory, what it deals in.
static double shop_greed(const mapstruct *map)
Gets a shop's greed.
int identifyskill2
Second skill used to identify this object class.
====Textual A command containing textual data has data fields separated by one ASCII space character. word::A sequence of ASCII characters that does not contain the space or nul character. This is to distinguish it from the _string_, which may contain space characters. Not to be confused with a machine word. int::A _word_ containing the textual representation of an integer. Not to be confused with any of the binary integers in the following section. Otherwise known as the "string value of integer data". Must be parsed, e.g. using `atoi()` to get the actual integer value. string::A sequence of ASCII characters. This must only appear at the end of a command, since spaces are used to separate fields of a textual message.=====Binary All multi-byte integers are transmitted in network byte order(MSB first). int8::1-byte(8-bit) integer int16::2-byte(16-bit) integer int32::4-byte(32-bit) integer lstring::A length-prefixed string, which consists of an `int8` followed by that many bytes of the actual string. This is used to transmit a string(that may contain spaces) in the middle of binary data. l2string::Like _lstring_, but is prefixed with an `int16` to support longer strings Implementation Notes ~~~~~~~~~~~~~~~~~~~~ - Typical implementations read two bytes to determine the length of the subsequent read for the actual message, then read and parse the data from each message according to the commands described below. To send a message, the sender builds the message in a buffer, counts the length of the message, sends the length, and finally sends the actual message. TIP:Incorrectly transmitting or receiving the `length` field can lead to apparent "no response" issues as the client or server blocks to read the entire length of the message. - Since the protocol is highly interactive, it may be useful to set `TCP_NODELAY` on both the client and server. - If you are using a language with a buffered output stream, remember to flush the stream after a complete message. - If the connection is lost(which will also happen if the output buffer overflowing), the player is saved and the server cleans up. This does open up some abuses, but there is no perfect solution here. - The server only reads data from the socket if the player has an action. This isn 't really good, since many of the commands below might not be actual commands for the player. The alternative is to look at the data, and if it is a player command and there isn 't time, store it away to be processed later. But this increases complexity, in that the server must start buffering the commands. Fortunately, for now, there are few such client commands. Commands -------- In the documentation below, `S->C` represents a message to the client from the server, and `C->S` represents a message to the server from the client. Commands are documented in a brief format like:C->S:version< csval >[scval[vinfo]] Fields are enclosed like `< this >`. Optional fields are denoted like `[this]`. Spaces that appear in the command are literal, i.e. the<< _version > > command above uses spaces to separate its fields, but the command below does not:C->S:accountlogin< name >< password > As described in<< _messages > >, if a command contains data, then the command is separated from the data by a literal space. Many of the commands below refer to 'object tags'. Whenever the server creates an object, it creates a unique tag for that object(starting at 1 when the server is first run, and ever increasing.) Tags are unique, but are not consistent between runs. Thus, the client can not store tags when it exits and hope to re-use them when it joins the server at a later time - tags are only valid for the current connection. The protocol commands are broken into various sections which based somewhat on what the commands are for(ie, item related commands, map commands, image commands, etc.) In this way, all the commands related to similar functionality is in the same place. Initialization ~~~~~~~~~~~~~~ version ^^^^^^^ C->S:version< csval >[scval[vinfo]] S->C:version< csval >[scval[vinfo]] Used by the client and server to exchange which version of the Crossfire protocol they understand. Neither send this in response to the other - they should both send this shortly after a connection is established. csval::int, version level of C->S communications scval::int, version level of S->C communications vinfo::string, that is purely for informative that general client/server info(ie, javaclient, x11client, winclient, sinix server, etc). It is purely of interest of server admins who can see what type of clients people are using.=====Version ID If a new command is added to the protocol in the C->S direction, then the version number in csval will get increased. Likewise, the same is true for the scval. The version are currently integers, in the form ABCD. A=1, and will likely for quite a while. This will only really change if needed from rollover of B. B represents major protocol changes - if B mismatches, the clients will be totally unusable. Such an example would be change of map or item sending commands(either new commands or new format.) C represents more minor but still significant changes - clients might still work together, but some features that used to work may now fail due to the mismatch. An example may be a change in the meaning of some field in some command - providing the field is the same size, it still should be decoded properly, but the meaning won 't be processed properly. D represents very minor changes or new commands. Things should work no worse if D does not match, however if they do match, some new features might be included. An example of the would be the C->S mark command to mark items. Server not understanding this just means that the server can not process it, and will ignore it.=====Handling As far as the client is concerned, its _scval_ must be at least equal to the server, and its _csval_ should not be newer than the server. The server does not care about the version command it receives right now - all it currently does is log mismatches. In theory, the server should keep track of what the client has, and adjust the commands it sends respectively in the S->C direction. The server is resilant enough that it won 't crash with a version mismatch(however, client may end up sending commands that the server just ignores). It is really up to the client to enforce versioning and quit if the versions don 't match. NOTE:Since all packets have the length as the first 2 bytes, all that either the client or server needs to be able to do is look at the first string and see if it understands it. If not, it knows how many bytes it can skip. As such, exact version matches should not be necessary for proper operation - however, both the client and server needs to be coded to handle such cases.=====History _scval_ and _vinfo_ were added in version 1020. Before then, there was only one version sent in the version command. NOTE:For the most part, this has been obsoleted by the setup command which always return status and whether it understood the command or not. However there are still some cases where using this versioning is useful - an example it the addition of the requestinfo/replyinfo commands - the client wants to wait for acknowledge of all the replyinfo commands it has issued before sending the addme command. However, if the server doesn 't understand these options, the client will never get a response. With the versioning, the client can look at the version and know if it should wait for a response or if the server will never send back. setup ^^^^^ C->S, S->C:setup< option1 >< value1 >< option2 >< value2 > ... Sent by the client to request protocol option changes. This can be at any point during the life of a connection, but usually sent at least once right after the<< _version > > command. The server responds with a message in the same format confirming what configuration options were set. The server only sends a setup command in response to one from the client. The sc_version should be updated in the server if commands have been obsoleted such that old clients may not be able to play. option::word, name of configuration option value::word, value of configuration option. May need further parsing according to the setup options below=====Setup Options There are really 2 set of setup commands here:. Those that control preferences of the client(how big is the map, what faceset to use, etc). . Those that describe capabilities of the client(client supports this protocol command or that) .Setup Options[options="autowidth,header"]|===========================|Command|Description|beat|Ask the server to enable heartbeat support. When heartbeat is enabled, the client must send the server a command every three seconds. If no commands need to be sent, use the `beat` no-op command. Clients that do not contact the server within the interval are assumed to have a temporary connection failure.|bot(0/1 value)|If set to 1, the client will not be considered a player when updating information to the metaserver. This is to avoid having a server with many bots appear more crowded than others.|darkness(0/1 value)|If set to 1(default), the server will send darkness information in the map protocol commands. If 0, the server will not include darkness, thus saving a minor amount of bandwidth. Since the client is free to ignore the darkness information, this does not allow the client to cheat. In the case of the old 'map' protocol command, turning darkness off will result in the masking faces not getting sent to the client.|extended_stats(0/1 value)|If set to 1, the server will send the CS_STAT_RACE_xxx and CS_STAT_BASE_xxx values too, so the client can display various status related to statistics. Default is 0.|facecache(0/1)|Determines if the client is caching images(1) or wants the images sent to it without caching them(0). Default is 0. This replaces the setfacemode command.|faceset(8 bit)|Faceset the client wishes to use. If the faceset is not valid, the server returns the faceset the client will be using(default 0).|loginmethod(8 bit)|Client sends this to server to note login support. This is basically used as a subset of the csversion/scversion to find out what level of login support the server and client support. Current defined values:0:no advanced support - only legacy login method 1:account based login(described more below) 2:new character creation support This list may grow - for example, advanced character creation could become a feature.|map2cmd:(1)|This indicates client support for the map2 protocol command. See the map2 protocol details above for the main differences. Obsolete:This is the only supported mode now, but many clients use it as a sanity check for protocol versions, so the server still replies. It doesn 't do anything with the data|mapsize(int x) X(int y)|Sets the map size to x X y. Note the spaces here are only for clarity - there should be no spaces when actually sent(it should be 11x11 or 25x25). The default map size unless changed is 11x11. The minimum map size the server will allow is 9x9(no technical reason this could be smaller, but I don 't think the game would be smaller). The maximum map size supported in the current protocol is 63x63. However, each server can have its maximum map size sent to most any value. If the client sends an invalid mapsize command or a mapsize of 0x0, the server will respond with a mapsize that is the maximum size the server supports. Thus, if the client wants to know the maximum map size, it can just do a 'mapsize 0x0' or 'mapsize' and it will get the maximum size back. The server will constrain the provided mapsize x &y to the configured minumum and maximums. For example, if the maximum map size is 25x25, the minimum map size is 9x9, and the client sends a 31x7 mapsize request, the mapsize will be set to 25x9 and the server will send back a mapsize 25x9 setup command. When the values are valid, the server will send back a mapsize XxY setup command. Note that this is from its parsed values, so it may not match stringwise with what the client sent, but will match 0 wise. For example, the client may send a 'mapsize 025X025' command, in which case the server will respond with a 'mapsize 25x25' command - the data is functionally the same. The server will send an updated map view when this command is sent.|notifications(int value)|Value indicating what notifications the client accepts. It is incremental, a value means "all notifications till this level". The following levels are supported:1:quest-related notifications("addquest" and "updquest") 2:knowledge-related notifications("addknowledge") 3:character status flags(overloaded, blind,...)|num_look_objects(int value)|The maximum number of objects shown in the ground view. If more objects are present, fake objects are created for selecting the previous/next group of items. Defaults to 50 if not set. The server may adjust the given value to a suitable one data
static void count_unpaid_callback(object *item, void *data)
uint8_t real_wiz
Use mud-like wizards.
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to.
Magical Runes Runes are magical inscriptions on the dungeon which cast a spell or detonate when something steps on them Flying objects don t detonate runes Beware ! Runes are invisible most of the time They are only visible occasionally ! There are several runes which are there are some special runes which may only be called with the invoke and people may apply it to read it Maybe useful for mazes ! This rune will not nor is it ordinarily invisible Partial Visibility of they ll be visible only part of the time They have a(your level/2) chance of being visible in any given round
#define FLAG_PLAYER_SOLD
Object was sold to a shop by a player.
#define FLAG_UNPAID
Object hasn't been paid for yet.
sstring name
More definite name, like "generate_kobold".
uint32_t nrof
Number of objects.
living stats
Str, Con, Dex, etc.
int object_set_value(object *op, const char *key, const char *value, int add_key)
Updates the key in op to value.
int can_pay(object *pl)
Checks all unpaid items in op's inventory, adds up all the money they have, and checks that they can ...
#define FLAG_CURSED
The object is cursed.
int pay_for_amount(uint64_t to_pay, object *pl)
Takes the amount of money from the the player inventory and from it's various pouches using the pay_f...
#define CUSTOM_NAME_FIELD
Key in an object for the player-assigned custom name.
static void count_unpaid(object *pl, object *item, int *unpaid_count, uint64_t *unpaid_price)
Sum the amount to pay for all unpaid items and find available money.
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
void events_execute_global_event(int eventcode,...)
Execute a global event.
@ llevDebug
Only for debugging purposes.
static uint64_t pay_from_container(object *pl, object *pouch, uint64_t to_pay)
This pays for the item, and takes the proper amount of money off the specified container (pouch or pl...
object * identify(object *op)
Identifies an item.