--- deliantra/server/include/object.h 2010/04/02 03:41:24 1.230 +++ deliantra/server/include/object.h 2018/11/18 16:32:27 1.275 @@ -1,32 +1,31 @@ /* * This file is part of Deliantra, the Roguelike Realtime MMORPG. - * - * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * + * Copyright (©) 2018 Marc Alexander Lehmann / the Deliantra team + * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team * Copyright (©) 2001 Mark Wedel & Crossfire Development Team * Copyright (©) 1992 Frank Tore Johansen - * + * * Deliantra is free software: you can redistribute it and/or modify it under * the terms of the Affero GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the Affero GNU General Public License * and the GNU General Public License along with this program. If not, see * . - * + * * The authors can be reached via e-mail to */ #ifndef OBJECT_H #define OBJECT_H -#include - #include "cfperl.h" #include "shstr.h" @@ -34,45 +33,37 @@ typedef int tag_t; -enum { - body_skill, - body_combat, - body_range, - body_shield, - body_arm, - body_torso, - body_head, - body_neck, - body_finger, - body_shoulder, - body_foot, - body_hand, - body_wrist, - body_waist, - NUM_BODY_LOCATIONS -}; - -enum slottype_t +// also see common/item.C +enum { - slot_none, - slot_combat, - slot_ranged, +# define def(name, use, nonuse) body_ ## name, +# include "slotinc.h" +# undef def + NUM_BODY_LOCATIONS }; /* See common/item.c */ -typedef struct Body_Locations +struct Body_Locations { - keyword save_name; /* Name used to load/save it to disk */ + const char *name; /* Short name/identifier */ + keyword kw; /* Name used to load/save it to disk */ const char *use_name; /* Name used when describing an item we can use */ const char *nonuse_name; /* Name to describe objects we can't use */ -} Body_Locations; +}; extern Body_Locations body_locations[NUM_BODY_LOCATIONS]; +// for each set of directions (1 == up, 2 == right, 4 == down, 8 == left) +// contains the wall suffix (0, 1_3, 1_4 and so on). +extern const char *wall_suffix[16]; + #define NUM_COINS 4 /* number of coin types */ extern const char *const coins[NUM_COINS + 1]; +// restart server when object_count reaches this value +#define RESTART_COUNT 0xe0000000 + /* * Each object (this also means archetypes!) could have a few of these * "dangling" from it; this could also end up containing 'parse errors'. @@ -85,10 +76,59 @@ */ struct key_value : slice_allocated { - key_value *next; + key_value *next; // must be first element shstr key, value; }; +// "crossfires version of a perl hash." +struct key_values +{ + key_value *first; // must be first element + + bool empty() const + { + return !first; + } + + void clear (); + shstr_tmp get (shstr_tmp key) const; + void del (shstr_tmp key); + void set (shstr_tmp key, shstr_tmp value); + + void add (shstr_tmp key, shstr_tmp value); // liek set, but doesn't check for duplicates + void reverse (); // reverses the ordering, to be used after loading an object + key_values &operator =(const key_values &kv); + + // custom extra fields management + struct access_proxy + { + key_values &kv; + shstr_tmp key; + + access_proxy (key_values &kv, shstr_tmp key) + : kv (kv), key (key) + { + } + + const access_proxy &operator =(shstr_tmp value) const + { + kv.set (key, value); + return *this; + } + + operator const shstr_tmp () const { return kv.get (key); } + operator const char *() const { return kv.get (key); } + + private: + void operator =(int); + }; + + const access_proxy operator [](shstr_tmp key) + { + return access_proxy (*this, key); + } +}; + //-GPL struct UUID @@ -257,7 +297,7 @@ //float ACC (RW, expmul) = 1.0; /* needed experience = (calc_exp*expmul) - means some */ // /* races/classes can need less/more exp to gain levels */ - static const float expmul = 1.0;//D + constexpr static const float expmul = 1.0;//D float ACC (RW, move_slow_penalty); /* How much this slows down the object */ /* Following are values used by any object */ @@ -291,14 +331,30 @@ const_utf8_string query_short_name (const object *op); const_utf8_string query_name (const object *op); const_utf8_string query_base_name (const object *op, int plural); +sint64 query_cost (const object *tmp, object *who, int flag); +const char *query_cost_string (const object *tmp, object *who, int flag); + +int change_ability_duration (object *spell, object *caster); +int min_casting_level (object *caster, object *spell); +int casting_level (object *caster, object *spell); +sint16 SP_level_spellpoint_cost (object *caster, object *spell, int flags); +int SP_level_dam_adjust (object *caster, object *spob); +int SP_level_duration_adjust (object *caster, object *spob); +int SP_level_range_adjust (object *caster, object *spob); + +struct freelist_item +{ + freelist_item *next; + uint32_t count; +}; -struct object : zero_initialised, object_copy +struct object : object_copy { // These variables are not changed by ->copy_to maptile *ACC (RW, map); /* Pointer to the map in which this object is present */ UUID ACC (RW, uuid); // Unique Identifier, survives saves etc. - int ACC (RO, count); + uint32_t ACC (RO, count); object_vector_index ACC (RO, index); // index into objects object_vector_index ACC (RO, active); // index into actives @@ -318,51 +374,27 @@ */ object *ACC (RW, more); /* Pointer to the rest of a large body of objects */ object *head; /* Points to the main object of a large body */ // NO ACC, perl semantics are different - key_value *key_values; /* Fields not explictly known by the loader. */ - // privates / perl - shstr_tmp kv_get (shstr_tmp key) const; - void kv_del (shstr_tmp key); - void kv_set (shstr_tmp key, shstr_tmp value); - -//-GPL - - // custom extra fields management - struct key_value_access_proxy + MTH void set_flag (int flagnum) { - object &ob; - shstr_tmp key; - - key_value_access_proxy (object &ob, shstr_tmp key) - : ob (ob), key (key) - { - } - - const key_value_access_proxy &operator =(shstr_tmp value) const - { - ob.kv_set (key, value); - return *this; - } - - operator const shstr_tmp () const { return ob.kv_get (key); } - operator const char *() const { return ob.kv_get (key); } - - private: - void operator =(int); - }; + flag [flagnum] = true; + } - // operator [] is too annoying to use - const key_value_access_proxy kv (shstr_tmp key) + MTH void clr_flag (int flagnum) { - return key_value_access_proxy (*this, key); + flag [flagnum] = false; } + // extra key value pairs + key_values kv; + +//-GPL + bool parse_kv (object_thawer &f); // parse kv pairs, (ab-)used by archetypes, which should not exist at all MTH void post_load_check (); // do some adjustments after parsing static object *read (object_thawer &f, maptile *map = 0); // map argument due to toal design bogosity, must go. bool write (object_freezer &f); - MTH int slottype () const; MTH static object *create (); const mapxy &operator =(const mapxy &pos); MTH void copy_to (object *dst); @@ -379,6 +411,7 @@ // recursively destroy all objects in inventory, optionally dropping them to the ground instead MTH void destroy_inv (bool drop_to_ground = false); + MTH void destroy_inv_fast (); // like destroy_inv (false), but only works when *this is destroyed, too MTH object *insert (object *item); // insert into inventory MTH void play_sound (faceidx sound) const; MTH void say_msg (const_utf8_string msg) const; @@ -405,7 +438,7 @@ // can be different if originator is causing op to // move (originator is pushing op) // returns 0 if the object is not able to move to the - // desired space, 1 otherwise (in which case we also + // desired space, 1 otherwise (in which case we also // move the object accordingly. This function is // very similiar to move_object. int move (int dir, object *originator); @@ -428,11 +461,9 @@ && can_merge_slow (op1, op2); } - MTH void set_owner (object *owner); + MTH void set_owner (object_ornull *owner); MTH void set_speed (float speed); MTH void set_glow_radius (sint8 rad); - bool change_weapon (object *ob); // deprecated - MTH bool change_skill (object *ob); // deprecated? MTH void open_container (object *new_container); MTH void close_container () @@ -454,6 +485,8 @@ || (!env && flag [FLAG_APPLIED])); } + MTH object *find_spell (const_utf8_string prefix) const; + MTH object *force_find (shstr_tmp name); MTH void force_set_timer (int duration); MTH object *force_add (shstr_tmp name, int duration = 0); @@ -493,9 +526,9 @@ return nrof ? nrof : 1; } - MTH sint32 total_weight () const + MTH weight_t total_weight () const { - return (weight + carrying) * number_of (); + return sint64 (weight + carrying) * number_of (); } MTH void update_weight (); @@ -507,9 +540,9 @@ } // return the volume of this object in cm³ - MTH uint64 volume () const + MTH volume_t volume () const { - return (uint64)total_weight () + return (volume_t)total_weight () * 1024 // 1000 actually * (type == CONTAINER ? 128 : 1) / dominant_material ()->density; // ugh, division @@ -533,6 +566,8 @@ MTH bool is_dragon () const; + MTH bool is_immunity () const { return invisible && type == SIGN; } + MTH bool has_active_speed () const { return speed >= MIN_ACTIVE_SPEED; } // temporary: wether the object can be saved in a map file @@ -550,6 +585,12 @@ MTH bool has_dialogue () const { return msg_has_dialogue (&msg); } + /* need_identify returns true if the item should be identified. This + * function really should not exist - by default, any item not identified + * should need it. + */ + MTH bool need_identify () const; + // returns the outermost owner, never returns 0 MTH object *outer_owner () { @@ -613,6 +654,9 @@ return !!contr; } + /* elmex: this method checks whether the object is in a shop */ + MTH bool is_in_shop () const; + MTH bool affects_los () const { return glow_radius || flag [FLAG_BLOCKSVIEW]; @@ -623,7 +667,7 @@ return glow_radius; } - // returns the player that cna see this object, if any + // returns the player that can see this object, if any MTH object *visible_to () const; MTH std::string long_desc (object *who = 0); // query_name . " " . describe @@ -644,6 +688,12 @@ MTH void create_treasure (treasurelist *tl, int flags = 0); + // makes sure the player has the named skill, + // and also makes it innate if can_use is true. + // returns the new skill or 0 if no such skill exists. + MTH object *give_skill (shstr_cmp name, bool can_use = false); + MTH void become_follower (object *new_god); + // insert object at same map position as 'where' // handles both inventory and map "positions" MTH object *insert_at (object *where, object *originator = 0, int flags = 0); @@ -656,13 +706,19 @@ MTH void activate_recursive (); MTH void deactivate_recursive (); + // prefetch and activate the surrounding area + MTH void prefetch_surrounding_maps (); + // set the given flag on all objects in the inventory recursively MTH void set_flag_inv (int flag, int value = 1); - void enter_exit (object *exit);//Perl - MTH void enter_map (maptile *newmap, int x, int y); + void enter_exit (object *exit); // perl + MTH bool enter_map (maptile *newmap, int x, int y); void player_goto (const_utf8_string path, int x, int y); // only for players - bool apply (object *ob, int aflags = AP_APPLY); + MTH bool apply (object *ob, int aflags = AP_APPLY); // ob may be 0 + + MTH object *mark () const; + MTH void splay_marked (); // returns the mapspace this object is in mapspace &ms () const; @@ -723,13 +779,14 @@ MTH struct region *region () const; - void statusmsg (const_utf8_string msg, int color = NDI_BLACK); - void failmsg (const_utf8_string msg, int color = NDI_RED); + MTH void statusmsg (const_utf8_string msg, int color = NDI_BLACK); + MTH void failmsg (const_utf8_string msg, int color = NDI_RED); + void failmsgf (const_utf8_string format, ...); // always NDI_RED... - const_utf8_string query_inventory (object *who = 0, const_utf8_string indent = ""); + MTH const_utf8_string query_inventory (object *who = 0, const_utf8_string indent = ""); MTH const_octet_string ref () const; // creates and returns a consistent persistent object reference - static object *deref (const_octet_string ref); // returns the object from the generated refreence, if possible + static object *deref (const_octet_string ref); // returns the object from the generated reference, if possible // make some noise with given item into direction dir, // currently only used for players to make them temporarily visible @@ -749,12 +806,26 @@ MTH int anim_frames () const { return anim ().num_animations; } MTH int anim_facings () const { return anim ().facings; } + // sets a new animation frame, if the object has animation frames, + // and updates the face + MTH void update_anim_frame (int frame); + MTH utf8_string as_string (); + // low-level management, statistics, ... + static uint32_t ACC (RW, object_count); + static uint32_t ACC (RW, free_count); + static uint32_t ACC (RW, create_count); + static uint32_t ACC (RW, destroy_count); + static freelist_item *freelist; + MTH static void freelist_free (int count); + protected: void link (); void unlink (); + void do_delete (); + object (); ~object (); @@ -800,7 +871,7 @@ //-GPL INTERFACE_CLASS (archetype) -struct archetype : object +struct archetype : object, zero_initialised { static arch_ptr empty; // the empty_archetype MTH static void gc (); @@ -820,7 +891,7 @@ MTH void post_load_check (); // do some adjustments after parsing object_vector_index ACC (RW, archid); // index in archvector - shstr ACC (RW, archname); /* More definite name, like "generate_kobold" */ + shstr ACC (RW, archname); /* More definite name, like "generate_kobold" */ sint8 ACC (RW, max_x); /* extents, compared to the head (min_x, min_y should be zero, but aren't...) */ @@ -828,6 +899,9 @@ static archetype *read (object_thawer &f); MTH static void commit_load (); // commit any objects loaded, resolves cyclic dependencies and more static void postpone_arch_ref (arch_ptr &ref, const_utf8_string other_arch); /* postpone other_arch reference */ + +protected: + void do_delete (); }; // returns whether the object is a dragon player, which are often specialcased @@ -859,16 +933,16 @@ #define for_inv_removable(op,var) \ for (object *var, *next_ = (op)->inv; (var = next_), var && (next_ = var->below), var; ) -#define for_all_objects(var) \ - for (unsigned _i = 0; _i < objects.size (); ++_i) \ +#define for_all_objects(var) \ + for (unsigned _i = 0; _i < objects.size (); ++_i) \ statementvar (object *, var, objects [_i]) -#define for_all_actives(var) \ - for (unsigned _i = 0; _i < actives.size (); ++_i) \ +#define for_all_actives(var) \ + for (unsigned _i = 0; _i < actives.size (); ++_i) \ statementvar (object *, var, actives [_i]) -#define for_all_archetypes(var) \ - for (unsigned _i = 0; _i < archetypes.size (); ++_i) \ +#define for_all_archetypes(var) \ + for (unsigned _i = 0; _i < archetypes.size (); ++_i) \ statementvar (archetype *, var, archetypes [_i]) //+GPL @@ -876,12 +950,12 @@ /* Used by update_object to know if the object being passed is * being added or removed. */ -#define UP_OBJ_INSERT 1 -#define UP_OBJ_REMOVE 2 -#define UP_OBJ_CHANGE 3 -#define UP_OBJ_FACE 4 /* Only thing that changed was the face */ +#define UP_OBJ_INSERT 1 // object was inserted +#define UP_OBJ_REMOVE 2 // object was removed +#define UP_OBJ_CHANGE 3 // object has changed in some unspecified way +#define UP_OBJ_FACE 4 // only thing that changed was the face -/* These are flags passed to insert_ob_in_map and +/* These are flags passed to insert_ob_in_map and * insert_ob_in_ob. Note that all flags may not be meaningful * for both functions. * Most are fairly explanatory: @@ -892,7 +966,7 @@ * originator - saves cpu time if you know the inserted object * is not meaningful in terms of having an effect. * INS_ON_TOP: Always put object on top. Generally only needed when loading - * files from disk and ordering needs to be preserved. + * files from disk and ordering needs to be preserved. * INS_BELOW_ORIGINATOR: Insert new object immediately below originator - * Use for treasure chests so the new object is the highest thing * beneath the player, but not actually above it. Note - the @@ -910,6 +984,7 @@ #define INS_NO_WALK_ON 0x0004 #define INS_ON_TOP 0x0008 #define INS_BELOW_ORIGINATOR 0x0010 +#define INS_NO_AUTO_EXIT 0x0020 // temporary, fix exits instead //-GPL