ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.c
(Generate patch)

Comparing deliantra/server/common/object.c (file contents):
Revision 1.2 by root, Tue Feb 7 23:29:55 2006 UTC vs.
Revision 1.5 by root, Mon May 29 15:28:24 2006 UTC

1/* 1/*
2 * static char *rcsid_object_c = 2 * static char *rcsid_object_c =
3 * "$Id: object.c,v 1.2 2006/02/07 23:29:55 root Exp $"; 3 * "$Id: object.c,v 1.5 2006/05/29 15:28:24 root Exp $";
4 */ 4 */
5 5
6/* 6/*
7 CrossFire, A Multiplayer game for X-windows 7 CrossFire, A Multiplayer game for X-windows
8 8
69 0,1,2,3,4,5,6,7,8,1,2,2,2,3,4,4,4,5,6,6,6,7,8,8,8, 69 0,1,2,3,4,5,6,7,8,1,2,2,2,3,4,4,4,5,6,6,6,7,8,8,8,
70 1,2,2,2,2,2,3,4,4,4,4,4,5,6,6,6,6,6,7,8,8,8,8,8}; 70 1,2,2,2,2,2,3,4,4,4,4,4,5,6,6,6,6,6,7,8,8,8,8,8};
71 71
72 72
73/* Returns TRUE if every key_values in wants has a partner with the same value in has. */ 73/* Returns TRUE if every key_values in wants has a partner with the same value in has. */
74static int compare_ob_value_lists_one(object * wants, object * has) { 74static int compare_ob_value_lists_one(const object * wants, const object * has) {
75 key_value * wants_field; 75 key_value * wants_field;
76 76
77 /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both 77 /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both
78 * objects with lists are rare, and lists stay short. If not, use a 78 * objects with lists are rare, and lists stay short. If not, use a
79 * different structure or at least keep the lists sorted... 79 * different structure or at least keep the lists sorted...
103 /* If we get here, every field in wants has a matching field in has. */ 103 /* If we get here, every field in wants has a matching field in has. */
104 return TRUE; 104 return TRUE;
105} 105}
106 106
107/* Returns TRUE if ob1 has the same key_values as ob2. */ 107/* Returns TRUE if ob1 has the same key_values as ob2. */
108static int compare_ob_value_lists(object * ob1, object * ob2) { 108static int compare_ob_value_lists(const object * ob1, const object * ob2) {
109 /* However, there may be fields in has which aren't partnered in wants, 109 /* However, there may be fields in has which aren't partnered in wants,
110 * so we need to run the comparison *twice*. :( 110 * so we need to run the comparison *twice*. :(
111 */ 111 */
112 return compare_ob_value_lists_one(ob1, ob2) && compare_ob_value_lists_one(ob2, ob1); 112 return compare_ob_value_lists_one(ob1, ob2) && compare_ob_value_lists_one(ob2, ob1);
113} 113}
198 (ob1->materialname != ob2->materialname) || 198 (ob1->materialname != ob2->materialname) ||
199 (ob1->lore != ob2->lore) || 199 (ob1->lore != ob2->lore) ||
200 (ob1->subtype != ob2->subtype) || 200 (ob1->subtype != ob2->subtype) ||
201 (ob1->move_type != ob2->move_type) || 201 (ob1->move_type != ob2->move_type) ||
202 (ob1->move_block != ob2->move_block) || 202 (ob1->move_block != ob2->move_block) ||
203 (ob1->move_allow != ob2->move_allow) ||
203 (ob1->move_on != ob2->move_on) || 204 (ob1->move_on != ob2->move_on) ||
204 (ob1->move_off != ob2->move_off) || 205 (ob1->move_off != ob2->move_off) ||
205 (ob1->move_slow != ob2->move_slow) || 206 (ob1->move_slow != ob2->move_slow) ||
206 (ob1->move_slow_penalty != ob2->move_slow_penalty) 207 (ob1->move_slow_penalty != ob2->move_slow_penalty)
207 ) 208 )
212 * some items equipped, and we don't want those to merge. 213 * some items equipped, and we don't want those to merge.
213 */ 214 */
214 if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED)) 215 if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED))
215 return 0; 216 return 0;
216 217
218 switch (ob1->type) {
219 case SCROLL:
220 if (ob1->level != ob2->level) return 0;
221 break;
222
223 }
217 if (ob1->key_values != NULL || ob2->key_values != NULL) { 224 if (ob1->key_values != NULL || ob2->key_values != NULL) {
218 /* At least one of these has key_values. */ 225 /* At least one of these has key_values. */
219 if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) { 226 if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) {
220 /* One has fields, but the other one doesn't. */ 227 /* One has fields, but the other one doesn't. */
221 return 0; 228 return 0;
222 } else {
223 return compare_ob_value_lists(ob1, ob2); 229 } else if (!compare_ob_value_lists(ob1, ob2)) {
230 return 0;
224 } 231 }
225 } 232 }
226 233
227 switch (ob1->type) {
228 case SCROLL:
229 if (ob1->level != ob2->level) return 0;
230 break;
231
232 }
233 /* Everything passes, must be OK. */ 234 /* Everything passes, must be OK. */
234 return 1; 235 return 1;
235} 236}
236 237
237/* 238/*
385 * get_nearest_part(multi-object, object 2) returns the part of the 386 * get_nearest_part(multi-object, object 2) returns the part of the
386 * multi-object 1 which is closest to the second object. 387 * multi-object 1 which is closest to the second object.
387 * If it's not a multi-object, it is returned. 388 * If it's not a multi-object, it is returned.
388 */ 389 */
389 390
390object *get_nearest_part(object *op,object *pl) { 391object *get_nearest_part(object *op, const object *pl) {
391 object *tmp,*closest; 392 object *tmp,*closest;
392 int last_dist,i; 393 int last_dist,i;
393 if(op->more==NULL) 394 if(op->more==NULL)
394 return op; 395 return op;
395 for(last_dist=distance(op,pl),closest=op,tmp=op->more;tmp!=NULL;tmp=tmp->more) 396 for(last_dist=distance(op,pl),closest=op,tmp=op->more;tmp!=NULL;tmp=tmp->more)
414 * Returns the first object which has a name equal to the argument. 415 * Returns the first object which has a name equal to the argument.
415 * Used only by the patch command, but not all that useful. 416 * Used only by the patch command, but not all that useful.
416 * Enables features like "patch <name-of-other-player> food 999" 417 * Enables features like "patch <name-of-other-player> food 999"
417 */ 418 */
418 419
419object *find_object_name(char *str) { 420object *find_object_name(const char *str) {
420 const char *name=add_string(str); 421 const char *name=add_string(str);
421 object *op; 422 object *op;
422 for(op=objects;op!=NULL;op=op->next) 423 for(op=objects;op!=NULL;op=op->next)
423 if(op->name==name) 424 if(op->name==name)
424 break; 425 break;
1019 if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags & P_IS_ALIVE)) 1020 if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags & P_IS_ALIVE))
1020 update_now=1; 1021 update_now=1;
1021 1022
1022 if ((move_on | op->move_on) != move_on) update_now=1; 1023 if ((move_on | op->move_on) != move_on) update_now=1;
1023 if ((move_off | op->move_off) != move_off) update_now=1; 1024 if ((move_off | op->move_off) != move_off) update_now=1;
1025 /* This isn't perfect, but I don't expect a lot of objects to
1026 * to have move_allow right now.
1027 */
1024 if ((move_block | op->move_block) != move_block) update_now=1; 1028 if (((move_block | op->move_block) & ~op->move_allow) != move_block)
1029 update_now=1;
1025 if ((move_slow | op->move_slow) != move_slow) update_now=1; 1030 if ((move_slow | op->move_slow) != move_slow) update_now=1;
1026 } 1031 }
1027 /* if the object is being removed, we can't make intelligent 1032 /* if the object is being removed, we can't make intelligent
1028 * decisions, because remove_ob can't really pass the object 1033 * decisions, because remove_ob can't really pass the object
1029 * that is being removed. 1034 * that is being removed.
1511 if(op->more!=NULL) { 1516 if(op->more!=NULL) {
1512 /* The part may be on a different map. */ 1517 /* The part may be on a different map. */
1513 1518
1514 object *more = op->more; 1519 object *more = op->more;
1515 1520
1521 /* We really need the caller to normalize coordinates - if
1522 * we set the map, that doesn't work if the location is within
1523 * a map and this is straddling an edge. So only if coordinate
1524 * is clear wrong do we normalize it.
1525 */
1526 if (OUT_OF_REAL_MAP(more->map, more->x, more->y)) {
1516 /* Debugging information so you can see the last coordinates this object had */ 1527 /* Debugging information so you can see the last coordinates this object had */
1517 more->ox = more->x; 1528 more->ox = more->x;
1518 more->oy = more->y; 1529 more->oy = more->y;
1519 more->map = get_map_from_coord(m, &more->x, &more->y); 1530 more->map = get_map_from_coord(m, &more->x, &more->y);
1531 } else if (!more->map) {
1532 /* For backwards compatibility - when not dealing with tiled maps,
1533 * more->map should always point to the parent.
1534 */
1535 more->map = m;
1536 }
1520 1537
1521 if (insert_ob_in_map(more, more->map, originator, flag) == NULL) { 1538 if (insert_ob_in_map(more, more->map, originator, flag) == NULL) {
1522 if ( ! op->head) 1539 if ( ! op->head)
1523 LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); 1540 LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n");
1524 return NULL; 1541 return NULL;
1706 1723
1707/* this function inserts an object in the map, but if it 1724/* this function inserts an object in the map, but if it
1708 * finds an object of its own type, it'll remove that one first. 1725 * finds an object of its own type, it'll remove that one first.
1709 * op is the object to insert it under: supplies x and the map. 1726 * op is the object to insert it under: supplies x and the map.
1710 */ 1727 */
1711void replace_insert_ob_in_map(char *arch_string, object *op) { 1728void replace_insert_ob_in_map(const char *arch_string, object *op) {
1712 object *tmp; 1729 object *tmp;
1713 object *tmp1; 1730 object *tmp1;
1714 1731
1715 /* first search for itself and remove any old instances */ 1732 /* first search for itself and remove any old instances */
1716 1733
2084 * present_arch(arch, map, x, y) searches for any objects with 2101 * present_arch(arch, map, x, y) searches for any objects with
2085 * a matching archetype at the given map and coordinates. 2102 * a matching archetype at the given map and coordinates.
2086 * The first matching object is returned, or NULL if none. 2103 * The first matching object is returned, or NULL if none.
2087 */ 2104 */
2088 2105
2089object *present_arch(archetype *at, mapstruct *m, int x, int y) { 2106object *present_arch(const archetype *at, mapstruct *m, int x, int y) {
2090 object *tmp; 2107 object *tmp;
2091 if(m==NULL || out_of_map(m,x,y)) { 2108 if(m==NULL || out_of_map(m,x,y)) {
2092 LOG(llevError,"Present_arch called outside map.\n"); 2109 LOG(llevError,"Present_arch called outside map.\n");
2093 return NULL; 2110 return NULL;
2094 } 2111 }
2120 * present_in_ob(type, object) searches for any objects with 2137 * present_in_ob(type, object) searches for any objects with
2121 * a matching type variable in the inventory of the given object. 2138 * a matching type variable in the inventory of the given object.
2122 * The first matching object is returned, or NULL if none. 2139 * The first matching object is returned, or NULL if none.
2123 */ 2140 */
2124 2141
2125object *present_in_ob(unsigned char type,object *op) { 2142object *present_in_ob(unsigned char type, const object *op) {
2126 object *tmp; 2143 object *tmp;
2127 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) 2144 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below)
2128 if(tmp->type==type) 2145 if(tmp->type==type)
2129 return tmp; 2146 return tmp;
2130 return NULL; 2147 return NULL;
2143 * the object name, not the archetype name. this is so that the 2160 * the object name, not the archetype name. this is so that the
2144 * spell code can use one object type (force), but change it's name 2161 * spell code can use one object type (force), but change it's name
2145 * to be unique. 2162 * to be unique.
2146 */ 2163 */
2147 2164
2148object *present_in_ob_by_name(int type, char *str,object *op) { 2165object *present_in_ob_by_name(int type, const char *str, const object *op) {
2149 object *tmp; 2166 object *tmp;
2150 2167
2151 for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) { 2168 for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) {
2152 if ((type==-1 || tmp->type==type) && (!strcmp(str, tmp->name))) 2169 if ((type==-1 || tmp->type==type) && (!strcmp(str, tmp->name)))
2153 return tmp; 2170 return tmp;
2159 * present_arch_in_ob(archetype, object) searches for any objects with 2176 * present_arch_in_ob(archetype, object) searches for any objects with
2160 * a matching archetype in the inventory of the given object. 2177 * a matching archetype in the inventory of the given object.
2161 * The first matching object is returned, or NULL if none. 2178 * The first matching object is returned, or NULL if none.
2162 */ 2179 */
2163 2180
2164object *present_arch_in_ob(archetype *at, object *op) { 2181object *present_arch_in_ob(const archetype *at, const object *op) {
2165 object *tmp; 2182 object *tmp;
2166 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) 2183 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below)
2167 if( tmp->arch == at) 2184 if( tmp->arch == at)
2168 return tmp; 2185 return tmp;
2169 return NULL; 2186 return NULL;
2223 * to know if the space in question will block the object. We can't use 2240 * to know if the space in question will block the object. We can't use
2224 * the archetype because that isn't correct if the monster has been 2241 * the archetype because that isn't correct if the monster has been
2225 * customized, changed states, etc. 2242 * customized, changed states, etc.
2226 */ 2243 */
2227 2244
2228int find_free_spot(object *ob, mapstruct *m,int x,int y,int start,int stop) { 2245int find_free_spot(const object *ob, mapstruct *m,int x,int y,int start,int stop) {
2229 int i,index=0, flag; 2246 int i,index=0, flag;
2230 static int altern[SIZEOFFREE]; 2247 static int altern[SIZEOFFREE];
2231 2248
2232 for(i=start;i<stop;i++) { 2249 for(i=start;i<stop;i++) {
2233 flag = ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]); 2250 flag = ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]);
2254 * find_free_spot(), but it will search max number of squares. 2271 * find_free_spot(), but it will search max number of squares.
2255 * But it will return the first available spot, not a random choice. 2272 * But it will return the first available spot, not a random choice.
2256 * Changed 0.93.2: Have it return -1 if there is no free spot available. 2273 * Changed 0.93.2: Have it return -1 if there is no free spot available.
2257 */ 2274 */
2258 2275
2259int find_first_free_spot(object *ob, mapstruct *m,int x,int y) { 2276int find_first_free_spot(const object *ob, mapstruct *m,int x,int y) {
2260 int i; 2277 int i;
2261 for(i=0;i<SIZEOFFREE;i++) { 2278 for(i=0;i<SIZEOFFREE;i++) {
2262 if(!ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i])) 2279 if(!ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]))
2263 return i; 2280 return i;
2264 } 2281 }
2365/* 2382/*
2366 * distance(object 1, object 2) will return the square of the 2383 * distance(object 1, object 2) will return the square of the
2367 * distance between the two given objects. 2384 * distance between the two given objects.
2368 */ 2385 */
2369 2386
2370int distance(object *ob1,object *ob2) { 2387int distance(const object *ob1, const object *ob2) {
2371 int i; 2388 int i;
2372 i= (ob1->x - ob2->x)*(ob1->x - ob2->x)+ 2389 i= (ob1->x - ob2->x)*(ob1->x - ob2->x)+
2373 (ob1->y - ob2->y)*(ob1->y - ob2->y); 2390 (ob1->y - ob2->y)*(ob1->y - ob2->y);
2374 return i; 2391 return i;
2375} 2392}
2540 * core dumps if they do. 2557 * core dumps if they do.
2541 * 2558 *
2542 * Add a check so we can't pick up invisible objects (0.93.8) 2559 * Add a check so we can't pick up invisible objects (0.93.8)
2543 */ 2560 */
2544 2561
2545int can_pick(object *who,object *item) { 2562int can_pick(const object *who, const object *item) {
2546 return /*QUERY_FLAG(who,FLAG_WIZ)||*/ 2563 return /*QUERY_FLAG(who,FLAG_WIZ)||*/
2547 (item->weight>0&&!QUERY_FLAG(item,FLAG_NO_PICK)&& 2564 (item->weight>0&&!QUERY_FLAG(item,FLAG_NO_PICK)&&
2548 !QUERY_FLAG(item,FLAG_ALIVE)&&!item->invisible && 2565 !QUERY_FLAG(item,FLAG_ALIVE)&&!item->invisible &&
2549 (who->type==PLAYER||item->weight<who->weight/3)); 2566 (who->type==PLAYER||item->weight<who->weight/3));
2550} 2567}
2585 2602
2586 return dst; 2603 return dst;
2587} 2604}
2588 2605
2589/* return true if the object was destroyed, 0 otherwise */ 2606/* return true if the object was destroyed, 0 otherwise */
2590int was_destroyed (object *op, tag_t old_tag) 2607int was_destroyed (const object *op, tag_t old_tag)
2591{ 2608{
2592 /* checking for FLAG_FREED isn't necessary, but makes this function more 2609 /* checking for FLAG_FREED isn't necessary, but makes this function more
2593 * robust */ 2610 * robust */
2594 return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED); 2611 return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED);
2595} 2612}
2599/* load_object on it. I admit it is a highly inefficient way to make things, */ 2616/* load_object on it. I admit it is a highly inefficient way to make things, */
2600/* but it was simple to make and allows reusing the load_object function. */ 2617/* but it was simple to make and allows reusing the load_object function. */
2601/* Remember not to use load_object_str in a time-critical situation. */ 2618/* Remember not to use load_object_str in a time-critical situation. */
2602/* Also remember that multiparts objects are not supported for now. */ 2619/* Also remember that multiparts objects are not supported for now. */
2603 2620
2604object* load_object_str(char *obstr) 2621object* load_object_str(const char *obstr)
2605{ 2622{
2606 object *op; 2623 object *op;
2607 FILE *tempfile; 2624 FILE *tempfile;
2608 char filename[MAX_BUF]; 2625 char filename[MAX_BUF];
2609 sprintf(filename,"%s/cfloadobstr2044",settings.tmpdir); 2626 sprintf(filename,"%s/cfloadobstr2044",settings.tmpdir);
2633 2650
2634/* This returns the first object in who's inventory that 2651/* This returns the first object in who's inventory that
2635 * has the same type and subtype match. 2652 * has the same type and subtype match.
2636 * returns NULL if no match. 2653 * returns NULL if no match.
2637 */ 2654 */
2638object *find_obj_by_type_subtype(object *who, int type, int subtype) 2655object *find_obj_by_type_subtype(const object *who, int type, int subtype)
2639{ 2656{
2640 object *tmp; 2657 object *tmp;
2641 2658
2642 for (tmp=who->inv; tmp; tmp=tmp->below) 2659 for (tmp=who->inv; tmp; tmp=tmp->below)
2643 if (tmp->type == type && tmp->subtype == subtype) return tmp; 2660 if (tmp->type == type && tmp->subtype == subtype) return tmp;
2649 * otherwise return NULL. 2666 * otherwise return NULL.
2650 * 2667 *
2651 * key must be a passed in shared string - otherwise, this won't 2668 * key must be a passed in shared string - otherwise, this won't
2652 * do the desired thing. 2669 * do the desired thing.
2653 */ 2670 */
2654key_value * get_ob_key_link(object * ob, const char * key) { 2671key_value * get_ob_key_link(const object * ob, const char * key) {
2655 key_value * link; 2672 key_value * link;
2656 2673
2657 for (link = ob->key_values; link != NULL; link = link->next) { 2674 for (link = ob->key_values; link != NULL; link = link->next) {
2658 if (link->key == key) { 2675 if (link->key == key) {
2659 return link; 2676 return link;
2668 * 2685 *
2669 * The argument doesn't need to be a shared string. 2686 * The argument doesn't need to be a shared string.
2670 * 2687 *
2671 * The returned string is shared. 2688 * The returned string is shared.
2672 */ 2689 */
2673const char * get_ob_key_value(object * op, const char * const key) { 2690const char * get_ob_key_value(const object * op, const char * const key) {
2674 key_value * link; 2691 key_value * link;
2675 const char * canonical_key; 2692 const char * canonical_key;
2676 2693
2677 canonical_key = find_string(key); 2694 canonical_key = find_string(key);
2678 2695
2708 * Returns TRUE on success. 2725 * Returns TRUE on success.
2709 */ 2726 */
2710int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) { 2727int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) {
2711 key_value * field = NULL, *last=NULL; 2728 key_value * field = NULL, *last=NULL;
2712 2729
2713 LOG(llevDebug, "set_ob_value_s: '%s' '%s' %d\n", canonical_key, value, add_key);
2714
2715 for (field=op->key_values; field != NULL; field=field->next) { 2730 for (field=op->key_values; field != NULL; field=field->next) {
2716 if (field->key != canonical_key) { 2731 if (field->key != canonical_key) {
2717 last = field; 2732 last = field;
2718 continue; 2733 continue;
2719 } 2734 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines